Ahem. Actually _checking_ that asynchronous askalg() worked would

have been helpful. Since async verify_ssh_host_key() worked, I
didn't think anything else could go wrong. How wrong I was.

[originally from svn r5331]
This commit is contained in:
Simon Tatham 2005-02-17 18:56:37 +00:00
Родитель 8574822b9b
Коммит fceaa2e4a7
3 изменённых файлов: 115 добавлений и 90 удалений

Просмотреть файл

@ -320,7 +320,7 @@ static void askalg_callback(void *ctx, int result)
{ {
struct algstate *state = (struct algstate *)ctx; struct algstate *state = (struct algstate *)ctx;
state->callback(state->ctx, result == 0); state->callback(state->ctx, result == NSAlertFirstButtonReturn);
sfree(state); sfree(state);
} }
@ -343,7 +343,7 @@ int askalg(void *frontend, const char *algtype, const char *algname,
state->callback = callback; state->callback = callback;
state->ctx = ctx; state->ctx = ctx;
alert = [NSAlert alloc]; alert = [[NSAlert alloc] init];
[alert setInformativeText:[NSString stringWithCString:text]]; [alert setInformativeText:[NSString stringWithCString:text]];
[alert addButtonWithTitle:@"Yes"]; [alert addButtonWithTitle:@"Yes"];
[alert addButtonWithTitle:@"No"]; [alert addButtonWithTitle:@"No"];

Просмотреть файл

@ -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 - (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
contextInfo:(void *)contextInfo 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; alert_ctx = NULL;
this_callback(this_ctx, returnCode); /* transfers ownership of ctx */
} }
@end @end

179
ssh.c
Просмотреть файл

@ -4827,7 +4827,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
{ {
unsigned char *in = (unsigned char *)vin; unsigned char *in = (unsigned char *)vin;
struct do_ssh2_transport_state { struct do_ssh2_transport_state {
int nbits, pbits, warn; int nbits, pbits, warn_kex, warn_cscipher, warn_sccipher;
Bignum p, g, e, f, K; Bignum p, g, e, f, K;
int kex_init_value, kex_reply_value; int kex_init_value, kex_reply_value;
const struct ssh_mac **maclist; const struct ssh_mac **maclist;
@ -4851,6 +4851,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
struct Packet *pktout; struct Packet *pktout;
int dlgret; int dlgret;
int guessok; int guessok;
int ignorepkt;
}; };
crState(do_ssh2_transport_state); crState(do_ssh2_transport_state);
@ -5063,7 +5064,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
* to. * to.
*/ */
{ {
char *str; char *str, *preferred;
int i, j, len; int i, j, len;
if (pktin->type != SSH2_MSG_KEXINIT) { 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->scmac_tobe = NULL;
s->cscomp_tobe = NULL; s->cscomp_tobe = NULL;
s->sccomp_tobe = NULL; s->sccomp_tobe = NULL;
s->warn_kex = s->warn_cscipher = s->warn_sccipher = FALSE;
pktin->savedpos += 16; /* skip garbage cookie */ pktin->savedpos += 16; /* skip garbage cookie */
ssh_pkt_getstring(pktin, &str, &len); /* key exchange algorithms */ ssh_pkt_getstring(pktin, &str, &len); /* key exchange algorithms */
s->warn = 0;
preferred = NULL;
for (i = 0; i < s->n_preferred_kex; i++) { for (i = 0; i < s->n_preferred_kex; i++) {
const struct ssh_kex *k = s->preferred_kex[i]; const struct ssh_kex *k = s->preferred_kex[i];
if (!k) { if (!k) {
s->warn = 1; s->warn_kex = TRUE;
} else if (in_commasep_string(k->name, str, len)) { } else {
ssh->kex = k; if (!preferred) preferred = k->name;
if (in_commasep_string(k->name, str, len))
ssh->kex = k;
} }
if (ssh->kex) { 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);
}
}
break; break;
}
} }
if (!ssh->kex) { if (!ssh->kex) {
bombout(("Couldn't agree a key exchange algorithm (available: %s)", 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 * the first algorithm in our list, even if it's still the algorithm
* we end up using. * we end up using.
*/ */
s->guessok = s->guessok = first_in_commasep_string(preferred, str, len);
first_in_commasep_string(s->preferred_kex[0]->name, str, len);
ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */ ssh_pkt_getstring(pktin, &str, &len); /* host key algorithms */
for (i = 0; i < lenof(hostkey_algs); i++) { for (i = 0; i < lenof(hostkey_algs); i++) {
if (in_commasep_string(hostkey_algs[i]->name, str, len)) { 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 && s->guessok = s->guessok &&
first_in_commasep_string(hostkey_algs[0]->name, str, len); first_in_commasep_string(hostkey_algs[0]->name, str, len);
ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */ ssh_pkt_getstring(pktin, &str, &len); /* client->server cipher */
s->warn = 0;
for (i = 0; i < s->n_preferred_ciphers; i++) { for (i = 0; i < s->n_preferred_ciphers; i++) {
const struct ssh2_ciphers *c = s->preferred_ciphers[i]; const struct ssh2_ciphers *c = s->preferred_ciphers[i];
if (!c) { if (!c) {
s->warn = 1; s->warn_cscipher = TRUE;
} else { } else {
for (j = 0; j < c->nciphers; j++) { for (j = 0; j < c->nciphers; j++) {
if (in_commasep_string(c->list[j]->name, str, len)) { 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->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);
}
}
break; break;
}
} }
if (!s->cscipher_tobe) { if (!s->cscipher_tobe) {
bombout(("Couldn't agree a client-to-server cipher (available: %s)", 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 */ ssh_pkt_getstring(pktin, &str, &len); /* server->client cipher */
s->warn = 0;
for (i = 0; i < s->n_preferred_ciphers; i++) { for (i = 0; i < s->n_preferred_ciphers; i++) {
const struct ssh2_ciphers *c = s->preferred_ciphers[i]; const struct ssh2_ciphers *c = s->preferred_ciphers[i];
if (!c) { if (!c) {
s->warn = 1; s->warn_sccipher = TRUE;
} else { } else {
for (j = 0; j < c->nciphers; j++) { for (j = 0; j < c->nciphers; j++) {
if (in_commasep_string(c->list[j]->name, str, len)) { 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->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);
}
}
break; break;
}
} }
if (!s->sccipher_tobe) { if (!s->sccipher_tobe) {
bombout(("Couldn't agree a server-to-client cipher (available: %s)", 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); /* client->server language */
ssh_pkt_getstring(pktin, &str, &len); /* server->client 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 */ crWaitUntil(pktin); /* Ignore packet */
} }