# HG changeset patch # User Matt Johnston # Date 1389965967 -28800 # Node ID ff597bf2cfb0c65d946050079486d2f3bcd126c0 # Parent f05107560aa946688710aefa48d595a6a1483a8a DROPBEAR_CLI_AUTH_IMMEDIATE fixed, now enabled by default diff -r f05107560aa9 -r ff597bf2cfb0 cli-auth.c --- a/cli-auth.c Wed Dec 11 21:50:33 2013 +0800 +++ b/cli-auth.c Fri Jan 17 21:39:27 2014 +0800 @@ -41,16 +41,6 @@ /* Send a "none" auth request to get available methods */ void cli_auth_getmethods() { TRACE(("enter cli_auth_getmethods")) -#ifdef CLI_IMMEDIATE_AUTH - ses.authstate.authtypes = AUTH_TYPE_PUBKEY; - if (getenv(DROPBEAR_PASSWORD_ENV)) { - ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT; - } - if (cli_auth_try() == DROPBEAR_SUCCESS) { - TRACE(("skipped initial none auth query")) - return; - } -#endif CHECKCLEARTOWRITE(); buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); buf_putstring(ses.writepayload, cli_opts.username, @@ -60,6 +50,18 @@ buf_putstring(ses.writepayload, "none", 4); /* 'none' method */ encrypt_packet(); + +#ifdef DROPBEAR_CLI_IMMEDIATE_AUTH + ses.authstate.authtypes = AUTH_TYPE_PUBKEY; + if (getenv(DROPBEAR_PASSWORD_ENV)) { + ses.authstate.authtypes |= AUTH_TYPE_PASSWORD | AUTH_TYPE_INTERACT; + } + if (cli_auth_try() == DROPBEAR_SUCCESS) { + TRACE(("skipped initial none auth query")) + /* Note that there will be two auth responses in-flight */ + cli_ses.ignore_next_auth_response = 1; + } +#endif TRACE(("leave cli_auth_getmethods")) } @@ -150,31 +152,46 @@ TRACE(("<- MSG_USERAUTH_FAILURE")) TRACE(("enter recv_msg_userauth_failure")) + if (ses.authstate.authdone) { + TRACE(("leave recv_msg_userauth_failure, already authdone.")) + return; + } + if (cli_ses.state != USERAUTH_REQ_SENT) { /* Perhaps we should be more fatal? */ dropbear_exit("Unexpected userauth failure"); } + /* When DROPBEAR_CLI_IMMEDIATE_AUTH is set there will be an initial response for + the "none" auth request, and then a response to the immediate auth request. + We need to be careful handling them. */ + if (cli_ses.ignore_next_auth_response) { + TRACE(("ignore next response, state set to USERAUTH_REQ_SENT")) + cli_ses.state = USERAUTH_REQ_SENT; + } else { + cli_ses.state = USERAUTH_FAIL_RCVD; + cli_ses.lastauthtype = AUTH_TYPE_NONE; #ifdef ENABLE_CLI_PUBKEY_AUTH - /* If it was a pubkey auth request, we should cross that key - * off the list. */ - if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) { - cli_pubkeyfail(); - } + /* If it was a pubkey auth request, we should cross that key + * off the list. */ + if (cli_ses.lastauthtype == AUTH_TYPE_PUBKEY) { + cli_pubkeyfail(); + } #endif #ifdef ENABLE_CLI_INTERACT_AUTH - /* If we get a failure message for keyboard interactive without - * receiving any request info packet, then we don't bother trying - * keyboard interactive again */ - if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT - && !cli_ses.interact_request_received) { - TRACE(("setting auth_interact_failed = 1")) - cli_ses.auth_interact_failed = 1; + /* If we get a failure message for keyboard interactive without + * receiving any request info packet, then we don't bother trying + * keyboard interactive again */ + if (cli_ses.lastauthtype == AUTH_TYPE_INTERACT + && !cli_ses.interact_request_received) { + TRACE(("setting auth_interact_failed = 1")) + cli_ses.auth_interact_failed = 1; + } +#endif } -#endif - cli_ses.lastauthtype = AUTH_TYPE_NONE; + cli_ses.ignore_next_auth_response = 0; methods = buf_getstring(ses.payload, &methlen); @@ -227,13 +244,14 @@ } m_free(methods); - - cli_ses.state = USERAUTH_FAIL_RCVD; TRACE(("leave recv_msg_userauth_failure")) } void recv_msg_userauth_success() { + /* This function can validly get called multiple times + if DROPBEAR_CLI_IMMEDIATE_AUTH is set */ + TRACE(("received msg_userauth_success")) /* Note: in delayed-zlib mode, setting authdone here * will enable compression in the transport layer */ diff -r f05107560aa9 -r ff597bf2cfb0 cli-session.c --- a/cli-session.c Wed Dec 11 21:50:33 2013 +0800 +++ b/cli-session.c Fri Jan 17 21:39:27 2014 +0800 @@ -228,6 +228,10 @@ cli_ses.state = USERAUTH_REQ_SENT; TRACE(("leave cli_sessionloop: sent userauth methods req")) return; + + case USERAUTH_REQ_SENT: + TRACE(("leave cli_sessionloop: waiting, req_sent")) + return; case USERAUTH_FAIL_RCVD: if (cli_auth_try() == DROPBEAR_FAILURE) { diff -r f05107560aa9 -r ff597bf2cfb0 common-kex.c --- a/common-kex.c Wed Dec 11 21:50:33 2013 +0800 +++ b/common-kex.c Fri Jan 17 21:39:27 2014 +0800 @@ -792,6 +792,11 @@ hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize)); buf_setlen(ses.hash, hash_desc->hashsize); +#ifdef DEBUG_KEXHASH + printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len); + printhex("kexhash", ses.hash->data, ses.hash->len); +#endif + buf_burn(ses.kexhashbuf); buf_free(ses.kexhashbuf); ses.kexhashbuf = NULL; diff -r f05107560aa9 -r ff597bf2cfb0 dbutil.c --- a/dbutil.c Wed Dec 11 21:50:33 2013 +0800 +++ b/dbutil.c Fri Jan 17 21:39:27 2014 +0800 @@ -812,6 +812,10 @@ /* make sure that the socket closes */ void m_close(int fd) { + if (fd == -1) { + return; + } + int val; do { val = close(fd); diff -r f05107560aa9 -r ff597bf2cfb0 options.h --- a/options.h Wed Dec 11 21:50:33 2013 +0800 +++ b/options.h Fri Jan 17 21:39:27 2014 +0800 @@ -222,13 +222,6 @@ * return the password on standard output */ /*#define ENABLE_CLI_ASKPASS_HELPER*/ -/* Send a real auth request first rather than requesting a list of available methods. - * It saves a network round trip at login but prevents immediate login to - * accounts with no password, and might be rejected by some strict servers (none - * encountered yet) - hence it isn't enabled by default. */ -/* #define CLI_IMMEDIATE_AUTH */ - - /* Source for randomness. This must be able to provide hundreds of bytes per SSH * connection without blocking. In addition /dev/random is used for seeding * rsa/dss key generation */ diff -r f05107560aa9 -r ff597bf2cfb0 session.h --- a/session.h Wed Dec 11 21:50:33 2013 +0800 +++ b/session.h Fri Jan 17 21:39:27 2014 +0800 @@ -233,6 +233,7 @@ typedef enum { STATE_NOTHING, + USERAUTH_WAIT, USERAUTH_REQ_SENT, USERAUTH_FAIL_RCVD, USERAUTH_SUCCESS_RCVD, @@ -267,6 +268,7 @@ int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD, for the last type of auth we tried */ + int ignore_next_auth_response; #ifdef ENABLE_CLI_INTERACT_AUTH int auth_interact_failed; /* flag whether interactive auth can still be used */ diff -r f05107560aa9 -r ff597bf2cfb0 sysoptions.h --- a/sysoptions.h Wed Dec 11 21:50:33 2013 +0800 +++ b/sysoptions.h Fri Jan 17 21:39:27 2014 +0800 @@ -176,6 +176,12 @@ accept for keyb-interactive auth */ +/* Send a real auth request immediately after sending a query for the available methods. + * It saves a network round trip at login. + * If problems are encountered it can be disabled here. */ + #define CLI_IMMEDIATE_AUTH + + #if defined(DROPBEAR_AES256) || defined(DROPBEAR_AES128) #define DROPBEAR_AES #endif