*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.26 2001/06/27 04:48:52 markus Exp $");
+RCSID("$OpenBSD: auth.c,v 1.43 2002/05/17 14:27:55 millert Exp $");
#ifdef HAVE_LOGIN_H
#include <login.h>
#include "bufaux.h"
#include "uidswap.h"
#include "tildexpand.h"
+#include "misc.h"
+#include "bufaux.h"
+#include "packet.h"
/* import */
extern ServerOptions options;
+/* Debugging messages */
+Buffer auth_debug;
+int auth_debug_init;
+
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
if (!pw || !pw->pw_name)
return 0;
+#define DAY (24L * 60 * 60) /* 1 day in seconds */
spw = getspnam(pw->pw_name);
if (spw != NULL) {
- int days = time(NULL) / 86400;
+ time_t today = time(NULL) / DAY;
+ debug3("allowed_user: today %d sp_expire %d sp_lstchg %d"
+ " sp_max %d", (int)today, (int)spw->sp_expire,
+ (int)spw->sp_lstchg, (int)spw->sp_max);
+
+ /*
+ * We assume account and password expiration occurs the
+ * day after the day specified.
+ */
+ if (spw->sp_expire != -1 && today > spw->sp_expire) {
+ log("Account %.100s has expired", pw->pw_name);
+ return 0;
+ }
- /* Check account expiry */
- if ((spw->sp_expire >= 0) && (days > spw->sp_expire))
+ if (spw->sp_lstchg == 0) {
+ log("User %.100s password has expired (root forced)",
+ pw->pw_name);
return 0;
+ }
- /* Check password expiry */
- if ((spw->sp_lstchg >= 0) && (spw->sp_max >= 0) &&
- (days > (spw->sp_lstchg + spw->sp_max)))
+ if (spw->sp_max != -1 &&
+ today > spw->sp_lstchg + spw->sp_max) {
+ log("User %.100s password has expired (password aged)",
+ pw->pw_name);
return 0;
+ }
}
#else
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
/* deny if shell does not exists or is not executable */
- if (stat(shell, &st) != 0)
+ if (stat(shell, &st) != 0) {
+ log("User %.100s not allowed because shell %.100s does not exist",
+ pw->pw_name, shell);
return 0;
- if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
+ }
+ if (S_ISREG(st.st_mode) == 0 ||
+ (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
+ log("User %.100s not allowed because shell %.100s is not executable",
+ pw->pw_name, shell);
return 0;
+ }
if (options.num_deny_users > 0 || options.num_allow_users > 0) {
- hostname = get_canonical_hostname(options.reverse_mapping_check);
+ hostname = get_canonical_hostname(options.verify_reverse_mapping);
ipaddr = get_remote_ipaddr();
}
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++)
if (match_user(pw->pw_name, hostname, ipaddr,
- options.deny_users[i]))
+ options.deny_users[i])) {
+ log("User %.100s not allowed because listed in DenyUsers",
+ pw->pw_name);
return 0;
+ }
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
- if (i >= options.num_allow_users)
+ if (i >= options.num_allow_users) {
+ log("User %.100s not allowed because not listed in AllowUsers",
+ pw->pw_name);
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)
+ if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
+ log("User %.100s not allowed because not in any group",
+ pw->pw_name);
return 0;
+ }
/* Return false if one of user's groups is listed in DenyGroups */
if (options.num_deny_groups > 0)
if (ga_match(options.deny_groups,
options.num_deny_groups)) {
ga_free();
+ log("User %.100s not allowed because a group is listed in DenyGroups",
+ pw->pw_name);
return 0;
}
/*
if (!ga_match(options.allow_groups,
options.num_allow_groups)) {
ga_free();
+ log("User %.100s not allowed because none of user's groups are listed in AllowGroups",
+ pw->pw_name);
return 0;
}
ga_free();
authmsg,
method,
authctxt->valid ? "" : "illegal user ",
- authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user,
+ authctxt->user,
get_remote_ipaddr(),
get_remote_port(),
info);
+
+#ifdef WITH_AIXAUTHENTICATE
+ if (authenticated == 0 && strcmp(method, "password") == 0)
+ loginfailed(authctxt->user,
+ get_canonical_hostname(options.verify_reverse_mapping),
+ "ssh");
+#endif /* WITH_AIXAUTHENTICATE */
+
}
/*
}
if (cp[0] == '%' && cp[1] == 'u') {
buffer_append(&buffer, pw->pw_name,
- strlen(pw->pw_name));
+ strlen(pw->pw_name));
cp++;
continue;
}
Key *found;
char *user_hostfile;
struct stat st;
- int host_status;
+ HostStatus host_status;
/* Check if we know the host and its host key. */
found = key_new(key->type);
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0)) {
+ (st.st_mode & 022) != 0)) {
log("Authentication refused for %.100s: "
"bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
char *err, size_t errlen)
{
uid_t uid = pw->pw_uid;
- char homedir[MAXPATHLEN];
- char buf[MAXPATHLEN];
+ char buf[MAXPATHLEN], homedir[MAXPATHLEN];
char *cp;
struct stat st;
- strlcpy(homedir, pw->pw_dir, sizeof(homedir));
- if ((cp = dirname(homedir)) == NULL)
- strlcpy(homedir, "/", sizeof(homedir));
- else
- memmove(homedir, cp, strlen(cp));
-
if (realpath(file, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", file,
strerror(errno));
return -1;
}
+ if (realpath(pw->pw_dir, homedir) == NULL) {
+ snprintf(err, errlen, "realpath %s failed: %s", pw->pw_dir,
+ strerror(errno));
+ return -1;
+ }
/* check the open file to avoid races */
if (fstat(fileno(f), &st) < 0 ||
return -1;
}
- debug3("secure_filename: terminating check at '%s'", homedir);
-
/* for each component of the canonical path, walking upwards */
for (;;) {
if ((cp = dirname(buf)) == NULL) {
}
strlcpy(buf, cp, sizeof(buf));
- /* If are passed the homedir then we can stop */
- if (strcmp(buf, homedir) == 0)
- break;
-
debug3("secure_filename: checking '%s'", buf);
if (stat(buf, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
- snprintf(err, errlen,
+ snprintf(err, errlen,
"bad ownership or modes for directory %s", buf);
return -1;
}
+ /* If are passed the homedir then we can stop */
+ if (strcmp(homedir, buf) == 0) {
+ debug3("secure_filename: terminating check at '%s'",
+ buf);
+ break;
+ }
/*
* dirname should always complete with a "/" path,
* but we can be paranoid and check for "." too
}
return 0;
}
+
+struct passwd *
+getpwnamallow(const char *user)
+{
+#ifdef HAVE_LOGIN_CAP
+ extern login_cap_t *lc;
+#ifdef BSD_AUTH
+ auth_session_t *as;
+#endif
+#endif
+ struct passwd *pw;
+
+ pw = getpwnam(user);
+ if (pw == NULL || !allowed_user(pw))
+ return (NULL);
+#ifdef HAVE_LOGIN_CAP
+ if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ debug("unable to get login class: %s", user);
+ return (NULL);
+ }
+#ifdef BSD_AUTH
+ if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
+ auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
+ debug("Approval failure for %s", user);
+ pw = NULL;
+ }
+ if (as != NULL)
+ auth_close(as);
+#endif
+#endif
+ if (pw != NULL)
+ return (pwcopy(pw));
+ return (NULL);
+}
+
+void
+auth_debug_add(const char *fmt,...)
+{
+ char buf[1024];
+ va_list args;
+
+ if (!auth_debug_init)
+ return;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ buffer_put_cstring(&auth_debug, buf);
+}
+
+void
+auth_debug_send(void)
+{
+ char *msg;
+
+ if (!auth_debug_init)
+ return;
+ while (buffer_len(&auth_debug)) {
+ msg = buffer_get_string(&auth_debug, NULL);
+ packet_send_debug("%s", msg);
+ xfree(msg);
+ }
+}
+
+void
+auth_debug_reset(void)
+{
+ if (auth_debug_init)
+ buffer_clear(&auth_debug);
+ else {
+ buffer_init(&auth_debug);
+ auth_debug_init = 1;
+ }
+}