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 2004 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 <mechglueP.h>
30*0Sstevel@tonic-gate #include <stdio.h>
31*0Sstevel@tonic-gate #include <stdlib.h>
32*0Sstevel@tonic-gate #include <strings.h>
33*0Sstevel@tonic-gate #include <errno.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #define	MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate /*
38*0Sstevel@tonic-gate  * This file contains the support routines for the glue layer.
39*0Sstevel@tonic-gate  */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate  * get_der_length: Givin a pointer to a buffer that contains a DER encoded
43*0Sstevel@tonic-gate  * length, decode the length updating the buffer to point to the character
44*0Sstevel@tonic-gate  * after the DER encoding. The parameter bytes will point to the number of
45*0Sstevel@tonic-gate  * bytes that made up the DER encoding of the length originally pointed to
46*0Sstevel@tonic-gate  * by the buffer. Note we return -1 on error.
47*0Sstevel@tonic-gate  */
48*0Sstevel@tonic-gate int
49*0Sstevel@tonic-gate get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
50*0Sstevel@tonic-gate {
51*0Sstevel@tonic-gate 	/* p points to the beginning of the buffer */
52*0Sstevel@tonic-gate 	unsigned char *p = *buf;
53*0Sstevel@tonic-gate 	int length, new_length;
54*0Sstevel@tonic-gate 	int octets;
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	if (buf_len < 1)
57*0Sstevel@tonic-gate 		return (-1);
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	/* We should have at least one byte */
60*0Sstevel@tonic-gate 	*bytes = 1;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	/*
63*0Sstevel@tonic-gate 	 * If the High order bit is not set then the length is just the value
64*0Sstevel@tonic-gate 	 * of *p.
65*0Sstevel@tonic-gate 	 */
66*0Sstevel@tonic-gate 	if (*p < 128) {
67*0Sstevel@tonic-gate 		*buf = p+1;	/* Advance the buffer */
68*0Sstevel@tonic-gate 	return (*p);		/* return the length */
69*0Sstevel@tonic-gate 	}
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	/*
72*0Sstevel@tonic-gate 	 * if the High order bit is set, then the low order bits represent
73*0Sstevel@tonic-gate 	 * the number of bytes that contain the DER encoding of the length.
74*0Sstevel@tonic-gate 	 */
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	octets = *p++ & 0x7f;
77*0Sstevel@tonic-gate 	*bytes += octets;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	/* See if the supplied buffer contains enough bytes for the length. */
80*0Sstevel@tonic-gate 	if (octets > buf_len - 1)
81*0Sstevel@tonic-gate 		return (-1);
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	/*
84*0Sstevel@tonic-gate 	 * Calculate a multibyte length. The length is encoded as an
85*0Sstevel@tonic-gate 	 * unsigned integer base 256.
86*0Sstevel@tonic-gate 	 */
87*0Sstevel@tonic-gate 	for (length = 0; octets; octets--) {
88*0Sstevel@tonic-gate 		new_length = (length << 8) + *p++;
89*0Sstevel@tonic-gate 		if (new_length < length)  /* overflow */
90*0Sstevel@tonic-gate 			return (-1);
91*0Sstevel@tonic-gate 		length = new_length;
92*0Sstevel@tonic-gate 	}
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	*buf = p; /* Advance the buffer */
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	return (length);
97*0Sstevel@tonic-gate }
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate /*
100*0Sstevel@tonic-gate  * der_length_size: Return the number of bytes to encode a given length.
101*0Sstevel@tonic-gate  */
102*0Sstevel@tonic-gate unsigned int
103*0Sstevel@tonic-gate der_length_size(unsigned int len)
104*0Sstevel@tonic-gate {
105*0Sstevel@tonic-gate 	int i;
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate 	if (len < 128)
108*0Sstevel@tonic-gate 		return (1);
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 	for (i = 0; len; i++) {
111*0Sstevel@tonic-gate 		len >>= 8;
112*0Sstevel@tonic-gate 	}
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	return (i+1);
115*0Sstevel@tonic-gate }
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /*
118*0Sstevel@tonic-gate  * put_der_length: Encode the supplied length into the buffer pointed to
119*0Sstevel@tonic-gate  * by buf. max_length represents the maximum length of the buffer pointed
120*0Sstevel@tonic-gate  * to by buff. We will advance buf to point to the character after the newly
121*0Sstevel@tonic-gate  * DER encoded length. We return 0 on success or -l it the length cannot
122*0Sstevel@tonic-gate  * be encoded in max_len characters.
123*0Sstevel@tonic-gate  */
124*0Sstevel@tonic-gate int
125*0Sstevel@tonic-gate put_der_length(unsigned length, unsigned char **buf, unsigned int max_len)
126*0Sstevel@tonic-gate {
127*0Sstevel@tonic-gate 	unsigned char *s = *buf, *p;
128*0Sstevel@tonic-gate 	unsigned int buf_len = 0;
129*0Sstevel@tonic-gate 	int i, first;
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 	/* Oops */
132*0Sstevel@tonic-gate 	if (buf == 0 || max_len < 1)
133*0Sstevel@tonic-gate 		return (-1);
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	/* Single byte is the length */
136*0Sstevel@tonic-gate 	if (length < 128) {
137*0Sstevel@tonic-gate 		*s++ = length;
138*0Sstevel@tonic-gate 		*buf = s;
139*0Sstevel@tonic-gate 		return (0);
140*0Sstevel@tonic-gate 	}
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/* First byte contains the number of octets */
143*0Sstevel@tonic-gate 	p = s + 1;
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	/* Running total of the DER encoding length */
146*0Sstevel@tonic-gate 	buf_len = 0;
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	/*
149*0Sstevel@tonic-gate 	 * Encode MSB first. We do the encoding by setting a shift
150*0Sstevel@tonic-gate 	 * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
151*0Sstevel@tonic-gate 	 * by the factor. We then encode the resulting low order byte.
152*0Sstevel@tonic-gate 	 * We subtract 8 from the shift factor and repeat to ecnode the next
153*0Sstevel@tonic-gate 	 * byte. We stop when the shift factor is zero or we've run out of
154*0Sstevel@tonic-gate 	 * buffer to encode into.
155*0Sstevel@tonic-gate 	 */
156*0Sstevel@tonic-gate 	first = 0;
157*0Sstevel@tonic-gate 	for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
158*0Sstevel@tonic-gate 		unsigned int v;
159*0Sstevel@tonic-gate 		v = (length >> i) & 0xff;
160*0Sstevel@tonic-gate 		if ((v) || first) {
161*0Sstevel@tonic-gate 			buf_len += 1;
162*0Sstevel@tonic-gate 			*p++ = v;
163*0Sstevel@tonic-gate 			first = 1;
164*0Sstevel@tonic-gate 		}
165*0Sstevel@tonic-gate 	}
166*0Sstevel@tonic-gate 	if (i >= 0)			/* buffer overflow */
167*0Sstevel@tonic-gate 		return (-1);
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	/*
170*0Sstevel@tonic-gate 	 * We go back now and set the first byte to be the length with
171*0Sstevel@tonic-gate 	 * the high order bit set.
172*0Sstevel@tonic-gate 	 */
173*0Sstevel@tonic-gate 	*s = buf_len | 0x80;
174*0Sstevel@tonic-gate 	*buf = p;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	return (0);
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate /*
181*0Sstevel@tonic-gate  *  glue routine for get_mech_type
182*0Sstevel@tonic-gate  *
183*0Sstevel@tonic-gate  */
184*0Sstevel@tonic-gate OM_uint32
185*0Sstevel@tonic-gate __gss_get_mech_type(OID, token)
186*0Sstevel@tonic-gate 	gss_OID			OID;
187*0Sstevel@tonic-gate 	const gss_buffer_t	token;
188*0Sstevel@tonic-gate {
189*0Sstevel@tonic-gate 	unsigned char *buffer_ptr;
190*0Sstevel@tonic-gate 	int length;
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	/*
193*0Sstevel@tonic-gate 	 * This routine reads the prefix of "token" in order to determine
194*0Sstevel@tonic-gate 	 * its mechanism type. It assumes the encoding suggested in
195*0Sstevel@tonic-gate 	 * Appendix B of RFC 1508. This format starts out as follows :
196*0Sstevel@tonic-gate 	 *
197*0Sstevel@tonic-gate 	 * tag for APPLICATION 0, Sequence[constructed, definite length]
198*0Sstevel@tonic-gate 	 * length of remainder of token
199*0Sstevel@tonic-gate 	 * tag of OBJECT IDENTIFIER
200*0Sstevel@tonic-gate 	 * length of mechanism OID
201*0Sstevel@tonic-gate 	 * encoding of mechanism OID
202*0Sstevel@tonic-gate 	 * <the rest of the token>
203*0Sstevel@tonic-gate 	 *
204*0Sstevel@tonic-gate 	 * Numerically, this looks like :
205*0Sstevel@tonic-gate 	 *
206*0Sstevel@tonic-gate 	 * 0x60
207*0Sstevel@tonic-gate 	 * <length> - could be multiple bytes
208*0Sstevel@tonic-gate 	 * 0x06
209*0Sstevel@tonic-gate 	 * <length> - assume only one byte, hence OID length < 127
210*0Sstevel@tonic-gate 	 * <mech OID bytes>
211*0Sstevel@tonic-gate 	 *
212*0Sstevel@tonic-gate 	 * The routine fills in the OID value and returns an error as necessary.
213*0Sstevel@tonic-gate 	 */
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	if (OID == NULL)
216*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	if ((token == NULL) || (token->value == NULL))
219*0Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	/* Skip past the APP/Sequnce byte and the token length */
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	buffer_ptr = (unsigned char *) token->value;
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x60)
226*0Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
227*0Sstevel@tonic-gate 	length = *buffer_ptr++;
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	/* check if token length is null */
230*0Sstevel@tonic-gate 	if (length == 0)
231*0Sstevel@tonic-gate 	    return (GSS_S_DEFECTIVE_TOKEN);
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 	if (length & 0x80) {
234*0Sstevel@tonic-gate 		if ((length & 0x7f) > 4)
235*0Sstevel@tonic-gate 			return (GSS_S_DEFECTIVE_TOKEN);
236*0Sstevel@tonic-gate 		buffer_ptr += length & 0x7f;
237*0Sstevel@tonic-gate 	}
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x06)
240*0Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	OID->length = (OM_uint32) *(buffer_ptr++);
243*0Sstevel@tonic-gate 	OID->elements = (void *) buffer_ptr;
244*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate /*
249*0Sstevel@tonic-gate  *  Internal routines to get and release an internal mechanism name
250*0Sstevel@tonic-gate  */
251*0Sstevel@tonic-gate OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
252*0Sstevel@tonic-gate 					internal_name)
253*0Sstevel@tonic-gate OM_uint32		*minor_status;
254*0Sstevel@tonic-gate const gss_OID		mech_type;
255*0Sstevel@tonic-gate gss_union_name_t	union_name;
256*0Sstevel@tonic-gate gss_name_t		*internal_name;
257*0Sstevel@tonic-gate {
258*0Sstevel@tonic-gate 	OM_uint32			status;
259*0Sstevel@tonic-gate 	gss_mechanism		mech;
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
262*0Sstevel@tonic-gate 	if (mech) {
263*0Sstevel@tonic-gate 		if (mech->gss_import_name)
264*0Sstevel@tonic-gate 			status = mech->gss_import_name(
265*0Sstevel@tonic-gate 						mech->context,
266*0Sstevel@tonic-gate 						minor_status,
267*0Sstevel@tonic-gate 						union_name->external_name,
268*0Sstevel@tonic-gate 						union_name->name_type,
269*0Sstevel@tonic-gate 						internal_name);
270*0Sstevel@tonic-gate 		else
271*0Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 		return (status);
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
277*0Sstevel@tonic-gate }
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate OM_uint32 __gss_export_internal_name(minor_status, mech_type,
281*0Sstevel@tonic-gate 		internal_name, name_buf)
282*0Sstevel@tonic-gate OM_uint32		*minor_status;
283*0Sstevel@tonic-gate const gss_OID		mech_type;
284*0Sstevel@tonic-gate const gss_name_t	internal_name;
285*0Sstevel@tonic-gate gss_buffer_t		name_buf;
286*0Sstevel@tonic-gate {
287*0Sstevel@tonic-gate 	OM_uint32 status;
288*0Sstevel@tonic-gate 	gss_mechanism mech;
289*0Sstevel@tonic-gate 	gss_buffer_desc dispName;
290*0Sstevel@tonic-gate 	gss_OID nameOid;
291*0Sstevel@tonic-gate 	unsigned char *buf = NULL;
292*0Sstevel@tonic-gate 	const unsigned char tokId[] = "\x04\x01";
293*0Sstevel@tonic-gate 	const int tokIdLen = 2;
294*0Sstevel@tonic-gate 	const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
295*0Sstevel@tonic-gate 	int mechOidDERLen = 0;
296*0Sstevel@tonic-gate 	int mechOidLen = 0;
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
299*0Sstevel@tonic-gate 	if (!mech)
300*0Sstevel@tonic-gate 		return (GSS_S_BAD_MECH);
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 	if (mech->gss_export_name)
303*0Sstevel@tonic-gate 		return (mech->gss_export_name(mech->context,
304*0Sstevel@tonic-gate 						minor_status,
305*0Sstevel@tonic-gate 						internal_name,
306*0Sstevel@tonic-gate 						name_buf));
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate 	/*
309*0Sstevel@tonic-gate 	 * if we are here it is because the mechanism does not provide
310*0Sstevel@tonic-gate 	 * a gss_export_name so we will use our implementation.  We
311*0Sstevel@tonic-gate 	 * do required that the mechanism define a gss_display_name.
312*0Sstevel@tonic-gate 	 */
313*0Sstevel@tonic-gate 	if (!mech->gss_display_name)
314*0Sstevel@tonic-gate 		return (GSS_S_UNAVAILABLE);
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 	/*
317*0Sstevel@tonic-gate 	 * NOTE: RFC2743 (section 3.2) governs the format of the outer
318*0Sstevel@tonic-gate 	 *	 wrapper of exported names; the mechanisms' specs govern
319*0Sstevel@tonic-gate 	 *	 the format of the inner portion of the exported name
320*0Sstevel@tonic-gate 	 *	 and, for some (e.g., RFC1964, the Kerberos V mech), a
321*0Sstevel@tonic-gate 	 *	 generic default as implemented here will do.
322*0Sstevel@tonic-gate 	 *
323*0Sstevel@tonic-gate 	 * The outer wrapper of an exported MN is: 2-octet tok Id
324*0Sstevel@tonic-gate 	 * (0x0401) + 2-octet network-byte order mech OID length + mech
325*0Sstevel@tonic-gate 	 * oid (in DER format, including DER tag and DER length) +
326*0Sstevel@tonic-gate 	 * 4-octet network-byte order length of inner portion + inner
327*0Sstevel@tonic-gate 	 * portion.
328*0Sstevel@tonic-gate 	 *
329*0Sstevel@tonic-gate 	 * For the Kerberos V mechanism the inner portion of an exported
330*0Sstevel@tonic-gate 	 * MN is the display name string and ignores the name type OID
331*0Sstevel@tonic-gate 	 * altogether.  And we hope this will be so for any future
332*0Sstevel@tonic-gate 	 * mechanisms also, so that factoring name export/import out of
333*0Sstevel@tonic-gate 	 * the mech and into libgss pays off.
334*0Sstevel@tonic-gate 	 */
335*0Sstevel@tonic-gate 	if ((status = mech->gss_display_name(mech->context,
336*0Sstevel@tonic-gate 						minor_status,
337*0Sstevel@tonic-gate 						internal_name,
338*0Sstevel@tonic-gate 						&dispName,
339*0Sstevel@tonic-gate 						&nameOid))
340*0Sstevel@tonic-gate 						!= GSS_S_COMPLETE)
341*0Sstevel@tonic-gate 		return (status);
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	/* determine the size of the buffer needed */
344*0Sstevel@tonic-gate 	mechOidDERLen = der_length_size(mech_type->length);
345*0Sstevel@tonic-gate 	name_buf->length = tokIdLen + mechOidLenLen +
346*0Sstevel@tonic-gate 				mechOidTagLen + mechOidDERLen +
347*0Sstevel@tonic-gate 				mech_type->length +
348*0Sstevel@tonic-gate 				nameLenLen + dispName.length;
349*0Sstevel@tonic-gate 	if ((name_buf->value = (void*)malloc(name_buf->length)) ==
350*0Sstevel@tonic-gate 		(void*)NULL) {
351*0Sstevel@tonic-gate 			name_buf->length = 0;
352*0Sstevel@tonic-gate 			(void) gss_release_buffer(&status, &dispName);
353*0Sstevel@tonic-gate 			return (GSS_S_FAILURE);
354*0Sstevel@tonic-gate 	}
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	/* now create the name ..... */
357*0Sstevel@tonic-gate 	buf = (unsigned char *)name_buf->value;
358*0Sstevel@tonic-gate 	(void) memset(name_buf->value, 0, name_buf->length);
359*0Sstevel@tonic-gate 	(void) memcpy(buf, tokId, tokIdLen);
360*0Sstevel@tonic-gate 	buf += tokIdLen;
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	/* spec allows only 2 bytes for the mech oid length */
363*0Sstevel@tonic-gate 	mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
364*0Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0xFF00) >> 8;
365*0Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0x00FF);
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	/*
368*0Sstevel@tonic-gate 	 * DER Encoding of mech OID contains OID Tag (0x06), length and
369*0Sstevel@tonic-gate 	 * mech OID value
370*0Sstevel@tonic-gate 	 */
371*0Sstevel@tonic-gate 	*buf++ = 0x06;
372*0Sstevel@tonic-gate 	if (put_der_length(mech_type->length, &buf,
373*0Sstevel@tonic-gate 		(name_buf->length - tokIdLen -2)) != 0) {
374*0Sstevel@tonic-gate 		name_buf->length = 0;
375*0Sstevel@tonic-gate 		free(name_buf->value);
376*0Sstevel@tonic-gate 		(void) gss_release_buffer(&status, &dispName);
377*0Sstevel@tonic-gate 		return (GSS_S_FAILURE);
378*0Sstevel@tonic-gate 	}
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	(void) memcpy(buf, mech_type->elements, mech_type->length);
381*0Sstevel@tonic-gate 	buf += mech_type->length;
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	/* spec designates the next 4 bytes for the name length */
384*0Sstevel@tonic-gate 	*buf++ = (dispName.length & 0xFF000000) >> 24;
385*0Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x00FF0000) >> 16;
386*0Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x0000FF00) >> 8;
387*0Sstevel@tonic-gate 	*buf++ = (dispName.length & 0X000000FF);
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 	/* for the final ingredient - add the name from gss_display_name */
390*0Sstevel@tonic-gate 	(void) memcpy(buf, dispName.value, dispName.length);
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	/* release the buffer obtained from gss_display_name */
393*0Sstevel@tonic-gate 	(void) gss_release_buffer(minor_status, &dispName);
394*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
395*0Sstevel@tonic-gate } /*  __gss_export_internal_name */
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
399*0Sstevel@tonic-gate 						external_name, name_type)
400*0Sstevel@tonic-gate OM_uint32		*minor_status;
401*0Sstevel@tonic-gate const gss_OID		mech_type;
402*0Sstevel@tonic-gate const gss_name_t	internal_name;
403*0Sstevel@tonic-gate gss_buffer_t		external_name;
404*0Sstevel@tonic-gate gss_OID			*name_type;
405*0Sstevel@tonic-gate {
406*0Sstevel@tonic-gate 	OM_uint32			status;
407*0Sstevel@tonic-gate 	gss_mechanism		mech;
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
410*0Sstevel@tonic-gate 	if (mech) {
411*0Sstevel@tonic-gate 		if (mech->gss_display_name)
412*0Sstevel@tonic-gate 			status = mech->gss_display_name(
413*0Sstevel@tonic-gate 							mech->context,
414*0Sstevel@tonic-gate 							minor_status,
415*0Sstevel@tonic-gate 							internal_name,
416*0Sstevel@tonic-gate 							external_name,
417*0Sstevel@tonic-gate 							name_type);
418*0Sstevel@tonic-gate 		else
419*0Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 		return (status);
422*0Sstevel@tonic-gate 	}
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate OM_uint32
428*0Sstevel@tonic-gate __gss_release_internal_name(minor_status, mech_type, internal_name)
429*0Sstevel@tonic-gate OM_uint32		*minor_status;
430*0Sstevel@tonic-gate const gss_OID		mech_type;
431*0Sstevel@tonic-gate gss_name_t		*internal_name;
432*0Sstevel@tonic-gate {
433*0Sstevel@tonic-gate 	OM_uint32			status;
434*0Sstevel@tonic-gate 	gss_mechanism		mech;
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
437*0Sstevel@tonic-gate 	if (mech) {
438*0Sstevel@tonic-gate 		if (mech->gss_release_name)
439*0Sstevel@tonic-gate 			status = mech->gss_release_name(
440*0Sstevel@tonic-gate 							mech->context,
441*0Sstevel@tonic-gate 							minor_status,
442*0Sstevel@tonic-gate 							internal_name);
443*0Sstevel@tonic-gate 		else
444*0Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 		return (status);
447*0Sstevel@tonic-gate 	}
448*0Sstevel@tonic-gate 
449*0Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
450*0Sstevel@tonic-gate }
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate /*
454*0Sstevel@tonic-gate  * This function converts an internal gssapi name to a union gssapi
455*0Sstevel@tonic-gate  * name.  Note that internal_name should be considered "consumed" by
456*0Sstevel@tonic-gate  * this call, whether or not we return an error.
457*0Sstevel@tonic-gate  */
458*0Sstevel@tonic-gate OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
459*0Sstevel@tonic-gate 						internal_name, external_name)
460*0Sstevel@tonic-gate 	OM_uint32 *minor_status;
461*0Sstevel@tonic-gate 	gss_mechanism		mech;
462*0Sstevel@tonic-gate 	gss_name_t		internal_name;
463*0Sstevel@tonic-gate 	gss_name_t		*external_name;
464*0Sstevel@tonic-gate {
465*0Sstevel@tonic-gate 	OM_uint32 major_status, tmp;
466*0Sstevel@tonic-gate 	gss_union_name_t union_name;
467*0Sstevel@tonic-gate 
468*0Sstevel@tonic-gate 	union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
469*0Sstevel@tonic-gate 	if (!union_name) {
470*0Sstevel@tonic-gate 			goto allocation_failure;
471*0Sstevel@tonic-gate 	}
472*0Sstevel@tonic-gate 	union_name->mech_type = 0;
473*0Sstevel@tonic-gate 	union_name->mech_name = internal_name;
474*0Sstevel@tonic-gate 	union_name->name_type = 0;
475*0Sstevel@tonic-gate 	union_name->external_name = 0;
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 	major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
478*0Sstevel@tonic-gate 						&union_name->mech_type);
479*0Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
480*0Sstevel@tonic-gate 		goto allocation_failure;
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 	union_name->external_name =
483*0Sstevel@tonic-gate 		(gss_buffer_t)malloc(sizeof (gss_buffer_desc));
484*0Sstevel@tonic-gate 	if (!union_name->external_name) {
485*0Sstevel@tonic-gate 			goto allocation_failure;
486*0Sstevel@tonic-gate 	}
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	major_status = mech->gss_display_name(mech->context, minor_status,
489*0Sstevel@tonic-gate 						internal_name,
490*0Sstevel@tonic-gate 						union_name->external_name,
491*0Sstevel@tonic-gate 						&union_name->name_type);
492*0Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
493*0Sstevel@tonic-gate 		goto allocation_failure;
494*0Sstevel@tonic-gate 
495*0Sstevel@tonic-gate 	*external_name =  (gss_name_t)union_name;
496*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate allocation_failure:
499*0Sstevel@tonic-gate 	if (union_name) {
500*0Sstevel@tonic-gate 		if (union_name->external_name) {
501*0Sstevel@tonic-gate 			if (union_name->external_name->value)
502*0Sstevel@tonic-gate 				free(union_name->external_name->value);
503*0Sstevel@tonic-gate 			free(union_name->external_name);
504*0Sstevel@tonic-gate 		}
505*0Sstevel@tonic-gate 		if (union_name->name_type)
506*0Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->name_type);
507*0Sstevel@tonic-gate 		if (union_name->mech_type)
508*0Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->mech_type);
509*0Sstevel@tonic-gate 		free(union_name);
510*0Sstevel@tonic-gate 	}
511*0Sstevel@tonic-gate 	/*
512*0Sstevel@tonic-gate 	 * do as the top comment says - since we are now owners of
513*0Sstevel@tonic-gate 	 * internal_name, we must clean it up
514*0Sstevel@tonic-gate 	 */
515*0Sstevel@tonic-gate 	if (internal_name)
516*0Sstevel@tonic-gate 		(void) __gss_release_internal_name(&tmp, &mech->mech_type,
517*0Sstevel@tonic-gate 						&internal_name);
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 	return (major_status);
520*0Sstevel@tonic-gate }
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate /*
523*0Sstevel@tonic-gate  * Glue routine for returning the mechanism-specific credential from a
524*0Sstevel@tonic-gate  * external union credential.
525*0Sstevel@tonic-gate  */
526*0Sstevel@tonic-gate gss_cred_id_t
527*0Sstevel@tonic-gate __gss_get_mechanism_cred(union_cred, mech_type)
528*0Sstevel@tonic-gate 	const gss_union_cred_t	union_cred;
529*0Sstevel@tonic-gate 	const gss_OID		mech_type;
530*0Sstevel@tonic-gate {
531*0Sstevel@tonic-gate 	int			i;
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate 	if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
534*0Sstevel@tonic-gate 		return (GSS_C_NO_CREDENTIAL);
535*0Sstevel@tonic-gate 
536*0Sstevel@tonic-gate 	for (i = 0; i < union_cred->count; i++) {
537*0Sstevel@tonic-gate 		if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
538*0Sstevel@tonic-gate 			return (union_cred->cred_array[i]);
539*0Sstevel@tonic-gate 	}
540*0Sstevel@tonic-gate 	return (GSS_C_NO_CREDENTIAL);
541*0Sstevel@tonic-gate }
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate /*
545*0Sstevel@tonic-gate  * Routine to create and copy the gss_buffer_desc structure.
546*0Sstevel@tonic-gate  * Both space for the structure and the data is allocated.
547*0Sstevel@tonic-gate  */
548*0Sstevel@tonic-gate OM_uint32
549*0Sstevel@tonic-gate __gss_create_copy_buffer(srcBuf, destBuf, addNullChar)
550*0Sstevel@tonic-gate 	const gss_buffer_t	srcBuf;
551*0Sstevel@tonic-gate 	gss_buffer_t 		*destBuf;
552*0Sstevel@tonic-gate 	int			addNullChar;
553*0Sstevel@tonic-gate {
554*0Sstevel@tonic-gate 	gss_buffer_t aBuf;
555*0Sstevel@tonic-gate 	int len;
556*0Sstevel@tonic-gate 
557*0Sstevel@tonic-gate 	if (destBuf == NULL)
558*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 	*destBuf = 0;
561*0Sstevel@tonic-gate 
562*0Sstevel@tonic-gate 	aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
563*0Sstevel@tonic-gate 	if (!aBuf)
564*0Sstevel@tonic-gate 		return (GSS_S_FAILURE);
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 	if (addNullChar)
567*0Sstevel@tonic-gate 		len = srcBuf->length + 1;
568*0Sstevel@tonic-gate 	else
569*0Sstevel@tonic-gate 		len = srcBuf->length;
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 	if (!(aBuf->value = (void*)malloc(len))) {
572*0Sstevel@tonic-gate 		free(aBuf);
573*0Sstevel@tonic-gate 		return (GSS_S_FAILURE);
574*0Sstevel@tonic-gate 	}
575*0Sstevel@tonic-gate 
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate 	(void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
578*0Sstevel@tonic-gate 	aBuf->length = srcBuf->length;
579*0Sstevel@tonic-gate 	*destBuf = aBuf;
580*0Sstevel@tonic-gate 
581*0Sstevel@tonic-gate 	/* optionally add a NULL character */
582*0Sstevel@tonic-gate 	if (addNullChar)
583*0Sstevel@tonic-gate 		((char *)aBuf->value)[aBuf->length] = '\0';
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
586*0Sstevel@tonic-gate } /* ****** __gss_create_copy_buffer  ****** */
587