]> andersk Git - openssh.git/blobdiff - auth2.c
- markus@cvs.openbsd.org 2001/05/18 14:13:29
[openssh.git] / auth2.c
diff --git a/auth2.c b/auth2.c
index bab1c2ed83777a33ae092f3359186aaa55209a12..e800c0587490538ad45e106c26f8c81d1a046a5a 100644 (file)
--- a/auth2.c
+++ b/auth2.c
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.28 2001/01/18 17:00:00 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.57 2001/05/18 14:13:28 markus Exp $");
 
-#ifdef HAVE_OSF_SIA
-# include <sia.h>
-# include <siad.h>
-#endif
-
-#include <openssl/dsa.h>
-#include <openssl/rsa.h>
 #include <openssl/evp.h>
 
+#include "ssh2.h"
 #include "xmalloc.h"
 #include "rsa.h"
-#include "ssh.h"
-#include "pty.h"
+#include "sshpty.h"
 #include "packet.h"
 #include "buffer.h"
+#include "log.h"
 #include "servconf.h"
 #include "compat.h"
 #include "channels.h"
 #include "bufaux.h"
-#include "ssh2.h"
 #include "auth.h"
 #include "session.h"
 #include "dispatch.h"
-#include "auth.h"
 #include "key.h"
+#include "cipher.h"
 #include "kex.h"
-
+#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"
 
 /* import */
 extern ServerOptions options;
@@ -63,10 +61,6 @@ extern int session_id2_len;
 #ifdef WITH_AIXAUTHENTICATE
 extern char *aixloginmsg;
 #endif
-#ifdef HAVE_OSF_SIA
-extern int saved_argc;
-extern char **saved_argv;
-#endif
 
 static Authctxt        *x_authctxt = NULL;
 static int one = 1;
@@ -86,15 +80,19 @@ void        protocol_error(int type, int plen, void *ctxt);
 
 /* helper */
 Authmethod     *authmethod_lookup(const char *name);
-struct passwd  *pwcopy(struct passwd *pw);
-int    user_key_allowed(struct passwd *pw, Key *key);
 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);
 
 /* auth */
 void   userauth_banner(void);
+void   userauth_reply(Authctxt *authctxt, int authenticated);
 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);
 
 Authmethod authmethods[] = {
@@ -104,12 +102,15 @@ Authmethod authmethods[] = {
        {"publickey",
                userauth_pubkey,
                &options.pubkey_authentication},
-       {"keyboard-interactive",
-               userauth_kbdint,
-               &options.kbd_interactive_authentication},
        {"password",
                userauth_passwd,
                &options.password_authentication},
+       {"keyboard-interactive",
+               userauth_kbdint,
+               &options.kbd_interactive_authentication},
+       {"hostbased",
+               userauth_hostbased,
+               &options.hostbased_authentication},
        {NULL, NULL, NULL}
 };
 
@@ -124,17 +125,16 @@ do_authentication2()
 
        x_authctxt = authctxt;          /*XXX*/
 
-#ifdef AFS
-       /* If machine has AFS, set process authentication group. */
-       if (k_hasafs()) {
-               k_setpag();
-               k_unlog();
-       }
-#endif
+       /* challenge-reponse 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;
+
        dispatch_init(&protocol_error);
        dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
        dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
-       do_authenticated2(authctxt);
+       do_authenticated(authctxt);
 }
 
 void
@@ -203,7 +203,6 @@ input_userauth_request(int type, int plen, void *ctxt)
        if (authctxt->attempt++ == 0) {
                /* setup auth context */
                struct passwd *pw = NULL;
-               setproctitle("%s", user);
                pw = getpwnam(user);
                if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
                        authctxt->pw = pwcopy(pw);
@@ -218,13 +217,14 @@ input_userauth_request(int type, int plen, void *ctxt)
                        start_pam("NOUSER");
 #endif
                }
+               setproctitle("%s", pw ? user : "unknown");
                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: missmatch: (%s,%s)!=(%s,%s)",
+                       log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)",
                            user, service, authctxt->user, authctxt->service);
                        authctxt->valid = 0;
                }
@@ -232,6 +232,12 @@ input_userauth_request(int type, int plen, void *ctxt)
        /* reset state */
        dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error);
        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);
@@ -239,16 +245,28 @@ input_userauth_request(int type, int plen, void *ctxt)
                debug2("input_userauth_request: try method %s", method);
                authenticated = m->userauth(authctxt);
        }
+       userauth_finish(authctxt, authenticated, method);
+
+       xfree(service);
+       xfree(user);
+       xfree(method);
+}
+
+void
+userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+{
        if (!authctxt->valid && authenticated)
                fatal("INTERNAL ERROR: authenticated invalid user %s",
                    authctxt->user);
 
        /* Special handling for root */
-       if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
+       if (authenticated && authctxt->pw->pw_uid == 0 &&
+           !auth_root_allowed(method))
                authenticated = 0;
 
 #ifdef USE_PAM
-       if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL))
+       if (authenticated && authctxt->user && !do_pam_account(authctxt->user,
+           NULL))
                authenticated = 0;
 #endif /* USE_PAM */
 
@@ -257,10 +275,6 @@ input_userauth_request(int type, int plen, void *ctxt)
 
        if (!authctxt->postponed)
                userauth_reply(authctxt, authenticated);
-
-       xfree(service);
-       xfree(user);
-       xfree(method);
 }
 
 void
@@ -273,11 +287,8 @@ userauth_banner(void)
 
        if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
                return;
-       if ((fd = open(options.banner, O_RDONLY)) < 0) {
-               error("userauth_banner: open %s failed: %s",
-                   options.banner, strerror(errno));
+       if ((fd = open(options.banner, O_RDONLY)) < 0)
                return;
-       }
        if (fstat(fd, &st) < 0)
                goto done;
        len = st.st_size;
@@ -297,17 +308,18 @@ done:
        return;
 }
 
-void   
+void
 userauth_reply(Authctxt *authctxt, int authenticated)
 {
        char *methods;
 
        /* XXX todo: check if multiple auth methods are needed */
-       if (authenticated) {
+       if (authenticated == 1) {
 #ifdef WITH_AIXAUTHENTICATE
                /* We don't have a pty yet, so just label the line as "ssh" */
-               if (loginsuccess(authctxt->user?authctxt->user:"NOUSER", 
-                       get_canonical_hostname(), "ssh", &aixloginmsg) < 0)
+               if (loginsuccess(authctxt->user?authctxt->user:"NOUSER",
+                   get_canonical_hostname(options.reverse_mapping_check),
+                   "ssh", &aixloginmsg) < 0)
                        aixloginmsg = NULL;
 #endif /* WITH_AIXAUTHENTICATE */
                /* turn off userauth */
@@ -319,7 +331,7 @@ userauth_reply(Authctxt *authctxt, int authenticated)
                authctxt->success = 1;
        } else {
                if (authctxt->failures++ > AUTH_FAIL_MAX)
-                        packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+                       packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
                methods = authmethods_get();
                packet_start(SSH2_MSG_USERAUTH_FAILURE);
                packet_put_cstring(methods);
@@ -338,11 +350,11 @@ userauth_none(Authctxt *authctxt)
        if (m != NULL)
                m->enabled = NULL;
        packet_done();
-        userauth_banner();
+       userauth_banner();
 
        if (authctxt->valid == 0)
                return(0);
-               
+
 #ifdef HAVE_CYGWIN
        if (check_nt_auth(1, authctxt->pw->pw_uid) == 0)
                return(0);
@@ -350,11 +362,9 @@ userauth_none(Authctxt *authctxt)
 #ifdef USE_PAM
        return auth_pam_password(authctxt->pw, "");
 #elif defined(HAVE_OSF_SIA)
-       return (sia_validate_user(NULL, saved_argc, saved_argv, 
-               get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER", 
-                       NULL, 0, NULL, "") == SIASUCCESS);
+       return 0;
 #else /* !HAVE_OSF_SIA && !USE_PAM */
-       return auth_password(authctxt->pw, "");
+       return auth_password(authctxt, "");
 #endif /* USE_PAM */
 }
 
@@ -377,11 +387,9 @@ userauth_passwd(Authctxt *authctxt)
 #ifdef USE_PAM
            auth_pam_password(authctxt->pw, password) == 1)
 #elif defined(HAVE_OSF_SIA)
-           sia_validate_user(NULL, saved_argc, saved_argv, 
-                       get_canonical_hostname(), authctxt->user?authctxt->user:"NOUSER", 
-                       NULL, 0, NULL, password) == SIASUCCESS)
+           auth_sia_password(authctxt->user, password) == 1)
 #else /* !USE_PAM && !HAVE_OSF_SIA */
-           auth_password(authctxt->pw, password) == 1)
+           auth_password(authctxt, password) == 1)
 #endif /* USE_PAM */
                authenticated = 1;
        memset(password, 0, len);
@@ -393,23 +401,23 @@ int
 userauth_kbdint(Authctxt *authctxt)
 {
        int authenticated = 0;
-       char *lang = NULL;
-       char *devs = NULL;
+       char *lang, *devs;
 
        lang = packet_get_string(NULL);
        devs = packet_get_string(NULL);
        packet_done();
 
-       debug("keyboard-interactive language %s devs %s", lang, devs);
+       debug("keyboard-interactive devs %s", devs);
 
-       authenticated = auth2_challenge(authctxt, devs);
+       if (options.challenge_response_authentication)
+               authenticated = auth2_challenge(authctxt, devs);
 
 #ifdef USE_PAM
-       if (authenticated == 0)
+       if (authenticated == 0 && options.pam_authentication_via_kbd_int)
                authenticated = auth2_pam(authctxt);
 #endif
-       xfree(lang);
        xfree(devs);
+       xfree(lang);
 #ifdef HAVE_CYGWIN
        if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
                return(0);
@@ -476,7 +484,7 @@ userauth_pubkey(Authctxt *authctxt)
                        } else {
                                buffer_put_cstring(&b, "publickey");
                                buffer_put_char(&b, have_sig);
-                               buffer_put_cstring(&b, key_ssh_name(key));
+                               buffer_put_cstring(&b, pkalg);
                        }
                        buffer_put_string(&b, pkblob, blen);
 #ifdef DEBUG_PK
@@ -506,7 +514,7 @@ userauth_pubkey(Authctxt *authctxt)
                                packet_put_string(pkblob, blen);
                                packet_send();
                                packet_write_wait();
-                               authenticated = -1;
+                               authctxt->postponed = 1;
                        }
                }
                if (authenticated != 1)
@@ -523,6 +531,81 @@ userauth_pubkey(Authctxt *authctxt)
        return authenticated;
 }
 
+int
+userauth_hostbased(Authctxt *authctxt)
+{
+       Buffer b;
+       Key *key;
+       char *pkalg, *pkblob, *sig, *cuser, *chost, *service;
+       u_int alen, blen, slen;
+       int pktype;
+       int authenticated = 0;
+
+       if (!authctxt->valid) {
+               debug2("userauth_hostbased: disabled because of invalid user");
+               return 0;
+       }
+       pkalg = packet_get_string(&alen);
+       pkblob = packet_get_string(&blen);
+       chost = packet_get_string(NULL);
+       cuser = packet_get_string(NULL);
+       sig = packet_get_string(&slen);
+
+       debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+           cuser, chost, pkalg, slen);
+#ifdef DEBUG_PK
+       debug("signature:");
+       buffer_init(&b);
+       buffer_append(&b, sig, slen);
+       buffer_dump(&b);
+       buffer_free(&b);
+#endif
+       pktype = key_type_from_name(pkalg);
+       if (pktype == KEY_UNSPEC) {
+               /* this is perfectly legal */
+               log("userauth_hostbased: unsupported "
+                   "public key algorithm: %s", pkalg);
+               goto done;
+       }
+       key = key_from_blob(pkblob, blen);
+       if (key == NULL) {
+               debug("userauth_hostbased: cannot decode key: %s", pkalg);
+               goto done;
+       }
+       service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+           authctxt->service;
+       buffer_init(&b);
+       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, service);
+       buffer_put_cstring(&b, "hostbased");
+       buffer_put_string(&b, pkalg, alen);
+       buffer_put_string(&b, pkblob, blen);
+       buffer_put_cstring(&b, chost);
+       buffer_put_cstring(&b, cuser);
+#ifdef DEBUG_PK
+       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 = 1;
+
+       buffer_clear(&b);
+       key_free(key);
+
+done:
+       debug2("userauth_hostbased: authenticated %d", authenticated);
+       xfree(pkalg);
+       xfree(pkblob);
+       xfree(cuser);
+       xfree(chost);
+       xfree(sig);
+       return authenticated;
+}
+
 /* get current user */
 
 struct passwd*
@@ -583,7 +666,7 @@ authmethod_lookup(const char *name)
 int
 user_key_allowed(struct passwd *pw, Key *key)
 {
-       char line[8192], file[1024];
+       char line[8192], file[MAXPATHLEN];
        int found_key = 0;
        FILE *f;
        u_long linenum = 0;
@@ -594,11 +677,11 @@ user_key_allowed(struct passwd *pw, Key *key)
                return 0;
 
        /* Temporarily use the user's uid. */
-       temporarily_use_uid(pw->pw_uid);
+       temporarily_use_uid(pw);
 
        /* The authorized keys. */
        snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
-           SSH_USER_PERMITTED_KEYS2);
+           _PATH_SSH_USER_PERMITTED_KEYS2);
 
        /* Fail quietly if file does not exist */
        if (stat(file, &st) < 0) {
@@ -626,10 +709,10 @@ user_key_allowed(struct passwd *pw, Key *key)
                            key_type(key), pw->pw_name, file);
                        fail = 1;
                } else {
-                       /* Check path to SSH_USER_PERMITTED_KEYS */
+                       /* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
                        int i;
                        static const char *check[] = {
-                               "", SSH_USER_DIR, NULL
+                               "", _PATH_SSH_USER_DIR, NULL
                        };
                        for (i = 0; check[i]; i++) {
                                snprintf(line, sizeof line, "%.500s/%.100s",
@@ -648,7 +731,7 @@ user_key_allowed(struct passwd *pw, Key *key)
                }
                if (fail) {
                        fclose(f);
-                       log("%s",buf);
+                       log("%s", buf);
                        restore_uid();
                        return 0;
                }
@@ -686,7 +769,7 @@ user_key_allowed(struct passwd *pw, Key *key)
                        }
                }
                if (key_equal(found, key) &&
-                   auth_parse_options(pw, options, linenum) == 1) {
+                   auth_parse_options(pw, options, file, linenum) == 1) {
                        found_key = 1;
                        debug("matching key found: file %s, line %ld",
                            file, linenum);
@@ -696,5 +779,73 @@ user_key_allowed(struct passwd *pw, Key *key)
        restore_uid();
        fclose(f);
        key_free(found);
+       if (!found_key)
+               debug2("key not found");
        return found_key;
 }
+
+/* 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;
+
+       resolvedname = get_canonical_hostname(options.reverse_mapping_check);
+       ipaddr = get_remote_ipaddr();
+
+       debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
+           chost, resolvedname, ipaddr);
+
+       if (options.hostbased_uses_name_from_packet_only) {
+               if (auth_rhosts2(pw, cuser, chost, chost) == 0)
+                       return 0;
+               lookup = chost;
+       } else {
+               if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
+                       debug2("stripping trailing dot from chost %s", chost);
+                       chost[len - 1] = '\0';
+               }
+               if (strcasecmp(resolvedname, chost) != 0)
+                       log("userauth_hostbased mismatch: "
+                           "client sends %s, but we resolve %s to %s",
+                           chost, ipaddr, resolvedname);
+               if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
+                       return 0;
+               lookup = resolvedname;
+       }
+       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);
+
+       debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ?
+           "ok" : "not found", lookup);
+       return (host_status == HOST_OK);
+}
This page took 0.055026 seconds and 4 git commands to generate.