]> andersk Git - openssh.git/blobdiff - auth.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / auth.c
diff --git a/auth.c b/auth.c
index 5d23343b927873167989c40de5c396dbaa088f4c..da87807a80e00a1a04e728eb313c3c2cb926ddf2 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.75 2006/08/03 03:34:41 deraadt Exp $ */
+/* $OpenBSD: auth.c,v 1.83 2010/01/13 23:47:26 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -32,6 +32,7 @@
 #include <netinet/in.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #ifdef HAVE_PATHS_H
 # include <paths.h>
 #endif
@@ -48,6 +49,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "xmalloc.h"
 #include "match.h"
@@ -93,7 +95,7 @@ allowed_user(struct passwd * pw)
 {
        struct stat st;
        const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
-       char *shell;
+       char *shell, *tmp, *chroot_path;
        u_int i;
 #ifdef USE_SHADOW
        struct spwd *spw = NULL;
@@ -113,15 +115,14 @@ allowed_user(struct passwd * pw)
 #endif /* USE_SHADOW */
 
        /* grab passwd field for locked account check */
+       passwd = pw->pw_passwd;
 #ifdef USE_SHADOW
        if (spw != NULL)
-#if defined(HAVE_LIBIAF)  &&  !defined(BROKEN_LIBIAF)
+#ifdef USE_LIBIAF
                passwd = get_iaf_password(pw);
 #else
                passwd = spw->sp_pwdp;
-#endif /* HAVE_LIBIAF  && !BROKEN_LIBIAF */
-#else
-       passwd = pw->pw_passwd;
+#endif /* USE_LIBIAF */
 #endif
 
        /* check for locked account */
@@ -141,9 +142,9 @@ allowed_user(struct passwd * pw)
                if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
                        locked = 1;
 #endif
-#if defined(HAVE_LIBIAF)  &&  !defined(BROKEN_LIBIAF)
+#ifdef USE_LIBIAF
                free(passwd);
-#endif /* HAVE_LIBIAF  && !BROKEN_LIBIAF */
+#endif /* USE_LIBIAF */
                if (locked) {
                        logit("User %.100s not allowed because account is locked",
                            pw->pw_name);
@@ -155,20 +156,40 @@ allowed_user(struct passwd * pw)
         * Get the shell from the password data.  An empty shell field is
         * legal, and means /bin/sh.
         */
-       shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
+       shell = xstrdup((pw->pw_shell[0] == '\0') ?
+           _PATH_BSHELL : pw->pw_shell);
+
+       /*
+        * Amend shell if chroot is requested.
+        */
+       if (options.chroot_directory != NULL &&
+           strcasecmp(options.chroot_directory, "none") != 0) {
+               tmp = tilde_expand_filename(options.chroot_directory,
+                   pw->pw_uid);
+               chroot_path = percent_expand(tmp, "h", pw->pw_dir,
+                   "u", pw->pw_name, (char *)NULL);
+               xfree(tmp);
+               xasprintf(&tmp, "%s/%s", chroot_path, shell);
+               xfree(shell);
+               shell = tmp;
+               free(chroot_path);
+       }
 
        /* deny if shell does not exists or is not executable */
        if (stat(shell, &st) != 0) {
                logit("User %.100s not allowed because shell %.100s does not exist",
                    pw->pw_name, shell);
+               xfree(shell);
                return 0;
        }
        if (S_ISREG(st.st_mode) == 0 ||
            (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
                logit("User %.100s not allowed because shell %.100s is not executable",
                    pw->pw_name, shell);
+               xfree(shell);
                return 0;
        }
+       xfree(shell);
 
        if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
            options.num_deny_groups > 0 || options.num_allow_groups > 0) {
@@ -410,7 +431,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
  *
  * Returns 0 on success and -1 on failure
  */
-int
+static int
 secure_filename(FILE *f, const char *file, struct passwd *pw,
     char *err, size_t errlen)
 {
@@ -454,7 +475,7 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
                        return -1;
                }
 
-               /* If are passed the homedir then we can stop */
+               /* If are past the homedir then we can stop */
                if (comparehome && strcmp(homedir, buf) == 0) {
                        debug3("secure_filename: terminating check at '%s'",
                            buf);
@@ -470,6 +491,50 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
        return 0;
 }
 
+FILE *
+auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
+{
+       char line[1024];
+       struct stat st;
+       int fd;
+       FILE *f;
+
+       /*
+        * Open the file containing the authorized keys
+        * Fail quietly if file does not exist
+        */
+       if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
+               if (errno != ENOENT)
+                       debug("Could not open keyfile '%s': %s", file,
+                          strerror(errno));
+               return NULL;
+       }
+
+       if (fstat(fd, &st) < 0) {
+               close(fd);
+               return NULL;
+       }
+       if (!S_ISREG(st.st_mode)) {
+               logit("User %s authorized keys %s is not a regular file",
+                   pw->pw_name, file);
+               close(fd);
+               return NULL;
+       }
+       unset_nonblock(fd);
+       if ((f = fdopen(fd, "r")) == NULL) {
+               close(fd);
+               return NULL;
+       }
+       if (options.strict_modes &&
+           secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+               fclose(f);
+               logit("Authentication refused: %s", line);
+               return NULL;
+       }
+
+       return f;
+}
+
 struct passwd *
 getpwnamallow(const char *user)
 {
@@ -569,8 +634,8 @@ fakepw(void)
        fake.pw_passwd =
            "$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
        fake.pw_gecos = "NOUSER";
-       fake.pw_uid = privsep_pw->pw_uid;
-       fake.pw_gid = privsep_pw->pw_gid;
+       fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
+       fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
 #ifdef HAVE_PW_CLASS_IN_PASSWD
        fake.pw_class = "";
 #endif
This page took 0.355484 seconds and 4 git commands to generate.