Ahem. Actually _checking_ that asynchronous askalg() worked would
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 17 Feb 2005 18:56:37 +0000 (18:56 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Thu, 17 Feb 2005 18:56:37 +0000 (18:56 +0000)
have been helpful. Since async verify_ssh_host_key() worked, I
didn't think anything else could go wrong. How wrong I was.

git-svn-id: svn://svn.tartarus.org/sgt/putty@5331 cda61777-01e9-0310-a592-d414129be87e

macosx/osxdlg.m
macosx/osxwin.m
ssh.c

index 0ea327f..588a814 100644 (file)
@@ -320,7 +320,7 @@ static void askalg_callback(void *ctx, int result)
 {
     struct algstate *state = (struct algstate *)ctx;
 
-    state->callback(state->ctx, result == 0);
+    state->callback(state->ctx, result == NSAlertFirstButtonReturn);
     sfree(state);
 }
 
@@ -343,7 +343,7 @@ int askalg(void *frontend, const char *algtype, const char *algname,
     state->callback = callback;
     state->ctx = ctx;
 
-    alert = [NSAlert alloc];
+    alert = [[NSAlert alloc] init];
     [alert setInformativeText:[NSString stringWithCString:text]];
     [alert addButtonWithTitle:@"Yes"];
     [alert addButtonWithTitle:@"No"];
index 8166f91..0424b0b 100644 (file)
@@ -794,8 +794,28 @@ printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
 - (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
     contextInfo:(void *)contextInfo
 {
-    alert_callback(alert_ctx, returnCode);   /* transfers ownership of ctx */
+    [self performSelectorOnMainThread:
+     @selector(alertSheetDidFinishEnding:)
+     withObject:[NSNumber numberWithInt:returnCode]
+     waitUntilDone:NO];
+}
+
+- (void)alertSheetDidFinishEnding:(id)object
+{
+    int returnCode = [object intValue];
+    void (*this_callback)(void *, int);
+    void *this_ctx;
+
+    /*
+     * We must save the values of our alert_callback and alert_ctx
+     * fields, in case they are set up again by the callback
+     * function!
+     */
+    this_callback = alert_callback;
+    this_ctx = alert_ctx;
     alert_ctx = NULL;
+
+    this_callback(this_ctx, returnCode);   /* transfers ownership of ctx */
 }
 
 @end
diff --git a/ssh.c b/ssh.c
index e41e9a9..58e72f5 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -4827,7 +4827,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
 {
     unsigned char *in = (unsigned char *)vin;
     struct do_ssh2_transport_state {
-       int nbits, pbits, warn;
+       int nbits, pbits, warn_kex, warn_cscipher, warn_sccipher;
        Bignum p, g, e, f, K;
        int kex_init_value, kex_reply_value;
        const struct ssh_mac **maclist;
@@ -4851,6 +4851,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        struct Packet *pktout;
         int dlgret;
        int guessok;
+       int ignorepkt;
     };
     crState(do_ssh2_transport_state);
 
@@ -5063,7 +5064,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
      * to.
      */
     {
-       char *str;
+       char *str, *preferred;
        int i, j, len;
 
        if (pktin->type != SSH2_MSG_KEXINIT) {
@@ -5078,41 +5079,23 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        s->scmac_tobe = NULL;
        s->cscomp_tobe = NULL;
        s->sccomp_tobe = NULL;
+       s->warn_kex = s->warn_cscipher = s->warn_sccipher = FALSE;
+
        pktin->savedpos += 16;          /* skip garbage cookie */
        ssh_pkt_getstring(pktin, &str, &len);    /* key exchange algorithms */
-       s->warn = 0;
+
+       preferred = NULL;
        for (i = 0; i < s->n_preferred_kex; i++) {
            const struct ssh_kex *k = s->preferred_kex[i];
            if (!k) {
-               s->warn = 1;
-           } else if (in_commasep_string(k->name, str, len)) {
-               ssh->kex = k;
+               s->warn_kex = TRUE;
+           } else {
+               if (!preferred) preferred = k->name;
+               if (in_commasep_string(k->name, str, len))
+                   ssh->kex = k;
            }
-           if (ssh->kex) {
-               if (s->warn) {
-                   ssh_set_frozen(ssh, 1);
-                   s->dlgret = askalg(ssh->frontend, "key-exchange algorithm",
-                                      ssh->kex->name,
-                                      ssh_dialog_callback, ssh);
-                   if (s->dlgret < 0) {
-                       do {
-                           crReturn(0);
-                           if (pktin) {
-                               bombout(("Unexpected data from server while"
-                                        " waiting for user response"));
-                               crStop(0);
-                           }
-                       } while (pktin || inlen > 0);
-                       s->dlgret = ssh->user_response;
-                   }
-                   ssh_set_frozen(ssh, 0);
-                   if (s->dlgret == 0) {
-                       ssh->close_expected = TRUE;
-                       ssh_closing((Plug)ssh, NULL, 0, 0);
-                   }
-                }
+           if (ssh->kex)
                break;
-           }
        }
        if (!ssh->kex) {
            bombout(("Couldn't agree a key exchange algorithm (available: %s)",
@@ -5124,8 +5107,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
         * the first algorithm in our list, even if it's still the algorithm
         * we end up using.
         */
-       s->guessok =
-           first_in_commasep_string(s->preferred_kex[0]->name, str, len);
+       s->guessok = first_in_commasep_string(preferred, str, len);
        ssh_pkt_getstring(pktin, &str, &len);    /* host key algorithms */
        for (i = 0; i < lenof(hostkey_algs); i++) {
            if (in_commasep_string(hostkey_algs[i]->name, str, len)) {
@@ -5136,11 +5118,10 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        s->guessok = s->guessok &&
            first_in_commasep_string(hostkey_algs[0]->name, str, len);
        ssh_pkt_getstring(pktin, &str, &len);    /* client->server cipher */
-       s->warn = 0;
        for (i = 0; i < s->n_preferred_ciphers; i++) {
            const struct ssh2_ciphers *c = s->preferred_ciphers[i];
            if (!c) {
-               s->warn = 1;
+               s->warn_cscipher = TRUE;
            } else {
                for (j = 0; j < c->nciphers; j++) {
                    if (in_commasep_string(c->list[j]->name, str, len)) {
@@ -5149,32 +5130,8 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
                    }
                }
            }
-           if (s->cscipher_tobe) {
-               if (s->warn) {
-                   ssh_set_frozen(ssh, 1);
-                   s->dlgret = askalg(ssh->frontend,
-                                      "client-to-server cipher",
-                                      s->cscipher_tobe->name,
-                                      ssh_dialog_callback, ssh);
-                   if (s->dlgret < 0) {
-                       do {
-                           crReturn(0);
-                           if (pktin) {
-                               bombout(("Unexpected data from server while"
-                                        " waiting for user response"));
-                               crStop(0);
-                           }
-                       } while (pktin || inlen > 0);
-                       s->dlgret = ssh->user_response;
-                   }
-                   ssh_set_frozen(ssh, 0);
-                   if (s->dlgret == 0) {
-                       ssh->close_expected = TRUE;
-                       ssh_closing((Plug)ssh, NULL, 0, 0);
-                   }
-                }
+           if (s->cscipher_tobe)
                break;
-           }
        }
        if (!s->cscipher_tobe) {
            bombout(("Couldn't agree a client-to-server cipher (available: %s)",
@@ -5183,11 +5140,10 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        }
 
        ssh_pkt_getstring(pktin, &str, &len);    /* server->client cipher */
-       s->warn = 0;
        for (i = 0; i < s->n_preferred_ciphers; i++) {
            const struct ssh2_ciphers *c = s->preferred_ciphers[i];
            if (!c) {
-               s->warn = 1;
+               s->warn_sccipher = TRUE;
            } else {
                for (j = 0; j < c->nciphers; j++) {
                    if (in_commasep_string(c->list[j]->name, str, len)) {
@@ -5196,32 +5152,8 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
                    }
                }
            }
-           if (s->sccipher_tobe) {
-               if (s->warn) {
-                   ssh_set_frozen(ssh, 1);
-                   s->dlgret = askalg(ssh->frontend,
-                                      "server-to-client cipher",
-                                      s->sccipher_tobe->name,
-                                      ssh_dialog_callback, ssh);
-                   if (s->dlgret < 0) {
-                       do {
-                           crReturn(0);
-                           if (pktin) {
-                               bombout(("Unexpected data from server while"
-                                        " waiting for user response"));
-                               crStop(0);
-                           }
-                       } while (pktin || inlen > 0);
-                       s->dlgret = ssh->user_response;
-                   }
-                   ssh_set_frozen(ssh, 0);
-                   if (s->dlgret == 0) {
-                       ssh->close_expected = TRUE;
-                       ssh_closing((Plug)ssh, NULL, 0, 0);
-                   }
-                }
+           if (s->sccipher_tobe)
                break;
-           }
        }
        if (!s->sccipher_tobe) {
            bombout(("Couldn't agree a server-to-client cipher (available: %s)",
@@ -5263,7 +5195,80 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        }
        ssh_pkt_getstring(pktin, &str, &len);  /* client->server language */
        ssh_pkt_getstring(pktin, &str, &len);  /* server->client language */
-       if (ssh2_pkt_getbool(pktin) && !s->guessok) /* first_kex_packet_follows */
+       s->ignorepkt = ssh2_pkt_getbool(pktin) && !s->guessok;
+
+       if (s->warn_kex) {
+           ssh_set_frozen(ssh, 1);
+           s->dlgret = askalg(ssh->frontend, "key-exchange algorithm",
+                              ssh->kex->name,
+                              ssh_dialog_callback, ssh);
+           if (s->dlgret < 0) {
+               do {
+                   crReturn(0);
+                   if (pktin) {
+                       bombout(("Unexpected data from server while"
+                                " waiting for user response"));
+                       crStop(0);
+                   }
+               } while (pktin || inlen > 0);
+               s->dlgret = ssh->user_response;
+           }
+           ssh_set_frozen(ssh, 0);
+           if (s->dlgret == 0) {
+               ssh->close_expected = TRUE;
+               ssh_closing((Plug)ssh, NULL, 0, 0);
+           }
+       }
+
+       if (s->warn_cscipher) {
+           ssh_set_frozen(ssh, 1);
+           s->dlgret = askalg(ssh->frontend,
+                              "client-to-server cipher",
+                              s->cscipher_tobe->name,
+                              ssh_dialog_callback, ssh);
+           if (s->dlgret < 0) {
+               do {
+                   crReturn(0);
+                   if (pktin) {
+                       bombout(("Unexpected data from server while"
+                                " waiting for user response"));
+                       crStop(0);
+                   }
+               } while (pktin || inlen > 0);
+               s->dlgret = ssh->user_response;
+           }
+           ssh_set_frozen(ssh, 0);
+           if (s->dlgret == 0) {
+               ssh->close_expected = TRUE;
+               ssh_closing((Plug)ssh, NULL, 0, 0);
+           }
+       }
+
+       if (s->warn_sccipher) {
+           ssh_set_frozen(ssh, 1);
+           s->dlgret = askalg(ssh->frontend,
+                              "server-to-client cipher",
+                              s->sccipher_tobe->name,
+                              ssh_dialog_callback, ssh);
+           if (s->dlgret < 0) {
+               do {
+                   crReturn(0);
+                   if (pktin) {
+                       bombout(("Unexpected data from server while"
+                                " waiting for user response"));
+                       crStop(0);
+                   }
+               } while (pktin || inlen > 0);
+               s->dlgret = ssh->user_response;
+           }
+           ssh_set_frozen(ssh, 0);
+           if (s->dlgret == 0) {
+               ssh->close_expected = TRUE;
+               ssh_closing((Plug)ssh, NULL, 0, 0);
+           }
+       }
+
+       if (s->ignorepkt) /* first_kex_packet_follows */
            crWaitUntil(pktin);                /* Ignore packet */
     }