From be57bcef59397cfc1264736f14776e13e321a66c Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 17 Jan 2004 13:00:18 +0000 Subject: [PATCH] Idiot me! store_host_key() was blindly _appending_ new host keys to the end of the host key file. This is perfectly all right if a host key never changes, but it's completely useless if you need to replace an existing entry. This version should do better. git-svn-id: svn://svn.tartarus.org/sgt/putty@3719 cda61777-01e9-0310-a592-d414129be87e --- unix/uxstore.c | 57 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/unix/uxstore.c b/unix/uxstore.c index 54d35fc9..3d2e2412 100644 --- a/unix/uxstore.c +++ b/unix/uxstore.c @@ -19,7 +19,7 @@ #include "tree234.h" enum { - INDEX_DIR, INDEX_HOSTKEYS, INDEX_RANDSEED, + INDEX_DIR, INDEX_HOSTKEYS, INDEX_HOSTKEYS_TMP, INDEX_RANDSEED, INDEX_SESSIONDIR, INDEX_SESSION, }; @@ -98,6 +98,7 @@ 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); } @@ -495,26 +496,48 @@ int verify_host_key(const char *hostname, int port, 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[FILENAME_MAX], tmpfilename[FILENAME_MAX]; - 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(filename, INDEX_HOSTKEYS, NULL); + rfp = fopen(filename, "r"); + if (!rfp) + return; + make_filename(tmpfilename, INDEX_HOSTKEYS_TMP, NULL); + wfp = fopen(tmpfilename, "w"); + if (!wfp) { + fclose(rfp); + return; } - if (fd < 0) { - perror(filename); - exit(1); + + /* + * 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. + */ + while ( (line = fgetline(rfp)) ) { + if (strncmp(line, newtext, headerlen)) + fputs(line, wfp); } - 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(rfp); + fclose(wfp); + + rename(tmpfilename, filename); + + sfree(newtext); } void read_random_seed(noise_consumer_t consumer) -- 2.11.0