summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ssh/sshd/auth2-gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ssh/sshd/auth2-gss.c')
-rw-r--r--usr/src/cmd/ssh/sshd/auth2-gss.c533
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 */