diff options
Diffstat (limited to 'usr/src/cmd/ssh/sshd/auth2-gss.c')
-rw-r--r-- | usr/src/cmd/ssh/sshd/auth2-gss.c | 533 |
1 files changed, 0 insertions, 533 deletions
diff --git a/usr/src/cmd/ssh/sshd/auth2-gss.c b/usr/src/cmd/ssh/sshd/auth2-gss.c deleted file mode 100644 index 8525707c1e..0000000000 --- a/usr/src/cmd/ssh/sshd/auth2-gss.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include "includes.h" - -#ifdef GSSAPI -#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 "bufaux.h" -#include "packet.h" - -#include <gssapi/gssapi.h> -#include "ssh-gss.h" - -extern ServerOptions options; -extern uchar_t *session_id2; -extern int session_id2_len; -extern Gssctxt *xxx_gssctxt; - -static void userauth_gssapi_finish(Authctxt *authctxt, Gssctxt *gssctxt); - -static void -userauth_gssapi_keyex(Authctxt *authctxt) -{ - gss_buffer_desc g_mic_data, mic_tok; - Buffer mic_data; - OM_uint32 maj_status, min_status; - - if (authctxt == NULL || authctxt->method == NULL) - fatal("No authentication context during gssapi-keyex userauth"); - - if (xxx_gssctxt == NULL || xxx_gssctxt->context == GSS_C_NO_CONTEXT) { - /* fatal()? or return? */ - debug("No GSS-API context during gssapi-keyex userauth"); - return; - } - - /* Make data buffer to verify MIC with */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - - mic_tok.value = packet_get_string(&mic_tok.length); - - maj_status = gss_verify_mic(&min_status, xxx_gssctxt->context, - &g_mic_data, &mic_tok, NULL); - - packet_check_eom(); - buffer_clear(&mic_data); - - if (maj_status != GSS_S_COMPLETE) - debug2("MIC verification failed, GSSAPI userauth failed"); - else - userauth_gssapi_finish(authctxt, xxx_gssctxt); - - /* Leave Gssctxt around for ssh_gssapi_cleanup/storecreds() */ - if (xxx_gssctxt->deleg_creds == GSS_C_NO_CREDENTIAL) - ssh_gssapi_delete_ctx(&xxx_gssctxt); -} - -static void ssh_gssapi_userauth_error(Gssctxt *ctxt); -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_errtok(int, u_int32_t, void *); -static void input_gssapi_exchange_complete(int type, u_int32_t plen, - void *ctxt); - -static void -userauth_gssapi_abandon(Authctxt *authctxt, Authmethod *method) -{ - ssh_gssapi_delete_ctx((Gssctxt **)&method->method_data); - xxx_gssctxt = NULL; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); -} - -static void -userauth_gssapi(Authctxt *authctxt) -{ - gss_OID_set supported_mechs; - int mechs, present = 0; - OM_uint32 min_status; - uint_t len; - char *doid = NULL; - gss_OID oid = GSS_C_NULL_OID; - - if (datafellows & SSH_OLD_GSSAPI) { - debug("Early drafts of GSSAPI userauth not supported"); - return; - } - - mechs = packet_get_int(); - if (mechs == 0) { - packet_check_eom(); - debug("Mechanism negotiation is not supported"); - return; - } - - ssh_gssapi_server_mechs(&supported_mechs); - - do { - mechs--; - - if (oid != GSS_C_NULL_OID) - ssh_gssapi_release_oid(&oid); - - doid = packet_get_string(&len); - - /* ick */ - if (doid[0] != 0x06 || (len > 2 && doid[1] != len - 2)) { - log("Mechanism OID received using the old " - "encoding form"); - oid = ssh_gssapi_make_oid(len, doid); - } else { - oid = ssh_gssapi_make_oid(len - 2, doid + 2); - } - - (void) gss_test_oid_set_member(&min_status, oid, - supported_mechs, &present); - - debug("Client offered gssapi userauth with %s (%s)", - ssh_gssapi_oid_to_str(oid), - present ? "supported" : "unsupported"); - } while (!present && (mechs > 0)); - - if (!present) { - /* userauth_finish() will send SSH2_MSG_USERAUTH_FAILURE */ - debug2("No mechanism offered by the client is available"); - ssh_gssapi_release_oid(&oid); - return; - } - - ssh_gssapi_build_ctx((Gssctxt **)&authctxt->method->method_data, - 0, oid); - ssh_gssapi_release_oid(&oid); - /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */ - - packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE); - - /* Just return whatever we found -- the matched mech does us no good */ - packet_put_string(doid, len); - xfree(doid); - - packet_send(); - packet_write_wait(); - - /* Setup rest of gssapi userauth conversation */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); - authctxt->method->postponed = 1; -} - -static void -input_gssapi_token(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok; - OM_uint32 maj_status, min_status; - uint_t len; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - fatal("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - } - - gssctxt = authctxt->method->method_data; - recv_tok.value = packet_get_string(&len); - recv_tok.length = len; /* u_int vs. size_t */ - - maj_status = ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); - packet_check_eom(); - - if (GSS_ERROR(maj_status)) { - ssh_gssapi_userauth_error(gssctxt); - if (send_tok.length != 0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - } - authctxt->method->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, authctxt->method->name); - } else { - if (send_tok.length != 0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); - packet_put_string(send_tok.value, send_tok.length); - packet_send(); - packet_write_wait(); - } - if (maj_status == GSS_S_COMPLETE) { - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, - &input_gssapi_mic); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, - &input_gssapi_exchange_complete); - } - } - - gss_release_buffer(&min_status, &send_tok); -} - -static void -input_gssapi_errtok(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc send_tok, recv_tok; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - fatal("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - } - - gssctxt = authctxt->method->method_data; - recv_tok.value = packet_get_string(&recv_tok.length); - packet_check_eom(); - - /* Push the error token into GSSAPI to see what it says */ - (void) ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok); - - debug("Client sent GSS-API error token during GSS userauth-- %s", - ssh_gssapi_last_error(gssctxt, NULL, NULL)); - - /* We can't return anything to the client, even if we wanted to */ - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - - - /* - * The client will have already moved on to the next auth and - * will send a new userauth request. The spec says that the - * server MUST NOT send a SSH_MSG_USERAUTH_FAILURE packet in - * response to this. - * - * We leave authctxt->method->postponed == 1 here so that a call - * to input_userauth_request() will detect this failure (as - * userauth abandonment) and act accordingly. - */ -} - -static void -input_gssapi_mic(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - gss_buffer_desc g_mic_data, mic_tok; - Buffer mic_data; - OM_uint32 maj_status, min_status; - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) { - debug3("No authentication or GSSAPI context during " - "gssapi-with-mic userauth"); - return; - } - - gssctxt = authctxt->method->method_data; - - /* Make data buffer to verify MIC with */ - buffer_init(&mic_data); - buffer_put_string(&mic_data, session_id2, session_id2_len); - buffer_put_char(&mic_data, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&mic_data, authctxt->user); - buffer_put_cstring(&mic_data, authctxt->service); - buffer_put_cstring(&mic_data, authctxt->method->name); - - g_mic_data.value = buffer_ptr(&mic_data); - g_mic_data.length = buffer_len(&mic_data); - - mic_tok.value = packet_get_string(&mic_tok.length); - - maj_status = gss_verify_mic(&min_status, gssctxt->context, - &g_mic_data, &mic_tok, NULL); - - packet_check_eom(); - buffer_free(&mic_data); - - if (maj_status != GSS_S_COMPLETE) - debug2("MIC verification failed, GSSAPI userauth failed"); - else - userauth_gssapi_finish(authctxt, gssctxt); - - /* Delete context from keyex */ - if (xxx_gssctxt != gssctxt) - ssh_gssapi_delete_ctx(&xxx_gssctxt); - - /* Leave Gssctxt around for ssh_gssapi_cleanup/storecreds() */ - if (gssctxt->deleg_creds == GSS_C_NO_CREDENTIAL) - ssh_gssapi_delete_ctx(&gssctxt); - - xxx_gssctxt = gssctxt; - - authctxt->method->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); - userauth_finish(authctxt, authctxt->method->name); -} - -/* - * This is called when the client thinks we've completed authentication. - * It should only be enabled in the dispatch handler by the function above, - * which only enables it once the GSSAPI exchange is complete. - */ -static void -input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) -{ - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - - packet_check_eom(); - - if (authctxt == NULL || authctxt->method == NULL || - (authctxt->method->method_data == NULL)) - fatal("No authentication or GSSAPI context"); - - gssctxt = authctxt->method->method_data; - - /* - * SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE -> gssapi userauth - * failure, the client should use SSH2_MSG_USERAUTH_GSSAPI_MIC - * instead. - * - * There's two reasons for this: - * - * 1) we don't have GSS mechs that don't support integrity - * protection, and even if we did we'd not want to use them with - * SSHv2, and, - * - * 2) we currently have no way to dynamically detect whether a - * given mechanism does or does not support integrity - * protection, so when a context's flags do not indicate - * integrity protection we can't know if the client simply - * didn't request it, so we assume it didn't and reject the - * userauth. - * - * We could fail partially (i.e., force the use of other - * userauth methods without counting this one as failed). But - * this will do for now. - */ -#if 0 - authctxt->method->authenticated = ssh_gssapi_userok(gssctxt, - authctxt->user); -#endif - - if (xxx_gssctxt != gssctxt) - ssh_gssapi_delete_ctx(&gssctxt); - ssh_gssapi_delete_ctx(&gssctxt); - authctxt->method->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, authctxt->method->name); -} - -static void -ssh_gssapi_userauth_error(Gssctxt *ctxt) -{ - char *errstr; - OM_uint32 maj, min; - - errstr = ssh_gssapi_last_error(ctxt, &maj, &min); - if (errstr) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR); - packet_put_int(maj); - packet_put_int(min); - packet_put_cstring(errstr); - packet_put_cstring(""); - packet_send(); - packet_write_wait(); - xfree(errstr); - } -} - -/* - * Code common to gssapi-keyex and gssapi-with-mic userauth. - * - * Does authorization, figures out how to store delegated creds. - */ -static void -userauth_gssapi_finish(Authctxt *authctxt, Gssctxt *gssctxt) -{ - char *local_user = NULL; - gss_buffer_desc dispname; - OM_uint32 major; - - if (*authctxt->user != '\0' && - ssh_gssapi_userok(gssctxt, authctxt->user)) { - - /* - * If the client princ did not map to the requested - * username then we don't want to clobber existing creds - * for the user with the delegated creds. - */ - local_user = ssh_gssapi_localname(gssctxt); - if (local_user == NULL || - strcmp(local_user, authctxt->user) == 0) - gssctxt->default_creds = 1; /* store creds as default */ - - authctxt->method->authenticated = - do_pam_non_initial_userauth(authctxt); - - } else if (*authctxt->user == '\0') { - /* Requested username == ""; derive username from princ name */ - if ((local_user = ssh_gssapi_localname(gssctxt)) == NULL) - return; - - /* Changed username (from implicit, '') */ - userauth_user_svc_change(authctxt, local_user, NULL); - - gssctxt->default_creds = 1; /* store creds as default */ - - authctxt->method->authenticated = - do_pam_non_initial_userauth(authctxt); - } - - if (local_user != NULL) - xfree(local_user); - - if (*authctxt->user != '\0' && authctxt->method->authenticated != 0) { - major = gss_display_name(&gssctxt->minor, gssctxt->src_name, - &dispname, NULL); - if (major == GSS_S_COMPLETE) { - log("Authorized principal %.*s, authenticated with " - "GSS mechanism %s, to: %s", - dispname.length, (char *)dispname.value, - ssh_gssapi_oid_to_name(gssctxt->actual_mech), - authctxt->user); - } - (void) gss_release_buffer(&gssctxt->minor, &dispname); - } -} - -#if 0 -/* Deprecated userauths -- should not be enabled */ -Authmethod method_external = { - "external-keyx", - &options.gss_authentication, - userauth_gssapi_keyex, - NULL, /* no abandon function */ - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -Authmethod method_gssapi = { - "gssapi", - &options.gss_authentication, - userauth_gssapi, - userauth_gssapi_abandon, - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; -#endif - -Authmethod method_external = { - "gssapi-keyex", - &options.gss_authentication, - userauth_gssapi_keyex, - NULL, /* no abandon function */ - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -Authmethod method_gssapi = { - "gssapi-with-mic", - &options.gss_authentication, - userauth_gssapi, - userauth_gssapi_abandon, - NULL, - NULL, - /* State counters */ - 0, 0, 0, 0, - /* State flags */ - 0, 0, 0, 0, 0, 0 -}; - -#endif /* GSSAPI */ |