X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=ssh.c;h=3af4f61006eeb0387a676c07c6e764a53389b03a;hb=4e550f96b2edcf33f2480d2374815ec3df6a60f5;hp=0815ff3241112a2d355fe6d83f1a2f297401c8a0;hpb=44239efc6bd47006b53c1a853a60f02501d61c6e;p=PuTTY.git diff --git a/ssh.c b/ssh.c index 0815ff32..3af4f610 100644 --- a/ssh.c +++ b/ssh.c @@ -750,6 +750,7 @@ struct ssh_tag { unsigned long max_data_size; int kex_in_progress; long next_rekey, last_rekey; + char *deferred_rekey_reason; /* points to STATIC string; don't free */ }; #define logevent(s) logevent(ssh->frontend, s) @@ -4649,7 +4650,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int n_preferred_ciphers; const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX]; const struct ssh_compress *preferred_comp; - int first_kex; + int got_session_id, activated_authconn; struct Packet *pktout; }; crState(do_ssh2_transport_state); @@ -4660,10 +4661,20 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, s->csmac_tobe = s->scmac_tobe = NULL; s->cscomp_tobe = s->sccomp_tobe = NULL; - s->first_kex = 1; + s->got_session_id = s->activated_authconn = FALSE; + /* + * Be prepared to work around the buggy MAC problem. + */ + if (ssh->remote_bugs & BUG_SSH2_HMAC) + s->maclist = buggymacs, s->nmacs = lenof(buggymacs); + else + s->maclist = macs, s->nmacs = lenof(macs); + + begin_key_exchange: { - int i; + int i, j, commalist_started; + /* * Set up the preferred key exchange. (NULL => warn below here) */ @@ -4691,10 +4702,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, break; } } - } - { - int i; /* * Set up the preferred ciphers. (NULL => warn below here) */ @@ -4724,27 +4732,14 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, break; } } - } - - /* - * Set up preferred compression. - */ - if (ssh->cfg.compression) - s->preferred_comp = &ssh_zlib; - else - s->preferred_comp = &ssh_comp_none; - /* - * Be prepared to work around the buggy MAC problem. - */ - if (ssh->remote_bugs & BUG_SSH2_HMAC) - s->maclist = buggymacs, s->nmacs = lenof(buggymacs); - else - s->maclist = macs, s->nmacs = lenof(macs); - - begin_key_exchange: - { - int i, j, commalist_started; + /* + * Set up preferred compression. + */ + if (ssh->cfg.compression) + s->preferred_comp = &ssh_zlib; + else + s->preferred_comp = &ssh_comp_none; /* * Enable queueing of outgoing auth- or connection-layer @@ -5116,7 +5111,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, verify_ssh_host_key(ssh->frontend, ssh->savedhost, ssh->savedport, ssh->hostkey->keytype, s->keystr, s->fingerprint); - if (s->first_kex) { /* don't bother logging this in rekeys */ + if (!s->got_session_id) { /* don't bother logging this in rekeys */ logevent("Host key fingerprint is:"); logevent(s->fingerprint); } @@ -5129,9 +5124,11 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, * the session id, used in session key construction and * authentication. */ - if (s->first_kex) + if (!s->got_session_id) { memcpy(ssh->v2_session_id, s->exchange_hash, sizeof(s->exchange_hash)); + s->got_session_id = TRUE; + } /* * Send SSH2_MSG_NEWKEYS. @@ -5249,14 +5246,25 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, } /* - * Key exchange is over. Schedule a timer for our next rekey. + * Key exchange is over. Loop straight back round if we have a + * deferred rekey reason. + */ + if (ssh->deferred_rekey_reason) { + logevent(ssh->deferred_rekey_reason); + pktin = NULL; + ssh->deferred_rekey_reason = NULL; + goto begin_key_exchange; + } + + /* + * Otherwise, schedule a timer for our next rekey. */ ssh->kex_in_progress = FALSE; ssh->last_rekey = GETTICKCOUNT(); if (ssh->cfg.ssh_rekey_time != 0) ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC, ssh2_timer, ssh); - + /* * If this is the first key exchange phase, we must pass the * SSH2_MSG_NEWKEYS packet to the next layer, not because it @@ -5265,10 +5273,10 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, * exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because * it would only confuse the layer above. */ - if (!s->first_kex) { + if (s->activated_authconn) { crReturn(1); } - s->first_kex = 0; + s->activated_authconn = TRUE; /* * Now we're encrypting. Begin returning 1 to the protocol main @@ -5913,8 +5921,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET } type; int gotit, need_pw, can_pubkey, can_passwd, can_keyb_inter; - int tried_pubkey_config, tried_agent, tried_keyb_inter; - int kbd_inter_running; + int tried_pubkey_config, tried_agent; + int kbd_inter_running, kbd_inter_refused; int we_are_in; int num_prompts, curr_prompt, echo; char username[100]; @@ -6043,8 +6051,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, s->tried_pubkey_config = FALSE; s->tried_agent = FALSE; - s->tried_keyb_inter = FALSE; s->kbd_inter_running = FALSE; + s->kbd_inter_refused = FALSE; /* Load the pub half of ssh->cfg.keyfile so we notice if it's in Pageant */ if (!filename_is_null(ssh->cfg.keyfile)) { int keytype; @@ -6111,6 +6119,10 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, */ if (!s->gotit) s->curr_prompt = 0; + } else if (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) { + /* FIXME: perhaps we should support this? */ + bombout(("PASSWD_CHANGEREQ not yet supported")); + crStopV; } else if (pktin->type != SSH2_MSG_USERAUTH_FAILURE) { bombout(("Strange packet received during authentication: type %d", pktin->type)); @@ -6435,10 +6447,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, } } - if (!s->method && s->can_keyb_inter && !s->tried_keyb_inter) { + if (!s->method && s->can_keyb_inter && !s->kbd_inter_refused) { s->method = AUTH_KEYBOARD_INTERACTIVE; s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE; - s->tried_keyb_inter = TRUE; ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK; ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER; @@ -6457,6 +6468,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, s->gotit = TRUE; logevent("Keyboard-interactive authentication refused"); s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE_QUIET; + s->kbd_inter_refused = TRUE; /* don't try it again */ continue; } @@ -6467,7 +6479,6 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, if (s->kbd_inter_running) { s->method = AUTH_KEYBOARD_INTERACTIVE; s->type = AUTH_TYPE_KEYBOARD_INTERACTIVE; - s->tried_keyb_inter = TRUE; ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK; ssh->pkt_ctx |= SSH2_PKTCTX_KBDINTER; @@ -7366,6 +7377,7 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle, ssh->queuelen = ssh->queuesize = 0; ssh->queueing = FALSE; ssh->qhead = ssh->qtail = NULL; + ssh->deferred_rekey_reason = NULL; *backend_handle = ssh; @@ -7503,7 +7515,7 @@ static void ssh_free(void *handle) static void ssh_reconfig(void *handle, Config *cfg) { Ssh ssh = (Ssh) handle; - char *rekeying = NULL; + char *rekeying = NULL, rekey_mandatory = FALSE; unsigned long old_max_data_size; pinger_reconfig(ssh->pinger, &ssh->cfg, cfg); @@ -7530,11 +7542,27 @@ static void ssh_reconfig(void *handle, Config *cfg) rekeying = "Initiating key re-exchange (data limit lowered)"; } - if (rekeying && !ssh->kex_in_progress) { - do_ssh2_transport(ssh, rekeying, -1, NULL); + if (ssh->cfg.compression != cfg->compression) { + rekeying = "Initiating key re-exchange (compression setting changed)"; + rekey_mandatory = TRUE; + } + + if (ssh->cfg.ssh2_des_cbc != cfg->ssh2_des_cbc || + memcmp(ssh->cfg.ssh_cipherlist, cfg->ssh_cipherlist, + sizeof(ssh->cfg.ssh_cipherlist))) { + rekeying = "Initiating key re-exchange (cipher settings changed)"; + rekey_mandatory = TRUE; } ssh->cfg = *cfg; /* STRUCTURE COPY */ + + if (rekeying) { + if (!ssh->kex_in_progress) { + do_ssh2_transport(ssh, rekeying, -1, NULL); + } else if (rekey_mandatory) { + ssh->deferred_rekey_reason = rekeying; + } + } } /*