X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/eb18f58d67d469ae01babc341aaf2f39f9da56a4..6a2c4cd8b3908e0d7e28789e83b4dc2b69aaf6d4:/auth2-gss.c diff --git a/auth2-gss.c b/auth2-gss.c index feb97d7c..3289ba18 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.2 2003/08/24 17:36:51 deraadt Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.8 2004/06/21 17:36:31 avsm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -43,6 +43,7 @@ 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 *); @@ -53,7 +54,7 @@ static void input_gssapi_errtok(int, u_int32_t, void *); 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; @@ -78,17 +79,19 @@ 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 +101,16 @@ 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)))) { + xfree(doid); return (0); + } 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 +130,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 +143,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 +155,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 +164,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); } } @@ -220,9 +230,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(); @@ -232,12 +241,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 };