X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/7364bd04fc18484f99f74b901c4581795bcf2787..HEAD:/auth2-gss.c diff --git a/auth2-gss.c b/auth2-gss.c index c7651112..0e08d889 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.1 2003/08/22 10:56:08 markus 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. @@ -28,39 +28,45 @@ #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; static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); +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 *); /* * 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; if (!authctxt->valid || authctxt->user == NULL) return (0); @@ -78,17 +84,18 @@ userauth_gssapi(Authctxt *authctxt) if (doid) xfree(doid); + 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); @@ -98,14 +105,18 @@ userauth_gssapi(Authctxt *authctxt) 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); return (0); + } - authctxt->methoddata=(void *)ctxt; + authctxt->methoddata = (void *)ctxt; packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); - /* Return OID in same format as we received it*/ + /* Return the OID that we received */ packet_put_string(doid, len); packet_send(); @@ -125,7 +136,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; - OM_uint32 maj_status, min_status; + OM_uint32 maj_status, min_status, flags; u_int len; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) @@ -138,7 +149,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt) packet_check_eom(); maj_status = PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, - &send_tok, NULL)); + &send_tok, &flags)); xfree(recv_tok.value); @@ -150,7 +161,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"); + userauth_finish(authctxt, 0, "gssapi-with-mic"); } else { if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); @@ -159,8 +170,13 @@ 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); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, - &input_gssapi_exchange_complete); + if (flags & GSS_C_INTEG_FLAG) + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, + &input_gssapi_mic); + else + dispatch_set( + SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, + &input_gssapi_exchange_complete); } } @@ -175,12 +191,14 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; OM_uint32 maj_status; + u_int len; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); gssctxt = authctxt->methoddata; - recv_tok.value = packet_get_string(&recv_tok.length); + recv_tok.value = packet_get_string(&len); + recv_tok.length = len; packet_check_eom(); @@ -218,9 +236,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) gssctxt = authctxt->methoddata; /* - * We don't need to check the status, because the stored credentials - * which userok uses are only populated once the context init step - * has returned complete. + * We don't need to check the status, because we're only enabled in + * the dispatcher once the exchange is complete */ packet_check_eom(); @@ -230,12 +247,53 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 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"); +} + +static void +input_gssapi_mic(int type, u_int32_t plen, void *ctxt) +{ + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; + int authenticated = 0; + Buffer b; + gss_buffer_desc mic, gssbuf; + u_int len; + + if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) + fatal("No authentication or GSSAPI context"); + + gssctxt = authctxt->methoddata; + + mic.value = packet_get_string(&len); + mic.length = len; + + ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, + "gssapi-with-mic"); + + gssbuf.value = buffer_ptr(&b); + gssbuf.length = buffer_len(&b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + else + logit("GSSAPI MIC check failed"); + + buffer_free(&b); + xfree(mic.value); + + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + 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"); + userauth_finish(authctxt, authenticated, "gssapi-with-mic"); } Authmethod method_gssapi = { - "gssapi", + "gssapi-with-mic", userauth_gssapi, &options.gss_authentication };