xref: /onnv-gate/usr/src/cmd/fs.d/nfs/lib/nfs_sec.c (revision 8650:2d9ec0dd504c)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57693SVallish.Vaidyeshwara@Sun.COM  * Common Development and Distribution License (the "License").
67693SVallish.Vaidyeshwara@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /* LINTLIBRARY */
220Sstevel@tonic-gate 
230Sstevel@tonic-gate /*
24*8650SVallish.Vaidyeshwara@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * nfs security related library routines.
300Sstevel@tonic-gate  *
310Sstevel@tonic-gate  * Some of the routines in this file are adopted from
320Sstevel@tonic-gate  * lib/libnsl/netselect/netselect.c and are modified to be
330Sstevel@tonic-gate  * used for accessing /etc/nfssec.conf.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /* SVr4.0 1.18	*/
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #include <stdio.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <ctype.h>
410Sstevel@tonic-gate #include <stdlib.h>
420Sstevel@tonic-gate #include <syslog.h>
430Sstevel@tonic-gate #include <synch.h>
440Sstevel@tonic-gate #include <rpc/rpc.h>
450Sstevel@tonic-gate #include <nfs/nfs_sec.h>
460Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
470Sstevel@tonic-gate #ifdef WNFS_SEC_NEGO
480Sstevel@tonic-gate #include "webnfs.h"
490Sstevel@tonic-gate #endif
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #define	GETBYNAME	1
520Sstevel@tonic-gate #define	GETBYNUM	2
530Sstevel@tonic-gate 
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * mapping for /etc/nfssec.conf
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate struct sc_data {
580Sstevel@tonic-gate 	char	*string;
590Sstevel@tonic-gate 	int	value;
600Sstevel@tonic-gate };
610Sstevel@tonic-gate 
620Sstevel@tonic-gate static struct sc_data sc_service[] = {
630Sstevel@tonic-gate 	"default",	rpc_gss_svc_default,
640Sstevel@tonic-gate 	"-",		rpc_gss_svc_none,
650Sstevel@tonic-gate 	"none",		rpc_gss_svc_none,
660Sstevel@tonic-gate 	"integrity",	rpc_gss_svc_integrity,
670Sstevel@tonic-gate 	"privacy",	rpc_gss_svc_privacy,
680Sstevel@tonic-gate 	NULL,		SC_FAILURE
690Sstevel@tonic-gate };
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static char *gettoken(char *, int);
720Sstevel@tonic-gate extern	int atoi(const char *str);
730Sstevel@tonic-gate 
740Sstevel@tonic-gate extern	bool_t rpc_gss_get_principal_name(rpc_gss_principal_t *, char *,
750Sstevel@tonic-gate 			char *, char *, char *);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate extern	bool_t rpc_gss_mech_to_oid(char *, rpc_gss_OID *);
780Sstevel@tonic-gate extern	bool_t rpc_gss_qop_to_num(char *, char *, uint_t *);
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate  *  blank() returns true if the line is a blank line, 0 otherwise
820Sstevel@tonic-gate  */
830Sstevel@tonic-gate static int
blank(cp)840Sstevel@tonic-gate blank(cp)
850Sstevel@tonic-gate char *cp;
860Sstevel@tonic-gate {
870Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
880Sstevel@tonic-gate 		cp++;
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 	return (*cp == '\0');
910Sstevel@tonic-gate }
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  *  comment() returns true if the line is a comment, 0 otherwise.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate static int
comment(cp)970Sstevel@tonic-gate comment(cp)
980Sstevel@tonic-gate char *cp;
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	while (*cp && isspace(*cp)) {
1010Sstevel@tonic-gate 		cp++;
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 	return (*cp == '#');
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate  *	getvalue() searches for the given string in the given array,
1090Sstevel@tonic-gate  *	and returns the integer value associated with the string.
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate static unsigned long
getvalue(cp,sc_data)1120Sstevel@tonic-gate getvalue(cp, sc_data)
1130Sstevel@tonic-gate char *cp;
1140Sstevel@tonic-gate struct sc_data sc_data[];
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	int i;	/* used to index through the given struct sc_data array */
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	for (i = 0; sc_data[i].string; i++) {
1190Sstevel@tonic-gate 		if (strcmp(sc_data[i].string, cp) == 0) {
1200Sstevel@tonic-gate 			break;
1210Sstevel@tonic-gate 		}
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate 	return (sc_data[i].value);
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate  *	shift1left() moves all characters in the string over 1 to
1280Sstevel@tonic-gate  *	the left.
1290Sstevel@tonic-gate  */
1300Sstevel@tonic-gate static void
shift1left(p)1310Sstevel@tonic-gate shift1left(p)
1320Sstevel@tonic-gate char *p;
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate 	for (; *p; p++)
1350Sstevel@tonic-gate 		*p = *(p + 1);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate  *	gettoken() behaves much like strtok(), except that
1410Sstevel@tonic-gate  *	it knows about escaped space characters (i.e., space characters
1420Sstevel@tonic-gate  *	preceeded by a '\' are taken literally).
1430Sstevel@tonic-gate  *
1440Sstevel@tonic-gate  *	XXX We should make this MT-hot by making it more like strtok_r().
1450Sstevel@tonic-gate  */
1460Sstevel@tonic-gate static char *
gettoken(cp,skip)1470Sstevel@tonic-gate gettoken(cp, skip)
1480Sstevel@tonic-gate char	*cp;
1490Sstevel@tonic-gate int skip;
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate 	static char	*savep;	/* the place where we left off    */
1520Sstevel@tonic-gate 	register char	*p;	/* the beginning of the new token */
1530Sstevel@tonic-gate 	register char	*retp;	/* the token to be returned	  */
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	/* Determine if first or subsequent call  */
1570Sstevel@tonic-gate 	p = (cp == NULL)? savep: cp;
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/* Return if no tokens remain.  */
1600Sstevel@tonic-gate 	if (p == 0) {
1610Sstevel@tonic-gate 		return (NULL);
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	while (isspace(*p))
1650Sstevel@tonic-gate 		p++;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	if (*p == '\0') {
1680Sstevel@tonic-gate 		return (NULL);
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	/*
1720Sstevel@tonic-gate 	 *	Save the location of the token and then skip past it
1730Sstevel@tonic-gate 	 */
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	retp = p;
1760Sstevel@tonic-gate 	while (*p) {
1770Sstevel@tonic-gate 		if (isspace(*p))
1780Sstevel@tonic-gate 			if (skip == TRUE) {
1790Sstevel@tonic-gate 				shift1left(p);
1800Sstevel@tonic-gate 				continue;
1810Sstevel@tonic-gate 			} else
1820Sstevel@tonic-gate 				break;
1830Sstevel@tonic-gate 		/*
1840Sstevel@tonic-gate 		 *	Only process the escape of the space separator;
1850Sstevel@tonic-gate 		 *	since the token may contain other separators,
1860Sstevel@tonic-gate 		 *	let the other routines handle the escape of
1870Sstevel@tonic-gate 		 *	specific characters in the token.
1880Sstevel@tonic-gate 		 */
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		if (*p == '\\' && *(p + 1) != '\n' && isspace(*(p + 1))) {
1910Sstevel@tonic-gate 			shift1left(p);
1920Sstevel@tonic-gate 		}
1930Sstevel@tonic-gate 		p++;
1940Sstevel@tonic-gate 	}
1950Sstevel@tonic-gate 	if (*p == '\0') {
1960Sstevel@tonic-gate 		savep = 0;	/* indicate this is last token */
1970Sstevel@tonic-gate 	} else {
1980Sstevel@tonic-gate 		*p = '\0';
1990Sstevel@tonic-gate 		savep = ++p;
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 	return (retp);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate  *  matchname() parses a line of the /etc/nfssec.conf file
2060Sstevel@tonic-gate  *  and match the sc_name with the given name.
2070Sstevel@tonic-gate  *  If there is a match, it fills the information into the given
2080Sstevel@tonic-gate  *  pointer of the seconfig_t structure.
2090Sstevel@tonic-gate  *
2100Sstevel@tonic-gate  *  Returns TRUE if a match is found.
2110Sstevel@tonic-gate  */
2120Sstevel@tonic-gate static bool_t
matchname(char * line,char * name,seconfig_t * secp)2130Sstevel@tonic-gate matchname(char *line, char *name, seconfig_t *secp)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate 	char	*tok1,	*tok2;	/* holds a token from the line */
2160Sstevel@tonic-gate 	char	*secname, *gss_mech, *gss_qop; /* pointer to a secmode name */
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	if ((secname = gettoken(line, FALSE)) == NULL) {
2190Sstevel@tonic-gate 		/* bad line */
2200Sstevel@tonic-gate 		return (FALSE);
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	if (strcmp(secname, name) != 0) {
2240Sstevel@tonic-gate 		return (FALSE);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	tok1 = tok2 = NULL;
2280Sstevel@tonic-gate 	if (((tok1 = gettoken(NULL, FALSE)) == NULL) ||
2297693SVallish.Vaidyeshwara@Sun.COM 	    ((gss_mech = gettoken(NULL, FALSE)) == NULL) ||
2307693SVallish.Vaidyeshwara@Sun.COM 	    ((gss_qop = gettoken(NULL, FALSE)) == NULL) ||
2317693SVallish.Vaidyeshwara@Sun.COM 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
2327693SVallish.Vaidyeshwara@Sun.COM 	    ((secp->sc_service = getvalue(tok2, sc_service))
2337693SVallish.Vaidyeshwara@Sun.COM 	    == SC_FAILURE)) {
2340Sstevel@tonic-gate 		return (FALSE);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 	secp->sc_nfsnum = atoi(tok1);
2370Sstevel@tonic-gate 	(void) strcpy(secp->sc_name, secname);
2380Sstevel@tonic-gate 	(void) strcpy(secp->sc_gss_mech, gss_mech);
2390Sstevel@tonic-gate 	secp->sc_gss_mech_type = NULL;
2400Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
2417693SVallish.Vaidyeshwara@Sun.COM 		if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) ||
2427693SVallish.Vaidyeshwara@Sun.COM 		    !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) {
2437693SVallish.Vaidyeshwara@Sun.COM 			return (FALSE);
2447693SVallish.Vaidyeshwara@Sun.COM 		}
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	return (TRUE);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate /*
2510Sstevel@tonic-gate  *  matchnum() parses a line of the /etc/nfssec.conf file
2520Sstevel@tonic-gate  *  and match the sc_nfsnum with the given number.
2530Sstevel@tonic-gate  *  If it is a match, it fills the information in the given pointer
2540Sstevel@tonic-gate  *  of the seconfig_t structure.
2550Sstevel@tonic-gate  *
2560Sstevel@tonic-gate  *  Returns TRUE if a match is found.
2570Sstevel@tonic-gate  */
2580Sstevel@tonic-gate static bool_t
matchnum(char * line,int num,seconfig_t * secp)2590Sstevel@tonic-gate matchnum(char *line, int num, seconfig_t *secp)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 	char	*tok1,	*tok2;	/* holds a token from the line */
2620Sstevel@tonic-gate 	char	*secname, *gss_mech, *gss_qop;	/* pointer to a secmode name */
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	if ((secname = gettoken(line, FALSE)) == NULL) {
2650Sstevel@tonic-gate 		/* bad line */
2660Sstevel@tonic-gate 		return (FALSE);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	tok1 = tok2 = NULL;
2700Sstevel@tonic-gate 	if ((tok1 = gettoken(NULL, FALSE)) == NULL) {
2710Sstevel@tonic-gate 		/* bad line */
2720Sstevel@tonic-gate 		return (FALSE);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if ((secp->sc_nfsnum = atoi(tok1)) != num) {
2760Sstevel@tonic-gate 		return (FALSE);
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	if (((gss_mech = gettoken(NULL, FALSE)) == NULL) ||
2807693SVallish.Vaidyeshwara@Sun.COM 	    ((gss_qop = gettoken(NULL, FALSE)) == NULL) ||
2817693SVallish.Vaidyeshwara@Sun.COM 	    ((tok2 = gettoken(NULL, FALSE)) == NULL) ||
2827693SVallish.Vaidyeshwara@Sun.COM 	    ((secp->sc_service = getvalue(tok2, sc_service))
2837693SVallish.Vaidyeshwara@Sun.COM 	    == SC_FAILURE)) {
2840Sstevel@tonic-gate 		return (FALSE);
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	(void) strcpy(secp->sc_name, secname);
2880Sstevel@tonic-gate 	(void) strcpy(secp->sc_gss_mech, gss_mech);
2890Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
2907693SVallish.Vaidyeshwara@Sun.COM 		if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) ||
2917693SVallish.Vaidyeshwara@Sun.COM 		    !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) {
2927693SVallish.Vaidyeshwara@Sun.COM 			return (FALSE);
2937693SVallish.Vaidyeshwara@Sun.COM 		}
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	return (TRUE);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate  *  Fill in the RPC Protocol security flavor number
3010Sstevel@tonic-gate  *  into the sc_rpcnum of seconfig_t structure.
3020Sstevel@tonic-gate  *
3030Sstevel@tonic-gate  *  Mainly to map NFS secmod number to RPCSEC_GSS if
3040Sstevel@tonic-gate  *  a mechanism name is specified.
3050Sstevel@tonic-gate  */
3060Sstevel@tonic-gate static void
get_rpcnum(seconfig_t * secp)3070Sstevel@tonic-gate get_rpcnum(seconfig_t *secp)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate 	if (secp->sc_gss_mech[0] != '-') {
3100Sstevel@tonic-gate 		secp->sc_rpcnum = RPCSEC_GSS;
3110Sstevel@tonic-gate 	} else {
3120Sstevel@tonic-gate 		secp->sc_rpcnum = secp->sc_nfsnum;
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate /*
3170Sstevel@tonic-gate  *  Parse a given hostname (nodename[.domain@realm]) to
3180Sstevel@tonic-gate  *  instant name (nodename[.domain]) and realm.
3190Sstevel@tonic-gate  *
3200Sstevel@tonic-gate  *  Assuming user has allocated the space for inst and realm.
3210Sstevel@tonic-gate  */
3220Sstevel@tonic-gate static int
parsehostname(char * hostname,char * inst,char * realm)3230Sstevel@tonic-gate parsehostname(char *hostname, char *inst, char *realm)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	char *h, *r;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	if (!hostname)
3280Sstevel@tonic-gate 		return (0);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	h = (char *)strdup(hostname);
3310Sstevel@tonic-gate 	if (!h) {
3320Sstevel@tonic-gate 		syslog(LOG_ERR, "parsehostname: no memory\n");
3330Sstevel@tonic-gate 		return (0);
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	r = (char *)strchr(h, '@');
3370Sstevel@tonic-gate 	if (!r) {
3380Sstevel@tonic-gate 		(void) strcpy(inst, h);
3390Sstevel@tonic-gate 		(void) strcpy(realm, "");
3400Sstevel@tonic-gate 	} else {
3410Sstevel@tonic-gate 		*r++ = '\0';
3420Sstevel@tonic-gate 		(void) strcpy(inst, h);
3430Sstevel@tonic-gate 		(void) strcpy(realm, r);
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 	free(h);
3460Sstevel@tonic-gate 	return (1);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate  *  Get the name corresponding to a qop num.
3510Sstevel@tonic-gate  */
3520Sstevel@tonic-gate char *
nfs_get_qop_name(seconfig_t * entryp)3530Sstevel@tonic-gate nfs_get_qop_name(seconfig_t *entryp)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	char	*tok;	/* holds a token from the line */
3560Sstevel@tonic-gate 	char	*secname, *gss_qop = NULL; /* pointer to a secmode name */
3570Sstevel@tonic-gate 	static	mutex_t matching_lock = DEFAULTMUTEX;
3580Sstevel@tonic-gate 	char	line[BUFSIZ];	/* holds each line of NFSSEC_CONF */
3590Sstevel@tonic-gate 	FILE	*fp;		/* file stream for NFSSEC_CONF */
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if ((fp = fopen(NFSSEC_CONF, "r")) == NULL) {
3627693SVallish.Vaidyeshwara@Sun.COM 		return (NULL);
3630Sstevel@tonic-gate 	}
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	(void) mutex_lock(&matching_lock);
3660Sstevel@tonic-gate 	while (fgets(line, BUFSIZ, fp)) {
3677693SVallish.Vaidyeshwara@Sun.COM 		if (!(blank(line) || comment(line))) {
3687693SVallish.Vaidyeshwara@Sun.COM 			if ((secname = gettoken(line, FALSE)) == NULL) {
3697693SVallish.Vaidyeshwara@Sun.COM 				/* bad line */
3707693SVallish.Vaidyeshwara@Sun.COM 				continue;
3717693SVallish.Vaidyeshwara@Sun.COM 			}
3727693SVallish.Vaidyeshwara@Sun.COM 			if (strcmp(secname, entryp->sc_name) == 0) {
3737693SVallish.Vaidyeshwara@Sun.COM 				tok = NULL;
3747693SVallish.Vaidyeshwara@Sun.COM 				if ((tok = gettoken(NULL, FALSE)) == NULL) {
3757693SVallish.Vaidyeshwara@Sun.COM 					/* bad line */
3767693SVallish.Vaidyeshwara@Sun.COM 					goto err;
3777693SVallish.Vaidyeshwara@Sun.COM 				}
3787693SVallish.Vaidyeshwara@Sun.COM 
3797693SVallish.Vaidyeshwara@Sun.COM 				if (atoi(tok) != entryp->sc_nfsnum)
3807693SVallish.Vaidyeshwara@Sun.COM 					goto err;
3817693SVallish.Vaidyeshwara@Sun.COM 
3827693SVallish.Vaidyeshwara@Sun.COM 				if ((gettoken(NULL, FALSE) == NULL) ||
3837693SVallish.Vaidyeshwara@Sun.COM 				    ((gss_qop = gettoken(NULL, FALSE))
3847693SVallish.Vaidyeshwara@Sun.COM 				    == NULL)) {
3857693SVallish.Vaidyeshwara@Sun.COM 					goto err;
3867693SVallish.Vaidyeshwara@Sun.COM 				}
3877693SVallish.Vaidyeshwara@Sun.COM 				break;
3887693SVallish.Vaidyeshwara@Sun.COM 			}
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 	}
3910Sstevel@tonic-gate err:
3920Sstevel@tonic-gate 	(void) mutex_unlock(&matching_lock);
3930Sstevel@tonic-gate 	(void) fclose(fp);
3940Sstevel@tonic-gate 	return (gss_qop);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate  * This routine creates an auth handle assocaited with the
3990Sstevel@tonic-gate  * negotiated security flavor contained in nfs_sec.  The auth
4000Sstevel@tonic-gate  * handle will be used in the next LOOKUP request to fetch
4010Sstevel@tonic-gate  * the filehandle.
4020Sstevel@tonic-gate  */
4030Sstevel@tonic-gate AUTH *
nfs_create_ah(CLIENT * cl,char * hostname,seconfig_t * nfs_sec)4040Sstevel@tonic-gate nfs_create_ah(CLIENT *cl, char *hostname, seconfig_t *nfs_sec)
4050Sstevel@tonic-gate {
4060Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
4070Sstevel@tonic-gate 	char svc_name[MAXNETNAMELEN+1];
4080Sstevel@tonic-gate 	char *gss_qop;
4090Sstevel@tonic-gate 	static int window = 60;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	if (nfs_sec == NULL)
4127693SVallish.Vaidyeshwara@Sun.COM 		goto err;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	switch (nfs_sec->sc_rpcnum) {
4157693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_UNIX:
4167693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_NONE:
4177693SVallish.Vaidyeshwara@Sun.COM 			return (NULL);
4180Sstevel@tonic-gate 
4197693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_DES:
4207693SVallish.Vaidyeshwara@Sun.COM 			if (!host2netname(netname, hostname, NULL))
4217693SVallish.Vaidyeshwara@Sun.COM 				goto err;
4220Sstevel@tonic-gate 
4237693SVallish.Vaidyeshwara@Sun.COM 			return (authdes_seccreate(netname, window, hostname,
4247693SVallish.Vaidyeshwara@Sun.COM 			    NULL));
4250Sstevel@tonic-gate 
4267693SVallish.Vaidyeshwara@Sun.COM 		case RPCSEC_GSS:
4277693SVallish.Vaidyeshwara@Sun.COM 			if (cl == NULL)
4287693SVallish.Vaidyeshwara@Sun.COM 				goto err;
4290Sstevel@tonic-gate 
4307693SVallish.Vaidyeshwara@Sun.COM 			if (nfs_sec->sc_gss_mech_type == NULL) {
4317693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
4327693SVallish.Vaidyeshwara@Sun.COM 				"nfs_create_ah: need mechanism information\n");
4337693SVallish.Vaidyeshwara@Sun.COM 				goto err;
4347693SVallish.Vaidyeshwara@Sun.COM 			}
4350Sstevel@tonic-gate 
4367693SVallish.Vaidyeshwara@Sun.COM 			/*
4377693SVallish.Vaidyeshwara@Sun.COM 			 * RPCSEC_GSS service names are of the form svc@host.dom
4387693SVallish.Vaidyeshwara@Sun.COM 			 */
4397693SVallish.Vaidyeshwara@Sun.COM 			(void) sprintf(svc_name, "nfs@%s", hostname);
4400Sstevel@tonic-gate 
4417693SVallish.Vaidyeshwara@Sun.COM 			gss_qop = nfs_get_qop_name(nfs_sec);
4427693SVallish.Vaidyeshwara@Sun.COM 			if (gss_qop == NULL)
4437693SVallish.Vaidyeshwara@Sun.COM 				goto err;
4440Sstevel@tonic-gate 
4457693SVallish.Vaidyeshwara@Sun.COM 			return (rpc_gss_seccreate(cl, svc_name,
4467693SVallish.Vaidyeshwara@Sun.COM 			    nfs_sec->sc_gss_mech, nfs_sec->sc_service, gss_qop,
4477693SVallish.Vaidyeshwara@Sun.COM 			    NULL, NULL));
4480Sstevel@tonic-gate 
4497693SVallish.Vaidyeshwara@Sun.COM 		default:
4507693SVallish.Vaidyeshwara@Sun.COM 			syslog(LOG_ERR, "nfs_create_ah: unknown flavor\n");
4517693SVallish.Vaidyeshwara@Sun.COM 			return (NULL);
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate err:
4540Sstevel@tonic-gate 	syslog(LOG_ERR, "nfs_create_ah: failed to make auth handle\n");
4550Sstevel@tonic-gate 	return (NULL);
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate #ifdef WNFS_SEC_NEGO
4590Sstevel@tonic-gate /*
4600Sstevel@tonic-gate  * This routine negotiates sec flavors with server and returns:
4610Sstevel@tonic-gate  *	SNEGO_SUCCESS:		successful; sec flavors are
4620Sstevel@tonic-gate  *				returned in snego,
4630Sstevel@tonic-gate  *	SNEGO_DEF_VALID:	default sec flavor valid; no need
4640Sstevel@tonic-gate  *				to negotiate flavors,
4650Sstevel@tonic-gate  *	SNEGO_ARRAY_TOO_SMALL:	array too small,
4660Sstevel@tonic-gate  *	SNEGO_FAILURE:		failure
4670Sstevel@tonic-gate  */
4680Sstevel@tonic-gate /*
4690Sstevel@tonic-gate  * The following depicts how sec flavors are placed in an
4700Sstevel@tonic-gate  * overloaded V2 fhandle:
4710Sstevel@tonic-gate  *
4720Sstevel@tonic-gate  * Note that the first four octets contain the length octet,
4730Sstevel@tonic-gate  * the status octet, and two padded octets to make them XDR
4740Sstevel@tonic-gate  * four-octet aligned.
4750Sstevel@tonic-gate  *
4760Sstevel@tonic-gate  *   1   2   3   4                                          32
4770Sstevel@tonic-gate  * +---+---+---+---+---+---+---+---+   +---+---+---+---+   +---+
4780Sstevel@tonic-gate  * | l | s |   |   |     sec_1     |...|     sec_n     |...|   |
4790Sstevel@tonic-gate  * +---+---+---+---+---+---+---+---+   +---+---+---+---+   +---+
4800Sstevel@tonic-gate  *
4810Sstevel@tonic-gate  * where
4820Sstevel@tonic-gate  *
4830Sstevel@tonic-gate  *   the status octet s indicates whether there are more security
4840Sstevel@tonic-gate  *   flavors(1 means yes, 0 means no) that require the client to
4850Sstevel@tonic-gate  *   perform another 0x81 LOOKUP to get them,
4860Sstevel@tonic-gate  *
4870Sstevel@tonic-gate  *   the length octet l is the length describing the number of
4880Sstevel@tonic-gate  *   valid octets that follow.  (l = 4 * n, where n is the number
4890Sstevel@tonic-gate  *
4900Sstevel@tonic-gate  * The following depicts how sec flavors are placed in an
4910Sstevel@tonic-gate  * overloaded V3 fhandle:
4920Sstevel@tonic-gate  *
4930Sstevel@tonic-gate  *  1        4
4940Sstevel@tonic-gate  * +--+--+--+--+
4950Sstevel@tonic-gate  * |    len    |
4960Sstevel@tonic-gate  * +--+--+--+--+
4970Sstevel@tonic-gate  *                                               up to 64
4980Sstevel@tonic-gate  * +--+--+--+--+--+--+--+--+--+--+--+--+     +--+--+--+--+
4990Sstevel@tonic-gate  * |s |  |  |  |   sec_1   |   sec_2   | ... |   sec_n   |
5000Sstevel@tonic-gate  * +--+--+--+--+--+--+--+--+--+--+--+--+     +--+--+--+--+
5010Sstevel@tonic-gate  *
5020Sstevel@tonic-gate  * len = 4 * (n+1), where n is the number of security flavors
5030Sstevel@tonic-gate  * sent in the current overloaded filehandle.
5040Sstevel@tonic-gate  *
5050Sstevel@tonic-gate  * the status octet s indicates whether there are more security
5060Sstevel@tonic-gate  * mechanisms(1 means yes, 0 means no) that require the client
5070Sstevel@tonic-gate  * to perform another 0x81 LOOKUP to get them.
5080Sstevel@tonic-gate  *
5090Sstevel@tonic-gate  * Three octets are padded after the status octet.
5100Sstevel@tonic-gate  */
5110Sstevel@tonic-gate enum snego_stat
nfs_sec_nego(rpcprog_t vers,CLIENT * clnt,char * fspath,struct snego_t * snego)5120Sstevel@tonic-gate nfs_sec_nego(rpcprog_t vers, CLIENT *clnt, char *fspath, struct snego_t *snego)
5130Sstevel@tonic-gate {
5140Sstevel@tonic-gate 	enum clnt_stat rpc_stat;
5150Sstevel@tonic-gate 	static int MAX_V2_CNT = (WNL_FHSIZE/sizeof (int)) - 1;
5160Sstevel@tonic-gate 	static int MAX_V3_CNT = (WNL3_FHSIZE/sizeof (int)) - 1;
5170Sstevel@tonic-gate 	static struct timeval TIMEOUT = { 25, 0 };
5180Sstevel@tonic-gate 	int status;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	if (clnt == NULL || fspath == NULL || snego == NULL)
5210Sstevel@tonic-gate 		return (SNEGO_FAILURE);
5220Sstevel@tonic-gate 
5237693SVallish.Vaidyeshwara@Sun.COM 	if (vers == WNL_V2) {
5247693SVallish.Vaidyeshwara@Sun.COM 		wnl_diropargs arg;
5257693SVallish.Vaidyeshwara@Sun.COM 		wnl_diropres clnt_res;
5260Sstevel@tonic-gate 
5277693SVallish.Vaidyeshwara@Sun.COM 		memset((char *)&arg.dir, 0, sizeof (wnl_fh));
5287693SVallish.Vaidyeshwara@Sun.COM 		arg.name = fspath;
5297693SVallish.Vaidyeshwara@Sun.COM 		memset((char *)&clnt_res, 0, sizeof (clnt_res));
5307693SVallish.Vaidyeshwara@Sun.COM 		rpc_stat = clnt_call(clnt, WNLPROC_LOOKUP,
5317693SVallish.Vaidyeshwara@Sun.COM 		    (xdrproc_t)xdr_wnl_diropargs, (caddr_t)&arg,
5327693SVallish.Vaidyeshwara@Sun.COM 		    (xdrproc_t)xdr_wnl_diropres, (caddr_t)&clnt_res,
5337693SVallish.Vaidyeshwara@Sun.COM 		    TIMEOUT);
5347693SVallish.Vaidyeshwara@Sun.COM 		if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL_OK)
5357693SVallish.Vaidyeshwara@Sun.COM 			return (SNEGO_DEF_VALID);
5367693SVallish.Vaidyeshwara@Sun.COM 		if (rpc_stat != RPC_AUTHERROR)
5370Sstevel@tonic-gate 			return (SNEGO_FAILURE);
5387693SVallish.Vaidyeshwara@Sun.COM 
5397693SVallish.Vaidyeshwara@Sun.COM 		{
5407693SVallish.Vaidyeshwara@Sun.COM 			struct rpc_err e;
5417693SVallish.Vaidyeshwara@Sun.COM 			wnl_diropres res;
5427693SVallish.Vaidyeshwara@Sun.COM 			char *p;
5437693SVallish.Vaidyeshwara@Sun.COM 			int tot = 0;
5440Sstevel@tonic-gate 
5457693SVallish.Vaidyeshwara@Sun.COM 			CLNT_GETERR(clnt, &e);
5467693SVallish.Vaidyeshwara@Sun.COM 			if (e.re_why != AUTH_TOOWEAK)
5477693SVallish.Vaidyeshwara@Sun.COM 				return (SNEGO_FAILURE);
5487693SVallish.Vaidyeshwara@Sun.COM 
5497693SVallish.Vaidyeshwara@Sun.COM 			if ((p = malloc(strlen(fspath)+3)) == NULL) {
5507693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR, "no memory\n");
5517693SVallish.Vaidyeshwara@Sun.COM 				return (SNEGO_FAILURE);
5527693SVallish.Vaidyeshwara@Sun.COM 			}
5530Sstevel@tonic-gate 			/*
5547693SVallish.Vaidyeshwara@Sun.COM 			 * Do an x81 LOOKUP
5550Sstevel@tonic-gate 			 */
5567693SVallish.Vaidyeshwara@Sun.COM 			p[0] = (char)WNL_SEC_NEGO;
5577693SVallish.Vaidyeshwara@Sun.COM 			strcpy(&p[2], fspath);
5587693SVallish.Vaidyeshwara@Sun.COM 			do {
5597693SVallish.Vaidyeshwara@Sun.COM 				p[1] = (char)(1+snego->cnt); /* sec index */
5607693SVallish.Vaidyeshwara@Sun.COM 				arg.name = p;
5617693SVallish.Vaidyeshwara@Sun.COM 				memset((char *)&res, 0, sizeof (wnl_diropres));
5627693SVallish.Vaidyeshwara@Sun.COM 				if (wnlproc_lookup_2(&arg, &res, clnt) !=
5637693SVallish.Vaidyeshwara@Sun.COM 				    RPC_SUCCESS || res.status != WNL_OK) {
5647693SVallish.Vaidyeshwara@Sun.COM 					free(p);
5657693SVallish.Vaidyeshwara@Sun.COM 					return (SNEGO_FAILURE);
5667693SVallish.Vaidyeshwara@Sun.COM 				}
5670Sstevel@tonic-gate 
5687693SVallish.Vaidyeshwara@Sun.COM 				/*
5697693SVallish.Vaidyeshwara@Sun.COM 				 * retrieve flavors from filehandle:
5707693SVallish.Vaidyeshwara@Sun.COM 				 *	1st byte: length
5717693SVallish.Vaidyeshwara@Sun.COM 				 *	2nd byte: status
5727693SVallish.Vaidyeshwara@Sun.COM 				 *	3rd & 4th: pad
5737693SVallish.Vaidyeshwara@Sun.COM 				 *	5th and after: sec flavors.
5747693SVallish.Vaidyeshwara@Sun.COM 				 */
5757693SVallish.Vaidyeshwara@Sun.COM 				{
5767693SVallish.Vaidyeshwara@Sun.COM 					char *c = (char *)&res.wnl_diropres_u.
5777693SVallish.Vaidyeshwara@Sun.COM 					    wnl_diropres.file;
5787693SVallish.Vaidyeshwara@Sun.COM 					int ii;
5797693SVallish.Vaidyeshwara@Sun.COM 					int cnt = ((int)*c)/sizeof (uint_t);
5807693SVallish.Vaidyeshwara@Sun.COM 					/* LINTED pointer alignment */
5817693SVallish.Vaidyeshwara@Sun.COM 					int *ip = (int *)(c+sizeof (int));
5820Sstevel@tonic-gate 
5837693SVallish.Vaidyeshwara@Sun.COM 					tot += cnt;
5847693SVallish.Vaidyeshwara@Sun.COM 					if (tot >= MAX_FLAVORS) {
5857693SVallish.Vaidyeshwara@Sun.COM 						free(p);
5867693SVallish.Vaidyeshwara@Sun.COM 						return (SNEGO_ARRAY_TOO_SMALL);
5877693SVallish.Vaidyeshwara@Sun.COM 					}
5887693SVallish.Vaidyeshwara@Sun.COM 					status = (int)*(c+1);
5897693SVallish.Vaidyeshwara@Sun.COM 					if (cnt > MAX_V2_CNT || cnt < 0) {
5907693SVallish.Vaidyeshwara@Sun.COM 						free(p);
5917693SVallish.Vaidyeshwara@Sun.COM 						return (SNEGO_FAILURE);
5927693SVallish.Vaidyeshwara@Sun.COM 					}
5937693SVallish.Vaidyeshwara@Sun.COM 					for (ii = 0; ii < cnt; ii++)
5947693SVallish.Vaidyeshwara@Sun.COM 						snego->array[snego->cnt+ii] =
5957693SVallish.Vaidyeshwara@Sun.COM 						    ntohl(*(ip+ii));
5967693SVallish.Vaidyeshwara@Sun.COM 					snego->cnt += cnt;
5977693SVallish.Vaidyeshwara@Sun.COM 				}
5987693SVallish.Vaidyeshwara@Sun.COM 			} while (status);
5997693SVallish.Vaidyeshwara@Sun.COM 			free(p);
6007693SVallish.Vaidyeshwara@Sun.COM 			return (SNEGO_SUCCESS);
6017693SVallish.Vaidyeshwara@Sun.COM 		}
6027693SVallish.Vaidyeshwara@Sun.COM 	} else if (vers == WNL_V3) {
6037693SVallish.Vaidyeshwara@Sun.COM 		WNL_LOOKUP3args arg;
6047693SVallish.Vaidyeshwara@Sun.COM 		WNL_LOOKUP3res clnt_res;
6050Sstevel@tonic-gate 
6067693SVallish.Vaidyeshwara@Sun.COM 		memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
6077693SVallish.Vaidyeshwara@Sun.COM 		arg.what.name = fspath;
6087693SVallish.Vaidyeshwara@Sun.COM 		arg.what.dir.data.data_len = 0;
6097693SVallish.Vaidyeshwara@Sun.COM 		arg.what.dir.data.data_val = 0;
6107693SVallish.Vaidyeshwara@Sun.COM 		memset((char *)&clnt_res, 0, sizeof (clnt_res));
6117693SVallish.Vaidyeshwara@Sun.COM 		rpc_stat = clnt_call(clnt, WNLPROC3_LOOKUP,
6127693SVallish.Vaidyeshwara@Sun.COM 		    (xdrproc_t)xdr_WNL_LOOKUP3args, (caddr_t)&arg,
6137693SVallish.Vaidyeshwara@Sun.COM 		    (xdrproc_t)xdr_WNL_LOOKUP3res, (caddr_t)&clnt_res,
6147693SVallish.Vaidyeshwara@Sun.COM 		    TIMEOUT);
6157693SVallish.Vaidyeshwara@Sun.COM 		if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL3_OK)
6167693SVallish.Vaidyeshwara@Sun.COM 			return (SNEGO_DEF_VALID);
6177693SVallish.Vaidyeshwara@Sun.COM 		if (rpc_stat != RPC_AUTHERROR)
6180Sstevel@tonic-gate 			return (SNEGO_FAILURE);
6197693SVallish.Vaidyeshwara@Sun.COM 
6207693SVallish.Vaidyeshwara@Sun.COM 		{
6217693SVallish.Vaidyeshwara@Sun.COM 			struct rpc_err e;
6227693SVallish.Vaidyeshwara@Sun.COM 			WNL_LOOKUP3res res;
6237693SVallish.Vaidyeshwara@Sun.COM 			char *p;
6247693SVallish.Vaidyeshwara@Sun.COM 			int tot = 0;
6250Sstevel@tonic-gate 
6267693SVallish.Vaidyeshwara@Sun.COM 			CLNT_GETERR(clnt, &e);
6277693SVallish.Vaidyeshwara@Sun.COM 			if (e.re_why != AUTH_TOOWEAK)
6287693SVallish.Vaidyeshwara@Sun.COM 				return (SNEGO_FAILURE);
6297693SVallish.Vaidyeshwara@Sun.COM 
6307693SVallish.Vaidyeshwara@Sun.COM 			if ((p = malloc(strlen(fspath)+3)) == NULL) {
6317693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR, "no memory\n");
6327693SVallish.Vaidyeshwara@Sun.COM 				return (SNEGO_FAILURE);
6337693SVallish.Vaidyeshwara@Sun.COM 			}
6340Sstevel@tonic-gate 			/*
6357693SVallish.Vaidyeshwara@Sun.COM 			 * Do an x81 LOOKUP
6360Sstevel@tonic-gate 			 */
6377693SVallish.Vaidyeshwara@Sun.COM 			p[0] = (char)WNL_SEC_NEGO;
6387693SVallish.Vaidyeshwara@Sun.COM 			strcpy(&p[2], fspath);
6397693SVallish.Vaidyeshwara@Sun.COM 			do {
6407693SVallish.Vaidyeshwara@Sun.COM 				p[1] = (char)(1+snego->cnt); /* sec index */
6417693SVallish.Vaidyeshwara@Sun.COM 				arg.what.name = p;
6427693SVallish.Vaidyeshwara@Sun.COM 				memset((char *)&res, 0,
6437693SVallish.Vaidyeshwara@Sun.COM 				    sizeof (WNL_LOOKUP3res));
6447693SVallish.Vaidyeshwara@Sun.COM 				if (wnlproc3_lookup_3(&arg, &res, clnt) !=
6457693SVallish.Vaidyeshwara@Sun.COM 				    RPC_SUCCESS || res.status != WNL3_OK) {
6467693SVallish.Vaidyeshwara@Sun.COM 					free(p);
6477693SVallish.Vaidyeshwara@Sun.COM 					return (SNEGO_FAILURE);
6487693SVallish.Vaidyeshwara@Sun.COM 				}
6490Sstevel@tonic-gate 
6507693SVallish.Vaidyeshwara@Sun.COM 				/*
6517693SVallish.Vaidyeshwara@Sun.COM 				 * retrieve flavors from filehandle:
6527693SVallish.Vaidyeshwara@Sun.COM 				 *
6537693SVallish.Vaidyeshwara@Sun.COM 				 * 1st byte: status
6547693SVallish.Vaidyeshwara@Sun.COM 				 * 2nd thru 4th: pad
6557693SVallish.Vaidyeshwara@Sun.COM 				 * 5th and after: sec flavors.
6567693SVallish.Vaidyeshwara@Sun.COM 				 */
6577693SVallish.Vaidyeshwara@Sun.COM 				{
658*8650SVallish.Vaidyeshwara@Sun.COM 					char *c = res.WNL_LOOKUP3res_u.
6597693SVallish.Vaidyeshwara@Sun.COM 					    res_ok.object.data.data_val;
6607693SVallish.Vaidyeshwara@Sun.COM 					int ii;
6617693SVallish.Vaidyeshwara@Sun.COM 					int len = res.WNL_LOOKUP3res_u.res_ok.
6627693SVallish.Vaidyeshwara@Sun.COM 					    object.data.data_len;
6637693SVallish.Vaidyeshwara@Sun.COM 					int cnt;
6647693SVallish.Vaidyeshwara@Sun.COM 					/* LINTED pointer alignment */
6657693SVallish.Vaidyeshwara@Sun.COM 					int *ip = (int *)(c+sizeof (int));
6660Sstevel@tonic-gate 
6677693SVallish.Vaidyeshwara@Sun.COM 					cnt = len/sizeof (uint_t) - 1;
6687693SVallish.Vaidyeshwara@Sun.COM 					tot += cnt;
6697693SVallish.Vaidyeshwara@Sun.COM 					if (tot >= MAX_FLAVORS) {
6707693SVallish.Vaidyeshwara@Sun.COM 						free(p);
6717693SVallish.Vaidyeshwara@Sun.COM 						return (SNEGO_ARRAY_TOO_SMALL);
6727693SVallish.Vaidyeshwara@Sun.COM 					}
6737693SVallish.Vaidyeshwara@Sun.COM 					status = (int)(*c);
6747693SVallish.Vaidyeshwara@Sun.COM 					if (cnt > MAX_V3_CNT || cnt < 0) {
6757693SVallish.Vaidyeshwara@Sun.COM 						free(p);
6767693SVallish.Vaidyeshwara@Sun.COM 						return (SNEGO_FAILURE);
6777693SVallish.Vaidyeshwara@Sun.COM 					}
6787693SVallish.Vaidyeshwara@Sun.COM 					for (ii = 0; ii < cnt; ii++)
6797693SVallish.Vaidyeshwara@Sun.COM 						snego->array[snego->cnt+ii] =
6807693SVallish.Vaidyeshwara@Sun.COM 						    ntohl(*(ip+ii));
6817693SVallish.Vaidyeshwara@Sun.COM 					snego->cnt += cnt;
6827693SVallish.Vaidyeshwara@Sun.COM 				}
6837693SVallish.Vaidyeshwara@Sun.COM 			} while (status);
6847693SVallish.Vaidyeshwara@Sun.COM 			free(p);
6857693SVallish.Vaidyeshwara@Sun.COM 			return (SNEGO_SUCCESS);
6867693SVallish.Vaidyeshwara@Sun.COM 		}
6870Sstevel@tonic-gate 	}
6880Sstevel@tonic-gate 	return (SNEGO_FAILURE);
6890Sstevel@tonic-gate }
6900Sstevel@tonic-gate #endif
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate /*
6930Sstevel@tonic-gate  *  Get seconfig from /etc/nfssec.conf by name or by number or
6940Sstevel@tonic-gate  *  by descriptior.
6950Sstevel@tonic-gate  */
6960Sstevel@tonic-gate /* ARGSUSED */
6970Sstevel@tonic-gate static int
get_seconfig(int whichway,char * name,int num,rpc_gss_service_t service,seconfig_t * entryp)6980Sstevel@tonic-gate get_seconfig(int whichway, char *name, int num,
6990Sstevel@tonic-gate 		rpc_gss_service_t service, seconfig_t *entryp)
7000Sstevel@tonic-gate {
7010Sstevel@tonic-gate 	static	mutex_t matching_lock = DEFAULTMUTEX;
7020Sstevel@tonic-gate 	char	line[BUFSIZ];	/* holds each line of NFSSEC_CONF */
7030Sstevel@tonic-gate 	FILE	*fp;		/* file stream for NFSSEC_CONF */
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	if ((whichway == GETBYNAME) && (name == NULL))
7060Sstevel@tonic-gate 		return (SC_NOTFOUND);
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	if ((fp = fopen(NFSSEC_CONF, "r")) == NULL) {
7090Sstevel@tonic-gate 		return (SC_OPENFAIL);
7100Sstevel@tonic-gate 	}
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	(void) mutex_lock(&matching_lock);
7130Sstevel@tonic-gate 	while (fgets(line, BUFSIZ, fp)) {
7147693SVallish.Vaidyeshwara@Sun.COM 		if (!(blank(line) || comment(line))) {
7157693SVallish.Vaidyeshwara@Sun.COM 			switch (whichway) {
7167693SVallish.Vaidyeshwara@Sun.COM 				case GETBYNAME:
7177693SVallish.Vaidyeshwara@Sun.COM 					if (matchname(line, name, entryp)) {
7187693SVallish.Vaidyeshwara@Sun.COM 						goto found;
7197693SVallish.Vaidyeshwara@Sun.COM 					}
7207693SVallish.Vaidyeshwara@Sun.COM 					break;
7210Sstevel@tonic-gate 
7227693SVallish.Vaidyeshwara@Sun.COM 				case GETBYNUM:
7237693SVallish.Vaidyeshwara@Sun.COM 					if (matchnum(line, num, entryp)) {
7247693SVallish.Vaidyeshwara@Sun.COM 						goto found;
7257693SVallish.Vaidyeshwara@Sun.COM 					}
7267693SVallish.Vaidyeshwara@Sun.COM 					break;
7277693SVallish.Vaidyeshwara@Sun.COM 
7287693SVallish.Vaidyeshwara@Sun.COM 				default:
7297693SVallish.Vaidyeshwara@Sun.COM 					break;
7300Sstevel@tonic-gate 			}
7310Sstevel@tonic-gate 		}
7320Sstevel@tonic-gate 	}
7330Sstevel@tonic-gate 	(void) mutex_unlock(&matching_lock);
7340Sstevel@tonic-gate 	(void) fclose(fp);
7350Sstevel@tonic-gate 	return (SC_NOTFOUND);
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate found:
7380Sstevel@tonic-gate 	(void) mutex_unlock(&matching_lock);
7390Sstevel@tonic-gate 	(void) fclose(fp);
7400Sstevel@tonic-gate 	(void) get_rpcnum(entryp);
7410Sstevel@tonic-gate 	return (SC_NOERROR);
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate /*
7460Sstevel@tonic-gate  *  NFS project private API.
7470Sstevel@tonic-gate  *  Get a seconfig entry from /etc/nfssec.conf by nfs specific sec name,
7480Sstevel@tonic-gate  *  e.g. des, krb5p, etc.
7490Sstevel@tonic-gate  */
7500Sstevel@tonic-gate int
nfs_getseconfig_byname(char * secmode_name,seconfig_t * entryp)7510Sstevel@tonic-gate nfs_getseconfig_byname(char *secmode_name, seconfig_t *entryp)
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate 	if (!entryp)
7540Sstevel@tonic-gate 		return (SC_NOMEM);
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	return (get_seconfig(GETBYNAME, secmode_name, 0, rpc_gss_svc_none,
7577693SVallish.Vaidyeshwara@Sun.COM 	    entryp));
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate /*
7610Sstevel@tonic-gate  *  NFS project private API.
7620Sstevel@tonic-gate  *
7630Sstevel@tonic-gate  *  Get a seconfig entry from /etc/nfssec.conf by nfs specific sec number,
7640Sstevel@tonic-gate  *  e.g. AUTH_DES, AUTH_KRB5_P, etc.
7650Sstevel@tonic-gate  */
7660Sstevel@tonic-gate int
nfs_getseconfig_bynumber(int nfs_secnum,seconfig_t * entryp)7670Sstevel@tonic-gate nfs_getseconfig_bynumber(int nfs_secnum, seconfig_t *entryp)
7680Sstevel@tonic-gate {
7690Sstevel@tonic-gate 	if (!entryp)
7700Sstevel@tonic-gate 		return (SC_NOMEM);
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	return (get_seconfig(GETBYNUM, NULL, nfs_secnum, rpc_gss_svc_none,
7737693SVallish.Vaidyeshwara@Sun.COM 	    entryp));
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate /*
7770Sstevel@tonic-gate  *  NFS project private API.
7780Sstevel@tonic-gate  *
7790Sstevel@tonic-gate  *  Get a seconfig_t entry used as the default for NFS operations.
7800Sstevel@tonic-gate  *  The default flavor entry is defined in /etc/nfssec.conf.
7810Sstevel@tonic-gate  *
7820Sstevel@tonic-gate  *  Assume user has allocate spaces for secp.
7830Sstevel@tonic-gate  */
7840Sstevel@tonic-gate int
nfs_getseconfig_default(seconfig_t * secp)7850Sstevel@tonic-gate nfs_getseconfig_default(seconfig_t *secp)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate 	if (secp == NULL)
7880Sstevel@tonic-gate 		return (SC_NOMEM);
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	return (nfs_getseconfig_byname("default", secp));
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate  *  NFS project private API.
7960Sstevel@tonic-gate  *
7970Sstevel@tonic-gate  *  Free an sec_data structure.
7980Sstevel@tonic-gate  *  Free the parts that nfs_clnt_secdata allocates.
7990Sstevel@tonic-gate  */
8000Sstevel@tonic-gate void
nfs_free_secdata(sec_data_t * secdata)8010Sstevel@tonic-gate nfs_free_secdata(sec_data_t *secdata)
8020Sstevel@tonic-gate {
8030Sstevel@tonic-gate 	dh_k4_clntdata_t *dkdata;
8040Sstevel@tonic-gate 	gss_clntdata_t *gdata;
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	if (!secdata)
8070Sstevel@tonic-gate 		return;
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	switch (secdata->rpcflavor) {
8107693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_UNIX:
8117693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_NONE:
8127693SVallish.Vaidyeshwara@Sun.COM 			break;
8130Sstevel@tonic-gate 
8147693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_DES:
8157693SVallish.Vaidyeshwara@Sun.COM 			/* LINTED pointer alignment */
8167693SVallish.Vaidyeshwara@Sun.COM 			dkdata = (dh_k4_clntdata_t *)secdata->data;
8177693SVallish.Vaidyeshwara@Sun.COM 			if (dkdata) {
8187693SVallish.Vaidyeshwara@Sun.COM 				if (dkdata->netname)
8197693SVallish.Vaidyeshwara@Sun.COM 					free(dkdata->netname);
8207693SVallish.Vaidyeshwara@Sun.COM 				if (dkdata->syncaddr.buf)
8217693SVallish.Vaidyeshwara@Sun.COM 					free(dkdata->syncaddr.buf);
8227693SVallish.Vaidyeshwara@Sun.COM 				free(dkdata);
8237693SVallish.Vaidyeshwara@Sun.COM 			}
8247693SVallish.Vaidyeshwara@Sun.COM 			break;
8250Sstevel@tonic-gate 
8267693SVallish.Vaidyeshwara@Sun.COM 		case RPCSEC_GSS:
8277693SVallish.Vaidyeshwara@Sun.COM 			/* LINTED pointer alignment */
8287693SVallish.Vaidyeshwara@Sun.COM 			gdata = (gss_clntdata_t *)secdata->data;
8297693SVallish.Vaidyeshwara@Sun.COM 			if (gdata) {
8307693SVallish.Vaidyeshwara@Sun.COM 				if (gdata->mechanism.elements)
8317693SVallish.Vaidyeshwara@Sun.COM 					free(gdata->mechanism.elements);
8327693SVallish.Vaidyeshwara@Sun.COM 				free(gdata);
8337693SVallish.Vaidyeshwara@Sun.COM 			}
8347693SVallish.Vaidyeshwara@Sun.COM 			break;
8350Sstevel@tonic-gate 
8367693SVallish.Vaidyeshwara@Sun.COM 		default:
8377693SVallish.Vaidyeshwara@Sun.COM 			break;
8380Sstevel@tonic-gate 	}
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 	free(secdata);
8410Sstevel@tonic-gate }
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate /*
8440Sstevel@tonic-gate  *  Make an client side sec_data structure and fill in appropriate value
8450Sstevel@tonic-gate  *  based on its rpc security flavor.
8460Sstevel@tonic-gate  *
8470Sstevel@tonic-gate  *  It is caller's responsibility to allocate space for seconfig_t,
8480Sstevel@tonic-gate  *  and this routine will allocate space for the sec_data structure
8490Sstevel@tonic-gate  *  and related data field.
8500Sstevel@tonic-gate  *
8510Sstevel@tonic-gate  *  Return the sec_data_t on success.
8520Sstevel@tonic-gate  *  If fail, return NULL pointer.
8530Sstevel@tonic-gate  */
8540Sstevel@tonic-gate sec_data_t *
nfs_clnt_secdata(seconfig_t * secp,char * hostname,struct knetconfig * knconf,struct netbuf * syncaddr,int flags)8550Sstevel@tonic-gate nfs_clnt_secdata(seconfig_t *secp, char *hostname, struct knetconfig *knconf,
8560Sstevel@tonic-gate 		struct netbuf *syncaddr, int flags)
8570Sstevel@tonic-gate {
8580Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
8590Sstevel@tonic-gate 	sec_data_t *secdata;
8600Sstevel@tonic-gate 	dh_k4_clntdata_t *dkdata;
8610Sstevel@tonic-gate 	gss_clntdata_t *gdata;
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	secdata = malloc(sizeof (sec_data_t));
8640Sstevel@tonic-gate 	if (!secdata) {
8650Sstevel@tonic-gate 		syslog(LOG_ERR, "nfs_clnt_secdata: no memory\n");
8660Sstevel@tonic-gate 		return (NULL);
8670Sstevel@tonic-gate 	}
8680Sstevel@tonic-gate 	(void) memset(secdata, 0, sizeof (sec_data_t));
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	secdata->secmod = secp->sc_nfsnum;
8710Sstevel@tonic-gate 	secdata->rpcflavor = secp->sc_rpcnum;
8720Sstevel@tonic-gate 	secdata->uid = secp->sc_uid;
8730Sstevel@tonic-gate 	secdata->flags = flags;
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 	/*
8760Sstevel@tonic-gate 	 *  Now, fill in the information for client side secdata :
8770Sstevel@tonic-gate 	 *
8780Sstevel@tonic-gate 	 *  For AUTH_UNIX, AUTH_DES
8790Sstevel@tonic-gate 	 *  hostname can be in the form of
8800Sstevel@tonic-gate 	 *    nodename or
8810Sstevel@tonic-gate 	 *    nodename.domain
8820Sstevel@tonic-gate 	 *
8830Sstevel@tonic-gate 	 *  For RPCSEC_GSS security flavor
8840Sstevel@tonic-gate 	 *  hostname can be in the form of
8850Sstevel@tonic-gate 	 *    nodename or
8860Sstevel@tonic-gate 	 *    nodename.domain  or
8870Sstevel@tonic-gate 	 *    nodename@realm (realm can be the same as the domain) or
8880Sstevel@tonic-gate 	 *    nodename.domain@realm
8890Sstevel@tonic-gate 	 */
8900Sstevel@tonic-gate 	switch (secp->sc_rpcnum) {
8917693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_UNIX:
8927693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_NONE:
8937693SVallish.Vaidyeshwara@Sun.COM 			secdata->data = NULL;
8947693SVallish.Vaidyeshwara@Sun.COM 			break;
8950Sstevel@tonic-gate 
8967693SVallish.Vaidyeshwara@Sun.COM 		case AUTH_DES:
8977693SVallish.Vaidyeshwara@Sun.COM 			/*
8987693SVallish.Vaidyeshwara@Sun.COM 			 *  If hostname is in the format of host.nisdomain
8997693SVallish.Vaidyeshwara@Sun.COM 			 *  the netname will be constructed with
9007693SVallish.Vaidyeshwara@Sun.COM 			 *  this nisdomain name rather than the default
9017693SVallish.Vaidyeshwara@Sun.COM 			 *  domain of the machine.
9027693SVallish.Vaidyeshwara@Sun.COM 			 */
9037693SVallish.Vaidyeshwara@Sun.COM 			if (!host2netname(netname, hostname, NULL)) {
9047693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR, "host2netname: %s: unknown\n",
9057693SVallish.Vaidyeshwara@Sun.COM 				    hostname);
9067693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9077693SVallish.Vaidyeshwara@Sun.COM 			}
9087693SVallish.Vaidyeshwara@Sun.COM 			dkdata = malloc(sizeof (dh_k4_clntdata_t));
9097693SVallish.Vaidyeshwara@Sun.COM 			if (!dkdata) {
9107693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9117693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: no memory\n");
9127693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9137693SVallish.Vaidyeshwara@Sun.COM 			}
9147693SVallish.Vaidyeshwara@Sun.COM 			(void) memset((char *)dkdata, 0,
9157693SVallish.Vaidyeshwara@Sun.COM 			    sizeof (dh_k4_clntdata_t));
9167693SVallish.Vaidyeshwara@Sun.COM 			if ((dkdata->netname = strdup(netname)) == NULL) {
9177693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9187693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: no memory\n");
9197693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9207693SVallish.Vaidyeshwara@Sun.COM 			}
9217693SVallish.Vaidyeshwara@Sun.COM 			dkdata->netnamelen = strlen(netname);
9227693SVallish.Vaidyeshwara@Sun.COM 			dkdata->knconf = knconf;
9237693SVallish.Vaidyeshwara@Sun.COM 			dkdata->syncaddr = *syncaddr;
9247693SVallish.Vaidyeshwara@Sun.COM 			dkdata->syncaddr.buf = malloc(syncaddr->len);
9257693SVallish.Vaidyeshwara@Sun.COM 			if (dkdata->syncaddr.buf == NULL) {
9267693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9277693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: no memory\n");
9287693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9297693SVallish.Vaidyeshwara@Sun.COM 			}
9307693SVallish.Vaidyeshwara@Sun.COM 			(void) memcpy(dkdata->syncaddr.buf, syncaddr->buf,
9317693SVallish.Vaidyeshwara@Sun.COM 			    syncaddr->len);
9327693SVallish.Vaidyeshwara@Sun.COM 			secdata->data = (caddr_t)dkdata;
9337693SVallish.Vaidyeshwara@Sun.COM 			break;
9340Sstevel@tonic-gate 
9357693SVallish.Vaidyeshwara@Sun.COM 		case RPCSEC_GSS:
9367693SVallish.Vaidyeshwara@Sun.COM 			if (secp->sc_gss_mech_type == NULL) {
9377693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9387693SVallish.Vaidyeshwara@Sun.COM 			"nfs_clnt_secdata: need mechanism information\n");
9397693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9407693SVallish.Vaidyeshwara@Sun.COM 			}
9417693SVallish.Vaidyeshwara@Sun.COM 
9427693SVallish.Vaidyeshwara@Sun.COM 			gdata = malloc(sizeof (gss_clntdata_t));
9437693SVallish.Vaidyeshwara@Sun.COM 			if (!gdata) {
9447693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9457693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: no memory\n");
9467693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9477693SVallish.Vaidyeshwara@Sun.COM 			}
9480Sstevel@tonic-gate 
9497693SVallish.Vaidyeshwara@Sun.COM 			(void) strcpy(gdata->uname, "nfs");
9507693SVallish.Vaidyeshwara@Sun.COM 			if (!parsehostname(hostname, gdata->inst,
9517693SVallish.Vaidyeshwara@Sun.COM 			    gdata->realm)) {
9527693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9537693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: bad host name\n");
9547693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9557693SVallish.Vaidyeshwara@Sun.COM 			}
9560Sstevel@tonic-gate 
9577693SVallish.Vaidyeshwara@Sun.COM 			gdata->mechanism.length =
9587693SVallish.Vaidyeshwara@Sun.COM 			    secp->sc_gss_mech_type->length;
9597693SVallish.Vaidyeshwara@Sun.COM 			if (!(gdata->mechanism.elements =
9607693SVallish.Vaidyeshwara@Sun.COM 			    malloc(secp->sc_gss_mech_type->length))) {
9617693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
9627693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_clnt_secdata: no memory\n");
9637693SVallish.Vaidyeshwara@Sun.COM 				goto err_out;
9647693SVallish.Vaidyeshwara@Sun.COM 			}
9657693SVallish.Vaidyeshwara@Sun.COM 			(void) memcpy(gdata->mechanism.elements,
9667693SVallish.Vaidyeshwara@Sun.COM 			    secp->sc_gss_mech_type->elements,
9677693SVallish.Vaidyeshwara@Sun.COM 			    secp->sc_gss_mech_type->length);
9687693SVallish.Vaidyeshwara@Sun.COM 
9697693SVallish.Vaidyeshwara@Sun.COM 			gdata->qop = secp->sc_qop;
9707693SVallish.Vaidyeshwara@Sun.COM 			gdata->service = secp->sc_service;
9717693SVallish.Vaidyeshwara@Sun.COM 			secdata->data = (caddr_t)gdata;
9727693SVallish.Vaidyeshwara@Sun.COM 			break;
9737693SVallish.Vaidyeshwara@Sun.COM 
9747693SVallish.Vaidyeshwara@Sun.COM 		default:
9757693SVallish.Vaidyeshwara@Sun.COM 			syslog(LOG_ERR, "nfs_clnt_secdata: unknown flavor\n");
9767693SVallish.Vaidyeshwara@Sun.COM 			goto err_out;
9770Sstevel@tonic-gate 	}
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 	return (secdata);
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate err_out:
9820Sstevel@tonic-gate 	free(secdata);
9830Sstevel@tonic-gate 	return (NULL);
9840Sstevel@tonic-gate }
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate /*
9870Sstevel@tonic-gate  *  nfs_get_root_principal() maps a host name to its principal name
9880Sstevel@tonic-gate  *  based on the given security information.
9890Sstevel@tonic-gate  *
9900Sstevel@tonic-gate  *  input :  seconfig - security configuration information
9910Sstevel@tonic-gate  *		host - the host name which could be in the following forms:
9920Sstevel@tonic-gate  *		node
9930Sstevel@tonic-gate  *		node.namedomain
9940Sstevel@tonic-gate  *		node@secdomain (e.g. kerberos realm is a secdomain)
9950Sstevel@tonic-gate  *		node.namedomain@secdomain
9960Sstevel@tonic-gate  *  output : rootname_p - address of the principal name for the host
9970Sstevel@tonic-gate  *
9980Sstevel@tonic-gate  *  Currently, this routine is only used by share program.
9990Sstevel@tonic-gate  *
10000Sstevel@tonic-gate  */
10010Sstevel@tonic-gate bool_t
nfs_get_root_principal(seconfig_t * seconfig,char * host,caddr_t * rootname_p)10020Sstevel@tonic-gate nfs_get_root_principal(seconfig_t *seconfig, char *host, caddr_t *rootname_p)
10030Sstevel@tonic-gate {
10040Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1], node[MAX_NAME_LEN];
10050Sstevel@tonic-gate 	char secdomain[MAX_NAME_LEN];
10060Sstevel@tonic-gate 	rpc_gss_principal_t gssname;
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 	switch (seconfig->sc_rpcnum) {
10090Sstevel@tonic-gate 		case AUTH_DES:
10107693SVallish.Vaidyeshwara@Sun.COM 			if (!host2netname(netname, host, NULL)) {
10117693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
10120Sstevel@tonic-gate 			    "nfs_get_root_principal: unknown host: %s\n", host);
10137693SVallish.Vaidyeshwara@Sun.COM 				return (FALSE);
10147693SVallish.Vaidyeshwara@Sun.COM 			}
10157693SVallish.Vaidyeshwara@Sun.COM 			*rootname_p = strdup(netname);
10167693SVallish.Vaidyeshwara@Sun.COM 			if (!*rootname_p) {
10177693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
10187693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_get_root_principal: no memory\n");
10197693SVallish.Vaidyeshwara@Sun.COM 				return (FALSE);
10207693SVallish.Vaidyeshwara@Sun.COM 			}
10217693SVallish.Vaidyeshwara@Sun.COM 			break;
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 		case RPCSEC_GSS:
10247693SVallish.Vaidyeshwara@Sun.COM 			if (!parsehostname(host, node, secdomain)) {
10257693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
10267693SVallish.Vaidyeshwara@Sun.COM 				    "nfs_get_root_principal: bad host name\n");
10277693SVallish.Vaidyeshwara@Sun.COM 				return (FALSE);
10287693SVallish.Vaidyeshwara@Sun.COM 			}
10297693SVallish.Vaidyeshwara@Sun.COM 			if (!rpc_gss_get_principal_name(&gssname,
10307693SVallish.Vaidyeshwara@Sun.COM 			    seconfig->sc_gss_mech, "root", node, secdomain)) {
10317693SVallish.Vaidyeshwara@Sun.COM 				syslog(LOG_ERR,
10320Sstevel@tonic-gate 	"nfs_get_root_principal: can not get principal name : %s\n", host);
10337693SVallish.Vaidyeshwara@Sun.COM 				return (FALSE);
10347693SVallish.Vaidyeshwara@Sun.COM 			}
10350Sstevel@tonic-gate 
10367693SVallish.Vaidyeshwara@Sun.COM 			*rootname_p = (caddr_t)gssname;
10377693SVallish.Vaidyeshwara@Sun.COM 			break;
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 		default:
10407693SVallish.Vaidyeshwara@Sun.COM 			return (FALSE);
10410Sstevel@tonic-gate 	}
10420Sstevel@tonic-gate 	return (TRUE);
10430Sstevel@tonic-gate }
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate /*
10470Sstevel@tonic-gate  *  SYSLOG SC_* errors.
10480Sstevel@tonic-gate  */
10490Sstevel@tonic-gate int
nfs_syslog_scerr(int scerror,char msg[])10500Sstevel@tonic-gate nfs_syslog_scerr(int scerror, char msg[])
10510Sstevel@tonic-gate {
10520Sstevel@tonic-gate 	switch (scerror) {
10530Sstevel@tonic-gate 		case SC_NOMEM :
10540Sstevel@tonic-gate 			sprintf(msg, "%s : no memory", NFSSEC_CONF);
10550Sstevel@tonic-gate 			return (0);
10560Sstevel@tonic-gate 		case SC_OPENFAIL :
10570Sstevel@tonic-gate 			sprintf(msg, "can not open %s", NFSSEC_CONF);
10580Sstevel@tonic-gate 			return (0);
10590Sstevel@tonic-gate 		case SC_NOTFOUND :
10600Sstevel@tonic-gate 			sprintf(msg, "has no entry in %s", NFSSEC_CONF);
10610Sstevel@tonic-gate 			return (0);
10620Sstevel@tonic-gate 		case SC_BADENTRIES :
10630Sstevel@tonic-gate 			sprintf(msg, "bad entry in %s", NFSSEC_CONF);
10640Sstevel@tonic-gate 			return (0);
10650Sstevel@tonic-gate 		default:
10660Sstevel@tonic-gate 			msg[0] = '\0';
10670Sstevel@tonic-gate 			return (-1);
10680Sstevel@tonic-gate 	}
10690Sstevel@tonic-gate }
1070