xref: /titanic_41/usr/src/cmd/fs.d/nfs/lib/nfs_sec.c (revision cd3004d2ae645166ae299c80df2060ee2ee108e1)
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
5bfa62c28SVallish Vaidyeshwara  * Common Development and Distribution License (the "License").
6bfa62c28SVallish Vaidyeshwara  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /* LINTLIBRARY */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate /*
24*cd3004d2SMarcel Telka  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
25*cd3004d2SMarcel Telka  */
26*cd3004d2SMarcel Telka 
27*cd3004d2SMarcel Telka /*
286ee094dbSVallish Vaidyeshwara  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
297c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * nfs security related library routines.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * Some of the routines in this file are adopted from
367c478bd9Sstevel@tonic-gate  * lib/libnsl/netselect/netselect.c and are modified to be
377c478bd9Sstevel@tonic-gate  * used for accessing /etc/nfssec.conf.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /* SVr4.0 1.18	*/
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <string.h>
447c478bd9Sstevel@tonic-gate #include <ctype.h>
457c478bd9Sstevel@tonic-gate #include <stdlib.h>
467c478bd9Sstevel@tonic-gate #include <syslog.h>
477c478bd9Sstevel@tonic-gate #include <synch.h>
487c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
497c478bd9Sstevel@tonic-gate #include <nfs/nfs_sec.h>
507c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
517c478bd9Sstevel@tonic-gate #ifdef WNFS_SEC_NEGO
527c478bd9Sstevel@tonic-gate #include "webnfs.h"
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #define	GETBYNAME	1
567c478bd9Sstevel@tonic-gate #define	GETBYNUM	2
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * mapping for /etc/nfssec.conf
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate struct sc_data {
627c478bd9Sstevel@tonic-gate 	char	*string;
637c478bd9Sstevel@tonic-gate 	int	value;
647c478bd9Sstevel@tonic-gate };
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static struct sc_data sc_service[] = {
677c478bd9Sstevel@tonic-gate 	"default",	rpc_gss_svc_default,
687c478bd9Sstevel@tonic-gate 	"-",		rpc_gss_svc_none,
697c478bd9Sstevel@tonic-gate 	"none",		rpc_gss_svc_none,
707c478bd9Sstevel@tonic-gate 	"integrity",	rpc_gss_svc_integrity,
717c478bd9Sstevel@tonic-gate 	"privacy",	rpc_gss_svc_privacy,
727c478bd9Sstevel@tonic-gate 	NULL,		SC_FAILURE
737c478bd9Sstevel@tonic-gate };
747c478bd9Sstevel@tonic-gate 
7503242fafSMarcel Telka static mutex_t matching_lock = DEFAULTMUTEX;
767c478bd9Sstevel@tonic-gate static char *gettoken(char *, int);
777c478bd9Sstevel@tonic-gate extern	int atoi(const char *str);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate extern	bool_t rpc_gss_get_principal_name(rpc_gss_principal_t *, char *,
807c478bd9Sstevel@tonic-gate 			char *, char *, char *);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate extern	bool_t rpc_gss_mech_to_oid(char *, rpc_gss_OID *);
837c478bd9Sstevel@tonic-gate extern	bool_t rpc_gss_qop_to_num(char *, char *, uint_t *);
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate  *  blank() returns true if the line is a blank line, 0 otherwise
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate static int
blank(cp)897c478bd9Sstevel@tonic-gate blank(cp)
907c478bd9Sstevel@tonic-gate char *cp;
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
937c478bd9Sstevel@tonic-gate 		cp++;
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 	return (*cp == '\0');
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  *  comment() returns true if the line is a comment, 0 otherwise.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate static int
comment(cp)1027c478bd9Sstevel@tonic-gate comment(cp)
1037c478bd9Sstevel@tonic-gate char *cp;
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
1067c478bd9Sstevel@tonic-gate 		cp++;
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 	return (*cp == '#');
1097c478bd9Sstevel@tonic-gate }
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate  *	getvalue() searches for the given string in the given array,
1147c478bd9Sstevel@tonic-gate  *	and returns the integer value associated with the string.
1157c478bd9Sstevel@tonic-gate  */
1167c478bd9Sstevel@tonic-gate static unsigned long
getvalue(cp,sc_data)1177c478bd9Sstevel@tonic-gate getvalue(cp, sc_data)
1187c478bd9Sstevel@tonic-gate char *cp;
1197c478bd9Sstevel@tonic-gate struct sc_data sc_data[];
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	int i;	/* used to index through the given struct sc_data array */
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	for (i = 0; sc_data[i].string; i++) {
1247c478bd9Sstevel@tonic-gate 		if (strcmp(sc_data[i].string, cp) == 0) {
1257c478bd9Sstevel@tonic-gate 			break;
1267c478bd9Sstevel@tonic-gate 		}
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 	return (sc_data[i].value);
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  *	shift1left() moves all characters in the string over 1 to
1337c478bd9Sstevel@tonic-gate  *	the left.
1347c478bd9Sstevel@tonic-gate  */
1357c478bd9Sstevel@tonic-gate static void
shift1left(p)1367c478bd9Sstevel@tonic-gate shift1left(p)
1377c478bd9Sstevel@tonic-gate char *p;
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	for (; *p; p++)
1407c478bd9Sstevel@tonic-gate 		*p = *(p + 1);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  *	gettoken() behaves much like strtok(), except that
1467c478bd9Sstevel@tonic-gate  *	it knows about escaped space characters (i.e., space characters
1477c478bd9Sstevel@tonic-gate  *	preceeded by a '\' are taken literally).
1487c478bd9Sstevel@tonic-gate  *
1497c478bd9Sstevel@tonic-gate  *	XXX We should make this MT-hot by making it more like strtok_r().
1507c478bd9Sstevel@tonic-gate  */
1517c478bd9Sstevel@tonic-gate static char *
gettoken(cp,skip)1527c478bd9Sstevel@tonic-gate gettoken(cp, skip)
1537c478bd9Sstevel@tonic-gate char	*cp;
1547c478bd9Sstevel@tonic-gate int skip;
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	static char	*savep;	/* the place where we left off    */
1577c478bd9Sstevel@tonic-gate 	register char	*p;	/* the beginning of the new token */
1587c478bd9Sstevel@tonic-gate 	register char	*retp;	/* the token to be returned	  */
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/* Determine if first or subsequent call  */
1627c478bd9Sstevel@tonic-gate 	p = (cp == NULL)? savep: cp;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	/* Return if no tokens remain.  */
1657c478bd9Sstevel@tonic-gate 	if (p == 0) {
1667c478bd9Sstevel@tonic-gate 		return (NULL);
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	while (isspace(*p))
1707c478bd9Sstevel@tonic-gate 		p++;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
1737c478bd9Sstevel@tonic-gate 		return (NULL);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/*
1777c478bd9Sstevel@tonic-gate 	 *	Save the location of the token and then skip past it
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	retp = p;
1817c478bd9Sstevel@tonic-gate 	while (*p) {
182*cd3004d2SMarcel Telka 		if (isspace(*p)) {
1837c478bd9Sstevel@tonic-gate 			if (skip == TRUE) {
1847c478bd9Sstevel@tonic-gate 				shift1left(p);
1857c478bd9Sstevel@tonic-gate 				continue;
1867c478bd9Sstevel@tonic-gate 			} else
1877c478bd9Sstevel@tonic-gate 				break;
188*cd3004d2SMarcel Telka 		}
189*cd3004d2SMarcel Telka 
1907c478bd9Sstevel@tonic-gate 		/*
1917c478bd9Sstevel@tonic-gate 		 *	Only process the escape of the space separator;
1927c478bd9Sstevel@tonic-gate 		 *	since the token may contain other separators,
1937c478bd9Sstevel@tonic-gate 		 *	let the other routines handle the escape of
1947c478bd9Sstevel@tonic-gate 		 *	specific characters in the token.
1957c478bd9Sstevel@tonic-gate 		 */
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 		if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
1987c478bd9Sstevel@tonic-gate 			shift1left(p);
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 		p++;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	if (*p == '\0') {
2037c478bd9Sstevel@tonic-gate 		savep = 0;	/* indicate this is last token */
2047c478bd9Sstevel@tonic-gate 	} else {
2057c478bd9Sstevel@tonic-gate 		*p = '\0';
2067c478bd9Sstevel@tonic-gate 		savep = ++p;
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	return (retp);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate /*
2127c478bd9Sstevel@tonic-gate  *  matchname() parses a line of the /etc/nfssec.conf file
2137c478bd9Sstevel@tonic-gate  *  and match the sc_name with the given name.
2147c478bd9Sstevel@tonic-gate  *  If there is a match, it fills the information into the given
2157c478bd9Sstevel@tonic-gate  *  pointer of the seconfig_t structure.
2167c478bd9Sstevel@tonic-gate  *
2177c478bd9Sstevel@tonic-gate  *  Returns TRUE if a match is found.
2187c478bd9Sstevel@tonic-gate  */
2197c478bd9Sstevel@tonic-gate static bool_t
matchname(char * line,char * name,seconfig_t * secp)2207c478bd9Sstevel@tonic-gate matchname(char *line, char *name, seconfig_t *secp)
2217c478bd9Sstevel@tonic-gate {
2227c478bd9Sstevel@tonic-gate 	char	*tok1,	*tok2;	/* holds a token from the line */
2237c478bd9Sstevel@tonic-gate 	char	*secname, *gss_mech, *gss_qop; /* pointer to a secmode name */
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	if ((secname = gettoken(line, FALSE)) == NULL) {
2267c478bd9Sstevel@tonic-gate 		/* bad line */
2277c478bd9Sstevel@tonic-gate 		return (FALSE);
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (strcmp(secname, name) != 0) {
2317c478bd9Sstevel@tonic-gate 		return (FALSE);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	tok1 = tok2 = NULL;
2357c478bd9Sstevel@tonic-gate 	if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
2367c478bd9Sstevel@tonic-gate 	    ((gss_mech = gettoken(NULL, FALSE)) == NULL) ||
2377c478bd9Sstevel@tonic-gate 	    ((gss_qop = gettoken(NULL, FALSE)) == NULL) ||
2387c478bd9Sstevel@tonic-gate 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
2397c478bd9Sstevel@tonic-gate 	    ((secp->sc_service = getvalue(tok2, sc_service))
2407c478bd9Sstevel@tonic-gate 	    == SC_FAILURE)) {
2417c478bd9Sstevel@tonic-gate 		return (FALSE);
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 	secp->sc_nfsnum = atoi(tok1);
2447c478bd9Sstevel@tonic-gate 	(void) strcpy(secp->sc_name, secname);
2457c478bd9Sstevel@tonic-gate 	(void) strcpy(secp->sc_gss_mech, gss_mech);
2467c478bd9Sstevel@tonic-gate 	secp->sc_gss_mech_type = NULL;
2477c478bd9Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
2487c478bd9Sstevel@tonic-gate 		if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) ||
2497c478bd9Sstevel@tonic-gate 		    !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) {
2507c478bd9Sstevel@tonic-gate 			return (FALSE);
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	return (TRUE);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  *  matchnum() parses a line of the /etc/nfssec.conf file
2597c478bd9Sstevel@tonic-gate  *  and match the sc_nfsnum with the given number.
2607c478bd9Sstevel@tonic-gate  *  If it is a match, it fills the information in the given pointer
2617c478bd9Sstevel@tonic-gate  *  of the seconfig_t structure.
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  *  Returns TRUE if a match is found.
2647c478bd9Sstevel@tonic-gate  */
2657c478bd9Sstevel@tonic-gate static bool_t
matchnum(char * line,int num,seconfig_t * secp)2667c478bd9Sstevel@tonic-gate matchnum(char *line, int num, seconfig_t *secp)
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate 	char	*tok1,	*tok2;	/* holds a token from the line */
2697c478bd9Sstevel@tonic-gate 	char	*secname, *gss_mech, *gss_qop;	/* pointer to a secmode name */
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	if ((secname = gettoken(line, FALSE)) == NULL) {
2727c478bd9Sstevel@tonic-gate 		/* bad line */
2737c478bd9Sstevel@tonic-gate 		return (FALSE);
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	tok1 = tok2 = NULL;
2777c478bd9Sstevel@tonic-gate 	if ((tok1 = gettoken(NULL, FALSE)) == NULL) {
2787c478bd9Sstevel@tonic-gate 		/* bad line */
2797c478bd9Sstevel@tonic-gate 		return (FALSE);
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if ((secp->sc_nfsnum = atoi(tok1)) != num) {
2837c478bd9Sstevel@tonic-gate 		return (FALSE);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	if (((gss_mech = gettoken(NULL, FALSE)) == NULL) ||
2877c478bd9Sstevel@tonic-gate 	    ((gss_qop = gettoken(NULL, FALSE)) == NULL) ||
2887c478bd9Sstevel@tonic-gate 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
2897c478bd9Sstevel@tonic-gate 	    ((secp->sc_service = getvalue(tok2, sc_service))
2907c478bd9Sstevel@tonic-gate 	    == SC_FAILURE)) {
2917c478bd9Sstevel@tonic-gate 		return (FALSE);
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	(void) strcpy(secp->sc_name, secname);
2957c478bd9Sstevel@tonic-gate 	(void) strcpy(secp->sc_gss_mech, gss_mech);
2967c478bd9Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
2977c478bd9Sstevel@tonic-gate 		if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) ||
2987c478bd9Sstevel@tonic-gate 		    !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) {
2997c478bd9Sstevel@tonic-gate 			return (FALSE);
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	return (TRUE);
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate  *  Fill in the RPC Protocol security flavor number
3087c478bd9Sstevel@tonic-gate  *  into the sc_rpcnum of seconfig_t structure.
3097c478bd9Sstevel@tonic-gate  *
3107c478bd9Sstevel@tonic-gate  *  Mainly to map NFS secmod number to RPCSEC_GSS if
3117c478bd9Sstevel@tonic-gate  *  a mechanism name is specified.
3127c478bd9Sstevel@tonic-gate  */
3137c478bd9Sstevel@tonic-gate static void
get_rpcnum(seconfig_t * secp)3147c478bd9Sstevel@tonic-gate get_rpcnum(seconfig_t *secp)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
3177c478bd9Sstevel@tonic-gate 		secp->sc_rpcnum = RPCSEC_GSS;
3187c478bd9Sstevel@tonic-gate 	} else {
3197c478bd9Sstevel@tonic-gate 		secp->sc_rpcnum = secp->sc_nfsnum;
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate /*
3247c478bd9Sstevel@tonic-gate  *  Parse a given hostname (nodename[.domain@realm]) to
3257c478bd9Sstevel@tonic-gate  *  instant name (nodename[.domain]) and realm.
3267c478bd9Sstevel@tonic-gate  *
3277c478bd9Sstevel@tonic-gate  *  Assuming user has allocated the space for inst and realm.
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate static int
parsehostname(char * hostname,char * inst,char * realm)3307c478bd9Sstevel@tonic-gate parsehostname(char *hostname, char *inst, char *realm)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	char *h, *r;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	if (!hostname)
3357c478bd9Sstevel@tonic-gate 		return (0);
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	h = (char *)strdup(hostname);
3387c478bd9Sstevel@tonic-gate 	if (!h) {
3397c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "parsehostname: no memory\n");
3407c478bd9Sstevel@tonic-gate 		return (0);
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	r = (char *)strchr(h, '@');
3447c478bd9Sstevel@tonic-gate 	if (!r) {
3457c478bd9Sstevel@tonic-gate 		(void) strcpy(inst, h);
3467c478bd9Sstevel@tonic-gate 		(void) strcpy(realm, "");
3477c478bd9Sstevel@tonic-gate 	} else {
3487c478bd9Sstevel@tonic-gate 		*r++ = '\0';
3497c478bd9Sstevel@tonic-gate 		(void) strcpy(inst, h);
3507c478bd9Sstevel@tonic-gate 		(void) strcpy(realm, r);
3517c478bd9Sstevel@tonic-gate 	}
3527c478bd9Sstevel@tonic-gate 	free(h);
3537c478bd9Sstevel@tonic-gate 	return (1);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate  *  Get the name corresponding to a qop num.
3587c478bd9Sstevel@tonic-gate  */
3597c478bd9Sstevel@tonic-gate char *
nfs_get_qop_name(seconfig_t * entryp)3607c478bd9Sstevel@tonic-gate nfs_get_qop_name(seconfig_t *entryp)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	char	*tok;	/* holds a token from the line */
3637c478bd9Sstevel@tonic-gate 	char	*secname, *gss_qop = NULL; /* pointer to a secmode name */
3647c478bd9Sstevel@tonic-gate 	char	line[BUFSIZ];	/* holds each line of NFSSEC_CONF */
3657c478bd9Sstevel@tonic-gate 	FILE	*fp;		/* file stream for NFSSEC_CONF */
3667c478bd9Sstevel@tonic-gate 
36703242fafSMarcel Telka 	(void) mutex_lock(&matching_lock);
3687c478bd9Sstevel@tonic-gate 	if ((fp = fopen(NFSSEC_CONF, "r")) == NULL) {
36903242fafSMarcel Telka 		(void) mutex_unlock(&matching_lock);
3707c478bd9Sstevel@tonic-gate 		return (NULL);
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	while (fgets(line, BUFSIZ, fp)) {
3747c478bd9Sstevel@tonic-gate 		if (!(blank(line) || comment(line))) {
3757c478bd9Sstevel@tonic-gate 			if ((secname = gettoken(line, FALSE)) == NULL) {
3767c478bd9Sstevel@tonic-gate 				/* bad line */
3777c478bd9Sstevel@tonic-gate 				continue;
3787c478bd9Sstevel@tonic-gate 			}
3797c478bd9Sstevel@tonic-gate 			if (strcmp(secname, entryp->sc_name) == 0) {
3807c478bd9Sstevel@tonic-gate 				tok = NULL;
3817c478bd9Sstevel@tonic-gate 				if ((tok = gettoken(NULL, FALSE)) == NULL) {
3827c478bd9Sstevel@tonic-gate 					/* bad line */
3837c478bd9Sstevel@tonic-gate 					goto err;
3847c478bd9Sstevel@tonic-gate 				}
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 				if (atoi(tok) != entryp->sc_nfsnum)
3877c478bd9Sstevel@tonic-gate 					goto err;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 				if ((gettoken(NULL, FALSE) == NULL) ||
390bfa62c28SVallish Vaidyeshwara 				    ((gss_qop = gettoken(NULL, FALSE))
391bfa62c28SVallish Vaidyeshwara 				    == NULL)) {
3927c478bd9Sstevel@tonic-gate 					goto err;
3937c478bd9Sstevel@tonic-gate 				}
3947c478bd9Sstevel@tonic-gate 				break;
3957c478bd9Sstevel@tonic-gate 			}
3967c478bd9Sstevel@tonic-gate 		}
3977c478bd9Sstevel@tonic-gate 	}
3987c478bd9Sstevel@tonic-gate err:
3997c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
40003242fafSMarcel Telka 	(void) mutex_unlock(&matching_lock);
4017c478bd9Sstevel@tonic-gate 	return (gss_qop);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate  * This routine creates an auth handle assocaited with the
4067c478bd9Sstevel@tonic-gate  * negotiated security flavor contained in nfs_sec.  The auth
4077c478bd9Sstevel@tonic-gate  * handle will be used in the next LOOKUP request to fetch
4087c478bd9Sstevel@tonic-gate  * the filehandle.
4097c478bd9Sstevel@tonic-gate  */
4107c478bd9Sstevel@tonic-gate AUTH *
nfs_create_ah(CLIENT * cl,char * hostname,seconfig_t * nfs_sec)4117c478bd9Sstevel@tonic-gate nfs_create_ah(CLIENT *cl, char *hostname, seconfig_t *nfs_sec)
4127c478bd9Sstevel@tonic-gate {
4137c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
4147c478bd9Sstevel@tonic-gate 	char svc_name[MAXNETNAMELEN+1];
4157c478bd9Sstevel@tonic-gate 	char *gss_qop;
4167c478bd9Sstevel@tonic-gate 	static int window = 60;
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	if (nfs_sec == NULL)
4197c478bd9Sstevel@tonic-gate 		goto err;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	switch (nfs_sec->sc_rpcnum) {
4227c478bd9Sstevel@tonic-gate 		case AUTH_UNIX:
4237c478bd9Sstevel@tonic-gate 		case AUTH_NONE:
4247c478bd9Sstevel@tonic-gate 			return (NULL);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 		case AUTH_DES:
4277c478bd9Sstevel@tonic-gate 			if (!host2netname(netname, hostname, NULL))
4287c478bd9Sstevel@tonic-gate 				goto err;
4297c478bd9Sstevel@tonic-gate 
430bfa62c28SVallish Vaidyeshwara 			return (authdes_seccreate(netname, window, hostname,
431bfa62c28SVallish Vaidyeshwara 			    NULL));
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 		case RPCSEC_GSS:
4347c478bd9Sstevel@tonic-gate 			if (cl == NULL)
4357c478bd9Sstevel@tonic-gate 				goto err;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 			if (nfs_sec->sc_gss_mech_type == NULL) {
4387c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
4397c478bd9Sstevel@tonic-gate 				"nfs_create_ah: need mechanism information\n");
4407c478bd9Sstevel@tonic-gate 				goto err;
4417c478bd9Sstevel@tonic-gate 			}
4427c478bd9Sstevel@tonic-gate 
443bfa62c28SVallish Vaidyeshwara 			/*
444bfa62c28SVallish Vaidyeshwara 			 * RPCSEC_GSS service names are of the form svc@host.dom
445bfa62c28SVallish Vaidyeshwara 			 */
4467c478bd9Sstevel@tonic-gate 			(void) sprintf(svc_name, "nfs@%s", hostname);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 			gss_qop = nfs_get_qop_name(nfs_sec);
4497c478bd9Sstevel@tonic-gate 			if (gss_qop == NULL)
4507c478bd9Sstevel@tonic-gate 				goto err;
4517c478bd9Sstevel@tonic-gate 
452bfa62c28SVallish Vaidyeshwara 			return (rpc_gss_seccreate(cl, svc_name,
453bfa62c28SVallish Vaidyeshwara 			    nfs_sec->sc_gss_mech, nfs_sec->sc_service, gss_qop,
454bfa62c28SVallish Vaidyeshwara 			    NULL, NULL));
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		default:
4577c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "nfs_create_ah: unknown flavor\n");
4587c478bd9Sstevel@tonic-gate 			return (NULL);
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate err:
4617c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "nfs_create_ah: failed to make auth handle\n");
4627c478bd9Sstevel@tonic-gate 	return (NULL);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate #ifdef WNFS_SEC_NEGO
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * This routine negotiates sec flavors with server and returns:
4687c478bd9Sstevel@tonic-gate  *	SNEGO_SUCCESS:		successful; sec flavors are
4697c478bd9Sstevel@tonic-gate  *				returned in snego,
4707c478bd9Sstevel@tonic-gate  *	SNEGO_DEF_VALID:	default sec flavor valid; no need
4717c478bd9Sstevel@tonic-gate  *				to negotiate flavors,
4727c478bd9Sstevel@tonic-gate  *	SNEGO_ARRAY_TOO_SMALL:	array too small,
4737c478bd9Sstevel@tonic-gate  *	SNEGO_FAILURE:		failure
4747c478bd9Sstevel@tonic-gate  */
4757c478bd9Sstevel@tonic-gate /*
4767c478bd9Sstevel@tonic-gate  * The following depicts how sec flavors are placed in an
4777c478bd9Sstevel@tonic-gate  * overloaded V2 fhandle:
4787c478bd9Sstevel@tonic-gate  *
4797c478bd9Sstevel@tonic-gate  * Note that the first four octets contain the length octet,
4807c478bd9Sstevel@tonic-gate  * the status octet, and two padded octets to make them XDR
4817c478bd9Sstevel@tonic-gate  * four-octet aligned.
4827c478bd9Sstevel@tonic-gate  *
4837c478bd9Sstevel@tonic-gate  *   1   2   3   4                                          32
4847c478bd9Sstevel@tonic-gate  * +---+---+---+---+---+---+---+---+   +---+---+---+---+   +---+
4857c478bd9Sstevel@tonic-gate  * | l | s |   |   |     sec_1     |...|     sec_n     |...|   |
4867c478bd9Sstevel@tonic-gate  * +---+---+---+---+---+---+---+---+   +---+---+---+---+   +---+
4877c478bd9Sstevel@tonic-gate  *
4887c478bd9Sstevel@tonic-gate  * where
4897c478bd9Sstevel@tonic-gate  *
4907c478bd9Sstevel@tonic-gate  *   the status octet s indicates whether there are more security
4917c478bd9Sstevel@tonic-gate  *   flavors(1 means yes, 0 means no) that require the client to
4927c478bd9Sstevel@tonic-gate  *   perform another 0x81 LOOKUP to get them,
4937c478bd9Sstevel@tonic-gate  *
4947c478bd9Sstevel@tonic-gate  *   the length octet l is the length describing the number of
4957c478bd9Sstevel@tonic-gate  *   valid octets that follow.  (l = 4 * n, where n is the number
4967c478bd9Sstevel@tonic-gate  *
4977c478bd9Sstevel@tonic-gate  * The following depicts how sec flavors are placed in an
4987c478bd9Sstevel@tonic-gate  * overloaded V3 fhandle:
4997c478bd9Sstevel@tonic-gate  *
5007c478bd9Sstevel@tonic-gate  *  1        4
5017c478bd9Sstevel@tonic-gate  * +--+--+--+--+
5027c478bd9Sstevel@tonic-gate  * |    len    |
5037c478bd9Sstevel@tonic-gate  * +--+--+--+--+
5047c478bd9Sstevel@tonic-gate  *                                               up to 64
5057c478bd9Sstevel@tonic-gate  * +--+--+--+--+--+--+--+--+--+--+--+--+     +--+--+--+--+
5067c478bd9Sstevel@tonic-gate  * |s |  |  |  |   sec_1   |   sec_2   | ... |   sec_n   |
5077c478bd9Sstevel@tonic-gate  * +--+--+--+--+--+--+--+--+--+--+--+--+     +--+--+--+--+
5087c478bd9Sstevel@tonic-gate  *
5097c478bd9Sstevel@tonic-gate  * len = 4 * (n+1), where n is the number of security flavors
5107c478bd9Sstevel@tonic-gate  * sent in the current overloaded filehandle.
5117c478bd9Sstevel@tonic-gate  *
5127c478bd9Sstevel@tonic-gate  * the status octet s indicates whether there are more security
5137c478bd9Sstevel@tonic-gate  * mechanisms(1 means yes, 0 means no) that require the client
5147c478bd9Sstevel@tonic-gate  * to perform another 0x81 LOOKUP to get them.
5157c478bd9Sstevel@tonic-gate  *
5167c478bd9Sstevel@tonic-gate  * Three octets are padded after the status octet.
5177c478bd9Sstevel@tonic-gate  */
5187c478bd9Sstevel@tonic-gate enum snego_stat
nfs_sec_nego(rpcprog_t vers,CLIENT * clnt,char * fspath,struct snego_t * snego)5197c478bd9Sstevel@tonic-gate nfs_sec_nego(rpcprog_t vers, CLIENT *clnt, char *fspath, struct snego_t *snego)
5207c478bd9Sstevel@tonic-gate {
5217c478bd9Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
5227c478bd9Sstevel@tonic-gate 	static int MAX_V2_CNT = (WNL_FHSIZE/sizeof (int)) - 1;
5237c478bd9Sstevel@tonic-gate 	static int MAX_V3_CNT = (WNL3_FHSIZE/sizeof (int)) - 1;
5247c478bd9Sstevel@tonic-gate 	static struct timeval TIMEOUT = { 25, 0 };
5257c478bd9Sstevel@tonic-gate 	int status;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	if (clnt == NULL || fspath == NULL || snego == NULL)
5287c478bd9Sstevel@tonic-gate 		return (SNEGO_FAILURE);
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if (vers == WNL_V2) {
5317c478bd9Sstevel@tonic-gate 		wnl_diropargs arg;
5327c478bd9Sstevel@tonic-gate 		wnl_diropres clnt_res;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 		memset((char *)&arg.dir, 0, sizeof (wnl_fh));
5357c478bd9Sstevel@tonic-gate 		arg.name = fspath;
5367c478bd9Sstevel@tonic-gate 		memset((char *)&clnt_res, 0, sizeof (clnt_res));
5377c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(clnt, WNLPROC_LOOKUP,
5387c478bd9Sstevel@tonic-gate 		    (xdrproc_t)xdr_wnl_diropargs, (caddr_t)&arg,
5397c478bd9Sstevel@tonic-gate 		    (xdrproc_t)xdr_wnl_diropres, (caddr_t)&clnt_res,
5407c478bd9Sstevel@tonic-gate 		    TIMEOUT);
5417c478bd9Sstevel@tonic-gate 		if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL_OK)
5427c478bd9Sstevel@tonic-gate 			return (SNEGO_DEF_VALID);
5437c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_AUTHERROR)
5447c478bd9Sstevel@tonic-gate 			return (SNEGO_FAILURE);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		{
5477c478bd9Sstevel@tonic-gate 			struct rpc_err e;
548bfa62c28SVallish Vaidyeshwara 			wnl_diropres res;
5497c478bd9Sstevel@tonic-gate 			char *p;
5507c478bd9Sstevel@tonic-gate 			int tot = 0;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 			CLNT_GETERR(clnt, &e);
5537c478bd9Sstevel@tonic-gate 			if (e.re_why != AUTH_TOOWEAK)
5547c478bd9Sstevel@tonic-gate 				return (SNEGO_FAILURE);
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 			if ((p = malloc(strlen(fspath)+3)) == NULL) {
5577c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "no memory\n");
5587c478bd9Sstevel@tonic-gate 				return (SNEGO_FAILURE);
5597c478bd9Sstevel@tonic-gate 			}
5607c478bd9Sstevel@tonic-gate 			/*
5617c478bd9Sstevel@tonic-gate 			 * Do an x81 LOOKUP
5627c478bd9Sstevel@tonic-gate 			 */
5637c478bd9Sstevel@tonic-gate 			p[0] = (char)WNL_SEC_NEGO;
5647c478bd9Sstevel@tonic-gate 			strcpy(&p[2], fspath);
5657c478bd9Sstevel@tonic-gate 			do {
5667c478bd9Sstevel@tonic-gate 				p[1] = (char)(1+snego->cnt); /* sec index */
5677c478bd9Sstevel@tonic-gate 				arg.name = p;
568bfa62c28SVallish Vaidyeshwara 				memset((char *)&res, 0, sizeof (wnl_diropres));
569bfa62c28SVallish Vaidyeshwara 				if (wnlproc_lookup_2(&arg, &res, clnt) !=
570bfa62c28SVallish Vaidyeshwara 				    RPC_SUCCESS || res.status != WNL_OK) {
5717c478bd9Sstevel@tonic-gate 					free(p);
5727c478bd9Sstevel@tonic-gate 					return (SNEGO_FAILURE);
5737c478bd9Sstevel@tonic-gate 				}
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 				/*
5767c478bd9Sstevel@tonic-gate 				 * retrieve flavors from filehandle:
5777c478bd9Sstevel@tonic-gate 				 *	1st byte: length
5787c478bd9Sstevel@tonic-gate 				 *	2nd byte: status
5797c478bd9Sstevel@tonic-gate 				 *	3rd & 4th: pad
5807c478bd9Sstevel@tonic-gate 				 *	5th and after: sec flavors.
5817c478bd9Sstevel@tonic-gate 				 */
5827c478bd9Sstevel@tonic-gate 				{
583bfa62c28SVallish Vaidyeshwara 					char *c = (char *)&res.wnl_diropres_u.
5847c478bd9Sstevel@tonic-gate 					    wnl_diropres.file;
5857c478bd9Sstevel@tonic-gate 					int ii;
5867c478bd9Sstevel@tonic-gate 					int cnt = ((int)*c)/sizeof (uint_t);
5877c478bd9Sstevel@tonic-gate 					/* LINTED pointer alignment */
5887c478bd9Sstevel@tonic-gate 					int *ip = (int *)(c+sizeof (int));
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 					tot += cnt;
5917c478bd9Sstevel@tonic-gate 					if (tot >= MAX_FLAVORS) {
5927c478bd9Sstevel@tonic-gate 						free(p);
5937c478bd9Sstevel@tonic-gate 						return (SNEGO_ARRAY_TOO_SMALL);
5947c478bd9Sstevel@tonic-gate 					}
5957c478bd9Sstevel@tonic-gate 					status = (int)*(c+1);
5967c478bd9Sstevel@tonic-gate 					if (cnt > MAX_V2_CNT || cnt < 0) {
5977c478bd9Sstevel@tonic-gate 						free(p);
5987c478bd9Sstevel@tonic-gate 						return (SNEGO_FAILURE);
5997c478bd9Sstevel@tonic-gate 					}
6007c478bd9Sstevel@tonic-gate 					for (ii = 0; ii < cnt; ii++)
6017c478bd9Sstevel@tonic-gate 						snego->array[snego->cnt+ii] =
6027c478bd9Sstevel@tonic-gate 						    ntohl(*(ip+ii));
6037c478bd9Sstevel@tonic-gate 					snego->cnt += cnt;
6047c478bd9Sstevel@tonic-gate 				}
6057c478bd9Sstevel@tonic-gate 			} while (status);
6067c478bd9Sstevel@tonic-gate 			free(p);
6077c478bd9Sstevel@tonic-gate 			return (SNEGO_SUCCESS);
6087c478bd9Sstevel@tonic-gate 		}
6097c478bd9Sstevel@tonic-gate 	} else if (vers == WNL_V3) {
6107c478bd9Sstevel@tonic-gate 		WNL_LOOKUP3args arg;
6117c478bd9Sstevel@tonic-gate 		WNL_LOOKUP3res clnt_res;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 		memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
6147c478bd9Sstevel@tonic-gate 		arg.what.name = fspath;
6157c478bd9Sstevel@tonic-gate 		arg.what.dir.data.data_len = 0;
6167c478bd9Sstevel@tonic-gate 		arg.what.dir.data.data_val = 0;
6177c478bd9Sstevel@tonic-gate 		memset((char *)&clnt_res, 0, sizeof (clnt_res));
6187c478bd9Sstevel@tonic-gate 		rpc_stat = clnt_call(clnt, WNLPROC3_LOOKUP,
6197c478bd9Sstevel@tonic-gate 		    (xdrproc_t)xdr_WNL_LOOKUP3args, (caddr_t)&arg,
6207c478bd9Sstevel@tonic-gate 		    (xdrproc_t)xdr_WNL_LOOKUP3res, (caddr_t)&clnt_res,
6217c478bd9Sstevel@tonic-gate 		    TIMEOUT);
6227c478bd9Sstevel@tonic-gate 		if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL3_OK)
6237c478bd9Sstevel@tonic-gate 			return (SNEGO_DEF_VALID);
6247c478bd9Sstevel@tonic-gate 		if (rpc_stat != RPC_AUTHERROR)
6257c478bd9Sstevel@tonic-gate 			return (SNEGO_FAILURE);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 		{
6287c478bd9Sstevel@tonic-gate 			struct rpc_err e;
629bfa62c28SVallish Vaidyeshwara 			WNL_LOOKUP3res res;
6307c478bd9Sstevel@tonic-gate 			char *p;
6317c478bd9Sstevel@tonic-gate 			int tot = 0;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 			CLNT_GETERR(clnt, &e);
6347c478bd9Sstevel@tonic-gate 			if (e.re_why != AUTH_TOOWEAK)
6357c478bd9Sstevel@tonic-gate 				return (SNEGO_FAILURE);
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 			if ((p = malloc(strlen(fspath)+3)) == NULL) {
6387c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "no memory\n");
6397c478bd9Sstevel@tonic-gate 				return (SNEGO_FAILURE);
6407c478bd9Sstevel@tonic-gate 			}
6417c478bd9Sstevel@tonic-gate 			/*
6427c478bd9Sstevel@tonic-gate 			 * Do an x81 LOOKUP
6437c478bd9Sstevel@tonic-gate 			 */
6447c478bd9Sstevel@tonic-gate 			p[0] = (char)WNL_SEC_NEGO;
6457c478bd9Sstevel@tonic-gate 			strcpy(&p[2], fspath);
6467c478bd9Sstevel@tonic-gate 			do {
6477c478bd9Sstevel@tonic-gate 				p[1] = (char)(1+snego->cnt); /* sec index */
6487c478bd9Sstevel@tonic-gate 				arg.what.name = p;
649bfa62c28SVallish Vaidyeshwara 				memset((char *)&res, 0,
650bfa62c28SVallish Vaidyeshwara 				    sizeof (WNL_LOOKUP3res));
651bfa62c28SVallish Vaidyeshwara 				if (wnlproc3_lookup_3(&arg, &res, clnt) !=
652bfa62c28SVallish Vaidyeshwara 				    RPC_SUCCESS || res.status != WNL3_OK) {
6537c478bd9Sstevel@tonic-gate 					free(p);
6547c478bd9Sstevel@tonic-gate 					return (SNEGO_FAILURE);
6557c478bd9Sstevel@tonic-gate 				}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 				/*
6587c478bd9Sstevel@tonic-gate 				 * retrieve flavors from filehandle:
6597c478bd9Sstevel@tonic-gate 				 *
6607c478bd9Sstevel@tonic-gate 				 * 1st byte: status
6617c478bd9Sstevel@tonic-gate 				 * 2nd thru 4th: pad
6627c478bd9Sstevel@tonic-gate 				 * 5th and after: sec flavors.
6637c478bd9Sstevel@tonic-gate 				 */
6647c478bd9Sstevel@tonic-gate 				{
6656ee094dbSVallish Vaidyeshwara 					char *c = res.WNL_LOOKUP3res_u.
666bfa62c28SVallish Vaidyeshwara 					    res_ok.object.data.data_val;
6677c478bd9Sstevel@tonic-gate 					int ii;
668bfa62c28SVallish Vaidyeshwara 					int len = res.WNL_LOOKUP3res_u.res_ok.
6697c478bd9Sstevel@tonic-gate 					    object.data.data_len;
6707c478bd9Sstevel@tonic-gate 					int cnt;
6717c478bd9Sstevel@tonic-gate 					/* LINTED pointer alignment */
6727c478bd9Sstevel@tonic-gate 					int *ip = (int *)(c+sizeof (int));
6737c478bd9Sstevel@tonic-gate 
6747c478bd9Sstevel@tonic-gate 					cnt = len/sizeof (uint_t) - 1;
6757c478bd9Sstevel@tonic-gate 					tot += cnt;
6767c478bd9Sstevel@tonic-gate 					if (tot >= MAX_FLAVORS) {
6777c478bd9Sstevel@tonic-gate 						free(p);
6787c478bd9Sstevel@tonic-gate 						return (SNEGO_ARRAY_TOO_SMALL);
6797c478bd9Sstevel@tonic-gate 					}
6807c478bd9Sstevel@tonic-gate 					status = (int)(*c);
6817c478bd9Sstevel@tonic-gate 					if (cnt > MAX_V3_CNT || cnt < 0) {
6827c478bd9Sstevel@tonic-gate 						free(p);
6837c478bd9Sstevel@tonic-gate 						return (SNEGO_FAILURE);
6847c478bd9Sstevel@tonic-gate 					}
6857c478bd9Sstevel@tonic-gate 					for (ii = 0; ii < cnt; ii++)
6867c478bd9Sstevel@tonic-gate 						snego->array[snego->cnt+ii] =
6877c478bd9Sstevel@tonic-gate 						    ntohl(*(ip+ii));
6887c478bd9Sstevel@tonic-gate 					snego->cnt += cnt;
6897c478bd9Sstevel@tonic-gate 				}
6907c478bd9Sstevel@tonic-gate 			} while (status);
6917c478bd9Sstevel@tonic-gate 			free(p);
6927c478bd9Sstevel@tonic-gate 			return (SNEGO_SUCCESS);
6937c478bd9Sstevel@tonic-gate 		}
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 	return (SNEGO_FAILURE);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate #endif
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  *  Get seconfig from /etc/nfssec.conf by name or by number or
7017c478bd9Sstevel@tonic-gate  *  by descriptior.
7027c478bd9Sstevel@tonic-gate  */
7037c478bd9Sstevel@tonic-gate /* ARGSUSED */
7047c478bd9Sstevel@tonic-gate static int
get_seconfig(int whichway,char * name,int num,rpc_gss_service_t service,seconfig_t * entryp)7057c478bd9Sstevel@tonic-gate get_seconfig(int whichway, char *name, int num,
7067c478bd9Sstevel@tonic-gate 		rpc_gss_service_t service, seconfig_t *entryp)
7077c478bd9Sstevel@tonic-gate {
7087c478bd9Sstevel@tonic-gate 	char	line[BUFSIZ];	/* holds each line of NFSSEC_CONF */
7097c478bd9Sstevel@tonic-gate 	FILE	*fp;		/* file stream for NFSSEC_CONF */
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	if ((whichway == GETBYNAME) && (name == NULL))
7127c478bd9Sstevel@tonic-gate 		return (SC_NOTFOUND);
7137c478bd9Sstevel@tonic-gate 
71403242fafSMarcel Telka 	(void) mutex_lock(&matching_lock);
7157c478bd9Sstevel@tonic-gate 	if ((fp = fopen(NFSSEC_CONF, "r")) == NULL) {
71603242fafSMarcel Telka 		(void) mutex_unlock(&matching_lock);
7177c478bd9Sstevel@tonic-gate 		return (SC_OPENFAIL);
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	while (fgets(line, BUFSIZ, fp)) {
7217c478bd9Sstevel@tonic-gate 		if (!(blank(line) || comment(line))) {
7227c478bd9Sstevel@tonic-gate 			switch (whichway) {
7237c478bd9Sstevel@tonic-gate 				case GETBYNAME:
7247c478bd9Sstevel@tonic-gate 					if (matchname(line, name, entryp)) {
7257c478bd9Sstevel@tonic-gate 						goto found;
7267c478bd9Sstevel@tonic-gate 					}
7277c478bd9Sstevel@tonic-gate 					break;
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 				case GETBYNUM:
7307c478bd9Sstevel@tonic-gate 					if (matchnum(line, num, entryp)) {
7317c478bd9Sstevel@tonic-gate 						goto found;
7327c478bd9Sstevel@tonic-gate 					}
7337c478bd9Sstevel@tonic-gate 					break;
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 				default:
7367c478bd9Sstevel@tonic-gate 					break;
7377c478bd9Sstevel@tonic-gate 			}
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 	}
7407c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
74103242fafSMarcel Telka 	(void) mutex_unlock(&matching_lock);
7427c478bd9Sstevel@tonic-gate 	return (SC_NOTFOUND);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate found:
7457c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
74603242fafSMarcel Telka 	(void) mutex_unlock(&matching_lock);
7477c478bd9Sstevel@tonic-gate 	(void) get_rpcnum(entryp);
7487c478bd9Sstevel@tonic-gate 	return (SC_NOERROR);
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate /*
7537c478bd9Sstevel@tonic-gate  *  NFS project private API.
7547c478bd9Sstevel@tonic-gate  *  Get a seconfig entry from /etc/nfssec.conf by nfs specific sec name,
7557c478bd9Sstevel@tonic-gate  *  e.g. des, krb5p, etc.
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate int
nfs_getseconfig_byname(char * secmode_name,seconfig_t * entryp)7587c478bd9Sstevel@tonic-gate nfs_getseconfig_byname(char *secmode_name, seconfig_t *entryp)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate 	if (!entryp)
7617c478bd9Sstevel@tonic-gate 		return (SC_NOMEM);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	return (get_seconfig(GETBYNAME, secmode_name, 0, rpc_gss_svc_none,
7647c478bd9Sstevel@tonic-gate 	    entryp));
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate /*
7687c478bd9Sstevel@tonic-gate  *  NFS project private API.
7697c478bd9Sstevel@tonic-gate  *
7707c478bd9Sstevel@tonic-gate  *  Get a seconfig entry from /etc/nfssec.conf by nfs specific sec number,
7717c478bd9Sstevel@tonic-gate  *  e.g. AUTH_DES, AUTH_KRB5_P, etc.
7727c478bd9Sstevel@tonic-gate  */
7737c478bd9Sstevel@tonic-gate int
nfs_getseconfig_bynumber(int nfs_secnum,seconfig_t * entryp)7747c478bd9Sstevel@tonic-gate nfs_getseconfig_bynumber(int nfs_secnum, seconfig_t *entryp)
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate 	if (!entryp)
7777c478bd9Sstevel@tonic-gate 		return (SC_NOMEM);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	return (get_seconfig(GETBYNUM, NULL, nfs_secnum, rpc_gss_svc_none,
7807c478bd9Sstevel@tonic-gate 	    entryp));
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate /*
7847c478bd9Sstevel@tonic-gate  *  NFS project private API.
7857c478bd9Sstevel@tonic-gate  *
7867c478bd9Sstevel@tonic-gate  *  Get a seconfig_t entry used as the default for NFS operations.
7877c478bd9Sstevel@tonic-gate  *  The default flavor entry is defined in /etc/nfssec.conf.
7887c478bd9Sstevel@tonic-gate  *
7897c478bd9Sstevel@tonic-gate  *  Assume user has allocate spaces for secp.
7907c478bd9Sstevel@tonic-gate  */
7917c478bd9Sstevel@tonic-gate int
nfs_getseconfig_default(seconfig_t * secp)7927c478bd9Sstevel@tonic-gate nfs_getseconfig_default(seconfig_t *secp)
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate 	if (secp == NULL)
7957c478bd9Sstevel@tonic-gate 		return (SC_NOMEM);
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	return (nfs_getseconfig_byname("default", secp));
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate /*
8027c478bd9Sstevel@tonic-gate  *  NFS project private API.
8037c478bd9Sstevel@tonic-gate  *
8047c478bd9Sstevel@tonic-gate  *  Free an sec_data structure.
8057c478bd9Sstevel@tonic-gate  *  Free the parts that nfs_clnt_secdata allocates.
8067c478bd9Sstevel@tonic-gate  */
8077c478bd9Sstevel@tonic-gate void
nfs_free_secdata(sec_data_t * secdata)8087c478bd9Sstevel@tonic-gate nfs_free_secdata(sec_data_t *secdata)
8097c478bd9Sstevel@tonic-gate {
8107c478bd9Sstevel@tonic-gate 	dh_k4_clntdata_t *dkdata;
8117c478bd9Sstevel@tonic-gate 	gss_clntdata_t *gdata;
8127c478bd9Sstevel@tonic-gate 
8137c478bd9Sstevel@tonic-gate 	if (!secdata)
8147c478bd9Sstevel@tonic-gate 		return;
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	switch (secdata->rpcflavor) {
8177c478bd9Sstevel@tonic-gate 		case AUTH_UNIX:
8187c478bd9Sstevel@tonic-gate 		case AUTH_NONE:
8197c478bd9Sstevel@tonic-gate 			break;
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 		case AUTH_DES:
8227c478bd9Sstevel@tonic-gate 			/* LINTED pointer alignment */
8237c478bd9Sstevel@tonic-gate 			dkdata = (dh_k4_clntdata_t *)secdata->data;
8247c478bd9Sstevel@tonic-gate 			if (dkdata) {
8257c478bd9Sstevel@tonic-gate 				if (dkdata->netname)
8267c478bd9Sstevel@tonic-gate 					free(dkdata->netname);
8277c478bd9Sstevel@tonic-gate 				if (dkdata->syncaddr.buf)
8287c478bd9Sstevel@tonic-gate 					free(dkdata->syncaddr.buf);
8297c478bd9Sstevel@tonic-gate 				free(dkdata);
8307c478bd9Sstevel@tonic-gate 			}
8317c478bd9Sstevel@tonic-gate 			break;
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 		case RPCSEC_GSS:
8347c478bd9Sstevel@tonic-gate 			/* LINTED pointer alignment */
8357c478bd9Sstevel@tonic-gate 			gdata = (gss_clntdata_t *)secdata->data;
8367c478bd9Sstevel@tonic-gate 			if (gdata) {
8377c478bd9Sstevel@tonic-gate 				if (gdata->mechanism.elements)
8387c478bd9Sstevel@tonic-gate 					free(gdata->mechanism.elements);
8397c478bd9Sstevel@tonic-gate 				free(gdata);
8407c478bd9Sstevel@tonic-gate 			}
8417c478bd9Sstevel@tonic-gate 			break;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 		default:
8447c478bd9Sstevel@tonic-gate 			break;
8457c478bd9Sstevel@tonic-gate 	}
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	free(secdata);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate /*
8517c478bd9Sstevel@tonic-gate  *  Make an client side sec_data structure and fill in appropriate value
8527c478bd9Sstevel@tonic-gate  *  based on its rpc security flavor.
8537c478bd9Sstevel@tonic-gate  *
8547c478bd9Sstevel@tonic-gate  *  It is caller's responsibility to allocate space for seconfig_t,
8557c478bd9Sstevel@tonic-gate  *  and this routine will allocate space for the sec_data structure
8567c478bd9Sstevel@tonic-gate  *  and related data field.
8577c478bd9Sstevel@tonic-gate  *
8587c478bd9Sstevel@tonic-gate  *  Return the sec_data_t on success.
8597c478bd9Sstevel@tonic-gate  *  If fail, return NULL pointer.
8607c478bd9Sstevel@tonic-gate  */
8617c478bd9Sstevel@tonic-gate sec_data_t *
nfs_clnt_secdata(seconfig_t * secp,char * hostname,struct knetconfig * knconf,struct netbuf * syncaddr,int flags)8627c478bd9Sstevel@tonic-gate nfs_clnt_secdata(seconfig_t *secp, char *hostname, struct knetconfig *knconf,
8637c478bd9Sstevel@tonic-gate 		struct netbuf *syncaddr, int flags)
8647c478bd9Sstevel@tonic-gate {
8657c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
8667c478bd9Sstevel@tonic-gate 	sec_data_t *secdata;
8677c478bd9Sstevel@tonic-gate 	dh_k4_clntdata_t *dkdata;
8687c478bd9Sstevel@tonic-gate 	gss_clntdata_t *gdata;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	secdata = malloc(sizeof (sec_data_t));
8717c478bd9Sstevel@tonic-gate 	if (!secdata) {
8727c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "nfs_clnt_secdata: no memory\n");
8737c478bd9Sstevel@tonic-gate 		return (NULL);
8747c478bd9Sstevel@tonic-gate 	}
8757c478bd9Sstevel@tonic-gate 	(void) memset(secdata, 0, sizeof (sec_data_t));
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	secdata->secmod = secp->sc_nfsnum;
8787c478bd9Sstevel@tonic-gate 	secdata->rpcflavor = secp->sc_rpcnum;
8797c478bd9Sstevel@tonic-gate 	secdata->uid = secp->sc_uid;
8807c478bd9Sstevel@tonic-gate 	secdata->flags = flags;
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	/*
8837c478bd9Sstevel@tonic-gate 	 *  Now, fill in the information for client side secdata :
8847c478bd9Sstevel@tonic-gate 	 *
8857c478bd9Sstevel@tonic-gate 	 *  For AUTH_UNIX, AUTH_DES
8867c478bd9Sstevel@tonic-gate 	 *  hostname can be in the form of
8877c478bd9Sstevel@tonic-gate 	 *    nodename or
8887c478bd9Sstevel@tonic-gate 	 *    nodename.domain
8897c478bd9Sstevel@tonic-gate 	 *
8907c478bd9Sstevel@tonic-gate 	 *  For RPCSEC_GSS security flavor
8917c478bd9Sstevel@tonic-gate 	 *  hostname can be in the form of
8927c478bd9Sstevel@tonic-gate 	 *    nodename or
8937c478bd9Sstevel@tonic-gate 	 *    nodename.domain  or
8947c478bd9Sstevel@tonic-gate 	 *    nodename@realm (realm can be the same as the domain) or
8957c478bd9Sstevel@tonic-gate 	 *    nodename.domain@realm
8967c478bd9Sstevel@tonic-gate 	 */
8977c478bd9Sstevel@tonic-gate 	switch (secp->sc_rpcnum) {
8987c478bd9Sstevel@tonic-gate 		case AUTH_UNIX:
8997c478bd9Sstevel@tonic-gate 		case AUTH_NONE:
9007c478bd9Sstevel@tonic-gate 			secdata->data = NULL;
9017c478bd9Sstevel@tonic-gate 			break;
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 		case AUTH_DES:
9047c478bd9Sstevel@tonic-gate 			/*
9057c478bd9Sstevel@tonic-gate 			 *  If hostname is in the format of host.nisdomain
9067c478bd9Sstevel@tonic-gate 			 *  the netname will be constructed with
9077c478bd9Sstevel@tonic-gate 			 *  this nisdomain name rather than the default
9087c478bd9Sstevel@tonic-gate 			 *  domain of the machine.
9097c478bd9Sstevel@tonic-gate 			 */
9107c478bd9Sstevel@tonic-gate 			if (!host2netname(netname, hostname, NULL)) {
9117c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "host2netname: %s: unknown\n",
9127c478bd9Sstevel@tonic-gate 				    hostname);
9137c478bd9Sstevel@tonic-gate 				goto err_out;
9147c478bd9Sstevel@tonic-gate 			}
9157c478bd9Sstevel@tonic-gate 			dkdata = malloc(sizeof (dh_k4_clntdata_t));
9167c478bd9Sstevel@tonic-gate 			if (!dkdata) {
917bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
918bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: no memory\n");
9197c478bd9Sstevel@tonic-gate 				goto err_out;
9207c478bd9Sstevel@tonic-gate 			}
921bfa62c28SVallish Vaidyeshwara 			(void) memset((char *)dkdata, 0,
922bfa62c28SVallish Vaidyeshwara 			    sizeof (dh_k4_clntdata_t));
9237c478bd9Sstevel@tonic-gate 			if ((dkdata->netname = strdup(netname)) == NULL) {
924bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
925bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: no memory\n");
9267c478bd9Sstevel@tonic-gate 				goto err_out;
9277c478bd9Sstevel@tonic-gate 			}
9287c478bd9Sstevel@tonic-gate 			dkdata->netnamelen = strlen(netname);
9297c478bd9Sstevel@tonic-gate 			dkdata->knconf = knconf;
9307c478bd9Sstevel@tonic-gate 			dkdata->syncaddr = *syncaddr;
9317c478bd9Sstevel@tonic-gate 			dkdata->syncaddr.buf = malloc(syncaddr->len);
9327c478bd9Sstevel@tonic-gate 			if (dkdata->syncaddr.buf == NULL) {
933bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
934bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: no memory\n");
9357c478bd9Sstevel@tonic-gate 				goto err_out;
9367c478bd9Sstevel@tonic-gate 			}
9377c478bd9Sstevel@tonic-gate 			(void) memcpy(dkdata->syncaddr.buf, syncaddr->buf,
9387c478bd9Sstevel@tonic-gate 			    syncaddr->len);
9397c478bd9Sstevel@tonic-gate 			secdata->data = (caddr_t)dkdata;
9407c478bd9Sstevel@tonic-gate 			break;
9417c478bd9Sstevel@tonic-gate 
942bfa62c28SVallish Vaidyeshwara 		case RPCSEC_GSS:
9437c478bd9Sstevel@tonic-gate 			if (secp->sc_gss_mech_type == NULL) {
9447c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
9457c478bd9Sstevel@tonic-gate 			"nfs_clnt_secdata: need mechanism information\n");
9467c478bd9Sstevel@tonic-gate 				goto err_out;
9477c478bd9Sstevel@tonic-gate 			}
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 			gdata = malloc(sizeof (gss_clntdata_t));
9507c478bd9Sstevel@tonic-gate 			if (!gdata) {
951bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
952bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: no memory\n");
9537c478bd9Sstevel@tonic-gate 				goto err_out;
9547c478bd9Sstevel@tonic-gate 			}
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 			(void) strcpy(gdata->uname, "nfs");
957bfa62c28SVallish Vaidyeshwara 			if (!parsehostname(hostname, gdata->inst,
958bfa62c28SVallish Vaidyeshwara 			    gdata->realm)) {
959bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
960bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: bad host name\n");
9617c478bd9Sstevel@tonic-gate 				goto err_out;
9627c478bd9Sstevel@tonic-gate 			}
9637c478bd9Sstevel@tonic-gate 
964bfa62c28SVallish Vaidyeshwara 			gdata->mechanism.length =
965bfa62c28SVallish Vaidyeshwara 			    secp->sc_gss_mech_type->length;
9667c478bd9Sstevel@tonic-gate 			if (!(gdata->mechanism.elements =
9677c478bd9Sstevel@tonic-gate 			    malloc(secp->sc_gss_mech_type->length))) {
968bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
969bfa62c28SVallish Vaidyeshwara 				    "nfs_clnt_secdata: no memory\n");
9707c478bd9Sstevel@tonic-gate 				goto err_out;
9717c478bd9Sstevel@tonic-gate 			}
9727c478bd9Sstevel@tonic-gate 			(void) memcpy(gdata->mechanism.elements,
9737c478bd9Sstevel@tonic-gate 			    secp->sc_gss_mech_type->elements,
9747c478bd9Sstevel@tonic-gate 			    secp->sc_gss_mech_type->length);
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 			gdata->qop = secp->sc_qop;
9777c478bd9Sstevel@tonic-gate 			gdata->service = secp->sc_service;
9787c478bd9Sstevel@tonic-gate 			secdata->data = (caddr_t)gdata;
9797c478bd9Sstevel@tonic-gate 			break;
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 		default:
9827c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "nfs_clnt_secdata: unknown flavor\n");
9837c478bd9Sstevel@tonic-gate 			goto err_out;
9847c478bd9Sstevel@tonic-gate 	}
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	return (secdata);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate err_out:
9897c478bd9Sstevel@tonic-gate 	free(secdata);
9907c478bd9Sstevel@tonic-gate 	return (NULL);
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  *  nfs_get_root_principal() maps a host name to its principal name
9957c478bd9Sstevel@tonic-gate  *  based on the given security information.
9967c478bd9Sstevel@tonic-gate  *
9977c478bd9Sstevel@tonic-gate  *  input :  seconfig - security configuration information
9987c478bd9Sstevel@tonic-gate  *		host - the host name which could be in the following forms:
9997c478bd9Sstevel@tonic-gate  *		node
10007c478bd9Sstevel@tonic-gate  *		node.namedomain
10017c478bd9Sstevel@tonic-gate  *		node@secdomain (e.g. kerberos realm is a secdomain)
10027c478bd9Sstevel@tonic-gate  *		node.namedomain@secdomain
10037c478bd9Sstevel@tonic-gate  *  output : rootname_p - address of the principal name for the host
10047c478bd9Sstevel@tonic-gate  *
10057c478bd9Sstevel@tonic-gate  *  Currently, this routine is only used by share program.
10067c478bd9Sstevel@tonic-gate  *
10077c478bd9Sstevel@tonic-gate  */
10087c478bd9Sstevel@tonic-gate bool_t
nfs_get_root_principal(seconfig_t * seconfig,char * host,caddr_t * rootname_p)10097c478bd9Sstevel@tonic-gate nfs_get_root_principal(seconfig_t *seconfig, char *host, caddr_t *rootname_p)
10107c478bd9Sstevel@tonic-gate {
10117c478bd9Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1], node[MAX_NAME_LEN];
10127c478bd9Sstevel@tonic-gate 	char secdomain[MAX_NAME_LEN];
10137c478bd9Sstevel@tonic-gate 	rpc_gss_principal_t gssname;
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	switch (seconfig->sc_rpcnum) {
10167c478bd9Sstevel@tonic-gate 		case AUTH_DES:
10177c478bd9Sstevel@tonic-gate 			if (!host2netname(netname, host, NULL)) {
10187c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
10197c478bd9Sstevel@tonic-gate 			    "nfs_get_root_principal: unknown host: %s\n", host);
10207c478bd9Sstevel@tonic-gate 				return (FALSE);
10217c478bd9Sstevel@tonic-gate 			}
10227c478bd9Sstevel@tonic-gate 			*rootname_p = strdup(netname);
10237c478bd9Sstevel@tonic-gate 			if (!*rootname_p) {
1024bfa62c28SVallish Vaidyeshwara 				syslog(LOG_ERR,
1025bfa62c28SVallish Vaidyeshwara 				    "nfs_get_root_principal: no memory\n");
10267c478bd9Sstevel@tonic-gate 				return (FALSE);
10277c478bd9Sstevel@tonic-gate 			}
10287c478bd9Sstevel@tonic-gate 			break;
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 		case RPCSEC_GSS:
10317c478bd9Sstevel@tonic-gate 			if (!parsehostname(host, node, secdomain)) {
10327c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
10337c478bd9Sstevel@tonic-gate 				    "nfs_get_root_principal: bad host name\n");
10347c478bd9Sstevel@tonic-gate 				return (FALSE);
10357c478bd9Sstevel@tonic-gate 			}
10367c478bd9Sstevel@tonic-gate 			if (!rpc_gss_get_principal_name(&gssname,
1037bfa62c28SVallish Vaidyeshwara 			    seconfig->sc_gss_mech, "root", node, secdomain)) {
10387c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
10397c478bd9Sstevel@tonic-gate 	"nfs_get_root_principal: can not get principal name : %s\n", host);
10407c478bd9Sstevel@tonic-gate 				return (FALSE);
10417c478bd9Sstevel@tonic-gate 			}
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 			*rootname_p = (caddr_t)gssname;
10447c478bd9Sstevel@tonic-gate 			break;
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 		default:
10477c478bd9Sstevel@tonic-gate 			return (FALSE);
10487c478bd9Sstevel@tonic-gate 	}
10497c478bd9Sstevel@tonic-gate 	return (TRUE);
10507c478bd9Sstevel@tonic-gate }
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate  *  SYSLOG SC_* errors.
10557c478bd9Sstevel@tonic-gate  */
10567c478bd9Sstevel@tonic-gate int
nfs_syslog_scerr(int scerror,char msg[])10577c478bd9Sstevel@tonic-gate nfs_syslog_scerr(int scerror, char msg[])
10587c478bd9Sstevel@tonic-gate {
10597c478bd9Sstevel@tonic-gate 	switch (scerror) {
10607c478bd9Sstevel@tonic-gate 		case SC_NOMEM :
10617c478bd9Sstevel@tonic-gate 			sprintf(msg, "%s : no memory", NFSSEC_CONF);
10627c478bd9Sstevel@tonic-gate 			return (0);
10637c478bd9Sstevel@tonic-gate 		case SC_OPENFAIL :
10647c478bd9Sstevel@tonic-gate 			sprintf(msg, "can not open %s", NFSSEC_CONF);
10657c478bd9Sstevel@tonic-gate 			return (0);
10667c478bd9Sstevel@tonic-gate 		case SC_NOTFOUND :
10677c478bd9Sstevel@tonic-gate 			sprintf(msg, "has no entry in %s", NFSSEC_CONF);
10687c478bd9Sstevel@tonic-gate 			return (0);
10697c478bd9Sstevel@tonic-gate 		case SC_BADENTRIES :
10707c478bd9Sstevel@tonic-gate 			sprintf(msg, "bad entry in %s", NFSSEC_CONF);
10717c478bd9Sstevel@tonic-gate 			return (0);
10727c478bd9Sstevel@tonic-gate 		default:
10737c478bd9Sstevel@tonic-gate 			msg[0] = '\0';
10747c478bd9Sstevel@tonic-gate 			return (-1);
10757c478bd9Sstevel@tonic-gate 	}
10767c478bd9Sstevel@tonic-gate }
1077