diff -Naur hydra-5.4-src.orig/hydra-ssh2.c hydra-5.4-src/hydra-ssh2.c --- hydra-5.4-src.orig/hydra-ssh2.c 2007-03-22 14:04:29.000000000 +0000 +++ hydra-5.4-src/hydra-ssh2.c 2009-12-18 03:12:56.000000000 +0000 @@ -7,12 +7,51 @@ } #else -#warning "If compilation of hydra-ssh2 fails, you are not using v0.11. Download from http://www.0xbadc0de.be/" +#warning "If compilation of hydra-ssh2 fails, you are not using v0.4. Download from http://www.libssh.org/" #include extern char *HYDRA_EXIT; +/* try to authenticate with one password */ +static int +try_password(ssh_session ssh_session, char *password){ + int auth_state; + int i; + /* printf("ssh-trying pass \"%s\"\n",password); */ + /* We try keyboard-interactive when it's supported. kbdint is + * what openssh tries first when logging somewhere. + */ + auth_state = ssh_userauth_kbdint(ssh_session, NULL, NULL); + if(auth_state == SSH_AUTH_INFO){ + i=0; + /* we feed 10 password responses at max. Keybint is challenge-response + * based so the server could ask unrelated questions + */ + while(auth_state == SSH_AUTH_INFO && i<10){ + ssh_userauth_kbdint_setanswer(ssh_session, i, password); + auth_state = ssh_userauth_kbdint(ssh_session, NULL, NULL); + i++; + } + /* Partial authentication is specific to SSH : the password is valid but + * an other authentication token is needed (generaly private key) + */ + if(auth_state == SSH_AUTH_PARTIAL) + auth_state = SSH_AUTH_SUCCESS; + if(auth_state == SSH_AUTH_INFO) + auth_state = SSH_AUTH_ERROR; + return auth_state; + } + if(auth_state == SSH_AUTH_ERROR) + return auth_state; + /* Keyboard-interactive is not supported so we run through the password + * method */ + auth_state = ssh_userauth_password(ssh_session, NULL, password); + if(auth_state == SSH_AUTH_PARTIAL) + auth_state = SSH_AUTH_SUCCESS; + return auth_state; +} + int start_ssh2(int s, unsigned long int ip, int port, unsigned char options, char *miscptr, FILE * fp) { @@ -21,17 +60,17 @@ char *buf; char *rc; struct sockaddr_in targetip; - SSH_SESSION *ssh_session; - SSH_OPTIONS *ssh_opt; + ssh_session ssh_session; + char buffer[64], firstlogin[128]; int auth_state; - int i = 0; + const int btrue = 1; if (strlen(login = hydra_get_next_login()) == 0) login = empty; if (strlen(pass = hydra_get_next_password()) == 0) pass = empty; - ssh_opt=options_new(); + ssh_session=ssh_new(); memset(&targetip, 0, sizeof(targetip)); memcpy(&targetip.sin_addr.s_addr, &ip, 4); targetip.sin_family = AF_INET; @@ -41,16 +80,18 @@ buf = malloc(20); inet_ntop(AF_INET, &targetip.sin_addr, buf, 20); #endif - options_set_wanted_method(ssh_opt,KEX_COMP_C_S,"none"); - options_set_wanted_method(ssh_opt,KEX_COMP_S_C,"none"); - options_set_port(ssh_opt, port); - options_set_host(ssh_opt, buf); - options_set_username(ssh_opt, login); - - if ((ssh_session = ssh_connect(ssh_opt)) == NULL) { + snprintf(firstlogin,sizeof(firstlogin),"%s",login); + ssh_options_set(ssh_session, SSH_OPTIONS_SSH1, &btrue); + ssh_options_set(ssh_session, SSH_OPTIONS_PORT, &port); + ssh_options_set(ssh_session, SSH_OPTIONS_HOST, buf); + ssh_options_set(ssh_session, SSH_OPTIONS_USER, login); + /* printf("ssh-connecting with login \"%s\"\n",login); */ + if (ssh_connect(ssh_session) == SSH_ERROR) { rc = ssh_get_error(ssh_session); if ((rc != NULL) && (rc[0] != '\0')) { - if (strncmp("connect:", ssh_get_error(ssh_session), strlen("connect:")) == 0) + snprintf(buffer,sizeof(buffer),"%s",rc); + ssh_disconnect(ssh_session); + if (strncmp("connect:", buffer, strlen("connect:")) == 0) return 3; else return 4; @@ -60,43 +101,54 @@ free(buf); buf = NULL; #endif - - do { - /* why this crap? */ - auth_state = ssh_userauth_kbdint(ssh_session, login, NULL); - while (i < 10 && auth_state == SSH_AUTH_INFO) { - ssh_userauth_kbdint_setanswer(ssh_session, i, pass); - auth_state = ssh_userauth_kbdint(ssh_session, login, NULL); - i++; - } - - if (auth_state == SSH_AUTH_SUCCESS || ssh_userauth_password(ssh_session, login, pass) == SSH_AUTH_SUCCESS) { - ssh_disconnect(ssh_session); /* this automagically frees the ssh_opt buffer */ - hydra_report_found_host(port, ip, "ssh2", fp); - hydra_completed_pair_found(); - if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) - return 2; - /* free(ssh_opt); */ /* DOUBLE FREE ! */ + /* None method is important since it can flag passwordless servers */ + auth_state=ssh_userauth_none(ssh_session, login); + if(auth_state == SSH_AUTH_SUCCESS){ + /* passwordless server */ + hydra_report_found_host(port, ip, "ssh2", fp); + hydra_completed_pair_found(); + ssh_disconnect(ssh_session); + if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) + return 2; + else return 1; - } else { - if (ssh_error_code(ssh_session) == 1) { - hydra_completed_pair(); + } + + do { + auth_state=try_password(ssh_session, pass); + if (auth_state == SSH_AUTH_SUCCESS) { + ssh_disconnect(ssh_session); /* this automagically frees the ssh_opt buffer */ + hydra_report_found_host(port, ip, "ssh2", fp); + hydra_completed_pair_found(); if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) return 2; + return 1; } else { - ssh_disconnect(ssh_session); /* this automagically frees the ssh_opt buffer */ - hydra_completed_pair(); /* really? */ - if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0) + if (auth_state == SSH_AUTH_DENIED) { + hydra_completed_pair(); + if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0){ + ssh_disconnect(ssh_session); return 2; - /* free(ssh_opt); */ /* DOUBLE FREE ! */ + } + /* set a new password to try */ + login=hydra_get_next_login(); + if(strcmp(login,firstlogin) != 0){ + /* we can't try a new login without a new session. */ + ssh_disconnect(ssh_session); + //hydra_completed_pair_skip(); + return 1; + } + pass=hydra_get_next_password(); + /* try again using same session */ + } else { + ssh_disconnect(ssh_session); /* this automagically frees the ssh_opt buffer */ + /* there was an error. The password was not really tried.*/ + //hydra_completed_pair_skip(); return 1; } } } while(1); - /* not reached */ - - /* free(ssh_opt); */ /* risk of double free */ return 1; }