xref: /titanic_41/usr/src/cmd/ssh/ssh/gss-clnt.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. *
3*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
4*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
5*7c478bd9Sstevel@tonic-gate  * are met:
6*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
7*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
8*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
9*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
10*7c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
13*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14*7c478bd9Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15*7c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
16*7c478bd9Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17*7c478bd9Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
18*7c478bd9Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19*7c478bd9Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20*7c478bd9Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*7c478bd9Sstevel@tonic-gate  */
23*7c478bd9Sstevel@tonic-gate /*
24*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
25*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #include "includes.h"
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
31*7c478bd9Sstevel@tonic-gate 
32*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include "ssh.h"
35*7c478bd9Sstevel@tonic-gate #include "ssh2.h"
36*7c478bd9Sstevel@tonic-gate #include "xmalloc.h"
37*7c478bd9Sstevel@tonic-gate #include "buffer.h"
38*7c478bd9Sstevel@tonic-gate #include "bufaux.h"
39*7c478bd9Sstevel@tonic-gate #include "packet.h"
40*7c478bd9Sstevel@tonic-gate #include "compat.h"
41*7c478bd9Sstevel@tonic-gate #include <openssl/evp.h>
42*7c478bd9Sstevel@tonic-gate #include "cipher.h"
43*7c478bd9Sstevel@tonic-gate #include "kex.h"
44*7c478bd9Sstevel@tonic-gate #include "log.h"
45*7c478bd9Sstevel@tonic-gate #include "compat.h"
46*7c478bd9Sstevel@tonic-gate #include "monitor_wrap.h"
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #include <netdb.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #include "ssh-gss.h"
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate void
53*7c478bd9Sstevel@tonic-gate ssh_gssapi_client_kex_hook(Kex *kex, char **proposal)
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	gss_OID_set mechs = GSS_C_NULL_OID_SET;
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	if (kex == NULL || kex->serverhost == NULL)
58*7c478bd9Sstevel@tonic-gate 		fatal("INTERNAL ERROR (%s)", __func__);
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 	ssh_gssapi_client_mechs(kex->serverhost, &mechs);
61*7c478bd9Sstevel@tonic-gate 	ssh_gssapi_modify_kex(kex, mechs, proposal);
62*7c478bd9Sstevel@tonic-gate }
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate void
65*7c478bd9Sstevel@tonic-gate ssh_gssapi_client_mechs(const char *server_host, gss_OID_set *mechs)
66*7c478bd9Sstevel@tonic-gate {
67*7c478bd9Sstevel@tonic-gate 	gss_OID_set	indicated = GSS_C_NULL_OID_SET;
68*7c478bd9Sstevel@tonic-gate 	gss_OID_set	acquired, supported;
69*7c478bd9Sstevel@tonic-gate 	gss_OID		mech;
70*7c478bd9Sstevel@tonic-gate 	gss_cred_id_t	creds;
71*7c478bd9Sstevel@tonic-gate 	Gssctxt		*ctxt = NULL;
72*7c478bd9Sstevel@tonic-gate 	gss_buffer_desc	tok;
73*7c478bd9Sstevel@tonic-gate 	OM_uint32	maj, min;
74*7c478bd9Sstevel@tonic-gate 	int		i;
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	if (!mechs)
77*7c478bd9Sstevel@tonic-gate 		return;
78*7c478bd9Sstevel@tonic-gate 	*mechs = GSS_C_NULL_OID_SET;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	maj = gss_indicate_mechs(&min, &indicated);
81*7c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
82*7c478bd9Sstevel@tonic-gate 		debug("No GSS-API mechanisms are installed");
83*7c478bd9Sstevel@tonic-gate 		return;
84*7c478bd9Sstevel@tonic-gate 	}
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	maj = gss_create_empty_oid_set(&min, &supported);
87*7c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
88*7c478bd9Sstevel@tonic-gate 		debug("Failed to allocate resources (%s) for GSS-API",
89*7c478bd9Sstevel@tonic-gate 			ssh_gssapi_last_error(NULL, &maj, &min));
90*7c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &indicated);
91*7c478bd9Sstevel@tonic-gate 		return;
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 	maj = gss_acquire_cred(&min, GSS_C_NO_NAME, 0, indicated,
94*7c478bd9Sstevel@tonic-gate 			GSS_C_INITIATE, &creds, &acquired, NULL);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	if (GSS_ERROR(maj)) {
97*7c478bd9Sstevel@tonic-gate 		debug("Failed to acquire GSS-API credentials for any "
98*7c478bd9Sstevel@tonic-gate 			"mechanisms (%s)",
99*7c478bd9Sstevel@tonic-gate 			ssh_gssapi_last_error(NULL, &maj, &min));
100*7c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &indicated);
101*7c478bd9Sstevel@tonic-gate 		(void) gss_release_oid_set(&min, &supported);
102*7c478bd9Sstevel@tonic-gate 		return;
103*7c478bd9Sstevel@tonic-gate 	}
104*7c478bd9Sstevel@tonic-gate 	(void) gss_release_cred(&min, &creds);
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	for (i = 0 ; i < acquired->count ; i++) {
107*7c478bd9Sstevel@tonic-gate 		mech = &acquired->elements[i];
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 		if (ssh_gssapi_is_spnego(mech))
110*7c478bd9Sstevel@tonic-gate 			continue;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 		ssh_gssapi_build_ctx(&ctxt, 1, mech);
113*7c478bd9Sstevel@tonic-gate 		if (!ctxt)
114*7c478bd9Sstevel@tonic-gate 			continue;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 		/*
117*7c478bd9Sstevel@tonic-gate 		 * This is useful for mechs like Kerberos, which can
118*7c478bd9Sstevel@tonic-gate 		 * detect unknown target princs here, but not for
119*7c478bd9Sstevel@tonic-gate 		 * mechs like SPKM, which cannot detect unknown princs
120*7c478bd9Sstevel@tonic-gate 		 * until context tokens are actually exchanged.
121*7c478bd9Sstevel@tonic-gate 		 *
122*7c478bd9Sstevel@tonic-gate 		 * 'Twould be useful to have a test that could save us
123*7c478bd9Sstevel@tonic-gate 		 * the bother of trying this for SPKM and the such...
124*7c478bd9Sstevel@tonic-gate 		 */
125*7c478bd9Sstevel@tonic-gate 		maj = ssh_gssapi_init_ctx(ctxt, server_host, 0,
126*7c478bd9Sstevel@tonic-gate 				NULL, &tok);
127*7c478bd9Sstevel@tonic-gate 		if (GSS_ERROR(maj)) {
128*7c478bd9Sstevel@tonic-gate 			debug("Skipping GSS-API mechanism %s (%s)",
129*7c478bd9Sstevel@tonic-gate 				ssh_gssapi_oid_to_name(mech),
130*7c478bd9Sstevel@tonic-gate 				ssh_gssapi_last_error(ctxt, NULL, NULL));
131*7c478bd9Sstevel@tonic-gate 			continue;
132*7c478bd9Sstevel@tonic-gate 		}
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&min, &tok);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 		maj = gss_add_oid_set_member(&min, mech, &supported);
137*7c478bd9Sstevel@tonic-gate 		if (GSS_ERROR(maj))
138*7c478bd9Sstevel@tonic-gate 			debug("Failed to allocate resources (%s) for GSS-API",
139*7c478bd9Sstevel@tonic-gate 				ssh_gssapi_last_error(NULL, &maj, &min));
140*7c478bd9Sstevel@tonic-gate 	}
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	*mechs = supported;
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate /* Wrapper to init_sec_context
147*7c478bd9Sstevel@tonic-gate  * Requires that the context contains:
148*7c478bd9Sstevel@tonic-gate  *	oid
149*7c478bd9Sstevel@tonic-gate  * 	server name (from ssh_gssapi_import_name)
150*7c478bd9Sstevel@tonic-gate  */
151*7c478bd9Sstevel@tonic-gate OM_uint32
152*7c478bd9Sstevel@tonic-gate ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds,
153*7c478bd9Sstevel@tonic-gate 		    gss_buffer_t recv_tok, gss_buffer_t send_tok)
154*7c478bd9Sstevel@tonic-gate {
155*7c478bd9Sstevel@tonic-gate 	int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host,
158*7c478bd9Sstevel@tonic-gate 		deleg_creds, recv_tok, send_tok);
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	if (deleg_creds) {
161*7c478bd9Sstevel@tonic-gate 		flags |= GSS_C_DELEG_FLAG;
162*7c478bd9Sstevel@tonic-gate 		debug("Delegating GSS-API credentials");
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/* Build target principal */
166*7c478bd9Sstevel@tonic-gate 	if (ctx->desired_name == GSS_C_NO_NAME &&
167*7c478bd9Sstevel@tonic-gate 	    !ssh_gssapi_import_name(ctx, server_host))
168*7c478bd9Sstevel@tonic-gate 		return ctx->major;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate       	ctx->major=gss_init_sec_context(&ctx->minor,
171*7c478bd9Sstevel@tonic-gate       					GSS_C_NO_CREDENTIAL,
172*7c478bd9Sstevel@tonic-gate       					&ctx->context,
173*7c478bd9Sstevel@tonic-gate       					ctx->desired_name,
174*7c478bd9Sstevel@tonic-gate       					ctx->desired_mech,
175*7c478bd9Sstevel@tonic-gate       					flags,
176*7c478bd9Sstevel@tonic-gate       					0, /* default lifetime */
177*7c478bd9Sstevel@tonic-gate       					NULL, /* no channel bindings */
178*7c478bd9Sstevel@tonic-gate       					recv_tok,
179*7c478bd9Sstevel@tonic-gate       					NULL, /* actual mech type */
180*7c478bd9Sstevel@tonic-gate       					send_tok,
181*7c478bd9Sstevel@tonic-gate       					&ctx->flags,
182*7c478bd9Sstevel@tonic-gate       					NULL); /* actual lifetime */
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate       	if (GSS_ERROR(ctx->major))
185*7c478bd9Sstevel@tonic-gate 		ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()");
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate       	return(ctx->major);
188*7c478bd9Sstevel@tonic-gate }
189*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
190