X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/blobdiff_plain/941f3f292f6a74a7252f16e5466044ff10f6bd75..HEAD:/openssh/auth2-gss.c diff --git a/openssh/auth2-gss.c b/openssh/auth2-gss.c index 917cec7..c8f28ac 100644 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@ -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 @@ -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; @@ -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,30 +139,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"); - goid.elements = doid; - goid.length = len; - } else { + 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 { + logit("Badly formed OID received"); } - gss_test_oid_set_member(&ms, &goid, 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, &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); @@ -173,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); @@ -184,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 @@ -232,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) { - if ((authctxt->user == NULL) || (strcmp(authctxt->user, "") == 0)) { - char *lname = NULL; - PRIVSEP(ssh_gssapi_localname(&lname)); - if (lname && lname[0] != '\0') { - 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) { + char *lname = NULL; + + if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) { + 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"); + } } } @@ -273,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; @@ -286,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; } @@ -296,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 @@ -327,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); @@ -340,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"); @@ -377,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 };