1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +00:00

First stab at a host key cache on the Mac.

[originally from svn r5260]
This commit is contained in:
Owen Dunn 2005-02-06 15:00:36 +00:00
parent 3fb9e2326d
commit d13ac1bc34
3 changed files with 147 additions and 10 deletions

View File

@ -696,6 +696,7 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
{ {
Str255 stuff; Str255 stuff;
Session *s = frontend; Session *s = frontend;
int ret;
/* /*
* This function is horribly wrong. For one thing, the alert * This function is horribly wrong. For one thing, the alert
@ -703,16 +704,31 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
* Aqua. Also, PuTTY might be in the background, in which case we * Aqua. Also, PuTTY might be in the background, in which case we
* should use the Notification Manager to wake up the user. In * should use the Notification Manager to wake up the user. In
* any case, we shouldn't hold up processing of other connections' * any case, we shouldn't hold up processing of other connections'
* data just because this one's waiting for the user. It should * data just because this one's waiting for the user. Also see the
* also handle a host key cache, of course, and see the note below * note below about closing the connection. All in all, a bit of
* about closing the connection. All in all, a bit of a mess * a mess really.
* really.
*/ */
/* Verify the key against the cache */
ret = verify_host_key(host, port, keytype, keystr);
if (ret == 0) /* success - key matched OK */
return;
if (ret == 2) { /* key was different */
stuff[0] = sprintf((char *)(&stuff[1]),
"WARNING - POTENTIAL SECURITY BREACH\n",
"The key fingerprint is: %s\n"
"Continue connecting?", fingerprint);
ParamText(stuff, NULL, NULL, NULL);
}
if (ret == 1) { /* key was absent */
stuff[0] = sprintf((char *)(&stuff[1]), stuff[0] = sprintf((char *)(&stuff[1]),
"The server's key fingerprint is: %s\n" "The server's key fingerprint is: %s\n"
"Continue connecting?", fingerprint); "Continue connecting?", fingerprint);
ParamText(stuff, NULL, NULL, NULL); ParamText(stuff, NULL, NULL, NULL);
}
if (CautionAlert(wQuestion, NULL) == 2) { if (CautionAlert(wQuestion, NULL) == 2) {
/* /*
* User chose "Cancel". Unfortunately, if I tear the * User chose "Cancel". Unfortunately, if I tear the
@ -720,6 +736,8 @@ void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
* think this function should actually return something * think this function should actually return something
* telling the SSH code to abandon the connection. * telling the SSH code to abandon the connection.
*/ */
} else {
store_host_key(host, port, keytype, keystr);
} }
} }

View File

@ -21,6 +21,7 @@
#define INTERNAL_CREATOR FOUR_CHAR_CODE('pTTI') #define INTERNAL_CREATOR FOUR_CHAR_CODE('pTTI')
#define SESS_TYPE FOUR_CHAR_CODE('Sess') #define SESS_TYPE FOUR_CHAR_CODE('Sess')
#define SEED_TYPE FOUR_CHAR_CODE('Seed') #define SEED_TYPE FOUR_CHAR_CODE('Seed')
#define HKYS_TYPE FOUR_CHAR_CODE('Hkys')
struct mac_gestalts { struct mac_gestalts {
long sysvers; long sysvers;
@ -167,6 +168,8 @@ extern OSErr get_putty_dir(Boolean makeit, short *pVRefNum, long *pDirID);
extern OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID); extern OSErr get_session_dir(Boolean makeit, short *pVRefNum, long *pDirID);
extern void *open_settings_r_fsp(FSSpec *); extern void *open_settings_r_fsp(FSSpec *);
extern void *open_settings_w_fsp(FSSpec *); extern void *open_settings_w_fsp(FSSpec *);
extern int verify_host_key(const char *, int, const char *, const char*);
extern void store_host_key(const char *, int, const char *, const char*);
/* from macucs.c */ /* from macucs.c */
extern void init_ucs(Session *); extern void init_ucs(Session *);
/* from macnet.c */ /* from macnet.c */

View File

@ -1,4 +1,4 @@
/* $Id: macstore.c,v 1.19 2003/04/01 18:10:25 simon Exp $ */ /* $Id$ */
/* /*
* macstore.c: Macintosh-specific impementation of the interface * macstore.c: Macintosh-specific impementation of the interface
@ -602,6 +602,122 @@ void write_random_seed(void *data, int len)
return; return;
} }
int verify_host_key(const char *hostname, int port,
const char *keytype, const char *key)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
FSSpec keyfile;
short refnum;
char *resname;
Str255 presname;
char *resvalue;
Handle reshandle;
int len, compare;
if (get_putty_dir(kCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
return 1;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pSSH Host Keys",
&keyfile);
if (error == fnfErr) {
/* Keys file doesn't exist yet, so we can't match the key */
return 1;
}
refnum = FSpOpenResFile(&keyfile, fsRdPerm);
if (refnum == -1) {
/* We couldn't open the resource fork, so we can't match the key */
return 1;
}
UseResFile(refnum);
resname = dupprintf("%s@%d:%s", keytype, port, hostname);
c2pstrcpy(presname, resname);
reshandle = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), presname);
if (ResError() != noErr) {
/* Couldn't open the specific resource */
return 1;
}
len = GetHandleSize(reshandle);
resvalue = snewn(len+1, char);
memcpy(resvalue, *reshandle, len);
resvalue[len]='\0';
ReleaseResource(reshandle);
CloseResFile(refnum);
compare = strncmp(resvalue, key, strlen(resvalue));
sfree(resname);
sfree(resvalue);
if (compare) {
/* Key different */
return 2;
} else {
/* Key matched */
return 0;
}
}
void store_host_key(const char *hostname, int port,
const char *keytype, const char *key)
{
short puttyVRefNum;
long puttyDirID;
OSErr error;
FSSpec keyfile;
short keyrefnum;
char *resname;
Str255 presname;
Handle resvalue;
int id;
/* Open the host key file */
if (get_putty_dir(~kCreateFolder, &puttyVRefNum, &puttyDirID) != noErr)
goto out;
error = FSMakeFSSpec(puttyVRefNum, puttyDirID, "\pSSH Host Keys",
&keyfile);
if (error == fnfErr) {
/* It doesn't exist, so create it */
FSpCreateResFile(&keyfile, INTERNAL_CREATOR, HKYS_TYPE, smRoman);
keyrefnum = FSpOpenResFile(&keyfile, fsWrPerm);
if (ResError() == noErr) {
copy_resource('STR', -16397); /* XXX: wtf is this? */
CloseResFile(keyrefnum);
}
} else if (error != noErr) goto out;
keyrefnum = FSpOpenResFile(&keyfile, fsWrPerm);
if (keyrefnum == -1) goto out;
UseResFile(keyrefnum);
resname = dupprintf("%s@%d:%s", keytype, port, hostname);
c2pstrcpy(presname, resname);
error = PtrToHand(key, &resvalue, strlen(key));
if (error != noErr) goto out;
id = Unique1ID(FOUR_CHAR_CODE('TEXT'));
if (ResError() != noErr) goto out;
AddResource(resvalue, FOUR_CHAR_CODE('TEXT'), id, presname);
if (ResError() != noErr) goto out;
CloseResFile(keyrefnum);
return;
out:
fatalbox("Writing host key failed (%d)", error);
sfree(resname);
}
/* /*
* Emacs magic: * Emacs magic:
* Local Variables: * Local Variables: