xref: /titanic_41/usr/src/cmd/ssh/ssh/gss-clnt.c (revision c15e4e4b931f60f7af37864eb58a2cb72782abeb)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. *
37c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
47c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
57c478bd9Sstevel@tonic-gate  * are met:
67c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
77c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
87c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
97c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
107c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
137c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
147c478bd9Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
157c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
167c478bd9Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
177c478bd9Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
187c478bd9Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
197c478bd9Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
207c478bd9Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
217c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
227c478bd9Sstevel@tonic-gate  */
237c478bd9Sstevel@tonic-gate /*
24*c15e4e4bSjp161948  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include "includes.h"
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #ifdef GSSAPI
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #include "ssh.h"
357c478bd9Sstevel@tonic-gate #include "ssh2.h"
367c478bd9Sstevel@tonic-gate #include "xmalloc.h"
377c478bd9Sstevel@tonic-gate #include "buffer.h"
387c478bd9Sstevel@tonic-gate #include "bufaux.h"
397c478bd9Sstevel@tonic-gate #include "packet.h"
407c478bd9Sstevel@tonic-gate #include "compat.h"
417c478bd9Sstevel@tonic-gate #include <openssl/evp.h>
427c478bd9Sstevel@tonic-gate #include "cipher.h"
437c478bd9Sstevel@tonic-gate #include "kex.h"
447c478bd9Sstevel@tonic-gate #include "log.h"
457c478bd9Sstevel@tonic-gate #include "compat.h"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate #include <netdb.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include "ssh-gss.h"
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate void
ssh_gssapi_client_kex_hook(Kex * kex,char ** proposal)527c478bd9Sstevel@tonic-gate ssh_gssapi_client_kex_hook(Kex *kex, char **proposal)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	gss_OID_set mechs = GSS_C_NULL_OID_SET;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	if (kex == NULL || kex->serverhost == NULL)
577c478bd9Sstevel@tonic-gate 		fatal("INTERNAL ERROR (%s)", __func__);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	ssh_gssapi_client_mechs(kex->serverhost, &mechs);
607c478bd9Sstevel@tonic-gate 	ssh_gssapi_modify_kex(kex, mechs, proposal);
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate void
ssh_gssapi_client_mechs(const char * server_host,gss_OID_set * mechs)647c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	gss_OID_set	indicated = GSS_C_NULL_OID_SET;
677c478bd9Sstevel@tonic-gate 	gss_OID_set	acquired, supported;
687c478bd9Sstevel@tonic-gate 	gss_OID		mech;
697c478bd9Sstevel@tonic-gate 	gss_cred_id_t	creds;
707c478bd9Sstevel@tonic-gate 	Gssctxt		*ctxt = NULL;
717c478bd9Sstevel@tonic-gate 	gss_buffer_desc	tok;
727c478bd9Sstevel@tonic-gate 	OM_uint32	maj, min;
737c478bd9Sstevel@tonic-gate 	int		i;
749a8058b5Sjp161948 	char		*errmsg;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	if (!mechs)
777c478bd9Sstevel@tonic-gate 		return;
787c478bd9Sstevel@tonic-gate 	*mechs = GSS_C_NULL_OID_SET;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	maj = gss_indicate_mechs(&min, &indicated);
817c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
827c478bd9Sstevel@tonic-gate 		debug("No GSS-API mechanisms are installed");
837c478bd9Sstevel@tonic-gate 		return;
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	maj = gss_create_empty_oid_set(&min, &supported);
877c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
889a8058b5Sjp161948 		errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
899a8058b5Sjp161948 		debug("Failed to allocate resources (%s) for GSS-API", errmsg);
909a8058b5Sjp161948 		xfree(errmsg);
917c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &indicated);
927c478bd9Sstevel@tonic-gate 		return;
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 	maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated,
957c478bd9Sstevel@tonic-gate 	    GSS_C_INITIATE, &creds, &acquired, NULL);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
989a8058b5Sjp161948 		errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
997c478bd9Sstevel@tonic-gate 		debug("Failed to acquire GSS-API credentials for any "
1009a8058b5Sjp161948 		    "mechanisms (%s)", errmsg);
1019a8058b5Sjp161948 		xfree(errmsg);
1027c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &indicated);
1037c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &supported);
1047c478bd9Sstevel@tonic-gate 		return;
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 	(void) gss_release_cred(&min, &creds);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	for (i = 0; i < acquired->count; i++) {
1097c478bd9Sstevel@tonic-gate 		mech = &acquired->elements[i];
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 		if (ssh_gssapi_is_spnego(mech))
1127c478bd9Sstevel@tonic-gate 			continue;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 		ssh_gssapi_build_ctx(&ctxt, 1, mech);
1157c478bd9Sstevel@tonic-gate 		if (!ctxt)
1167c478bd9Sstevel@tonic-gate 			continue;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 		/*
1197c478bd9Sstevel@tonic-gate 		 * This is useful for mechs like Kerberos, which can
1207c478bd9Sstevel@tonic-gate 		 * detect unknown target princs here, but not for
1217c478bd9Sstevel@tonic-gate 		 * mechs like SPKM, which cannot detect unknown princs
1227c478bd9Sstevel@tonic-gate 		 * until context tokens are actually exchanged.
1237c478bd9Sstevel@tonic-gate 		 *
1247c478bd9Sstevel@tonic-gate 		 * 'Twould be useful to have a test that could save us
1257c478bd9Sstevel@tonic-gate 		 * the bother of trying this for SPKM and the such...
1267c478bd9Sstevel@tonic-gate 		 */
127*c15e4e4bSjp161948 		maj = ssh_gssapi_init_ctx(ctxt, server_host, 0, NULL, &tok);
1287c478bd9Sstevel@tonic-gate 		if (GSS_ERROR(maj)) {
1299a8058b5Sjp161948 			errmsg = ssh_gssapi_last_error(ctxt, NULL, NULL);
1307c478bd9Sstevel@tonic-gate 			debug("Skipping GSS-API mechanism %s (%s)",
1319a8058b5Sjp161948 			    ssh_gssapi_oid_to_name(mech), errmsg);
1329a8058b5Sjp161948 			xfree(errmsg);
1337c478bd9Sstevel@tonic-gate 			continue;
1347c478bd9Sstevel@tonic-gate 		}
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&min, &tok);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 		maj = gss_add_oid_set_member(&min, mech, &supported);
1399a8058b5Sjp161948 		if (GSS_ERROR(maj)) {
1409a8058b5Sjp161948 			errmsg = ssh_gssapi_last_error(NULL, &maj, &min);
1417c478bd9Sstevel@tonic-gate 			debug("Failed to allocate resources (%s) for GSS-API",
1429a8058b5Sjp161948 			    errmsg);
1439a8058b5Sjp161948 			xfree(errmsg);
1449a8058b5Sjp161948 		}
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	*mechs = supported;
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 
151*c15e4e4bSjp161948 /*
152*c15e4e4bSjp161948  * Wrapper to init_sec_context. Requires that the context contains:
153*c15e4e4bSjp161948  *
1547c478bd9Sstevel@tonic-gate  *	oid
1557c478bd9Sstevel@tonic-gate  * 	server name (from ssh_gssapi_import_name)
1567c478bd9Sstevel@tonic-gate  */
1577c478bd9Sstevel@tonic-gate OM_uint32
ssh_gssapi_init_ctx(Gssctxt * ctx,const char * server_host,int deleg_creds,gss_buffer_t recv_tok,gss_buffer_t send_tok)1587c478bd9Sstevel@tonic-gate ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds,
1597c478bd9Sstevel@tonic-gate 		    gss_buffer_t recv_tok, gss_buffer_t send_tok)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host,
1647c478bd9Sstevel@tonic-gate 	    deleg_creds, recv_tok, send_tok);
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	if (deleg_creds) {
1677c478bd9Sstevel@tonic-gate 		flags |= GSS_C_DELEG_FLAG;
1687c478bd9Sstevel@tonic-gate 		debug("Delegating GSS-API credentials");
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	/* Build target principal */
1727c478bd9Sstevel@tonic-gate 	if (ctx->desired_name == GSS_C_NO_NAME &&
173*c15e4e4bSjp161948 	    !ssh_gssapi_import_name(ctx, server_host)) {
174*c15e4e4bSjp161948 		return (ctx->major);
175*c15e4e4bSjp161948 	}
1767c478bd9Sstevel@tonic-gate 
177*c15e4e4bSjp161948 	ctx->major = gss_init_sec_context(&ctx->minor, GSS_C_NO_CREDENTIAL,
178*c15e4e4bSjp161948 	    &ctx->context, ctx->desired_name, ctx->desired_mech, flags,
1797c478bd9Sstevel@tonic-gate 	    0, /* default lifetime */
1807c478bd9Sstevel@tonic-gate 	    NULL, /* no channel bindings */
1817c478bd9Sstevel@tonic-gate 	    recv_tok,
1827c478bd9Sstevel@tonic-gate 	    NULL, /* actual mech type */
183*c15e4e4bSjp161948 	    send_tok, &ctx->flags,
1847c478bd9Sstevel@tonic-gate 	    NULL); /* actual lifetime */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(ctx->major))
1877c478bd9Sstevel@tonic-gate 		ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()");
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	return (ctx->major);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
192