X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/31de8b2bb1409917e2613548d0a0016ac47be0c4..103ff3950fe7618d2a9815810a7be6a8019bac35:/auth.c diff --git a/auth.c b/auth.c index 4698e399..2dc5c2be 100644 --- a/auth.c +++ b/auth.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth.c,v 1.57 2005/01/22 08:17:59 dtucker Exp $"); +RCSID("$OpenBSD: auth.c,v 1.60 2005/06/17 02:44:32 djm Exp $"); #ifdef HAVE_LOGIN_H #include @@ -50,6 +50,8 @@ RCSID("$OpenBSD: auth.c,v 1.57 2005/01/22 08:17:59 dtucker Exp $"); #include "misc.h" #include "bufaux.h" #include "packet.h" +#include "loginrec.h" +#include "monitor_wrap.h" /* import */ extern ServerOptions options; @@ -74,7 +76,7 @@ allowed_user(struct passwd * pw) struct stat st; const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL; char *shell; - int i; + u_int i; #ifdef USE_SHADOW struct spwd *spw = NULL; #endif @@ -95,7 +97,11 @@ allowed_user(struct passwd * pw) /* grab passwd field for locked account check */ #ifdef USE_SHADOW if (spw != NULL) +#if defined(HAVE_LIBIAF) && !defined(BROKEN_LIBIAF) + passwd = get_iaf_password(pw); +#else passwd = spw->sp_pwdp; +#endif /* HAVE_LIBIAF && !BROKEN_LIBIAF */ #else passwd = pw->pw_passwd; #endif @@ -117,6 +123,9 @@ allowed_user(struct passwd * pw) if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) locked = 1; #endif +#if defined(HAVE_LIBIAF) && !defined(BROKEN_LIBIAF) + free(passwd); +#endif /* HAVE_LIBIAF && !BROKEN_LIBIAF */ if (locked) { logit("User %.100s not allowed because account is locked", pw->pw_name); @@ -143,7 +152,8 @@ allowed_user(struct passwd * pw) return 0; } - if (options.num_deny_users > 0 || options.num_allow_users > 0) { + if (options.num_deny_users > 0 || options.num_allow_users > 0 || + options.num_deny_groups > 0 || options.num_allow_groups > 0) { hostname = get_canonical_hostname(options.use_dns); ipaddr = get_remote_ipaddr(); } @@ -207,7 +217,7 @@ allowed_user(struct passwd * pw) } #ifdef CUSTOM_SYS_AUTH_ALLOWED_USER - if (!sys_auth_allowed_user(pw)) + if (!sys_auth_allowed_user(pw, &loginmsg)) return 0; #endif @@ -243,8 +253,50 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) info); #ifdef CUSTOM_FAILED_LOGIN - if (authenticated == 0 && strcmp(method, "password") == 0) - record_failed_login(authctxt->user, "ssh"); + if (authenticated == 0 && !authctxt->postponed && + (strcmp(method, "password") == 0 || + strncmp(method, "keyboard-interactive", 20) == 0 || + strcmp(method, "challenge-response") == 0)) + record_failed_login(authctxt->user, + get_canonical_hostname(options.use_dns), "ssh"); +#endif +#ifdef SSH_AUDIT_EVENTS + if (authenticated == 0 && !authctxt->postponed) { + ssh_audit_event_t event; + + debug3("audit failed auth attempt, method %s euid %d", + method, (int)geteuid()); + /* + * Because the auth loop is used in both monitor and slave, + * we must be careful to send each event only once and with + * enough privs to write the event. + */ + event = audit_classify_auth(method); + switch(event) { + case SSH_AUTH_FAIL_NONE: + case SSH_AUTH_FAIL_PASSWD: + case SSH_AUTH_FAIL_KBDINT: + if (geteuid() == 0) + audit_event(event); + break; + case SSH_AUTH_FAIL_PUBKEY: + case SSH_AUTH_FAIL_HOSTBASED: + case SSH_AUTH_FAIL_GSSAPI: + /* + * This is required to handle the case where privsep + * is enabled but it's root logging in, since + * use_privsep won't be cleared until after a + * successful login. + */ + if (geteuid() == 0) + audit_event(event); + else + PRIVSEP(audit_event(event)); + break; + default: + error("unknown authentication audit event %d", event); + } + } #endif } @@ -281,64 +333,41 @@ auth_root_allowed(char *method) * * This returns a buffer allocated by xmalloc. */ -char * -expand_filename(const char *filename, struct passwd *pw) +static char * +expand_authorized_keys(const char *filename, struct passwd *pw) { - Buffer buffer; - char *file; - const char *cp; + char *file, *ret; - /* - * Build the filename string in the buffer by making the appropriate - * substitutions to the given file name. - */ - buffer_init(&buffer); - for (cp = filename; *cp; cp++) { - if (cp[0] == '%' && cp[1] == '%') { - buffer_append(&buffer, "%", 1); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'h') { - buffer_append(&buffer, pw->pw_dir, strlen(pw->pw_dir)); - cp++; - continue; - } - if (cp[0] == '%' && cp[1] == 'u') { - buffer_append(&buffer, pw->pw_name, - strlen(pw->pw_name)); - cp++; - continue; - } - buffer_append(&buffer, cp, 1); - } - buffer_append(&buffer, "\0", 1); + file = percent_expand(filename, "h", pw->pw_dir, + "u", pw->pw_name, (char *)NULL); /* * Ensure that filename starts anchored. If not, be backward * compatible and prepend the '%h/' */ - file = xmalloc(MAXPATHLEN); - cp = buffer_ptr(&buffer); - if (*cp != '/') - snprintf(file, MAXPATHLEN, "%s/%s", pw->pw_dir, cp); - else - strlcpy(file, cp, MAXPATHLEN); + if (*file == '/') + return (file); + + ret = xmalloc(MAXPATHLEN); + if (strlcpy(ret, pw->pw_dir, MAXPATHLEN) >= MAXPATHLEN || + strlcat(ret, "/", MAXPATHLEN) >= MAXPATHLEN || + strlcat(ret, file, MAXPATHLEN) >= MAXPATHLEN) + fatal("expand_authorized_keys: path too long"); - buffer_free(&buffer); - return file; + xfree(file); + return (ret); } char * authorized_keys_file(struct passwd *pw) { - return expand_filename(options.authorized_keys_file, pw); + return expand_authorized_keys(options.authorized_keys_file, pw); } char * authorized_keys_file2(struct passwd *pw) { - return expand_filename(options.authorized_keys_file2, pw); + return expand_authorized_keys(options.authorized_keys_file2, pw); } /* return ok if key exists in sysfile or userfile */ @@ -468,8 +497,12 @@ getpwnamallow(const char *user) logit("Invalid user %.100s from %.100s", user, get_remote_ipaddr()); #ifdef CUSTOM_FAILED_LOGIN - record_failed_login(user, "ssh"); + record_failed_login(user, + get_canonical_hostname(options.use_dns), "ssh"); #endif +#ifdef SSH_AUDIT_EVENTS + audit_event(SSH_INVALID_USER); +#endif /* SSH_AUDIT_EVENTS */ return (NULL); } if (!allowed_user(pw))