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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  *	name.c
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include "dh_gssapi.h"
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <string.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/param.h>
367c478bd9Sstevel@tonic-gate #include <sys/note.h>
377c478bd9Sstevel@tonic-gate #include <thread.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate extern int
407c478bd9Sstevel@tonic-gate get_der_length(unsigned char **, unsigned int, unsigned int *);
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate extern unsigned int
437c478bd9Sstevel@tonic-gate der_length_size(unsigned int);
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate extern int
467c478bd9Sstevel@tonic-gate put_der_length(unsigned int, unsigned char **, unsigned int);
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /* Diffie-Hellman ONC RPC netname name type */
497c478bd9Sstevel@tonic-gate static gss_OID_desc __DH_GSS_C_NT_NETNAME_desc =
507c478bd9Sstevel@tonic-gate 	{ 9,  "\053\006\004\001\052\002\032\001\001" };
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate const gss_OID_desc * const __DH_GSS_C_NT_NETNAME = &__DH_GSS_C_NT_NETNAME_desc;
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #define	OID_MAX_NAME_ENTRIES  32
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  * __dh_gss_compare_name: Diffie-Hellman machanism support for
587c478bd9Sstevel@tonic-gate  * gss_compare_name. Given two gss_name_ts that are presumed to
597c478bd9Sstevel@tonic-gate  * be rpc netnames set the *equal parameter to true if they are
607c478bd9Sstevel@tonic-gate  * the same, else set it to false.
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_compare_name(void * ctx,OM_uint32 * minor,gss_name_t name1,gss_name_t name2,int * equal)647c478bd9Sstevel@tonic-gate __dh_gss_compare_name(void *ctx,	/* Per mechanism context (not used) */
657c478bd9Sstevel@tonic-gate 		    OM_uint32 *minor,	/* Mechanism status */
667c478bd9Sstevel@tonic-gate 		    gss_name_t name1,	/* First name to compare */
677c478bd9Sstevel@tonic-gate 		    gss_name_t name2,	/* Second name to compare */
687c478bd9Sstevel@tonic-gate 		    int *equal		/* The result */)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	if (minor == 0 || equal == 0)
737c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	if (name1 == 0 || name2 == 0) {
787c478bd9Sstevel@tonic-gate 		*minor = DH_BADARG_FAILURE;
797c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	*equal = (strcmp((char *)name1, (char *)name2) == 0);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * __dh_gss_display_name: Supports gss_display_name for Diffie-Hellman
897c478bd9Sstevel@tonic-gate  * mechanism. This takes a gss internal name and converts it to
907c478bd9Sstevel@tonic-gate  * a counted string suitable for display.
917c478bd9Sstevel@tonic-gate  */
927c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_display_name(void * ctx,OM_uint32 * minor,gss_name_t name,gss_buffer_t output,gss_OID * name_type)937c478bd9Sstevel@tonic-gate __dh_gss_display_name(void * ctx, /* Per mechanism context (not used) */
947c478bd9Sstevel@tonic-gate 		    OM_uint32* minor, /* Mechanism status */
957c478bd9Sstevel@tonic-gate 		    gss_name_t name, /* Diffie-Hellman internal name */
967c478bd9Sstevel@tonic-gate 		    gss_buffer_t output, /* Were the printable name goes */
977c478bd9Sstevel@tonic-gate 		    gss_OID *name_type /* Name type of the internal name */)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (minor == 0 || output == 0)
1027c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (name == 0)
1057c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	output->length = 0;
1107c478bd9Sstevel@tonic-gate 	output->value = (void *)strdup((char *)name);
1117c478bd9Sstevel@tonic-gate 	if (output->value == NULL) {
1127c478bd9Sstevel@tonic-gate 		*minor = DH_NOMEM_FAILURE;
1137c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 	output->length = strlen((char *)name) + 1;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * Note: we no longer copy the name type OID. The current draft of
1197c478bd9Sstevel@tonic-gate  * the standard specifies:
1207c478bd9Sstevel@tonic-gate  *
1217c478bd9Sstevel@tonic-gate  * "The returned gss_OID will be a pointer into static stoarge
1227c478bd9Sstevel@tonic-gate  *  and should be treated as read-only by the caller (in particular,
1237c478bd9Sstevel@tonic-gate  *  it does not need to be freed)."
1247c478bd9Sstevel@tonic-gate  *
1257c478bd9Sstevel@tonic-gate  *	if (name_type) {
1267c478bd9Sstevel@tonic-gate  *		if ((*minor = __OID_copy(name_type, __DH_GSS_C_NT_NETNAME))
1277c478bd9Sstevel@tonic-gate  *			!= DH_SUCCESS) {
1287c478bd9Sstevel@tonic-gate  *			free(output->value);
1297c478bd9Sstevel@tonic-gate  *			output->value = NULL;
1307c478bd9Sstevel@tonic-gate  *			return (GSS_S_FAILURE);
1317c478bd9Sstevel@tonic-gate  *		}
1327c478bd9Sstevel@tonic-gate  *	}
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	if (name_type)
1367c478bd9Sstevel@tonic-gate 		*name_type = (gss_OID) __DH_GSS_C_NT_NETNAME;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * Routine that takes a netname as a character string and assigns it
1437c478bd9Sstevel@tonic-gate  * to a an gss_name_t pointed to by output.
1447c478bd9Sstevel@tonic-gate  */
1457c478bd9Sstevel@tonic-gate static OM_uint32
do_netname_nametype(OM_uint32 * minor,char * input,gss_name_t * output)1467c478bd9Sstevel@tonic-gate do_netname_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	if (__dh_validate_principal(input) != DH_SUCCESS)
1497c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAME);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
1527c478bd9Sstevel@tonic-gate 	*output = (gss_name_t)strdup((char *)input);
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	if (*output == NULL) {
1557c478bd9Sstevel@tonic-gate 		*minor = DH_NOMEM_FAILURE;
1567c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate  * do_uid_nametype converts a uid to a gss_name_t pointed to by output
1647c478bd9Sstevel@tonic-gate  */
1657c478bd9Sstevel@tonic-gate static OM_uint32
do_uid_nametype(OM_uint32 * minor,uid_t uid,gss_name_t * output)1667c478bd9Sstevel@tonic-gate do_uid_nametype(OM_uint32 *minor, uid_t uid, gss_name_t *output)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (!user2netname(netname, uid, NULL)) {
1717c478bd9Sstevel@tonic-gate 		*minor = DH_NETNAME_FAILURE;
1727c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 	return (do_netname_nametype(minor, netname, output));
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate  * do_username_nametype converts a username to a gss_name_t pointed to by
1797c478bd9Sstevel@tonic-gate  * output.
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  * A username will be represented by the following:
1827c478bd9Sstevel@tonic-gate  * 	name[/node][@security-domain]
1837c478bd9Sstevel@tonic-gate  *
1847c478bd9Sstevel@tonic-gate  * Then optional security-domain will represent secure rpc domain if
1857c478bd9Sstevel@tonic-gate  * present. If not present the local domain will be used. name is the
1867c478bd9Sstevel@tonic-gate  * user name as found in the unix password file. If name is root and
1877c478bd9Sstevel@tonic-gate  * node is present, then node will represent the host. If the host is
1887c478bd9Sstevel@tonic-gate  * a qualified name we assume that it is a DNS name and will only return
1897c478bd9Sstevel@tonic-gate  * the first commponnet since we want host name that are relative to
1907c478bd9Sstevel@tonic-gate  * the security domain (secure rpc domain).
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate static OM_uint32
do_username_nametype(OM_uint32 * minor,char * uname,gss_name_t * output)1947c478bd9Sstevel@tonic-gate do_username_nametype(OM_uint32 *minor, char *uname, gss_name_t *output)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
1977c478bd9Sstevel@tonic-gate 	char *user, *node, *domain;
1987c478bd9Sstevel@tonic-gate 	struct passwd pwd;
1997c478bd9Sstevel@tonic-gate 	char buff[1024];
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	/* Set outputs to sane values */
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	*output = 0;
2047c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* See if we have a name */
2077c478bd9Sstevel@tonic-gate 	if (uname == 0) {
2087c478bd9Sstevel@tonic-gate 		*minor = DH_NO_SUCH_USER;
2097c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/* copy the name so that we can do surgery on it */
2137c478bd9Sstevel@tonic-gate 	user = strdup(uname);
2147c478bd9Sstevel@tonic-gate 	if (user == 0) {
2157c478bd9Sstevel@tonic-gate 		*minor = DH_NOMEM_FAILURE;
2167c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	/* Look for optional node part */
2217c478bd9Sstevel@tonic-gate 	node = strchr(user, '/');
2227c478bd9Sstevel@tonic-gate 	if (node) {
2237c478bd9Sstevel@tonic-gate 		/*
2247c478bd9Sstevel@tonic-gate 		 * user is now just the user portion and node
2257c478bd9Sstevel@tonic-gate 		 * points to the start of the node part.
2267c478bd9Sstevel@tonic-gate 		 */
2277c478bd9Sstevel@tonic-gate 		*node++ = '\0';
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		/* Now see if there is a domain */
2307c478bd9Sstevel@tonic-gate 		domain = strchr(node, '@');
2317c478bd9Sstevel@tonic-gate 	}
2327c478bd9Sstevel@tonic-gate 	else
2337c478bd9Sstevel@tonic-gate 		/* Check for a domain */
2347c478bd9Sstevel@tonic-gate 		domain = strchr(user, '@');
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	/* Set domain to the beginning of the domain part if pressent */
2377c478bd9Sstevel@tonic-gate 	if (domain)
2387c478bd9Sstevel@tonic-gate 		*domain++ = '\0';
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	/*
2417c478bd9Sstevel@tonic-gate 	 * See if the node part is important. If the user is root get
2427c478bd9Sstevel@tonic-gate 	 * the host from the node. If node is not present we assume
2437c478bd9Sstevel@tonic-gate 	 * we're the local host.
2447c478bd9Sstevel@tonic-gate 	 */
2457c478bd9Sstevel@tonic-gate 	if (strcmp(user, "root") == 0) {
2467c478bd9Sstevel@tonic-gate 		char *dot;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 		/*
2497c478bd9Sstevel@tonic-gate 		 * We only want the host part of a qualfied host name. We
2507c478bd9Sstevel@tonic-gate 		 * assume the domain part of a hostname is a DNS domain,
2517c478bd9Sstevel@tonic-gate 		 * not an rpc domain. The rpc domain can be specified
2527c478bd9Sstevel@tonic-gate 		 * in the optional security domain part.
2537c478bd9Sstevel@tonic-gate 		 */
2547c478bd9Sstevel@tonic-gate 		if (node) {
2557c478bd9Sstevel@tonic-gate 			dot = strchr(node, '.');
2567c478bd9Sstevel@tonic-gate 			if (dot)
2577c478bd9Sstevel@tonic-gate 				*dot = '\0';
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 		/*
2607c478bd9Sstevel@tonic-gate 		 * If node is null, assume local host. If domain is
261*bbf21555SRichard Lowe 		 * null assume local domain. See host2netname(3NSL)
2627c478bd9Sstevel@tonic-gate 		 */
2637c478bd9Sstevel@tonic-gate 		if (!host2netname(netname, node,  domain)) {
2647c478bd9Sstevel@tonic-gate 			*minor = DH_NETNAME_FAILURE;
2657c478bd9Sstevel@tonic-gate 			free(user);
2667c478bd9Sstevel@tonic-gate 			return (GSS_S_FAILURE);
2677c478bd9Sstevel@tonic-gate 		}
2687c478bd9Sstevel@tonic-gate 		free(user);
2697c478bd9Sstevel@tonic-gate 		return (do_netname_nametype(minor, netname, output));
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	/*
2737c478bd9Sstevel@tonic-gate 	 * We use getpwnam_r to convert the name to uid.  Note it is
2747c478bd9Sstevel@tonic-gate 	 * important to use getpwnam_r to preserve MT safty.
2757c478bd9Sstevel@tonic-gate 	 */
2767c478bd9Sstevel@tonic-gate 	if (getpwnam_r(user, &pwd, buff, sizeof (buff)) == NULL) {
2777c478bd9Sstevel@tonic-gate 		*minor = DH_NO_SUCH_USER;
2787c478bd9Sstevel@tonic-gate 		free(user);
2797c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
282*bbf21555SRichard Lowe 	/* If domain is null assume local domain. See user2netname(3NSL) */
2837c478bd9Sstevel@tonic-gate 	if (!user2netname(netname, pwd.pw_uid, domain)) {
2847c478bd9Sstevel@tonic-gate 		*minor = DH_NETNAME_FAILURE;
2857c478bd9Sstevel@tonic-gate 		free(user);
2867c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 	free(user);
2897c478bd9Sstevel@tonic-gate 	return (do_netname_nametype(minor, netname, output));
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate  * do_hostbase_nametype convert a hostbase service name of the form
2947c478bd9Sstevel@tonic-gate  *	service@hostname.
2957c478bd9Sstevel@tonic-gate  *
2967c478bd9Sstevel@tonic-gate  * For Diffie-Hellman we assume that the service is running with the
2977c478bd9Sstevel@tonic-gate  * credtials of the machine, i.e., as root.
2987c478bd9Sstevel@tonic-gate  */
2997c478bd9Sstevel@tonic-gate static OM_uint32
do_hostbase_nametype(OM_uint32 * minor,char * input,gss_name_t * output)3007c478bd9Sstevel@tonic-gate do_hostbase_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
3017c478bd9Sstevel@tonic-gate {
3027c478bd9Sstevel@tonic-gate 	/* Get the nostname */
3037c478bd9Sstevel@tonic-gate 	char *host = strchr(input, '@');
3047c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	/* If no host return bad name */
3087c478bd9Sstevel@tonic-gate 	if (host == NULL)
3097c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAME);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/* Advance pass the "@" sign */
3127c478bd9Sstevel@tonic-gate 	host += 1;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/* Convert the hostname to its netname */
3157c478bd9Sstevel@tonic-gate 	if (!host2netname(netname, host, NULL)) {
3167c478bd9Sstevel@tonic-gate 		*minor = DH_NETNAME_FAILURE;
3177c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* Internalize the netname to output */
3217c478bd9Sstevel@tonic-gate 	return (do_netname_nametype(minor, netname, output));
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate  * do_exported_netname: Convert an exported Diffie-Hellman name
3267c478bd9Sstevel@tonic-gate  * to a Diffie-Hellman internal name.
3277c478bd9Sstevel@tonic-gate  */
3287c478bd9Sstevel@tonic-gate static OM_uint32
do_exported_netname(dh_context_t ctx,OM_uint32 * minor,gss_buffer_t input,gss_name_t * output)3297c478bd9Sstevel@tonic-gate do_exported_netname(dh_context_t ctx, /* Diffie-Hellman mech context */
3307c478bd9Sstevel@tonic-gate 		    OM_uint32 *minor, /* Mech status */
3317c478bd9Sstevel@tonic-gate 		    gss_buffer_t input, /* The export name to convert */
3327c478bd9Sstevel@tonic-gate 		    gss_name_t *output /* The converted internal name */)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate 	/* All export names must start with this */
3357c478bd9Sstevel@tonic-gate 	const char tokid[] = "\x04\x01";
3367c478bd9Sstevel@tonic-gate 	const int tokid_len = 2;
3377c478bd9Sstevel@tonic-gate 	const int OIDlen_len = 2;
3387c478bd9Sstevel@tonic-gate 	const int namelen_len = 4;
3397c478bd9Sstevel@tonic-gate 	unsigned char *p = (unsigned char *)input->value;
3407c478bd9Sstevel@tonic-gate 	OM_uint32 len = input->length;
3417c478bd9Sstevel@tonic-gate 	int	 mechoidlen;
3427c478bd9Sstevel@tonic-gate 	OM_uint32 oidlen; /* includes object tag len & DER len bytes */
3437c478bd9Sstevel@tonic-gate 	OM_uint32 namelen;
3447c478bd9Sstevel@tonic-gate 	OM_uint32 currlen;
3457c478bd9Sstevel@tonic-gate 	OM_uint32 bytes;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	*minor = DH_BADARG_FAILURE;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	/* The len must be at least this big */
3507c478bd9Sstevel@tonic-gate 	if (len < tokid_len + OIDlen_len + namelen_len)
3517c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/* Export names must start with the token id of 0x04 0x01 */
3547c478bd9Sstevel@tonic-gate 	if (memcmp(p, tokid, tokid_len) != 0)
3557c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3567c478bd9Sstevel@tonic-gate 	p += tokid_len;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	/* Decode the Mechanism oid */
3597c478bd9Sstevel@tonic-gate 	oidlen = (*p++ << 8) & 0xff00;
3607c478bd9Sstevel@tonic-gate 	oidlen |= *p++ & 0xff;
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	/* Check that we actually have the mechanism oid elements */
3637c478bd9Sstevel@tonic-gate 	if (len < tokid_len + OIDlen_len + oidlen + namelen_len)
3647c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/* Compare that the input is for this mechanism */
3677c478bd9Sstevel@tonic-gate 	if (*p++ != 0x06)
3687c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3697c478bd9Sstevel@tonic-gate 	currlen = len - (tokid_len + OIDlen_len + oidlen + namelen_len);
3707c478bd9Sstevel@tonic-gate 	if ((mechoidlen = get_der_length(&p, currlen, &bytes)) < 0)
3717c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3727c478bd9Sstevel@tonic-gate 	if (mechoidlen != ctx->mech->length)
3737c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3747c478bd9Sstevel@tonic-gate 	if (memcmp(p, ctx->mech->elements, mechoidlen) != 0)
3757c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3767c478bd9Sstevel@tonic-gate 	p += mechoidlen;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/* Grab the length of the mechanism specific name per RFC 2078 */
3797c478bd9Sstevel@tonic-gate 	namelen = (*p++ << 24) & 0xff000000;
3807c478bd9Sstevel@tonic-gate 	namelen |= (*p++ << 16) & 0xff0000;
3817c478bd9Sstevel@tonic-gate 	namelen |= (*p++ << 8) & 0xff00;
3827c478bd9Sstevel@tonic-gate 	namelen |= *p++ & 0xff;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	/* This should alway be false */
3857c478bd9Sstevel@tonic-gate 	if (len < tokid_len + OIDlen_len + oidlen + namelen_len + namelen)
3867c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	/* Make sure the bytes for the netname oid length are available */
3897c478bd9Sstevel@tonic-gate 	if (namelen < OIDlen_len)
3907c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	/* Get the netname oid length */
3937c478bd9Sstevel@tonic-gate 	oidlen = (*p++ << 8) & 0xff00;
3947c478bd9Sstevel@tonic-gate 	oidlen = *p++ & 0xff;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/* See if we have the elements of the netname oid */
3977c478bd9Sstevel@tonic-gate 	if (namelen < OIDlen_len + oidlen)
3987c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/* Check that the oid is really a netname */
4017c478bd9Sstevel@tonic-gate 	if (oidlen != __DH_GSS_C_NT_NETNAME->length)
4027c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
4037c478bd9Sstevel@tonic-gate 	if (memcmp(p, __DH_GSS_C_NT_NETNAME->elements,
4047c478bd9Sstevel@tonic-gate 	    __DH_GSS_C_NT_NETNAME->length) != 0)
4057c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	/* p now points to the netname wich is null terminated */
4087c478bd9Sstevel@tonic-gate 	p += oidlen;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/*
4117c478bd9Sstevel@tonic-gate 	 * How the netname is encoded in an export name type for
4127c478bd9Sstevel@tonic-gate 	 * this mechanism. See _dh_gss_export_name below.
4137c478bd9Sstevel@tonic-gate 	 */
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	if (namelen != OIDlen_len + oidlen + strlen((char *)p) + 1)
4167c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	/* Grab the netname */
4197c478bd9Sstevel@tonic-gate 	*output = (gss_name_t)strdup((char *)p);
4207c478bd9Sstevel@tonic-gate 	if (*output) {
4217c478bd9Sstevel@tonic-gate 		*minor = 0;
4227c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	*minor = DH_NOMEM_FAILURE;
4267c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate /*
4307c478bd9Sstevel@tonic-gate  * __dh_gss_import_name: Diffie-Hellman entry point for gss_import_name.
4317c478bd9Sstevel@tonic-gate  * Given an input name of a specified name type, convert this to a
4327c478bd9Sstevel@tonic-gate  * Diffie-Hellman internal name (netname).
4337c478bd9Sstevel@tonic-gate  *
4347c478bd9Sstevel@tonic-gate  * The idea here is simply compare the name_type supplied with each
4357c478bd9Sstevel@tonic-gate  * name type that we know how to deal with. If we have a match we call
4367c478bd9Sstevel@tonic-gate  * the appropriate support routine form above. If we done't have a match
4377c478bd9Sstevel@tonic-gate  * we return GSS_S_BAD_NAMETYPE
4387c478bd9Sstevel@tonic-gate  */
4397c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_import_name(void * ctx,OM_uint32 * minor,gss_buffer_t input,gss_OID name_type,gss_name_t * output)4407c478bd9Sstevel@tonic-gate __dh_gss_import_name(void *ctx, /* Per mechanism context */
4417c478bd9Sstevel@tonic-gate 		    OM_uint32 *minor, /* Mechanism status */
4427c478bd9Sstevel@tonic-gate 		    gss_buffer_t input, /* The name to convert */
4437c478bd9Sstevel@tonic-gate 		    gss_OID name_type, /* of this name_type */
4447c478bd9Sstevel@tonic-gate 		    gss_name_t *output /* The converted name */)
4457c478bd9Sstevel@tonic-gate {
4467c478bd9Sstevel@tonic-gate 	char *name;
4477c478bd9Sstevel@tonic-gate 	OM_uint32 stat;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	if (minor == NULL || output == NULL)
4507c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (input == NULL || input->value == NULL)
4537c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
4547c478bd9Sstevel@tonic-gate 	if (name_type == GSS_C_NO_OID)
4557c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAMETYPE);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	/* Set sane state */
4587c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
4597c478bd9Sstevel@tonic-gate 	*output = GSS_C_NO_NAME;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 		/* UID in machine format */
4627c478bd9Sstevel@tonic-gate 	if (__OID_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)) {
4637c478bd9Sstevel@tonic-gate 		uid_t uid;
4647c478bd9Sstevel@tonic-gate 		if (input->length != sizeof (uid_t))
4657c478bd9Sstevel@tonic-gate 			return (GSS_S_BAD_NAME);
4667c478bd9Sstevel@tonic-gate 		uid = *(uid_t *)input->value;
4677c478bd9Sstevel@tonic-gate 		/* Should we assume that the id is network byte order ??? */
4687c478bd9Sstevel@tonic-gate 		/* uid = htonl(uid); No, this should be the local orfering */
4697c478bd9Sstevel@tonic-gate 		return (do_uid_nametype(minor, uid, output));
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		/* Name that was exported with __dh_gss_export_name */
4727c478bd9Sstevel@tonic-gate 	} else if (__OID_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
4737c478bd9Sstevel@tonic-gate 		stat = do_exported_netname((dh_context_t)ctx, minor,
4747c478bd9Sstevel@tonic-gate 		    input, output);
4757c478bd9Sstevel@tonic-gate 		return (stat);
4767c478bd9Sstevel@tonic-gate 	}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/* Null ternamte name so we can manipulate as a c-style string */
4797c478bd9Sstevel@tonic-gate 	name = malloc(input->length+1);
4807c478bd9Sstevel@tonic-gate 	if (name == NULL) {
4817c478bd9Sstevel@tonic-gate 		*minor = DH_NOMEM_FAILURE;
4827c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
4837c478bd9Sstevel@tonic-gate 	}
4847c478bd9Sstevel@tonic-gate 	memcpy(name, input->value, input->length);
4857c478bd9Sstevel@tonic-gate 	name[input->length] = '\0';
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 		/* Diffie-Hellman (ONC RPC netname) */
4897c478bd9Sstevel@tonic-gate 	if (__OID_equal(name_type, __DH_GSS_C_NT_NETNAME)) {
4907c478bd9Sstevel@tonic-gate 		stat = do_netname_nametype(minor, name, output);
4917c478bd9Sstevel@tonic-gate 		free(name);
4927c478bd9Sstevel@tonic-gate 		return (stat);
4937c478bd9Sstevel@tonic-gate 		/* Host based service name (service@hostname) */
4947c478bd9Sstevel@tonic-gate 	} else if (__OID_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)) {
4957c478bd9Sstevel@tonic-gate 		stat = do_hostbase_nametype(minor, name, output);
4967c478bd9Sstevel@tonic-gate 		free(name);
4977c478bd9Sstevel@tonic-gate 		return (stat);
4987c478bd9Sstevel@tonic-gate 		/* Thus local OS user name */
4997c478bd9Sstevel@tonic-gate 	} else if (__OID_equal(name_type, GSS_C_NT_USER_NAME)) {
5007c478bd9Sstevel@tonic-gate 		stat = do_username_nametype(minor, name, output);
5017c478bd9Sstevel@tonic-gate 		free(name);
5027c478bd9Sstevel@tonic-gate 		return (stat);
5037c478bd9Sstevel@tonic-gate 		/* The os user id writen as a string */
5047c478bd9Sstevel@tonic-gate 	} else if (__OID_equal(name_type, GSS_C_NT_STRING_UID_NAME)) {
5057c478bd9Sstevel@tonic-gate 		char *p;
5067c478bd9Sstevel@tonic-gate 		/* Convert the name to a uid */
5077c478bd9Sstevel@tonic-gate 		uid_t uid = (uid_t)strtol(name, &p, 0);
5087c478bd9Sstevel@tonic-gate 		free(name);
5097c478bd9Sstevel@tonic-gate 		if (*p != '\0')
5107c478bd9Sstevel@tonic-gate 			return (GSS_S_BAD_NAME);
5117c478bd9Sstevel@tonic-gate 		return (do_uid_nametype(minor, uid, output));
5127c478bd9Sstevel@tonic-gate 	} else {
5137c478bd9Sstevel@tonic-gate 		/* Any thing else */
5147c478bd9Sstevel@tonic-gate 		free(name);
5157c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAMETYPE);
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate /*
5207c478bd9Sstevel@tonic-gate  * __dh_gss_release_name: DH entry point for gss_release_name.
5217c478bd9Sstevel@tonic-gate  * Release an internal DH name.
5227c478bd9Sstevel@tonic-gate  */
5237c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_release_name(void * ctx,OM_uint32 * minor,gss_name_t * name)5247c478bd9Sstevel@tonic-gate __dh_gss_release_name(void *ctx, OM_uint32 *minor, gss_name_t *name)
5257c478bd9Sstevel@tonic-gate {
5267c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	if (minor == 0 || name == 0)
5297c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	free(*name);
5347c478bd9Sstevel@tonic-gate 	*name = GSS_C_NO_NAME;
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /* Lock for initializing oid_name_tab */
5407c478bd9Sstevel@tonic-gate static mutex_t name_tab_lock = DEFAULTMUTEX;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate /* Table of name types that this mechanism understands */
5437c478bd9Sstevel@tonic-gate static const gss_OID_desc * oid_name_tab[OID_MAX_NAME_ENTRIES];
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * __dh_gss_inquire_names_for_mech: DH entry point for
5477c478bd9Sstevel@tonic-gate  * gss_inquire_names_for_mech.
5487c478bd9Sstevel@tonic-gate  *
5497c478bd9Sstevel@tonic-gate  * Return a set of OID name types that a mechanism can understand
5507c478bd9Sstevel@tonic-gate  */
5517c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_inquire_names_for_mech(void * ctx,OM_uint32 * minor,gss_OID mech,gss_OID_set * names)5527c478bd9Sstevel@tonic-gate __dh_gss_inquire_names_for_mech(void *ctx, OM_uint32 *minor,
5537c478bd9Sstevel@tonic-gate     gss_OID mech, gss_OID_set *names)
5547c478bd9Sstevel@tonic-gate {
5557c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx,mech))
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	/* See if we need to initialize the table */
5587c478bd9Sstevel@tonic-gate 	if (oid_name_tab[0] == 0) {
5597c478bd9Sstevel@tonic-gate 		mutex_lock(&name_tab_lock);
5607c478bd9Sstevel@tonic-gate 		/* If nobody sneaked in, initialize the table */
5617c478bd9Sstevel@tonic-gate 		if (oid_name_tab[0] == 0) {
5627c478bd9Sstevel@tonic-gate 			oid_name_tab[0] = __DH_GSS_C_NT_NETNAME;
5637c478bd9Sstevel@tonic-gate 			oid_name_tab[1] = GSS_C_NT_HOSTBASED_SERVICE;
5647c478bd9Sstevel@tonic-gate 			oid_name_tab[2] = GSS_C_NT_USER_NAME;
5657c478bd9Sstevel@tonic-gate 			oid_name_tab[3] = GSS_C_NT_MACHINE_UID_NAME;
5667c478bd9Sstevel@tonic-gate 			oid_name_tab[4] = GSS_C_NT_STRING_UID_NAME;
5677c478bd9Sstevel@tonic-gate 			oid_name_tab[5] = GSS_C_NT_EXPORT_NAME;
5687c478bd9Sstevel@tonic-gate 			/* oid_name_tab[6] = GSS_C_NT_ANONYMOUS_NAME; */
5697c478bd9Sstevel@tonic-gate 		}
5707c478bd9Sstevel@tonic-gate 		mutex_unlock(&name_tab_lock);
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	/* Return the set of OIDS from the table */
5747c478bd9Sstevel@tonic-gate 	if ((*minor = __OID_copy_set_from_array(names,
5757c478bd9Sstevel@tonic-gate 	    oid_name_tab, 6)) != DH_SUCCESS)
5767c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate  * Private libgss entry point to convert a principal name to uid.
5847c478bd9Sstevel@tonic-gate  */
5857c478bd9Sstevel@tonic-gate OM_uint32
__dh_pname_to_uid(void * ctx,OM_uint32 * minor,const gss_name_t pname,uid_t * uid)5867c478bd9Sstevel@tonic-gate __dh_pname_to_uid(void *ctx, /* DH mech context (not used) */
5877c478bd9Sstevel@tonic-gate 		OM_uint32 *minor, /* Mech status */
5887c478bd9Sstevel@tonic-gate 		const gss_name_t pname, /* principal */
5897c478bd9Sstevel@tonic-gate 		uid_t *uid  /* where to put the uid */)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	gid_t gid;
5947c478bd9Sstevel@tonic-gate 	gid_t glist[NGRPS];
5957c478bd9Sstevel@tonic-gate 	int glen;
5967c478bd9Sstevel@tonic-gate 	/* Convert the principal name to a netname */
5977c478bd9Sstevel@tonic-gate 	char *netname = (char *)pname;
5987c478bd9Sstevel@tonic-gate 	char host_netname[MAXNETNAMELEN+1];
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate 	if (pname == 0)
6017c478bd9Sstevel@tonic-gate 		return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
6027c478bd9Sstevel@tonic-gate 	if (minor == 0 || uid == 0)
6037c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
6067c478bd9Sstevel@tonic-gate 	*uid = UID_NOBODY;
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	/* First try to convert as a user */
6097c478bd9Sstevel@tonic-gate 	if (netname2user(netname, uid, &gid, &glen, glist))
6107c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
6117c478bd9Sstevel@tonic-gate 	/* Get this hosts netname */
6127c478bd9Sstevel@tonic-gate 	else if (host2netname(host_netname, NULL, NULL)) {
6137c478bd9Sstevel@tonic-gate 		/*
6147c478bd9Sstevel@tonic-gate 		 * If the netname is this host's netname then we're root
6157c478bd9Sstevel@tonic-gate 		 * else we're nobody.
6167c478bd9Sstevel@tonic-gate 		 */
6177c478bd9Sstevel@tonic-gate 		if (strncmp(netname, host_netname, MAXNETNAMELEN) == 0)
6187c478bd9Sstevel@tonic-gate 			*uid = 0;
6197c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	/* We could not get a netname */
6237c478bd9Sstevel@tonic-gate 	*minor = DH_NETNAME_FAILURE;
6247c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate /*
6287c478bd9Sstevel@tonic-gate  * __dh_gss_export_name: Diffie-Hellman support for gss_export_name.
6297c478bd9Sstevel@tonic-gate  * Given a Diffie-Hellman internal name return the GSS exported format.
6307c478bd9Sstevel@tonic-gate  */
6317c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_export_name(void * ctx,OM_uint32 * minor,const gss_name_t input_name,gss_buffer_t exported_name)6327c478bd9Sstevel@tonic-gate __dh_gss_export_name(void *ctx, /* Per mechanism context */
6337c478bd9Sstevel@tonic-gate 		    OM_uint32 *minor, /* Mechanism status */
6347c478bd9Sstevel@tonic-gate 		    const gss_name_t input_name, /* The name to export */
6357c478bd9Sstevel@tonic-gate 		    gss_buffer_t exported_name /* Exported name goes here */)
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	/* input_name is dh principal name */
6387c478bd9Sstevel@tonic-gate 	dh_principal pname = (dh_principal)input_name;
6397c478bd9Sstevel@tonic-gate 	dh_context_t dc = (dh_context_t)ctx;
6407c478bd9Sstevel@tonic-gate 	/* Magic for exported blobs */
6417c478bd9Sstevel@tonic-gate 	const char tokid[] = "\x04\x01";
6427c478bd9Sstevel@tonic-gate 	const int tokid_len = 2;
6437c478bd9Sstevel@tonic-gate 	const int OIDlen_len = 2; /* Why did they do this? */
6447c478bd9Sstevel@tonic-gate 	const int namelen_len = 4;
6457c478bd9Sstevel@tonic-gate 	const int mechoid_tag_len = 1;
6467c478bd9Sstevel@tonic-gate 	unsigned char *p;
6477c478bd9Sstevel@tonic-gate 	OM_uint32 len;
6487c478bd9Sstevel@tonic-gate 	OM_uint32 namelen;
6497c478bd9Sstevel@tonic-gate 	OM_uint32 currlen;
6507c478bd9Sstevel@tonic-gate 	OM_uint32 oid_der_len = 0;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	if (minor == 0 || exported_name == GSS_C_NO_BUFFER)
6537c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
6547c478bd9Sstevel@tonic-gate 	if (input_name == GSS_C_NO_NAME)
6557c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_READ);
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	/* Set sane outputs */
6587c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
6597c478bd9Sstevel@tonic-gate 	exported_name->length = 0;
6607c478bd9Sstevel@tonic-gate 	exported_name->value = NULL;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	/* Determine the length of the name */
6637c478bd9Sstevel@tonic-gate 	namelen = OIDlen_len + __DH_GSS_C_NT_NETNAME->length
6647c478bd9Sstevel@tonic-gate 	    + strlen(pname)+1;
6657c478bd9Sstevel@tonic-gate 	oid_der_len = der_length_size(dc->mech->length);
6667c478bd9Sstevel@tonic-gate 	/* Find the total length */
6677c478bd9Sstevel@tonic-gate 	len = tokid_len + OIDlen_len + mechoid_tag_len + oid_der_len
6687c478bd9Sstevel@tonic-gate 		+ dc->mech->length + namelen_len + namelen;
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	/* Allocate the blob */
6717c478bd9Sstevel@tonic-gate 	p = New(unsigned char, len);
6727c478bd9Sstevel@tonic-gate 	if (p == NULL) {
6737c478bd9Sstevel@tonic-gate 		*minor = DH_NOMEM_FAILURE;
6747c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
6757c478bd9Sstevel@tonic-gate 	}
6767c478bd9Sstevel@tonic-gate 	/* Set the blob to the exported name */
6777c478bd9Sstevel@tonic-gate 	exported_name->length = len;
6787c478bd9Sstevel@tonic-gate 	exported_name->value = p;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	/* Start with some magic */
6817c478bd9Sstevel@tonic-gate 	memcpy(p, tokid, tokid_len);
6827c478bd9Sstevel@tonic-gate 	p += tokid_len;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/*
6857c478bd9Sstevel@tonic-gate 	 * The spec only allows two bytes for the oid length.
6867c478bd9Sstevel@tonic-gate 	 * We are assuming here that the correct encodeing is MSB first as
6877c478bd9Sstevel@tonic-gate 	 * was done in libgss.
6887c478bd9Sstevel@tonic-gate 	 */
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	*p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
6917c478bd9Sstevel@tonic-gate 			& 0xff00) >> 8;
6927c478bd9Sstevel@tonic-gate 	*p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
6937c478bd9Sstevel@tonic-gate 			& 0x00ff);
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/* Now the mechanism OID DER Encoding */
6967c478bd9Sstevel@tonic-gate 	*p++ = 0x06; /* Universal Tag for OID */
6977c478bd9Sstevel@tonic-gate 	currlen = len - tokid_len - OIDlen_len - mechoid_tag_len;
6987c478bd9Sstevel@tonic-gate 	if (!put_der_length(dc->mech->length, &p, currlen) == 0) {
6997c478bd9Sstevel@tonic-gate 		return (GSS_S_FAILURE);
7007c478bd9Sstevel@tonic-gate 	}
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate 	/* Now the mechanism OID elements */
7037c478bd9Sstevel@tonic-gate 	memcpy(p, dc->mech->elements, dc->mech->length);
7047c478bd9Sstevel@tonic-gate 	p += dc->mech->length;
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 	/* The name length most MSB first */
7077c478bd9Sstevel@tonic-gate 	*p++ = (namelen & 0xff000000) >> 24;
7087c478bd9Sstevel@tonic-gate 	*p++ = (namelen & 0x00ff0000) >> 16;
7097c478bd9Sstevel@tonic-gate 	*p++ = (namelen & 0x0000ff00) >> 8;
7107c478bd9Sstevel@tonic-gate 	*p++ = (namelen & 0x000000ff);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	/*
7137c478bd9Sstevel@tonic-gate 	 * We'll now encode the netname oid. Again we'll just use 2 bytes.
7147c478bd9Sstevel@tonic-gate 	 * This is the same encoding that the libgss implementor uses, so
7157c478bd9Sstevel@tonic-gate 	 * we'll just follow along.
7167c478bd9Sstevel@tonic-gate 	 */
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	*p++ = (__DH_GSS_C_NT_NETNAME->length & 0xff00) >> 8;
7197c478bd9Sstevel@tonic-gate 	*p++ = (__DH_GSS_C_NT_NETNAME->length &0x00ff);
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 	/* The netname oid values */
7227c478bd9Sstevel@tonic-gate 	memcpy(p, __DH_GSS_C_NT_NETNAME->elements,
7237c478bd9Sstevel@tonic-gate 	    __DH_GSS_C_NT_NETNAME->length);
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	p += __DH_GSS_C_NT_NETNAME->length;
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	/* Now we copy the netname including the null byte to be safe */
7287c478bd9Sstevel@tonic-gate 	memcpy(p, pname, strlen(pname) + 1);
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate /*
7347c478bd9Sstevel@tonic-gate  * Support routine for __dh_internal_release_oid. Return True if
7357c478bd9Sstevel@tonic-gate  * the supplied OID points to the reference OID or if the elements
7367c478bd9Sstevel@tonic-gate  * of the reference OID are the same as the supplied OID. In the
7377c478bd9Sstevel@tonic-gate  * latter case, just free the OID container and set the pointer to it
7387c478bd9Sstevel@tonic-gate  * to GSS_C_NO_OID. Otherwise return false
7397c478bd9Sstevel@tonic-gate  */
7407c478bd9Sstevel@tonic-gate static int
release_oid(const gss_OID_desc * const ref,gss_OID * oid)7417c478bd9Sstevel@tonic-gate release_oid(const gss_OID_desc * const ref, gss_OID *oid)
7427c478bd9Sstevel@tonic-gate {
7437c478bd9Sstevel@tonic-gate 	gss_OID id = *oid;
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	if (id == ref)
7467c478bd9Sstevel@tonic-gate 		return (TRUE);
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 	/*
7497c478bd9Sstevel@tonic-gate 	 * If some on create a shallow copy free, the structure point to
7507c478bd9Sstevel@tonic-gate 	 * id and set the pointer to it to GSS_C_NO_OID
7517c478bd9Sstevel@tonic-gate 	 */
7527c478bd9Sstevel@tonic-gate 	if (id->elements == ref->elements) {
7537c478bd9Sstevel@tonic-gate 		Free(id);
7547c478bd9Sstevel@tonic-gate 		*oid = GSS_C_NO_OID;
7557c478bd9Sstevel@tonic-gate 		return (TRUE);
7567c478bd9Sstevel@tonic-gate 	}
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 	return (FALSE);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate /*
7627c478bd9Sstevel@tonic-gate  * __dh_gss_internal_release_oid: DH support for the gss_internal_relaese_oid
7637c478bd9Sstevel@tonic-gate  * entry. Check that the refence to an oid is one of our mechanisms static
7647c478bd9Sstevel@tonic-gate  * OIDS. If it is return true indicating to libgss that we have handled the
7657c478bd9Sstevel@tonic-gate  * release of that OID. Otherwise we return false and let libgss deal with it.
7667c478bd9Sstevel@tonic-gate  *
7677c478bd9Sstevel@tonic-gate  * The only OIDS we know are the calling mechanism found in the context
7687c478bd9Sstevel@tonic-gate  * and the shared DH_GSS_C_NT_NETNAME name type
7697c478bd9Sstevel@tonic-gate  */
7707c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_internal_release_oid(void * ctx,OM_uint32 * minor,gss_OID * oid)7717c478bd9Sstevel@tonic-gate __dh_gss_internal_release_oid(void *ctx, OM_uint32 *minor, gss_OID *oid)
7727c478bd9Sstevel@tonic-gate {
7737c478bd9Sstevel@tonic-gate 	dh_context_t dhcxt = (dh_context_t)ctx;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	if (minor == 0)
7767c478bd9Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	*minor = DH_SUCCESS;
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	if (oid == NULL || *oid == NULL)
7817c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	if (release_oid(dhcxt->mech, oid))
7847c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	if (release_oid(__DH_GSS_C_NT_NETNAME, oid))
7877c478bd9Sstevel@tonic-gate 		return (GSS_S_COMPLETE);
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
7907c478bd9Sstevel@tonic-gate }
791