1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-14 09:37:34 -05:00

Rationalised host key storage. Also started code reorg: persistent-state

routines have been moved out into a replaceable module winstore.c.

[originally from svn r639]
This commit is contained in:
Simon Tatham
2000-09-27 15:21:04 +00:00
parent 0fed43e9f4
commit aad0a52dfb
11 changed files with 585 additions and 232 deletions

179
windlg.c
View File

@ -14,6 +14,7 @@
#include "ssh.h"
#include "putty.h"
#include "win_res.h"
#include "storage.h"
#define NPANELS 8
#define MAIN_NPANELS 8
@ -1644,128 +1645,70 @@ void showabout (HWND hwnd) {
}
}
void verify_ssh_host_key(char *host, char *keystr) {
char *otherstr, *mungedhost;
int len;
HKEY rkey;
len = 1 + strlen(keystr);
/*
* Now read a saved key in from the registry and see what it
* says.
*/
otherstr = smalloc(len);
mungedhost = smalloc(3*strlen(host)+1);
if (!otherstr || !mungedhost)
fatalbox("Out of memory");
mungestr(host, mungedhost);
if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
&rkey) != ERROR_SUCCESS) {
if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n"
"in the registry. There is thus no way to tell\n"
"if the remote host is what you think it is.\n"
"Connect anyway?", "PuTTY Problem",
MB_ICONWARNING | MB_YESNO) == IDNO)
exit(0);
} else {
DWORD readlen = len;
DWORD type;
int ret;
ret = RegQueryValueEx(rkey, mungedhost, NULL,
&type, otherstr, &readlen);
if (ret == ERROR_MORE_DATA ||
(ret == ERROR_SUCCESS && type == REG_SZ &&
strcmp(otherstr, keystr))) {
if (MessageBox(NULL,
"This host's host key is different from the\n"
"one cached in the registry! Someone may be\n"
"impersonating this host for malicious reasons;\n"
"alternatively, the host key may have changed\n"
"due to sloppy system administration.\n"
"Replace key in registry and connect?",
"PuTTY: Security Warning",
MB_ICONWARNING | MB_YESNO) == IDNO)
exit(0);
RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
strlen(keystr)+1);
} else if (ret != ERROR_SUCCESS || type != REG_SZ) {
if (MessageBox(NULL,
"This host's host key is not cached in the\n"
"registry. Do you want to add it to the cache\n"
"and carry on connecting?",
"PuTTY: New Host",
MB_ICONWARNING | MB_YESNO) == IDNO)
exit(0);
RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr,
strlen(keystr)+1);
}
RegCloseKey(rkey);
}
}
/*
* Recursively delete a registry key and everything under it.
*/
static void registry_recursive_remove(HKEY key) {
DWORD i;
char name[MAX_PATH+1];
HKEY subkey;
i = 0;
while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) {
if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {
registry_recursive_remove(subkey);
RegCloseKey(subkey);
}
RegDeleteKey(key, name);
}
}
/*
* Destroy all registry information associated with PuTTY.
*/
void registry_cleanup(void) {
HKEY key;
void verify_ssh_host_key(char *host, char *keytype,
char *keystr, char *fingerprint) {
int ret;
char name[MAX_PATH+1];
static const char absentmsg[] =
"The server's host key is not cached in the registry. You\n"
"have no guarantee that the server is the computer you\n"
"think it is.\n"
"The server's key fingerprint is:\n"
"%s\n"
"If you trust this host, hit Yes to add the key to\n"
"PuTTY's cache and carry on connecting.\n"
"If you do not trust this host, hit No to abandon the\n"
"connection.\n";
static const char wrongmsg[] =
"WARNING - POTENTIAL SECURITY BREACH!\n"
"\n"
"The server's host key does not match the one PuTTY has\n"
"cached in the registry. This means that either the\n"
"server administrator has changed the host key, or you\n"
"have actually connected to another computer pretending\n"
"to be the server.\n"
"The new key fingerprint is:\n"
"%s\n"
"If you were expecting this change and trust the new key,\n"
"hit Yes to update PuTTY's cache and continue connecting.\n"
"If you want to carry on connecting but without updating\n"
"the cache, hit No.\n"
"If you want to abandon the connection completely, hit\n"
"Cancel. Hitting Cancel is the ONLY guaranteed safe\n"
"choice.\n";
static const char mbtitle[] = "PuTTY Security Alert";
char message[160+ /* sensible fingerprint max size */
(sizeof(absentmsg) > sizeof(wrongmsg) ?
sizeof(absentmsg) : sizeof(wrongmsg))];
/*
* Open the main PuTTY registry key and remove everything in it.
* Verify the key against the registry.
*/
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) == ERROR_SUCCESS) {
registry_recursive_remove(key);
RegCloseKey(key);
ret = verify_host_key(host, keytype, keystr);
if (ret == 0) /* success - key matched OK */
return;
if (ret == 2) { /* key was different */
int mbret;
sprintf(message, wrongmsg, fingerprint);
mbret = MessageBox(NULL, message, mbtitle,
MB_ICONWARNING | MB_YESNOCANCEL);
if (mbret == IDYES)
store_host_key(host, keytype, keystr);
if (mbret == IDCANCEL)
exit(0);
}
/*
* Now open the parent key and remove the PuTTY main key. Once
* we've done that, see if the parent key has any other
* children.
*/
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT,
&key) == ERROR_SUCCESS) {
RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);
ret = RegEnumKey(key, 0, name, sizeof(name));
RegCloseKey(key);
/*
* If the parent key had no other children, we must delete
* it in its turn. That means opening the _grandparent_
* key.
*/
if (ret != ERROR_SUCCESS) {
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,
&key) == ERROR_SUCCESS) {
RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);
RegCloseKey(key);
}
}
if (ret == 1) { /* key was absent */
int mbret;
sprintf(message, absentmsg, fingerprint);
mbret = MessageBox(NULL, message, mbtitle,
MB_ICONWARNING | MB_YESNO);
if (mbret == IDNO)
exit(0);
store_host_key(host, keytype, keystr);
}
/*
* Now we're done.
*/
}