From c5e9c988d0706d1abb7fab7b2d2b1514bc119584 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 9 Nov 1999 11:10:04 +0000 Subject: [PATCH] Changes from executor: - NetHack keypad mode (Shift only works with NumLock off) - Alt-Space handling (best I could manage; not too bad considering) - Event Log rather than Telnet Negotiation Log git-svn-id: svn://svn.tartarus.org/sgt/putty@284 cda61777-01e9-0310-a592-d414129be87e --- putty.h | 7 +++++-- ssh.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- ssh.h | 2 ++ sshblowf.c | 1 + sshdes.c | 2 ++ telnet.c | 20 +++++++++---------- win_res.h | 9 ++++++--- win_res.rc | 52 +++++++++++++++++++++++++++--------------------- windlg.c | 49 ++++++++++++++++++++++++++++++++++----------- window.c | 45 ++++++++++++++++++++++++++++++----------- 10 files changed, 189 insertions(+), 65 deletions(-) diff --git a/putty.h b/putty.h index 13609159..e5744eab 100644 --- a/putty.h +++ b/putty.h @@ -114,6 +114,9 @@ typedef struct { int linux_funkeys; int app_cursor; int app_keypad; + int nethack_keypad; + int alt_f4; /* is it special? */ + int alt_space; /* is it special? */ /* Terminal options */ int savelines; int dec_om; @@ -186,8 +189,8 @@ void random_save_seed(void); int do_config (void); int do_reconfig (HWND); void do_defaults (char *); -void lognegot (char *); -void shownegot (HWND); +void logevent (char *); +void showeventlog (HWND); void showabout (HWND); void verify_ssh_host_key(char *host, struct RSAKey *key); void get_sesslist(int allocate); diff --git a/ssh.c b/ssh.c index e61654af..93a12807 100644 --- a/ssh.c +++ b/ssh.c @@ -251,9 +251,10 @@ static int ssh_versioncmp(char *a, char *b) { } static int do_ssh_init(void) { - char c; + char c, *vsp; char version[10]; - char vstring[40]; + char vstring[80]; + char vlog[sizeof(vstring)+20]; int i; #ifdef FWHACK @@ -269,11 +270,15 @@ static int do_ssh_init(void) { if (s_read(&c,1) != 1 || c != 'S') return 0; if (s_read(&c,1) != 1 || c != 'H') return 0; #endif + strcpy(vstring, "SSH-"); + vsp = vstring+4; if (s_read(&c,1) != 1 || c != '-') return 0; i = 0; while (1) { if (s_read(&c,1) != 1) return 0; + if (vsp < vstring+sizeof(vstring)-1) + *vsp++ = c; if (i >= 0) { if (c == '-') { version[i] = '\0'; @@ -285,8 +290,16 @@ static int do_ssh_init(void) { break; } + *vsp = 0; + sprintf(vlog, "Server version: %s", vstring); + vlog[strcspn(vlog, "\r\n")] = '\0'; + logevent(vlog); + sprintf(vstring, "SSH-%s-PuTTY\n", (ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5")); + sprintf(vlog, "We claim version: %s", vstring); + vlog[strcspn(vlog, "\r\n")] = '\0'; + logevent(vlog); s_write(vstring, strlen(vstring)); return 1; } @@ -315,14 +328,33 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { if (pktin.type != SSH_SMSG_PUBLIC_KEY) fatalbox("Public key packet not received"); - memcpy(cookie, pktin.body, 8); + logevent("Received public keys"); - MD5Init(&md5c); + memcpy(cookie, pktin.body, 8); i = makekey(pktin.body+8, &servkey, &keystr1); j = makekey(pktin.body+8+i, &hostkey, &keystr2); + /* + * Hash the host key and print the hash in the log box. Just as + * a last resort in case the registry's host key checking is + * compromised, we'll allow the user some ability to verify + * host keys by eye. + */ + MD5Init(&md5c); + MD5Update(&md5c, keystr2, hostkey.bytes); + MD5Final(session_id, &md5c); + { + char logmsg[80]; + int i; + logevent("Host key MD5 is:"); + strcpy(logmsg, " "); + for (i = 0; i < 16; i++) + sprintf(logmsg+strlen(logmsg), "%02x", session_id[i]); + logevent(logmsg); + } + supported_ciphers_mask = ((pktin.body[12+i+j] << 24) | (pktin.body[13+i+j] << 16) | (pktin.body[14+i+j] << 8) | @@ -333,6 +365,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { (pktin.body[18+i+j] << 8) | (pktin.body[19+i+j])); + MD5Init(&md5c); + MD5Update(&md5c, keystr2, hostkey.bytes); MD5Update(&md5c, keystr1, servkey.bytes); MD5Update(&md5c, pktin.body, 8); @@ -364,6 +398,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { rsaencrypt(rsabuf, hostkey.bytes, &servkey); } + logevent("Encrypted session key"); + cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH : cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES : SSH_CIPHER_3DES; @@ -371,6 +407,11 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { c_write("Selected cipher not supported, falling back to 3DES\r\n", 53); cipher_type = SSH_CIPHER_3DES; } + switch (cipher_type) { + case SSH_CIPHER_3DES: logevent("Using 3DES encryption"); break; + case SSH_CIPHER_DES: logevent("Using single-DES encryption"); break; + case SSH_CIPHER_BLOWFISH: logevent("Using Blowfish encryption"); break; + } s_wrpkt_start(SSH_CMSG_SESSION_KEY, len+15); pktout.body[0] = cipher_type; @@ -381,6 +422,7 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { pktout.body[len+11] = pktout.body[len+12] = 0; /* protocol flags */ pktout.body[len+13] = pktout.body[len+14] = 0; s_wrpkt(); + logevent("Trying to enable encryption..."); free(rsabuf); @@ -394,6 +436,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { if (pktin.type != SSH_SMSG_SUCCESS) fatalbox("Encryption not successfully enabled"); + logevent("Successfully started encryption"); + fflush(stdout); { static char username[100]; @@ -442,6 +486,11 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { c_write(stuff, strlen(stuff)); } s_wrpkt_start(SSH_CMSG_USER, 4+strlen(username)); + { + char userlog[20+sizeof(username)]; + sprintf(userlog, "Sent username \"%s\"", username); + logevent(userlog); + } pktout.body[0] = pktout.body[1] = pktout.body[2] = 0; pktout.body[3] = strlen(username); memcpy(pktout.body+4, username, strlen(username)); @@ -465,16 +514,19 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { cfg.try_tis_auth && (supported_auths_mask & (1<"), telopt(option)); - lognegot(buf); + logevent(buf); } static void send_opt (int cmd, int option) { @@ -285,11 +285,11 @@ static void process_subneg (void) { n = 4 + strlen(cfg.termspeed); b[n] = IAC; b[n+1] = SE; s_write (b, n+2); - lognegot("server:\tSB TSPEED SEND"); + logevent("server:\tSB TSPEED SEND"); sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed); - lognegot (logbuf); + logevent (logbuf); } else - lognegot ("server:\tSB TSPEED "); + logevent ("server:\tSB TSPEED "); break; case TELOPT_TTYPE: if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) { @@ -302,11 +302,11 @@ static void process_subneg (void) { b[n+4] = IAC; b[n+5] = SE; s_write (b, n+6); b[n+4] = 0; - lognegot("server:\tSB TTYPE SEND"); + logevent("server:\tSB TTYPE SEND"); sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4); - lognegot(logbuf); + logevent(logbuf); } else - lognegot("server:\tSB TTYPE \r\n"); + logevent("server:\tSB TTYPE \r\n"); break; case TELOPT_OLD_ENVIRON: case TELOPT_NEW_ENVIRON: @@ -316,7 +316,7 @@ static void process_subneg (void) { char logbuf[50]; p++; sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt)); - lognegot (logbuf); + logevent (logbuf); if (sb_opt == TELOPT_OLD_ENVIRON) { if (cfg.rfc_environ) { value = RFC_VALUE; @@ -368,7 +368,7 @@ static void process_subneg (void) { s_write (b, n); sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt), n==6 ? "" : ""); - lognegot (logbuf); + logevent (logbuf); } break; } @@ -681,7 +681,7 @@ static void telnet_size(void) { sprintf(logbuf, "client:\tSB NAWS %d,%d", ((unsigned char)b[3] << 8) + (unsigned char)b[4], ((unsigned char)b[5] << 8) + (unsigned char)b[6]); - lognegot (logbuf); + logevent (logbuf); } /* diff --git a/win_res.h b/win_res.h index 3e8cb30e..aec42f63 100644 --- a/win_res.h +++ b/win_res.h @@ -57,9 +57,12 @@ #define IDC1_KPSTATIC 1010 #define IDC1_KPNORMAL 1011 #define IDC1_KPAPPLIC 1012 -#define IDC1_CURSTATIC 1013 -#define IDC1_CURNORMAL 1014 -#define IDC1_CURAPPLIC 1015 +#define IDC1_KPNH 1013 +#define IDC1_CURSTATIC 1014 +#define IDC1_CURNORMAL 1015 +#define IDC1_CURAPPLIC 1016 +#define IDC1_ALTF4 1017 +#define IDC1_ALTSPACE 1018 #define IDC2_WRAPMODE 1001 #define IDC2_DECOM 1002 diff --git a/win_res.rc b/win_res.rc index d71f0e37..37b5eca0 100644 --- a/win_res.rc +++ b/win_res.rc @@ -77,28 +77,34 @@ STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER FONT 8, "MS Sans Serif" BEGIN LTEXT "Action of Backspace:", IDC1_DELSTATIC, 3, 3, 162, 8 - AUTORADIOBUTTON "Control-&H (ASCII 8)", IDC1_DEL008, 3, 12, 162, 10, WS_GROUP - AUTORADIOBUTTON "Control-&? (ASCII 127)", IDC1_DEL127, 3, 22, 162, 10 - LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 35, 162, 8 - AUTORADIOBUTTON "&Standard (ESC [ 1 ~ and ESC [ 4 ~)", - IDC1_HOMETILDE, 3, 44, 162, 10, WS_GROUP - AUTORADIOBUTTON "&rxvt (ESC [ H and ESC O w)", - IDC1_HOMERXVT, 3, 54, 162, 10 - LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 67, 162, 8 - AUTORADIOBUTTON "S&tandard (ESC [ 11 ~ through ESC [ 15 ~)", - IDC1_FUNCTILDE, 3, 76, 162, 10, WS_GROUP - AUTORADIOBUTTON "&Linux (ESC [ [ A through ESC [ [ E)", - IDC1_FUNCLINUX, 3, 86, 162, 10 - LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 99, 162, 8 - AUTORADIOBUTTON "&Normal (depends on NumLock)", - IDC1_KPNORMAL, 3, 108, 162, 10, WS_GROUP - AUTORADIOBUTTON "A&pplication (ESC O P etc)", - IDC1_KPAPPLIC, 3, 118, 162, 10 - LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 131, 162, 8 - AUTORADIOBUTTON "Nor&mal (ESC [ A through ESC [ D)", - IDC1_CURNORMAL, 3, 140, 162, 10, WS_GROUP - AUTORADIOBUTTON "Appl&ication (ESC O A through ESC O D)", - IDC1_CURAPPLIC, 3, 150, 162, 10 + AUTORADIOBUTTON "Control-&H", IDC1_DEL008, 3, 12, 50, 10, WS_GROUP + AUTORADIOBUTTON "Control-&? (127)", IDC1_DEL127, 62, 12, 100, 10 + LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 25, 162, 8 + AUTORADIOBUTTON "&Standard", + IDC1_HOMETILDE, 3, 34, 50, 10, WS_GROUP + AUTORADIOBUTTON "&rxvt", + IDC1_HOMERXVT, 62, 34, 50, 10 + LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 47, 162, 8 + AUTORADIOBUTTON "S&tandard", + IDC1_FUNCTILDE, 3, 56, 50, 10, WS_GROUP + AUTORADIOBUTTON "&Linux console", + IDC1_FUNCLINUX, 62, 56, 100, 10 + LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 69, 162, 8 + AUTORADIOBUTTON "&Normal", + IDC1_CURNORMAL, 3, 78, 50, 10, WS_GROUP + AUTORADIOBUTTON "A&pplication", + IDC1_CURAPPLIC, 62, 78, 50, 10 + LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 91, 162, 8 + AUTORADIOBUTTON "Nor&mal", + IDC1_KPNORMAL, 3, 100, 50, 10, WS_GROUP + AUTORADIOBUTTON "Appl&ication", + IDC1_KPAPPLIC, 62, 100, 50, 10 + AUTORADIOBUTTON "N&etHack", + IDC1_KPNH, 121, 100, 50, 10 + AUTOCHECKBOX "ALT-F&4 is special (closes window)", + IDC1_ALTF4, 3, 113, 162, 10 + AUTOCHECKBOX "ALT-Space is special (S&ystem menu)", + IDC1_ALTSPACE, 3, 123, 162, 10 END IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163 @@ -217,7 +223,7 @@ END IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "PuTTY Negotiation Log" +CAPTION "PuTTY Event Log" FONT 8, "MS Sans Serif" BEGIN DEFPUSHBUTTON "&Close", IDOK, 58, 102, 44, 14 diff --git a/windlg.c b/windlg.c index 1d0604e5..69f91fb9 100644 --- a/windlg.c +++ b/windlg.c @@ -15,8 +15,9 @@ static const char *const puttystr = PUTTY_REG_POS "\\Sessions"; -static char **negots = NULL; -static int nnegots = 0, negsize = 0; +static char **events = NULL; +static int nevents = 0, negsize = 0; + static HWND logbox = NULL, abtbox = NULL; static char hex[16] = "0123456789ABCDEF"; @@ -153,6 +154,9 @@ static void save_settings (char *section, int do_host) { wppi (sesskey, "LinuxFunctionKeys", cfg.linux_funkeys); wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor); wppi (sesskey, "ApplicationKeypad", cfg.app_keypad); + wppi (sesskey, "NetHackKeypad", cfg.nethack_keypad); + wppi (sesskey, "AltF4", cfg.alt_f4); + wppi (sesskey, "AltSpace", cfg.alt_space); wppi (sesskey, "ScrollbackLines", cfg.savelines); wppi (sesskey, "DECOriginMode", cfg.dec_om); wppi (sesskey, "AutoWrapMode", cfg.wrap_mode); @@ -283,6 +287,9 @@ static void load_settings (char *section, int do_host) { gppi (sesskey, "LinuxFunctionKeys", 0, &cfg.linux_funkeys); 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, "ScrollbackLines", 200, &cfg.savelines); gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om); gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode); @@ -355,9 +362,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++; + events[nevents] = smalloc(1+strlen(string)); + strcpy (events[nevents], string); + nevents++; if (logbox) SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING, 0, (LPARAM)string); } -void shownegot (HWND hwnd) { +void showeventlog (HWND hwnd) { if (!logbox) { logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX), hwnd, LogProc); diff --git a/window.c b/window.c index 2581623f..6afd10e8 100644 --- a/window.c +++ b/window.c @@ -341,9 +341,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { AppendMenu (p, MF_ENABLED, IDM_TEL_EOR, "End Of Record"); AppendMenu (p, MF_ENABLED, IDM_TEL_EOF, "End Of File"); AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) p, "Telnet Command"); - AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "Show Negotiation"); AppendMenu (m, MF_SEPARATOR, 0, 0); } + AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "Event Log"); + AppendMenu (m, MF_SEPARATOR, 0, 0); AppendMenu (m, MF_ENABLED, IDM_NEWSESS, "New Session"); AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "Duplicate Session"); s = CreateMenu(); @@ -628,7 +629,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message, case WM_SYSCOMMAND: switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */ case IDM_SHOWLOG: - shownegot(hwnd); + showeventlog(hwnd); break; case IDM_NEWSESS: case IDM_DUPSESS: @@ -1013,6 +1014,8 @@ static int WINAPI WndProc (HWND hwnd, UINT message, int len; len = TranslateKey (wParam, lParam, buf); + if (len == -1) + return DefWindowProc (hwnd, message, wParam, lParam); back->send (buf, len); } return 0; @@ -1253,9 +1256,12 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) { SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); return 0; } - if ((lParam & 0x20000000) && wParam == VK_F4) { - SendMessage (hwnd, WM_CLOSE, 0, 0); - return 0; + if ((lParam & 0x20000000) && wParam == VK_F4 && cfg.alt_f4) { + return -1; + } + if ((lParam & 0x20000000) && wParam == VK_SPACE && cfg.alt_space) { + SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); + return -1; } /* @@ -1281,12 +1287,29 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) { return p - output; } - /* - * If we're in applications keypad mode, we have to process it - * before char-map translation, because it will pre-empt lots - * of stuff, even if NumLock is off. - */ - if (app_keypad_keys) { + if (cfg.nethack_keypad) { + int shift = keystate[VK_SHIFT] & 0x80; + /* + * NB the shifted versions only work with numlock off. + */ + switch ( (lParam >> 16) & 0x1FF ) { + case 0x047: *p++ = shift ? 'Y' : 'y'; return p - output; + case 0x048: *p++ = shift ? 'K' : 'k'; return p - output; + case 0x049: *p++ = shift ? 'U' : 'u'; return p - output; + case 0x04B: *p++ = shift ? 'H' : 'h'; return p - output; + case 0x04C: *p++ = '.'; return p - output; + case 0x04D: *p++ = shift ? 'L' : 'l'; return p - output; + case 0x04F: *p++ = shift ? 'B' : 'b'; return p - output; + case 0x050: *p++ = shift ? 'J' : 'j'; return p - output; + case 0x051: *p++ = shift ? 'N' : 'n'; return p - output; + case 0x053: *p++ = '.'; return p - output; + } + } else if (app_keypad_keys) { + /* + * If we're in applications keypad mode, we have to process it + * before char-map translation, because it will pre-empt lots + * of stuff, even if NumLock is off. + */ if (ret) { /* * Hack to ensure NumLock doesn't interfere with -- 2.11.0