X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/f25da523d156f0d30858552e0eec860462df1ca8..88c152099b9012a92e6ff4d8157933b55401cdf3:/windlg.c diff --git a/windlg.c b/windlg.c index e7d58fd6..1b800e87 100644 --- a/windlg.c +++ b/windlg.c @@ -1,131 +1,70 @@ #include #include #include +#ifndef AUTO_WINSOCK +#ifdef WINSOCK_TWO +#include +#else #include +#endif +#endif #include #include #include "ssh.h" #include "putty.h" #include "win_res.h" +#include "storage.h" -#define NPANELS 7 -#define MAIN_NPANELS 7 -#define RECONF_NPANELS 4 - -static const char *const puttystr = PUTTY_REG_POS "\\Sessions"; +#define NPANELS 8 +#define MAIN_NPANELS 8 +#define RECONF_NPANELS 5 -static void get_sesslist(int allocate); +static char **events = NULL; +static int nevents = 0, negsize = 0; -static char **negots = NULL; -static int nnegots = 0, negsize = 0; static HWND logbox = NULL, abtbox = NULL; -static char hex[16] = "0123456789ABCDEF"; - -static void mungestr(char *in, char *out) { - int candot = 0; - - while (*in) { - if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' || - *in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) { - *out++ = '%'; - *out++ = hex[((unsigned char)*in) >> 4]; - *out++ = hex[((unsigned char)*in) & 15]; - } else - *out++ = *in; - in++; - candot = 1; - } - *out = '\0'; - return; -} - -static void unmungestr(char *in, char *out) { - while (*in) { - if (*in == '%' && in[1] && in[2]) { - int i, j; - - i = in[1] - '0'; i -= (i > 9 ? 7 : 0); - j = in[2] - '0'; j -= (j > 9 ? 7 : 0); - - *out++ = (i<<4) + j; - in += 3; - } else - *out++ = *in++; - } - *out = '\0'; - return; -} - -static void wpps(HKEY key, LPCTSTR name, LPCTSTR value) { - RegSetValueEx(key, name, 0, REG_SZ, value, 1+strlen(value)); -} - -static void wppi(HKEY key, LPCTSTR name, int value) { - RegSetValueEx(key, name, 0, REG_DWORD, - (CONST BYTE *)&value, sizeof(value)); -} - -static void gpps(HKEY key, LPCTSTR name, LPCTSTR def, - LPTSTR val, int len) { - DWORD type, size; - size = len; - - if (key == NULL || - RegQueryValueEx(key, name, 0, &type, val, &size) != ERROR_SUCCESS || - type != REG_SZ) { +static void gpps(void *handle, char *name, char *def, char *val, int len) { + if (!read_setting_s(handle, name, val, len)) { strncpy(val, def, len); val[len-1] = '\0'; } } -static void gppi(HKEY key, LPCTSTR name, int def, int *i) { - DWORD type, val, size; - size = sizeof(val); - - if (key == NULL || - RegQueryValueEx(key, name, 0, &type, - (BYTE *)&val, &size) != ERROR_SUCCESS || - size != sizeof(val) || type != REG_DWORD) - *i = def; - else - *i = val; +static void gppi(void *handle, char *name, int def, int *i) { + *i = read_setting_i(handle, name, def); } static HINSTANCE hinst; -static char **sessions; -static int nsessions; - static int readytogo; static void save_settings (char *section, int do_host) { int i; - HKEY subkey1, sesskey; char *p; + void *sesskey; - p = malloc(3*strlen(section)+1); - mungestr(section, p); - - if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1)!=ERROR_SUCCESS || - RegCreateKey(subkey1, p, &sesskey) != ERROR_SUCCESS) { - sesskey = NULL; - } + sesskey = open_settings_w(section); + if (!sesskey) + return; - free(p); - RegCloseKey(subkey1); - - wppi (sesskey, "Present", 1); + write_setting_i (sesskey, "Present", 1); if (do_host) { - wpps (sesskey, "HostName", cfg.host); - wppi (sesskey, "PortNumber", cfg.port); - wpps (sesskey, "Protocol", - cfg.protocol == PROT_SSH ? "ssh" : "telnet"); + write_setting_s (sesskey, "HostName", cfg.host); + write_setting_i (sesskey, "PortNumber", cfg.port); + p = "raw"; + for (i = 0; backends[i].name != NULL; i++) + if (backends[i].protocol == cfg.protocol) { + p = backends[i].name; + break; + } + write_setting_s (sesskey, "Protocol", p); } - wppi (sesskey, "CloseOnExit", !!cfg.close_on_exit); - wpps (sesskey, "TerminalType", cfg.termtype); - wpps (sesskey, "TerminalSpeed", cfg.termspeed); + write_setting_i (sesskey, "CloseOnExit", !!cfg.close_on_exit); + write_setting_i (sesskey, "WarnOnClose", !!cfg.warn_on_close); + write_setting_s (sesskey, "TerminalType", cfg.termtype); + write_setting_s (sesskey, "TerminalSpeed", cfg.termspeed); { char buf[2*sizeof(cfg.environmt)], *p, *q; p = buf; @@ -143,39 +82,51 @@ static void save_settings (char *section, int do_host) { q++; } *p = '\0'; - wpps (sesskey, "Environment", buf); + write_setting_s (sesskey, "Environment", buf); } - wpps (sesskey, "UserName", cfg.username); - wppi (sesskey, "NoPTY", cfg.nopty); - wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" : - "3des"); - wppi (sesskey, "RFCEnviron", cfg.rfc_environ); - wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete); - wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend); - wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys); - wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor); - wppi (sesskey, "ApplicationKeypad", cfg.app_keypad); - wppi (sesskey, "ScrollbackLines", cfg.savelines); - wppi (sesskey, "DECOriginMode", cfg.dec_om); - wppi (sesskey, "AutoWrapMode", cfg.wrap_mode); - wppi (sesskey, "LFImpliesCR", cfg.lfhascr); - wppi (sesskey, "WinNameAlways", cfg.win_name_always); - wppi (sesskey, "TermWidth", cfg.width); - wppi (sesskey, "TermHeight", cfg.height); - wpps (sesskey, "Font", cfg.font); - wppi (sesskey, "FontIsBold", cfg.fontisbold); - wppi (sesskey, "FontHeight", cfg.fontheight); - wppi (sesskey, "FontVTMode", cfg.vtmode); - wppi (sesskey, "TryPalette", cfg.try_palette); - wppi (sesskey, "BoldAsColour", cfg.bold_colour); + write_setting_s (sesskey, "UserName", cfg.username); + write_setting_i (sesskey, "NoPTY", cfg.nopty); + write_setting_i (sesskey, "AgentFwd", cfg.agentfwd); + write_setting_s (sesskey, "RemoteCmd", cfg.remote_cmd); + write_setting_s (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" : + cfg.cipher == CIPHER_DES ? "des" : "3des"); + write_setting_i (sesskey, "AuthTIS", cfg.try_tis_auth); + write_setting_i (sesskey, "SshProt", cfg.sshprot); + write_setting_s (sesskey, "PublicKeyFile", cfg.keyfile); + write_setting_i (sesskey, "RFCEnviron", cfg.rfc_environ); + write_setting_i (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete); + write_setting_i (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend); + write_setting_i (sesskey, "LinuxFunctionKeys", cfg.funky_type); + write_setting_i (sesskey, "ApplicationCursorKeys", cfg.app_cursor); + write_setting_i (sesskey, "ApplicationKeypad", cfg.app_keypad); + write_setting_i (sesskey, "NetHackKeypad", cfg.nethack_keypad); + write_setting_i (sesskey, "AltF4", cfg.alt_f4); + write_setting_i (sesskey, "AltSpace", cfg.alt_space); + write_setting_i (sesskey, "LdiscTerm", cfg.ldisc_term); + write_setting_i (sesskey, "BlinkCur", cfg.blink_cur); + write_setting_i (sesskey, "Beep", cfg.beep); + write_setting_i (sesskey, "ScrollbackLines", cfg.savelines); + write_setting_i (sesskey, "DECOriginMode", cfg.dec_om); + write_setting_i (sesskey, "AutoWrapMode", cfg.wrap_mode); + write_setting_i (sesskey, "LFImpliesCR", cfg.lfhascr); + write_setting_i (sesskey, "WinNameAlways", cfg.win_name_always); + write_setting_i (sesskey, "TermWidth", cfg.width); + write_setting_i (sesskey, "TermHeight", cfg.height); + write_setting_s (sesskey, "Font", cfg.font); + write_setting_i (sesskey, "FontIsBold", cfg.fontisbold); + write_setting_i (sesskey, "FontCharSet", cfg.fontcharset); + write_setting_i (sesskey, "FontHeight", cfg.fontheight); + write_setting_i (sesskey, "FontVTMode", cfg.vtmode); + write_setting_i (sesskey, "TryPalette", cfg.try_palette); + write_setting_i (sesskey, "BoldAsColour", cfg.bold_colour); for (i=0; i<22; i++) { char buf[20], buf2[30]; sprintf(buf, "Colour%d", i); sprintf(buf2, "%d,%d,%d", cfg.colours[i][0], cfg.colours[i][1], cfg.colours[i][2]); - wpps (sesskey, buf, buf2); + write_setting_s (sesskey, buf, buf2); } - wppi (sesskey, "MouseIsXterm", cfg.mouse_is_xterm); + write_setting_i (sesskey, "MouseIsXterm", cfg.mouse_is_xterm); for (i=0; i<256; i+=32) { char buf[20], buf2[256]; int j; @@ -185,61 +136,40 @@ static void save_settings (char *section, int do_host) { sprintf(buf2+strlen(buf2), "%s%d", (*buf2 ? "," : ""), cfg.wordness[j]); } - wpps (sesskey, buf, buf2); + write_setting_s (sesskey, buf, buf2); } - - RegCloseKey(sesskey); -} - -static void del_session (char *section) { - HKEY subkey1; - char *p; - - if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) - return; - - p = malloc(3*strlen(section)+1); - mungestr(section, p); - RegDeleteKey(subkey1, p); - free(p); - - RegCloseKey(subkey1); + write_setting_i (sesskey, "KoiWinXlat", cfg.xlat_enablekoiwin); + write_setting_i (sesskey, "88592Xlat", cfg.xlat_88592w1250); + write_setting_i (sesskey, "CapsLockCyr", cfg.xlat_capslockcyr); + write_setting_i (sesskey, "ScrollBar", cfg.scrollbar); + write_setting_i (sesskey, "ScrollOnKey", cfg.scroll_on_key); + write_setting_i (sesskey, "LockSize", cfg.locksize); + write_setting_i (sesskey, "BCE", cfg.bce); + write_setting_i (sesskey, "BlinkText", cfg.blinktext); + + close_settings_w(sesskey); } static void load_settings (char *section, int do_host) { int i; - HKEY subkey1, sesskey; - char *p; + char prot[10]; + void *sesskey; - p = malloc(3*strlen(section)+1); - mungestr(section, p); + sesskey = open_settings_r(section); - if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) { - sesskey = NULL; - } else { - if (RegOpenKey(subkey1, p, &sesskey) != ERROR_SUCCESS) { - sesskey = NULL; - } - RegCloseKey(subkey1); - } + gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host)); + gppi (sesskey, "PortNumber", default_port, &cfg.port); - free(p); + gpps (sesskey, "Protocol", "default", prot, 10); + cfg.protocol = default_protocol; + for (i = 0; backends[i].name != NULL; i++) + if (!strcmp(prot, backends[i].name)) { + cfg.protocol = backends[i].protocol; + break; + } - if (do_host) { - char prot[10]; - gpps (sesskey, "HostName", "", cfg.host, sizeof(cfg.host)); - gppi (sesskey, "PortNumber", 23, &cfg.port); - gpps (sesskey, "Protocol", "telnet", prot, 10); - if (!strcmp(prot, "ssh")) - cfg.protocol = PROT_SSH; - else - cfg.protocol = PROT_TELNET; - } else { - cfg.protocol = PROT_TELNET; - cfg.port = 23; - *cfg.host = '\0'; - } gppi (sesskey, "CloseOnExit", 1, &cfg.close_on_exit); + gppi (sesskey, "WarnOnClose", 1, &cfg.warn_on_close); gpps (sesskey, "TerminalType", "xterm", cfg.termtype, sizeof(cfg.termtype)); gpps (sesskey, "TerminalSpeed", "38400,38400", cfg.termspeed, @@ -248,7 +178,7 @@ static void load_settings (char *section, int do_host) { char buf[2*sizeof(cfg.environmt)], *p, *q; gpps (sesskey, "Environment", "", buf, sizeof(buf)); p = buf; - q = cfg.environmt; + q = cfg.environmt; while (*p) { while (*p && *p != ',') { int c = *p++; @@ -256,7 +186,7 @@ static void load_settings (char *section, int do_host) { c = '\t'; if (c == '\\') c = *p++; - *p++ = c; + *q++ = c; } if (*p == ',') p++; *q++ = '\0'; @@ -265,20 +195,33 @@ static void load_settings (char *section, int do_host) { } gpps (sesskey, "UserName", "", cfg.username, sizeof(cfg.username)); gppi (sesskey, "NoPTY", 0, &cfg.nopty); + gppi (sesskey, "AgentFwd", 0, &cfg.agentfwd); + gpps (sesskey, "RemoteCmd", "", cfg.remote_cmd, sizeof(cfg.remote_cmd)); { char cipher[10]; gpps (sesskey, "Cipher", "3des", cipher, 10); if (!strcmp(cipher, "blowfish")) cfg.cipher = CIPHER_BLOWFISH; + else if (!strcmp(cipher, "des")) + cfg.cipher = CIPHER_DES; else cfg.cipher = CIPHER_3DES; } + gppi (sesskey, "SshProt", 1, &cfg.sshprot); + gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth); + gpps (sesskey, "PublicKeyFile", "", cfg.keyfile, sizeof(cfg.keyfile)); gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ); gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete); gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend); - gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys); + gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.funky_type); gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor); gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad); + gppi (sesskey, "NetHackKeypad", 0, &cfg.nethack_keypad); + gppi (sesskey, "AltF4", 1, &cfg.alt_f4); + gppi (sesskey, "AltSpace", 0, &cfg.alt_space); + gppi (sesskey, "LdiscTerm", 0, &cfg.ldisc_term); + gppi (sesskey, "BlinkCur", 0, &cfg.blink_cur); + gppi (sesskey, "Beep", 1, &cfg.beep); gppi (sesskey, "ScrollbackLines", 200, &cfg.savelines); gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om); gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode); @@ -288,8 +231,9 @@ static void load_settings (char *section, int do_host) { gppi (sesskey, "TermHeight", 24, &cfg.height); gpps (sesskey, "Font", "Courier", cfg.font, sizeof(cfg.font)); gppi (sesskey, "FontIsBold", 0, &cfg.fontisbold); + gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg.fontcharset); gppi (sesskey, "FontHeight", 10, &cfg.fontheight); - gppi (sesskey, "FontVTMode", VT_POORMAN, &cfg.vtmode); + gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg.vtmode); gppi (sesskey, "TryPalette", 0, &cfg.try_palette); gppi (sesskey, "BoldAsColour", 1, &cfg.bold_colour); for (i=0; i<22; i++) { @@ -301,10 +245,14 @@ static void load_settings (char *section, int do_host) { "85,255,255", "187,187,187", "255,255,255" }; char buf[20], buf2[30]; + int c0, c1, c2; sprintf(buf, "Colour%d", i); gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2)); - sscanf(buf2, "%d,%d,%d", &cfg.colours[i][0], - &cfg.colours[i][1], &cfg.colours[i][2]); + if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) { + cfg.colours[i][0] = c0; + cfg.colours[i][1] = c1; + cfg.colours[i][2] = c2; + } } gppi (sesskey, "MouseIsXterm", 0, &cfg.mouse_is_xterm); for (i=0; i<256; i+=32) { @@ -330,7 +278,34 @@ static void load_settings (char *section, int do_host) { cfg.wordness[j] = atoi(q); } } - RegCloseKey(sesskey); + gppi (sesskey, "KoiWinXlat", 0, &cfg.xlat_enablekoiwin); + gppi (sesskey, "88592Xlat", 0, &cfg.xlat_88592w1250); + gppi (sesskey, "CapsLockCyr", 0, &cfg.xlat_capslockcyr); + gppi (sesskey, "ScrollBar", 1, &cfg.scrollbar); + gppi (sesskey, "ScrollOnKey", 0, &cfg.scroll_on_key); + gppi (sesskey, "LockSize", 0, &cfg.locksize); + gppi (sesskey, "BCE", 0, &cfg.bce); + gppi (sesskey, "BlinkText", 0, &cfg.blinktext); + + close_settings_r(sesskey); +} + +static void force_normal(HWND hwnd) +{ +static int recurse = 0; + + WINDOWPLACEMENT wp; + + if(recurse) return; + recurse = 1; + + wp.length = sizeof(wp); + if (GetWindowPlacement(hwnd, &wp)) + { + wp.showCmd = SW_SHOWNORMAL; + SetWindowPlacement(hwnd, &wp); + } + recurse = 0; } static void MyGetDlgItemInt (HWND hwnd, int id, int *result) { @@ -347,9 +322,9 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg, switch (msg) { case WM_INITDIALOG: - for (i=0; i= negsize) { +void logevent (char *string) { + if (nevents >= negsize) { negsize += 64; - negots = srealloc (negots, negsize * sizeof(*negots)); + events = srealloc (events, negsize * sizeof(*events)); } - negots[nnegots] = smalloc(1+strlen(string)); - strcpy (negots[nnegots], string); - nnegots++; - if (logbox) + events[nevents] = smalloc(1+strlen(string)); + strcpy (events[nevents], string); + nevents++; + if (logbox) { + int count; SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING, 0, (LPARAM)string); + count = SendDlgItemMessage (logbox, IDN_LIST, LB_GETCOUNT, 0, 0); + SendDlgItemMessage (logbox, IDN_LIST, LB_SETTOPINDEX, count-1, 0); + } } -void shownegot (HWND hwnd) { +void showeventlog (HWND hwnd) { if (!logbox) { logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX), hwnd, LogProc); @@ -1330,74 +1550,70 @@ void showabout (HWND hwnd) { } } -void verify_ssh_host_key(char *host, struct RSAKey *key) { - char *keystr, *otherstr, *mungedhost; - int len; - HKEY rkey; +void verify_ssh_host_key(char *host, int port, char *keytype, + char *keystr, char *fingerprint) { + int ret; - /* - * Format the key into a string. - */ - len = rsastr_len(key); - keystr = malloc(len); - if (!keystr) - fatalbox("Out of memory"); - rsastr_fmt(keystr, key); + static const char absentmsg[] = + "The server's host key is not cached in the registry. You\n" + "have no guarantee that the server is the computer you\n" + "think it is.\n" + "The server's key fingerprint is:\n" + "%s\n" + "If you trust this host, hit Yes to add the key to\n" + "PuTTY's cache and carry on connecting.\n" + "If you do not trust this host, hit No to abandon the\n" + "connection.\n"; + + static const char wrongmsg[] = + "WARNING - POTENTIAL SECURITY BREACH!\n" + "\n" + "The server's host key does not match the one PuTTY has\n" + "cached in the registry. This means that either the\n" + "server administrator has changed the host key, or you\n" + "have actually connected to another computer pretending\n" + "to be the server.\n" + "The new key fingerprint is:\n" + "%s\n" + "If you were expecting this change and trust the new key,\n" + "hit Yes to update PuTTY's cache and continue connecting.\n" + "If you want to carry on connecting but without updating\n" + "the cache, hit No.\n" + "If you want to abandon the connection completely, hit\n" + "Cancel. Hitting Cancel is the ONLY guaranteed safe\n" + "choice.\n"; + + static const char mbtitle[] = "PuTTY Security Alert"; + + + char message[160+ /* sensible fingerprint max size */ + (sizeof(absentmsg) > sizeof(wrongmsg) ? + sizeof(absentmsg) : sizeof(wrongmsg))]; /* - * Now read a saved key in from the registry and see what it - * says. + * Verify the key against the registry. */ - otherstr = malloc(len); - mungedhost = malloc(3*strlen(host)+1); - if (!otherstr || !mungedhost) - fatalbox("Out of memory"); - - mungestr(host, mungedhost); - - if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys", - &rkey) != ERROR_SUCCESS) { - if (MessageBox(NULL, "PuTTY was unable to open the host key cache\n" - "in the registry. There is thus no way to tell\n" - "if the remote host is what you think it is.\n" - "Connect anyway?", "PuTTY Problem", - MB_ICONWARNING | MB_YESNO) == IDNO) - exit(0); - } else { - DWORD readlen = len; - DWORD type; - int ret; - - ret = RegQueryValueEx(rkey, mungedhost, NULL, - &type, otherstr, &readlen); - - if (ret == ERROR_MORE_DATA || - (ret == ERROR_SUCCESS && type == REG_SZ && - strcmp(otherstr, keystr))) { - if (MessageBox(NULL, - "This host's host key is different from the\n" - "one cached in the registry! Someone may be\n" - "impersonating this host for malicious reasons;\n" - "alternatively, the host key may have changed\n" - "due to sloppy system administration.\n" - "Replace key in registry and connect?", - "PuTTY: Security Warning", - MB_ICONWARNING | MB_YESNO) == IDNO) - exit(0); - RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr, - strlen(keystr)+1); - } else if (ret != ERROR_SUCCESS || type != REG_SZ) { - if (MessageBox(NULL, - "This host's host key is not cached in the\n" - "registry. Do you want to add it to the cache\n" - "and carry on connecting?", - "PuTTY: New Host", - MB_ICONWARNING | MB_YESNO) == IDNO) - exit(0); - RegSetValueEx(rkey, mungedhost, 0, REG_SZ, keystr, - strlen(keystr)+1); - } - - RegCloseKey(rkey); + ret = verify_host_key(host, port, keytype, keystr); + + if (ret == 0) /* success - key matched OK */ + return; + if (ret == 2) { /* key was different */ + int mbret; + sprintf(message, wrongmsg, fingerprint); + mbret = MessageBox(NULL, message, mbtitle, + MB_ICONWARNING | MB_YESNOCANCEL); + if (mbret == IDYES) + store_host_key(host, port, keytype, keystr); + if (mbret == IDCANCEL) + exit(0); + } + if (ret == 1) { /* key was absent */ + int mbret; + sprintf(message, absentmsg, fingerprint); + mbret = MessageBox(NULL, message, mbtitle, + MB_ICONWARNING | MB_YESNO); + if (mbret == IDNO) + exit(0); + store_host_key(host, port, keytype, keystr); } }