mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 18:07:59 +00:00
First stab at a host key cache on the Mac.
[originally from svn r5260]
This commit is contained in:
parent
3fb9e2326d
commit
d13ac1bc34
26
mac/mac.c
26
mac/mac.c
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
118
mac/macstore.c
118
mac/macstore.c
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user