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*004388ebScasper  * Common Development and Distribution License (the "License").
6*004388ebScasper  * 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  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
23*004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * This module contains the interfaces for the NIS+ security mechanisms.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include "mt.h"
327c478bd9Sstevel@tonic-gate #include <ctype.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <strings.h>
367c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
377c478bd9Sstevel@tonic-gate #include <netconfig.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <sys/stat.h>
407c478bd9Sstevel@tonic-gate #include <sys/file.h>
417c478bd9Sstevel@tonic-gate #include <thread.h>
427c478bd9Sstevel@tonic-gate #include <synch.h>
437c478bd9Sstevel@tonic-gate #include <dlfcn.h>
447c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * NIS+ security file
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define	NIS_SEC_CF_MAX_LINELEN		512
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* the min number of fields allowable per line */
547c478bd9Sstevel@tonic-gate #define	NIS_SEC_CF_MIN_FIELDS		5
557c478bd9Sstevel@tonic-gate /* the max number of fields processed per line */
567c478bd9Sstevel@tonic-gate #define	NIS_SEC_CF_MAX_FIELDS		7
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /* field "Not Applicable" char */
597c478bd9Sstevel@tonic-gate #define	NIS_SEC_CF_NA_CHAR	'-'
607c478bd9Sstevel@tonic-gate #define	NIS_SEC_CF_NA_CMP(a)	((a)[0] == NIS_SEC_CF_NA_CHAR && (a)[1] == '\0')
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static const char	*cf_entry_type_mech_str = "mech";
647c478bd9Sstevel@tonic-gate static const char	*cf_mech_des_str = NIS_SEC_CF_DES_ALIAS;
657c478bd9Sstevel@tonic-gate static const char	*cf_mech_dh1920_str = "dh192-0";
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate static const char	*cf_secserv_default_str = "default";
687c478bd9Sstevel@tonic-gate static const char	*cf_secserv_none_str = "none";
697c478bd9Sstevel@tonic-gate static const char	*cf_secserv_integrity_str = "integrity";
707c478bd9Sstevel@tonic-gate static const char	*cf_secserv_privacy_str = "privacy";
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static mutex_t		nis_sec_cf_lock = DEFAULTMUTEX;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * GSS mechanisms file
777c478bd9Sstevel@tonic-gate  *
787c478bd9Sstevel@tonic-gate  * This is currently a private NIS+ interface but at some point in the future
797c478bd9Sstevel@tonic-gate  * can be broken out and made available to other apps that need to access
807c478bd9Sstevel@tonic-gate  * GSS backends.
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #define	MF_MAX_LINELEN	256
847c478bd9Sstevel@tonic-gate #define	MF_MAX_FLDLEN	MAXDHNAME
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /* mech file entry type */
877c478bd9Sstevel@tonic-gate typedef struct {
887c478bd9Sstevel@tonic-gate 	char *mechname;
897c478bd9Sstevel@tonic-gate 	char *oid;
907c478bd9Sstevel@tonic-gate 	char *libname;
917c478bd9Sstevel@tonic-gate 	/* the 4th field is not used by user land apps */
927c478bd9Sstevel@tonic-gate } mfent_t;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate static const char	mech_file[] = "/etc/gss/mech";
957c478bd9Sstevel@tonic-gate static const int	mech_file_flds_max = 3;
967c478bd9Sstevel@tonic-gate static const int	mech_file_flds_min = 3;
977c478bd9Sstevel@tonic-gate static mutex_t		mech_file_lock = DEFAULTMUTEX;
987c478bd9Sstevel@tonic-gate static const char	dh_str[] = "diffie_hellman";
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX1	"/usr/lib/"
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #ifdef _LP64
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	"64/"
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #else   /* _LP64 */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX2	""
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate #endif  /* _LP64 */
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #define	MECH_LIB_DIR		"gss/"
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate #define	MECH_LIB_PREFIX	MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static void
list_free_all(void (* free_ent)(),void ** mpp)1197c478bd9Sstevel@tonic-gate list_free_all(void (*free_ent)(), void **mpp)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	void **tpp = mpp;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	if (tpp) {
1247c478bd9Sstevel@tonic-gate 		for (; *tpp; tpp++)
1257c478bd9Sstevel@tonic-gate 			(*free_ent)(*tpp);
1267c478bd9Sstevel@tonic-gate 		free(mpp);
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate static void **
list_append_ent(void * ent,void ** list,uint_t cnt,void (* free_ent)())1317c478bd9Sstevel@tonic-gate list_append_ent(void *ent, void **list, uint_t cnt, void (*free_ent)())
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	void **new_l;
1347c478bd9Sstevel@tonic-gate 
13561961e0fSrobinson 	if (!(new_l = realloc(list, sizeof (*list) * (cnt + 1)))) {
1367c478bd9Sstevel@tonic-gate 		list_free_all(free_ent, list);
1377c478bd9Sstevel@tonic-gate 		return (NULL);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate 	*(new_l + cnt - 1) = ent;
1407c478bd9Sstevel@tonic-gate 	*(new_l + cnt) = NULL;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	return (new_l);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate static void **
list_copy(void * (* cp_ent)(),void ** mpp)1467c478bd9Sstevel@tonic-gate list_copy(void *(*cp_ent)(), void **mpp)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	void	**tpp_h;
1497c478bd9Sstevel@tonic-gate 	void	**tpp;
1507c478bd9Sstevel@tonic-gate 	void	*tp;
1517c478bd9Sstevel@tonic-gate 	int 	diff;
1527c478bd9Sstevel@tonic-gate 
15361961e0fSrobinson 	if (!mpp)
1547c478bd9Sstevel@tonic-gate 		return (NULL);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	for (tpp = mpp; *tpp; tpp++)
1577c478bd9Sstevel@tonic-gate 		;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	diff = tpp - mpp;
1607c478bd9Sstevel@tonic-gate 
16161961e0fSrobinson 	if (!(tpp_h = calloc(diff + 1, sizeof (*mpp))))
1627c478bd9Sstevel@tonic-gate 		return (NULL);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	for (tpp = tpp_h; *mpp; mpp++) {
16561961e0fSrobinson 		if (!(tp = (*cp_ent)(*mpp))) {
1667c478bd9Sstevel@tonic-gate 			free(tpp_h);
1677c478bd9Sstevel@tonic-gate 			return (NULL);
1687c478bd9Sstevel@tonic-gate 		}
1697c478bd9Sstevel@tonic-gate 		*tpp++ = tp;
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	return (tpp_h);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static char *
nextline(fd,line)1767c478bd9Sstevel@tonic-gate nextline(fd, line)
177*004388ebScasper 	FILE *fd;
1787c478bd9Sstevel@tonic-gate 	char *line;
1797c478bd9Sstevel@tonic-gate {
1807c478bd9Sstevel@tonic-gate 	char *cp;
1817c478bd9Sstevel@tonic-gate 
182*004388ebScasper 	if (fgets(line, NIS_SEC_CF_MAX_LINELEN, fd) == NULL)
1837c478bd9Sstevel@tonic-gate 		return (NULL);
1847c478bd9Sstevel@tonic-gate 	cp = index(line, '\n');
1857c478bd9Sstevel@tonic-gate 	if (cp)
1867c478bd9Sstevel@tonic-gate 		*cp = '\0';
1877c478bd9Sstevel@tonic-gate 	return (line);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static int
nextfield(char ** cpp,char * op,int n)1917c478bd9Sstevel@tonic-gate nextfield(char **cpp, char *op, int n)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	intptr_t max;
1957c478bd9Sstevel@tonic-gate 	char *dst = op;
1967c478bd9Sstevel@tonic-gate 	char *cp = *cpp;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	while (*cp == ' ' || *cp == '\t')
1997c478bd9Sstevel@tonic-gate 		cp++;
2007c478bd9Sstevel@tonic-gate 	if (*cp == '\0' || *cp == '#')
2017c478bd9Sstevel@tonic-gate 		return (0);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	max = (intptr_t)op + n;
2047c478bd9Sstevel@tonic-gate 	while (*cp && *cp != ' ' && *cp != '\t' && *cp != '#' &&
2057c478bd9Sstevel@tonic-gate 		(intptr_t)dst < max)
2067c478bd9Sstevel@tonic-gate 		*dst++ = *cp++;
2077c478bd9Sstevel@tonic-gate 	*dst = '\0';
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if ((intptr_t)dst >= max)
2107c478bd9Sstevel@tonic-gate 		/* not much else to do but move past current field */
2117c478bd9Sstevel@tonic-gate 		while (*cp && *cp != ' ' && *cp != '\t' && *cp != '#')
2127c478bd9Sstevel@tonic-gate 			cp++;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	*cpp = cp;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	return (1);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate static rpc_gss_service_t
str_to_secserv_t(const char * s)2217c478bd9Sstevel@tonic-gate str_to_secserv_t(const char *s)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	if (s) {
2257c478bd9Sstevel@tonic-gate 		if (strncmp(cf_secserv_none_str, s,
2267c478bd9Sstevel@tonic-gate 			    strlen(cf_secserv_none_str)) == 0)
2277c478bd9Sstevel@tonic-gate 			return (rpc_gss_svc_none);
2287c478bd9Sstevel@tonic-gate 		if (strncmp(cf_secserv_integrity_str, s,
2297c478bd9Sstevel@tonic-gate 			    strlen(cf_secserv_integrity_str)) == 0)
2307c478bd9Sstevel@tonic-gate 			return (rpc_gss_svc_integrity);
2317c478bd9Sstevel@tonic-gate 		if (strncmp(cf_secserv_privacy_str, s,
2327c478bd9Sstevel@tonic-gate 			    strlen(cf_secserv_privacy_str)) == 0)
2337c478bd9Sstevel@tonic-gate 			return (rpc_gss_svc_privacy);
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	return (rpc_gss_svc_default);
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate /*
2407c478bd9Sstevel@tonic-gate  * Return TRUE if all the chars up to the NUL are of the digit type.
2417c478bd9Sstevel@tonic-gate  * Else return FALSE.
2427c478bd9Sstevel@tonic-gate  */
2437c478bd9Sstevel@tonic-gate static bool_t
isnumberstr(const char * s)2447c478bd9Sstevel@tonic-gate isnumberstr(const char *s)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	for (; *s; s++)
24861961e0fSrobinson 		if (!isdigit(*s))
2497c478bd9Sstevel@tonic-gate 			return (FALSE);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	return (TRUE);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate  * Free security file mechanism entry.
2567c478bd9Sstevel@tonic-gate  */
2577c478bd9Sstevel@tonic-gate static void
sf_free_mech_ent(mechanism_t * mp)2587c478bd9Sstevel@tonic-gate sf_free_mech_ent(mechanism_t *mp)
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 	if (mp) {
2617c478bd9Sstevel@tonic-gate 		if (mp->mechname)
2627c478bd9Sstevel@tonic-gate 			free(mp->mechname);
2637c478bd9Sstevel@tonic-gate 		if (mp->alias)
2647c478bd9Sstevel@tonic-gate 			free(mp->alias);
2657c478bd9Sstevel@tonic-gate 		if (mp->qop)
2667c478bd9Sstevel@tonic-gate 			free(mp->qop);
2677c478bd9Sstevel@tonic-gate 		free(mp);
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate static void
free_fields(char ** cpp,int cnt)2727c478bd9Sstevel@tonic-gate free_fields(char **cpp, int cnt)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	char **tpp = cpp;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	if (cpp) {
2777c478bd9Sstevel@tonic-gate 		if (cnt)
2787c478bd9Sstevel@tonic-gate 			for (; cnt > 0; cnt--, tpp++)
2797c478bd9Sstevel@tonic-gate 				if (*tpp)
2807c478bd9Sstevel@tonic-gate 					free(*tpp);
2817c478bd9Sstevel@tonic-gate 				else
2827c478bd9Sstevel@tonic-gate 					break;
2837c478bd9Sstevel@tonic-gate 		free(cpp);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate  * Generic parse-linestr-of-config-file routine.  Arg linep is ptr
2897c478bd9Sstevel@tonic-gate  * (which will be modified) to the input string .  Arg minflds is the
2907c478bd9Sstevel@tonic-gate  * minimum number of fields expected.  Arg maxflds is the max number
2917c478bd9Sstevel@tonic-gate  * of fields that will be parsed.  Arg bufsiz is the max len of each
2927c478bd9Sstevel@tonic-gate  * field that will  be copied to the return area.
2937c478bd9Sstevel@tonic-gate  *
2947c478bd9Sstevel@tonic-gate  * If there are less fields in the entry than the max number,
2957c478bd9Sstevel@tonic-gate  * the remainding ptrs will be 0.
2967c478bd9Sstevel@tonic-gate  *
2977c478bd9Sstevel@tonic-gate  * Returns a ptr to an array of ptrs to strings on success else
2987c478bd9Sstevel@tonic-gate  * NULL on failure.
2997c478bd9Sstevel@tonic-gate  *
3007c478bd9Sstevel@tonic-gate  * The caller must free the storage (of a successful return only).
3017c478bd9Sstevel@tonic-gate  */
3027c478bd9Sstevel@tonic-gate static char **
parse_line(char * linep,int minflds,int maxflds,int bufsiz)3037c478bd9Sstevel@tonic-gate parse_line(char *linep, int minflds, int maxflds, int bufsiz)
3047c478bd9Sstevel@tonic-gate {
3057c478bd9Sstevel@tonic-gate 	char **fpp = calloc(maxflds, sizeof (linep));
3067c478bd9Sstevel@tonic-gate 	char **tpp = fpp;
3077c478bd9Sstevel@tonic-gate 	char *cp;
3087c478bd9Sstevel@tonic-gate 	int	i;
3097c478bd9Sstevel@tonic-gate 
31061961e0fSrobinson 	if (!fpp)
3117c478bd9Sstevel@tonic-gate 		return (NULL);
3127c478bd9Sstevel@tonic-gate 
31361961e0fSrobinson 	if (!(cp = malloc(bufsiz))) {
3147c478bd9Sstevel@tonic-gate 		free(fpp);
3157c478bd9Sstevel@tonic-gate 		return (NULL);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	for (i = 0; i < maxflds; i++, tpp++) {
3197c478bd9Sstevel@tonic-gate 		char *tp;
32061961e0fSrobinson 		if (!nextfield(&linep, cp, bufsiz)) {
3217c478bd9Sstevel@tonic-gate 			free(cp);
3227c478bd9Sstevel@tonic-gate 			if (i < minflds) {
3237c478bd9Sstevel@tonic-gate 				free_fields(fpp, i);
3247c478bd9Sstevel@tonic-gate 				return (NULL);
3257c478bd9Sstevel@tonic-gate 			} else
3267c478bd9Sstevel@tonic-gate 				return (fpp);
3277c478bd9Sstevel@tonic-gate 		}
32861961e0fSrobinson 		if (!(tp = strdup(cp))) {
3297c478bd9Sstevel@tonic-gate 			free_fields(fpp, i);
3307c478bd9Sstevel@tonic-gate 			free(cp);
3317c478bd9Sstevel@tonic-gate 			return (NULL);
3327c478bd9Sstevel@tonic-gate 		}
3337c478bd9Sstevel@tonic-gate 		*tpp = tp;
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	free(cp);
3377c478bd9Sstevel@tonic-gate 	return (fpp);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate  * Return a ptr to a mechanism entry read from a line of the sec conf file.
3427c478bd9Sstevel@tonic-gate  * Return NULL on EOF or error.
3437c478bd9Sstevel@tonic-gate  *
3447c478bd9Sstevel@tonic-gate  * An alias field of "des" (case not sig) will override any settings
3457c478bd9Sstevel@tonic-gate  * in the keylen or algtype fields like so:
3467c478bd9Sstevel@tonic-gate  *    keylen  = 192
3477c478bd9Sstevel@tonic-gate  *    algtype = 0
3487c478bd9Sstevel@tonic-gate  */
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate static mechanism_t *
get_secfile_ent(FILE * fptr)351*004388ebScasper get_secfile_ent(FILE *fptr)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate 	mechanism_t	*m;
3547c478bd9Sstevel@tonic-gate 	char		*cp;
3557c478bd9Sstevel@tonic-gate 	char		**flds;  /* line fields */
3567c478bd9Sstevel@tonic-gate 	const int	num_flds_min = NIS_SEC_CF_MIN_FIELDS;
3577c478bd9Sstevel@tonic-gate 	const int	num_flds_max = NIS_SEC_CF_MAX_FIELDS;
3587c478bd9Sstevel@tonic-gate 	char		line[NIS_SEC_CF_MAX_LINELEN + 1 ] = {0};
3597c478bd9Sstevel@tonic-gate 	const int	line_len = NIS_SEC_CF_MAX_LINELEN + 1;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/*
3627c478bd9Sstevel@tonic-gate 	 * NIS+ security conf file layout
3637c478bd9Sstevel@tonic-gate 	 * <Entry_type>
3647c478bd9Sstevel@tonic-gate 	 * mech 	<GSS_mechanism_name> <Mech_bit_size> <Mech_alg_type>
3657c478bd9Sstevel@tonic-gate 	 * 		<Alias> <GSS_quality_of_protection> <GSS_sec_svc>
3667c478bd9Sstevel@tonic-gate 	 *
3677c478bd9Sstevel@tonic-gate 	 * QOP and sec_svc are optional.
3687c478bd9Sstevel@tonic-gate 	 */
3697c478bd9Sstevel@tonic-gate 	const int	mn_offset = 1; /* mechname */
3707c478bd9Sstevel@tonic-gate 	const int	kl_offset = 2; /* key length */
3717c478bd9Sstevel@tonic-gate 	const int	at_offset = 3; /* alg type */
3727c478bd9Sstevel@tonic-gate 	const int	al_offset = 4; /* mech alias */
3737c478bd9Sstevel@tonic-gate 	const int	qp_offset = 5; /* qop */
3747c478bd9Sstevel@tonic-gate 	const int	ss_offset = 6; /* security svc */
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate cont:
3777c478bd9Sstevel@tonic-gate 	while (((cp = nextline(fptr, line)) != NULL) &&
3787c478bd9Sstevel@tonic-gate 		(*cp == '#' || *cp == '\0'))
3797c478bd9Sstevel@tonic-gate 		;
3807c478bd9Sstevel@tonic-gate 	if (cp == NULL)
3817c478bd9Sstevel@tonic-gate 		return (NULL);
3827c478bd9Sstevel@tonic-gate 
38361961e0fSrobinson 	if (!(flds = parse_line(cp, num_flds_min, num_flds_max,
3847c478bd9Sstevel@tonic-gate 					line_len)))
3857c478bd9Sstevel@tonic-gate 		goto cont;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	if (strncmp(cf_entry_type_mech_str, *flds,
3887c478bd9Sstevel@tonic-gate 		    strlen(cf_entry_type_mech_str))) {
3897c478bd9Sstevel@tonic-gate 		free_fields(flds, num_flds_max);
3907c478bd9Sstevel@tonic-gate 		goto cont;
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 
39361961e0fSrobinson 	if (!(m = malloc(sizeof (mechanism_t)))) {
3947c478bd9Sstevel@tonic-gate 		free_fields(flds, num_flds_max);
3957c478bd9Sstevel@tonic-gate 		return (NULL);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	/* mechanism name */
3997c478bd9Sstevel@tonic-gate 	m->mechname = NIS_SEC_CF_NA_CMP(*(flds + mn_offset)) ? NULL
4007c478bd9Sstevel@tonic-gate 		: strdup(*(flds + mn_offset));
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	/* mechanism alias */
4037c478bd9Sstevel@tonic-gate 	m->alias = NIS_SEC_CF_NA_CMP(*(flds + al_offset)) ? NULL
4047c478bd9Sstevel@tonic-gate 		: strdup(*(flds + al_offset));
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	/*
4077c478bd9Sstevel@tonic-gate 	 * qop: optional field
4087c478bd9Sstevel@tonic-gate 	 * Make qop NULL if the field was empty or was "default" or
4097c478bd9Sstevel@tonic-gate 	 * was '-'.
4107c478bd9Sstevel@tonic-gate 	 */
41161961e0fSrobinson 	if (!*(flds + qp_offset) ||
4127c478bd9Sstevel@tonic-gate 	    (strncasecmp(*(flds + qp_offset), cf_secserv_default_str,
4137c478bd9Sstevel@tonic-gate 				strlen(cf_secserv_default_str)) == 0) ||
4147c478bd9Sstevel@tonic-gate 	    NIS_SEC_CF_NA_CMP(*(flds + qp_offset)))
4157c478bd9Sstevel@tonic-gate 		m->qop = NULL;
4167c478bd9Sstevel@tonic-gate 	else
4177c478bd9Sstevel@tonic-gate 		m->qop = strdup(*(flds + qp_offset));
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	/* security service: optional field */
4207c478bd9Sstevel@tonic-gate 	m->secserv  = str_to_secserv_t(*(flds + ss_offset));
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	/* mech alias */
4237c478bd9Sstevel@tonic-gate 	if (*(flds + al_offset) &&
4247c478bd9Sstevel@tonic-gate 	    (strncasecmp(*(flds + al_offset), cf_mech_des_str,
4257c478bd9Sstevel@tonic-gate 				strlen(cf_mech_des_str)) == 0)) {
4267c478bd9Sstevel@tonic-gate 		/* we've got the AUTH_DES compat line */
4277c478bd9Sstevel@tonic-gate 		m->keylen = 192;
4287c478bd9Sstevel@tonic-gate 		m->algtype = 0;
4297c478bd9Sstevel@tonic-gate 	} else {
4307c478bd9Sstevel@tonic-gate 		/* key length (bits) */
4317c478bd9Sstevel@tonic-gate 		if (NIS_SEC_CF_NA_CMP(*(flds + kl_offset)))
4327c478bd9Sstevel@tonic-gate 			m->keylen = NIS_SEC_CF_NA_KA;
4337c478bd9Sstevel@tonic-gate 		else if (!isnumberstr(*(flds + kl_offset))) {
4347c478bd9Sstevel@tonic-gate 			free_fields(flds, num_flds_max);
4357c478bd9Sstevel@tonic-gate 			sf_free_mech_ent(m);
4367c478bd9Sstevel@tonic-gate 			goto cont;
4377c478bd9Sstevel@tonic-gate 		} else
4387c478bd9Sstevel@tonic-gate 			m->keylen =  atoi(*(flds + kl_offset));
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 		/* algorithm type */
4417c478bd9Sstevel@tonic-gate 		if (NIS_SEC_CF_NA_CMP(*(flds + at_offset)))
4427c478bd9Sstevel@tonic-gate 			m->algtype = NIS_SEC_CF_NA_KA;
4437c478bd9Sstevel@tonic-gate 		else if (!isnumberstr(*(flds + at_offset))) {
4447c478bd9Sstevel@tonic-gate 			free_fields(flds, num_flds_max);
4457c478bd9Sstevel@tonic-gate 			sf_free_mech_ent(m);
4467c478bd9Sstevel@tonic-gate 			goto cont;
4477c478bd9Sstevel@tonic-gate 		} else
4487c478bd9Sstevel@tonic-gate 			m->algtype =  atoi(*(flds + at_offset));
4497c478bd9Sstevel@tonic-gate 	}
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	free_fields(flds, num_flds_max);
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	return (m);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate  * Return TRUE if both entries have the same
4587c478bd9Sstevel@tonic-gate  * mechname/alias/keylen/algotype combo.  Else return FALSE.
4597c478bd9Sstevel@tonic-gate  */
4607c478bd9Sstevel@tonic-gate static bool_t
equal_entries(const mechanism_t * mp,const mechanism_t * tp)4617c478bd9Sstevel@tonic-gate equal_entries(const mechanism_t *mp, const mechanism_t *tp)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	if (mp && tp) {
4647c478bd9Sstevel@tonic-gate 		if (mp->keylen != tp->keylen)
4657c478bd9Sstevel@tonic-gate 			return (FALSE);
4667c478bd9Sstevel@tonic-gate 		if (mp->algtype != tp->algtype)
4677c478bd9Sstevel@tonic-gate 			return (FALSE);
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 		/* both NULL, the 2 are equal */
4707c478bd9Sstevel@tonic-gate 		if (!mp->mechname && !tp->mechname)
4717c478bd9Sstevel@tonic-gate 			return (TRUE);
4727c478bd9Sstevel@tonic-gate 		/* only one NULL, not equal */
4737c478bd9Sstevel@tonic-gate 		if (!mp->mechname || !tp->mechname)
4747c478bd9Sstevel@tonic-gate 			return (FALSE);
4757c478bd9Sstevel@tonic-gate 		if (strcmp(mp->mechname, tp->mechname) != 0)
4767c478bd9Sstevel@tonic-gate 			return (FALSE);
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		if (!mp->alias && !tp->alias)
4797c478bd9Sstevel@tonic-gate 			return (TRUE);
4807c478bd9Sstevel@tonic-gate 		if (!mp->alias || !tp->alias)
4817c478bd9Sstevel@tonic-gate 			return (FALSE);
4827c478bd9Sstevel@tonic-gate 		if (strcmp(mp->alias, tp->alias) != 0)
4837c478bd9Sstevel@tonic-gate 			return (FALSE);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	return (TRUE);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate static mechanism_t *
sf_copy_mech_ent(mechanism_t * mp)4907c478bd9Sstevel@tonic-gate sf_copy_mech_ent(mechanism_t *mp)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate 	mechanism_t *tp = calloc(1, sizeof (*mp));
4937c478bd9Sstevel@tonic-gate 
49461961e0fSrobinson 	if (!mp || !tp)
4957c478bd9Sstevel@tonic-gate 		return (NULL);
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	tp->mechname = mp->mechname ? strdup(mp->mechname) : NULL;
4987c478bd9Sstevel@tonic-gate 	tp->alias = mp->alias ? strdup(mp->alias) : NULL;
4997c478bd9Sstevel@tonic-gate 	tp->qop = mp->qop ? strdup(mp->qop) : NULL;
5007c478bd9Sstevel@tonic-gate 	tp->keylen = mp->keylen;
5017c478bd9Sstevel@tonic-gate 	tp->algtype = mp->algtype;
5027c478bd9Sstevel@tonic-gate 	tp->secserv = mp->secserv;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	return (tp);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate  * Return TRUE if the mechname/alias/keylen/algtype combo
5097c478bd9Sstevel@tonic-gate  * already exists in the no dups array.  Else return FALSE.
5107c478bd9Sstevel@tonic-gate  */
5117c478bd9Sstevel@tonic-gate static bool_t
member_of_dups(mechanism_t ** t,const mechanism_t * mp)5127c478bd9Sstevel@tonic-gate member_of_dups(mechanism_t **t, const mechanism_t *mp)
5137c478bd9Sstevel@tonic-gate {
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (t)
5167c478bd9Sstevel@tonic-gate 		for (; *t; t++)
5177c478bd9Sstevel@tonic-gate 			if (equal_entries(mp, *t))
5187c478bd9Sstevel@tonic-gate 				return (TRUE);
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	return (FALSE);
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate /*
5247c478bd9Sstevel@tonic-gate  * Return a list of valid mechanisms ranked by sequence in the NIS+
5257c478bd9Sstevel@tonic-gate  * security conf file.  Return NULL if there are no valid entries.
5267c478bd9Sstevel@tonic-gate  * On success, the last pointer of the array of pointers will be NULL.
5277c478bd9Sstevel@tonic-gate  *
5287c478bd9Sstevel@tonic-gate  * If input arg 'qop_secserv' is TRUE, include duplicate
5297c478bd9Sstevel@tonic-gate  * mechname/alias/keylen/algtype entries that differ only in the QOP
5307c478bd9Sstevel@tonic-gate  * and security service.  Else, duplicates are omitted.
5317c478bd9Sstevel@tonic-gate  *
5327c478bd9Sstevel@tonic-gate  * The list of mechanisms are gauranteed to be valid ones installed
5337c478bd9Sstevel@tonic-gate  * on the system.
5347c478bd9Sstevel@tonic-gate  *
5357c478bd9Sstevel@tonic-gate  * This implementation returns copies of the "master" list.  The "master"
5367c478bd9Sstevel@tonic-gate  * list will updated if the file is modified.
5377c478bd9Sstevel@tonic-gate  */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate mechanism_t **
__nis_get_mechanisms(bool_t qop_secserv)5407c478bd9Sstevel@tonic-gate __nis_get_mechanisms(bool_t qop_secserv)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	/*
5437c478bd9Sstevel@tonic-gate 	 * 'mechs' is the "master" list of valid mechanisms from
5447c478bd9Sstevel@tonic-gate 	 * the NIS+ security conf file.
5457c478bd9Sstevel@tonic-gate 	 * 'mechs_no_dups' is the "master" list of valid mechanisms
5467c478bd9Sstevel@tonic-gate 	 * that differ only in QOP/SecuritySvc fields.
5477c478bd9Sstevel@tonic-gate 	 */
5487c478bd9Sstevel@tonic-gate 	static mechanism_t	**mechs = NULL;
5497c478bd9Sstevel@tonic-gate 	static mechanism_t	**mechs_no_dups = NULL;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	mechanism_t	*mp;
5527c478bd9Sstevel@tonic-gate 	mechanism_t	**tmechs = NULL;	 /* temp mechs */
5537c478bd9Sstevel@tonic-gate 	mechanism_t	**tmechs_no_dups = NULL; /* temp mechs sans dups */
5547c478bd9Sstevel@tonic-gate 	int		ent_cnt = 0;		 /* valid cf file entry count */
5557c478bd9Sstevel@tonic-gate 	int		ent_cnt_no_dups = 0;	 /* valid cf count, no dups */
5567c478bd9Sstevel@tonic-gate 	static uint_t	last = 0;
5577c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
558*004388ebScasper 	FILE 		*fptr;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	if (stat(NIS_SEC_CF_PATHNAME, &sbuf) != 0)
5617c478bd9Sstevel@tonic-gate 		return (NULL);
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&nis_sec_cf_lock);
5647c478bd9Sstevel@tonic-gate 	if (sbuf.st_mtime > last) {
5657c478bd9Sstevel@tonic-gate 		last = sbuf.st_mtime;
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 		if (mechs) {
5687c478bd9Sstevel@tonic-gate 			/* free old master lists */
5697c478bd9Sstevel@tonic-gate 			__nis_release_mechanisms(mechs);
5707c478bd9Sstevel@tonic-gate 			if (mechs_no_dups)
5717c478bd9Sstevel@tonic-gate 				free(mechs_no_dups);
5727c478bd9Sstevel@tonic-gate 		}
5737c478bd9Sstevel@tonic-gate 		mechs = mechs_no_dups = NULL;
5747c478bd9Sstevel@tonic-gate 
575*004388ebScasper 		if (!(fptr = fopen(NIS_SEC_CF_PATHNAME, "rF"))) {
5767c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&nis_sec_cf_lock);
5777c478bd9Sstevel@tonic-gate 			return (NULL);
5787c478bd9Sstevel@tonic-gate 		}
5797c478bd9Sstevel@tonic-gate 
5807c478bd9Sstevel@tonic-gate 		while (mp = get_secfile_ent(fptr)) {
5817c478bd9Sstevel@tonic-gate 			/*
5827c478bd9Sstevel@tonic-gate 			 * Make sure entry is either the AUTH_DES compat
5837c478bd9Sstevel@tonic-gate 			 * one or a valid GSS one that is installed.
5847c478bd9Sstevel@tonic-gate 			 */
58561961e0fSrobinson 			if (!(AUTH_DES_COMPAT_CHK(mp) ||
5867c478bd9Sstevel@tonic-gate 				(NIS_SEC_CF_GSS_MECH(mp) &&
5877c478bd9Sstevel@tonic-gate 					rpc_gss_is_installed(mp->mechname)))) {
5887c478bd9Sstevel@tonic-gate 				continue;
5897c478bd9Sstevel@tonic-gate 			}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 			ent_cnt++;
5927c478bd9Sstevel@tonic-gate 			tmechs = (mechanism_t **)
5937c478bd9Sstevel@tonic-gate 			    list_append_ent((void *)mp, (void **)tmechs,
5947c478bd9Sstevel@tonic-gate 			    ent_cnt, (void (*)())sf_free_mech_ent);
5957c478bd9Sstevel@tonic-gate 			if (tmechs == NULL) {
596*004388ebScasper 				(void) fclose(fptr);
5977c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&nis_sec_cf_lock);
5987c478bd9Sstevel@tonic-gate 				return (NULL);
5997c478bd9Sstevel@tonic-gate 			}
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 			if (member_of_dups(tmechs_no_dups, mp))
6027c478bd9Sstevel@tonic-gate 				continue;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 			ent_cnt_no_dups++;
6057c478bd9Sstevel@tonic-gate 			tmechs_no_dups = (mechanism_t **)
6067c478bd9Sstevel@tonic-gate 			    list_append_ent((void *)mp, (void **)tmechs_no_dups,
6077c478bd9Sstevel@tonic-gate 			    ent_cnt_no_dups, (void (*)())sf_free_mech_ent);
6087c478bd9Sstevel@tonic-gate 			if (tmechs_no_dups == NULL) {
609*004388ebScasper 				(void) fclose(fptr);
6107c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&nis_sec_cf_lock);
6117c478bd9Sstevel@tonic-gate 				return (NULL);
6127c478bd9Sstevel@tonic-gate 			}
6137c478bd9Sstevel@tonic-gate 		}
614*004388ebScasper 		(void) fclose(fptr);
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 		/* set master lists to point to new built ones */
6177c478bd9Sstevel@tonic-gate 		mechs = tmechs;
6187c478bd9Sstevel@tonic-gate 		mechs_no_dups = tmechs_no_dups;
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&nis_sec_cf_lock);
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	if (qop_secserv)
6237c478bd9Sstevel@tonic-gate 		/* return a copy of the list with possible dups */
6247c478bd9Sstevel@tonic-gate 		return (mechs ?
6257c478bd9Sstevel@tonic-gate 			(mechanism_t **)list_copy(
6267c478bd9Sstevel@tonic-gate 				(void *(*)()) sf_copy_mech_ent,
6277c478bd9Sstevel@tonic-gate 				(void **)mechs) :
6287c478bd9Sstevel@tonic-gate 			NULL);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	/* return a copy of the list without dups */
6317c478bd9Sstevel@tonic-gate 	return (mechs_no_dups ?
6327c478bd9Sstevel@tonic-gate 		(mechanism_t **)list_copy((void *(*)()) sf_copy_mech_ent,
6337c478bd9Sstevel@tonic-gate 						(void **)mechs_no_dups) :
6347c478bd9Sstevel@tonic-gate 		NULL);
6357c478bd9Sstevel@tonic-gate }
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate /*
6387c478bd9Sstevel@tonic-gate  * Search the mechs (no dups array) for an entry (mechname or alias)
6397c478bd9Sstevel@tonic-gate  * that matches (case not sig) the given mechname.  On target match,
6407c478bd9Sstevel@tonic-gate  * load the given memory locations pointed to by args keylen and
6417c478bd9Sstevel@tonic-gate  * algtype with values from the matched entry.
6427c478bd9Sstevel@tonic-gate  *
6437c478bd9Sstevel@tonic-gate  * The AUTH_DES "compat" line (alias == "des") will return 192-0
6447c478bd9Sstevel@tonic-gate  * (overriding the fields in the conf file).
6457c478bd9Sstevel@tonic-gate  *
6467c478bd9Sstevel@tonic-gate  * For any other entry, a conf file field of '-' (not applicable),
6477c478bd9Sstevel@tonic-gate  * in the keylen or algtype field will result in the locations for
6487c478bd9Sstevel@tonic-gate  * keylen and algtype being set to -1. (this is actually done in
6497c478bd9Sstevel@tonic-gate  * __nis_get_mechanisms()).
6507c478bd9Sstevel@tonic-gate  *
6517c478bd9Sstevel@tonic-gate  * Returns 0 on success and -1 on failure.
6527c478bd9Sstevel@tonic-gate  */
6537c478bd9Sstevel@tonic-gate int
__nis_translate_mechanism(const char * mechname,int * keylen,int * algtype)6547c478bd9Sstevel@tonic-gate __nis_translate_mechanism(const char *mechname, int *keylen, int *algtype)
6557c478bd9Sstevel@tonic-gate {
6567c478bd9Sstevel@tonic-gate 	mechanism_t **mpp;
6577c478bd9Sstevel@tonic-gate 	mechanism_t **mpp_h;
6587c478bd9Sstevel@tonic-gate 
65961961e0fSrobinson 	if (!mechname || !keylen || !algtype)
6607c478bd9Sstevel@tonic-gate 		return (-1);
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	/* AUTH_DES */
6637c478bd9Sstevel@tonic-gate 	if (strcmp(mechname, NIS_SEC_CF_DES_ALIAS) == 0) {
6647c478bd9Sstevel@tonic-gate 		*keylen = AUTH_DES_KEYLEN;
6657c478bd9Sstevel@tonic-gate 		*algtype = AUTH_DES_ALGTYPE;
6667c478bd9Sstevel@tonic-gate 		return (0);
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate 
66961961e0fSrobinson 	if (!(mpp = __nis_get_mechanisms(FALSE)))
6707c478bd9Sstevel@tonic-gate 		return (-1);
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	mpp_h = mpp;
6737c478bd9Sstevel@tonic-gate 	for (; *mpp; mpp++) {
6747c478bd9Sstevel@tonic-gate 		mechanism_t *mp = *mpp;
6757c478bd9Sstevel@tonic-gate 		if (mp->mechname &&
67661961e0fSrobinson 		    (!strcasecmp(mechname, mp->mechname))) {
6777c478bd9Sstevel@tonic-gate 				*keylen = mp->keylen;
6787c478bd9Sstevel@tonic-gate 				*algtype = mp->algtype;
6797c478bd9Sstevel@tonic-gate 				__nis_release_mechanisms(mpp_h);
6807c478bd9Sstevel@tonic-gate 				return (0);
6817c478bd9Sstevel@tonic-gate 		}
6827c478bd9Sstevel@tonic-gate 		if (mp->alias &&
68361961e0fSrobinson 		    (!strcasecmp(mechname, mp->alias))) {
6847c478bd9Sstevel@tonic-gate 				*keylen = mp->keylen;
6857c478bd9Sstevel@tonic-gate 				*algtype = mp->algtype;
6867c478bd9Sstevel@tonic-gate 				__nis_release_mechanisms(mpp_h);
6877c478bd9Sstevel@tonic-gate 				return (0);
6887c478bd9Sstevel@tonic-gate 		}
6897c478bd9Sstevel@tonic-gate 	}
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	__nis_release_mechanisms(mpp_h);
6927c478bd9Sstevel@tonic-gate 	return (-1);
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate  * Translate a mechname to an alias name.
6987c478bd9Sstevel@tonic-gate  *
6997c478bd9Sstevel@tonic-gate  * Returns alias on success or NULL on failure.
7007c478bd9Sstevel@tonic-gate  *
7017c478bd9Sstevel@tonic-gate  * Note alias will be the nullstring CSTYLE(on success) if cf
7027c478bd9Sstevel@tonic-gate  * alias field was "Not Applicable".
7037c478bd9Sstevel@tonic-gate  */
7047c478bd9Sstevel@tonic-gate char *
__nis_mechname2alias(const char * mechname,char * alias,size_t bufsize)7057c478bd9Sstevel@tonic-gate __nis_mechname2alias(const char *mechname,	/* in */
7067c478bd9Sstevel@tonic-gate 			char *alias,		/* out */
7077c478bd9Sstevel@tonic-gate 			size_t bufsize)		/* in */
7087c478bd9Sstevel@tonic-gate {
7097c478bd9Sstevel@tonic-gate 	mechanism_t **mpp;
7107c478bd9Sstevel@tonic-gate 	mechanism_t **mpp_h;
7117c478bd9Sstevel@tonic-gate 
71261961e0fSrobinson 	if (!mechname || !alias)
7137c478bd9Sstevel@tonic-gate 		return (NULL);
7147c478bd9Sstevel@tonic-gate 
71561961e0fSrobinson 	if (!(mpp = __nis_get_mechanisms(FALSE)))
7167c478bd9Sstevel@tonic-gate 		return (NULL);
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 	mpp_h = mpp;
7197c478bd9Sstevel@tonic-gate 	for (; *mpp; mpp++) {
7207c478bd9Sstevel@tonic-gate 		mechanism_t *mp = *mpp;
7217c478bd9Sstevel@tonic-gate 		int len;
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 		if (mp->mechname &&
7247c478bd9Sstevel@tonic-gate 		    (strcasecmp(mechname, mp->mechname) == 0)) {
7257c478bd9Sstevel@tonic-gate 			if (mp->alias) {
7267c478bd9Sstevel@tonic-gate 				if ((len = strlen(mp->alias)) < bufsize) {
7277c478bd9Sstevel@tonic-gate 					(void) strncpy(alias, mp->alias,
7287c478bd9Sstevel@tonic-gate 							len + 1);
7297c478bd9Sstevel@tonic-gate 					__nis_release_mechanisms(mpp_h);
7307c478bd9Sstevel@tonic-gate 					return (alias);
7317c478bd9Sstevel@tonic-gate 				}
7327c478bd9Sstevel@tonic-gate 			} else { /* cf file entry alias field was NA */
7337c478bd9Sstevel@tonic-gate 				alias[0] = '\0';
7347c478bd9Sstevel@tonic-gate 				__nis_release_mechanisms(mpp_h);
7357c478bd9Sstevel@tonic-gate 				return (alias);
7367c478bd9Sstevel@tonic-gate 			}
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 	}
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	__nis_release_mechanisms(mpp_h);
7427c478bd9Sstevel@tonic-gate 	return (NULL);
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate void
__nis_release_mechanisms(mechanism_t ** mpp)7467c478bd9Sstevel@tonic-gate __nis_release_mechanisms(mechanism_t **mpp)
7477c478bd9Sstevel@tonic-gate {
7487c478bd9Sstevel@tonic-gate 	list_free_all(sf_free_mech_ent, (void **)mpp);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate /*
7527c478bd9Sstevel@tonic-gate  * Convert an authtype (ie. DH640-0) to mechanism alias (ie. dh640-0).
7537c478bd9Sstevel@tonic-gate  * Input the authtype ptr, the mechalis ptr and the size of the mechalias
7547c478bd9Sstevel@tonic-gate  * buf.
7557c478bd9Sstevel@tonic-gate  *
7567c478bd9Sstevel@tonic-gate  * If mechalias buf is not large enough, truncate and don't indicate failure.
7577c478bd9Sstevel@tonic-gate  *
7587c478bd9Sstevel@tonic-gate  * Return the mechalias ptr on success or NULL on failure CSTYLE(any of
7597c478bd9Sstevel@tonic-gate  * the input args are NULL/0).
7607c478bd9Sstevel@tonic-gate  */
7617c478bd9Sstevel@tonic-gate char *
__nis_authtype2mechalias(const char * authtype,char * mechalias,size_t mechaliaslen)7627c478bd9Sstevel@tonic-gate __nis_authtype2mechalias(
7637c478bd9Sstevel@tonic-gate 	const char *authtype,	/* in */
7647c478bd9Sstevel@tonic-gate 	char *mechalias,	/* out */
7657c478bd9Sstevel@tonic-gate 	size_t mechaliaslen)	/* in */
7667c478bd9Sstevel@tonic-gate {
7677c478bd9Sstevel@tonic-gate 	char *dst = mechalias;
7687c478bd9Sstevel@tonic-gate 	const char *src = authtype;
7697c478bd9Sstevel@tonic-gate 	const char *max = src + mechaliaslen;
7707c478bd9Sstevel@tonic-gate 
77161961e0fSrobinson 	if (!src || !dst || mechaliaslen == 0)
7727c478bd9Sstevel@tonic-gate 		return (NULL);
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	while (*src && src < max - 1)
7757c478bd9Sstevel@tonic-gate 		*dst++ = tolower(*src++);
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	*dst = '\0';
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	return (mechalias);
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * Convert an mechalias (ie. dh640-0) to authtype (ie. DH640-0).
7847c478bd9Sstevel@tonic-gate  * Input the authtype ptr, the mechalis ptr and the size of the mechalias
7857c478bd9Sstevel@tonic-gate  * buf.
7867c478bd9Sstevel@tonic-gate  *
7877c478bd9Sstevel@tonic-gate  * A special mechalias of "dh192-0" will get converted to "DES".
7887c478bd9Sstevel@tonic-gate  *
7897c478bd9Sstevel@tonic-gate  * If authtype buf is not large enough, truncate and don't indicate failure.
7907c478bd9Sstevel@tonic-gate  *
7917c478bd9Sstevel@tonic-gate  * Return the authtype ptr on success or NULL on failure (any of
7927c478bd9Sstevel@tonic-gate  * the input args are NULL/0.
7937c478bd9Sstevel@tonic-gate  */
7947c478bd9Sstevel@tonic-gate char *
__nis_mechalias2authtype(const char * mechalias,char * authtype,size_t authtypelen)7957c478bd9Sstevel@tonic-gate __nis_mechalias2authtype(
7967c478bd9Sstevel@tonic-gate 	const char *mechalias,	/* in */
7977c478bd9Sstevel@tonic-gate 	char *authtype,		/* out */
7987c478bd9Sstevel@tonic-gate 	size_t authtypelen)	/* in */
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate 	const char *src = mechalias;
8027c478bd9Sstevel@tonic-gate 	char *dst = authtype;
8037c478bd9Sstevel@tonic-gate 	const char *max = src + authtypelen;
8047c478bd9Sstevel@tonic-gate 	const int slen = strlen(cf_mech_dh1920_str);
8057c478bd9Sstevel@tonic-gate 
80661961e0fSrobinson 	if (!src || !dst || !authtypelen)
8077c478bd9Sstevel@tonic-gate 		return (NULL);
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	if (strncasecmp(src, cf_mech_dh1920_str, slen + 1)
8107c478bd9Sstevel@tonic-gate 	    == 0) {
8117c478bd9Sstevel@tonic-gate 		if (slen >= authtypelen)
8127c478bd9Sstevel@tonic-gate 			return (NULL);
8137c478bd9Sstevel@tonic-gate 		(void) strcpy(authtype, AUTH_DES_AUTH_TYPE);
8147c478bd9Sstevel@tonic-gate 		return (authtype);
8157c478bd9Sstevel@tonic-gate 	}
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 	while (*src && src < max - 1)
8187c478bd9Sstevel@tonic-gate 		*dst++ = toupper(*src++);
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 	*dst = '\0';
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	return (authtype);
8237c478bd9Sstevel@tonic-gate }
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate /*
8267c478bd9Sstevel@tonic-gate  * Given a DH key length and algorithm type, return the mech
8277c478bd9Sstevel@tonic-gate  * alias string.  If the keyalg is not the classic AUTH_DES,
8287c478bd9Sstevel@tonic-gate  * then search the NIS+ security cf.
8297c478bd9Sstevel@tonic-gate  *
8307c478bd9Sstevel@tonic-gate  * On success return the mech alias string address.  Return
8317c478bd9Sstevel@tonic-gate  * NULL on failure.  Failure occurs if keylen or algtype is
8327c478bd9Sstevel@tonic-gate  * not found or the length of the input buf is too small
8337c478bd9Sstevel@tonic-gate  * or input args are bogus.  Alias buf will not be
8347c478bd9Sstevel@tonic-gate  * changed on failure.
8357c478bd9Sstevel@tonic-gate  */
8367c478bd9Sstevel@tonic-gate char *
__nis_keyalg2mechalias(keylen_t keylen,algtype_t algtype,char * alias,size_t alias_len)8377c478bd9Sstevel@tonic-gate __nis_keyalg2mechalias(
8387c478bd9Sstevel@tonic-gate 	keylen_t	keylen,		/* in */
8397c478bd9Sstevel@tonic-gate 	algtype_t	algtype,	/* in */
8407c478bd9Sstevel@tonic-gate 	char		*alias,		/* out */
8417c478bd9Sstevel@tonic-gate 	size_t		alias_len)	/* in */
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate 	mechanism_t	**mechs;  /* array of mechanisms */
8447c478bd9Sstevel@tonic-gate 
84561961e0fSrobinson 	if (!alias)
8467c478bd9Sstevel@tonic-gate 		return (NULL);
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	if (AUTH_DES_KEY(keylen, algtype)) {
8497c478bd9Sstevel@tonic-gate 		if (alias_len > strlen(NIS_SEC_CF_DES_ALIAS)) {
8507c478bd9Sstevel@tonic-gate 			(void) strcpy(alias, NIS_SEC_CF_DES_ALIAS);
8517c478bd9Sstevel@tonic-gate 			return (alias);
8527c478bd9Sstevel@tonic-gate 		}
8537c478bd9Sstevel@tonic-gate 		else
8547c478bd9Sstevel@tonic-gate 			return (NULL);
8557c478bd9Sstevel@tonic-gate 	} else
8567c478bd9Sstevel@tonic-gate 		if (mechs = __nis_get_mechanisms(FALSE)) {
8577c478bd9Sstevel@tonic-gate 			mechanism_t **mpp;
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 			for (mpp = mechs; *mpp; mpp++) {
8607c478bd9Sstevel@tonic-gate 				mechanism_t *mp = *mpp;
8617c478bd9Sstevel@tonic-gate 
86261961e0fSrobinson 				if (!VALID_MECH_ENTRY(mp) ||
8637c478bd9Sstevel@tonic-gate 				    AUTH_DES_COMPAT_CHK(mp))
8647c478bd9Sstevel@tonic-gate 					continue;
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 				if (keylen == mp->keylen &&
8677c478bd9Sstevel@tonic-gate 				    algtype == mp->algtype && mp->alias) {
8687c478bd9Sstevel@tonic-gate 					int al_len = strlen(mp->alias);
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 					if (alias_len > al_len) {
8717c478bd9Sstevel@tonic-gate 						(void) strncpy(alias, mp->alias,
8727c478bd9Sstevel@tonic-gate 							al_len + 1);
8737c478bd9Sstevel@tonic-gate 						return (alias);
8747c478bd9Sstevel@tonic-gate 					} else {
8757c478bd9Sstevel@tonic-gate 						__nis_release_mechanisms(mechs);
8767c478bd9Sstevel@tonic-gate 						return (NULL);
8777c478bd9Sstevel@tonic-gate 					}
8787c478bd9Sstevel@tonic-gate 				}
8797c478bd9Sstevel@tonic-gate 			}
8807c478bd9Sstevel@tonic-gate 			__nis_release_mechanisms(mechs);
8817c478bd9Sstevel@tonic-gate 		}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	return (NULL);
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate /*
8877c478bd9Sstevel@tonic-gate  * Given the key length and algorithm type, return the auth type
8887c478bd9Sstevel@tonic-gate  * string suitable for the cred table.
8897c478bd9Sstevel@tonic-gate  *
8907c478bd9Sstevel@tonic-gate  * Return the authtype on success and NULL on failure.
8917c478bd9Sstevel@tonic-gate  */
8927c478bd9Sstevel@tonic-gate char *
__nis_keyalg2authtype(keylen_t keylen,algtype_t algtype,char * authtype,size_t authtype_len)8937c478bd9Sstevel@tonic-gate __nis_keyalg2authtype(
8947c478bd9Sstevel@tonic-gate 	keylen_t keylen,	/* in */
8957c478bd9Sstevel@tonic-gate 	algtype_t algtype,	/* in */
8967c478bd9Sstevel@tonic-gate 	char *authtype,		/* out */
8977c478bd9Sstevel@tonic-gate 	size_t authtype_len)	/* in */
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	char alias[MECH_MAXALIASNAME+1] = {0};
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 
90261961e0fSrobinson 	if (!authtype || authtype_len == 0)
9037c478bd9Sstevel@tonic-gate 		return (NULL);
9047c478bd9Sstevel@tonic-gate 
90561961e0fSrobinson 	if (!__nis_keyalg2mechalias(keylen, algtype, alias, sizeof (alias)))
9067c478bd9Sstevel@tonic-gate 		return (NULL);
9077c478bd9Sstevel@tonic-gate 
90861961e0fSrobinson 	if (!__nis_mechalias2authtype(alias, authtype, authtype_len))
9097c478bd9Sstevel@tonic-gate 		return (NULL);
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	return (authtype);
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate /*
9157c478bd9Sstevel@tonic-gate  * Return a ptr to the next mech file entry or NULL on EOF.
9167c478bd9Sstevel@tonic-gate  * The caller should free the storage of a successful return.
9177c478bd9Sstevel@tonic-gate  */
9187c478bd9Sstevel@tonic-gate static mfent_t *
get_mechfile_ent(FILE * fptr)919*004388ebScasper get_mechfile_ent(FILE *fptr)
9207c478bd9Sstevel@tonic-gate {
9217c478bd9Sstevel@tonic-gate 	mfent_t		*m;
9227c478bd9Sstevel@tonic-gate 	char		*cp;
9237c478bd9Sstevel@tonic-gate 	char		**flds;
9247c478bd9Sstevel@tonic-gate 	char		line[MF_MAX_LINELEN] = {0};
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate cont:
9287c478bd9Sstevel@tonic-gate 	while (((cp = nextline(fptr, line)) != NULL) &&
9297c478bd9Sstevel@tonic-gate 		(*cp == '#' || *cp == '\0'))
9307c478bd9Sstevel@tonic-gate 		;
9317c478bd9Sstevel@tonic-gate 	if (cp == NULL)
9327c478bd9Sstevel@tonic-gate 		return (NULL);
9337c478bd9Sstevel@tonic-gate 
93461961e0fSrobinson 	if (!(flds = parse_line(cp, mech_file_flds_min,
9357c478bd9Sstevel@tonic-gate 					mech_file_flds_max, MF_MAX_FLDLEN)))
9367c478bd9Sstevel@tonic-gate 		goto cont;
9377c478bd9Sstevel@tonic-gate 
93861961e0fSrobinson 	if (!(m = malloc(sizeof (mfent_t)))) {
9397c478bd9Sstevel@tonic-gate 		free_fields(flds, mech_file_flds_max);
9407c478bd9Sstevel@tonic-gate 		return (NULL);
9417c478bd9Sstevel@tonic-gate 	}
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate 	m->mechname = strdup(*flds);
9447c478bd9Sstevel@tonic-gate 	m->oid = strdup(*(flds + 1));
9457c478bd9Sstevel@tonic-gate 	m->libname = strdup(*(flds + 2));
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	free_fields(flds, mech_file_flds_max);
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	return (m);
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate static mfent_t *
mf_copy_ent(mfent_t * mp)9537c478bd9Sstevel@tonic-gate mf_copy_ent(mfent_t *mp)
9547c478bd9Sstevel@tonic-gate {
9557c478bd9Sstevel@tonic-gate 	mfent_t *tp = calloc(1, sizeof (*mp));
9567c478bd9Sstevel@tonic-gate 
95761961e0fSrobinson 	if (!mp || !tp)
9587c478bd9Sstevel@tonic-gate 		return (NULL);
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	tp->mechname = mp->mechname ? strdup(mp->mechname) : NULL;
9617c478bd9Sstevel@tonic-gate 	tp->oid = mp->oid ? strdup(mp->oid) : NULL;
9627c478bd9Sstevel@tonic-gate 	tp->libname = mp->libname ? strdup(mp->libname) : NULL;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	return (tp);
9657c478bd9Sstevel@tonic-gate }
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate static void
mf_free_ent(mfent_t * mp)9697c478bd9Sstevel@tonic-gate mf_free_ent(mfent_t *mp)
9707c478bd9Sstevel@tonic-gate {
9717c478bd9Sstevel@tonic-gate 	if (mp) {
9727c478bd9Sstevel@tonic-gate 		if (mp->mechname)
9737c478bd9Sstevel@tonic-gate 			free(mp->mechname);
9747c478bd9Sstevel@tonic-gate 		if (mp->oid)
9757c478bd9Sstevel@tonic-gate 			free(mp->oid);
9767c478bd9Sstevel@tonic-gate 		if (mp->libname)
9777c478bd9Sstevel@tonic-gate 			free(mp->libname);
9787c478bd9Sstevel@tonic-gate 		free(mp);
9797c478bd9Sstevel@tonic-gate 	}
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 
9837c478bd9Sstevel@tonic-gate static void
mf_free_mechs(mfent_t ** mpp)9847c478bd9Sstevel@tonic-gate mf_free_mechs(mfent_t **mpp)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 	list_free_all(mf_free_ent, (void **)mpp);
9877c478bd9Sstevel@tonic-gate }
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate /*
9907c478bd9Sstevel@tonic-gate  * Return a copy of the list of the mech file entries.  The ptr to the last
9917c478bd9Sstevel@tonic-gate  * entry will be NULL on success.  The master list will be updated when
9927c478bd9Sstevel@tonic-gate  * the mechs file is modified.
9937c478bd9Sstevel@tonic-gate  *
9947c478bd9Sstevel@tonic-gate  * Return NULL if the file does not exist or no valid mechs exist in the
9957c478bd9Sstevel@tonic-gate  * file.
9967c478bd9Sstevel@tonic-gate  */
9977c478bd9Sstevel@tonic-gate static mfent_t **
mf_get_mechs()9987c478bd9Sstevel@tonic-gate mf_get_mechs()
9997c478bd9Sstevel@tonic-gate {
10007c478bd9Sstevel@tonic-gate 	static mfent_t	**mechs = NULL;		/* master mechs list */
10017c478bd9Sstevel@tonic-gate 	mfent_t		*mp;			/* a mech entry */
10027c478bd9Sstevel@tonic-gate 	mfent_t		**tmechs = NULL;	/* temp mechs list */
10037c478bd9Sstevel@tonic-gate 	uint_t		ent_cnt = 0;		/* valid cf file entry count */
10047c478bd9Sstevel@tonic-gate 	static uint_t	last = 0;		/* file last modified date */
10057c478bd9Sstevel@tonic-gate 	struct stat	sbuf;
1006*004388ebScasper 	FILE 		*fptr;
10077c478bd9Sstevel@tonic-gate 
10087c478bd9Sstevel@tonic-gate 	if (stat(mech_file, &sbuf) != 0)
10097c478bd9Sstevel@tonic-gate 		return (NULL);
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&mech_file_lock);
10127c478bd9Sstevel@tonic-gate 	if (sbuf.st_mtime > last) {
10137c478bd9Sstevel@tonic-gate 		last = sbuf.st_mtime;
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 		if (mechs) {
10167c478bd9Sstevel@tonic-gate 			/* free old master list */
10177c478bd9Sstevel@tonic-gate 			mf_free_mechs(mechs);
10187c478bd9Sstevel@tonic-gate 			mechs = NULL;
10197c478bd9Sstevel@tonic-gate 		}
10207c478bd9Sstevel@tonic-gate 
1021*004388ebScasper 		if (!(fptr = fopen(mech_file, "rF"))) {
10227c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&mech_file_lock);
10237c478bd9Sstevel@tonic-gate 			return (NULL);
10247c478bd9Sstevel@tonic-gate 		}
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 		while (mp = get_mechfile_ent(fptr)) {
10277c478bd9Sstevel@tonic-gate 			ent_cnt++;
10287c478bd9Sstevel@tonic-gate 			tmechs = (mfent_t **)list_append_ent((void *)mp,
10297c478bd9Sstevel@tonic-gate 			    (void **)tmechs, ent_cnt, (void (*)()) mf_free_ent);
10307c478bd9Sstevel@tonic-gate 			if (tmechs == NULL) {
1031*004388ebScasper 				(void) fclose(fptr);
10327c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&mech_file_lock);
10337c478bd9Sstevel@tonic-gate 				return (NULL);
10347c478bd9Sstevel@tonic-gate 			}
10357c478bd9Sstevel@tonic-gate 		}
1036*004388ebScasper 		(void) fclose(fptr);
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 		mechs = tmechs;  /* set master list to pt to newly built one */
10397c478bd9Sstevel@tonic-gate 	}
10407c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&mech_file_lock);
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	/* return a copy of the master list */
10437c478bd9Sstevel@tonic-gate 	return (mechs ? (mfent_t **)list_copy((void *(*)()) mf_copy_ent,
10447c478bd9Sstevel@tonic-gate 						(void **)mechs) : NULL);
10457c478bd9Sstevel@tonic-gate }
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate /*
10487c478bd9Sstevel@tonic-gate  * Translate a full mechname to it's corresponding library name
10497c478bd9Sstevel@tonic-gate  * as specified in the mech file.
10507c478bd9Sstevel@tonic-gate  */
10517c478bd9Sstevel@tonic-gate char *
mechfile_name2lib(const char * mechname,char * libname,int len)10527c478bd9Sstevel@tonic-gate mechfile_name2lib(const char *mechname, char *libname, int len)
10537c478bd9Sstevel@tonic-gate {
10547c478bd9Sstevel@tonic-gate 	mfent_t **mechs = mf_get_mechs();
10557c478bd9Sstevel@tonic-gate 	mfent_t **mpp;
10567c478bd9Sstevel@tonic-gate 
105761961e0fSrobinson 	if (!mechs || !mechname || !libname || !len)
10587c478bd9Sstevel@tonic-gate 		return (NULL);
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate 	for (mpp = mechs; *mpp; mpp++) {
10617c478bd9Sstevel@tonic-gate 		mfent_t *mp = *mpp;
10627c478bd9Sstevel@tonic-gate 
10637c478bd9Sstevel@tonic-gate 		if (mp->mechname && strcasecmp(mechname, mp->mechname) == 0) {
10647c478bd9Sstevel@tonic-gate 			if (strlen(mp->libname) < len) {
10657c478bd9Sstevel@tonic-gate 				(void) strcpy(libname, mp->libname);
10667c478bd9Sstevel@tonic-gate 					mf_free_mechs(mechs);
10677c478bd9Sstevel@tonic-gate 					return (libname);
10687c478bd9Sstevel@tonic-gate 				}
10697c478bd9Sstevel@tonic-gate 		}
10707c478bd9Sstevel@tonic-gate 	}
10717c478bd9Sstevel@tonic-gate 	mf_free_mechs(mechs);
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	return (NULL);
10747c478bd9Sstevel@tonic-gate }
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate /*
10777c478bd9Sstevel@tonic-gate  * Given a key length and algo type, return the appro DH mech library
10787c478bd9Sstevel@tonic-gate  * name.
10797c478bd9Sstevel@tonic-gate  */
10807c478bd9Sstevel@tonic-gate char *
__nis_get_mechanism_library(keylen_t keylen,algtype_t algtype,char * buffer,size_t buflen)10817c478bd9Sstevel@tonic-gate __nis_get_mechanism_library(keylen_t keylen, algtype_t algtype,
10827c478bd9Sstevel@tonic-gate 			    char *buffer, size_t buflen)
10837c478bd9Sstevel@tonic-gate {
10847c478bd9Sstevel@tonic-gate 	char mechname[MAXDHNAME + 1];
10857c478bd9Sstevel@tonic-gate 
108661961e0fSrobinson 	if (keylen == 0 || !buffer || buflen == 0)
10877c478bd9Sstevel@tonic-gate 		return (NULL);
10887c478bd9Sstevel@tonic-gate 
108961961e0fSrobinson 	(void) snprintf(mechname, sizeof (mechname),
109061961e0fSrobinson 					"%s_%d_%d", dh_str, keylen, algtype);
10917c478bd9Sstevel@tonic-gate 
109261961e0fSrobinson 	if (!mechfile_name2lib(mechname, buffer, buflen))
10937c478bd9Sstevel@tonic-gate 		return (NULL);
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	return (buffer);
10967c478bd9Sstevel@tonic-gate }
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate /*
10997c478bd9Sstevel@tonic-gate  * Input key length, algorithm type, and a string identifying a symbol
11007c478bd9Sstevel@tonic-gate  * (example: "__gen_dhkeys").
11017c478bd9Sstevel@tonic-gate  *
11027c478bd9Sstevel@tonic-gate  * Returns a function pointer to the specified symbol in the appropriate
11037c478bd9Sstevel@tonic-gate  * key length/algorithm type library, or NULL if the symbol isn't found.
11047c478bd9Sstevel@tonic-gate  */
11057c478bd9Sstevel@tonic-gate void *
__nis_get_mechanism_symbol(keylen_t keylen,algtype_t algtype,const char * symname)11067c478bd9Sstevel@tonic-gate __nis_get_mechanism_symbol(keylen_t keylen,
11077c478bd9Sstevel@tonic-gate 				algtype_t algtype,
11087c478bd9Sstevel@tonic-gate 				const char *symname)
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate {
11117c478bd9Sstevel@tonic-gate 	void *handle;
11127c478bd9Sstevel@tonic-gate 	char libname[MAXDHNAME+1];
11137c478bd9Sstevel@tonic-gate 	char libpath[MAXPATHLEN+1];
11147c478bd9Sstevel@tonic-gate 
111561961e0fSrobinson 	if (!__nis_get_mechanism_library(keylen, algtype, libname, MAXDHNAME))
11167c478bd9Sstevel@tonic-gate 		return (NULL);
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 	if (strlen(MECH_LIB_PREFIX) + strlen(libname) + 1 > sizeof (libpath))
11197c478bd9Sstevel@tonic-gate 		return (NULL);
11207c478bd9Sstevel@tonic-gate 
112161961e0fSrobinson 	(void) snprintf(libpath, sizeof (libpath),
112261961e0fSrobinson 					"%s%s", MECH_LIB_PREFIX, libname);
11237c478bd9Sstevel@tonic-gate 
112461961e0fSrobinson 	if (!(handle = dlopen(libpath, RTLD_LAZY)))
11257c478bd9Sstevel@tonic-gate 		return (NULL);
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	return (dlsym(handle, symname));
11287c478bd9Sstevel@tonic-gate }
1129