#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 9 #define MAIN_NPANELS 9 #define RECONF_NPANELS 6 static char **events = NULL; static int nevents = 0, negsize = 0; static HWND logbox = NULL, abtbox = NULL; 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(void *handle, char *name, int def, int *i) { *i = read_setting_i(handle, name, def); } static HINSTANCE hinst; static int readytogo; static void save_settings (char *section, int do_host) { int i; char *p; void *sesskey; sesskey = open_settings_w(section); if (!sesskey) return; write_setting_i (sesskey, "Present", 1); if (do_host) { 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); } 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; q = cfg.environmt; while (*q) { while (*q) { int c = *q++; if (c == '=' || c == ',' || c == '\\') *p++ = '\\'; if (c == '\t') c = '='; *p++ = c; } *p++ = ','; q++; } *p = '\0'; write_setting_s (sesskey, "Environment", buf); } 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_s (sesskey, "WinTitle", cfg.wintitle); 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]); write_setting_s (sesskey, buf, buf2); } write_setting_i (sesskey, "MouseIsXterm", cfg.mouse_is_xterm); for (i=0; i<256; i+=32) { char buf[20], buf2[256]; int j; sprintf(buf, "Wordness%d", i); *buf2 = '\0'; for (j=i; j 0) { if (!*p) goto disaster; while (*p) p++; p++; i--; } q = p; if (!*p) goto disaster; while (*p) p++; p++; while (*p) { while (*p) *q++ = *p++; *q++ = *p++; } *q = '\0'; disaster:; } break; } break; } return GeneralPanelProc (hwnd, msg, wParam, lParam); } static int CALLBACK SshProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { OPENFILENAME of; char filename[sizeof(cfg.keyfile)]; switch (msg) { case WM_INITDIALOG: SetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype); SetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username); CheckDlgButton (hwnd, IDC3_NOPTY, cfg.nopty); CheckDlgButton (hwnd, IDC3_AGENTFWD, cfg.agentfwd); CheckRadioButton (hwnd, IDC3_CIPHER3DES, IDC3_CIPHERDES, cfg.cipher == CIPHER_BLOWFISH ? IDC3_CIPHERBLOWF : cfg.cipher == CIPHER_DES ? IDC3_CIPHERDES : IDC3_CIPHER3DES); CheckRadioButton (hwnd, IDC3_SSHPROT1, IDC3_SSHPROT2, cfg.sshprot == 1 ? IDC3_SSHPROT1 : IDC3_SSHPROT2); CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth); SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC3_TTEDIT: if (HIWORD(wParam) == EN_CHANGE) GetDlgItemText (hwnd, IDC3_TTEDIT, cfg.termtype, sizeof(cfg.termtype)-1); break; case IDC3_LOGEDIT: if (HIWORD(wParam) == EN_CHANGE) GetDlgItemText (hwnd, IDC3_LOGEDIT, cfg.username, sizeof(cfg.username)-1); break; case IDC3_NOPTY: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) cfg.nopty = IsDlgButtonChecked (hwnd, IDC3_NOPTY); break; case IDC3_AGENTFWD: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) cfg.agentfwd = IsDlgButtonChecked (hwnd, IDC3_AGENTFWD); break; case IDC3_CIPHER3DES: case IDC3_CIPHERBLOWF: case IDC3_CIPHERDES: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { if (IsDlgButtonChecked (hwnd, IDC3_CIPHER3DES)) cfg.cipher = CIPHER_3DES; else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERBLOWF)) cfg.cipher = CIPHER_BLOWFISH; else if (IsDlgButtonChecked (hwnd, IDC3_CIPHERDES)) cfg.cipher = CIPHER_DES; } break; case IDC3_SSHPROT1: case IDC3_SSHPROT2: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT1)) cfg.sshprot = 1; else if (IsDlgButtonChecked (hwnd, IDC3_SSHPROT2)) cfg.sshprot = 2; } break; case IDC3_AUTHTIS: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS); break; case IDC3_PKEDIT: if (HIWORD(wParam) == EN_CHANGE) GetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile, sizeof(cfg.keyfile)-1); break; case IDC3_PKBUTTON: /* * FIXME: this crashes. Find out why. */ memset(&of, 0, sizeof(of)); #ifdef OPENFILENAME_SIZE_VERSION_400 of.lStructSize = OPENFILENAME_SIZE_VERSION_400; #else of.lStructSize = sizeof(of); #endif of.hwndOwner = hwnd; of.lpstrFilter = "All Files\0*\0\0\0"; of.lpstrCustomFilter = NULL; of.nFilterIndex = 1; of.lpstrFile = filename; strcpy(filename, cfg.keyfile); of.nMaxFile = sizeof(filename); of.lpstrFileTitle = NULL; of.lpstrInitialDir = NULL; of.lpstrTitle = "Select Public Key File"; of.Flags = 0; if (GetOpenFileName(&of)) { strcpy(cfg.keyfile, filename); SetDlgItemText (hwnd, IDC3_PKEDIT, cfg.keyfile); } break; } break; } return GeneralPanelProc (hwnd, msg, wParam, lParam); } static int CALLBACK SelectionProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { int i; switch (msg) { case WM_INITDIALOG: CheckRadioButton (hwnd, IDC4_MBWINDOWS, IDC4_MBXTERM, cfg.mouse_is_xterm ? IDC4_MBXTERM : IDC4_MBWINDOWS); { static int tabs[4] = {25, 61, 96, 128}; SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_SETTABSTOPS, 4, (LPARAM) tabs); } for (i=0; i<256; i++) { char str[100]; sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i, (i>=0x21 && i != 0x7F) ? i : ' ', cfg.wordness[i]); SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_ADDSTRING, 0, (LPARAM) str); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC4_MBWINDOWS: case IDC4_MBXTERM: cfg.mouse_is_xterm = IsDlgButtonChecked (hwnd, IDC4_MBXTERM); break; case IDC4_CCSET: { BOOL ok; int i; int n = GetDlgItemInt (hwnd, IDC4_CCEDIT, &ok, FALSE); if (!ok) MessageBeep (0); else { for (i=0; i<256; i++) if (SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_GETSEL, i, 0)) { char str[100]; cfg.wordness[i] = n; SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_DELETESTRING, i, 0); sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i, (i>=0x21 && i != 0x7F) ? i : ' ', cfg.wordness[i]); SendDlgItemMessage (hwnd, IDC4_CCLIST, LB_INSERTSTRING, i, (LPARAM)str); } } } break; } break; } return GeneralPanelProc (hwnd, msg, wParam, lParam); } static int CALLBACK ColourProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static const char *const colours[] = { "Default Foreground", "Default Bold Foreground", "Default Background", "Default Bold Background", "Cursor Text", "Cursor Colour", "ANSI Black", "ANSI Black Bold", "ANSI Red", "ANSI Red Bold", "ANSI Green", "ANSI Green Bold", "ANSI Yellow", "ANSI Yellow Bold", "ANSI Blue", "ANSI Blue Bold", "ANSI Magenta", "ANSI Magenta Bold", "ANSI Cyan", "ANSI Cyan Bold", "ANSI White", "ANSI White Bold" }; static const int permanent[] = { TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE }; switch (msg) { case WM_INITDIALOG: CheckDlgButton (hwnd, IDC5_BOLDCOLOUR, cfg.bold_colour); CheckDlgButton (hwnd, IDC5_PALETTE, cfg.try_palette); { int i; for (i=0; i<22; i++) if (cfg.bold_colour || permanent[i]) SendDlgItemMessage (hwnd, IDC5_LIST, LB_ADDSTRING, 0, (LPARAM) colours[i]); } SendDlgItemMessage (hwnd, IDC5_LIST, LB_SETCURSEL, 0, 0); SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[0][0], FALSE); SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[0][1], FALSE); SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[0][2], FALSE); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC5_BOLDCOLOUR: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { int n, i; cfg.bold_colour = IsDlgButtonChecked (hwnd, IDC5_BOLDCOLOUR); n = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCOUNT, 0, 0); if (cfg.bold_colour && n!=22) { for (i=0; i<22; i++) if (!permanent[i]) SendDlgItemMessage (hwnd, IDC5_LIST, LB_INSERTSTRING, i, (LPARAM) colours[i]); } else if (!cfg.bold_colour && n!=12) { for (i=22; i-- ;) if (!permanent[i]) SendDlgItemMessage (hwnd, IDC5_LIST, LB_DELETESTRING, i, 0); } } break; case IDC5_PALETTE: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) cfg.try_palette = IsDlgButtonChecked (hwnd, IDC5_PALETTE); break; case IDC5_LIST: if (HIWORD(wParam) == LBN_DBLCLK || HIWORD(wParam) == LBN_SELCHANGE) { int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL, 0, 0); if (!cfg.bold_colour) i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2); SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE); SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE); SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE); } break; case IDC5_CHANGE: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { static CHOOSECOLOR cc; static DWORD custom[16] = {0}; /* zero initialisers */ int i = SendDlgItemMessage (hwnd, IDC5_LIST, LB_GETCURSEL, 0, 0); if (!cfg.bold_colour) i = (i < 3 ? i*2 : i == 3 ? 5 : i*2-2); cc.lStructSize = sizeof(cc); cc.hwndOwner = hwnd; cc.hInstance = (HWND)hinst; cc.lpCustColors = custom; cc.rgbResult = RGB (cfg.colours[i][0], cfg.colours[i][1], cfg.colours[i][2]); cc.Flags = CC_FULLOPEN | CC_RGBINIT; if (ChooseColor(&cc)) { cfg.colours[i][0] = (unsigned char) (cc.rgbResult & 0xFF); cfg.colours[i][1] = (unsigned char) (cc.rgbResult >> 8) & 0xFF; cfg.colours[i][2] = (unsigned char) (cc.rgbResult >> 16) & 0xFF; SetDlgItemInt (hwnd, IDC5_RVALUE, cfg.colours[i][0], FALSE); SetDlgItemInt (hwnd, IDC5_GVALUE, cfg.colours[i][1], FALSE); SetDlgItemInt (hwnd, IDC5_BVALUE, cfg.colours[i][2], FALSE); } } break; } break; } return GeneralPanelProc (hwnd, msg, wParam, lParam); } static int CALLBACK TranslationProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: CheckRadioButton (hwnd, IDC6_NOXLAT, IDC6_88592WIN1250, cfg.xlat_88592w1250 ? IDC6_88592WIN1250 : cfg.xlat_enablekoiwin ? IDC6_KOI8WIN1251 : IDC6_NOXLAT); CheckDlgButton (hwnd, IDC6_CAPSLOCKCYR, cfg.xlat_capslockcyr); CheckRadioButton (hwnd, IDC2_VTXWINDOWS, IDC2_VTPOORMAN, cfg.vtmode == VT_XWINDOWS ? IDC2_VTXWINDOWS : cfg.vtmode == VT_OEMANSI ? IDC2_VTOEMANSI : cfg.vtmode == VT_OEMONLY ? IDC2_VTOEMONLY : IDC2_VTPOORMAN); case WM_COMMAND: switch (LOWORD(wParam)) { case IDC6_NOXLAT: case IDC6_KOI8WIN1251: case IDC6_88592WIN1250: cfg.xlat_enablekoiwin = IsDlgButtonChecked (hwnd, IDC6_KOI8WIN1251); cfg.xlat_88592w1250 = IsDlgButtonChecked (hwnd, IDC6_88592WIN1250); break; case IDC6_CAPSLOCKCYR: if (HIWORD(wParam) == BN_CLICKED || HIWORD(wParam) == BN_DOUBLECLICKED) { cfg.xlat_capslockcyr = IsDlgButtonChecked (hwnd, IDC6_CAPSLOCKCYR); } break; case IDC2_VTXWINDOWS: case IDC2_VTOEMANSI: case IDC2_VTOEMONLY: case IDC2_VTPOORMAN: cfg.vtmode = (IsDlgButtonChecked (hwnd, IDC2_VTXWINDOWS) ? VT_XWINDOWS : IsDlgButtonChecked (hwnd, IDC2_VTOEMANSI) ? VT_OEMANSI : IsDlgButtonChecked (hwnd, IDC2_VTOEMONLY) ? VT_OEMONLY : VT_POORMAN); break; } } return GeneralPanelProc (hwnd, msg, wParam, lParam); } static DLGPROC panelproc[NPANELS] = { ConnectionProc, KeyboardProc, TerminalProc, WindowProc, TelnetProc, SshProc, SelectionProc, ColourProc, TranslationProc }; static char *panelids[NPANELS] = { MAKEINTRESOURCE(IDD_PANEL0), MAKEINTRESOURCE(IDD_PANEL1), MAKEINTRESOURCE(IDD_PANEL2), MAKEINTRESOURCE(IDD_PANELW), MAKEINTRESOURCE(IDD_PANEL3), MAKEINTRESOURCE(IDD_PANEL35), MAKEINTRESOURCE(IDD_PANEL4), MAKEINTRESOURCE(IDD_PANEL5), MAKEINTRESOURCE(IDD_PANEL6) }; static char *names[NPANELS] = { "Connection", "Keyboard", "Terminal", "Window", "Telnet", "SSH", "Selection", "Colours", "Translation" }; static int mainp[MAIN_NPANELS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8}; static int reconfp[RECONF_NPANELS] = { 1, 2, 3, 6, 7, 8}; static int GenericMainDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, int npanels, int *panelnums, HWND *page) { HWND hw; switch (msg) { case WM_INITDIALOG: { /* centre the window */ RECT rs, rd; hw = GetDesktopWindow(); if (GetWindowRect (hw, &rs) && GetWindowRect (hwnd, &rd)) MoveWindow (hwnd, (rs.right + rs.left + rd.left - rd.right)/2, (rs.bottom + rs.top + rd.top - rd.bottom)/2, rd.right-rd.left, rd.bottom-rd.top, TRUE); } *page = NULL; { /* initialise the tab control */ TC_ITEMHEADER tab; int i; hw = GetDlgItem (hwnd, IDC_TAB); for (i=0; icode == TCN_SELCHANGE) { int i = TabCtrl_GetCurSel(((LPNMHDR)lParam)->hwndFrom); if (*page) DestroyWindow (*page); /* *page = CreateDialogIndirect (hinst, panels[panelnums[i]].temp, hwnd, panelproc[panelnums[i]]);*/ *page = CreateDialog (hinst, panelids[panelnums[i]], hwnd, panelproc[panelnums[i]]); SetWindowLong (*page, GWL_EXSTYLE, GetWindowLong (*page, GWL_EXSTYLE) | WS_EX_CONTROLPARENT); SetFocus (((LPNMHDR)lParam)->hwndFrom); /* ensure focus stays */ return 0; } break; /* case WM_CTLCOLORDLG: */ /* return (int) GetStockObject (LTGRAY_BRUSH); */ case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (*cfg.host) EndDialog (hwnd, 1); else MessageBeep (0); return 0; case IDCANCEL: EndDialog (hwnd, 0); return 0; } return 0; case WM_CLOSE: EndDialog (hwnd, 0); return 0; /* Grrr Explorer will maximize Dialogs! */ case WM_SIZE: if (wParam == SIZE_MAXIMIZED) force_normal(hwnd); return 0; } return 0; } static int CALLBACK MainDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { #if 0 HWND hw; int i; #endif static HWND page = NULL; if (msg == WM_COMMAND && LOWORD(wParam) == IDOK) { #if 0 /* * If the Connection panel is active and the Session List * box is selected, we treat a press of Open to have an * implicit press of Load preceding it. */ hw = GetDlgItem (hwnd, IDC_TAB); i = TabCtrl_GetCurSel(hw); if (panelproc[mainp[i]] == ConnectionProc && page && implicit_load_ok) { SendMessage (page, WM_COMMAND, MAKELONG(IDC0_SESSLOAD, BN_CLICKED), 0); } #endif } if (msg == WM_COMMAND && LOWORD(wParam) == IDC_ABOUT) { EnableWindow(hwnd, 0); DialogBox(hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), GetParent(hwnd), AboutProc); EnableWindow(hwnd, 1); SetActiveWindow(hwnd); } return GenericMainDlgProc (hwnd, msg, wParam, lParam, MAIN_NPANELS, mainp, &page); } static int CALLBACK ReconfDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HWND page; return GenericMainDlgProc (hwnd, msg, wParam, lParam, RECONF_NPANELS, reconfp, &page); } void get_sesslist(int allocate) { static char otherbuf[2048]; static char *buffer; int buflen, bufsize, i; char *p, *ret; void *handle; if (allocate) { if ((handle = enum_settings_start()) == NULL) return; buflen = bufsize = 0; buffer = NULL; do { ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf)); if (ret) { int len = strlen(otherbuf)+1; if (bufsize < buflen+len) { bufsize = buflen + len + 2048; buffer = srealloc(buffer, bufsize); } strcpy(buffer+buflen, otherbuf); buflen += strlen(buffer+buflen)+1; } } while (ret); enum_settings_finish(handle); buffer = srealloc(buffer, buflen+1); buffer[buflen] = '\0'; p = buffer; nsessions = 1; /* "Default Settings" counts as one */ while (*p) { if (strcmp(p, "Default Settings")) nsessions++; while (*p) p++; p++; } sessions = smalloc(nsessions * sizeof(char *)); sessions[0] = "Default Settings"; p = buffer; i = 1; while (*p) { if (strcmp(p, "Default Settings")) sessions[i++] = p; while (*p) p++; p++; } } else { sfree (buffer); sfree (sessions); } } int do_config (void) { int ret; get_sesslist(TRUE); savedsession[0] = '\0'; ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_MAINBOX), NULL, MainDlgProc); get_sesslist(FALSE); return ret; } int do_reconfig (HWND hwnd) { Config backup_cfg; int ret; backup_cfg = cfg; /* structure copy */ ret = DialogBox (hinst, MAKEINTRESOURCE(IDD_RECONF), hwnd, ReconfDlgProc); if (!ret) cfg = backup_cfg; /* structure copy */ else force_normal(hwnd); return ret; } void do_defaults (char *session) { if (session) load_settings (session, TRUE); else load_settings ("Default Settings", FALSE); } void logevent (char *string) { if (nevents >= negsize) { negsize += 64; events = srealloc (events, negsize * sizeof(*events)); } 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 showeventlog (HWND hwnd) { if (!logbox) { logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX), hwnd, LogProc); ShowWindow (logbox, SW_SHOWNORMAL); } } void showabout (HWND hwnd) { if (!abtbox) { abtbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_ABOUTBOX), hwnd, AboutProc); ShowWindow (abtbox, SW_SHOWNORMAL); } } void verify_ssh_host_key(char *host, int port, char *keytype, char *keystr, char *fingerprint) { int ret; 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))]; /* * Verify the key against the registry. */ 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); } }