X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/1e3b8b0749ec6793df5d8a9aca41ad4cae79bd4a..bdf80b2c2976a203dd6d9f65a2ae382080bebee6:/auth2.c diff --git a/auth2.c b/auth2.c index a0e6d577..88fca2c9 100644 --- a/auth2.c +++ b/auth2.c @@ -23,35 +23,28 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.23 2000/12/19 23:17:55 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.42 2001/02/13 22:49:40 markus Exp $"); -#ifdef HAVE_OSF_SIA -# include -# include -#endif - -#include -#include #include +#include "ssh2.h" #include "xmalloc.h" #include "rsa.h" -#include "ssh.h" #include "pty.h" #include "packet.h" #include "buffer.h" +#include "log.h" #include "servconf.h" #include "compat.h" #include "channels.h" #include "bufaux.h" -#include "ssh2.h" #include "auth.h" #include "session.h" #include "dispatch.h" -#include "auth.h" #include "key.h" +#include "cipher.h" #include "kex.h" - +#include "pathnames.h" #include "uidswap.h" #include "auth-options.h" @@ -63,10 +56,6 @@ extern int session_id2_len; #ifdef WITH_AIXAUTHENTICATE extern char *aixloginmsg; #endif -#ifdef HAVE_OSF_SIA -extern int saved_argc; -extern char **saved_argv; -#endif static Authctxt *x_authctxt = NULL; static int one = 1; @@ -84,7 +73,6 @@ 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); - /* helper */ Authmethod *authmethod_lookup(const char *name); struct passwd *pwcopy(struct passwd *pw); @@ -92,6 +80,7 @@ int user_key_allowed(struct passwd *pw, Key *key); char *authmethods_get(void); /* auth */ +void userauth_banner(void); int userauth_none(Authctxt *authctxt); int userauth_passwd(Authctxt *authctxt); int userauth_pubkey(Authctxt *authctxt); @@ -104,12 +93,12 @@ Authmethod authmethods[] = { {"publickey", userauth_pubkey, &options.pubkey_authentication}, - {"keyboard-interactive", - userauth_kbdint, - &options.kbd_interactive_authentication}, {"password", userauth_passwd, &options.password_authentication}, + {"keyboard-interactive", + userauth_kbdint, + &options.kbd_interactive_authentication}, {NULL, NULL, NULL} }; @@ -120,21 +109,18 @@ Authmethod authmethods[] = { void do_authentication2() { - Authctxt *authctxt = xmalloc(sizeof(*authctxt)); - memset(authctxt, 'a', sizeof(*authctxt)); - authctxt->valid = 0; - authctxt->attempt = 0; - authctxt->success = 0; + Authctxt *authctxt = authctxt_new(); + x_authctxt = authctxt; /*XXX*/ -#ifdef KRB4 - /* turn off kerberos, not supported by SSH2 */ - options.kerberos_authentication = 0; -#endif + /* challenge-reponse is implemented via keyboard interactive */ + if (options.challenge_reponse_authentication) + options.kbd_interactive_authentication = 1; + dispatch_init(&protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); - do_authenticated2(); + do_authenticated2(authctxt); } void @@ -185,42 +171,42 @@ input_userauth_request(int type, int plen, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; - char *user, *service, *method; + char *user, *service, *method, *style = NULL; int authenticated = 0; if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); - if (authctxt->attempt++ >= AUTH_FAIL_MAX) { -#ifdef WITH_AIXAUTHENTICATE - loginfailed(authctxt->user?authctxt->user:"NOUSER", - get_canonical_hostname(), "ssh"); -#endif /* WITH_AIXAUTHENTICATE */ - packet_disconnect("too many failed userauth_requests"); - } 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); - debug("attempt #%d", authctxt->attempt); + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; - if (authctxt->attempt == 1) { + if (authctxt->attempt++ == 0) { /* 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); #ifdef USE_PAM - start_pam(pw); + start_pam(pw->pw_name); #endif } else { log("input_userauth_request: illegal user %s", user); +#ifdef USE_PAM + start_pam("NOUSER"); +#endif } + setproctitle("%s", pw ? user : "unknown"); authctxt->user = xstrdup(user); authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; /* currently unused */ } else if (authctxt->valid) { if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { @@ -229,85 +215,88 @@ input_userauth_request(int type, int plen, void *ctxt) authctxt->valid = 0; } } + /* reset state */ + dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error); + authctxt->postponed = 0; + /* try to authenticate user */ 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 (!authctxt->valid && authenticated) + fatal("INTERNAL ERROR: authenticated invalid user %s", + authctxt->user); /* Special handling for root */ - if (authenticated == 1 && - authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) { + if (authenticated && authctxt->pw->pw_uid == 0 && + !auth_root_allowed(method)) authenticated = 0; - log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname()); - } #ifdef USE_PAM - if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL)) + if (authenticated && authctxt->user && !do_pam_account(authctxt->user, + NULL)) authenticated = 0; #endif /* USE_PAM */ /* Log before sending the reply */ - userauth_log(authctxt, authenticated, method); - userauth_reply(authctxt, authenticated); + auth_log(authctxt, authenticated, method, " ssh2"); + + if (!authctxt->postponed) + userauth_reply(authctxt, authenticated); xfree(service); xfree(user); xfree(method); } - void -userauth_log(Authctxt *authctxt, int authenticated, char *method) +userauth_banner(void) { - void (*authlog) (const char *fmt,...) = verbose; - char *user = NULL, *authmsg = NULL; - - /* Raise logging level */ - if (authenticated == 1 || - !authctxt->valid || - authctxt->attempt >= AUTH_FAIL_LOG || - strcmp(method, "password") == 0) - authlog = log; - - if (authenticated == 1) { - authmsg = "Accepted"; - } else if (authenticated == 0) { - authmsg = "Failed"; - } else { - authmsg = "Postponed"; - } - - if (authctxt->valid) { - user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user; - } else { - user = "NOUSER"; + struct stat st; + char *banner = NULL; + off_t len, n; + int fd; + + if (options.banner == NULL || (datafellows & SSH_BUG_BANNER)) + return; + if ((fd = open(options.banner, O_RDONLY)) < 0) { + error("userauth_banner: open %s failed: %s", + options.banner, strerror(errno)); + return; } - - authlog("%s %s for %.200s from %.200s port %d ssh2", - authmsg, - method, - user, - get_remote_ipaddr(), - get_remote_port()); + if (fstat(fd, &st) < 0) + goto done; + len = st.st_size; + banner = xmalloc(len + 1); + if ((n = read(fd, banner, len)) < 0) + goto done; + banner[n] = '\0'; + packet_start(SSH2_MSG_USERAUTH_BANNER); + packet_put_cstring(banner); + packet_put_cstring(""); /* language, unused */ + packet_send(); + debug("userauth_banner: sent"); +done: + if (banner) + xfree(banner); + close(fd); + return; } -void +void userauth_reply(Authctxt *authctxt, int authenticated) { + char *methods; + /* XXX todo: check if multiple auth methods are needed */ if (authenticated == 1) { #ifdef WITH_AIXAUTHENTICATE /* We don't have a pty yet, so just label the line as "ssh" */ - if (loginsuccess(authctxt->user?authctxt->user:"NOUSER", - get_canonical_hostname(), "ssh", &aixloginmsg) < 0) + if (loginsuccess(authctxt->user?authctxt->user:"NOUSER", + get_canonical_hostname(options.reverse_mapping_check), + "ssh", &aixloginmsg) < 0) aixloginmsg = NULL; #endif /* WITH_AIXAUTHENTICATE */ /* turn off userauth */ @@ -317,16 +306,16 @@ userauth_reply(Authctxt *authctxt, int authenticated) packet_write_wait(); /* now we can break out */ authctxt->success = 1; - } else if (authenticated == 0) { - char *methods = authmethods_get(); + } else { + if (authctxt->failures++ > AUTH_FAIL_MAX) + packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + methods = authmethods_get(); packet_start(SSH2_MSG_USERAUTH_FAILURE); 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 */ } } @@ -338,10 +327,11 @@ userauth_none(Authctxt *authctxt) if (m != NULL) m->enabled = NULL; packet_done(); + userauth_banner(); if (authctxt->valid == 0) return(0); - + #ifdef HAVE_CYGWIN if (check_nt_auth(1, authctxt->pw->pw_uid) == 0) return(0); @@ -349,9 +339,7 @@ userauth_none(Authctxt *authctxt) #ifdef USE_PAM return auth_pam_password(authctxt->pw, ""); #elif defined(HAVE_OSF_SIA) - return (sia_validate_user(NULL, saved_argc, saved_argv, - get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER", - NULL, 0, NULL, "") == SIASUCCESS); + return 0; #else /* !HAVE_OSF_SIA && !USE_PAM */ return auth_password(authctxt->pw, ""); #endif /* USE_PAM */ @@ -376,9 +364,7 @@ userauth_passwd(Authctxt *authctxt) #ifdef USE_PAM auth_pam_password(authctxt->pw, password) == 1) #elif defined(HAVE_OSF_SIA) - sia_validate_user(NULL, saved_argc, saved_argv, - get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER", - NULL, 0, NULL, password) == SIASUCCESS) + auth_sia_password(authctxt->user, password) == 1) #else /* !USE_PAM && !HAVE_OSF_SIA */ auth_password(authctxt->pw, password) == 1) #endif /* USE_PAM */ @@ -400,15 +386,13 @@ userauth_kbdint(Authctxt *authctxt) packet_done(); debug("keyboard-interactive language %s devs %s", lang, devs); + + if (options.challenge_reponse_authentication) + authenticated = auth2_challenge(authctxt, devs); + #ifdef USE_PAM if (authenticated == 0) authenticated = auth2_pam(authctxt); -#endif -#ifdef SKEY - /* XXX hardcoded, we should look at devs */ - if (authenticated == 0) - if (options.skey_authentication != 0) - authenticated = auth2_skey(authctxt); #endif xfree(lang); xfree(devs); @@ -508,7 +492,7 @@ userauth_pubkey(Authctxt *authctxt) packet_put_string(pkblob, blen); packet_send(); packet_write_wait(); - authenticated = -1; + authctxt->postponed = 1; } } if (authenticated != 1) @@ -585,7 +569,7 @@ authmethod_lookup(const char *name) int user_key_allowed(struct passwd *pw, Key *key) { - char line[8192], file[1024]; + char line[8192], file[MAXPATHLEN]; int found_key = 0; FILE *f; u_long linenum = 0; @@ -600,7 +584,7 @@ user_key_allowed(struct passwd *pw, Key *key) /* The authorized keys. */ snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir, - SSH_USER_PERMITTED_KEYS2); + _PATH_SSH_USER_PERMITTED_KEYS2); /* Fail quietly if file does not exist */ if (stat(file, &st) < 0) { @@ -628,10 +612,10 @@ user_key_allowed(struct passwd *pw, Key *key) key_type(key), pw->pw_name, file); fail = 1; } else { - /* Check path to SSH_USER_PERMITTED_KEYS */ + /* Check path to _PATH_SSH_USER_PERMITTED_KEYS */ int i; static const char *check[] = { - "", SSH_USER_DIR, NULL + "", _PATH_SSH_USER_DIR, NULL }; for (i = 0; check[i]; i++) { snprintf(line, sizeof line, "%.500s/%.100s", @@ -688,7 +672,7 @@ user_key_allowed(struct passwd *pw, Key *key) } } if (key_equal(found, key) && - auth_parse_options(pw, options, linenum) == 1) { + auth_parse_options(pw, options, file, linenum) == 1) { found_key = 1; debug("matching key found: file %s, line %ld", file, linenum); @@ -700,20 +684,3 @@ user_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; -#ifdef HAVE_PW_CLASS_IN_PASSWD - copy->pw_class = xstrdup(pw->pw_class); -#endif - copy->pw_dir = xstrdup(pw->pw_dir); - copy->pw_shell = xstrdup(pw->pw_shell); - return copy; -}