X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/fa08c86b0da2449181b5e9e64cd62eb0344e88bf..2e4fb373fccee2e5a296d484189169914f6e07d8:/auth2.c diff --git a/auth2.c b/auth2.c index 46bf07c8..8d229955 100644 --- a/auth2.c +++ b/auth2.c @@ -23,50 +23,40 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.21 2000/11/12 19:50:37 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.46 2001/03/11 13:25:36 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 "sshpty.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" +#include "misc.h" /* import */ extern ServerOptions options; -extern unsigned char *session_id2; +extern u_char *session_id2; 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,14 +74,13 @@ 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); 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 @@ -151,7 +137,7 @@ void input_service_request(int type, int plen, void *ctxt) { Authctxt *authctxt = ctxt; - unsigned int len; + u_int len; int accept = 0; char *service = packet_get_string(&len); packet_done(); @@ -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,94 @@ 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; +#ifdef BSD_AUTH + if (authctxt->as) { + auth_close(authctxt->as); + authctxt->as = NULL; + } +#endif + /* 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 +312,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 +333,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,11 +345,9 @@ 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, ""); + return auth_password(authctxt, ""); #endif /* USE_PAM */ } @@ -363,7 +357,7 @@ userauth_passwd(Authctxt *authctxt) char *password; int authenticated = 0; int change; - unsigned int len; + u_int len; change = packet_get_char(); if (change) log("password change not supported"); @@ -376,11 +370,9 @@ 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) + auth_password(authctxt, password) == 1) #endif /* USE_PAM */ authenticated = 1; memset(password, 0, len); @@ -400,10 +392,13 @@ userauth_kbdint(Authctxt *authctxt) 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); + + if (options.challenge_reponse_authentication) + authenticated = auth2_challenge(authctxt, devs); + +#ifdef USE_PAM + if (authenticated == 0) + authenticated = auth2_pam(authctxt); #endif xfree(lang); xfree(devs); @@ -420,7 +415,7 @@ userauth_pubkey(Authctxt *authctxt) Buffer b; Key *key; char *pkalg, *pkblob, *sig; - unsigned int alen, blen, slen; + u_int alen, blen, slen; int have_sig, pktype; int authenticated = 0; @@ -429,14 +424,27 @@ userauth_pubkey(Authctxt *authctxt) return 0; } have_sig = packet_get_char(); - pkalg = packet_get_string(&alen); + if (datafellows & SSH_BUG_PKAUTH) { + debug2("userauth_pubkey: SSH_BUG_PKAUTH"); + /* no explicit pkalg given */ + pkblob = packet_get_string(&blen); + buffer_init(&b); + buffer_append(&b, pkblob, blen); + /* so we have to extract the pkalg from the pkblob */ + pkalg = buffer_get_string(&b, &alen); + buffer_free(&b); + } else { + pkalg = packet_get_string(&alen); + pkblob = packet_get_string(&blen); + } pktype = key_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { - log("bad pkalg %s", pkalg); + /* this is perfectly legal */ + log("userauth_pubkey: unsupported public key algorithm: %s", pkalg); xfree(pkalg); + xfree(pkblob); return 0; } - pkblob = packet_get_string(&blen); key = key_from_blob(pkblob, blen); if (key != NULL) { if (have_sig) { @@ -452,12 +460,16 @@ userauth_pubkey(Authctxt *authctxt) buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); buffer_put_cstring(&b, authctxt->user); buffer_put_cstring(&b, - datafellows & SSH_BUG_PUBKEYAUTH ? + datafellows & SSH_BUG_PKSERVICE ? "ssh-userauth" : authctxt->service); - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, key_ssh_name(key)); + if (datafellows & SSH_BUG_PKAUTH) { + buffer_put_char(&b, have_sig); + } else { + buffer_put_cstring(&b, "publickey"); + buffer_put_char(&b, have_sig); + buffer_put_cstring(&b, key_ssh_name(key)); + } buffer_put_string(&b, pkblob, blen); #ifdef DEBUG_PK buffer_dump(&b); @@ -486,7 +498,7 @@ userauth_pubkey(Authctxt *authctxt) packet_put_string(pkblob, blen); packet_send(); packet_write_wait(); - authenticated = -1; + authctxt->postponed = 1; } } if (authenticated != 1) @@ -517,7 +529,7 @@ char * authmethods_get(void) { Authmethod *method = NULL; - unsigned int size = 0; + u_int size = 0; char *list; for (method = authmethods; method->name != NULL; method++) { @@ -563,10 +575,10 @@ 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; - unsigned long linenum = 0; + u_long linenum = 0; struct stat st; Key *found; @@ -578,7 +590,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) { @@ -606,10 +618,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", @@ -628,7 +640,7 @@ user_key_allowed(struct passwd *pw, Key *key) } if (fail) { fclose(f); - log("%s",buf); + log("%s", buf); restore_uid(); return 0; } @@ -666,7 +678,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); @@ -676,22 +688,7 @@ user_key_allowed(struct passwd *pw, Key *key) restore_uid(); fclose(f); key_free(found); + if (!found_key) + debug2("key not 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; -}