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