mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Implement Zlib compression, in both SSH1 and SSH2.
[originally from svn r792]
This commit is contained in:
parent
84077ea5ee
commit
462063cdc5
3
Makefile
3
Makefile
@ -69,7 +69,7 @@ MOBJ2 = tree234.$(OBJ)
|
||||
##-- objects putty pscp plink
|
||||
OBJS1 = sshcrc.$(OBJ) sshdes.$(OBJ) sshmd5.$(OBJ) sshrsa.$(OBJ) sshrand.$(OBJ)
|
||||
OBJS2 = sshsha.$(OBJ) sshblowf.$(OBJ) noise.$(OBJ) sshdh.$(OBJ) sshdss.$(OBJ)
|
||||
OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ)
|
||||
OBJS3 = sshbn.$(OBJ) sshpubk.$(OBJ) ssh.$(OBJ) pageantc.$(OBJ) sshzlib.$(OBJ)
|
||||
##-- objects pageant
|
||||
PAGE1 = pageant.$(OBJ) sshrsa.$(OBJ) sshpubk.$(OBJ) sshdes.$(OBJ) sshbn.$(OBJ)
|
||||
PAGE2 = sshmd5.$(OBJ) version.$(OBJ) tree234.$(OBJ)
|
||||
@ -229,6 +229,7 @@ sshdh.$(OBJ): sshdh.c ssh.h
|
||||
sshdss.$(OBJ): sshdss.c ssh.h
|
||||
sshbn.$(OBJ): sshbn.c ssh.h
|
||||
sshpubk.$(OBJ): sshpubk.c ssh.h
|
||||
sshzlib.$(OBJ): sshzlib.c ssh.h
|
||||
scp.$(OBJ): scp.c putty.h network.h winstuff.h
|
||||
version.$(OBJ): version.c
|
||||
be_all.$(OBJ): be_all.c
|
||||
|
1
putty.h
1
putty.h
@ -140,6 +140,7 @@ typedef struct {
|
||||
/* SSH options */
|
||||
char remote_cmd[512];
|
||||
int nopty;
|
||||
int compression;
|
||||
int agentfwd;
|
||||
enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES } cipher;
|
||||
char keyfile[FILENAME_MAX];
|
||||
|
@ -66,6 +66,7 @@ void save_settings (char *section, int do_host, Config *cfg) {
|
||||
}
|
||||
write_setting_s (sesskey, "UserName", cfg->username);
|
||||
write_setting_i (sesskey, "NoPTY", cfg->nopty);
|
||||
write_setting_i (sesskey, "Compression", cfg->compression);
|
||||
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" :
|
||||
@ -186,6 +187,7 @@ void load_settings (char *section, int do_host, Config *cfg) {
|
||||
}
|
||||
gpps (sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
|
||||
gppi (sesskey, "NoPTY", 0, &cfg->nopty);
|
||||
gppi (sesskey, "Compression", 0, &cfg->compression);
|
||||
gppi (sesskey, "AgentFwd", 0, &cfg->agentfwd);
|
||||
gpps (sesskey, "RemoteCmd", "", cfg->remote_cmd, sizeof(cfg->remote_cmd));
|
||||
{
|
||||
|
187
ssh.c
187
ssh.c
@ -51,6 +51,7 @@
|
||||
#define SSH1_CMSG_EXIT_CONFIRMATION 33 /* 0x21 */
|
||||
#define SSH1_MSG_IGNORE 32 /* 0x20 */
|
||||
#define SSH1_MSG_DEBUG 36 /* 0x24 */
|
||||
#define SSH1_CMSG_REQUEST_COMPRESSION 37 /* 0x25 */
|
||||
#define SSH1_CMSG_AUTH_TIS 39 /* 0x27 */
|
||||
#define SSH1_SMSG_AUTH_TIS_CHALLENGE 40 /* 0x28 */
|
||||
#define SSH1_CMSG_AUTH_TIS_RESPONSE 41 /* 0x29 */
|
||||
@ -186,10 +187,19 @@ const static struct ssh_mac *macs[] = {
|
||||
const static struct ssh_mac *buggymacs[] = {
|
||||
&ssh_sha1_buggy, &ssh_md5, &ssh_mac_none };
|
||||
|
||||
static void ssh_comp_none_init(void) { }
|
||||
static int ssh_comp_none_block(unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen) {
|
||||
return 0;
|
||||
}
|
||||
const static struct ssh_compress ssh_comp_none = {
|
||||
"none"
|
||||
"none",
|
||||
ssh_comp_none_init, ssh_comp_none_block,
|
||||
ssh_comp_none_init, ssh_comp_none_block
|
||||
};
|
||||
const static struct ssh_compress *compressions[] = { &ssh_comp_none };
|
||||
extern const struct ssh_compress ssh_zlib;
|
||||
const static struct ssh_compress *compressions[] = {
|
||||
&ssh_zlib, &ssh_comp_none };
|
||||
|
||||
/*
|
||||
* 2-3-4 tree storing channels.
|
||||
@ -226,6 +236,7 @@ static SHA_State exhash;
|
||||
static Socket s = NULL;
|
||||
|
||||
static unsigned char session_key[32];
|
||||
static int ssh1_compressing;
|
||||
static const struct ssh_cipher *cipher = NULL;
|
||||
static const struct ssh_cipher *cscipher = NULL;
|
||||
static const struct ssh_cipher *sccipher = NULL;
|
||||
@ -373,9 +384,6 @@ next_packet:
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
|
||||
pktin.type = pktin.data[st->pad];
|
||||
pktin.body = pktin.data + st->pad + 1;
|
||||
|
||||
st->realcrc = crc32(pktin.data, st->biglen-4);
|
||||
st->gotcrc = GET_32BIT(pktin.data+st->biglen-4);
|
||||
if (st->gotcrc != st->realcrc) {
|
||||
@ -383,6 +391,39 @@ next_packet:
|
||||
crReturn(0);
|
||||
}
|
||||
|
||||
pktin.body = pktin.data + st->pad + 1;
|
||||
|
||||
if (ssh1_compressing) {
|
||||
unsigned char *decompblk;
|
||||
int decomplen;
|
||||
#if 0
|
||||
int i;
|
||||
debug(("Packet payload pre-decompression:\n"));
|
||||
for (i = -1; i < pktin.length; i++)
|
||||
debug((" %02x", (unsigned char)pktin.body[i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
zlib_decompress_block(pktin.body-1, pktin.length+1,
|
||||
&decompblk, &decomplen);
|
||||
|
||||
if (pktin.maxlen < st->pad + decomplen) {
|
||||
pktin.maxlen = st->pad + decomplen;
|
||||
pktin.data = realloc(pktin.data, pktin.maxlen+APIEXTRA);
|
||||
if (!pktin.data)
|
||||
fatalbox("Out of memory");
|
||||
}
|
||||
|
||||
memcpy(pktin.body-1, decompblk, decomplen);
|
||||
free(decompblk);
|
||||
pktin.length = decomplen-1;
|
||||
#if 0
|
||||
debug(("Packet payload post-decompression:\n"));
|
||||
for (i = -1; i < pktin.length; i++)
|
||||
debug((" %02x", (unsigned char)pktin.body[i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
|
||||
pktin.type == SSH1_SMSG_STDERR_DATA ||
|
||||
pktin.type == SSH1_MSG_DEBUG ||
|
||||
@ -395,6 +436,8 @@ next_packet:
|
||||
}
|
||||
}
|
||||
|
||||
pktin.type = pktin.body[-1];
|
||||
|
||||
if (pktin.type == SSH1_MSG_DEBUG) {
|
||||
/* log debug message */
|
||||
char buf[80];
|
||||
@ -515,6 +558,34 @@ next_packet:
|
||||
}
|
||||
st->incoming_sequence++; /* whether or not we MACed */
|
||||
|
||||
/*
|
||||
* Decompress packet payload.
|
||||
*/
|
||||
{
|
||||
unsigned char *newpayload;
|
||||
int newlen;
|
||||
if (sccomp && sccomp->decompress(pktin.data+5, pktin.length-5,
|
||||
&newpayload, &newlen)) {
|
||||
if (pktin.maxlen < newlen+5) {
|
||||
pktin.maxlen = newlen+5;
|
||||
pktin.data = (pktin.data == NULL ? malloc(pktin.maxlen+APIEXTRA) :
|
||||
realloc(pktin.data, pktin.maxlen+APIEXTRA));
|
||||
if (!pktin.data)
|
||||
fatalbox("Out of memory");
|
||||
}
|
||||
pktin.length = 5 + newlen;
|
||||
memcpy(pktin.data+5, newpayload, newlen);
|
||||
#if 0
|
||||
debug(("Post-decompression payload:\r\n"));
|
||||
for (st->i = 0; st->i < newlen; st->i++)
|
||||
debug((" %02x", (unsigned char)pktin.data[5+st->i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
|
||||
free(newpayload);
|
||||
}
|
||||
}
|
||||
|
||||
pktin.savedpos = 6;
|
||||
pktin.type = pktin.data[5];
|
||||
|
||||
@ -524,7 +595,7 @@ next_packet:
|
||||
crFinish(0);
|
||||
}
|
||||
|
||||
static void s_wrpkt_start(int type, int len) {
|
||||
static void ssh1_pktout_size(int len) {
|
||||
int pad, biglen;
|
||||
|
||||
len += 5; /* type and CRC */
|
||||
@ -546,20 +617,46 @@ static void s_wrpkt_start(int type, int len) {
|
||||
if (!pktout.data)
|
||||
fatalbox("Out of memory");
|
||||
}
|
||||
|
||||
pktout.type = type;
|
||||
pktout.body = pktout.data+4+pad+1;
|
||||
}
|
||||
|
||||
static void s_wrpkt_start(int type, int len) {
|
||||
ssh1_pktout_size(len);
|
||||
pktout.type = type;
|
||||
}
|
||||
|
||||
static void s_wrpkt(void) {
|
||||
int pad, len, biglen, i;
|
||||
unsigned long crc;
|
||||
|
||||
pktout.body[-1] = pktout.type;
|
||||
|
||||
if (ssh1_compressing) {
|
||||
unsigned char *compblk;
|
||||
int complen;
|
||||
#if 0
|
||||
debug(("Packet payload pre-compression:\n"));
|
||||
for (i = -1; i < pktout.length; i++)
|
||||
debug((" %02x", (unsigned char)pktout.body[i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
zlib_compress_block(pktout.body-1, pktout.length+1,
|
||||
&compblk, &complen);
|
||||
ssh1_pktout_size(complen-1);
|
||||
memcpy(pktout.body-1, compblk, complen);
|
||||
free(compblk);
|
||||
#if 0
|
||||
debug(("Packet payload post-compression:\n"));
|
||||
for (i = -1; i < pktout.length; i++)
|
||||
debug((" %02x", (unsigned char)pktout.body[i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
len = pktout.length + 5; /* type and CRC */
|
||||
pad = 8 - (len%8);
|
||||
biglen = len + pad;
|
||||
|
||||
pktout.body[-1] = pktout.type;
|
||||
for (i=0; i<pad; i++)
|
||||
pktout.data[i+4] = random_byte();
|
||||
crc = crc32(pktout.data+4, biglen-4);
|
||||
@ -767,6 +864,26 @@ static void ssh2_pkt_send(void) {
|
||||
int cipherblk, maclen, padding, i;
|
||||
static unsigned long outgoing_sequence = 0;
|
||||
|
||||
/*
|
||||
* Compress packet payload.
|
||||
*/
|
||||
#if 0
|
||||
debug(("Pre-compression payload:\r\n"));
|
||||
for (i = 5; i < pktout.length; i++)
|
||||
debug((" %02x", (unsigned char)pktout.data[i]));
|
||||
debug(("\r\n"));
|
||||
#endif
|
||||
{
|
||||
unsigned char *newpayload;
|
||||
int newlen;
|
||||
if (cscomp && cscomp->compress(pktout.data+5, pktout.length-5,
|
||||
&newpayload, &newlen)) {
|
||||
pktout.length = 5;
|
||||
ssh2_pkt_adddata(newpayload, newlen);
|
||||
free(newpayload);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add padding. At least four bytes, and must also bring total
|
||||
* length (minus MAC) up to a multiple of the block size.
|
||||
@ -1637,6 +1754,21 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
|
||||
logevent("Allocated pty");
|
||||
}
|
||||
|
||||
if (cfg.compression) {
|
||||
send_packet(SSH1_CMSG_REQUEST_COMPRESSION, PKT_INT, 6, PKT_END);
|
||||
do { crReturnV; } while (!ispkt);
|
||||
if (pktin.type != SSH1_SMSG_SUCCESS && pktin.type != SSH1_SMSG_FAILURE) {
|
||||
bombout(("Protocol confusion"));
|
||||
crReturnV;
|
||||
} else if (pktin.type == SSH1_SMSG_FAILURE) {
|
||||
c_write("Server refused to compress\r\n", 32);
|
||||
}
|
||||
logevent("Started compression");
|
||||
ssh1_compressing = TRUE;
|
||||
zlib_compress_init();
|
||||
zlib_decompress_init();
|
||||
}
|
||||
|
||||
if (*cfg.remote_cmd)
|
||||
send_packet(SSH1_CMSG_EXEC_CMD, PKT_STR, cfg.remote_cmd, PKT_END);
|
||||
else
|
||||
@ -1845,12 +1977,13 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
static unsigned char exchange_hash[20];
|
||||
static unsigned char keyspace[40];
|
||||
static const struct ssh_cipher *preferred_cipher;
|
||||
static const struct ssh_compress *preferred_comp;
|
||||
|
||||
crBegin;
|
||||
random_init();
|
||||
|
||||
/*
|
||||
* Set up the preferred cipher.
|
||||
* Set up the preferred cipher and compression.
|
||||
*/
|
||||
if (cfg.cipher == CIPHER_BLOWFISH) {
|
||||
preferred_cipher = &ssh_blowfish_ssh2;
|
||||
@ -1863,6 +1996,10 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
/* Shouldn't happen, but we do want to initialise to _something_. */
|
||||
preferred_cipher = &ssh_3des_ssh2;
|
||||
}
|
||||
if (cfg.compression)
|
||||
preferred_comp = &ssh_zlib;
|
||||
else
|
||||
preferred_comp = &ssh_comp_none;
|
||||
|
||||
/*
|
||||
* Be prepared to work around the buggy MAC problem.
|
||||
@ -1925,16 +2062,18 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
}
|
||||
/* List client->server compression algorithms. */
|
||||
ssh2_pkt_addstring_start();
|
||||
for (i = 0; i < lenof(compressions); i++) {
|
||||
ssh2_pkt_addstring_str(compressions[i]->name);
|
||||
if (i < lenof(compressions)-1)
|
||||
for (i = 0; i < lenof(compressions)+1; i++) {
|
||||
const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];
|
||||
ssh2_pkt_addstring_str(c->name);
|
||||
if (i < lenof(compressions))
|
||||
ssh2_pkt_addstring_str(",");
|
||||
}
|
||||
/* List server->client compression algorithms. */
|
||||
ssh2_pkt_addstring_start();
|
||||
for (i = 0; i < lenof(compressions); i++) {
|
||||
ssh2_pkt_addstring_str(compressions[i]->name);
|
||||
if (i < lenof(compressions)-1)
|
||||
for (i = 0; i < lenof(compressions)+1; i++) {
|
||||
const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];
|
||||
ssh2_pkt_addstring_str(c->name);
|
||||
if (i < lenof(compressions))
|
||||
ssh2_pkt_addstring_str(",");
|
||||
}
|
||||
/* List client->server languages. Empty list. */
|
||||
@ -2007,16 +2146,18 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
}
|
||||
}
|
||||
ssh2_pkt_getstring(&str, &len); /* client->server compression */
|
||||
for (i = 0; i < lenof(compressions); i++) {
|
||||
if (in_commasep_string(compressions[i]->name, str, len)) {
|
||||
cscomp_tobe = compressions[i];
|
||||
for (i = 0; i < lenof(compressions)+1; i++) {
|
||||
const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];
|
||||
if (in_commasep_string(c->name, str, len)) {
|
||||
cscomp_tobe = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ssh2_pkt_getstring(&str, &len); /* server->client compression */
|
||||
for (i = 0; i < lenof(compressions); i++) {
|
||||
if (in_commasep_string(compressions[i]->name, str, len)) {
|
||||
sccomp_tobe = compressions[i];
|
||||
for (i = 0; i < lenof(compressions)+1; i++) {
|
||||
const struct ssh_compress *c = i==0 ? preferred_comp : compressions[i-1];
|
||||
if (in_commasep_string(c->name, str, len)) {
|
||||
sccomp_tobe = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2105,6 +2246,8 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
|
||||
scmac = scmac_tobe;
|
||||
cscomp = cscomp_tobe;
|
||||
sccomp = sccomp_tobe;
|
||||
cscomp->compress_init();
|
||||
sccomp->decompress_init();
|
||||
/*
|
||||
* Set IVs after keys.
|
||||
*/
|
||||
|
16
ssh.h
16
ssh.h
@ -137,6 +137,12 @@ struct ssh_hostkey {
|
||||
|
||||
struct ssh_compress {
|
||||
char *name;
|
||||
void (*compress_init)(void);
|
||||
int (*compress)(unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
void (*decompress_init)(void);
|
||||
int (*decompress)(unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
};
|
||||
|
||||
#ifndef MSCRYPTOAPI
|
||||
@ -197,3 +203,13 @@ int rsa_generate(struct RSAKey *key, struct RSAAux *aux, int bits,
|
||||
progfn_t pfn, void *pfnparam);
|
||||
Bignum primegen(int bits, int modulus, int residue,
|
||||
int phase, progfn_t pfn, void *pfnparam);
|
||||
|
||||
/*
|
||||
* zlib compression.
|
||||
*/
|
||||
void zlib_compress_init(void);
|
||||
void zlib_decompress_init(void);
|
||||
int zlib_compress_block(unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
int zlib_decompress_block(unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
|
14
win_res.rc
14
win_res.rc
@ -31,24 +31,24 @@ BEGIN
|
||||
END
|
||||
|
||||
/* Accelerators used: aco */
|
||||
IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 280, 232
|
||||
IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 280, 242
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "PuTTY Configuration"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "&Open", IDOK, 184, 215, 44, 14
|
||||
PUSHBUTTON "&Cancel", IDCANCEL, 231, 215, 44, 14
|
||||
PUSHBUTTON "&About", IDC_ABOUT, 3, 215, 44, 14, NOT WS_TABSTOP
|
||||
DEFPUSHBUTTON "&Open", IDOK, 184, 225, 44, 14
|
||||
PUSHBUTTON "&Cancel", IDCANCEL, 231, 225, 44, 14
|
||||
PUSHBUTTON "&About", IDC_ABOUT, 3, 225, 44, 14, NOT WS_TABSTOP
|
||||
END
|
||||
|
||||
/* Accelerators used: ac */
|
||||
IDD_RECONF DIALOG DISCARDABLE 0, 0, 280, 232
|
||||
IDD_RECONF DIALOG DISCARDABLE 0, 0, 280, 242
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "PuTTY Reconfiguration"
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "&Apply", IDOK, 184, 215, 44, 14
|
||||
PUSHBUTTON "&Cancel", IDCANCEL, 231, 215, 44, 14
|
||||
DEFPUSHBUTTON "&Apply", IDOK, 184, 225, 44, 14
|
||||
PUSHBUTTON "&Cancel", IDCANCEL, 231, 225, 44, 14
|
||||
END
|
||||
|
||||
/* Accelerators used: co */
|
||||
|
10
windlg.c
10
windlg.c
@ -326,6 +326,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
|
||||
IDC_AGENTFWD,
|
||||
IDC_CMDSTATIC,
|
||||
IDC_CMDEDIT,
|
||||
IDC_COMPRESS,
|
||||
sshpanelend,
|
||||
|
||||
selectionpanelstart,
|
||||
@ -486,6 +487,7 @@ static void init_dlg_ctrls(HWND hwnd) {
|
||||
SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
|
||||
SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
|
||||
CheckDlgButton (hwnd, IDC_NOPTY, cfg.nopty);
|
||||
CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
|
||||
CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
|
||||
CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
|
||||
CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
|
||||
@ -631,7 +633,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
||||
|
||||
r.left = 3; r.right = r.left + 75;
|
||||
r.top = 13; r.bottom = r.top + 196;
|
||||
r.top = 13; r.bottom = r.top + 206;
|
||||
MapDialogRect(hwnd, &r);
|
||||
treeview = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, "",
|
||||
WS_CHILD | WS_VISIBLE |
|
||||
@ -972,6 +974,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
beginbox(&cp, "Protocol options",
|
||||
IDC_BOX_SSH3, IDC_BOXT_SSH3);
|
||||
checkbox(&cp, "Don't allocate a &pseudo-terminal", IDC_NOPTY);
|
||||
checkbox(&cp, "Enable compr&ession", IDC_COMPRESS);
|
||||
radioline(&cp, "Preferred SSH protocol version:",
|
||||
IDC_SSHPROTSTATIC, 2,
|
||||
"&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
|
||||
@ -1497,6 +1500,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||
cfg.nopty = IsDlgButtonChecked (hwnd, IDC_NOPTY);
|
||||
break;
|
||||
case IDC_COMPRESS:
|
||||
if (HIWORD(wParam) == BN_CLICKED ||
|
||||
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||
cfg.compression = IsDlgButtonChecked (hwnd, IDC_COMPRESS);
|
||||
break;
|
||||
case IDC_BUGGYMAC:
|
||||
if (HIWORD(wParam) == BN_CLICKED ||
|
||||
HIWORD(wParam) == BN_DOUBLECLICKED)
|
||||
|
Loading…
Reference in New Issue
Block a user