xref: /onnv-gate/usr/src/lib/libgss/g_glue.c (revision 5053)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*5053Sgtb  * Common Development and Distribution License (the "License").
6*5053Sgtb  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*5053Sgtb  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <mechglueP.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate #include <errno.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #define	MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * This file contains the support routines for the glue layer.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * get_der_length: Givin a pointer to a buffer that contains a DER encoded
420Sstevel@tonic-gate  * length, decode the length updating the buffer to point to the character
430Sstevel@tonic-gate  * after the DER encoding. The parameter bytes will point to the number of
440Sstevel@tonic-gate  * bytes that made up the DER encoding of the length originally pointed to
450Sstevel@tonic-gate  * by the buffer. Note we return -1 on error.
460Sstevel@tonic-gate  */
470Sstevel@tonic-gate int
480Sstevel@tonic-gate get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
490Sstevel@tonic-gate {
500Sstevel@tonic-gate 	/* p points to the beginning of the buffer */
510Sstevel@tonic-gate 	unsigned char *p = *buf;
520Sstevel@tonic-gate 	int length, new_length;
530Sstevel@tonic-gate 	int octets;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	if (buf_len < 1)
560Sstevel@tonic-gate 		return (-1);
570Sstevel@tonic-gate 
580Sstevel@tonic-gate 	/* We should have at least one byte */
590Sstevel@tonic-gate 	*bytes = 1;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	/*
620Sstevel@tonic-gate 	 * If the High order bit is not set then the length is just the value
630Sstevel@tonic-gate 	 * of *p.
640Sstevel@tonic-gate 	 */
650Sstevel@tonic-gate 	if (*p < 128) {
660Sstevel@tonic-gate 		*buf = p+1;	/* Advance the buffer */
670Sstevel@tonic-gate 	return (*p);		/* return the length */
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	/*
710Sstevel@tonic-gate 	 * if the High order bit is set, then the low order bits represent
720Sstevel@tonic-gate 	 * the number of bytes that contain the DER encoding of the length.
730Sstevel@tonic-gate 	 */
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	octets = *p++ & 0x7f;
760Sstevel@tonic-gate 	*bytes += octets;
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	/* See if the supplied buffer contains enough bytes for the length. */
790Sstevel@tonic-gate 	if (octets > buf_len - 1)
800Sstevel@tonic-gate 		return (-1);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	/*
830Sstevel@tonic-gate 	 * Calculate a multibyte length. The length is encoded as an
840Sstevel@tonic-gate 	 * unsigned integer base 256.
850Sstevel@tonic-gate 	 */
860Sstevel@tonic-gate 	for (length = 0; octets; octets--) {
870Sstevel@tonic-gate 		new_length = (length << 8) + *p++;
880Sstevel@tonic-gate 		if (new_length < length)  /* overflow */
890Sstevel@tonic-gate 			return (-1);
900Sstevel@tonic-gate 		length = new_length;
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	*buf = p; /* Advance the buffer */
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	return (length);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate  * der_length_size: Return the number of bytes to encode a given length.
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate unsigned int
1020Sstevel@tonic-gate der_length_size(unsigned int len)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	int i;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	if (len < 128)
1070Sstevel@tonic-gate 		return (1);
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	for (i = 0; len; i++) {
1100Sstevel@tonic-gate 		len >>= 8;
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	return (i+1);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate  * put_der_length: Encode the supplied length into the buffer pointed to
1180Sstevel@tonic-gate  * by buf. max_length represents the maximum length of the buffer pointed
1190Sstevel@tonic-gate  * to by buff. We will advance buf to point to the character after the newly
1200Sstevel@tonic-gate  * DER encoded length. We return 0 on success or -l it the length cannot
1210Sstevel@tonic-gate  * be encoded in max_len characters.
1220Sstevel@tonic-gate  */
1230Sstevel@tonic-gate int
1240Sstevel@tonic-gate put_der_length(unsigned length, unsigned char **buf, unsigned int max_len)
1250Sstevel@tonic-gate {
1260Sstevel@tonic-gate 	unsigned char *s = *buf, *p;
1270Sstevel@tonic-gate 	unsigned int buf_len = 0;
1280Sstevel@tonic-gate 	int i, first;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	/* Oops */
1310Sstevel@tonic-gate 	if (buf == 0 || max_len < 1)
1320Sstevel@tonic-gate 		return (-1);
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	/* Single byte is the length */
1350Sstevel@tonic-gate 	if (length < 128) {
1360Sstevel@tonic-gate 		*s++ = length;
1370Sstevel@tonic-gate 		*buf = s;
1380Sstevel@tonic-gate 		return (0);
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	/* First byte contains the number of octets */
1420Sstevel@tonic-gate 	p = s + 1;
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	/* Running total of the DER encoding length */
1450Sstevel@tonic-gate 	buf_len = 0;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	/*
1480Sstevel@tonic-gate 	 * Encode MSB first. We do the encoding by setting a shift
1490Sstevel@tonic-gate 	 * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
1500Sstevel@tonic-gate 	 * by the factor. We then encode the resulting low order byte.
1510Sstevel@tonic-gate 	 * We subtract 8 from the shift factor and repeat to ecnode the next
1520Sstevel@tonic-gate 	 * byte. We stop when the shift factor is zero or we've run out of
1530Sstevel@tonic-gate 	 * buffer to encode into.
1540Sstevel@tonic-gate 	 */
1550Sstevel@tonic-gate 	first = 0;
1560Sstevel@tonic-gate 	for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
1570Sstevel@tonic-gate 		unsigned int v;
1580Sstevel@tonic-gate 		v = (length >> i) & 0xff;
1590Sstevel@tonic-gate 		if ((v) || first) {
1600Sstevel@tonic-gate 			buf_len += 1;
1610Sstevel@tonic-gate 			*p++ = v;
1620Sstevel@tonic-gate 			first = 1;
1630Sstevel@tonic-gate 		}
1640Sstevel@tonic-gate 	}
1650Sstevel@tonic-gate 	if (i >= 0)			/* buffer overflow */
1660Sstevel@tonic-gate 		return (-1);
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	/*
1690Sstevel@tonic-gate 	 * We go back now and set the first byte to be the length with
1700Sstevel@tonic-gate 	 * the high order bit set.
1710Sstevel@tonic-gate 	 */
1720Sstevel@tonic-gate 	*s = buf_len | 0x80;
1730Sstevel@tonic-gate 	*buf = p;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	return (0);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate  *  glue routine for get_mech_type
1810Sstevel@tonic-gate  *
1820Sstevel@tonic-gate  */
1830Sstevel@tonic-gate OM_uint32
1840Sstevel@tonic-gate __gss_get_mech_type(OID, token)
1850Sstevel@tonic-gate 	gss_OID			OID;
1860Sstevel@tonic-gate 	const gss_buffer_t	token;
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	unsigned char *buffer_ptr;
1890Sstevel@tonic-gate 	int length;
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	/*
1920Sstevel@tonic-gate 	 * This routine reads the prefix of "token" in order to determine
1930Sstevel@tonic-gate 	 * its mechanism type. It assumes the encoding suggested in
1940Sstevel@tonic-gate 	 * Appendix B of RFC 1508. This format starts out as follows :
1950Sstevel@tonic-gate 	 *
1960Sstevel@tonic-gate 	 * tag for APPLICATION 0, Sequence[constructed, definite length]
1970Sstevel@tonic-gate 	 * length of remainder of token
1980Sstevel@tonic-gate 	 * tag of OBJECT IDENTIFIER
1990Sstevel@tonic-gate 	 * length of mechanism OID
2000Sstevel@tonic-gate 	 * encoding of mechanism OID
2010Sstevel@tonic-gate 	 * <the rest of the token>
2020Sstevel@tonic-gate 	 *
2030Sstevel@tonic-gate 	 * Numerically, this looks like :
2040Sstevel@tonic-gate 	 *
2050Sstevel@tonic-gate 	 * 0x60
2060Sstevel@tonic-gate 	 * <length> - could be multiple bytes
2070Sstevel@tonic-gate 	 * 0x06
2080Sstevel@tonic-gate 	 * <length> - assume only one byte, hence OID length < 127
2090Sstevel@tonic-gate 	 * <mech OID bytes>
2100Sstevel@tonic-gate 	 *
2110Sstevel@tonic-gate 	 * The routine fills in the OID value and returns an error as necessary.
2120Sstevel@tonic-gate 	 */
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	if (OID == NULL)
2150Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	if ((token == NULL) || (token->value == NULL))
2180Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Skip past the APP/Sequnce byte and the token length */
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	buffer_ptr = (unsigned char *) token->value;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x60)
2250Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2260Sstevel@tonic-gate 	length = *buffer_ptr++;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/* check if token length is null */
2290Sstevel@tonic-gate 	if (length == 0)
2300Sstevel@tonic-gate 	    return (GSS_S_DEFECTIVE_TOKEN);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	if (length & 0x80) {
2330Sstevel@tonic-gate 		if ((length & 0x7f) > 4)
2340Sstevel@tonic-gate 			return (GSS_S_DEFECTIVE_TOKEN);
2350Sstevel@tonic-gate 		buffer_ptr += length & 0x7f;
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x06)
2390Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	OID->length = (OM_uint32) *(buffer_ptr++);
2420Sstevel@tonic-gate 	OID->elements = (void *) buffer_ptr;
2430Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate  *  Internal routines to get and release an internal mechanism name
2490Sstevel@tonic-gate  */
2500Sstevel@tonic-gate OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
2510Sstevel@tonic-gate 					internal_name)
2520Sstevel@tonic-gate OM_uint32		*minor_status;
2530Sstevel@tonic-gate const gss_OID		mech_type;
2540Sstevel@tonic-gate gss_union_name_t	union_name;
2550Sstevel@tonic-gate gss_name_t		*internal_name;
2560Sstevel@tonic-gate {
2570Sstevel@tonic-gate 	OM_uint32			status;
2580Sstevel@tonic-gate 	gss_mechanism		mech;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
2610Sstevel@tonic-gate 	if (mech) {
2620Sstevel@tonic-gate 		if (mech->gss_import_name)
2630Sstevel@tonic-gate 			status = mech->gss_import_name(
2640Sstevel@tonic-gate 						mech->context,
2650Sstevel@tonic-gate 						minor_status,
2660Sstevel@tonic-gate 						union_name->external_name,
2670Sstevel@tonic-gate 						union_name->name_type,
2680Sstevel@tonic-gate 						internal_name);
2690Sstevel@tonic-gate 		else
2700Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 		return (status);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate OM_uint32 __gss_export_internal_name(minor_status, mech_type,
2800Sstevel@tonic-gate 		internal_name, name_buf)
2810Sstevel@tonic-gate OM_uint32		*minor_status;
2820Sstevel@tonic-gate const gss_OID		mech_type;
2830Sstevel@tonic-gate const gss_name_t	internal_name;
2840Sstevel@tonic-gate gss_buffer_t		name_buf;
2850Sstevel@tonic-gate {
2860Sstevel@tonic-gate 	OM_uint32 status;
2870Sstevel@tonic-gate 	gss_mechanism mech;
2880Sstevel@tonic-gate 	gss_buffer_desc dispName;
2890Sstevel@tonic-gate 	gss_OID nameOid;
2900Sstevel@tonic-gate 	unsigned char *buf = NULL;
2910Sstevel@tonic-gate 	const unsigned char tokId[] = "\x04\x01";
2920Sstevel@tonic-gate 	const int tokIdLen = 2;
2930Sstevel@tonic-gate 	const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
2940Sstevel@tonic-gate 	int mechOidDERLen = 0;
2950Sstevel@tonic-gate 	int mechOidLen = 0;
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
2980Sstevel@tonic-gate 	if (!mech)
2990Sstevel@tonic-gate 		return (GSS_S_BAD_MECH);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if (mech->gss_export_name)
3020Sstevel@tonic-gate 		return (mech->gss_export_name(mech->context,
3030Sstevel@tonic-gate 						minor_status,
3040Sstevel@tonic-gate 						internal_name,
3050Sstevel@tonic-gate 						name_buf));
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 	/*
3080Sstevel@tonic-gate 	 * if we are here it is because the mechanism does not provide
3090Sstevel@tonic-gate 	 * a gss_export_name so we will use our implementation.  We
3100Sstevel@tonic-gate 	 * do required that the mechanism define a gss_display_name.
3110Sstevel@tonic-gate 	 */
3120Sstevel@tonic-gate 	if (!mech->gss_display_name)
3130Sstevel@tonic-gate 		return (GSS_S_UNAVAILABLE);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	/*
3160Sstevel@tonic-gate 	 * NOTE: RFC2743 (section 3.2) governs the format of the outer
3170Sstevel@tonic-gate 	 *	 wrapper of exported names; the mechanisms' specs govern
3180Sstevel@tonic-gate 	 *	 the format of the inner portion of the exported name
3190Sstevel@tonic-gate 	 *	 and, for some (e.g., RFC1964, the Kerberos V mech), a
3200Sstevel@tonic-gate 	 *	 generic default as implemented here will do.
3210Sstevel@tonic-gate 	 *
3220Sstevel@tonic-gate 	 * The outer wrapper of an exported MN is: 2-octet tok Id
3230Sstevel@tonic-gate 	 * (0x0401) + 2-octet network-byte order mech OID length + mech
3240Sstevel@tonic-gate 	 * oid (in DER format, including DER tag and DER length) +
3250Sstevel@tonic-gate 	 * 4-octet network-byte order length of inner portion + inner
3260Sstevel@tonic-gate 	 * portion.
3270Sstevel@tonic-gate 	 *
3280Sstevel@tonic-gate 	 * For the Kerberos V mechanism the inner portion of an exported
3290Sstevel@tonic-gate 	 * MN is the display name string and ignores the name type OID
3300Sstevel@tonic-gate 	 * altogether.  And we hope this will be so for any future
3310Sstevel@tonic-gate 	 * mechanisms also, so that factoring name export/import out of
3320Sstevel@tonic-gate 	 * the mech and into libgss pays off.
3330Sstevel@tonic-gate 	 */
3340Sstevel@tonic-gate 	if ((status = mech->gss_display_name(mech->context,
3350Sstevel@tonic-gate 						minor_status,
3360Sstevel@tonic-gate 						internal_name,
3370Sstevel@tonic-gate 						&dispName,
3380Sstevel@tonic-gate 						&nameOid))
3390Sstevel@tonic-gate 						!= GSS_S_COMPLETE)
3400Sstevel@tonic-gate 		return (status);
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	/* determine the size of the buffer needed */
3430Sstevel@tonic-gate 	mechOidDERLen = der_length_size(mech_type->length);
3440Sstevel@tonic-gate 	name_buf->length = tokIdLen + mechOidLenLen +
3450Sstevel@tonic-gate 				mechOidTagLen + mechOidDERLen +
3460Sstevel@tonic-gate 				mech_type->length +
3470Sstevel@tonic-gate 				nameLenLen + dispName.length;
3480Sstevel@tonic-gate 	if ((name_buf->value = (void*)malloc(name_buf->length)) ==
3490Sstevel@tonic-gate 		(void*)NULL) {
3500Sstevel@tonic-gate 			name_buf->length = 0;
3510Sstevel@tonic-gate 			(void) gss_release_buffer(&status, &dispName);
3520Sstevel@tonic-gate 			return (GSS_S_FAILURE);
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	/* now create the name ..... */
3560Sstevel@tonic-gate 	buf = (unsigned char *)name_buf->value;
3570Sstevel@tonic-gate 	(void) memset(name_buf->value, 0, name_buf->length);
3580Sstevel@tonic-gate 	(void) memcpy(buf, tokId, tokIdLen);
3590Sstevel@tonic-gate 	buf += tokIdLen;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	/* spec allows only 2 bytes for the mech oid length */
3620Sstevel@tonic-gate 	mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
3630Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0xFF00) >> 8;
3640Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0x00FF);
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	/*
3670Sstevel@tonic-gate 	 * DER Encoding of mech OID contains OID Tag (0x06), length and
3680Sstevel@tonic-gate 	 * mech OID value
3690Sstevel@tonic-gate 	 */
3700Sstevel@tonic-gate 	*buf++ = 0x06;
3710Sstevel@tonic-gate 	if (put_der_length(mech_type->length, &buf,
3720Sstevel@tonic-gate 		(name_buf->length - tokIdLen -2)) != 0) {
3730Sstevel@tonic-gate 		name_buf->length = 0;
3740Sstevel@tonic-gate 		free(name_buf->value);
3750Sstevel@tonic-gate 		(void) gss_release_buffer(&status, &dispName);
3760Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	(void) memcpy(buf, mech_type->elements, mech_type->length);
3800Sstevel@tonic-gate 	buf += mech_type->length;
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	/* spec designates the next 4 bytes for the name length */
3830Sstevel@tonic-gate 	*buf++ = (dispName.length & 0xFF000000) >> 24;
3840Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x00FF0000) >> 16;
3850Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x0000FF00) >> 8;
3860Sstevel@tonic-gate 	*buf++ = (dispName.length & 0X000000FF);
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	/* for the final ingredient - add the name from gss_display_name */
3890Sstevel@tonic-gate 	(void) memcpy(buf, dispName.value, dispName.length);
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	/* release the buffer obtained from gss_display_name */
3920Sstevel@tonic-gate 	(void) gss_release_buffer(minor_status, &dispName);
3930Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
3940Sstevel@tonic-gate } /*  __gss_export_internal_name */
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
3980Sstevel@tonic-gate 						external_name, name_type)
3990Sstevel@tonic-gate OM_uint32		*minor_status;
4000Sstevel@tonic-gate const gss_OID		mech_type;
4010Sstevel@tonic-gate const gss_name_t	internal_name;
4020Sstevel@tonic-gate gss_buffer_t		external_name;
4030Sstevel@tonic-gate gss_OID			*name_type;
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate 	OM_uint32			status;
4060Sstevel@tonic-gate 	gss_mechanism		mech;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
4090Sstevel@tonic-gate 	if (mech) {
4100Sstevel@tonic-gate 		if (mech->gss_display_name)
4110Sstevel@tonic-gate 			status = mech->gss_display_name(
4120Sstevel@tonic-gate 							mech->context,
4130Sstevel@tonic-gate 							minor_status,
4140Sstevel@tonic-gate 							internal_name,
4150Sstevel@tonic-gate 							external_name,
4160Sstevel@tonic-gate 							name_type);
4170Sstevel@tonic-gate 		else
4180Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 		return (status);
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate OM_uint32
4270Sstevel@tonic-gate __gss_release_internal_name(minor_status, mech_type, internal_name)
4280Sstevel@tonic-gate OM_uint32		*minor_status;
4290Sstevel@tonic-gate const gss_OID		mech_type;
4300Sstevel@tonic-gate gss_name_t		*internal_name;
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate 	OM_uint32			status;
4330Sstevel@tonic-gate 	gss_mechanism		mech;
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
4360Sstevel@tonic-gate 	if (mech) {
4370Sstevel@tonic-gate 		if (mech->gss_release_name)
4380Sstevel@tonic-gate 			status = mech->gss_release_name(
4390Sstevel@tonic-gate 							mech->context,
4400Sstevel@tonic-gate 							minor_status,
4410Sstevel@tonic-gate 							internal_name);
4420Sstevel@tonic-gate 		else
4430Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 		return (status);
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate /*
4530Sstevel@tonic-gate  * This function converts an internal gssapi name to a union gssapi
4540Sstevel@tonic-gate  * name.  Note that internal_name should be considered "consumed" by
4550Sstevel@tonic-gate  * this call, whether or not we return an error.
4560Sstevel@tonic-gate  */
4570Sstevel@tonic-gate OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
4580Sstevel@tonic-gate 						internal_name, external_name)
4590Sstevel@tonic-gate 	OM_uint32 *minor_status;
4600Sstevel@tonic-gate 	gss_mechanism		mech;
4610Sstevel@tonic-gate 	gss_name_t		internal_name;
4620Sstevel@tonic-gate 	gss_name_t		*external_name;
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate 	OM_uint32 major_status, tmp;
4650Sstevel@tonic-gate 	gss_union_name_t union_name;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
4680Sstevel@tonic-gate 	if (!union_name) {
4690Sstevel@tonic-gate 			goto allocation_failure;
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 	union_name->mech_type = 0;
4720Sstevel@tonic-gate 	union_name->mech_name = internal_name;
4730Sstevel@tonic-gate 	union_name->name_type = 0;
4740Sstevel@tonic-gate 	union_name->external_name = 0;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
4770Sstevel@tonic-gate 						&union_name->mech_type);
4780Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
4790Sstevel@tonic-gate 		goto allocation_failure;
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	union_name->external_name =
4820Sstevel@tonic-gate 		(gss_buffer_t)malloc(sizeof (gss_buffer_desc));
4830Sstevel@tonic-gate 	if (!union_name->external_name) {
4840Sstevel@tonic-gate 			goto allocation_failure;
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	major_status = mech->gss_display_name(mech->context, minor_status,
4880Sstevel@tonic-gate 						internal_name,
4890Sstevel@tonic-gate 						union_name->external_name,
4900Sstevel@tonic-gate 						&union_name->name_type);
4910Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
4920Sstevel@tonic-gate 		goto allocation_failure;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	*external_name =  (gss_name_t)union_name;
4950Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate allocation_failure:
4980Sstevel@tonic-gate 	if (union_name) {
4990Sstevel@tonic-gate 		if (union_name->external_name) {
5000Sstevel@tonic-gate 			if (union_name->external_name->value)
5010Sstevel@tonic-gate 				free(union_name->external_name->value);
5020Sstevel@tonic-gate 			free(union_name->external_name);
5030Sstevel@tonic-gate 		}
5040Sstevel@tonic-gate 		if (union_name->name_type)
5050Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->name_type);
5060Sstevel@tonic-gate 		if (union_name->mech_type)
5070Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->mech_type);
5080Sstevel@tonic-gate 		free(union_name);
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 	/*
5110Sstevel@tonic-gate 	 * do as the top comment says - since we are now owners of
5120Sstevel@tonic-gate 	 * internal_name, we must clean it up
5130Sstevel@tonic-gate 	 */
5140Sstevel@tonic-gate 	if (internal_name)
5150Sstevel@tonic-gate 		(void) __gss_release_internal_name(&tmp, &mech->mech_type,
5160Sstevel@tonic-gate 						&internal_name);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	return (major_status);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate  * Glue routine for returning the mechanism-specific credential from a
5230Sstevel@tonic-gate  * external union credential.
5240Sstevel@tonic-gate  */
5250Sstevel@tonic-gate gss_cred_id_t
5260Sstevel@tonic-gate __gss_get_mechanism_cred(union_cred, mech_type)
5270Sstevel@tonic-gate 	const gss_union_cred_t	union_cred;
5280Sstevel@tonic-gate 	const gss_OID		mech_type;
5290Sstevel@tonic-gate {
5300Sstevel@tonic-gate 	int			i;
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
5330Sstevel@tonic-gate 		return (GSS_C_NO_CREDENTIAL);
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	for (i = 0; i < union_cred->count; i++) {
5360Sstevel@tonic-gate 		if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
5370Sstevel@tonic-gate 			return (union_cred->cred_array[i]);
5380Sstevel@tonic-gate 	}
5390Sstevel@tonic-gate 	return (GSS_C_NO_CREDENTIAL);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate /*
5440Sstevel@tonic-gate  * Routine to create and copy the gss_buffer_desc structure.
5450Sstevel@tonic-gate  * Both space for the structure and the data is allocated.
5460Sstevel@tonic-gate  */
5470Sstevel@tonic-gate OM_uint32
548*5053Sgtb gssint_create_copy_buffer(srcBuf, destBuf, addNullChar)
5490Sstevel@tonic-gate 	const gss_buffer_t	srcBuf;
5500Sstevel@tonic-gate 	gss_buffer_t 		*destBuf;
5510Sstevel@tonic-gate 	int			addNullChar;
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate 	gss_buffer_t aBuf;
5540Sstevel@tonic-gate 	int len;
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if (destBuf == NULL)
5570Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	*destBuf = 0;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
5620Sstevel@tonic-gate 	if (!aBuf)
5630Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if (addNullChar)
5660Sstevel@tonic-gate 		len = srcBuf->length + 1;
5670Sstevel@tonic-gate 	else
5680Sstevel@tonic-gate 		len = srcBuf->length;
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	if (!(aBuf->value = (void*)malloc(len))) {
5710Sstevel@tonic-gate 		free(aBuf);
5720Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	(void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
5770Sstevel@tonic-gate 	aBuf->length = srcBuf->length;
5780Sstevel@tonic-gate 	*destBuf = aBuf;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	/* optionally add a NULL character */
5810Sstevel@tonic-gate 	if (addNullChar)
5820Sstevel@tonic-gate 		((char *)aBuf->value)[aBuf->length] = '\0';
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
5850Sstevel@tonic-gate } /* ****** __gss_create_copy_buffer  ****** */
586