]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
SSH compression by linking with zlib.dll if present (compression
authorSimon Tatham <anakin@pobox.com>
Tue, 4 Jul 2000 09:15:12 +0000 (09:15 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 4 Jul 2000 09:15:12 +0000 (09:15 +0000)
quietly becomes unavailable if zlib.dll not found). Thanks to Joris
van Rantwijk (again).

[originally from svn r511]

putty.h
scp.h
ssh.c
ssh.h
win_res.h
win_res.rc
windlg.c

diff --git a/putty.h b/putty.h
index 0971fab3046d51d4110e03cc0133f8d1b2ae3af2..27838a108649cc12705158b156b58f5969b4d771 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -134,6 +134,7 @@ typedef struct {
     int nopty;
     enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES } cipher;
     int try_tis_auth;
+    int ssh_compression;
     /* Telnet options */
     char termtype[32];
     char termspeed[32];
@@ -194,6 +195,14 @@ GLOBAL int default_port;
 
 struct RSAKey;                        /* be a little careful of scope */
 
+/*
+ * Needed for PuTTY Secure Copy
+ */
+#define SCP_FLAG       1
+#define SCP_VERBOSE    2
+#define IS_SCP ((scp_flags & SCP_FLAG) != 0)
+GLOBAL int scp_flags;
+
 /*
  * Exports from window.c.
  */
diff --git a/scp.h b/scp.h
index 754f65c10ea07618e88d4586635824709abc89c9..25370d79d5cd08ffab8dcea44cf84f6854ca969b 100644 (file)
--- a/scp.h
+++ b/scp.h
@@ -3,12 +3,7 @@
  *  Joris van Rantwijk, Aug 1999, Jun 2000.
  */
 
-#define SCP_FLAG       1
-#define SCP_VERBOSE    2
-#define IS_SCP ((scp_flags & SCP_FLAG) != 0)
-
 /* Exported from ssh.c */
-extern int scp_flags;
 extern void (*ssh_get_password)(const char *prompt, char *str, int maxlen);
 char * ssh_scp_init(char *host, int port, char *cmd, char **realhost);
 int ssh_scp_recv(unsigned char *buf, int len);
diff --git a/ssh.c b/ssh.c
index a355c29781721a0a2ba3f60cf7a6649c3a4d058a..b917a575415eb08f9cfccc1846195d537ddb6c8c 100644 (file)
--- a/ssh.c
+++ b/ssh.c
 #define TRUE 1
 #endif
 
-#define logevent(s) { logevent(s); \
-                      if (IS_SCP && (scp_flags & SCP_VERBOSE) != 0) \
-                      fprintf(stderr, "%s\n", s); }
-
 #define SSH_MSG_DISCONNECT     1
 #define SSH_SMSG_PUBLIC_KEY    2
 #define SSH_CMSG_SESSION_KEY   3
 #define SSH_CMSG_EXIT_CONFIRMATION     33
 #define SSH_MSG_IGNORE         32
 #define SSH_MSG_DEBUG          36
+#define SSH_CMSG_REQUEST_COMPRESSION   37
 #define SSH_CMSG_AUTH_TIS      39
 #define SSH_SMSG_AUTH_TIS_CHALLENGE    40
 #define SSH_CMSG_AUTH_TIS_RESPONSE     41
 
 #define SSH_AUTH_TIS           5
+#define COMPRESSION_LEVEL      5
 
 #define GET_32BIT(cp) \
     (((unsigned long)(unsigned char)(cp)[0] << 24) | \
@@ -80,7 +78,7 @@ static SOCKET s = INVALID_SOCKET;
 
 static unsigned char session_key[32];
 static struct ssh_cipher *cipher = NULL;
-int scp_flags = 0;
+static int use_compression = 0;
 void (*ssh_get_password)(const char *prompt, char *str, int maxlen) = NULL;
 
 static char *savedhost;
@@ -155,6 +153,24 @@ static void ssh_protocol(unsigned char *in, int inlen, int ispkt);
 static void ssh_size(void);
 
 
+static void pktalloc(struct Packet *pkt, long newlen)
+{
+    if (pkt->maxlen < newlen) {
+       pkt->maxlen = newlen;
+#ifdef MSCRYPTOAPI
+       /* Allocate enough buffer space for extra block
+        * for MS CryptEncrypt() */
+       pkt->data = (pkt->data == NULL ? malloc(newlen+8) :
+                     realloc(pkt->data, newlen+8));
+#else
+       pkt->data = (pkt->data == NULL ? malloc(newlen) :
+                     realloc(pkt->data, newlen));
+#endif
+       if (!pkt->data)
+           fatalbox("Out of memory");
+    }
+}
+
 /*
  * Collect incoming data in the incoming packet buffer.
  * Decihper and verify the packet when it is completely read.
@@ -192,22 +208,9 @@ next_packet:
 
     pad = 8 - (len % 8);
     biglen = len + pad;
-    pktin.length = len - 5;
 
-    if (pktin.maxlen < biglen) {
-       pktin.maxlen = biglen;
-#ifdef MSCRYPTOAPI
-       /* Allocate enough buffer space for extra block
-        * for MS CryptEncrypt() */
-       pktin.data = (pktin.data == NULL ? malloc(biglen+8) :
-                     realloc(pktin.data, biglen+8));
-#else
-       pktin.data = (pktin.data == NULL ? malloc(biglen) :
-                     realloc(pktin.data, biglen));
-#endif
-       if (!pktin.data)
-           fatalbox("Out of memory");
-    }
+    if (pktin.maxlen < biglen)
+       pktalloc(&pktin, biglen);
 
     to_read = biglen;
     p = pktin.data;
@@ -228,15 +231,23 @@ next_packet:
     if (cipher)
        cipher->decrypt(pktin.data, biglen);
 
-    pktin.type = pktin.data[pad];
-    pktin.body = pktin.data + pad + 1;
-
     realcrc = crc32(pktin.data, biglen-4);
     gotcrc = GET_32BIT(pktin.data+biglen-4);
     if (gotcrc != realcrc) {
        fatalbox("Incorrect CRC received on packet");
     }
 
+    if (use_compression) {
+       ssh_decompress(pktin.data + pad, len - 4, &p, &len);
+       pktin.length = len - 1;
+       pktin.type = p[0];
+       pktin.body = p + 1;
+    } else {
+       pktin.length = len - 5;
+       pktin.type = pktin.data[pad];
+       pktin.body = pktin.data + pad + 1;
+    }
+
     if (pktin.type == SSH_SMSG_STDOUT_DATA ||
         pktin.type == SSH_SMSG_STDERR_DATA ||
         pktin.type == SSH_MSG_DEBUG ||
@@ -281,20 +292,8 @@ static void s_wrpkt_start(int type, int len) {
     biglen = len + pad;
 
     pktout.length = len-5;
-    if (pktout.maxlen < biglen) {
-       pktout.maxlen = biglen;
-#ifdef MSCRYPTOAPI
-       /* Allocate enough buffer space for extra block
-        * for MS CryptEncrypt() */
-       pktout.data = (pktout.data == NULL ? malloc(biglen+12) :
-                      realloc(pktout.data, biglen+12));
-#else
-       pktout.data = (pktout.data == NULL ? malloc(biglen+4) :
-                      realloc(pktout.data, biglen+4));
-#endif
-       if (!pktout.data)
-           fatalbox("Out of memory");
-    }
+    if (pktout.maxlen < biglen + 4)
+       pktalloc(&pktout, biglen + 4);
 
     pktout.type = type;
     pktout.body = pktout.data+4+pad+1;
@@ -307,8 +306,21 @@ static void s_wrpkt(void) {
     len = pktout.length + 5;          /* type and CRC */
     pad = 8 - (len%8);
     biglen = len + pad;
-
     pktout.body[-1] = pktout.type;
+
+    if (use_compression) {
+       unsigned char *p;
+       unsigned int n;
+       pktout.body = NULL;
+       ssh_compress(pktout.data + 4 + pad, pktout.length + 1, &p, &n);
+       len = n + 4;
+       pad = 8 - (len%8);
+       biglen = len + pad;
+       if (pktout.maxlen < biglen + 4)
+           pktalloc(&pktout, biglen + 4);
+       memcpy(pktout.data + 4 + pad, p, n);
+    }
+
     for (i=0; i<pad; i++)
        pktout.data[i+4] = random_byte();
     crc = crc32(pktout.data+4, biglen-4);
@@ -853,6 +865,21 @@ static int do_ssh_login(unsigned char *in, int inlen, int ispkt)
 
     logevent("Authentication successful");
 
+    if (cfg.ssh_compression &&
+        ssh_compression_init(COMPRESSION_LEVEL)) {
+       send_packet(SSH_CMSG_REQUEST_COMPRESSION,
+                   PKT_INT, COMPRESSION_LEVEL, PKT_END);
+       crWaitUntil(ispkt);
+       if (pktin.type == SSH_SMSG_SUCCESS) {
+           use_compression = 1;
+           logevent("Enabled SSH packet compression");
+       } else if (pktin.type == SSH_SMSG_FAILURE) {
+           logevent("Server does not support packet compression");
+       } else {
+           fatalbox("Strange packet received, type %d", pktin.type);
+       }
+    }
+
     crFinish(1);
 }
 
diff --git a/ssh.h b/ssh.h
index a9057e721658e82f4c608c47eeeefb8ebe4ce274..3d4efab73dfadfd777beb496f21559d5d8f778f2 100644 (file)
--- a/ssh.h
+++ b/ssh.h
@@ -62,3 +62,10 @@ int random_byte(void);
 void random_add_noise(void *noise, int length);
 
 void logevent (char *);
+
+int ssh_compression_init(int);
+void ssh_compress(unsigned char *src, unsigned int srclen,
+                  unsigned char **dest, unsigned int *destlen);
+void ssh_decompress(unsigned char *src, unsigned int srclen,
+                    unsigned char **dest, unsigned int *destlen);
+
index 6ea558c376c50dadd832f331b689205945f5d3d1..42425acd60df342499e2a54d946816c344c07e15 100644 (file)
--- a/win_res.h
+++ b/win_res.h
 #define IDC3_CIPHERBLOWF 1021
 #define IDC3_CIPHERDES  1022
 #define IDC3_AUTHTIS    1023
+#define IDC3_COMPRESS  1024
 
 #define IDC4_MBSTATIC   1001
 #define IDC4_MBWINDOWS  1002
index 49b429ccb65fe8e419eb58b2b087b14e6cc4e2da..3674ce4aad1bb351cc1e1dfc00a61f8df14cf996 100644 (file)
@@ -198,6 +198,7 @@ BEGIN
     AUTORADIOBUTTON "&Blowfish", IDC3_CIPHERBLOWF, 84, 50, 40, 10
     AUTORADIOBUTTON "&DES", IDC3_CIPHERDES, 127, 50, 30, 10
     AUTOCHECKBOX "Attempt TIS authentication", IDC3_AUTHTIS, 3, 60, 162, 10
+    AUTOCHECKBOX "Enable packet compression", IDC3_COMPRESS, 3, 70, 162, 10
 END
 
 IDD_PANEL4 DIALOG DISCARDABLE 6, 30, 168, 163
index c9c00bda6aef5b26949bee91f6a598f410a4ff62..eead076dcf5ebf752b664731d88ce7c4dde856c3 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -152,6 +152,7 @@ static void save_settings (char *section, int do_host) {
     wpps (sesskey, "Cipher", cfg.cipher == CIPHER_BLOWFISH ? "blowfish" :
                              cfg.cipher == CIPHER_DES ? "des" : "3des");
     wppi (sesskey, "AuthTIS", cfg.try_tis_auth);
+    wppi (sesskey, "SSHCompression", cfg.ssh_compression);
     wppi (sesskey, "RFCEnviron", cfg.rfc_environ);
     wppi (sesskey, "BackspaceIsDelete", cfg.bksp_is_delete);
     wppi (sesskey, "RXVTHomeEnd", cfg.rxvt_homeend);
@@ -288,6 +289,7 @@ static void load_settings (char *section, int do_host) {
            cfg.cipher = CIPHER_3DES;
     }
     gppi (sesskey, "AuthTIS", 0, &cfg.try_tis_auth);
+    gppi (sesskey, "SSHCompression", 0, &cfg.ssh_compression);
     gppi (sesskey, "RFCEnviron", 0, &cfg.rfc_environ);
     gppi (sesskey, "BackspaceIsDelete", 1, &cfg.bksp_is_delete);
     gppi (sesskey, "RXVTHomeEnd", 0, &cfg.rxvt_homeend);
@@ -956,6 +958,7 @@ static int CALLBACK SshProc (HWND hwnd, UINT msg,
 
                          IDC3_CIPHER3DES);
        CheckDlgButton (hwnd, IDC3_AUTHTIS, cfg.try_tis_auth);
+       CheckDlgButton (hwnd, IDC3_COMPRESS, cfg.ssh_compression);
        break;
       case WM_COMMAND:
        switch (LOWORD(wParam)) {
@@ -992,6 +995,11 @@ static int CALLBACK SshProc (HWND hwnd, UINT msg,
                HIWORD(wParam) == BN_DOUBLECLICKED)
                cfg.try_tis_auth = IsDlgButtonChecked (hwnd, IDC3_AUTHTIS);
            break;
+         case IDC3_COMPRESS:
+           if (HIWORD(wParam) == BN_CLICKED ||
+               HIWORD(wParam) == BN_DOUBLECLICKED)
+               cfg.ssh_compression = IsDlgButtonChecked (hwnd, IDC3_COMPRESS);
+           break;
        }
        break;
     }
@@ -1423,6 +1431,8 @@ void do_defaults (char *session) {
 }
 
 void logevent (char *string) {
+    if (IS_SCP && (scp_flags & SCP_VERBOSE) != 0)
+       fprintf(stderr, "%s\n", string);
     if (nevents >= negsize) {
        negsize += 64;
        events = srealloc (events, negsize * sizeof(*events));