xref: /titanic_53/usr/src/lib/libgss/g_glue.c (revision ab9b2e153c3a9a2b1141fefa87925b1a9beb1236)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*ab9b2e15Sgtb  * Common Development and Distribution License (the "License").
6*ab9b2e15Sgtb  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*ab9b2e15Sgtb  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <mechglueP.h>
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <strings.h>
327c478bd9Sstevel@tonic-gate #include <errno.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #define	MSO_BIT (8*(sizeof (int) - 1))  /* Most significant octet bit */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * This file contains the support routines for the glue layer.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * get_der_length: Givin a pointer to a buffer that contains a DER encoded
427c478bd9Sstevel@tonic-gate  * length, decode the length updating the buffer to point to the character
437c478bd9Sstevel@tonic-gate  * after the DER encoding. The parameter bytes will point to the number of
447c478bd9Sstevel@tonic-gate  * bytes that made up the DER encoding of the length originally pointed to
457c478bd9Sstevel@tonic-gate  * by the buffer. Note we return -1 on error.
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate int
487c478bd9Sstevel@tonic-gate get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
497c478bd9Sstevel@tonic-gate {
507c478bd9Sstevel@tonic-gate 	/* p points to the beginning of the buffer */
517c478bd9Sstevel@tonic-gate 	unsigned char *p = *buf;
527c478bd9Sstevel@tonic-gate 	int length, new_length;
537c478bd9Sstevel@tonic-gate 	int octets;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 	if (buf_len < 1)
567c478bd9Sstevel@tonic-gate 		return (-1);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	/* We should have at least one byte */
597c478bd9Sstevel@tonic-gate 	*bytes = 1;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 	/*
627c478bd9Sstevel@tonic-gate 	 * If the High order bit is not set then the length is just the value
637c478bd9Sstevel@tonic-gate 	 * of *p.
647c478bd9Sstevel@tonic-gate 	 */
657c478bd9Sstevel@tonic-gate 	if (*p < 128) {
667c478bd9Sstevel@tonic-gate 		*buf = p+1;	/* Advance the buffer */
677c478bd9Sstevel@tonic-gate 	return (*p);		/* return the length */
687c478bd9Sstevel@tonic-gate 	}
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	/*
717c478bd9Sstevel@tonic-gate 	 * if the High order bit is set, then the low order bits represent
727c478bd9Sstevel@tonic-gate 	 * the number of bytes that contain the DER encoding of the length.
737c478bd9Sstevel@tonic-gate 	 */
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	octets = *p++ & 0x7f;
767c478bd9Sstevel@tonic-gate 	*bytes += octets;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	/* See if the supplied buffer contains enough bytes for the length. */
797c478bd9Sstevel@tonic-gate 	if (octets > buf_len - 1)
807c478bd9Sstevel@tonic-gate 		return (-1);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	/*
837c478bd9Sstevel@tonic-gate 	 * Calculate a multibyte length. The length is encoded as an
847c478bd9Sstevel@tonic-gate 	 * unsigned integer base 256.
857c478bd9Sstevel@tonic-gate 	 */
867c478bd9Sstevel@tonic-gate 	for (length = 0; octets; octets--) {
877c478bd9Sstevel@tonic-gate 		new_length = (length << 8) + *p++;
887c478bd9Sstevel@tonic-gate 		if (new_length < length)  /* overflow */
897c478bd9Sstevel@tonic-gate 			return (-1);
907c478bd9Sstevel@tonic-gate 		length = new_length;
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	*buf = p; /* Advance the buffer */
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	return (length);
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * der_length_size: Return the number of bytes to encode a given length.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate unsigned int
1027c478bd9Sstevel@tonic-gate der_length_size(unsigned int len)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	int i;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	if (len < 128)
1077c478bd9Sstevel@tonic-gate 		return (1);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	for (i = 0; len; i++) {
1107c478bd9Sstevel@tonic-gate 		len >>= 8;
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	return (i+1);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * put_der_length: Encode the supplied length into the buffer pointed to
1187c478bd9Sstevel@tonic-gate  * by buf. max_length represents the maximum length of the buffer pointed
1197c478bd9Sstevel@tonic-gate  * to by buff. We will advance buf to point to the character after the newly
1207c478bd9Sstevel@tonic-gate  * DER encoded length. We return 0 on success or -l it the length cannot
1217c478bd9Sstevel@tonic-gate  * be encoded in max_len characters.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate int
1247c478bd9Sstevel@tonic-gate put_der_length(unsigned length, unsigned char **buf, unsigned int max_len)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	unsigned char *s = *buf, *p;
1277c478bd9Sstevel@tonic-gate 	unsigned int buf_len = 0;
1287c478bd9Sstevel@tonic-gate 	int i, first;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/* Oops */
1317c478bd9Sstevel@tonic-gate 	if (buf == 0 || max_len < 1)
1327c478bd9Sstevel@tonic-gate 		return (-1);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	/* Single byte is the length */
1357c478bd9Sstevel@tonic-gate 	if (length < 128) {
1367c478bd9Sstevel@tonic-gate 		*s++ = length;
1377c478bd9Sstevel@tonic-gate 		*buf = s;
1387c478bd9Sstevel@tonic-gate 		return (0);
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/* First byte contains the number of octets */
1427c478bd9Sstevel@tonic-gate 	p = s + 1;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/* Running total of the DER encoding length */
1457c478bd9Sstevel@tonic-gate 	buf_len = 0;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/*
1487c478bd9Sstevel@tonic-gate 	 * Encode MSB first. We do the encoding by setting a shift
1497c478bd9Sstevel@tonic-gate 	 * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
1507c478bd9Sstevel@tonic-gate 	 * by the factor. We then encode the resulting low order byte.
1517c478bd9Sstevel@tonic-gate 	 * We subtract 8 from the shift factor and repeat to ecnode the next
1527c478bd9Sstevel@tonic-gate 	 * byte. We stop when the shift factor is zero or we've run out of
1537c478bd9Sstevel@tonic-gate 	 * buffer to encode into.
1547c478bd9Sstevel@tonic-gate 	 */
1557c478bd9Sstevel@tonic-gate 	first = 0;
1567c478bd9Sstevel@tonic-gate 	for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
1577c478bd9Sstevel@tonic-gate 		unsigned int v;
1587c478bd9Sstevel@tonic-gate 		v = (length >> i) & 0xff;
1597c478bd9Sstevel@tonic-gate 		if ((v) || first) {
1607c478bd9Sstevel@tonic-gate 			buf_len += 1;
1617c478bd9Sstevel@tonic-gate 			*p++ = v;
1627c478bd9Sstevel@tonic-gate 			first = 1;
1637c478bd9Sstevel@tonic-gate 		}
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	if (i >= 0)			/* buffer overflow */
1667c478bd9Sstevel@tonic-gate 		return (-1);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	/*
1697c478bd9Sstevel@tonic-gate 	 * We go back now and set the first byte to be the length with
1707c478bd9Sstevel@tonic-gate 	 * the high order bit set.
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 	*s = buf_len | 0x80;
1737c478bd9Sstevel@tonic-gate 	*buf = p;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	return (0);
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  *  glue routine for get_mech_type
1817c478bd9Sstevel@tonic-gate  *
1827c478bd9Sstevel@tonic-gate  */
1837c478bd9Sstevel@tonic-gate OM_uint32
1847c478bd9Sstevel@tonic-gate __gss_get_mech_type(OID, token)
1857c478bd9Sstevel@tonic-gate 	gss_OID			OID;
1867c478bd9Sstevel@tonic-gate 	const gss_buffer_t	token;
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	unsigned char *buffer_ptr;
1897c478bd9Sstevel@tonic-gate 	int length;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/*
1927c478bd9Sstevel@tonic-gate 	 * This routine reads the prefix of "token" in order to determine
1937c478bd9Sstevel@tonic-gate 	 * its mechanism type. It assumes the encoding suggested in
1947c478bd9Sstevel@tonic-gate 	 * Appendix B of RFC 1508. This format starts out as follows :
1957c478bd9Sstevel@tonic-gate 	 *
1967c478bd9Sstevel@tonic-gate 	 * tag for APPLICATION 0, Sequence[constructed, definite length]
1977c478bd9Sstevel@tonic-gate 	 * length of remainder of token
1987c478bd9Sstevel@tonic-gate 	 * tag of OBJECT IDENTIFIER
1997c478bd9Sstevel@tonic-gate 	 * length of mechanism OID
2007c478bd9Sstevel@tonic-gate 	 * encoding of mechanism OID
2017c478bd9Sstevel@tonic-gate 	 * <the rest of the token>
2027c478bd9Sstevel@tonic-gate 	 *
2037c478bd9Sstevel@tonic-gate 	 * Numerically, this looks like :
2047c478bd9Sstevel@tonic-gate 	 *
2057c478bd9Sstevel@tonic-gate 	 * 0x60
2067c478bd9Sstevel@tonic-gate 	 * <length> - could be multiple bytes
2077c478bd9Sstevel@tonic-gate 	 * 0x06
2087c478bd9Sstevel@tonic-gate 	 * <length> - assume only one byte, hence OID length < 127
2097c478bd9Sstevel@tonic-gate 	 * <mech OID bytes>
2107c478bd9Sstevel@tonic-gate 	 *
2117c478bd9Sstevel@tonic-gate 	 * The routine fills in the OID value and returns an error as necessary.
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (OID == NULL)
2157c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if ((token == NULL) || (token->value == NULL))
2187c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/* Skip past the APP/Sequnce byte and the token length */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	buffer_ptr = (unsigned char *) token->value;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x60)
2257c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2267c478bd9Sstevel@tonic-gate 	length = *buffer_ptr++;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/* check if token length is null */
2297c478bd9Sstevel@tonic-gate 	if (length == 0)
2307c478bd9Sstevel@tonic-gate 	    return (GSS_S_DEFECTIVE_TOKEN);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	if (length & 0x80) {
2337c478bd9Sstevel@tonic-gate 		if ((length & 0x7f) > 4)
2347c478bd9Sstevel@tonic-gate 			return (GSS_S_DEFECTIVE_TOKEN);
2357c478bd9Sstevel@tonic-gate 		buffer_ptr += length & 0x7f;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if (*(buffer_ptr++) != 0x06)
2397c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	OID->length = (OM_uint32) *(buffer_ptr++);
2427c478bd9Sstevel@tonic-gate 	OID->elements = (void *) buffer_ptr;
2437c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate  *  Internal routines to get and release an internal mechanism name
2497c478bd9Sstevel@tonic-gate  */
2507c478bd9Sstevel@tonic-gate OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
2517c478bd9Sstevel@tonic-gate 					internal_name)
2527c478bd9Sstevel@tonic-gate OM_uint32		*minor_status;
2537c478bd9Sstevel@tonic-gate const gss_OID		mech_type;
2547c478bd9Sstevel@tonic-gate gss_union_name_t	union_name;
2557c478bd9Sstevel@tonic-gate gss_name_t		*internal_name;
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate 	OM_uint32			status;
2587c478bd9Sstevel@tonic-gate 	gss_mechanism		mech;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
2617c478bd9Sstevel@tonic-gate 	if (mech) {
2627c478bd9Sstevel@tonic-gate 		if (mech->gss_import_name)
2637c478bd9Sstevel@tonic-gate 			status = mech->gss_import_name(
2647c478bd9Sstevel@tonic-gate 						mech->context,
2657c478bd9Sstevel@tonic-gate 						minor_status,
2667c478bd9Sstevel@tonic-gate 						union_name->external_name,
2677c478bd9Sstevel@tonic-gate 						union_name->name_type,
2687c478bd9Sstevel@tonic-gate 						internal_name);
2697c478bd9Sstevel@tonic-gate 		else
2707c478bd9Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 		return (status);
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate OM_uint32 __gss_export_internal_name(minor_status, mech_type,
2807c478bd9Sstevel@tonic-gate 		internal_name, name_buf)
2817c478bd9Sstevel@tonic-gate OM_uint32		*minor_status;
2827c478bd9Sstevel@tonic-gate const gss_OID		mech_type;
2837c478bd9Sstevel@tonic-gate const gss_name_t	internal_name;
2847c478bd9Sstevel@tonic-gate gss_buffer_t		name_buf;
2857c478bd9Sstevel@tonic-gate {
2867c478bd9Sstevel@tonic-gate 	OM_uint32 status;
2877c478bd9Sstevel@tonic-gate 	gss_mechanism mech;
2887c478bd9Sstevel@tonic-gate 	gss_buffer_desc dispName;
2897c478bd9Sstevel@tonic-gate 	gss_OID nameOid;
2907c478bd9Sstevel@tonic-gate 	unsigned char *buf = NULL;
2917c478bd9Sstevel@tonic-gate 	const unsigned char tokId[] = "\x04\x01";
2927c478bd9Sstevel@tonic-gate 	const int tokIdLen = 2;
2937c478bd9Sstevel@tonic-gate 	const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
2947c478bd9Sstevel@tonic-gate 	int mechOidDERLen = 0;
2957c478bd9Sstevel@tonic-gate 	int mechOidLen = 0;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
2987c478bd9Sstevel@tonic-gate 	if (!mech)
2997c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_MECH);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (mech->gss_export_name)
3027c478bd9Sstevel@tonic-gate 		return (mech->gss_export_name(mech->context,
3037c478bd9Sstevel@tonic-gate 						minor_status,
3047c478bd9Sstevel@tonic-gate 						internal_name,
3057c478bd9Sstevel@tonic-gate 						name_buf));
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	/*
3087c478bd9Sstevel@tonic-gate 	 * if we are here it is because the mechanism does not provide
3097c478bd9Sstevel@tonic-gate 	 * a gss_export_name so we will use our implementation.  We
3107c478bd9Sstevel@tonic-gate 	 * do required that the mechanism define a gss_display_name.
3117c478bd9Sstevel@tonic-gate 	 */
3127c478bd9Sstevel@tonic-gate 	if (!mech->gss_display_name)
3137c478bd9Sstevel@tonic-gate 		return (GSS_S_UNAVAILABLE);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	/*
3167c478bd9Sstevel@tonic-gate 	 * NOTE: RFC2743 (section 3.2) governs the format of the outer
3177c478bd9Sstevel@tonic-gate 	 *	 wrapper of exported names; the mechanisms' specs govern
3187c478bd9Sstevel@tonic-gate 	 *	 the format of the inner portion of the exported name
3197c478bd9Sstevel@tonic-gate 	 *	 and, for some (e.g., RFC1964, the Kerberos V mech), a
3207c478bd9Sstevel@tonic-gate 	 *	 generic default as implemented here will do.
3217c478bd9Sstevel@tonic-gate 	 *
3227c478bd9Sstevel@tonic-gate 	 * The outer wrapper of an exported MN is: 2-octet tok Id
3237c478bd9Sstevel@tonic-gate 	 * (0x0401) + 2-octet network-byte order mech OID length + mech
3247c478bd9Sstevel@tonic-gate 	 * oid (in DER format, including DER tag and DER length) +
3257c478bd9Sstevel@tonic-gate 	 * 4-octet network-byte order length of inner portion + inner
3267c478bd9Sstevel@tonic-gate 	 * portion.
3277c478bd9Sstevel@tonic-gate 	 *
3287c478bd9Sstevel@tonic-gate 	 * For the Kerberos V mechanism the inner portion of an exported
3297c478bd9Sstevel@tonic-gate 	 * MN is the display name string and ignores the name type OID
3307c478bd9Sstevel@tonic-gate 	 * altogether.  And we hope this will be so for any future
3317c478bd9Sstevel@tonic-gate 	 * mechanisms also, so that factoring name export/import out of
3327c478bd9Sstevel@tonic-gate 	 * the mech and into libgss pays off.
3337c478bd9Sstevel@tonic-gate 	 */
3347c478bd9Sstevel@tonic-gate 	if ((status = mech->gss_display_name(mech->context,
3357c478bd9Sstevel@tonic-gate 						minor_status,
3367c478bd9Sstevel@tonic-gate 						internal_name,
3377c478bd9Sstevel@tonic-gate 						&dispName,
3387c478bd9Sstevel@tonic-gate 						&nameOid))
3397c478bd9Sstevel@tonic-gate 						!= GSS_S_COMPLETE)
3407c478bd9Sstevel@tonic-gate 		return (status);
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/* determine the size of the buffer needed */
3437c478bd9Sstevel@tonic-gate 	mechOidDERLen = der_length_size(mech_type->length);
3447c478bd9Sstevel@tonic-gate 	name_buf->length = tokIdLen + mechOidLenLen +
3457c478bd9Sstevel@tonic-gate 				mechOidTagLen + mechOidDERLen +
3467c478bd9Sstevel@tonic-gate 				mech_type->length +
3477c478bd9Sstevel@tonic-gate 				nameLenLen + dispName.length;
3487c478bd9Sstevel@tonic-gate 	if ((name_buf->value = (void*)malloc(name_buf->length)) ==
3497c478bd9Sstevel@tonic-gate 		(void*)NULL) {
3507c478bd9Sstevel@tonic-gate 			name_buf->length = 0;
3517c478bd9Sstevel@tonic-gate 			(void) gss_release_buffer(&status, &dispName);
3527c478bd9Sstevel@tonic-gate 			return (GSS_S_FAILURE);
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/* now create the name ..... */
3567c478bd9Sstevel@tonic-gate 	buf = (unsigned char *)name_buf->value;
3577c478bd9Sstevel@tonic-gate 	(void) memset(name_buf->value, 0, name_buf->length);
3587c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, tokId, tokIdLen);
3597c478bd9Sstevel@tonic-gate 	buf += tokIdLen;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/* spec allows only 2 bytes for the mech oid length */
3627c478bd9Sstevel@tonic-gate 	mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
3637c478bd9Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0xFF00) >> 8;
3647c478bd9Sstevel@tonic-gate 	*buf++ = (mechOidLen & 0x00FF);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/*
3677c478bd9Sstevel@tonic-gate 	 * DER Encoding of mech OID contains OID Tag (0x06), length and
3687c478bd9Sstevel@tonic-gate 	 * mech OID value
3697c478bd9Sstevel@tonic-gate 	 */
3707c478bd9Sstevel@tonic-gate 	*buf++ = 0x06;
3717c478bd9Sstevel@tonic-gate 	if (put_der_length(mech_type->length, &buf,
3727c478bd9Sstevel@tonic-gate 		(name_buf->length - tokIdLen -2)) != 0) {
3737c478bd9Sstevel@tonic-gate 		name_buf->length = 0;
3747c478bd9Sstevel@tonic-gate 		free(name_buf->value);
3757c478bd9Sstevel@tonic-gate 		(void) gss_release_buffer(&status, &dispName);
3767c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, mech_type->elements, mech_type->length);
3807c478bd9Sstevel@tonic-gate 	buf += mech_type->length;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	/* spec designates the next 4 bytes for the name length */
3837c478bd9Sstevel@tonic-gate 	*buf++ = (dispName.length & 0xFF000000) >> 24;
3847c478bd9Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x00FF0000) >> 16;
3857c478bd9Sstevel@tonic-gate 	*buf++ = (dispName.length & 0x0000FF00) >> 8;
3867c478bd9Sstevel@tonic-gate 	*buf++ = (dispName.length & 0X000000FF);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* for the final ingredient - add the name from gss_display_name */
3897c478bd9Sstevel@tonic-gate 	(void) memcpy(buf, dispName.value, dispName.length);
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/* release the buffer obtained from gss_display_name */
3927c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(minor_status, &dispName);
3937c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
3947c478bd9Sstevel@tonic-gate } /*  __gss_export_internal_name */
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
3987c478bd9Sstevel@tonic-gate 						external_name, name_type)
3997c478bd9Sstevel@tonic-gate OM_uint32		*minor_status;
4007c478bd9Sstevel@tonic-gate const gss_OID		mech_type;
4017c478bd9Sstevel@tonic-gate const gss_name_t	internal_name;
4027c478bd9Sstevel@tonic-gate gss_buffer_t		external_name;
4037c478bd9Sstevel@tonic-gate gss_OID			*name_type;
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	OM_uint32			status;
4067c478bd9Sstevel@tonic-gate 	gss_mechanism		mech;
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
4097c478bd9Sstevel@tonic-gate 	if (mech) {
4107c478bd9Sstevel@tonic-gate 		if (mech->gss_display_name)
4117c478bd9Sstevel@tonic-gate 			status = mech->gss_display_name(
4127c478bd9Sstevel@tonic-gate 							mech->context,
4137c478bd9Sstevel@tonic-gate 							minor_status,
4147c478bd9Sstevel@tonic-gate 							internal_name,
4157c478bd9Sstevel@tonic-gate 							external_name,
4167c478bd9Sstevel@tonic-gate 							name_type);
4177c478bd9Sstevel@tonic-gate 		else
4187c478bd9Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 		return (status);
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate OM_uint32
4277c478bd9Sstevel@tonic-gate __gss_release_internal_name(minor_status, mech_type, internal_name)
4287c478bd9Sstevel@tonic-gate OM_uint32		*minor_status;
4297c478bd9Sstevel@tonic-gate const gss_OID		mech_type;
4307c478bd9Sstevel@tonic-gate gss_name_t		*internal_name;
4317c478bd9Sstevel@tonic-gate {
4327c478bd9Sstevel@tonic-gate 	OM_uint32			status;
4337c478bd9Sstevel@tonic-gate 	gss_mechanism		mech;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 	mech = __gss_get_mechanism(mech_type);
4367c478bd9Sstevel@tonic-gate 	if (mech) {
4377c478bd9Sstevel@tonic-gate 		if (mech->gss_release_name)
4387c478bd9Sstevel@tonic-gate 			status = mech->gss_release_name(
4397c478bd9Sstevel@tonic-gate 							mech->context,
4407c478bd9Sstevel@tonic-gate 							minor_status,
4417c478bd9Sstevel@tonic-gate 							internal_name);
4427c478bd9Sstevel@tonic-gate 		else
4437c478bd9Sstevel@tonic-gate 			status = GSS_S_UNAVAILABLE;
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 		return (status);
4467c478bd9Sstevel@tonic-gate 	}
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	return (GSS_S_BAD_MECH);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate /*
4537c478bd9Sstevel@tonic-gate  * This function converts an internal gssapi name to a union gssapi
4547c478bd9Sstevel@tonic-gate  * name.  Note that internal_name should be considered "consumed" by
4557c478bd9Sstevel@tonic-gate  * this call, whether or not we return an error.
4567c478bd9Sstevel@tonic-gate  */
4577c478bd9Sstevel@tonic-gate OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
4587c478bd9Sstevel@tonic-gate 						internal_name, external_name)
4597c478bd9Sstevel@tonic-gate 	OM_uint32 *minor_status;
4607c478bd9Sstevel@tonic-gate 	gss_mechanism		mech;
4617c478bd9Sstevel@tonic-gate 	gss_name_t		internal_name;
4627c478bd9Sstevel@tonic-gate 	gss_name_t		*external_name;
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate 	OM_uint32 major_status, tmp;
4657c478bd9Sstevel@tonic-gate 	gss_union_name_t union_name;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
4687c478bd9Sstevel@tonic-gate 	if (!union_name) {
4697c478bd9Sstevel@tonic-gate 			goto allocation_failure;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 	union_name->mech_type = 0;
4727c478bd9Sstevel@tonic-gate 	union_name->mech_name = internal_name;
4737c478bd9Sstevel@tonic-gate 	union_name->name_type = 0;
4747c478bd9Sstevel@tonic-gate 	union_name->external_name = 0;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
4777c478bd9Sstevel@tonic-gate 						&union_name->mech_type);
4787c478bd9Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
4797c478bd9Sstevel@tonic-gate 		goto allocation_failure;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	union_name->external_name =
4827c478bd9Sstevel@tonic-gate 		(gss_buffer_t)malloc(sizeof (gss_buffer_desc));
4837c478bd9Sstevel@tonic-gate 	if (!union_name->external_name) {
4847c478bd9Sstevel@tonic-gate 			goto allocation_failure;
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	major_status = mech->gss_display_name(mech->context, minor_status,
4887c478bd9Sstevel@tonic-gate 						internal_name,
4897c478bd9Sstevel@tonic-gate 						union_name->external_name,
4907c478bd9Sstevel@tonic-gate 						&union_name->name_type);
4917c478bd9Sstevel@tonic-gate 	if (major_status != GSS_S_COMPLETE)
4927c478bd9Sstevel@tonic-gate 		goto allocation_failure;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	*external_name =  (gss_name_t)union_name;
4957c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate allocation_failure:
4987c478bd9Sstevel@tonic-gate 	if (union_name) {
4997c478bd9Sstevel@tonic-gate 		if (union_name->external_name) {
5007c478bd9Sstevel@tonic-gate 			if (union_name->external_name->value)
5017c478bd9Sstevel@tonic-gate 				free(union_name->external_name->value);
5027c478bd9Sstevel@tonic-gate 			free(union_name->external_name);
5037c478bd9Sstevel@tonic-gate 		}
5047c478bd9Sstevel@tonic-gate 		if (union_name->name_type)
5057c478bd9Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->name_type);
5067c478bd9Sstevel@tonic-gate 		if (union_name->mech_type)
5077c478bd9Sstevel@tonic-gate 			(void) gss_release_oid(&tmp, &union_name->mech_type);
5087c478bd9Sstevel@tonic-gate 		free(union_name);
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 	/*
5117c478bd9Sstevel@tonic-gate 	 * do as the top comment says - since we are now owners of
5127c478bd9Sstevel@tonic-gate 	 * internal_name, we must clean it up
5137c478bd9Sstevel@tonic-gate 	 */
5147c478bd9Sstevel@tonic-gate 	if (internal_name)
5157c478bd9Sstevel@tonic-gate 		(void) __gss_release_internal_name(&tmp, &mech->mech_type,
5167c478bd9Sstevel@tonic-gate 						&internal_name);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	return (major_status);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate /*
5227c478bd9Sstevel@tonic-gate  * Glue routine for returning the mechanism-specific credential from a
5237c478bd9Sstevel@tonic-gate  * external union credential.
5247c478bd9Sstevel@tonic-gate  */
5257c478bd9Sstevel@tonic-gate gss_cred_id_t
5267c478bd9Sstevel@tonic-gate __gss_get_mechanism_cred(union_cred, mech_type)
5277c478bd9Sstevel@tonic-gate 	const gss_union_cred_t	union_cred;
5287c478bd9Sstevel@tonic-gate 	const gss_OID		mech_type;
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	int			i;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
5337c478bd9Sstevel@tonic-gate 		return (GSS_C_NO_CREDENTIAL);
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	for (i = 0; i < union_cred->count; i++) {
5367c478bd9Sstevel@tonic-gate 		if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
5377c478bd9Sstevel@tonic-gate 			return (union_cred->cred_array[i]);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 	return (GSS_C_NO_CREDENTIAL);
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate /*
5447c478bd9Sstevel@tonic-gate  * Routine to create and copy the gss_buffer_desc structure.
5457c478bd9Sstevel@tonic-gate  * Both space for the structure and the data is allocated.
5467c478bd9Sstevel@tonic-gate  */
5477c478bd9Sstevel@tonic-gate OM_uint32
548*ab9b2e15Sgtb gssint_create_copy_buffer(srcBuf, destBuf, addNullChar)
5497c478bd9Sstevel@tonic-gate 	const gss_buffer_t	srcBuf;
5507c478bd9Sstevel@tonic-gate 	gss_buffer_t 		*destBuf;
5517c478bd9Sstevel@tonic-gate 	int			addNullChar;
5527c478bd9Sstevel@tonic-gate {
5537c478bd9Sstevel@tonic-gate 	gss_buffer_t aBuf;
5547c478bd9Sstevel@tonic-gate 	int len;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	if (destBuf == NULL)
5577c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	*destBuf = 0;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
5627c478bd9Sstevel@tonic-gate 	if (!aBuf)
5637c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	if (addNullChar)
5667c478bd9Sstevel@tonic-gate 		len = srcBuf->length + 1;
5677c478bd9Sstevel@tonic-gate 	else
5687c478bd9Sstevel@tonic-gate 		len = srcBuf->length;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	if (!(aBuf->value = (void*)malloc(len))) {
5717c478bd9Sstevel@tonic-gate 		free(aBuf);
5727c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	(void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
5777c478bd9Sstevel@tonic-gate 	aBuf->length = srcBuf->length;
5787c478bd9Sstevel@tonic-gate 	*destBuf = aBuf;
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 	/* optionally add a NULL character */
5817c478bd9Sstevel@tonic-gate 	if (addNullChar)
5827c478bd9Sstevel@tonic-gate 		((char *)aBuf->value)[aBuf->length] = '\0';
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
5857c478bd9Sstevel@tonic-gate } /* ****** __gss_create_copy_buffer  ****** */
586