xref: /onnv-gate/usr/src/uts/common/rpc/sec_gss/rpcsec_gss_utils.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1996-1997,2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/systm.h>
30*0Sstevel@tonic-gate #include <sys/errno.h>
31*0Sstevel@tonic-gate #include <sys/cmn_err.h>
32*0Sstevel@tonic-gate #include <gssapi/gssapi.h>
33*0Sstevel@tonic-gate #include <rpc/rpc.h>
34*0Sstevel@tonic-gate #include <rpc/rpcsec_defs.h>
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #ifdef RPCGSS_DEBUG
37*0Sstevel@tonic-gate /*
38*0Sstevel@tonic-gate  * Kernel rpcsec_gss module debugging aid. The global variable "rpcgss_log"
39*0Sstevel@tonic-gate  * is a bit mask which allows various types of debugging messages to be printed
40*0Sstevel@tonic-gate  * out.
41*0Sstevel@tonic-gate  *
42*0Sstevel@tonic-gate  *	  rpcgss_log & 1	will cause actual failures to be printed.
43*0Sstevel@tonic-gate  *	  rpcgss_log & 2 	will cause informational messages to be
44*0Sstevel@tonic-gate  *			printed on the client side of rpcsec_gss.
45*0Sstevel@tonic-gate  *	  rpcgss_log & 4	will cause informational messages to be
46*0Sstevel@tonic-gate  *			printed on the server side of rpcsec_gss.
47*0Sstevel@tonic-gate  *	  rpcgss_log & 8	will cause informational messages to be
48*0Sstevel@tonic-gate  *			printed on both client and server side of rpcsec_gss.
49*0Sstevel@tonic-gate  */
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate uint_t rpcgss_log = 0;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate #endif /* RPCGSS_DEBUG */
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate /*
56*0Sstevel@tonic-gate  * Internal utility routines.
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /*
60*0Sstevel@tonic-gate  *  Duplicate a gss_OID value.
61*0Sstevel@tonic-gate  */
62*0Sstevel@tonic-gate void
__rpc_gss_dup_oid(gss_OID oid,gss_OID * ret)63*0Sstevel@tonic-gate __rpc_gss_dup_oid(gss_OID oid, gss_OID *ret)
64*0Sstevel@tonic-gate {
65*0Sstevel@tonic-gate 	gss_OID tmp;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate 	if (oid == GSS_C_NULL_OID || oid->length == 0) {
68*0Sstevel@tonic-gate 		*ret = NULL;
69*0Sstevel@tonic-gate 		return;
70*0Sstevel@tonic-gate 	}
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	tmp = (gss_OID) kmem_alloc(sizeof (gss_OID_desc), KM_SLEEP);
73*0Sstevel@tonic-gate 	if (tmp) {
74*0Sstevel@tonic-gate 	    tmp->elements = kmem_alloc((oid->length), KM_SLEEP);
75*0Sstevel@tonic-gate 	    bcopy((char *)oid->elements, (char *)tmp->elements, oid->length);
76*0Sstevel@tonic-gate 	    tmp->length = oid->length;
77*0Sstevel@tonic-gate 	    *ret = tmp;
78*0Sstevel@tonic-gate 	} else {
79*0Sstevel@tonic-gate 	    *ret = NULL;
80*0Sstevel@tonic-gate 	}
81*0Sstevel@tonic-gate }
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate /*
84*0Sstevel@tonic-gate  *  Check if 2 gss_OID are the same.
85*0Sstevel@tonic-gate  */
86*0Sstevel@tonic-gate bool_t
__rpc_gss_oids_equal(oid1,oid2)87*0Sstevel@tonic-gate __rpc_gss_oids_equal(oid1, oid2)
88*0Sstevel@tonic-gate 	gss_OID	oid1, oid2;
89*0Sstevel@tonic-gate {
90*0Sstevel@tonic-gate 	if ((oid1->length == 0) && (oid2->length == 0))
91*0Sstevel@tonic-gate 		return (TRUE);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	if (oid1->length != oid2->length)
94*0Sstevel@tonic-gate 		return (FALSE);
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	return (bcmp(oid1->elements, oid2->elements, oid1->length) == 0);
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate void
__rpc_gss_convert_name(principal,name,name_type)100*0Sstevel@tonic-gate __rpc_gss_convert_name(principal, name, name_type)
101*0Sstevel@tonic-gate 	rpc_gss_principal_t	principal;
102*0Sstevel@tonic-gate 	gss_buffer_desc		*name;
103*0Sstevel@tonic-gate 	gss_OID			*name_type;
104*0Sstevel@tonic-gate {
105*0Sstevel@tonic-gate 	char			*cp;
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	cp = principal->name;
108*0Sstevel@tonic-gate 	if (*(int *)cp == 0)
109*0Sstevel@tonic-gate 		*name_type = GSS_C_NULL_OID;
110*0Sstevel@tonic-gate 	else {
111*0Sstevel@tonic-gate 		(*name_type)->length = *(int *)cp;
112*0Sstevel@tonic-gate 		(*name_type)->elements = (void *)(cp + sizeof (int));
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate 	cp += RNDUP(*(int *)cp) + sizeof (int);
115*0Sstevel@tonic-gate 	if ((name->length = *(int *)cp) == 0)
116*0Sstevel@tonic-gate 		name->value = NULL;
117*0Sstevel@tonic-gate 	else
118*0Sstevel@tonic-gate 		name->value = cp + sizeof (int);
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate /*
122*0Sstevel@tonic-gate  *  Make a client principal name from a flat exported gss name.
123*0Sstevel@tonic-gate  */
124*0Sstevel@tonic-gate bool_t
__rpc_gss_make_principal(principal,name)125*0Sstevel@tonic-gate __rpc_gss_make_principal(principal, name)
126*0Sstevel@tonic-gate 	rpc_gss_principal_t	*principal;
127*0Sstevel@tonic-gate 	gss_buffer_desc		*name;
128*0Sstevel@tonic-gate {
129*0Sstevel@tonic-gate 	int			plen;
130*0Sstevel@tonic-gate 	char			*s;
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate 	RPCGSS_LOG(8, "name-length = %lu\n", name->length);
133*0Sstevel@tonic-gate 	RPCGSS_LOG(8, "name-value = 0x%p\n", (void *)name->value);
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	plen = RNDUP(name->length) + sizeof (int);
136*0Sstevel@tonic-gate 	(*principal) = (rpc_gss_principal_t)kmem_alloc(plen, KM_SLEEP);
137*0Sstevel@tonic-gate 	if ((*principal) == NULL)
138*0Sstevel@tonic-gate 		return (FALSE);
139*0Sstevel@tonic-gate 	bzero((caddr_t)(*principal), plen);
140*0Sstevel@tonic-gate 	(*principal)->len = RNDUP(name->length);
141*0Sstevel@tonic-gate 	s = (*principal)->name;
142*0Sstevel@tonic-gate 	bcopy(name->value, s, name->length);
143*0Sstevel@tonic-gate 	return (TRUE);
144*0Sstevel@tonic-gate }
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate /*
148*0Sstevel@tonic-gate  * Make a copy of a principal name.
149*0Sstevel@tonic-gate  */
150*0Sstevel@tonic-gate rpc_gss_principal_t
__rpc_gss_dup_principal(principal)151*0Sstevel@tonic-gate __rpc_gss_dup_principal(principal)
152*0Sstevel@tonic-gate 	rpc_gss_principal_t	principal;
153*0Sstevel@tonic-gate {
154*0Sstevel@tonic-gate 	rpc_gss_principal_t	pdup;
155*0Sstevel@tonic-gate 	int			len;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	if (principal == NULL)
158*0Sstevel@tonic-gate 		return (NULL);
159*0Sstevel@tonic-gate 	len = principal->len + sizeof (int);
160*0Sstevel@tonic-gate 	if ((pdup = (rpc_gss_principal_t)mem_alloc(len)) == NULL)
161*0Sstevel@tonic-gate 		return (NULL);
162*0Sstevel@tonic-gate 	pdup->len = len;
163*0Sstevel@tonic-gate 	bcopy(principal->name, pdup->name, len);
164*0Sstevel@tonic-gate 	return (pdup);
165*0Sstevel@tonic-gate }
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate /*
168*0Sstevel@tonic-gate  * Returns highest and lowest versions of RPCSEC_GSS flavor supported.
169*0Sstevel@tonic-gate  */
170*0Sstevel@tonic-gate bool_t
rpc_gss_get_versions(vers_hi,vers_lo)171*0Sstevel@tonic-gate rpc_gss_get_versions(vers_hi, vers_lo)
172*0Sstevel@tonic-gate 	uint_t	*vers_hi;
173*0Sstevel@tonic-gate 	uint_t	*vers_lo;
174*0Sstevel@tonic-gate {
175*0Sstevel@tonic-gate 	*vers_hi = RPCSEC_GSS_VERSION;
176*0Sstevel@tonic-gate 	*vers_lo = RPCSEC_GSS_VERSION;
177*0Sstevel@tonic-gate 	return (TRUE);
178*0Sstevel@tonic-gate }
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate void
rpc_gss_display_status(major,minor,mech_type,uid,gss_function_name)181*0Sstevel@tonic-gate rpc_gss_display_status(major, minor, mech_type,
182*0Sstevel@tonic-gate 		uid, gss_function_name)
183*0Sstevel@tonic-gate 	OM_uint32	major, minor;
184*0Sstevel@tonic-gate 	gss_OID		mech_type;
185*0Sstevel@tonic-gate 	uid_t		uid;
186*0Sstevel@tonic-gate 	char		*gss_function_name;
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	int message_context;
190*0Sstevel@tonic-gate 	int major_stat;
191*0Sstevel@tonic-gate 	uint_t minor_stat;
192*0Sstevel@tonic-gate 	gss_buffer_desc status_string;
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	/*
195*0Sstevel@tonic-gate 	 * Before we return let us see
196*0Sstevel@tonic-gate 	 * whether we can log more meaningful error
197*0Sstevel@tonic-gate 	 * string using kgss_display_status
198*0Sstevel@tonic-gate 	 * If we can not just log the gssstat in hex
199*0Sstevel@tonic-gate 	 * and return.
200*0Sstevel@tonic-gate 	 */
201*0Sstevel@tonic-gate 	message_context = 0;
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	/*
204*0Sstevel@tonic-gate 	 * First get the status string out of gss_major_code
205*0Sstevel@tonic-gate 	 */
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	do {
208*0Sstevel@tonic-gate 	    major_stat = kgss_display_status(&minor_stat, major,
209*0Sstevel@tonic-gate 		GSS_C_GSS_CODE, mech_type,
210*0Sstevel@tonic-gate 		&message_context, &status_string, uid);
211*0Sstevel@tonic-gate 		/*
212*0Sstevel@tonic-gate 		 * If we failed just log the original error codes
213*0Sstevel@tonic-gate 		 */
214*0Sstevel@tonic-gate 	    if (major_stat != GSS_S_COMPLETE &&
215*0Sstevel@tonic-gate 		major != GSS_S_CONTINUE_NEEDED) {
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 		RPCGSS_LOG1(1, "%s GSS major error 0x%x\n",
218*0Sstevel@tonic-gate 			gss_function_name, major);
219*0Sstevel@tonic-gate 		RPCGSS_LOG1(1, "%s GSS minor error 0x%x\n",
220*0Sstevel@tonic-gate 			gss_function_name, minor);
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 		return;
223*0Sstevel@tonic-gate 	    } else {
224*0Sstevel@tonic-gate 		RPCGSS_LOG1(1, "%s GSS Error %s\n",
225*0Sstevel@tonic-gate 			(char *)gss_function_name,
226*0Sstevel@tonic-gate 			(char *)status_string.value);
227*0Sstevel@tonic-gate 		(void) gss_release_buffer(&minor_stat, &status_string);
228*0Sstevel@tonic-gate 	    }
229*0Sstevel@tonic-gate 	} while (message_context != 0);
230*0Sstevel@tonic-gate 	/*
231*0Sstevel@tonic-gate 	 * Now get the status string out of gss_minor_code
232*0Sstevel@tonic-gate 	 * This is mechanism specific error which is most
233*0Sstevel@tonic-gate 	 * useful
234*0Sstevel@tonic-gate 	 */
235*0Sstevel@tonic-gate 	message_context = 0;
236*0Sstevel@tonic-gate 	do {
237*0Sstevel@tonic-gate 	    major_stat = kgss_display_status(&minor_stat, minor,
238*0Sstevel@tonic-gate 		GSS_C_MECH_CODE, mech_type,
239*0Sstevel@tonic-gate 		&message_context, &status_string, uid);
240*0Sstevel@tonic-gate 	    if (major_stat != GSS_S_COMPLETE &&
241*0Sstevel@tonic-gate 		major_stat != GSS_S_CONTINUE_NEEDED) {
242*0Sstevel@tonic-gate 		RPCGSS_LOG1(1, "%s GSS minor error 0x%x\n",
243*0Sstevel@tonic-gate 		gss_function_name, minor);
244*0Sstevel@tonic-gate 		return;
245*0Sstevel@tonic-gate 	    } else {
246*0Sstevel@tonic-gate 		RPCGSS_LOG1(1,
247*0Sstevel@tonic-gate 		    "%s GSS Minor Error %s\n",
248*0Sstevel@tonic-gate 		    (char *)gss_function_name, (char *)status_string.value);
249*0Sstevel@tonic-gate 		(void) gss_release_buffer(&minor_stat,
250*0Sstevel@tonic-gate 		    &status_string);
251*0Sstevel@tonic-gate 	    }
252*0Sstevel@tonic-gate 	} while (message_context != 0);
253*0Sstevel@tonic-gate }
254