Created new data types `Filename' and `FontSpec', intended to be
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index dde5bfa..9ffb47e 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1719,8 +1719,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
 
     ssh->remote_bugs = 0;
 
-    if (ssh->cfg.sshbug_ignore1 == BUG_ON ||
-       (ssh->cfg.sshbug_ignore1 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_ignore1 == FORCE_ON ||
+       (ssh->cfg.sshbug_ignore1 == AUTO &&
         (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
          !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
          !strcmp(imp, "1.2.22") || !strcmp(imp, "Cisco-1.25")))) {
@@ -1733,8 +1733,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH1 ignore bug");
     }
 
-    if (ssh->cfg.sshbug_plainpw1 == BUG_ON ||
-       (ssh->cfg.sshbug_plainpw1 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_plainpw1 == FORCE_ON ||
+       (ssh->cfg.sshbug_plainpw1 == AUTO &&
         (!strcmp(imp, "Cisco-1.25")))) {
        /*
         * These versions need a plain password sent; they can't
@@ -1745,8 +1745,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version needs a plain SSH1 password");
     }
 
-    if (ssh->cfg.sshbug_rsa1 == BUG_ON ||
-       (ssh->cfg.sshbug_rsa1 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_rsa1 == FORCE_ON ||
+       (ssh->cfg.sshbug_rsa1 == AUTO &&
         (!strcmp(imp, "Cisco-1.25")))) {
        /*
         * These versions apparently have no clue whatever about
@@ -1757,8 +1757,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version can't handle RSA authentication");
     }
 
-    if (ssh->cfg.sshbug_hmac2 == BUG_ON ||
-       (ssh->cfg.sshbug_hmac2 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_hmac2 == FORCE_ON ||
+       (ssh->cfg.sshbug_hmac2 == AUTO &&
         (wc_match("2.1.0*", imp) || wc_match("2.0.*", imp) ||
          wc_match("2.2.0*", imp) || wc_match("2.3.0*", imp) ||
          wc_match("2.1 *", imp)))) {
@@ -1769,8 +1769,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH2 HMAC bug");
     }
 
-    if (ssh->cfg.sshbug_derivekey2 == BUG_ON ||
-       (ssh->cfg.sshbug_derivekey2 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_derivekey2 == FORCE_ON ||
+       (ssh->cfg.sshbug_derivekey2 == AUTO &&
         (wc_match("2.0.0*", imp) || wc_match("2.0.1[01]*", imp) ))) {
        /*
         * These versions have the key-derivation bug (failing to
@@ -1781,8 +1781,8 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH2 key-derivation bug");
     }
 
-    if (ssh->cfg.sshbug_rsapad2 == BUG_ON ||
-       (ssh->cfg.sshbug_rsapad2 == BUG_AUTO &&
+    if (ssh->cfg.sshbug_rsapad2 == FORCE_ON ||
+       (ssh->cfg.sshbug_rsapad2 == AUTO &&
         (wc_match("OpenSSH_2.[5-9]*", imp) ||
          wc_match("OpenSSH_3.[0-2]*", imp)))) {
        /*
@@ -1792,7 +1792,7 @@ static void ssh_detect_bugs(Ssh ssh, char *vstring)
        logevent("We believe remote version has SSH2 RSA padding bug");
     }
 
-    if (ssh->cfg.sshbug_dhgex2 == BUG_ON) {
+    if (ssh->cfg.sshbug_dhgex2 == FORCE_ON) {
        /*
         * User specified the SSH2 DH GEX bug.
         */
@@ -2055,7 +2055,7 @@ static char *connect_to_host(Ssh ssh, char *host, int port,
      * Try to find host.
      */
     logeventf(ssh, "Looking up host \"%s\"", host);
-    addr = name_lookup(host, port, realhost);
+    addr = name_lookup(host, port, realhost, &ssh->cfg);
     if ((err = sk_addr_error(addr)) != NULL)
        return err;
 
@@ -2068,7 +2068,8 @@ static char *connect_to_host(Ssh ssh, char *host, int port,
        logeventf(ssh, "Connecting to %s port %d", addrbuf, port);
     }
     ssh->fn = &fn_table;
-    ssh->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) ssh);
+    ssh->s = new_connection(addr, *realhost, port,
+                           0, 1, nodelay, (Plug) ssh, &ssh->cfg);
     if ((err = sk_socket_error(ssh->s)) != NULL) {
        ssh->s = NULL;
        return err;
@@ -2456,8 +2457,8 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     }
     s->tis_auth_refused = s->ccard_auth_refused = 0;
     /* Load the public half of ssh->cfg.keyfile so we notice if it's in Pageant */
-    if (*ssh->cfg.keyfile) {
-       if (!rsakey_pubblob(ssh->cfg.keyfile,
+    if (!filename_is_null(ssh->cfg.keyfile)) {
+       if (!rsakey_pubblob(&ssh->cfg.keyfile,
                            &s->publickey_blob, &s->publickey_bloblen))
            s->publickey_blob = NULL;
     } else
@@ -2585,7 +2586,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            if (s->authed)
                break;
        }
-       if (*ssh->cfg.keyfile && !s->tried_publickey)
+       if (!filename_is_null(ssh->cfg.keyfile) && !s->tried_publickey)
            s->pwpkt_type = SSH1_CMSG_AUTH_RSA;
 
        if (ssh->cfg.try_tis_auth &&
@@ -2651,7 +2652,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            if (flags & FLAG_VERBOSE)
                c_write_str(ssh, "Trying public key authentication.\r\n");
            logeventf(ssh, "Trying public key \"%s\"", ssh->cfg.keyfile);
-           type = key_type(ssh->cfg.keyfile);
+           type = key_type(&ssh->cfg.keyfile);
            if (type != SSH_KEYTYPE_SSH1) {
                sprintf(msgbuf, "Key is of wrong type (%s)",
                        key_type_to_str(type));
@@ -2661,7 +2662,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                s->tried_publickey = 1;
                continue;
            }
-           if (!rsakey_encrypted(ssh->cfg.keyfile, &comment)) {
+           if (!rsakey_encrypted(&ssh->cfg.keyfile, &comment)) {
                if (flags & FLAG_VERBOSE)
                    c_write_str(ssh, "No passphrase required.\r\n");
                goto tryauth;
@@ -2717,10 +2718,10 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            s->tried_publickey = 1;
            
            {
-               int ret = loadrsakey(ssh->cfg.keyfile, &s->key, s->password);
+               int ret = loadrsakey(&ssh->cfg.keyfile, &s->key, s->password);
                if (ret == 0) {
                    c_write_str(ssh, "Couldn't load private key from ");
-                   c_write_str(ssh, ssh->cfg.keyfile);
+                   c_write_str(ssh, filename_to_str(ssh->cfg.keyfile));
                    c_write_str(ssh, ".\r\n");
                    continue;          /* go and try password */
                }
@@ -3121,7 +3122,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            if (sport && dport) {
                if (type == 'L') {
                    pfd_addforward(host, dport, *saddr ? saddr : NULL,
-                                  sport, ssh, ssh->cfg.lport_acceptall);
+                                  sport, ssh, &ssh->cfg);
                    logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s"
                              " forwarding to %s:%.*s%.*s%d%.*s",
                              (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL,
@@ -3285,7 +3286,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                    c->ssh = ssh;
 
                    if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
-                                ssh->x11auth, NULL, -1) != NULL) {
+                                ssh->x11auth, NULL, -1, &ssh->cfg) != NULL) {
                        logevent("opening X11 forward connection failed");
                        sfree(c);
                        send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
@@ -3363,7 +3364,7 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                    sprintf(buf, "Received remote port open request for %s:%d",
                            host, port);
                    logevent(buf);
-                   e = pfd_newconnect(&c->u.pfd.s, host, port, c);
+                   e = pfd_newconnect(&c->u.pfd.s, host, port, c, &ssh->cfg);
                    if (e != NULL) {
                        char buf[256];
                        sprintf(buf, "Port open failed: %s", e);
@@ -4030,6 +4031,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
     SHA_Final(&ssh->exhash, s->exchange_hash);
 
     dh_cleanup(ssh->kex_ctx);
+    ssh->kex_ctx = NULL;
 
 #if 0
     debug(("Exchange hash is:\n"));
@@ -4386,13 +4388,13 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        s->tried_keyb_inter = FALSE;
        s->kbd_inter_running = FALSE;
        /* Load the pub half of ssh->cfg.keyfile so we notice if it's in Pageant */
-       if (*ssh->cfg.keyfile) {
+       if (!filename_is_null(ssh->cfg.keyfile)) {
            int keytype;
            logeventf(ssh, "Reading private key file \"%.150s\"", ssh->cfg.keyfile);
-           keytype = key_type(ssh->cfg.keyfile);
+           keytype = key_type(&ssh->cfg.keyfile);
            if (keytype == SSH_KEYTYPE_SSH2) {
                s->publickey_blob =
-                   ssh2_userkey_loadpub(ssh->cfg.keyfile, NULL,
+                   ssh2_userkey_loadpub(&ssh->cfg.keyfile, NULL,
                                         &s->publickey_bloblen);
            } else {
                char *msgbuf;
@@ -4690,7 +4692,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                 * willing to accept it.
                 */
                pub_blob =
-                   (unsigned char *)ssh2_userkey_loadpub(ssh->cfg.keyfile,
+                   (unsigned char *)ssh2_userkey_loadpub(&ssh->cfg.keyfile,
                                                          &algorithm,
                                                          &pub_blob_len);
                if (pub_blob) {
@@ -4718,7 +4720,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                     * Actually attempt a serious authentication using
                     * the key.
                     */
-                   if (ssh2_userkey_encrypted(ssh->cfg.keyfile, &comment)) {
+                   if (ssh2_userkey_encrypted(&ssh->cfg.keyfile, &comment)) {
                        sprintf(s->pwprompt,
                                "Passphrase for key \"%.100s\": ",
                                comment);
@@ -4870,7 +4872,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                 */
                struct ssh2_userkey *key;
 
-               key = ssh2_load_userkey(ssh->cfg.keyfile, s->password);
+               key = ssh2_load_userkey(&ssh->cfg.keyfile, s->password);
                if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
                    if (key == SSH2_WRONG_PASSPHRASE) {
                        c_write_str(ssh, "Wrong passphrase\r\n");
@@ -5185,7 +5187,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
            if (sport && dport) {
                if (type == 'L') {
                    pfd_addforward(host, dport, *saddr ? saddr : NULL,
-                                  sport, ssh, ssh->cfg.lport_acceptall);
+                                  sport, ssh, &ssh->cfg);
                    logeventf(ssh, "Local port %.*s%.*s%.*s%.*s%d%.*s"
                              " forwarding to %s:%.*s%.*s%d%.*s",
                              (int)(*saddr?strlen(saddr):0), *saddr?saddr:NULL,
@@ -5746,7 +5748,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                    if (!ssh->X11_fwd_enabled)
                        error = "X11 forwarding is not enabled";
                    else if (x11_init(&c->u.x11.s, ssh->cfg.x11_display, c,
-                                     ssh->x11auth, addrstr, port) != NULL) {
+                                     ssh->x11auth, addrstr, port,
+                                     &ssh->cfg) != NULL) {
                        error = "Unable to open an X11 connection";
                    } else {
                        c->type = CHAN_X11;
@@ -5765,7 +5768,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                        error = "Remote port is not recognised";
                    } else {
                        char *e = pfd_newconnect(&c->u.pfd.s, realpf->dhost,
-                                                realpf->dport, c);
+                                                realpf->dport, c, &ssh->cfg);
                        logeventf(ssh, "Received remote port open request"
                                  " for %s:%d", realpf->dhost, realpf->dport);
                        if (e != NULL) {
@@ -5900,6 +5903,7 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->sccomp = NULL;
     ssh->sc_comp_ctx = NULL;
     ssh->kex = NULL;
+    ssh->kex_ctx = NULL;
     ssh->hostkey = NULL;
     ssh->exitcode = -1;
     ssh->state = SSH_STATE_PREPACKET;
@@ -5946,6 +5950,9 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     ssh->term_width = ssh->cfg.width;
     ssh->term_height = ssh->cfg.height;
 
+    ssh->channels = NULL;
+    ssh->rportfwds = NULL;
+
     ssh->send_ok = 0;
     ssh->editing = 0;
     ssh->echoing = 0;
@@ -5962,6 +5969,65 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
     return NULL;
 }
 
+static void ssh_free(void *handle)
+{
+    Ssh ssh = (Ssh) handle;
+    struct ssh_channel *c;
+    struct ssh_rportfwd *pf;
+
+    if (ssh->v1_cipher_ctx)
+       ssh->cipher->free_context(ssh->v1_cipher_ctx);
+    if (ssh->cs_cipher_ctx)
+       ssh->cscipher->free_context(ssh->cs_cipher_ctx);
+    if (ssh->sc_cipher_ctx)
+       ssh->sccipher->free_context(ssh->sc_cipher_ctx);
+    if (ssh->cs_mac_ctx)
+       ssh->csmac->free_context(ssh->cs_mac_ctx);
+    if (ssh->sc_mac_ctx)
+       ssh->scmac->free_context(ssh->sc_mac_ctx);
+    if (ssh->cs_comp_ctx)
+       ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
+    if (ssh->sc_comp_ctx)
+       ssh->sccomp->compress_cleanup(ssh->sc_comp_ctx);
+    if (ssh->kex_ctx)
+       dh_cleanup(ssh->kex_ctx);
+    sfree(ssh->savedhost);
+
+    if (ssh->channels) {
+       while ((c = delpos234(ssh->channels, 0)) != NULL) {
+           switch (c->type) {
+             case CHAN_X11:
+               if (c->u.x11.s != NULL)
+                   x11_close(c->u.x11.s);
+               break;
+             case CHAN_SOCKDATA:
+               if (c->u.pfd.s != NULL)
+                   pfd_close(c->u.pfd.s);
+               break;
+           }
+           sfree(c);
+       }
+       freetree234(ssh->channels);
+    }
+
+    if (ssh->rportfwds) {
+       while ((pf = delpos234(ssh->rportfwds, 0)) != NULL)
+           sfree(pf);
+       freetree234(ssh->rportfwds);
+    }
+    sfree(ssh->deferred_send_data);
+    if (ssh->x11auth)
+       x11_free_auth(ssh->x11auth);
+    sfree(ssh->do_ssh_init_state);
+    sfree(ssh->do_ssh1_login_state);
+    sfree(ssh->do_ssh2_transport_state);
+    sfree(ssh->do_ssh2_authconn_state);
+    
+    if (ssh->s)
+       sk_close(ssh->s);
+    sfree(ssh);
+}
+
 /*
  * Reconfigure the SSH backend.
  * 
@@ -6234,6 +6300,7 @@ extern int ssh_fallback_cmd(void *handle)
 
 Backend ssh_backend = {
     ssh_init,
+    ssh_free,
     ssh_reconfig,
     ssh_send,
     ssh_sendbuffer,