****************** 227,578 ****- void enum_settings_finish(void *handle)- {- struct enumsettings *e = (struct enumsettings *) handle;- RegCloseKey(e->key);- sfree(e); }- static void hostkey_regname(char *buffer, const char *hostname,- int port, const char *keytype) {- int len;- strcpy(buffer, keytype);- strcat(buffer, "@");- len = strlen(buffer);- len += sprintf(buffer + len, "%d:", port);- mungestr(hostname, buffer + strlen(buffer)); } int verify_host_key(const char *hostname, int port, const char *keytype, const char *key) {- char *otherstr, *regname;- int len;- HKEY rkey;- DWORD readlen;- DWORD type;- int ret, compare;-- len = 1 + strlen(key);-- /*- * Now read a saved key in from the registry and see what it- * says.- */- otherstr = snewn(len, char);- regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char);- hostkey_regname(regname, hostname, port, keytype);- if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",- &rkey) != ERROR_SUCCESS)- return 1; /* key does not exist in registry */- readlen = len;- ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen);- if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&- !strcmp(keytype, "rsa")) {- /*- * Key didn't exist. If the key type is RSA, we'll try- * another trick, which is to look up the _old_ key format- * under just the hostname and translate that.- */- char *justhost = regname + 1 + strcspn(regname, ":");- char *oldstyle = snewn(len + 10, char); /* safety margin */- readlen = len;- ret = RegQueryValueEx(rkey, justhost, NULL, &type,- oldstyle, &readlen);- if (ret == ERROR_SUCCESS && type == REG_SZ) { /*- * The old format is two old-style bignums separated by- * a slash. An old-style bignum is made of groups of- * four hex digits: digits are ordered in sensible- * (most to least significant) order within each group,- * but groups are ordered in silly (least to most)- * order within the bignum. The new format is two- * ordinary C-format hex numbers (0xABCDEFG...XYZ, with- * A nonzero except in the special case 0x0, which- * doesn't appear anyway in RSA keys) separated by a- * comma. All hex digits are lowercase in both formats. */- char *p = otherstr;- char *q = oldstyle;- int i, j;-- for (i = 0; i < 2; i++) {- int ndigits, nwords;- *p++ = '0';- *p++ = 'x';- ndigits = strcspn(q, "/"); /* find / or end of string */- nwords = ndigits / 4;- /* now trim ndigits to remove leading zeros */- while (q[(ndigits - 1) ^ 3] == '0' && ndigits > 1)- ndigits--;- /* now move digits over to new string */- for (j = 0; j < ndigits; j++)- p[ndigits - 1 - j] = q[j ^ 3];- p += ndigits;- q += nwords * 4;- if (*q) {- q++; /* eat the slash */- *p++ = ','; /* add a comma */- }- *p = '\0'; /* terminate the string */- }- /*- * Now _if_ this key matches, we'll enter it in the new- * format. If not, we'll assume something odd went- * wrong, and hyper-cautiously do nothing.- */- if (!strcmp(otherstr, key))- RegSetValueEx(rkey, regname, 0, REG_SZ, otherstr,- strlen(otherstr) + 1);- } }- RegCloseKey(rkey);-- compare = strcmp(otherstr, key);-- sfree(otherstr);- sfree(regname);-- if (ret == ERROR_MORE_DATA ||- (ret == ERROR_SUCCESS && type == REG_SZ && compare))- return 2; /* key is different in registry */- else if (ret != ERROR_SUCCESS || type != REG_SZ)- return 1; /* key does not exist in registry */- else- return 0; /* key matched OK in registry */ } void store_host_key(const char *hostname, int port, const char *keytype, const char *key) {- char *regname;- HKEY rkey;- regname = snewn(3 * (strlen(hostname) + strlen(keytype)) + 15, char);- hostkey_regname(regname, hostname, port, keytype);-- if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",- &rkey) != ERROR_SUCCESS)- return; /* key does not exist in registry */- RegSetValueEx(rkey, regname, 0, REG_SZ, key, strlen(key) + 1);- RegCloseKey(rkey);- }- /*- * Find the random seed file path and store it in `seedpath'. */- static void get_seedpath(void)- {- HKEY rkey;- DWORD type, size;- size = sizeof(seedpath);- if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey) ==- ERROR_SUCCESS) {- int ret = RegQueryValueEx(rkey, "RandSeedFile",- 0, &type, seedpath, &size);- if (ret != ERROR_SUCCESS || type != REG_SZ)- seedpath[0] = '\0';- RegCloseKey(rkey);- } else- seedpath[0] = '\0';- if (!seedpath[0]) {- int len, ret;- len =- GetEnvironmentVariable("HOMEDRIVE", seedpath,- sizeof(seedpath));- ret =- GetEnvironmentVariable("HOMEPATH", seedpath + len,- sizeof(seedpath) - len);- if (ret == 0) { /* probably win95; store in \WINDOWS */- GetWindowsDirectory(seedpath, sizeof(seedpath));- len = strlen(seedpath);- } else- len += ret;- strcpy(seedpath + len, "\\PUTTY.RND");- } } void read_random_seed(noise_consumer_t consumer) {- HANDLE seedf;-- if (!seedpath[0])- get_seedpath();-- seedf = CreateFile(seedpath, GENERIC_READ,- FILE_SHARE_READ | FILE_SHARE_WRITE,- NULL, OPEN_EXISTING, 0, NULL);-- if (seedf != INVALID_HANDLE_VALUE) {- while (1) {- char buf[1024];- DWORD len;- if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len)- consumer(buf, len);- else- break;- }- CloseHandle(seedf); } } void write_random_seed(void *data, int len) {- HANDLE seedf;-- if (!seedpath[0])- get_seedpath();-- seedf = CreateFile(seedpath, GENERIC_WRITE, 0,- NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);-- if (seedf != INVALID_HANDLE_VALUE) {- DWORD lenwritten;-- WriteFile(seedf, data, len, &lenwritten, NULL);- CloseHandle(seedf);- }- }- /*- * Recursively delete a registry key and everything under it. */- static void registry_recursive_remove(HKEY key)- {- DWORD i;- char name[MAX_PATH + 1];- HKEY subkey;- i = 0;- while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) {- if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {- registry_recursive_remove(subkey);- RegCloseKey(subkey); }- RegDeleteKey(key, name); } } void cleanup_all(void) {- HKEY key;- int ret;- char name[MAX_PATH + 1];- /* ------------------------------------------------------------- * Wipe out the random seed file.- */- if (!seedpath[0])- get_seedpath();- remove(seedpath);- /* ------------------------------------------------------------- * Destroy all registry information associated with PuTTY.- */-- /*- * Open the main PuTTY registry key and remove everything in it.- */- if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) ==- ERROR_SUCCESS) {- registry_recursive_remove(key);- RegCloseKey(key);- }- /*- * Now open the parent key and remove the PuTTY main key. Once- * we've done that, see if the parent key has any other- * children.- */- if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT,- &key) == ERROR_SUCCESS) {- RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);- ret = RegEnumKey(key, 0, name, sizeof(name));- RegCloseKey(key);- /*- * If the parent key had no other children, we must delete- * it in its turn. That means opening the _grandparent_- * key.- */- if (ret != ERROR_SUCCESS) {- if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,- &key) == ERROR_SUCCESS) {- RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);- RegCloseKey(key);- }- }- }- /*- * Now we're done.- */- }--- 373,628 ----+ void enum_settings_finish(void *handle) {+ DIR *dp = (DIR *)handle;+ closedir(dp); }+ /*+ * Lines in the host keys file are of the form+ *+ * type@port:hostname keydata+ *+ * e.g.+ *+ * rsa@22:foovax.example.org 0x23,0x293487364395345345....2343+ */ int verify_host_key(const char *hostname, int port, const char *keytype, const char *key) {+ FILE *fp;+ char filename[FILENAME_MAX];+ char *line;+ int ret;+ make_filename(filename, INDEX_HOSTKEYS, NULL);+ fp = fopen(filename, "r");+ if (!fp)+ return 1; /* key does not exist */+ ret = 1;+ while ( (line = fgetline(fp)) ) {+ int i;+ char *p = line;+ char porttext[20];+ line[strcspn(line, "\n")] = '\0'; /* strip trailing newline */+ i = strlen(keytype);+ if (strncmp(p, keytype, i))+ goto done;+ p += i;++ if (*p != '@')+ goto done;+ p++;++ sprintf(porttext, "%d", port);+ i = strlen(porttext);+ if (strncmp(p, porttext, i))+ goto done;+ p += i;++ if (*p != ':')+ goto done;+ p++;++ i = strlen(hostname);+ if (strncmp(p, hostname, i))+ goto done;+ p += i;++ if (*p != ' ')+ goto done;+ p++; /*+ * Found the key. Now just work out whether it's the right+ * one or not. */+ if (!strcmp(p, key))+ ret = 0; /* key matched OK */+ else+ ret = 2; /* key mismatch */+ done:+ sfree(line);+ if (ret != 1)+ break; }+ fclose(fp);+ return ret; } void store_host_key(const char *hostname, int port, const char *keytype, const char *key) {+ FILE *rfp, *wfp;+ char *newtext, *line;+ int headerlen;+ char filename[FILENAME_MAX], tmpfilename[FILENAME_MAX];+ newtext = dupprintf("%s@%d:%s %s\n", keytype, port, hostname, key);+ headerlen = 1 + strcspn(newtext, " "); /* count the space too */+ /*+ * Open both the old file and a new file.+ */+ make_filename(tmpfilename, INDEX_HOSTKEYS_TMP, NULL);+ wfp = fopen(tmpfilename, "w");+ if (!wfp) {+ char dir[FILENAME_MAX];++ make_filename(dir, INDEX_DIR, NULL);+ _mkdir(dir);+ wfp = fopen(tmpfilename, "w");+ }+ 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);+ }+ /*+ * Now add the new line at the end.+ */+ fputs(newtext, wfp);+ fclose(wfp);+ _unlink(filename);+ rename(tmpfilename, filename);+ sfree(newtext); } void read_random_seed(noise_consumer_t consumer) {+ int fd;+ char fname[FILENAME_MAX];+ make_filename(fname, INDEX_RANDSEED, NULL);+ fd = _open(fname, _O_RDONLY);+ if (fd) {+ char buf[512];+ int ret;+ while ( (ret = _read(fd, buf, sizeof(buf))) > 0)+ consumer(buf, ret);+ _close(fd); } } void write_random_seed(void *data, int len) {+ int fd;+ char fname[FILENAME_MAX];+ make_filename(fname, INDEX_RANDSEED, NULL);+ /*+ * Don't truncate the random seed file if it already exists; if+ * something goes wrong half way through writing it, it would+ * be better to leave the old data there than to leave it empty. */+ fd = _open(fname, _O_CREAT | _O_WRONLY, 0600);+ if (fd < 0) {+ char dir[FILENAME_MAX];+ make_filename(dir, INDEX_DIR, NULL);+ _mkdir(dir);+ fd = _open(fname, _O_CREAT | _O_WRONLY, 0600); }++ while (len > 0) {+ int ret = _write(fd, data, len);+ if (ret <= 0) break;+ len -= ret;+ data = (char *)data + len; }++ _close(fd); } void cleanup_all(void) {+ }