diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2000-10-11 20:14:41 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2000-10-11 20:14:41 +0000 |
commit | b0db21bafca83b9f300b0f6004b89abd7fc38dcf (patch) | |
tree | fa46ea536f7ff3c12d1ab84feccac32a742d6b99 /usr.bin | |
parent | ebff282038cb5fae7bfed8e97cfcc1e3a5d53625 (diff) |
add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/ssh/auth.h | 20 | ||||
-rw-r--r-- | usr.bin/ssh/auth2-skey.c | 104 | ||||
-rw-r--r-- | usr.bin/ssh/auth2.c | 349 | ||||
-rw-r--r-- | usr.bin/ssh/cli.c | 196 | ||||
-rw-r--r-- | usr.bin/ssh/cli.h | 14 | ||||
-rw-r--r-- | usr.bin/ssh/lib/Makefile | 3 | ||||
-rw-r--r-- | usr.bin/ssh/readconf.c | 19 | ||||
-rw-r--r-- | usr.bin/ssh/readconf.h | 4 | ||||
-rw-r--r-- | usr.bin/ssh/readpass.c | 82 | ||||
-rw-r--r-- | usr.bin/ssh/servconf.c | 12 | ||||
-rw-r--r-- | usr.bin/ssh/servconf.h | 3 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.h | 4 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect2.c | 162 | ||||
-rw-r--r-- | usr.bin/ssh/sshd/Makefile | 2 | ||||
-rw-r--r-- | usr.bin/ssh/sshd_config | 1 |
15 files changed, 758 insertions, 217 deletions
diff --git a/usr.bin/ssh/auth.h b/usr.bin/ssh/auth.h index 65bf7ae1012..c4a8ac54407 100644 --- a/usr.bin/ssh/auth.h +++ b/usr.bin/ssh/auth.h @@ -24,17 +24,29 @@ #ifndef AUTH_H #define AUTH_H +typedef struct Authctxt Authctxt; +struct Authctxt { + int success; + int valid; + int attempt; + char *user; + char *service; + struct passwd *pw; +}; + void do_authentication(void); void do_authentication2(void); -struct passwd * -auth_get_user(void); +void userauth_log(Authctxt *authctxt, int authenticated, char *method); +void userauth_reply(Authctxt *authctxt, int authenticated); + +int auth2_skey(Authctxt *authctxt); -int allowed_user(struct passwd * pw); +int allowed_user(struct passwd * pw); +struct passwd * auth_get_user(void); #define AUTH_FAIL_MAX 6 #define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2) #define AUTH_FAIL_MSG "Too many authentication failures for %.100s" #endif - diff --git a/usr.bin/ssh/auth2-skey.c b/usr.bin/ssh/auth2-skey.c new file mode 100644 index 00000000000..9de08fc09cf --- /dev/null +++ b/usr.bin/ssh/auth2-skey.c @@ -0,0 +1,104 @@ +#include "includes.h" +RCSID("$OpenBSD: auth2-skey.c,v 1.1 2000/10/11 20:14:38 markus Exp $"); + +#include "ssh.h" +#include "ssh2.h" +#include "auth.h" +#include "packet.h" +#include "xmalloc.h" +#include "dispatch.h" + +void send_userauth_into_request(Authctxt *authctxt, int echo); +void input_userauth_info_response(int type, int plen, void *ctxt); + +/* + * try skey authentication, always return -1 (= postponed) since we have to + * wait for the s/key response. + */ +int +auth2_skey(Authctxt *authctxt) +{ + send_userauth_into_request(authctxt, 0); + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &input_userauth_info_response); + return -1; +} + +void +send_userauth_into_request(Authctxt *authctxt, int echo) +{ + int retval = -1; + struct skey skey; + char challenge[SKEY_MAX_CHALLENGE]; + char *fake; + + if (authctxt->user == NULL) + fatal("send_userauth_into_request: internal error: no user"); + + /* get skey challenge */ + if (authctxt->valid) + retval = skeychallenge(&skey, authctxt->user, challenge); + + if (retval == -1) { + fake = skey_fake_keyinfo(authctxt->user); + strlcpy(challenge, fake, sizeof challenge); + } + /* send our info request */ + packet_start(SSH2_MSG_USERAUTH_INFO_REQUEST); + packet_put_cstring("S/Key Authentication"); /* Name */ + packet_put_cstring(challenge); /* Instruction */ + packet_put_cstring(""); /* Language */ + packet_put_int(1); /* Number of prompts */ + packet_put_cstring(echo ? + "Response [Echo]: ": "Response: "); /* Prompt */ + packet_put_char(echo); /* Echo */ + packet_send(); + packet_write_wait(); + memset(challenge, 'c', sizeof challenge); +} + +void +input_userauth_info_response(int type, int plen, void *ctxt) +{ + Authctxt *authctxt = ctxt; + int authenticated = 0; + unsigned int nresp, rlen; + char *resp, *method; + + if (authctxt == NULL) + fatal("input_userauth_info_response: no authentication context"); + + if (authctxt->attempt++ >= AUTH_FAIL_MAX) + packet_disconnect("too many failed userauth_requests"); + + nresp = packet_get_int(); + if (nresp == 1) { + /* we only support s/key and assume s/key for nresp == 1 */ + method = "s/key"; + resp = packet_get_string(&rlen); + packet_done(); + if (strlen(resp) == 0) { + /* + * if we received a null response, resend prompt with + * echo enabled + */ + authenticated = -1; + userauth_log(authctxt, authenticated, method); + send_userauth_into_request(authctxt, 1); + } else { + /* verify skey response */ + if (authctxt->valid && + skey_haskey(authctxt->pw->pw_name) == 0 && + skey_passcheck(authctxt->pw->pw_name, resp) != -1) { + authenticated = 1; + } else { + authenticated = 0; + } + memset(resp, 'r', rlen); + /* unregister callback */ + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL); + userauth_log(authctxt, authenticated, method); + userauth_reply(authctxt, authenticated); + } + xfree(resp); + } +} diff --git a/usr.bin/ssh/auth2.c b/usr.bin/ssh/auth2.c index 7006bfeab06..2d05a2f2e93 100644 --- a/usr.bin/ssh/auth2.c +++ b/usr.bin/ssh/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.17 2000/10/11 19:59:52 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.18 2000/10/11 20:14:38 markus Exp $"); #include <openssl/dsa.h> #include <openssl/rsa.h> @@ -57,49 +57,72 @@ extern ServerOptions options; extern unsigned char *session_id2; extern int session_id2_len; +static Authctxt *x_authctxt = NULL; +static int one = 1; + +typedef struct Authmethod Authmethod; +struct Authmethod { + char *name; + int (*userauth)(Authctxt *authctxt); + int *enabled; +}; + /* protocol */ void input_service_request(int type, int plen, void *ctxt); void input_userauth_request(int type, int plen, void *ctxt); void protocol_error(int type, int plen, void *ctxt); -/* auth */ -int ssh2_auth_none(struct passwd *pw); -int ssh2_auth_password(struct passwd *pw); -int ssh2_auth_pubkey(struct passwd *pw, char *service); /* helper */ -struct passwd* auth_set_user(char *u, char *s); +Authmethod *authmethod_lookup(const char *name); +struct passwd *pwcopy(struct passwd *pw); int user_dsa_key_allowed(struct passwd *pw, Key *key); +char *authmethods_get(void); -typedef struct Authctxt Authctxt; -struct Authctxt { - char *user; - char *service; - struct passwd pw; - int valid; +/* auth */ +int userauth_none(Authctxt *authctxt); +int userauth_passwd(Authctxt *authctxt); +int userauth_pubkey(Authctxt *authctxt); +int userauth_kbdint(Authctxt *authctxt); + +Authmethod authmethods[] = { + {"none", + userauth_none, + &one}, + {"publickey", + userauth_pubkey, + &options.dsa_authentication}, + {"keyboard-interactive", + userauth_kbdint, + &options.kbd_interactive_authentication}, + {"password", + userauth_passwd, + &options.password_authentication}, + {NULL, NULL, NULL} }; -static Authctxt *authctxt = NULL; -static int userauth_success = 0; /* - * loop until userauth_success == TRUE + * loop until authctxt->success == TRUE */ void do_authentication2() { - /* turn off skey/kerberos, not supported by SSH2 */ -#ifdef SKEY - options.skey_authentication = 0; -#endif + Authctxt *authctxt = xmalloc(sizeof(*authctxt)); + memset(authctxt, 'a', sizeof(*authctxt)); + authctxt->valid = 0; + authctxt->attempt = 0; + authctxt->success = 0; + x_authctxt = authctxt; /*XXX*/ + #ifdef KRB4 + /* turn off kerberos, not supported by SSH2 */ options.kerberos_authentication = 0; #endif - dispatch_init(&protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); - dispatch_run(DISPATCH_BLOCK, &userauth_success, NULL); + dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); do_authenticated2(); } @@ -116,13 +139,17 @@ protocol_error(int type, int plen, void *ctxt) void input_service_request(int type, int plen, void *ctxt) { + Authctxt *authctxt = ctxt; unsigned int len; int accept = 0; char *service = packet_get_string(&len); packet_done(); + if (authctxt == NULL) + fatal("input_service_request: no authctxt"); + if (strcmp(service, "ssh-userauth") == 0) { - if (!userauth_success) { + if (!authctxt->success) { accept = 1; /* now we can handle user-auth requests */ dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); @@ -145,45 +172,87 @@ input_service_request(int type, int plen, void *ctxt) void input_userauth_request(int type, int plen, void *ctxt) { - static void (*authlog) (const char *fmt,...) = verbose; - static int attempt = 0; - unsigned int len; + Authctxt *authctxt = ctxt; + Authmethod *m = NULL; + char *user, *service, *method; int authenticated = 0; - char *user, *service, *method, *authmsg = NULL; - struct passwd *pw; - if (++attempt == AUTH_FAIL_MAX) + if (authctxt == NULL) + fatal("input_userauth_request: no authctxt"); + if (authctxt->attempt++ >= AUTH_FAIL_MAX) packet_disconnect("too many failed userauth_requests"); - user = packet_get_string(&len); - service = packet_get_string(&len); - method = packet_get_string(&len); + user = packet_get_string(NULL); + service = packet_get_string(NULL); + method = packet_get_string(NULL); debug("userauth-request for user %s service %s method %s", user, service, method); - - /* XXX we only allow the ssh-connection service */ - pw = auth_set_user(user, service); - if (pw && strcmp(service, "ssh-connection")==0) { - if (strcmp(method, "none") == 0) { - authenticated = ssh2_auth_none(pw); - } else if (strcmp(method, "password") == 0) { - authenticated = ssh2_auth_password(pw); - } else if (strcmp(method, "publickey") == 0) { - authenticated = ssh2_auth_pubkey(pw, service); + debug("attempt #%d", authctxt->attempt); + + if (authctxt->attempt == 1) { + /* setup auth context */ + struct passwd *pw = NULL; + setproctitle("%s", user); + pw = getpwnam(user); + if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) { + authctxt->pw = pwcopy(pw); + authctxt->valid = 1; + debug2("input_userauth_request: setting up authctxt for %s", user); + } else { + log("input_userauth_request: illegal user %s", user); } + authctxt->user = xstrdup(user); + authctxt->service = xstrdup(service); + } else if (authctxt->valid) { + if (strcmp(user, authctxt->user) != 0 || + strcmp(service, authctxt->service) != 0) { + log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)", + user, service, authctxt->user, authctxt->service); + authctxt->valid = 0; + } + } + + m = authmethod_lookup(method); + if (m != NULL) { + debug2("input_userauth_request: try method %s", method); + authenticated = m->userauth(authctxt); + } else { + debug2("input_userauth_request: unsupported method %s", method); + } + if (!authctxt->valid && authenticated == 1) { + log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method); + authenticated = 0; } - if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { + + /* Special handling for root */ + if (authenticated == 1 && + authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) { authenticated = 0; - log("ROOT LOGIN REFUSED FROM %.200s", - get_canonical_hostname()); + log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname()); } + /* Log before sending the reply */ + userauth_log(authctxt, authenticated, method); + userauth_reply(authctxt, authenticated); + + xfree(service); + xfree(user); + xfree(method); +} + + +void +userauth_log(Authctxt *authctxt, int authenticated, char *method) +{ + void (*authlog) (const char *fmt,...) = verbose; + char *user = NULL, *authmsg = NULL; + /* Raise logging level */ if (authenticated == 1 || - attempt == AUTH_FAIL_LOG || + !authctxt->valid || + authctxt->attempt >= AUTH_FAIL_LOG || strcmp(method, "password") == 0) authlog = log; - /* Log before sending the reply */ if (authenticated == 1) { authmsg = "Accepted"; } else if (authenticated == 0) { @@ -191,13 +260,24 @@ input_userauth_request(int type, int plen, void *ctxt) } else { authmsg = "Postponed"; } + + if (authctxt->valid) { + user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user; + } else { + user = "NOUSER"; + } + authlog("%s %s for %.200s from %.200s port %d ssh2", - authmsg, - method, - pw && pw->pw_uid == 0 ? "ROOT" : user, - get_remote_ipaddr(), - get_remote_port()); + authmsg, + method, + user, + get_remote_ipaddr(), + get_remote_port()); +} +void +userauth_reply(Authctxt *authctxt, int authenticated) +{ /* XXX todo: check if multiple auth methods are needed */ if (authenticated == 1) { /* turn off userauth */ @@ -206,28 +286,33 @@ input_userauth_request(int type, int plen, void *ctxt) packet_send(); packet_write_wait(); /* now we can break out */ - userauth_success = 1; + authctxt->success = 1; } else if (authenticated == 0) { + char *methods = authmethods_get(); packet_start(SSH2_MSG_USERAUTH_FAILURE); - packet_put_cstring("publickey,password"); /* XXX dynamic */ - packet_put_char(0); /* XXX partial success, unused */ + packet_put_cstring(methods); + packet_put_char(0); /* XXX partial success, unused */ packet_send(); packet_write_wait(); + xfree(methods); + } else { + /* do nothing, we did already send a reply */ } - - xfree(service); - xfree(user); - xfree(method); } int -ssh2_auth_none(struct passwd *pw) +userauth_none(Authctxt *authctxt) { + /* disable method "none", only allowed one time */ + Authmethod *m = authmethod_lookup("none"); + if (m != NULL) + m->enabled = NULL; packet_done(); - return auth_password(pw, ""); + return authctxt->valid ? auth_password(authctxt->pw, "") : 0; } + int -ssh2_auth_password(struct passwd *pw) +userauth_passwd(Authctxt *authctxt) { char *password; int authenticated = 0; @@ -238,15 +323,38 @@ ssh2_auth_password(struct passwd *pw) log("password change not supported"); password = packet_get_string(&len); packet_done(); - if (options.password_authentication && - auth_password(pw, password) == 1) + if (authctxt->valid && + auth_password(authctxt->pw, password) == 1) authenticated = 1; memset(password, 0, len); xfree(password); return authenticated; } + int -ssh2_auth_pubkey(struct passwd *pw, char *service) +userauth_kbdint(Authctxt *authctxt) +{ + int authenticated = 0; + char *lang = NULL; + char *devs = NULL; + + lang = packet_get_string(NULL); + devs = packet_get_string(NULL); + packet_done(); + + debug("keyboard-interactive language %s devs %s", lang, devs); +#ifdef SKEY + /* XXX hardcoded, we should look at devs */ + if (options.skey_authentication != 0) + authenticated = auth2_skey(authctxt); +#endif + xfree(lang); + xfree(devs); + return authenticated; +} + +int +userauth_pubkey(Authctxt *authctxt) { Buffer b; Key *key; @@ -255,15 +363,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service) int have_sig; int authenticated = 0; - if (options.dsa_authentication == 0) { - debug("pubkey auth disabled"); + if (!authctxt->valid) { + debug2("userauth_pubkey: disabled because of invalid user"); return 0; } have_sig = packet_get_char(); pkalg = packet_get_string(&alen); if (strcmp(pkalg, KEX_DSS) != 0) { - xfree(pkalg); log("bad pkalg %s", pkalg); /*XXX*/ + xfree(pkalg); return 0; } pkblob = packet_get_string(&blen); @@ -280,11 +388,11 @@ ssh2_auth_pubkey(struct passwd *pw, char *service) } /* reconstruct packet */ buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, pw->pw_name); + buffer_put_cstring(&b, authctxt->user); buffer_put_cstring(&b, datafellows & SSH_BUG_PUBKEYAUTH ? "ssh-userauth" : - service); + authctxt->service); buffer_put_cstring(&b, "publickey"); buffer_put_char(&b, have_sig); buffer_put_cstring(&b, KEX_DSS); @@ -293,15 +401,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service) buffer_dump(&b); #endif /* test for correct signature */ - if (user_dsa_key_allowed(pw, key) && + if (user_dsa_key_allowed(authctxt->pw, key) && dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) authenticated = 1; buffer_clear(&b); xfree(sig); } else { + debug("test whether pkalg/pkblob are acceptable"); packet_done(); - debug("test key..."); - /* test whether pkalg/pkblob are acceptable */ + /* XXX fake reply and always send PK_OK ? */ /* * XXX this allows testing whether a user is allowed @@ -310,7 +418,7 @@ ssh2_auth_pubkey(struct passwd *pw, char *service) * if a user is not allowed to login. is this an * issue? -markus */ - if (user_dsa_key_allowed(pw, key)) { + if (user_dsa_key_allowed(authctxt->pw, key)) { packet_start(SSH2_MSG_USERAUTH_PK_OK); packet_put_string(pkalg, alen); packet_put_string(pkblob, blen); @@ -328,49 +436,60 @@ ssh2_auth_pubkey(struct passwd *pw, char *service) return authenticated; } -/* set and get current user */ +/* get current user */ struct passwd* auth_get_user(void) { - return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL; + return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL; } -struct passwd* -auth_set_user(char *u, char *s) +#define DELIM "," + +char * +authmethods_get(void) { - struct passwd *pw, *copy; - - if (authctxt == NULL) { - authctxt = xmalloc(sizeof(*authctxt)); - authctxt->valid = 0; - authctxt->user = xstrdup(u); - authctxt->service = xstrdup(s); - setproctitle("%s", u); - pw = getpwnam(u); - if (!pw || !allowed_user(pw)) { - log("auth_set_user: illegal user %s", u); - return NULL; + Authmethod *method = NULL; + unsigned int size = 0; + char *list; + + for (method = authmethods; method->name != NULL; method++) { + if (strcmp(method->name, "none") == 0) + continue; + if (method->enabled != NULL && *(method->enabled) != 0) { + if (size != 0) + size += strlen(DELIM); + size += strlen(method->name); } - copy = &authctxt->pw; - memset(copy, 0, sizeof(*copy)); - copy->pw_name = xstrdup(pw->pw_name); - copy->pw_passwd = xstrdup(pw->pw_passwd); - copy->pw_uid = pw->pw_uid; - copy->pw_gid = pw->pw_gid; - copy->pw_class = xstrdup(pw->pw_class); - copy->pw_dir = xstrdup(pw->pw_dir); - copy->pw_shell = xstrdup(pw->pw_shell); - authctxt->valid = 1; - } else { - if (strcmp(u, authctxt->user) != 0 || - strcmp(s, authctxt->service) != 0) { - log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)", - u, s, authctxt->user, authctxt->service); - return NULL; + } + size++; /* trailing '\0' */ + list = xmalloc(size); + list[0] = '\0'; + + for (method = authmethods; method->name != NULL; method++) { + if (strcmp(method->name, "none") == 0) + continue; + if (method->enabled != NULL && *(method->enabled) != 0) { + if (list[0] != '\0') + strlcat(list, DELIM, size); + strlcat(list, method->name, size); } } - return auth_get_user(); + return list; +} + +Authmethod * +authmethod_lookup(const char *name) +{ + Authmethod *method = NULL; + if (name != NULL) + for (method = authmethods; method->name != NULL; method++) + if (method->enabled != NULL && + *(method->enabled) != 0 && + strcmp(name, method->name) == 0) + return method; + debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); + return NULL; } /* return 1 if user allows given key */ @@ -385,6 +504,9 @@ user_dsa_key_allowed(struct passwd *pw, Key *key) struct stat st; Key *found; + if (pw == NULL) + return 0; + /* Temporarily use the user's uid. */ temporarily_use_uid(pw->pw_uid); @@ -490,3 +612,18 @@ user_dsa_key_allowed(struct passwd *pw, Key *key) key_free(found); return found_key; } + +struct passwd * +pwcopy(struct passwd *pw) +{ + struct passwd *copy = xmalloc(sizeof(*copy)); + memset(copy, 0, sizeof(*copy)); + copy->pw_name = xstrdup(pw->pw_name); + copy->pw_passwd = xstrdup(pw->pw_passwd); + copy->pw_uid = pw->pw_uid; + copy->pw_gid = pw->pw_gid; + copy->pw_class = xstrdup(pw->pw_class); + copy->pw_dir = xstrdup(pw->pw_dir); + copy->pw_shell = xstrdup(pw->pw_shell); + return copy; +} diff --git a/usr.bin/ssh/cli.c b/usr.bin/ssh/cli.c new file mode 100644 index 00000000000..efc3af58b4a --- /dev/null +++ b/usr.bin/ssh/cli.c @@ -0,0 +1,196 @@ +#include "includes.h" +RCSID("$Id: cli.c,v 1.1 2000/10/11 20:14:39 markus Exp $"); + +#include "xmalloc.h" +#include "ssh.h" +#include <vis.h> + +static int cli_input = -1; +static int cli_output = -1; +static int cli_from_stdin = 0; + +sigset_t oset; +sigset_t nset; +struct sigaction nsa; +struct sigaction osa; +struct termios ntio; +struct termios otio; +int echo_modified; + +volatile int intr; + +static int +cli_open(int from_stdin) +{ + if (cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin) + return 1; + + if (from_stdin) { + if (!cli_from_stdin && cli_input >= 0) { + (void)close(cli_input); + } + cli_input = STDIN_FILENO; + cli_output = STDERR_FILENO; + } else { + cli_input = cli_output = open("/dev/tty", O_RDWR); + if (cli_input < 0) + fatal("You have no controlling tty. Cannot read passphrase."); + } + + cli_from_stdin = from_stdin; + + return cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin; +} + +static void +cli_close() +{ + if (!cli_from_stdin && cli_input >= 0) + close(cli_input); + cli_input = -1; + cli_output = -1; + cli_from_stdin = 0; + return; +} + +void +intrcatch() +{ + intr = 1; +} + +static void +cli_echo_disable() +{ + sigemptyset(&nset); + sigaddset(&nset, SIGTSTP); + (void) sigprocmask(SIG_BLOCK, &nset, &oset); + + intr = 0; + + memset(&nsa, 0, sizeof(nsa)); + nsa.sa_handler = intrcatch; + (void) sigaction(SIGINT, &nsa, &osa); + + echo_modified = 0; + if (tcgetattr(cli_input, &otio) == 0 && (otio.c_lflag & ECHO)) { + echo_modified = 1; + ntio = otio; + ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); + (void) tcsetattr(cli_input, TCSANOW, &ntio); + } + return; +} + +static void +cli_echo_restore() +{ + if (echo_modified != 0) { + tcsetattr(cli_input, TCSANOW, &otio); + echo_modified = 0; + } + + (void) sigprocmask(SIG_SETMASK, &oset, NULL); + (void) sigaction(SIGINT, &osa, NULL); + + if (intr != 0) { + kill(getpid(), SIGINT); + sigemptyset(&nset); + /* XXX tty has not neccessarily drained by now? */ + sigsuspend(&nset); + intr = 0; + } + return; +} + +static int +cli_read(char* buf, int size, int echo) +{ + char ch = 0; + int i = 0; + + if (!echo) + cli_echo_disable(); + + while (ch != '\n') { + if (read(cli_input, &ch, 1) != 1) + break; + if (ch == '\n' || intr != 0) + break; + if (i < size) + buf[i++] = ch; + } + buf[i] = '\0'; + + if (!echo) + cli_echo_restore(); + if (!intr && !echo) + (void) write(cli_output, "\n", 1); + return i; +} + +static int +cli_write(char* buf, int size) +{ + int i, len, pos, ret = 0; + char *output, *p; + + output = xmalloc(4*size); + for (p = output, i = 0; i < size; i++) { + if (buf[i] == '\n') + *p++ = buf[i]; + else + p = vis(p, buf[i], 0, 0); + } + len = p - output; + + for (pos = 0; pos < len; pos += ret) { + ret = write(cli_output, output + pos, len - pos); + if (ret == -1) + return -1; + } + return 0; +} + +/* + * Presents a prompt and returns the response allocated with xmalloc(). + * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo + * of response depending on arg. Tries to ensure that no other userland + * buffer is storing the response. + */ +char* +cli_read_passphrase(char* prompt, int from_stdin, int echo_enable) +{ + char buf[BUFSIZ]; + char* p; + + if (!cli_open(from_stdin)) + fatal("Cannot read passphrase."); + + fflush(stdout); + + cli_write(prompt, strlen(prompt)); + cli_read(buf, sizeof buf, echo_enable); + + cli_close(); + + p = xstrdup(buf); + memset(buf, 0, sizeof(buf)); + return (p); +} + +char* +cli_prompt(char* prompt, int echo_enable) +{ + return cli_read_passphrase(prompt, 0, echo_enable); +} + +void +cli_mesg(char* mesg) +{ + cli_open(0); + cli_write(mesg, strlen(mesg)); + cli_write("\n", strlen("\n")); + cli_close(); + return; +} diff --git a/usr.bin/ssh/cli.h b/usr.bin/ssh/cli.h new file mode 100644 index 00000000000..e33ce4a5047 --- /dev/null +++ b/usr.bin/ssh/cli.h @@ -0,0 +1,14 @@ +#ifndef CLI_H +#define CLI_H + +/* + * Presents a prompt and returns the response allocated with xmalloc(). + * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo + * of response depending on arg. Tries to ensure that no other userland + * buffer is storing the response. + */ +char* cli_read_passphrase(char* prompt, int from_stdin, int echo_enable); +char* cli_prompt(char* prompt, int echo_enable); +void cli_mesg(char* mesg); + +#endif /* CLI_H */ diff --git a/usr.bin/ssh/lib/Makefile b/usr.bin/ssh/lib/Makefile index 4bbe22216e2..b32b8b677a4 100644 --- a/usr.bin/ssh/lib/Makefile +++ b/usr.bin/ssh/lib/Makefile @@ -5,7 +5,8 @@ SRCS= authfd.c authfile.c bufaux.c buffer.c canohost.c channels.c \ cipher.c compat.c compress.c crc32.c deattack.c \ hostfile.c log.c match.c mpaux.c nchan.c packet.c readpass.c \ rsa.c tildexpand.c ttymodes.c uidswap.c xmalloc.c atomicio.c \ - key.c dispatch.c dsa.c kex.c hmac.c uuencode.c util.c + key.c dispatch.c dsa.c kex.c hmac.c uuencode.c util.c \ + cli.c NOPROFILE= yes NOPIC= yes diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c index 2ddf3ed1fec..717d25584a8 100644 --- a/usr.bin/ssh/readconf.c +++ b/usr.bin/ssh/readconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.48 2000/10/11 20:14:39 markus Exp $"); #include "ssh.h" #include "cipher.h" @@ -103,7 +103,8 @@ typedef enum { oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication, oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2, - oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication + oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication, + oKbdInteractiveAuthentication, oKbdInteractiveDevices } OpCodes; /* Textual representations of the tokens. */ @@ -119,6 +120,8 @@ static struct { { "useprivilegedport", oUsePrivilegedPort }, { "rhostsauthentication", oRhostsAuthentication }, { "passwordauthentication", oPasswordAuthentication }, + { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, + { "kbdinteractivedevices", oKbdInteractiveDevices }, { "rsaauthentication", oRSAAuthentication }, { "dsaauthentication", oDSAAuthentication }, { "skeyauthentication", oSkeyAuthentication }, @@ -288,6 +291,14 @@ parse_flag: intptr = &options->password_authentication; goto parse_flag; + case oKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; + + case oKbdInteractiveDevices: + charptr = &options->kbd_interactive_devices; + goto parse_string; + case oDSAAuthentication: intptr = &options->dsa_authentication; goto parse_flag; @@ -662,6 +673,8 @@ initialize_options(Options * options) options->afs_token_passing = -1; #endif options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->kbd_interactive_devices = NULL; options->rhosts_rsa_authentication = -1; options->fallback_to_rsh = -1; options->use_rsh = -1; @@ -732,6 +745,8 @@ fill_default_options(Options * options) #endif /* AFS */ if (options->password_authentication == -1) options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) + options->kbd_interactive_authentication = 0; if (options->rhosts_rsa_authentication == -1) options->rhosts_rsa_authentication = 1; if (options->fallback_to_rsh == -1) diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h index 23df57b4271..e94213fa177 100644 --- a/usr.bin/ssh/readconf.h +++ b/usr.bin/ssh/readconf.h @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: readconf.h,v 1.21 2000/09/07 20:27:53 deraadt Exp $"); */ +/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */ #ifndef READCONF_H #define READCONF_H @@ -47,6 +47,8 @@ typedef struct { #endif int password_authentication; /* Try password * authentication. */ + int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ + char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */ int use_rsh; /* Always use rsh (don\'t try ssh). */ int batch_mode; /* Batch mode: do not ask for passwords. */ diff --git a/usr.bin/ssh/readpass.c b/usr.bin/ssh/readpass.c index c38292f1571..f3a7dcbed27 100644 --- a/usr.bin/ssh/readpass.c +++ b/usr.bin/ssh/readpass.c @@ -32,88 +32,24 @@ */ #include "includes.h" -RCSID("$OpenBSD: readpass.c,v 1.11 2000/06/20 01:39:44 markus Exp $"); +RCSID("$OpenBSD: readpass.c,v 1.12 2000/10/11 20:14:39 markus Exp $"); #include "xmalloc.h" #include "ssh.h" - -volatile int intr; - -void -intcatch() -{ - intr = 1; -} +#include "cli.h" /* * Reads a passphrase from /dev/tty with echo turned off. Returns the * passphrase (allocated with xmalloc), being very careful to ensure that * no other userland buffer is storing the password. */ +/* + * Note: the funcationallity of this routing has been moved to + * cli_read_passphrase(). This routing remains to maintain + * compatibility with existing code. + */ char * -read_passphrase(const char *prompt, int from_stdin) +read_passphrase(char *prompt, int from_stdin) { - char buf[1024], *p, ch; - struct termios tio, saved_tio; - sigset_t oset, nset; - struct sigaction sa, osa; - int input, output, echo = 0; - - if (from_stdin) { - input = STDIN_FILENO; - output = STDERR_FILENO; - } else - input = output = open("/dev/tty", O_RDWR); - - if (input == -1) - fatal("You have no controlling tty. Cannot read passphrase.\n"); - - /* block signals, get terminal modes and turn off echo */ - sigemptyset(&nset); - sigaddset(&nset, SIGTSTP); - (void) sigprocmask(SIG_BLOCK, &nset, &oset); - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = intcatch; - (void) sigaction(SIGINT, &sa, &osa); - - intr = 0; - - if (tcgetattr(input, &saved_tio) == 0 && (saved_tio.c_lflag & ECHO)) { - echo = 1; - tio = saved_tio; - tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - (void) tcsetattr(input, TCSANOW, &tio); - } - - fflush(stdout); - - (void)write(output, prompt, strlen(prompt)); - for (p = buf; read(input, &ch, 1) == 1 && ch != '\n';) { - if (intr) - break; - if (p < buf + sizeof(buf) - 1) - *p++ = ch; - } - *p = '\0'; - if (!intr) - (void)write(output, "\n", 1); - - /* restore terminal modes and allow signals */ - if (echo) - tcsetattr(input, TCSANOW, &saved_tio); - (void) sigprocmask(SIG_SETMASK, &oset, NULL); - (void) sigaction(SIGINT, &osa, NULL); - - if (intr) { - kill(getpid(), SIGINT); - sigemptyset(&nset); - /* XXX tty has not neccessarily drained by now? */ - sigsuspend(&nset); - } - - if (!from_stdin) - (void)close(input); - p = xstrdup(buf); - memset(buf, 0, sizeof(buf)); - return (p); + return cli_read_passphrase(prompt, from_stdin, 0); } diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c index 81551081432..e90defe61e5 100644 --- a/usr.bin/ssh/servconf.c +++ b/usr.bin/ssh/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.52 2000/10/11 20:14:39 markus Exp $"); #include "ssh.h" #include "servconf.h" @@ -61,6 +61,7 @@ initialize_server_options(ServerOptions *options) options->afs_token_passing = -1; #endif options->password_authentication = -1; + options->kbd_interactive_authentication = -1; #ifdef SKEY options->skey_authentication = -1; #endif @@ -148,6 +149,8 @@ fill_default_server_options(ServerOptions *options) #endif /* AFS */ if (options->password_authentication == -1) options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) + options->kbd_interactive_authentication = 0; #ifdef SKEY if (options->skey_authentication == -1) options->skey_authentication = 1; @@ -183,7 +186,7 @@ typedef enum { #ifdef SKEY sSkeyAuthentication, #endif - sPasswordAuthentication, sListenAddress, + sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, @@ -220,6 +223,7 @@ static struct { { "afstokenpassing", sAFSTokenPassing }, #endif { "passwordauthentication", sPasswordAuthentication }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, #ifdef SKEY { "skeyauthentication", sSkeyAuthentication }, #endif @@ -497,6 +501,10 @@ parse_flag: intptr = &options->password_authentication; goto parse_flag; + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; + case sCheckMail: intptr = &options->check_mail; goto parse_flag; diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h index f00a1284f55..ef0790c7beb 100644 --- a/usr.bin/ssh/servconf.h +++ b/usr.bin/ssh/servconf.h @@ -11,7 +11,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: servconf.h,v 1.28 2000/09/07 20:27:53 deraadt Exp $"); */ +/* RCSID("$OpenBSD: servconf.h,v 1.29 2000/10/11 20:14:39 markus Exp $"); */ #ifndef SERVCONF_H #define SERVCONF_H @@ -78,6 +78,7 @@ typedef struct { #endif int password_authentication; /* If true, permit password * authentication. */ + int kbd_interactive_authentication; /* If true, permit */ #ifdef SKEY int skey_authentication; /* If true, permit s/key * authentication. */ diff --git a/usr.bin/ssh/ssh.h b/usr.bin/ssh/ssh.h index 3092d220e58..06810e77ef2 100644 --- a/usr.bin/ssh/ssh.h +++ b/usr.bin/ssh/ssh.h @@ -12,7 +12,7 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: ssh.h,v 1.52 2000/10/11 04:02:17 provos Exp $"); */ +/* RCSID("$OpenBSD: ssh.h,v 1.53 2000/10/11 20:14:39 markus Exp $"); */ #ifndef SSH_H #define SSH_H @@ -381,7 +381,7 @@ int auth_rsa_challenge_dialog(RSA *pk); * passphrase (allocated with xmalloc). Exits if EOF is encountered. If * from_stdin is true, the passphrase will be read from stdin instead. */ -char *read_passphrase(const char *prompt, int from_stdin); +char *read_passphrase(char *prompt, int from_stdin); /*------------ Definitions for logging. -----------------------*/ diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c index 455850eebc6..f8bbc600322 100644 --- a/usr.bin/ssh/sshconnect2.c +++ b/usr.bin/ssh/sshconnect2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.22 2000/10/11 04:02:17 provos Exp $"); +RCSID("$OpenBSD: sshconnect2.c,v 1.23 2000/10/11 20:14:39 markus Exp $"); #include <openssl/bn.h> #include <openssl/rsa.h> @@ -49,6 +49,7 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.22 2000/10/11 04:02:17 provos Exp $"); #include "dsa.h" #include "sshconnect.h" #include "authfile.h" +#include "cli.h" #include "dispatch.h" #include "authfd.h" @@ -457,8 +458,8 @@ struct Authctxt { const char *host; const char *service; AuthenticationConnection *agent; - int success; Authmethod *method; + int success; }; struct Authmethod { char *name; /* string to compare against server's list */ @@ -470,11 +471,16 @@ struct Authmethod { void input_userauth_success(int type, int plen, void *ctxt); void input_userauth_failure(int type, int plen, void *ctxt); void input_userauth_error(int type, int plen, void *ctxt); +void input_userauth_info_req(int type, int plen, void *ctxt); + +int userauth_none(Authctxt *authctxt); int userauth_pubkey(Authctxt *authctxt); int userauth_passwd(Authctxt *authctxt); +int userauth_kbdint(Authctxt *authctxt); void authmethod_clear(); -Authmethod *authmethod_get(char *auth_list); +Authmethod *authmethod_get(char *authlist); +Authmethod *authmethod_lookup(const char *name); Authmethod authmethods[] = { {"publickey", @@ -485,6 +491,14 @@ Authmethod authmethods[] = { userauth_passwd, &options.password_authentication, &options.batch_mode}, + {"keyboard-interactive", + userauth_kbdint, + &options.kbd_interactive_authentication, + &options.batch_mode}, + {"none", + userauth_none, + NULL, + NULL}, {NULL, NULL, NULL, NULL} }; @@ -521,17 +535,13 @@ ssh_userauth2(const char *server_user, char *host) authctxt.host = host; authctxt.service = "ssh-connection"; /* service name */ authctxt.success = 0; - authctxt.method = NULL; + authctxt.method = authmethod_lookup("none"); + if (authctxt.method == NULL) + fatal("ssh_userauth2: internal error: cannot send userauth none request"); + authmethod_clear(); /* initial userauth request */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt.server_user); - packet_put_cstring(authctxt.service); - packet_put_cstring("none"); - packet_send(); - packet_write_wait(); - - authmethod_clear(); + userauth_none(&authctxt); dispatch_init(&input_userauth_error); dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); @@ -541,7 +551,7 @@ ssh_userauth2(const char *server_user, char *host) if (authctxt.agent != NULL) ssh_close_authentication_connection(authctxt.agent); - debug("ssh-userauth2 successfull"); + debug("ssh-userauth2 successfull: method %s", authctxt.method->name); } void input_userauth_error(int type, int plen, void *ctxt) @@ -563,12 +573,11 @@ input_userauth_failure(int type, int plen, void *ctxt) Authctxt *authctxt = ctxt; char *authlist = NULL; int partial; - int dlen; if (authctxt == NULL) fatal("input_userauth_failure: no authentication context"); - authlist = packet_get_string(&dlen); + authlist = packet_get_string(NULL); partial = packet_get_char(); packet_done(); @@ -577,12 +586,12 @@ input_userauth_failure(int type, int plen, void *ctxt) debug("authentications that can continue: %s", authlist); for (;;) { - /* try old method or get next method */ method = authmethod_get(authlist); if (method == NULL) fatal("Unable to find an authentication method"); + authctxt->method = method; if (method->userauth(authctxt) != 0) { - debug2("we sent a packet, wait for reply"); + debug2("we sent a %s packet, wait for reply", method->name); break; } else { debug2("we did not send a packet, disable method"); @@ -593,6 +602,19 @@ input_userauth_failure(int type, int plen, void *ctxt) } int +userauth_none(Authctxt *authctxt) +{ + /* initial userauth request */ + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_send(); + packet_write_wait(); + return 1; +} + +int userauth_passwd(Authctxt *authctxt) { static int attempt = 0; @@ -611,7 +633,7 @@ userauth_passwd(Authctxt *authctxt) packet_start(SSH2_MSG_USERAUTH_REQUEST); packet_put_cstring(authctxt->server_user); packet_put_cstring(authctxt->service); - packet_put_cstring("password"); + packet_put_cstring(authctxt->method->name); packet_put_char(0); packet_put_cstring(password); memset(password, 0, strlen(password)); @@ -629,6 +651,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) int bloblen, slen; int skip = 0; int ret = -1; + int have_sig = 1; dsa_make_key_blob(k, &blob, &bloblen); @@ -647,8 +670,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) datafellows & SSH_BUG_PUBKEYAUTH ? "ssh-userauth" : authctxt->service); - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, 1); + buffer_put_cstring(&b, authctxt->method->name); + buffer_put_char(&b, have_sig); buffer_put_cstring(&b, KEX_DSS); buffer_put_string(&b, blob, bloblen); @@ -668,8 +691,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); buffer_put_cstring(&b, authctxt->server_user); buffer_put_cstring(&b, authctxt->service); - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, 1); + buffer_put_cstring(&b, authctxt->method->name); + buffer_put_char(&b, have_sig); buffer_put_cstring(&b, KEX_DSS); buffer_put_string(&b, blob, bloblen); } @@ -793,6 +816,92 @@ userauth_pubkey(Authctxt *authctxt) return sent; } +/* + * Send userauth request message specifying keyboard-interactive method. + */ +int +userauth_kbdint(Authctxt *authctxt) +{ + static int attempt = 0; + + if (attempt++ >= options.number_of_password_prompts) + return 0; + + debug2("userauth_kbdint"); + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); + packet_put_cstring(authctxt->service); + packet_put_cstring(authctxt->method->name); + packet_put_cstring(""); /* lang */ + packet_put_cstring(options.kbd_interactive_devices ? + options.kbd_interactive_devices : ""); + packet_send(); + packet_write_wait(); + + dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); + return 1; +} + +/* + * parse SSH2_MSG_USERAUTH_INFO_REQUEST, prompt user and send + * SSH2_MSG_USERAUTH_INFO_RESPONSE + */ +void +input_userauth_info_req(int type, int plen, void *ctxt) +{ + Authctxt *authctxt = ctxt; + char *name = NULL; + char *inst = NULL; + char *lang = NULL; + char *prompt = NULL; + char *response = NULL; + unsigned int num_prompts, i; + int echo = 0; + + debug2("input_userauth_info_req"); + + if (authctxt == NULL) + fatal("input_userauth_info_req: no authentication context"); + + name = packet_get_string(NULL); + inst = packet_get_string(NULL); + lang = packet_get_string(NULL); + + if (strlen(name) > 0) + cli_mesg(name); + xfree(name); + + if (strlen(inst) > 0) + cli_mesg(inst); + xfree(inst); + xfree(lang); /* unused */ + + num_prompts = packet_get_int(); + /* + * Begin to build info response packet based on prompts requested. + * We commit to providing the correct number of responses, so if + * further on we run into a problem that prevents this, we have to + * be sure and clean this up and send a correct error response. + */ + packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); + packet_put_int(num_prompts); + + for (i = 0; i < num_prompts; i++) { + prompt = packet_get_string(NULL); + echo = packet_get_char(); + + response = cli_prompt(prompt, echo); + + packet_put_cstring(response); + memset(response, 0, strlen(response)); + xfree(response); + xfree(prompt); + } + packet_done(); /* done with parsing incoming message. */ + + packet_send(); + packet_write_wait(); +} /* find auth method */ @@ -879,6 +988,7 @@ authmethod_get(char *authlist) if (authlist_current == NULL || strcmp(authlist, authlist_current) != 0) { /* start over if passed a different list */ + debug3("start over, passed a different list"); authmethod_clear(); authlist_current = xstrdup(authlist); authlist_working = xstrdup(authlist); @@ -893,16 +1003,20 @@ authmethod_get(char *authlist) } while (name != NULL) { + debug3("authmethod_lookup %s", name); method = authmethod_lookup(name); - if (method != NULL && authmethod_is_enabled(method)) + if (method != NULL && authmethod_is_enabled(method)) { + debug3("authmethod_is_enabled %s", name); break; + } name = strtok_r(NULL, DELIM, &authlist_state); + method = NULL; } if (authname_current != NULL) xfree(authname_current); - if (name != NULL) { + if (method != NULL) { debug("next auth method to try is %s", name); authname_current = xstrdup(name); return method; diff --git a/usr.bin/ssh/sshd/Makefile b/usr.bin/ssh/sshd/Makefile index 4938d58744d..0a9fba8e052 100644 --- a/usr.bin/ssh/sshd/Makefile +++ b/usr.bin/ssh/sshd/Makefile @@ -26,7 +26,7 @@ DPADD+= ${LIBKRB} .endif # KERBEROS .if (${SKEY:L} == "yes") -SRCS+= auth-skey.c +SRCS+= auth-skey.c auth2-skey.c .endif .include <bsd.prog.mk> diff --git a/usr.bin/ssh/sshd_config b/usr.bin/ssh/sshd_config index 71e73ba9dc0..0ef2fa8915b 100644 --- a/usr.bin/ssh/sshd_config +++ b/usr.bin/ssh/sshd_config @@ -37,6 +37,7 @@ PasswordAuthentication yes PermitEmptyPasswords no # Uncomment to disable s/key passwords #SkeyAuthentication no +#KbdInteractiveAuthentication yes # To change Kerberos options #KerberosAuthentication no |