X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/5217e987f210fb30c1c08ec8795e503fcea1b167..3de1c8f8279938a454280ed3a7916aa74d3df679:/openssh/auth2-gss.c diff --git a/openssh/auth2-gss.c b/openssh/auth2-gss.c index d74d98f..fab7cc2 100644 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@ -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. @@ -28,17 +28,22 @@ #ifdef GSSAPI +#include + +#include + +#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,27 +61,76 @@ userauth_external(Authctxt *authctxt) { packet_check_eom(); - if (authctxt->valid && strcmp(authctxt->user, "") != 0) { - return(PRIVSEP(ssh_gssapi_userok(authctxt->user))); + 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); @@ -97,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); @@ -231,11 +289,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) static void gssapi_set_implicit_username(Authctxt *authctxt) { - if ((strcmp(authctxt->user, "") == 0) && (authctxt->pw == NULL)) { + 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)); @@ -244,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) { @@ -281,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; @@ -337,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; @@ -379,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,