*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.56 2004/07/28 09:40:29 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.60 2005/06/17 02:44:32 djm Exp $");
#ifdef HAVE_LOGIN_H
#include <login.h>
#include "misc.h"
#include "bufaux.h"
#include "packet.h"
+#include "loginrec.h"
+#include "monitor_wrap.h"
/* import */
extern ServerOptions options;
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
/* 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
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);
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();
}
for (i = 0; i < options.num_deny_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i])) {
- logit("User %.100s not allowed because listed in DenyUsers",
- pw->pw_name);
+ logit("User %.100s from %.100s not allowed "
+ "because listed in DenyUsers",
+ pw->pw_name, hostname);
return 0;
}
}
break;
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users) {
- logit("User %.100s not allowed because not listed in AllowUsers",
- pw->pw_name);
+ logit("User %.100s from %.100s not allowed because "
+ "not listed in AllowUsers", pw->pw_name, hostname);
return 0;
}
}
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
/* Get the user's group access list (primary and supplementary) */
if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
- logit("User %.100s not allowed because not in any group",
- pw->pw_name);
+ logit("User %.100s from %.100s not allowed because "
+ "not in any group", pw->pw_name, hostname);
return 0;
}
if (ga_match(options.deny_groups,
options.num_deny_groups)) {
ga_free();
- logit("User %.100s not allowed because a group is listed in DenyGroups",
- pw->pw_name);
+ logit("User %.100s from %.100s not allowed "
+ "because a group is listed in DenyGroups",
+ pw->pw_name, hostname);
return 0;
}
/*
if (!ga_match(options.allow_groups,
options.num_allow_groups)) {
ga_free();
- logit("User %.100s not allowed because none of user's groups are listed in AllowGroups",
- pw->pw_name);
+ logit("User %.100s from %.100s not allowed "
+ "because none of user's groups are listed "
+ "in AllowGroups", pw->pw_name, hostname);
return 0;
}
ga_free();
}
#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
- if (!sys_auth_allowed_user(pw))
+ if (!sys_auth_allowed_user(pw, &loginmsg))
return 0;
#endif
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
}
*
* 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 */
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))