mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
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 [originally from svn r284]
This commit is contained in:
parent
59e798fc6d
commit
f6c63320ea
7
putty.h
7
putty.h
@ -114,6 +114,9 @@ typedef struct {
|
|||||||
int linux_funkeys;
|
int linux_funkeys;
|
||||||
int app_cursor;
|
int app_cursor;
|
||||||
int app_keypad;
|
int app_keypad;
|
||||||
|
int nethack_keypad;
|
||||||
|
int alt_f4; /* is it special? */
|
||||||
|
int alt_space; /* is it special? */
|
||||||
/* Terminal options */
|
/* Terminal options */
|
||||||
int savelines;
|
int savelines;
|
||||||
int dec_om;
|
int dec_om;
|
||||||
@ -186,8 +189,8 @@ void random_save_seed(void);
|
|||||||
int do_config (void);
|
int do_config (void);
|
||||||
int do_reconfig (HWND);
|
int do_reconfig (HWND);
|
||||||
void do_defaults (char *);
|
void do_defaults (char *);
|
||||||
void lognegot (char *);
|
void logevent (char *);
|
||||||
void shownegot (HWND);
|
void showeventlog (HWND);
|
||||||
void showabout (HWND);
|
void showabout (HWND);
|
||||||
void verify_ssh_host_key(char *host, struct RSAKey *key);
|
void verify_ssh_host_key(char *host, struct RSAKey *key);
|
||||||
void get_sesslist(int allocate);
|
void get_sesslist(int allocate);
|
||||||
|
67
ssh.c
67
ssh.c
@ -251,9 +251,10 @@ static int ssh_versioncmp(char *a, char *b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int do_ssh_init(void) {
|
static int do_ssh_init(void) {
|
||||||
char c;
|
char c, *vsp;
|
||||||
char version[10];
|
char version[10];
|
||||||
char vstring[40];
|
char vstring[80];
|
||||||
|
char vlog[sizeof(vstring)+20];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef FWHACK
|
#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 != 'S') return 0;
|
||||||
if (s_read(&c,1) != 1 || c != 'H') return 0;
|
if (s_read(&c,1) != 1 || c != 'H') return 0;
|
||||||
#endif
|
#endif
|
||||||
|
strcpy(vstring, "SSH-");
|
||||||
|
vsp = vstring+4;
|
||||||
if (s_read(&c,1) != 1 || c != '-') return 0;
|
if (s_read(&c,1) != 1 || c != '-') return 0;
|
||||||
i = 0;
|
i = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (s_read(&c,1) != 1)
|
if (s_read(&c,1) != 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (vsp < vstring+sizeof(vstring)-1)
|
||||||
|
*vsp++ = c;
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
if (c == '-') {
|
if (c == '-') {
|
||||||
version[i] = '\0';
|
version[i] = '\0';
|
||||||
@ -285,8 +290,16 @@ static int do_ssh_init(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*vsp = 0;
|
||||||
|
sprintf(vlog, "Server version: %s", vstring);
|
||||||
|
vlog[strcspn(vlog, "\r\n")] = '\0';
|
||||||
|
logevent(vlog);
|
||||||
|
|
||||||
sprintf(vstring, "SSH-%s-PuTTY\n",
|
sprintf(vstring, "SSH-%s-PuTTY\n",
|
||||||
(ssh_versioncmp(version, "1.5") <= 0 ? version : "1.5"));
|
(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));
|
s_write(vstring, strlen(vstring));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -315,14 +328,33 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
if (pktin.type != SSH_SMSG_PUBLIC_KEY)
|
if (pktin.type != SSH_SMSG_PUBLIC_KEY)
|
||||||
fatalbox("Public key packet not received");
|
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);
|
i = makekey(pktin.body+8, &servkey, &keystr1);
|
||||||
|
|
||||||
j = makekey(pktin.body+8+i, &hostkey, &keystr2);
|
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) |
|
supported_ciphers_mask = ((pktin.body[12+i+j] << 24) |
|
||||||
(pktin.body[13+i+j] << 16) |
|
(pktin.body[13+i+j] << 16) |
|
||||||
(pktin.body[14+i+j] << 8) |
|
(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[18+i+j] << 8) |
|
||||||
(pktin.body[19+i+j]));
|
(pktin.body[19+i+j]));
|
||||||
|
|
||||||
|
MD5Init(&md5c);
|
||||||
|
|
||||||
MD5Update(&md5c, keystr2, hostkey.bytes);
|
MD5Update(&md5c, keystr2, hostkey.bytes);
|
||||||
MD5Update(&md5c, keystr1, servkey.bytes);
|
MD5Update(&md5c, keystr1, servkey.bytes);
|
||||||
MD5Update(&md5c, pktin.body, 8);
|
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);
|
rsaencrypt(rsabuf, hostkey.bytes, &servkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logevent("Encrypted session key");
|
||||||
|
|
||||||
cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :
|
cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :
|
||||||
cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES :
|
cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES :
|
||||||
SSH_CIPHER_3DES;
|
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);
|
c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);
|
||||||
cipher_type = SSH_CIPHER_3DES;
|
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);
|
s_wrpkt_start(SSH_CMSG_SESSION_KEY, len+15);
|
||||||
pktout.body[0] = cipher_type;
|
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+11] = pktout.body[len+12] = 0; /* protocol flags */
|
||||||
pktout.body[len+13] = pktout.body[len+14] = 0;
|
pktout.body[len+13] = pktout.body[len+14] = 0;
|
||||||
s_wrpkt();
|
s_wrpkt();
|
||||||
|
logevent("Trying to enable encryption...");
|
||||||
|
|
||||||
free(rsabuf);
|
free(rsabuf);
|
||||||
|
|
||||||
@ -394,6 +436,8 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
if (pktin.type != SSH_SMSG_SUCCESS)
|
if (pktin.type != SSH_SMSG_SUCCESS)
|
||||||
fatalbox("Encryption not successfully enabled");
|
fatalbox("Encryption not successfully enabled");
|
||||||
|
|
||||||
|
logevent("Successfully started encryption");
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
{
|
{
|
||||||
static char username[100];
|
static char username[100];
|
||||||
@ -442,6 +486,11 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
c_write(stuff, strlen(stuff));
|
c_write(stuff, strlen(stuff));
|
||||||
}
|
}
|
||||||
s_wrpkt_start(SSH_CMSG_USER, 4+strlen(username));
|
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[0] = pktout.body[1] = pktout.body[2] = 0;
|
||||||
pktout.body[3] = strlen(username);
|
pktout.body[3] = strlen(username);
|
||||||
memcpy(pktout.body+4, username, 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 &&
|
cfg.try_tis_auth &&
|
||||||
(supported_auths_mask & (1<<SSH_AUTH_TIS))) {
|
(supported_auths_mask & (1<<SSH_AUTH_TIS))) {
|
||||||
pwpkt_type = SSH_CMSG_AUTH_TIS_RESPONSE;
|
pwpkt_type = SSH_CMSG_AUTH_TIS_RESPONSE;
|
||||||
|
logevent("Requested TIS authentication");
|
||||||
s_wrpkt_start(SSH_CMSG_AUTH_TIS, 0);
|
s_wrpkt_start(SSH_CMSG_AUTH_TIS, 0);
|
||||||
s_wrpkt();
|
s_wrpkt();
|
||||||
do { crReturnV; } while (!ispkt);
|
do { crReturnV; } while (!ispkt);
|
||||||
if (pktin.type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
if (pktin.type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
||||||
|
logevent("TIS authentication declined");
|
||||||
c_write("TIS authentication refused.\r\n", 29);
|
c_write("TIS authentication refused.\r\n", 29);
|
||||||
} else {
|
} else {
|
||||||
int challengelen = ((pktin.body[0] << 24) |
|
int challengelen = ((pktin.body[0] << 24) |
|
||||||
(pktin.body[1] << 16) |
|
(pktin.body[1] << 16) |
|
||||||
(pktin.body[2] << 8) |
|
(pktin.body[2] << 8) |
|
||||||
(pktin.body[3]));
|
(pktin.body[3]));
|
||||||
|
logevent("Received TIS challenge");
|
||||||
c_write(pktin.body+4, challengelen);
|
c_write(pktin.body+4, challengelen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,15 +564,19 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
pktout.body[3] = strlen(password);
|
pktout.body[3] = strlen(password);
|
||||||
memcpy(pktout.body+4, password, strlen(password));
|
memcpy(pktout.body+4, password, strlen(password));
|
||||||
s_wrpkt();
|
s_wrpkt();
|
||||||
|
logevent("Sent password");
|
||||||
memset(password, 0, strlen(password));
|
memset(password, 0, strlen(password));
|
||||||
do { crReturnV; } while (!ispkt);
|
do { crReturnV; } while (!ispkt);
|
||||||
if (pktin.type == 15) {
|
if (pktin.type == 15) {
|
||||||
c_write("Access denied\r\n", 15);
|
c_write("Access denied\r\n", 15);
|
||||||
|
logevent("Authentication refused");
|
||||||
} else if (pktin.type != 14) {
|
} else if (pktin.type != 14) {
|
||||||
fatalbox("Strange packet received, type %d", pktin.type);
|
fatalbox("Strange packet received, type %d", pktin.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logevent("Authentication successful");
|
||||||
|
|
||||||
if (!cfg.nopty) {
|
if (!cfg.nopty) {
|
||||||
i = strlen(cfg.termtype);
|
i = strlen(cfg.termtype);
|
||||||
s_wrpkt_start(SSH_CMSG_REQUEST_PTY, i+5*4+1);
|
s_wrpkt_start(SSH_CMSG_REQUEST_PTY, i+5*4+1);
|
||||||
@ -547,10 +603,12 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
} else if (pktin.type == SSH_SMSG_FAILURE) {
|
} else if (pktin.type == SSH_SMSG_FAILURE) {
|
||||||
c_write("Server refused to allocate pty\r\n", 32);
|
c_write("Server refused to allocate pty\r\n", 32);
|
||||||
}
|
}
|
||||||
|
logevent("Allocated pty");
|
||||||
}
|
}
|
||||||
|
|
||||||
s_wrpkt_start(SSH_CMSG_EXEC_SHELL, 0);
|
s_wrpkt_start(SSH_CMSG_EXEC_SHELL, 0);
|
||||||
s_wrpkt();
|
s_wrpkt();
|
||||||
|
logevent("Started session");
|
||||||
|
|
||||||
ssh_state = SSH_STATE_SESSION;
|
ssh_state = SSH_STATE_SESSION;
|
||||||
if (size_needed)
|
if (size_needed)
|
||||||
@ -567,6 +625,7 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||||||
c_write(pktin.body+4, len);
|
c_write(pktin.body+4, len);
|
||||||
} else if (pktin.type == SSH_MSG_DISCONNECT) {
|
} else if (pktin.type == SSH_MSG_DISCONNECT) {
|
||||||
ssh_state = SSH_STATE_CLOSED;
|
ssh_state = SSH_STATE_CLOSED;
|
||||||
|
logevent("Received disconnect request");
|
||||||
} else if (pktin.type == SSH_SMSG_SUCCESS) {
|
} else if (pktin.type == SSH_SMSG_SUCCESS) {
|
||||||
/* may be from EXEC_SHELL on some servers */
|
/* may be from EXEC_SHELL on some servers */
|
||||||
} else if (pktin.type == SSH_SMSG_FAILURE) {
|
} else if (pktin.type == SSH_SMSG_FAILURE) {
|
||||||
|
2
ssh.h
2
ssh.h
@ -44,3 +44,5 @@ void SHATransform(word32 *digest, word32 *data);
|
|||||||
|
|
||||||
int random_byte(void);
|
int random_byte(void);
|
||||||
void random_add_noise(void *noise, int length);
|
void random_add_noise(void *noise, int length);
|
||||||
|
|
||||||
|
void logevent (char *);
|
||||||
|
@ -396,6 +396,7 @@ static void blowfish_sesskey(unsigned char *key)
|
|||||||
ectx.iv0 = 0;
|
ectx.iv0 = 0;
|
||||||
ectx.iv1 = 0;
|
ectx.iv1 = 0;
|
||||||
dctx = ectx;
|
dctx = ectx;
|
||||||
|
logevent("Initialised Blowfish encryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blowfish_encrypt_blk(unsigned char *blk, int len)
|
static void blowfish_encrypt_blk(unsigned char *blk, int len)
|
||||||
|
2
sshdes.c
2
sshdes.c
@ -657,6 +657,7 @@ static void des3_sesskey(unsigned char *key) {
|
|||||||
memset(div1, 0, sizeof(div1));
|
memset(div1, 0, sizeof(div1));
|
||||||
memset(div2, 0, sizeof(div2));
|
memset(div2, 0, sizeof(div2));
|
||||||
memset(div3, 0, sizeof(div3));
|
memset(div3, 0, sizeof(div3));
|
||||||
|
logevent("Initialised triple-DES encryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void des3_encrypt_blk(unsigned char *blk, int len) {
|
static void des3_encrypt_blk(unsigned char *blk, int len) {
|
||||||
@ -678,6 +679,7 @@ static void des_sesskey(unsigned char *key) {
|
|||||||
memset(eiv1, 0, sizeof(eiv1));
|
memset(eiv1, 0, sizeof(eiv1));
|
||||||
des_set_key(key, &dkey1);
|
des_set_key(key, &dkey1);
|
||||||
memset(div1, 0, sizeof(div1));
|
memset(div1, 0, sizeof(div1));
|
||||||
|
logevent("Initialised single-DES encryption");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void des_encrypt_blk(unsigned char *blk, int len) {
|
static void des_encrypt_blk(unsigned char *blk, int len) {
|
||||||
|
20
telnet.c
20
telnet.c
@ -184,7 +184,7 @@ static void log_option (char *sender, int cmd, int option) {
|
|||||||
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
|
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
|
||||||
cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
|
cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
|
||||||
telopt(option));
|
telopt(option));
|
||||||
lognegot(buf);
|
logevent(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_opt (int cmd, int option) {
|
static void send_opt (int cmd, int option) {
|
||||||
@ -285,11 +285,11 @@ static void process_subneg (void) {
|
|||||||
n = 4 + strlen(cfg.termspeed);
|
n = 4 + strlen(cfg.termspeed);
|
||||||
b[n] = IAC; b[n+1] = SE;
|
b[n] = IAC; b[n+1] = SE;
|
||||||
s_write (b, n+2);
|
s_write (b, n+2);
|
||||||
lognegot("server:\tSB TSPEED SEND");
|
logevent("server:\tSB TSPEED SEND");
|
||||||
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
|
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
|
||||||
lognegot (logbuf);
|
logevent (logbuf);
|
||||||
} else
|
} else
|
||||||
lognegot ("server:\tSB TSPEED <something weird>");
|
logevent ("server:\tSB TSPEED <something weird>");
|
||||||
break;
|
break;
|
||||||
case TELOPT_TTYPE:
|
case TELOPT_TTYPE:
|
||||||
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
|
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;
|
b[n+4] = IAC; b[n+5] = SE;
|
||||||
s_write (b, n+6);
|
s_write (b, n+6);
|
||||||
b[n+4] = 0;
|
b[n+4] = 0;
|
||||||
lognegot("server:\tSB TTYPE SEND");
|
logevent("server:\tSB TTYPE SEND");
|
||||||
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
|
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
|
||||||
lognegot(logbuf);
|
logevent(logbuf);
|
||||||
} else
|
} else
|
||||||
lognegot("server:\tSB TTYPE <something weird>\r\n");
|
logevent("server:\tSB TTYPE <something weird>\r\n");
|
||||||
break;
|
break;
|
||||||
case TELOPT_OLD_ENVIRON:
|
case TELOPT_OLD_ENVIRON:
|
||||||
case TELOPT_NEW_ENVIRON:
|
case TELOPT_NEW_ENVIRON:
|
||||||
@ -316,7 +316,7 @@ static void process_subneg (void) {
|
|||||||
char logbuf[50];
|
char logbuf[50];
|
||||||
p++;
|
p++;
|
||||||
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
|
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
|
||||||
lognegot (logbuf);
|
logevent (logbuf);
|
||||||
if (sb_opt == TELOPT_OLD_ENVIRON) {
|
if (sb_opt == TELOPT_OLD_ENVIRON) {
|
||||||
if (cfg.rfc_environ) {
|
if (cfg.rfc_environ) {
|
||||||
value = RFC_VALUE;
|
value = RFC_VALUE;
|
||||||
@ -368,7 +368,7 @@ static void process_subneg (void) {
|
|||||||
s_write (b, n);
|
s_write (b, n);
|
||||||
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
|
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
|
||||||
n==6 ? "<nothing>" : "<stuff>");
|
n==6 ? "<nothing>" : "<stuff>");
|
||||||
lognegot (logbuf);
|
logevent (logbuf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -681,7 +681,7 @@ static void telnet_size(void) {
|
|||||||
sprintf(logbuf, "client:\tSB NAWS %d,%d",
|
sprintf(logbuf, "client:\tSB NAWS %d,%d",
|
||||||
((unsigned char)b[3] << 8) + (unsigned char)b[4],
|
((unsigned char)b[3] << 8) + (unsigned char)b[4],
|
||||||
((unsigned char)b[5] << 8) + (unsigned char)b[6]);
|
((unsigned char)b[5] << 8) + (unsigned char)b[6]);
|
||||||
lognegot (logbuf);
|
logevent (logbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,9 +57,12 @@
|
|||||||
#define IDC1_KPSTATIC 1010
|
#define IDC1_KPSTATIC 1010
|
||||||
#define IDC1_KPNORMAL 1011
|
#define IDC1_KPNORMAL 1011
|
||||||
#define IDC1_KPAPPLIC 1012
|
#define IDC1_KPAPPLIC 1012
|
||||||
#define IDC1_CURSTATIC 1013
|
#define IDC1_KPNH 1013
|
||||||
#define IDC1_CURNORMAL 1014
|
#define IDC1_CURSTATIC 1014
|
||||||
#define IDC1_CURAPPLIC 1015
|
#define IDC1_CURNORMAL 1015
|
||||||
|
#define IDC1_CURAPPLIC 1016
|
||||||
|
#define IDC1_ALTF4 1017
|
||||||
|
#define IDC1_ALTSPACE 1018
|
||||||
|
|
||||||
#define IDC2_WRAPMODE 1001
|
#define IDC2_WRAPMODE 1001
|
||||||
#define IDC2_DECOM 1002
|
#define IDC2_DECOM 1002
|
||||||
|
52
win_res.rc
52
win_res.rc
@ -77,28 +77,34 @@ STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
|
|||||||
FONT 8, "MS Sans Serif"
|
FONT 8, "MS Sans Serif"
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Action of Backspace:", IDC1_DELSTATIC, 3, 3, 162, 8
|
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-&H", IDC1_DEL008, 3, 12, 50, 10, WS_GROUP
|
||||||
AUTORADIOBUTTON "Control-&? (ASCII 127)", IDC1_DEL127, 3, 22, 162, 10
|
AUTORADIOBUTTON "Control-&? (127)", IDC1_DEL127, 62, 12, 100, 10
|
||||||
LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 35, 162, 8
|
LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 25, 162, 8
|
||||||
AUTORADIOBUTTON "&Standard (ESC [ 1 ~ and ESC [ 4 ~)",
|
AUTORADIOBUTTON "&Standard",
|
||||||
IDC1_HOMETILDE, 3, 44, 162, 10, WS_GROUP
|
IDC1_HOMETILDE, 3, 34, 50, 10, WS_GROUP
|
||||||
AUTORADIOBUTTON "&rxvt (ESC [ H and ESC O w)",
|
AUTORADIOBUTTON "&rxvt",
|
||||||
IDC1_HOMERXVT, 3, 54, 162, 10
|
IDC1_HOMERXVT, 62, 34, 50, 10
|
||||||
LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 67, 162, 8
|
LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 47, 162, 8
|
||||||
AUTORADIOBUTTON "S&tandard (ESC [ 11 ~ through ESC [ 15 ~)",
|
AUTORADIOBUTTON "S&tandard",
|
||||||
IDC1_FUNCTILDE, 3, 76, 162, 10, WS_GROUP
|
IDC1_FUNCTILDE, 3, 56, 50, 10, WS_GROUP
|
||||||
AUTORADIOBUTTON "&Linux (ESC [ [ A through ESC [ [ E)",
|
AUTORADIOBUTTON "&Linux console",
|
||||||
IDC1_FUNCLINUX, 3, 86, 162, 10
|
IDC1_FUNCLINUX, 62, 56, 100, 10
|
||||||
LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 99, 162, 8
|
LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 69, 162, 8
|
||||||
AUTORADIOBUTTON "&Normal (depends on NumLock)",
|
AUTORADIOBUTTON "&Normal",
|
||||||
IDC1_KPNORMAL, 3, 108, 162, 10, WS_GROUP
|
IDC1_CURNORMAL, 3, 78, 50, 10, WS_GROUP
|
||||||
AUTORADIOBUTTON "A&pplication (ESC O P etc)",
|
AUTORADIOBUTTON "A&pplication",
|
||||||
IDC1_KPAPPLIC, 3, 118, 162, 10
|
IDC1_CURAPPLIC, 62, 78, 50, 10
|
||||||
LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 131, 162, 8
|
LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 91, 162, 8
|
||||||
AUTORADIOBUTTON "Nor&mal (ESC [ A through ESC [ D)",
|
AUTORADIOBUTTON "Nor&mal",
|
||||||
IDC1_CURNORMAL, 3, 140, 162, 10, WS_GROUP
|
IDC1_KPNORMAL, 3, 100, 50, 10, WS_GROUP
|
||||||
AUTORADIOBUTTON "Appl&ication (ESC O A through ESC O D)",
|
AUTORADIOBUTTON "Appl&ication",
|
||||||
IDC1_CURAPPLIC, 3, 150, 162, 10
|
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
|
END
|
||||||
|
|
||||||
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
|
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
|
||||||
@ -217,7 +223,7 @@ END
|
|||||||
|
|
||||||
IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119
|
IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119
|
||||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "PuTTY Negotiation Log"
|
CAPTION "PuTTY Event Log"
|
||||||
FONT 8, "MS Sans Serif"
|
FONT 8, "MS Sans Serif"
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "&Close", IDOK, 58, 102, 44, 14
|
DEFPUSHBUTTON "&Close", IDOK, 58, 102, 44, 14
|
||||||
|
49
windlg.c
49
windlg.c
@ -15,8 +15,9 @@
|
|||||||
|
|
||||||
static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
|
static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
|
||||||
|
|
||||||
static char **negots = NULL;
|
static char **events = NULL;
|
||||||
static int nnegots = 0, negsize = 0;
|
static int nevents = 0, negsize = 0;
|
||||||
|
|
||||||
static HWND logbox = NULL, abtbox = NULL;
|
static HWND logbox = NULL, abtbox = NULL;
|
||||||
|
|
||||||
static char hex[16] = "0123456789ABCDEF";
|
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, "LinuxFunctionKeys", cfg.linux_funkeys);
|
||||||
wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
|
wppi (sesskey, "ApplicationCursorKeys", cfg.app_cursor);
|
||||||
wppi (sesskey, "ApplicationKeypad", cfg.app_keypad);
|
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, "ScrollbackLines", cfg.savelines);
|
||||||
wppi (sesskey, "DECOriginMode", cfg.dec_om);
|
wppi (sesskey, "DECOriginMode", cfg.dec_om);
|
||||||
wppi (sesskey, "AutoWrapMode", cfg.wrap_mode);
|
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, "LinuxFunctionKeys", 0, &cfg.linux_funkeys);
|
||||||
gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
|
gppi (sesskey, "ApplicationCursorKeys", 0, &cfg.app_cursor);
|
||||||
gppi (sesskey, "ApplicationKeypad", 0, &cfg.app_keypad);
|
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, "ScrollbackLines", 200, &cfg.savelines);
|
||||||
gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
|
gppi (sesskey, "DECOriginMode", 0, &cfg.dec_om);
|
||||||
gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
|
gppi (sesskey, "AutoWrapMode", 1, &cfg.wrap_mode);
|
||||||
@ -355,9 +362,9 @@ static int CALLBACK LogProc (HWND hwnd, UINT msg,
|
|||||||
|
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
for (i=0; i<nnegots; i++)
|
for (i=0; i<nevents; i++)
|
||||||
SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
|
SendDlgItemMessage (hwnd, IDN_LIST, LB_ADDSTRING,
|
||||||
0, (LPARAM)negots[i]);
|
0, (LPARAM)events[i]);
|
||||||
return 1;
|
return 1;
|
||||||
/* case WM_CTLCOLORDLG: */
|
/* case WM_CTLCOLORDLG: */
|
||||||
/* return (int) GetStockObject (LTGRAY_BRUSH); */
|
/* return (int) GetStockObject (LTGRAY_BRUSH); */
|
||||||
@ -624,8 +631,11 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
|
|||||||
cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
|
cfg.linux_funkeys ? IDC1_FUNCLINUX : IDC1_FUNCTILDE);
|
||||||
CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
|
CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC,
|
||||||
cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
|
cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL);
|
||||||
CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPAPPLIC,
|
CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH,
|
||||||
|
cfg.nethack_keypad ? IDC1_KPNH :
|
||||||
cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
|
cfg.app_keypad ? IDC1_KPAPPLIC : IDC1_KPNORMAL);
|
||||||
|
CheckDlgButton (hwnd, IDC1_ALTF4, cfg.alt_f4);
|
||||||
|
CheckDlgButton (hwnd, IDC1_ALTSPACE, cfg.alt_space);
|
||||||
break;
|
break;
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
if (HIWORD(wParam) == BN_CLICKED ||
|
if (HIWORD(wParam) == BN_CLICKED ||
|
||||||
@ -646,11 +656,26 @@ static int CALLBACK KeyboardProc (HWND hwnd, UINT msg,
|
|||||||
case IDC1_KPNORMAL:
|
case IDC1_KPNORMAL:
|
||||||
case IDC1_KPAPPLIC:
|
case IDC1_KPAPPLIC:
|
||||||
cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
|
cfg.app_keypad = IsDlgButtonChecked (hwnd, IDC1_KPAPPLIC);
|
||||||
|
cfg.nethack_keypad = FALSE;
|
||||||
|
break;
|
||||||
|
case IDC1_KPNH:
|
||||||
|
cfg.app_keypad = FALSE;
|
||||||
|
cfg.nethack_keypad = TRUE;
|
||||||
break;
|
break;
|
||||||
case IDC1_CURNORMAL:
|
case IDC1_CURNORMAL:
|
||||||
case IDC1_CURAPPLIC:
|
case IDC1_CURAPPLIC:
|
||||||
cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
|
cfg.app_cursor = IsDlgButtonChecked (hwnd, IDC1_CURAPPLIC);
|
||||||
break;
|
break;
|
||||||
|
case IDC1_ALTF4:
|
||||||
|
if (HIWORD(wParam) == BN_CLICKED ||
|
||||||
|
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||||
|
cfg.alt_f4 = IsDlgButtonChecked (hwnd, IDC1_ALTF4);
|
||||||
|
break;
|
||||||
|
case IDC1_ALTSPACE:
|
||||||
|
if (HIWORD(wParam) == BN_CLICKED ||
|
||||||
|
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||||
|
cfg.alt_space = IsDlgButtonChecked (hwnd, IDC1_ALTSPACE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return GeneralPanelProc (hwnd, msg, wParam, lParam);
|
return GeneralPanelProc (hwnd, msg, wParam, lParam);
|
||||||
@ -1361,20 +1386,20 @@ void do_defaults (char *session) {
|
|||||||
load_settings ("Default Settings", FALSE);
|
load_settings ("Default Settings", FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lognegot (char *string) {
|
void logevent (char *string) {
|
||||||
if (nnegots >= negsize) {
|
if (nevents >= negsize) {
|
||||||
negsize += 64;
|
negsize += 64;
|
||||||
negots = srealloc (negots, negsize * sizeof(*negots));
|
events = srealloc (events, negsize * sizeof(*events));
|
||||||
}
|
}
|
||||||
negots[nnegots] = smalloc(1+strlen(string));
|
events[nevents] = smalloc(1+strlen(string));
|
||||||
strcpy (negots[nnegots], string);
|
strcpy (events[nevents], string);
|
||||||
nnegots++;
|
nevents++;
|
||||||
if (logbox)
|
if (logbox)
|
||||||
SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
|
SendDlgItemMessage (logbox, IDN_LIST, LB_ADDSTRING,
|
||||||
0, (LPARAM)string);
|
0, (LPARAM)string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shownegot (HWND hwnd) {
|
void showeventlog (HWND hwnd) {
|
||||||
if (!logbox) {
|
if (!logbox) {
|
||||||
logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
|
logbox = CreateDialog (hinst, MAKEINTRESOURCE(IDD_LOGBOX),
|
||||||
hwnd, LogProc);
|
hwnd, LogProc);
|
||||||
|
45
window.c
45
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_EOR, "End Of Record");
|
||||||
AppendMenu (p, MF_ENABLED, IDM_TEL_EOF, "End Of File");
|
AppendMenu (p, MF_ENABLED, IDM_TEL_EOF, "End Of File");
|
||||||
AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) p, "Telnet Command");
|
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_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_NEWSESS, "New Session");
|
||||||
AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "Duplicate Session");
|
AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "Duplicate Session");
|
||||||
s = CreateMenu();
|
s = CreateMenu();
|
||||||
@ -628,7 +629,7 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
|
|||||||
case WM_SYSCOMMAND:
|
case WM_SYSCOMMAND:
|
||||||
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
|
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
|
||||||
case IDM_SHOWLOG:
|
case IDM_SHOWLOG:
|
||||||
shownegot(hwnd);
|
showeventlog(hwnd);
|
||||||
break;
|
break;
|
||||||
case IDM_NEWSESS:
|
case IDM_NEWSESS:
|
||||||
case IDM_DUPSESS:
|
case IDM_DUPSESS:
|
||||||
@ -1013,6 +1014,8 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = TranslateKey (wParam, lParam, buf);
|
len = TranslateKey (wParam, lParam, buf);
|
||||||
|
if (len == -1)
|
||||||
|
return DefWindowProc (hwnd, message, wParam, lParam);
|
||||||
back->send (buf, len);
|
back->send (buf, len);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1253,9 +1256,12 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
|
|||||||
SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
|
SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((lParam & 0x20000000) && wParam == VK_F4) {
|
if ((lParam & 0x20000000) && wParam == VK_F4 && cfg.alt_f4) {
|
||||||
SendMessage (hwnd, WM_CLOSE, 0, 0);
|
return -1;
|
||||||
return 0;
|
}
|
||||||
|
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;
|
return p - output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (cfg.nethack_keypad) {
|
||||||
* If we're in applications keypad mode, we have to process it
|
int shift = keystate[VK_SHIFT] & 0x80;
|
||||||
* before char-map translation, because it will pre-empt lots
|
/*
|
||||||
* of stuff, even if NumLock is off.
|
* NB the shifted versions only work with numlock off.
|
||||||
*/
|
*/
|
||||||
if (app_keypad_keys) {
|
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) {
|
if (ret) {
|
||||||
/*
|
/*
|
||||||
* Hack to ensure NumLock doesn't interfere with
|
* Hack to ensure NumLock doesn't interfere with
|
||||||
|
Loading…
Reference in New Issue
Block a user