X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/797f6ff3e6da533570a0dc074771d485619e49c8..0dbf44654a055731a4585543626a3f9d6758fa0d:/unix/uxstore.c diff --git a/unix/uxstore.c b/unix/uxstore.c index e12af036..9ee083ae 100644 --- a/unix/uxstore.c +++ b/unix/uxstore.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,8 +19,14 @@ #include "storage.h" #include "tree234.h" +#ifdef PATH_MAX +#define FNLEN PATH_MAX +#else +#define FNLEN 1024 /* XXX */ +#endif + enum { - INDEX_DIR, INDEX_HOSTKEYS, INDEX_RANDSEED, + INDEX_DIR, INDEX_HOSTKEYS, INDEX_HOSTKEYS_TMP, INDEX_RANDSEED, INDEX_SESSIONDIR, INDEX_SESSION, }; @@ -85,12 +92,14 @@ static void make_filename(char *filename, int index, const char *subname) char *home; int len; home = getenv("HOME"); - strncpy(filename, home, FILENAME_MAX); + if (!home) + home="/"; + strncpy(filename, home, FNLEN); len = strlen(filename); if (index == INDEX_SESSION) { char *munged = mungestr(subname); char *fn = dupprintf("/.putty/sessions/%s", munged); - strncpy(filename + len, fn, FILENAME_MAX - len); + strncpy(filename + len, fn, FNLEN - len); sfree(fn); sfree(munged); } else { @@ -98,45 +107,16 @@ static void make_filename(char *filename, int index, const char *subname) index == INDEX_DIR ? "/.putty" : index == INDEX_SESSIONDIR ? "/.putty/sessions" : index == INDEX_HOSTKEYS ? "/.putty/sshhostkeys" : + index == INDEX_HOSTKEYS_TMP ? "/.putty/sshhostkeys.tmp" : index == INDEX_RANDSEED ? "/.putty/randomseed" : - "/.putty/ERROR", FILENAME_MAX - len); - } - filename[FILENAME_MAX-1] = '\0'; -} - -/* - * Read an entire line of text from a file. Return a buffer - * malloced to be as big as necessary (caller must free). - */ -static char *fgetline(FILE *fp) -{ - char *ret = snewn(512, char); - int size = 512, len = 0; - while (fgets(ret + len, size - len, fp)) { - len += strlen(ret + len); - if (ret[len-1] == '\n') - break; /* got a newline, we're done */ - size = len + 512; - ret = sresize(ret, size, char); - } - if (len == 0) { /* first fgets returned NULL */ - sfree(ret); - return NULL; + "/.putty/ERROR", FNLEN - len); } - ret[len] = '\0'; - return ret; + filename[FNLEN-1] = '\0'; } -/* - * For the moment, the only existing Unix utility is pterm and that - * has no GUI configuration at all, so our write routines need do - * nothing. Eventually I suppose these will read and write an rc - * file somewhere or other. - */ - void *open_settings_w(const char *sessionname, char **errmsg) { - char filename[FILENAME_MAX]; + char filename[FNLEN]; FILE *fp; *errmsg = NULL; @@ -188,6 +168,7 @@ void close_settings_w(void *handle) * PuTTY's inbuilt defaults, but that the disk files will then * override those. This isn't optimal, but it's the best I can * immediately work out. + * FIXME: the above comment is a bit out of date. Did it happen? */ struct keyval { @@ -252,7 +233,7 @@ const char *get_setting(const char *key) void *open_settings_r(const char *sessionname) { - char filename[FILENAME_MAX]; + char filename[FNLEN]; FILE *fp; char *line; tree234 *ret; @@ -367,7 +348,7 @@ void close_settings_r(void *handle) void del_settings(const char *sessionname) { - char filename[FILENAME_MAX]; + char filename[FNLEN]; make_filename(filename, INDEX_SESSION, sessionname); unlink(filename); } @@ -375,7 +356,7 @@ void del_settings(const char *sessionname) void *enum_settings_start(void) { DIR *dp; - char filename[FILENAME_MAX]; + char filename[FNLEN]; make_filename(filename, INDEX_SESSIONDIR, NULL); dp = opendir(filename); @@ -388,7 +369,7 @@ char *enum_settings_next(void *handle, char *buffer, int buflen) DIR *dp = (DIR *)handle; struct dirent *de; struct stat st; - char fullpath[FILENAME_MAX]; + char fullpath[FNLEN]; int len; char *unmunged; @@ -396,10 +377,10 @@ char *enum_settings_next(void *handle, char *buffer, int buflen) len = strlen(fullpath); while ( (de = readdir(dp)) != NULL ) { - if (len < FILENAME_MAX) { + if (len < FNLEN) { fullpath[len] = '/'; - strncpy(fullpath+len+1, de->d_name, FILENAME_MAX-(len+1)); - fullpath[FILENAME_MAX-1] = '\0'; + strncpy(fullpath+len+1, de->d_name, FNLEN-(len+1)); + fullpath[FNLEN-1] = '\0'; } if (stat(fullpath, &st) < 0 || !S_ISREG(st.st_mode)) @@ -434,7 +415,7 @@ int verify_host_key(const char *hostname, int port, const char *keytype, const char *key) { FILE *fp; - char filename[FILENAME_MAX]; + char filename[FNLEN]; char *line; int ret; @@ -494,38 +475,66 @@ int verify_host_key(const char *hostname, int port, break; } + fclose(fp); return ret; } void store_host_key(const char *hostname, int port, const char *keytype, const char *key) { - FILE *fp; - int fd; - char filename[FILENAME_MAX]; + FILE *rfp, *wfp; + char *newtext, *line; + int headerlen; + char filename[FNLEN], tmpfilename[FNLEN]; - make_filename(filename, INDEX_HOSTKEYS, NULL); - fd = open(filename, O_CREAT | O_APPEND | O_RDWR, 0600); - if (fd < 0) { - char dir[FILENAME_MAX]; + newtext = dupprintf("%s@%d:%s %s\n", keytype, port, hostname, key); + headerlen = 1 + strcspn(newtext, " "); /* count the space too */ - make_filename(dir, INDEX_DIR, NULL); - mkdir(dir, 0700); - fd = open(filename, O_CREAT | O_APPEND | O_RDWR, 0600); + /* + * Open both the old file and a new file. + */ + make_filename(tmpfilename, INDEX_HOSTKEYS_TMP, NULL); + wfp = fopen(tmpfilename, "w"); + if (!wfp) { + char dir[FNLEN]; + + make_filename(dir, INDEX_DIR, NULL); + mkdir(dir, 0700); + wfp = fopen(tmpfilename, "w"); } - if (fd < 0) { - perror(filename); - exit(1); + if (!wfp) + return; + make_filename(filename, INDEX_HOSTKEYS, NULL); + rfp = fopen(filename, "r"); + + /* + * Copy all lines from the old file to the new one that _don't_ + * involve the same host key identifier as the one we're adding. + */ + if (rfp) { + while ( (line = fgetline(rfp)) ) { + if (strncmp(line, newtext, headerlen)) + fputs(line, wfp); + } + fclose(rfp); } - fp = fdopen(fd, "a"); - fprintf(fp, "%s@%d:%s %s\n", keytype, port, hostname, key); - fclose(fp); + + /* + * Now add the new line at the end. + */ + fputs(newtext, wfp); + + fclose(wfp); + + rename(tmpfilename, filename); + + sfree(newtext); } void read_random_seed(noise_consumer_t consumer) { int fd; - char fname[FILENAME_MAX]; + char fname[FNLEN]; make_filename(fname, INDEX_RANDSEED, NULL); fd = open(fname, O_RDONLY); @@ -541,7 +550,7 @@ void read_random_seed(noise_consumer_t consumer) void write_random_seed(void *data, int len) { int fd; - char fname[FILENAME_MAX]; + char fname[FNLEN]; make_filename(fname, INDEX_RANDSEED, NULL); /* @@ -551,7 +560,7 @@ void write_random_seed(void *data, int len) */ fd = open(fname, O_CREAT | O_WRONLY, 0600); if (fd < 0) { - char dir[FILENAME_MAX]; + char dir[FNLEN]; make_filename(dir, INDEX_DIR, NULL); mkdir(dir, 0700);