]> andersk Git - openssh.git/blobdiff - auth2.c
- itojun@cvs.openbsd.org 2002/05/13 02:37:39
[openssh.git] / auth2.c
diff --git a/auth2.c b/auth2.c
index 05b60128682b308e1575696e0468bc91dd3fa577..6bcc5652787fbac9e67e5205bee4291bb3331d3a 100644 (file)
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.60 2001/05/30 23:31:14 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.91 2002/05/13 02:37:39 itojun Exp $");
 
 #include <openssl/evp.h>
 
@@ -36,7 +36,7 @@ RCSID("$OpenBSD: auth2.c,v 1.60 2001/05/30 23:31:14 markus Exp $");
 #include "log.h"
 #include "servconf.h"
 #include "compat.h"
-#include "channel.h"
+#include "channels.h"
 #include "bufaux.h"
 #include "auth.h"
 #include "session.h"
@@ -47,22 +47,18 @@ RCSID("$OpenBSD: auth2.c,v 1.60 2001/05/30 23:31:14 markus Exp $");
 #include "pathnames.h"
 #include "uidswap.h"
 #include "auth-options.h"
-#include "misc.h"
 #include "hostfile.h"
 #include "canohost.h"
-#include "tildexpand.h"
 #include "match.h"
+#include "monitor_wrap.h"
+#include "atomicio.h"
 
 /* import */
 extern ServerOptions options;
 extern u_char *session_id2;
 extern int session_id2_len;
 
-#ifdef WITH_AIXAUTHENTICATE
-extern char *aixloginmsg;
-#endif
-
-static Authctxt        *x_authctxt = NULL;
+Authctxt *x_authctxt = NULL;
 static int one = 1;
 
 typedef struct Authmethod Authmethod;
@@ -74,25 +70,22 @@ struct Authmethod {
 
 /* protocol */
 
-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);
+static void input_service_request(int, u_int32_t, void *);
+static void input_userauth_request(int, u_int32_t, void *);
 
 /* helper */
-Authmethod     *authmethod_lookup(const char *name);
-char   *authmethods_get(void);
-int    user_key_allowed(struct passwd *pw, Key *key);
-int
-hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
-    Key *key);
+static Authmethod *authmethod_lookup(const char *);
+static char *authmethods_get(void);
+int user_key_allowed(struct passwd *, Key *);
+int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
 
 /* auth */
-void   userauth_banner(void);
-int    userauth_none(Authctxt *authctxt);
-int    userauth_passwd(Authctxt *authctxt);
-int    userauth_pubkey(Authctxt *authctxt);
-int    userauth_hostbased(Authctxt *authctxt);
-int    userauth_kbdint(Authctxt *authctxt);
+static void userauth_banner(void);
+static int userauth_none(Authctxt *);
+static int userauth_passwd(Authctxt *);
+static int userauth_pubkey(Authctxt *);
+static int userauth_hostbased(Authctxt *);
+static int userauth_kbdint(Authctxt *);
 
 Authmethod authmethods[] = {
        {"none",
@@ -117,43 +110,36 @@ Authmethod authmethods[] = {
  * loop until authctxt->success == TRUE
  */
 
-void
-do_authentication2()
+Authctxt *
+do_authentication2(void)
 {
        Authctxt *authctxt = authctxt_new();
 
        x_authctxt = authctxt;          /*XXX*/
 
-       /* challenge-reponse is implemented via keyboard interactive */
+       /* challenge-response is implemented via keyboard interactive */
        if (options.challenge_response_authentication)
                options.kbd_interactive_authentication = 1;
        if (options.pam_authentication_via_kbd_int)
                options.kbd_interactive_authentication = 1;
+       if (use_privsep)
+               options.pam_authentication_via_kbd_int = 0;
 
-       dispatch_init(&protocol_error);
+       dispatch_init(&dispatch_protocol_error);
        dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
        dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
-       do_authenticated(authctxt);
-}
 
-void
-protocol_error(int type, int plen, void *ctxt)
-{
-       log("auth: protocol error: type %d plen %d", type, plen);
-       packet_start(SSH2_MSG_UNIMPLEMENTED);
-       packet_put_int(0);
-       packet_send();
-       packet_write_wait();
+       return (authctxt);
 }
 
-void
-input_service_request(int type, int plen, void *ctxt)
+static void
+input_service_request(int type, u_int32_t seq, void *ctxt)
 {
        Authctxt *authctxt = ctxt;
        u_int len;
        int accept = 0;
        char *service = packet_get_string(&len);
-       packet_done();
+       packet_check_eom();
 
        if (authctxt == NULL)
                fatal("input_service_request: no authctxt");
@@ -179,8 +165,8 @@ input_service_request(int type, int plen, void *ctxt)
        xfree(service);
 }
 
-void
-input_userauth_request(int type, int plen, void *ctxt)
+static void
+input_userauth_request(int type, u_int32_t seq, void *ctxt)
 {
        Authctxt *authctxt = ctxt;
        Authmethod *m = NULL;
@@ -201,42 +187,35 @@ input_userauth_request(int type, int plen, void *ctxt)
 
        if (authctxt->attempt++ == 0) {
                /* setup auth context */
-               struct passwd *pw = NULL;
-               pw = getpwnam(user);
-               if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
-                       authctxt->pw = pwcopy(pw);
+               authctxt->pw = PRIVSEP(getpwnamallow(user));
+               if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
                        authctxt->valid = 1;
                        debug2("input_userauth_request: setting up authctxt for %s", user);
 #ifdef USE_PAM
-                       start_pam(pw->pw_name);
+                       PRIVSEP(start_pam(authctxt->pw->pw_name));
 #endif
                } else {
                        log("input_userauth_request: illegal user %s", user);
 #ifdef USE_PAM
-                       start_pam("NOUSER");
+                       PRIVSEP(start_pam("NOUSER"));
 #endif
                }
-               setproctitle("%s", pw ? user : "unknown");
+               setproctitle("%s%s", authctxt->pw ? user : "unknown",
+                   use_privsep ? " [net]" : "");
                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) {
-                       log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)",
-                           user, service, authctxt->user, authctxt->service);
-                       authctxt->valid = 0;
-               }
+               authctxt->style = style ? xstrdup(style) : NULL;
+               if (use_privsep)
+                       mm_inform_authserv(service, style);
+       } else if (strcmp(user, authctxt->user) != 0 ||
+           strcmp(service, authctxt->service) != 0) {
+               packet_disconnect("Change of username or service not allowed: "
+                   "(%s,%s) -> (%s,%s)",
+                   authctxt->user, authctxt->service, user, service);
        }
        /* reset state */
-       dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error);
+       auth2_challenge_stop(authctxt);
        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);
@@ -266,8 +245,8 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
                authenticated = 0;
 
 #ifdef USE_PAM
-       if (authenticated && authctxt->user && !do_pam_account(authctxt->user,
-           NULL))
+       if (!use_privsep && authenticated && authctxt->user && 
+           !do_pam_account(authctxt->user, NULL))
                authenticated = 0;
 #endif /* USE_PAM */
 
@@ -280,15 +259,21 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
        /* XXX todo: check if multiple auth methods are needed */
        if (authenticated == 1) {
                /* turn off userauth */
-               dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
+               dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
                packet_start(SSH2_MSG_USERAUTH_SUCCESS);
                packet_send();
                packet_write_wait();
                /* now we can break out */
                authctxt->success = 1;
        } else {
-               if (authctxt->failures++ > AUTH_FAIL_MAX)
+               if (authctxt->failures++ > AUTH_FAIL_MAX) {
+#ifdef WITH_AIXAUTHENTICATE
+                       loginfailed(authctxt->user,
+                           get_canonical_hostname(options.verify_reverse_mapping),
+                           "ssh");
+#endif /* WITH_AIXAUTHENTICATE */
                        packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+               }
                methods = authmethods_get();
                packet_start(SSH2_MSG_USERAUTH_FAILURE);
                packet_put_cstring(methods);
@@ -299,25 +284,45 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
        }
 }
 
-void
-userauth_banner(void)
+char *
+auth2_read_banner(void)
 {
        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)
-               return;
-       if (fstat(fd, &st) < 0)
-               goto done;
+       if ((fd = open(options.banner, O_RDONLY)) == -1)
+               return (NULL);
+       if (fstat(fd, &st) == -1) {
+               close(fd);
+               return (NULL);
+       }
        len = st.st_size;
        banner = xmalloc(len + 1);
-       if ((n = read(fd, banner, len)) < 0)
-               goto done;
+       n = atomicio(read, fd, banner, len);
+       close(fd);
+
+       if (n != len) {
+               free(banner);
+               return (NULL);
+       }
        banner[n] = '\0';
+       
+       return (banner);
+}
+
+static void
+userauth_banner(void)
+{
+       char *banner = NULL;
+
+       if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
+               return;
+
+       if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+               goto done;
+
        packet_start(SSH2_MSG_USERAUTH_BANNER);
        packet_put_cstring(banner);
        packet_put_cstring("");         /* language, unused */
@@ -326,37 +331,30 @@ userauth_banner(void)
 done:
        if (banner)
                xfree(banner);
-       close(fd);
        return;
 }
 
-int
+static int
 userauth_none(Authctxt *authctxt)
 {
        /* disable method "none", only allowed one time */
        Authmethod *m = authmethod_lookup("none");
        if (m != NULL)
                m->enabled = NULL;
-       packet_done();
+       packet_check_eom();
        userauth_banner();
 
        if (authctxt->valid == 0)
                return(0);
 
 #ifdef HAVE_CYGWIN
-       if (check_nt_auth(1, authctxt->pw->pw_uid) == 0)
+       if (check_nt_auth(1, authctxt->pw) == 0)
                return(0);
 #endif
-#ifdef USE_PAM
-       return auth_pam_password(authctxt->pw, "");
-#elif defined(HAVE_OSF_SIA)
-       return 0;
-#else /* !HAVE_OSF_SIA && !USE_PAM */
-       return auth_password(authctxt, "");
-#endif /* USE_PAM */
+       return PRIVSEP(auth_password(authctxt, ""));
 }
 
-int
+static int
 userauth_passwd(Authctxt *authctxt)
 {
        char *password;
@@ -367,25 +365,19 @@ userauth_passwd(Authctxt *authctxt)
        if (change)
                log("password change not supported");
        password = packet_get_string(&len);
-       packet_done();
+       packet_check_eom();
        if (authctxt->valid &&
 #ifdef HAVE_CYGWIN
-               check_nt_auth(1, authctxt->pw->pw_uid) &&
+           check_nt_auth(1, authctxt->pw) &&
 #endif
-#ifdef USE_PAM
-           auth_pam_password(authctxt->pw, password) == 1)
-#elif defined(HAVE_OSF_SIA)
-           auth_sia_password(authctxt->user, password) == 1)
-#else /* !USE_PAM && !HAVE_OSF_SIA */
-           auth_password(authctxt, password) == 1)
-#endif /* USE_PAM */
+           PRIVSEP(auth_password(authctxt, password)) == 1)
                authenticated = 1;
        memset(password, 0, len);
        xfree(password);
        return authenticated;
 }
 
-int
+static int
 userauth_kbdint(Authctxt *authctxt)
 {
        int authenticated = 0;
@@ -393,7 +385,7 @@ userauth_kbdint(Authctxt *authctxt)
 
        lang = packet_get_string(NULL);
        devs = packet_get_string(NULL);
-       packet_done();
+       packet_check_eom();
 
        debug("keyboard-interactive devs %s", devs);
 
@@ -407,18 +399,19 @@ userauth_kbdint(Authctxt *authctxt)
        xfree(devs);
        xfree(lang);
 #ifdef HAVE_CYGWIN
-       if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
+       if (check_nt_auth(0, authctxt->pw) == 0)
                return(0);
 #endif
        return authenticated;
 }
 
-int
+static int
 userauth_pubkey(Authctxt *authctxt)
 {
        Buffer b;
-       Key *key;
-       char *pkalg, *pkblob, *sig;
+       Key *key = NULL;
+       char *pkalg;
+       u_char *pkblob, *sig;
        u_int alen, blen, slen;
        int have_sig, pktype;
        int authenticated = 0;
@@ -444,87 +437,98 @@ userauth_pubkey(Authctxt *authctxt)
        pktype = key_type_from_name(pkalg);
        if (pktype == KEY_UNSPEC) {
                /* this is perfectly legal */
-               log("userauth_pubkey: unsupported public key algorithm: %s", pkalg);
-               xfree(pkalg);
-               xfree(pkblob);
-               return 0;
+               log("userauth_pubkey: unsupported public key algorithm: %s",
+                   pkalg);
+               goto done;
        }
        key = key_from_blob(pkblob, blen);
-       if (key != NULL) {
-               if (have_sig) {
-                       sig = packet_get_string(&slen);
-                       packet_done();
-                       buffer_init(&b);
-                       if (datafellows & SSH_OLD_SESSIONID) {
-                               buffer_append(&b, session_id2, session_id2_len);
-                       } else {
-                               buffer_put_string(&b, session_id2, session_id2_len);
-                       }
-                       /* reconstruct packet */
-                       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
-                       buffer_put_cstring(&b, authctxt->user);
-                       buffer_put_cstring(&b,
-                           datafellows & SSH_BUG_PKSERVICE ?
-                           "ssh-userauth" :
-                           authctxt->service);
-                       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, pkalg);
-                       }
-                       buffer_put_string(&b, pkblob, blen);
+       if (key == NULL) {
+               error("userauth_pubkey: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("userauth_pubkey: type mismatch for decoded key "
+                   "(received %d, expected %d)", key->type, pktype);
+               goto done;
+       }
+       if (have_sig) {
+               sig = packet_get_string(&slen);
+               packet_check_eom();
+               buffer_init(&b);
+               if (datafellows & SSH_OLD_SESSIONID) {
+                       buffer_append(&b, session_id2, session_id2_len);
+               } else {
+                       buffer_put_string(&b, session_id2, session_id2_len);
+               }
+               /* reconstruct packet */
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+               buffer_put_cstring(&b, authctxt->user);
+               buffer_put_cstring(&b,
+                   datafellows & SSH_BUG_PKSERVICE ?
+                   "ssh-userauth" :
+                   authctxt->service);
+               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, pkalg);
+               }
+               buffer_put_string(&b, pkblob, blen);
 #ifdef DEBUG_PK
-                       buffer_dump(&b);
+               buffer_dump(&b);
 #endif
-                       /* test for correct signature */
-                       if (user_key_allowed(authctxt->pw, key) &&
-                           key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
-                               authenticated = 1;
-                       buffer_clear(&b);
-                       xfree(sig);
-               } else {
-                       debug("test whether pkalg/pkblob are acceptable");
-                       packet_done();
-
-                       /* XXX fake reply and always send PK_OK ? */
-                       /*
-                        * XXX this allows testing whether a user is allowed
-                        * to login: if you happen to have a valid pubkey this
-                        * message is sent. the message is NEVER sent at all
-                        * if a user is not allowed to login. is this an
-                        * issue? -markus
-                        */
-                       if (user_key_allowed(authctxt->pw, key)) {
-                               packet_start(SSH2_MSG_USERAUTH_PK_OK);
-                               packet_put_string(pkalg, alen);
-                               packet_put_string(pkblob, blen);
-                               packet_send();
-                               packet_write_wait();
-                               authctxt->postponed = 1;
-                       }
+               /* test for correct signature */
+               authenticated = 0;
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
+                   PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+                               buffer_len(&b))) == 1)
+                       authenticated = 1;
+               buffer_clear(&b);
+               xfree(sig);
+       } else {
+               debug("test whether pkalg/pkblob are acceptable");
+               packet_check_eom();
+
+               /* XXX fake reply and always send PK_OK ? */
+               /*
+                * XXX this allows testing whether a user is allowed
+                * to login: if you happen to have a valid pubkey this
+                * message is sent. the message is NEVER sent at all
+                * if a user is not allowed to login. is this an
+                * issue? -markus
+                */
+               if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
+                       packet_start(SSH2_MSG_USERAUTH_PK_OK);
+                       packet_put_string(pkalg, alen);
+                       packet_put_string(pkblob, blen);
+                       packet_send();
+                       packet_write_wait();
+                       authctxt->postponed = 1;
                }
-               if (authenticated != 1)
-                       auth_clear_options();
-               key_free(key);
        }
+       if (authenticated != 1)
+               auth_clear_options();
+done:
        debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
+       if (key != NULL)
+               key_free(key);
        xfree(pkalg);
        xfree(pkblob);
 #ifdef HAVE_CYGWIN
-       if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
+       if (check_nt_auth(0, authctxt->pw) == 0)
                return(0);
 #endif
        return authenticated;
 }
 
-int
+static int
 userauth_hostbased(Authctxt *authctxt)
 {
        Buffer b;
-       Key *key;
-       char *pkalg, *pkblob, *sig, *cuser, *chost, *service;
+       Key *key = NULL;
+       char *pkalg, *cuser, *chost, *service;
+       u_char *pkblob, *sig;
        u_int alen, blen, slen;
        int pktype;
        int authenticated = 0;
@@ -557,7 +561,12 @@ userauth_hostbased(Authctxt *authctxt)
        }
        key = key_from_blob(pkblob, blen);
        if (key == NULL) {
-               debug("userauth_hostbased: cannot decode key: %s", pkalg);
+               error("userauth_hostbased: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       if (key->type != pktype) {
+               error("userauth_hostbased: type mismatch for decoded key "
+                   "(received %d, expected %d)", key->type, pktype);
                goto done;
        }
        service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
@@ -577,15 +586,17 @@ userauth_hostbased(Authctxt *authctxt)
        buffer_dump(&b);
 #endif
        /* test for allowed key and correct signature */
-       if (hostbased_key_allowed(authctxt->pw, cuser, chost, key) &&
-           key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
+       authenticated = 0;
+       if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
+           PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+                       buffer_len(&b))) == 1)
                authenticated = 1;
 
        buffer_clear(&b);
-       key_free(key);
-
 done:
        debug2("userauth_hostbased: authenticated %d", authenticated);
+       if (key != NULL)
+               key_free(key);
        xfree(pkalg);
        xfree(pkblob);
        xfree(cuser);
@@ -604,39 +615,30 @@ auth_get_user(void)
 
 #define        DELIM   ","
 
-char *
+static char *
 authmethods_get(void)
 {
        Authmethod *method = NULL;
-       u_int size = 0;
+       Buffer b;
        char *list;
 
+       buffer_init(&b);
        for (method = authmethods; method->name != NULL; method++) {
                if (strcmp(method->name, "none") == 0)
                        continue;
                if (method->enabled != NULL && *(method->enabled) != 0) {
-                       if (size != 0)
-                               size += strlen(DELIM);
-                       size += strlen(method->name);
-               }
-       }
-       size++;                 /* trailing '\0' */
-       list = xmalloc(size);
-       list[0] = '\0';
-
-       for (method = authmethods; method->name != NULL; method++) {
-               if (strcmp(method->name, "none") == 0)
-                       continue;
-               if (method->enabled != NULL && *(method->enabled) != 0) {
-                       if (list[0] != '\0')
-                               strlcat(list, DELIM, size);
-                       strlcat(list, method->name, size);
+                       if (buffer_len(&b) > 0)
+                               buffer_append(&b, ",", 1);
+                       buffer_append(&b, method->name, strlen(method->name));
                }
        }
+       buffer_append(&b, "\0", 1);
+       list = xstrdup(buffer_ptr(&b));
+       buffer_free(&b);
        return list;
 }
 
-Authmethod *
+static Authmethod *
 authmethod_lookup(const char *name)
 {
        Authmethod *method = NULL;
@@ -651,15 +653,16 @@ authmethod_lookup(const char *name)
 }
 
 /* return 1 if user allows given key */
-int
-user_key_allowed(struct passwd *pw, Key *key)
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
 {
-       char line[8192], *file;
+       char line[8192];
        int found_key = 0;
        FILE *f;
        u_long linenum = 0;
        struct stat st;
        Key *found;
+       char *fp;
 
        if (pw == NULL)
                return 0;
@@ -667,15 +670,12 @@ user_key_allowed(struct passwd *pw, Key *key)
        /* Temporarily use the user's uid. */
        temporarily_use_uid(pw);
 
-       /* The authorized keys. */
-       file = authorized_keys_file2(pw);
        debug("trying public key file %s", file);
 
        /* Fail quietly if file does not exist */
        if (stat(file, &st) < 0) {
                /* Restore the privileged uid. */
                restore_uid();
-               xfree(file);
                return 0;
        }
        /* Open the file containing the authorized keys. */
@@ -683,12 +683,10 @@ user_key_allowed(struct passwd *pw, Key *key)
        if (!f) {
                /* Restore the privileged uid. */
                restore_uid();
-               xfree(file);
                return 0;
        }
        if (options.strict_modes &&
-           secure_filename(f, file, pw->pw_uid, line, sizeof(line)) != 0) {
-               xfree(file);
+           secure_filename(f, file, pw, line, sizeof(line)) != 0) {
                fclose(f);
                log("Authentication refused: %s", line);
                restore_uid();
@@ -707,7 +705,7 @@ user_key_allowed(struct passwd *pw, Key *key)
                if (!*cp || *cp == '\n' || *cp == '#')
                        continue;
 
-               if (key_read(found, &cp) == -1) {
+               if (key_read(found, &cp) != 1) {
                        /* no key?  check if there are options for this key */
                        int quoted = 0;
                        debug2("user_key_allowed: check options: '%s'", cp);
@@ -721,7 +719,7 @@ user_key_allowed(struct passwd *pw, Key *key)
                        /* Skip remaining whitespace. */
                        for (; *cp == ' ' || *cp == '\t'; cp++)
                                ;
-                       if (key_read(found, &cp) == -1) {
+                       if (key_read(found, &cp) != 1) {
                                debug2("user_key_allowed: advance: '%s'", cp);
                                /* still no key?  advance to next line*/
                                continue;
@@ -730,32 +728,53 @@ user_key_allowed(struct passwd *pw, Key *key)
                if (key_equal(found, key) &&
                    auth_parse_options(pw, options, file, linenum) == 1) {
                        found_key = 1;
-                       debug("matching key found: file %s, line %ld",
+                       debug("matching key found: file %s, line %lu",
                            file, linenum);
+                       fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+                       verbose("Found matching %s key: %s",
+                           key_type(found), fp);
+                       xfree(fp);
                        break;
                }
        }
        restore_uid();
        fclose(f);
-       xfree(file);
        key_free(found);
        if (!found_key)
                debug2("key not found");
        return found_key;
 }
 
+/* check whether given key is in .ssh/authorized_keys* */
+int
+user_key_allowed(struct passwd *pw, Key *key)
+{
+       int success;
+       char *file;
+
+       file = authorized_keys_file(pw);
+       success = user_key_allowed2(pw, key, file);
+       xfree(file);
+       if (success)
+               return success;
+
+       /* try suffix "2" for backward compat, too */
+       file = authorized_keys_file2(pw);
+       success = user_key_allowed2(pw, key, file);
+       xfree(file);
+       return success;
+}
+
 /* return 1 if given hostkey is allowed */
 int
 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
     Key *key)
 {
-       Key *found;
        const char *resolvedname, *ipaddr, *lookup;
-       struct stat st;
-       char *user_hostfile;
-       int host_status, len;
+       HostStatus host_status;
+       int len;
 
-       resolvedname = get_canonical_hostname(options.reverse_mapping_check);
+       resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
        ipaddr = get_remote_ipaddr();
 
        debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
@@ -780,32 +799,16 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
        }
        debug2("userauth_hostbased: access allowed by auth_rhosts2");
 
-       /* XXX this is copied from auth-rh-rsa.c and should be shared */
-       found = key_new(key->type);
-       host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE2, lookup,
-           key, found, NULL);
-
-       if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
-               user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE2,
-                   pw->pw_uid);
-               if (options.strict_modes &&
-                   (stat(user_hostfile, &st) == 0) &&
-                   ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
-                    (st.st_mode & 022) != 0)) {
-                       log("Hostbased authentication refused for %.100s: "
-                           "bad owner or modes for %.200s",
-                           pw->pw_name, user_hostfile);
-               } else {
-                       temporarily_use_uid(pw);
-                       host_status = check_host_in_hostfile(user_hostfile,
-                           lookup, key, found, NULL);
-                       restore_uid();
-               }
-               xfree(user_hostfile);
-       }
-       key_free(found);
+       host_status = check_key_in_hostfiles(pw, key, lookup,
+           _PATH_SSH_SYSTEM_HOSTFILE,
+           options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
+
+       /* backward compat if no key has been found. */
+       if (host_status == HOST_NEW)
+               host_status = check_key_in_hostfiles(pw, key, lookup,
+                   _PATH_SSH_SYSTEM_HOSTFILE2,
+                   options.ignore_user_known_hosts ? NULL :
+                   _PATH_SSH_USER_HOSTFILE2);
 
-       debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ?
-           "ok" : "not found", lookup);
        return (host_status == HOST_OK);
 }
This page took 0.083124 seconds and 4 git commands to generate.