]> andersk Git - gssapi-openssh.git/blobdiff - openssh/auth2-gss.c
update missing from merge of Simon's 20061220 patch
[gssapi-openssh.git] / openssh / auth2-gss.c
index 64ee33278ccace850d8f0f88b6e4504b7182e82c..fab7cc239964b6c759f26f64558638763a5c023a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: auth2-gss.c,v 1.7 2003/11/21 11:57:03 djm Exp $       */
+/* $OpenBSD: auth2-gss.c,v 1.15 2006/08/03 03:34:41 deraadt Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
 
 #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;
 
@@ -56,28 +61,76 @@ userauth_external(Authctxt *authctxt)
 {
         packet_check_eom();
 
-       if (authctxt->valid && authctxt->user &&
-           strcmp(authctxt->user, "") != 0) {
+       if (authctxt->valid && authctxt->user && authctxt->user[0]) {
                return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
        }
        return 0;
 }
 
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+       int authenticated = 0;
+       Buffer b, b2;
+       gss_buffer_desc mic, gssbuf, gssbuf2;
+       u_int len;
+
+       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));
+           }
+       }
+       
+       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)
 {
-       gss_OID_desc oid = {0, NULL};
+       gss_OID_desc goid = {0, NULL};
        Gssctxt *ctxt = NULL;
        int mechs;
        gss_OID_set supported;
        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. */
 
        if (authctxt->user == NULL)
                return (0);
@@ -98,30 +151,34 @@ userauth_gssapi(Authctxt *authctxt)
                present = 0;
                doid = packet_get_string(&len);
 
-               if (doid[0] != SSH_GSS_OIDTYPE || doid[1] != len-2) {
-                       logit("Mechanism OID received using the old encoding form");
-                       oid.elements = doid;
-                       oid.length = len;
+               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,
+                           &present);
                } else {
-                       oid.elements = doid + 2;
-                       oid.length   = len - 2;
+                       logit("Badly formed OID received");
                }
-               gss_test_oid_set_member(&ms, &oid, supported, &present);
        } while (mechs > 0 && !present);
 
        gss_release_oid_set(&ms, &supported);
 
        if (!present) {
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
-       if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &oid)))) {
+       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);
 
@@ -232,11 +289,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
 static void
 gssapi_set_implicit_username(Authctxt *authctxt)
 {
-    if ((authctxt->user == NULL) || (strcmp(authctxt->user, "") == 0)) {
+    if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) {
        char *lname = NULL;
        PRIVSEP(ssh_gssapi_localname(&lname));
        if (lname && lname[0] != '\0') {
-           xfree(authctxt->user);
+           if (authctxt->user) xfree(authctxt->user);
            authctxt->user = lname;
            debug("set username to %s from gssapi context", lname);
            authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
@@ -245,6 +302,7 @@ gssapi_set_implicit_username(Authctxt *authctxt)
            }
        } else {
            debug("failed to set username from gssapi context");
+           packet_send_debug("failed to set username from gssapi context");
        }
     }
     if (authctxt->pw) {
@@ -282,7 +340,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
 
        packet_check_eom();
 
-       if (authctxt->valid && strcmp(authctxt->user, "") != 0) {
+       /* 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));
        } else {
            authenticated = 0;
@@ -338,7 +397,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
        gssbuf.length = buffer_len(&b);
 
        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
-           if (authctxt->valid && strcmp(authctxt->user, "") != 0) {
+           if (authctxt->valid && authctxt->user && authctxt->user[0]) {
                authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
            } else {
                authenticated = 0;
@@ -380,6 +439,12 @@ Authmethod method_external = {
        &options.gss_authentication
 };
        
+Authmethod method_gsskeyex = {
+       "gssapi-keyex",
+       userauth_gsskeyex,
+       &options.gss_authentication
+};
+
 Authmethod method_gssapi = {
        "gssapi-with-mic",
        userauth_gssapi_with_mic,
This page took 0.049429 seconds and 4 git commands to generate.