]> andersk Git - gssapi-openssh.git/blobdiff - openssh/auth2-gss.c
This fixes an issue with determining the auth method, for reporting
[gssapi-openssh.git] / openssh / auth2-gss.c
index def1b7bb7d48d91fd7927fb108701a2ed4554aaf..c8f28acef0bc7668b82b3684cdbcb8d5e1d3a6ce 100644 (file)
@@ -1,7 +1,7 @@
-/*     $OpenBSD: auth2-gss.c,v 1.8 2004/06/21 17:36:31 avsm Exp $      */
+/* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #ifdef GSSAPI
 
+#include <sys/types.h>
+
+#include <stdarg.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
 #include "auth.h"
 #include "ssh2.h"
-#include "xmalloc.h"
 #include "log.h"
 #include "dispatch.h"
+#include "buffer.h"
 #include "servconf.h"
-#include "compat.h"
 #include "packet.h"
-#include "monitor_wrap.h"
-
 #include "ssh-gss.h"
+#include "monitor_wrap.h"
 
 extern ServerOptions options;
 
@@ -48,23 +53,57 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_errtok(int, u_int32_t, void *);
 
-static int gssapi_with_mic = 1;        /* flag to toggle "gssapi-with-mic" vs.
-                                  "gssapi" */
-
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
 static int
-userauth_external(Authctxt *authctxt)
+userauth_gsskeyex(Authctxt *authctxt)
 {
-        packet_check_eom();
+       int authenticated = 0;
+       Buffer b, b2;
+       gss_buffer_desc mic, gssbuf, gssbuf2;
+       u_int len;
 
-       if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-               return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
+       mic.value = packet_get_string(&len);
+       mic.length = len;
+
+       packet_check_eom();
+
+       ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+           "gssapi-keyex");
+
+       gssbuf.value = buffer_ptr(&b);
+       gssbuf.length = buffer_len(&b);
+
+       /* client may have used empty username to determine target
+          name from GSSAPI context */
+       ssh_gssapi_buildmic(&b2, "", authctxt->service, "gssapi-keyex");
+
+       gssbuf2.value = buffer_ptr(&b2);
+       gssbuf2.length = buffer_len(&b2);
+
+       /* gss_kex_context is NULL with privsep, so we can't check it here */
+       if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+                                                  &gssbuf, &mic))) ||
+           !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+                                                  &gssbuf2, &mic)))) {
+           if (authctxt->valid && authctxt->user && authctxt->user[0]) {
+            authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                                      authctxt->pw,
+                                                      1 /* gssapi-keyex */));
+           }
        }
-       return 0;
+       
+       buffer_free(&b);
+       buffer_free(&b2);
+       xfree(mic.value);
+
+       return (authenticated);
 }
 
 /*
  * We only support those mechanisms that we know about (ie ones that we know
- * how to check local user kuserok and the like
+ * how to check local user kuserok and the like)
  */
 static int
 userauth_gssapi(Authctxt *authctxt)
@@ -76,7 +115,7 @@ userauth_gssapi(Authctxt *authctxt)
        int present;
        OM_uint32 ms;
        u_int len;
-       char *doid = NULL;
+       u_char *doid = NULL;
 
        /* authctxt->valid may be 0 if we haven't yet determined
           username from gssapi context. */
@@ -100,9 +139,8 @@ userauth_gssapi(Authctxt *authctxt)
                present = 0;
                doid = packet_get_string(&len);
 
-               if (len > 2 &&
-                  doid[0] == SSH_GSS_OIDTYPE &&
-                  doid[1] == len - 2) {
+               if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
+                   doid[1] == len - 2) {
                        goid.elements = doid + 2;
                        goid.length   = len - 2;
                        gss_test_oid_set_member(&ms, &goid, supported,
@@ -116,15 +154,19 @@ userauth_gssapi(Authctxt *authctxt)
 
        if (!present) {
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
+               if (ctxt != NULL)
+                       ssh_gssapi_delete_ctx(&ctxt);
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
-       authctxt->methoddata=(void *)ctxt;
+       authctxt->methoddata = (void *)ctxt;
 
        packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
 
@@ -174,9 +216,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
                }
                authctxt->postponed = 0;
                dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
-               userauth_finish(authctxt, 0,
-                               gssapi_with_mic ? "gssapi-with-mic" :
-                                                 "gssapi");
+               userauth_finish(authctxt, 0, "gssapi-with-mic");
        } else {
                if (send_tok.length != 0) {
                        packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@@ -185,7 +225,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
                }
                if (maj_status == GSS_S_COMPLETE) {
                        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
-                       if (flags & GSS_C_INTEG_FLAG && gssapi_with_mic)
+                       if (flags & GSS_C_INTEG_FLAG)
                                dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
                                    &input_gssapi_mic);
                        else
@@ -233,28 +273,28 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
 }
 
 static void
-gssapi_set_implicit_username(Authctxt *authctxt)
+gssapi_set_username(Authctxt *authctxt)
 {
+    char *lname = NULL;
+
     if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) {
-       char *lname = NULL;
-       PRIVSEP(ssh_gssapi_localname(&lname));
-       if (lname && lname[0] != '\0') {
-           if (authctxt->user) xfree(authctxt->user);
-           authctxt->user = lname;
-           debug("set username to %s from gssapi context", lname);
-           authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
-           if (authctxt->pw) {
-               authctxt->valid = 1;
-           }
-       } else {
-           debug("failed to set username from gssapi context");
-       }
-    }
-    if (authctxt->pw) {
+        PRIVSEP(ssh_gssapi_localname(&lname));
+        if (lname && lname[0] != '\0') {
+            if (authctxt->user) xfree(authctxt->user);
+            authctxt->user = lname;
+            debug("set username to %s from gssapi context", lname);
+            authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
+            if (authctxt->pw) {
+                authctxt->valid = 1;
 #ifdef USE_PAM
-       if (options.use_pam)
-               PRIVSEP(start_pam(authctxt));
+                if (options.use_pam)
+                    PRIVSEP(start_pam(authctxt));
 #endif
+            }
+        } else {
+            debug("failed to set username from gssapi context");
+            packet_send_debug("failed to set username from gssapi context");
+        }
     }
 }
 
@@ -274,7 +314,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
                fatal("No authentication or GSSAPI context");
 
-       gssapi_set_implicit_username(authctxt);
+       gssapi_set_username(authctxt);
 
        gssctxt = authctxt->methoddata;
 
@@ -287,7 +327,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 
        /* user should be set if valid but we double-check here */
        if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-           authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+           authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                       authctxt->pw, 0 /* !gssapi-keyex */));
        } else {
            authenticated = 0;
        }
@@ -297,22 +338,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
-       userauth_finish(authctxt, authenticated,
-                       gssapi_with_mic ? "gssapi-with-mic" : "gssapi");
-}
-
-static int
-userauth_gssapi_with_mic(Authctxt *authctxt)
-{
-    gssapi_with_mic = 1;
-    return userauth_gssapi(authctxt);
-}
-
-static int
-userauth_gssapi_without_mic(Authctxt *authctxt)
-{
-    gssapi_with_mic = 0;
-    return userauth_gssapi(authctxt);
+       userauth_finish(authctxt, authenticated, "gssapi-with-mic");
 }
 
 static void
@@ -328,8 +354,6 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
                fatal("No authentication or GSSAPI context");
 
-       gssapi_set_implicit_username(authctxt);
-
        gssctxt = authctxt->methoddata;
 
        mic.value = packet_get_string(&len);
@@ -341,11 +365,15 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        gssbuf.value = buffer_ptr(&b);
        gssbuf.length = buffer_len(&b);
 
+    gssapi_set_username(authctxt);
+
        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
            if (authctxt->valid && authctxt->user && authctxt->user[0]) {
-               authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+            authenticated =
+                PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw,
+                                              0 /* !gssapi-keyex */));
            } else {
-               authenticated = 0;
+            authenticated = 0;
            }
        else
                logit("GSSAPI MIC check failed");
@@ -378,21 +406,15 @@ static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
        }
 }
 
-Authmethod method_external = {
-       "external-keyx",
-       userauth_external,
+Authmethod method_gsskeyex = {
+       "gssapi-keyex",
+       userauth_gsskeyex,
        &options.gss_authentication
 };
-       
+
 Authmethod method_gssapi = {
        "gssapi-with-mic",
-       userauth_gssapi_with_mic,
-       &options.gss_authentication
-};
-
-Authmethod method_gssapi_compat = {
-       "gssapi",
-       userauth_gssapi_without_mic,
+       userauth_gssapi,
        &options.gss_authentication
 };
 
This page took 0.104414 seconds and 4 git commands to generate.