X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/02cf40019f8ae19176a73f9220603cc9e28d5224..60860bc3697233687834d4efd4f1fe616f2fb9fb:/mac/macstore.c diff --git a/mac/macstore.c b/mac/macstore.c index 244569e9..35f31bdb 100644 --- a/mac/macstore.c +++ b/mac/macstore.c @@ -1,4 +1,4 @@ -/* $Id: macstore.c,v 1.15 2003/02/01 21:44:05 ben Exp $ */ +/* $Id$ */ /* * macstore.c: Macintosh-specific impementation of the interface @@ -116,16 +116,20 @@ struct write_settings { FSSpec dstfile; }; -void *open_settings_w(char const *sessionname) { +void *open_settings_w(char const *sessionname, char **errmsg) { short sessVRefNum; long sessDirID; OSErr error; Str255 psessionname; FSSpec dstfile; - + + *errmsg = NULL; + error = get_session_dir(kCreateFolder, &sessVRefNum, &sessDirID); if (error != noErr) return NULL; + if (!sessionname || !*sessionname) + sessionname = "Default Settings"; c2pstrcpy(psessionname, sessionname); error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &dstfile); if (error == fnfErr) { @@ -147,7 +151,7 @@ void *open_settings_w_fsp(FSSpec *dstfile) OSErr error; Str255 tmpname; - ws = smalloc(sizeof *ws); + ws = snew(struct write_settings); ws->dstfile = *dstfile; /* Create a temporary file to save to first. */ @@ -183,6 +187,7 @@ void write_setting_s(void *handle, char const *key, char const *value) { Handle h; int id; OSErr error; + Str255 pkey; UseResFile(fd); if (ResError() != noErr) @@ -195,7 +200,8 @@ void write_setting_s(void *handle, char const *key, char const *value) { id = Unique1ID(FOUR_CHAR_CODE('TEXT')); if (ResError() != noErr) fatalbox("Failed to get ID for resource %s (%d)", key, ResError()); - addresource(h, FOUR_CHAR_CODE('TEXT'), id, key); + c2pstrcpy(pkey, key); + AddResource(h, FOUR_CHAR_CODE('TEXT'), id, pkey); if (ResError() != noErr) fatalbox("Failed to add resource %s (%d)", key, ResError()); } @@ -205,6 +211,7 @@ void write_setting_i(void *handle, char const *key, int value) { Handle h; int id; OSErr error; + Str255 pkey; UseResFile(fd); if (ResError() != noErr) @@ -219,7 +226,8 @@ void write_setting_i(void *handle, char const *key, int value) { id = Unique1ID(FOUR_CHAR_CODE('Int ')); if (ResError() != noErr) fatalbox("Failed to get ID for resource %s (%d)", key, ResError()); - addresource(h, FOUR_CHAR_CODE('Int '), id, key); + c2pstrcpy(pkey, key); + AddResource(h, FOUR_CHAR_CODE('Int '), id, pkey); if (ResError() != noErr) fatalbox("Failed to add resource %s (%d)", key, ResError()); } @@ -252,6 +260,8 @@ void *open_settings_r(char const *sessionname) error = get_session_dir(kDontCreateFolder, &sessVRefNum, &sessDirID); + if (!sessionname || !*sessionname) + sessionname = "Default Settings"; c2pstrcpy(psessionname, sessionname); error = FSMakeFSSpec(sessVRefNum, sessDirID, psessionname, &sessfile); if (error != noErr) goto out; @@ -270,7 +280,7 @@ void *open_settings_r_fsp(FSSpec *sessfile) fd = FSpOpenResFile(sessfile, fsRdPerm); if (fd == 0) {error = ResError(); goto out;} - handle = safemalloc(sizeof *handle); + handle = snew(int); *handle = fd; return handle; @@ -282,12 +292,14 @@ char *read_setting_s(void *handle, char const *key, char *buffer, int buflen) { int fd; Handle h; size_t len; + Str255 pkey; if (handle == NULL) goto out; fd = *(int *)handle; UseResFile(fd); if (ResError() != noErr) goto out; - h = get1namedresource(FOUR_CHAR_CODE('TEXT'), key); + c2pstrcpy(pkey, key); + h = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), pkey); if (h == NULL) goto out; len = GetHandleSize(h); @@ -307,12 +319,14 @@ int read_setting_i(void *handle, char const *key, int defvalue) { int fd; Handle h; int value; + Str255 pkey; if (handle == NULL) goto out; fd = *(int *)handle; UseResFile(fd); if (ResError() != noErr) goto out; - h = get1namedresource(FOUR_CHAR_CODE('Int '), key); + c2pstrcpy(pkey, key); + h = Get1NamedResource(FOUR_CHAR_CODE('Int '), pkey); if (h == NULL) goto out; value = *(int *)*h; ReleaseResource(h); @@ -358,18 +372,20 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec font) sfree(settingname); } -int read_setting_filename(void *handle, const char *name, Filename *result) +int read_setting_filename(void *handle, const char *key, Filename *result) { int fd; AliasHandle h; Boolean changed; OSErr err; + Str255 pkey; if (handle == NULL) goto out; fd = *(int *)handle; UseResFile(fd); if (ResError() != noErr) goto out; - h = (AliasHandle)get1namedresource(rAliasType, name); + c2pstrcpy(pkey, key); + h = (AliasHandle)Get1NamedResource(rAliasType, pkey); if (h == NULL) goto out; if ((*h)->userType == 'pTTY' && (*h)->aliasSize == sizeof(**h)) memset(result, 0, sizeof(*result)); @@ -397,12 +413,13 @@ int read_setting_filename(void *handle, const char *name, Filename *result) return 0; } -void write_setting_filename(void *handle, const char *name, Filename fn) +void write_setting_filename(void *handle, const char *key, Filename fn) { int fd = *(int *)handle; AliasHandle h; int id; OSErr error; + Str255 pkey; UseResFile(fd); if (ResError() != noErr) @@ -442,10 +459,11 @@ void write_setting_filename(void *handle, const char *name, Filename fn) /* Put the data in a resource. */ id = Unique1ID(rAliasType); if (ResError() != noErr) - fatalbox("Failed to get ID for resource %s (%d)", name, ResError()); - addresource((Handle)h, rAliasType, id, name); + fatalbox("Failed to get ID for resource %s (%d)", key, ResError()); + c2pstrcpy(pkey, key); + AddResource((Handle)h, rAliasType, id, pkey); if (ResError() != noErr) - fatalbox("Failed to add resource %s (%d)", name, ResError()); + fatalbox("Failed to add resource %s (%d)", key, ResError()); } void close_settings_r(void *handle) { @@ -456,7 +474,7 @@ void close_settings_r(void *handle) { CloseResFile(fd); if (ResError() != noErr) fatalbox("Close of saved session failed (%d)", ResError()); - safefree(handle); + sfree(handle); } void del_settings(char const *sessionname) { @@ -488,10 +506,10 @@ void *enum_settings_start(void) { OSErr error; struct enum_settings_state *state; - state = safemalloc(sizeof(*state)); + state = snew(struct enum_settings_state); error = get_session_dir(kDontCreateFolder, &state->vRefNum, &state->dirID); if (error != noErr) { - safefree(state); + sfree(state); return NULL; } state->index = 1; @@ -585,6 +603,135 @@ void write_random_seed(void *data, int len) } /* + * This host key cache uses a file in the PuTTY Preferences folder and + * stores keys as individual TEXT resources in the resource fork of + * that file. This has two problems. Firstly, a resource fork can + * contain no more than 2727 resources. Secondly, the Resource + * Manager uses a linear search to find a particular resource, which + * could make having lots of host keys quite slow. + */ + +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; + Handle reshandle; + 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); + + reshandle = Get1NamedResource(FOUR_CHAR_CODE('TEXT'), presname); + if (reshandle != NULL) { + /* The resource exists, we're replacing a host key */ + RemoveResource(reshandle); + } + 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: * Local Variables: * c-file-style: "simon"