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 5*7693SVallish.Vaidyeshwara@Sun.COM * Common Development and Distribution License (the "License"). 6*7693SVallish.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*7693SVallish.Vaidyeshwara@Sun.COM * Copyright 2008 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 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 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 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 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 * 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 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) || 229*7693SVallish.Vaidyeshwara@Sun.COM ((gss_mech = gettoken(NULL, FALSE)) == NULL) || 230*7693SVallish.Vaidyeshwara@Sun.COM ((gss_qop = gettoken(NULL, FALSE)) == NULL) || 231*7693SVallish.Vaidyeshwara@Sun.COM ((tok2 = gettoken(NULL, FALSE)) == NULL) || 232*7693SVallish.Vaidyeshwara@Sun.COM ((secp->sc_service = getvalue(tok2, sc_service)) 233*7693SVallish.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] != '-') { 241*7693SVallish.Vaidyeshwara@Sun.COM if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) || 242*7693SVallish.Vaidyeshwara@Sun.COM !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) { 243*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 244*7693SVallish.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 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) || 280*7693SVallish.Vaidyeshwara@Sun.COM ((gss_qop = gettoken(NULL, FALSE)) == NULL) || 281*7693SVallish.Vaidyeshwara@Sun.COM ((tok2 = gettoken(NULL, FALSE)) == NULL) || 282*7693SVallish.Vaidyeshwara@Sun.COM ((secp->sc_service = getvalue(tok2, sc_service)) 283*7693SVallish.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] != '-') { 290*7693SVallish.Vaidyeshwara@Sun.COM if (!rpc_gss_mech_to_oid(gss_mech, &secp->sc_gss_mech_type) || 291*7693SVallish.Vaidyeshwara@Sun.COM !rpc_gss_qop_to_num(gss_qop, gss_mech, &secp->sc_qop)) { 292*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 293*7693SVallish.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 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 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 * 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) { 362*7693SVallish.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)) { 367*7693SVallish.Vaidyeshwara@Sun.COM if (!(blank(line) || comment(line))) { 368*7693SVallish.Vaidyeshwara@Sun.COM if ((secname = gettoken(line, FALSE)) == NULL) { 369*7693SVallish.Vaidyeshwara@Sun.COM /* bad line */ 370*7693SVallish.Vaidyeshwara@Sun.COM continue; 371*7693SVallish.Vaidyeshwara@Sun.COM } 372*7693SVallish.Vaidyeshwara@Sun.COM if (strcmp(secname, entryp->sc_name) == 0) { 373*7693SVallish.Vaidyeshwara@Sun.COM tok = NULL; 374*7693SVallish.Vaidyeshwara@Sun.COM if ((tok = gettoken(NULL, FALSE)) == NULL) { 375*7693SVallish.Vaidyeshwara@Sun.COM /* bad line */ 376*7693SVallish.Vaidyeshwara@Sun.COM goto err; 377*7693SVallish.Vaidyeshwara@Sun.COM } 378*7693SVallish.Vaidyeshwara@Sun.COM 379*7693SVallish.Vaidyeshwara@Sun.COM if (atoi(tok) != entryp->sc_nfsnum) 380*7693SVallish.Vaidyeshwara@Sun.COM goto err; 381*7693SVallish.Vaidyeshwara@Sun.COM 382*7693SVallish.Vaidyeshwara@Sun.COM if ((gettoken(NULL, FALSE) == NULL) || 383*7693SVallish.Vaidyeshwara@Sun.COM ((gss_qop = gettoken(NULL, FALSE)) 384*7693SVallish.Vaidyeshwara@Sun.COM == NULL)) { 385*7693SVallish.Vaidyeshwara@Sun.COM goto err; 386*7693SVallish.Vaidyeshwara@Sun.COM } 387*7693SVallish.Vaidyeshwara@Sun.COM break; 388*7693SVallish.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 * 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) 412*7693SVallish.Vaidyeshwara@Sun.COM goto err; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate switch (nfs_sec->sc_rpcnum) { 415*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_UNIX: 416*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_NONE: 417*7693SVallish.Vaidyeshwara@Sun.COM return (NULL); 4180Sstevel@tonic-gate 419*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_DES: 420*7693SVallish.Vaidyeshwara@Sun.COM if (!host2netname(netname, hostname, NULL)) 421*7693SVallish.Vaidyeshwara@Sun.COM goto err; 4220Sstevel@tonic-gate 423*7693SVallish.Vaidyeshwara@Sun.COM return (authdes_seccreate(netname, window, hostname, 424*7693SVallish.Vaidyeshwara@Sun.COM NULL)); 4250Sstevel@tonic-gate 426*7693SVallish.Vaidyeshwara@Sun.COM case RPCSEC_GSS: 427*7693SVallish.Vaidyeshwara@Sun.COM if (cl == NULL) 428*7693SVallish.Vaidyeshwara@Sun.COM goto err; 4290Sstevel@tonic-gate 430*7693SVallish.Vaidyeshwara@Sun.COM if (nfs_sec->sc_gss_mech_type == NULL) { 431*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 432*7693SVallish.Vaidyeshwara@Sun.COM "nfs_create_ah: need mechanism information\n"); 433*7693SVallish.Vaidyeshwara@Sun.COM goto err; 434*7693SVallish.Vaidyeshwara@Sun.COM } 4350Sstevel@tonic-gate 436*7693SVallish.Vaidyeshwara@Sun.COM /* 437*7693SVallish.Vaidyeshwara@Sun.COM * RPCSEC_GSS service names are of the form svc@host.dom 438*7693SVallish.Vaidyeshwara@Sun.COM */ 439*7693SVallish.Vaidyeshwara@Sun.COM (void) sprintf(svc_name, "nfs@%s", hostname); 4400Sstevel@tonic-gate 441*7693SVallish.Vaidyeshwara@Sun.COM gss_qop = nfs_get_qop_name(nfs_sec); 442*7693SVallish.Vaidyeshwara@Sun.COM if (gss_qop == NULL) 443*7693SVallish.Vaidyeshwara@Sun.COM goto err; 4440Sstevel@tonic-gate 445*7693SVallish.Vaidyeshwara@Sun.COM return (rpc_gss_seccreate(cl, svc_name, 446*7693SVallish.Vaidyeshwara@Sun.COM nfs_sec->sc_gss_mech, nfs_sec->sc_service, gss_qop, 447*7693SVallish.Vaidyeshwara@Sun.COM NULL, NULL)); 4480Sstevel@tonic-gate 449*7693SVallish.Vaidyeshwara@Sun.COM default: 450*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, "nfs_create_ah: unknown flavor\n"); 451*7693SVallish.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 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 523*7693SVallish.Vaidyeshwara@Sun.COM if (vers == WNL_V2) { 524*7693SVallish.Vaidyeshwara@Sun.COM wnl_diropargs arg; 525*7693SVallish.Vaidyeshwara@Sun.COM wnl_diropres clnt_res; 5260Sstevel@tonic-gate 527*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&arg.dir, 0, sizeof (wnl_fh)); 528*7693SVallish.Vaidyeshwara@Sun.COM arg.name = fspath; 529*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&clnt_res, 0, sizeof (clnt_res)); 530*7693SVallish.Vaidyeshwara@Sun.COM rpc_stat = clnt_call(clnt, WNLPROC_LOOKUP, 531*7693SVallish.Vaidyeshwara@Sun.COM (xdrproc_t)xdr_wnl_diropargs, (caddr_t)&arg, 532*7693SVallish.Vaidyeshwara@Sun.COM (xdrproc_t)xdr_wnl_diropres, (caddr_t)&clnt_res, 533*7693SVallish.Vaidyeshwara@Sun.COM TIMEOUT); 534*7693SVallish.Vaidyeshwara@Sun.COM if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL_OK) 535*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_DEF_VALID); 536*7693SVallish.Vaidyeshwara@Sun.COM if (rpc_stat != RPC_AUTHERROR) 5370Sstevel@tonic-gate return (SNEGO_FAILURE); 538*7693SVallish.Vaidyeshwara@Sun.COM 539*7693SVallish.Vaidyeshwara@Sun.COM { 540*7693SVallish.Vaidyeshwara@Sun.COM struct rpc_err e; 541*7693SVallish.Vaidyeshwara@Sun.COM wnl_diropres res; 542*7693SVallish.Vaidyeshwara@Sun.COM char *p; 543*7693SVallish.Vaidyeshwara@Sun.COM int tot = 0; 5440Sstevel@tonic-gate 545*7693SVallish.Vaidyeshwara@Sun.COM CLNT_GETERR(clnt, &e); 546*7693SVallish.Vaidyeshwara@Sun.COM if (e.re_why != AUTH_TOOWEAK) 547*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 548*7693SVallish.Vaidyeshwara@Sun.COM 549*7693SVallish.Vaidyeshwara@Sun.COM if ((p = malloc(strlen(fspath)+3)) == NULL) { 550*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, "no memory\n"); 551*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 552*7693SVallish.Vaidyeshwara@Sun.COM } 5530Sstevel@tonic-gate /* 554*7693SVallish.Vaidyeshwara@Sun.COM * Do an x81 LOOKUP 5550Sstevel@tonic-gate */ 556*7693SVallish.Vaidyeshwara@Sun.COM p[0] = (char)WNL_SEC_NEGO; 557*7693SVallish.Vaidyeshwara@Sun.COM strcpy(&p[2], fspath); 558*7693SVallish.Vaidyeshwara@Sun.COM do { 559*7693SVallish.Vaidyeshwara@Sun.COM p[1] = (char)(1+snego->cnt); /* sec index */ 560*7693SVallish.Vaidyeshwara@Sun.COM arg.name = p; 561*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&res, 0, sizeof (wnl_diropres)); 562*7693SVallish.Vaidyeshwara@Sun.COM if (wnlproc_lookup_2(&arg, &res, clnt) != 563*7693SVallish.Vaidyeshwara@Sun.COM RPC_SUCCESS || res.status != WNL_OK) { 564*7693SVallish.Vaidyeshwara@Sun.COM free(p); 565*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 566*7693SVallish.Vaidyeshwara@Sun.COM } 5670Sstevel@tonic-gate 568*7693SVallish.Vaidyeshwara@Sun.COM /* 569*7693SVallish.Vaidyeshwara@Sun.COM * retrieve flavors from filehandle: 570*7693SVallish.Vaidyeshwara@Sun.COM * 1st byte: length 571*7693SVallish.Vaidyeshwara@Sun.COM * 2nd byte: status 572*7693SVallish.Vaidyeshwara@Sun.COM * 3rd & 4th: pad 573*7693SVallish.Vaidyeshwara@Sun.COM * 5th and after: sec flavors. 574*7693SVallish.Vaidyeshwara@Sun.COM */ 575*7693SVallish.Vaidyeshwara@Sun.COM { 576*7693SVallish.Vaidyeshwara@Sun.COM char *c = (char *)&res.wnl_diropres_u. 577*7693SVallish.Vaidyeshwara@Sun.COM wnl_diropres.file; 578*7693SVallish.Vaidyeshwara@Sun.COM int ii; 579*7693SVallish.Vaidyeshwara@Sun.COM int cnt = ((int)*c)/sizeof (uint_t); 580*7693SVallish.Vaidyeshwara@Sun.COM /* LINTED pointer alignment */ 581*7693SVallish.Vaidyeshwara@Sun.COM int *ip = (int *)(c+sizeof (int)); 5820Sstevel@tonic-gate 583*7693SVallish.Vaidyeshwara@Sun.COM tot += cnt; 584*7693SVallish.Vaidyeshwara@Sun.COM if (tot >= MAX_FLAVORS) { 585*7693SVallish.Vaidyeshwara@Sun.COM free(p); 586*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_ARRAY_TOO_SMALL); 587*7693SVallish.Vaidyeshwara@Sun.COM } 588*7693SVallish.Vaidyeshwara@Sun.COM status = (int)*(c+1); 589*7693SVallish.Vaidyeshwara@Sun.COM if (cnt > MAX_V2_CNT || cnt < 0) { 590*7693SVallish.Vaidyeshwara@Sun.COM free(p); 591*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 592*7693SVallish.Vaidyeshwara@Sun.COM } 593*7693SVallish.Vaidyeshwara@Sun.COM for (ii = 0; ii < cnt; ii++) 594*7693SVallish.Vaidyeshwara@Sun.COM snego->array[snego->cnt+ii] = 595*7693SVallish.Vaidyeshwara@Sun.COM ntohl(*(ip+ii)); 596*7693SVallish.Vaidyeshwara@Sun.COM snego->cnt += cnt; 597*7693SVallish.Vaidyeshwara@Sun.COM } 598*7693SVallish.Vaidyeshwara@Sun.COM } while (status); 599*7693SVallish.Vaidyeshwara@Sun.COM free(p); 600*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_SUCCESS); 601*7693SVallish.Vaidyeshwara@Sun.COM } 602*7693SVallish.Vaidyeshwara@Sun.COM } else if (vers == WNL_V3) { 603*7693SVallish.Vaidyeshwara@Sun.COM WNL_LOOKUP3args arg; 604*7693SVallish.Vaidyeshwara@Sun.COM WNL_LOOKUP3res clnt_res; 6050Sstevel@tonic-gate 606*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3)); 607*7693SVallish.Vaidyeshwara@Sun.COM arg.what.name = fspath; 608*7693SVallish.Vaidyeshwara@Sun.COM arg.what.dir.data.data_len = 0; 609*7693SVallish.Vaidyeshwara@Sun.COM arg.what.dir.data.data_val = 0; 610*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&clnt_res, 0, sizeof (clnt_res)); 611*7693SVallish.Vaidyeshwara@Sun.COM rpc_stat = clnt_call(clnt, WNLPROC3_LOOKUP, 612*7693SVallish.Vaidyeshwara@Sun.COM (xdrproc_t)xdr_WNL_LOOKUP3args, (caddr_t)&arg, 613*7693SVallish.Vaidyeshwara@Sun.COM (xdrproc_t)xdr_WNL_LOOKUP3res, (caddr_t)&clnt_res, 614*7693SVallish.Vaidyeshwara@Sun.COM TIMEOUT); 615*7693SVallish.Vaidyeshwara@Sun.COM if (rpc_stat == RPC_SUCCESS && clnt_res.status == WNL3_OK) 616*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_DEF_VALID); 617*7693SVallish.Vaidyeshwara@Sun.COM if (rpc_stat != RPC_AUTHERROR) 6180Sstevel@tonic-gate return (SNEGO_FAILURE); 619*7693SVallish.Vaidyeshwara@Sun.COM 620*7693SVallish.Vaidyeshwara@Sun.COM { 621*7693SVallish.Vaidyeshwara@Sun.COM struct rpc_err e; 622*7693SVallish.Vaidyeshwara@Sun.COM WNL_LOOKUP3res res; 623*7693SVallish.Vaidyeshwara@Sun.COM char *p; 624*7693SVallish.Vaidyeshwara@Sun.COM int tot = 0; 6250Sstevel@tonic-gate 626*7693SVallish.Vaidyeshwara@Sun.COM CLNT_GETERR(clnt, &e); 627*7693SVallish.Vaidyeshwara@Sun.COM if (e.re_why != AUTH_TOOWEAK) 628*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 629*7693SVallish.Vaidyeshwara@Sun.COM 630*7693SVallish.Vaidyeshwara@Sun.COM if ((p = malloc(strlen(fspath)+3)) == NULL) { 631*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, "no memory\n"); 632*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 633*7693SVallish.Vaidyeshwara@Sun.COM } 6340Sstevel@tonic-gate /* 635*7693SVallish.Vaidyeshwara@Sun.COM * Do an x81 LOOKUP 6360Sstevel@tonic-gate */ 637*7693SVallish.Vaidyeshwara@Sun.COM p[0] = (char)WNL_SEC_NEGO; 638*7693SVallish.Vaidyeshwara@Sun.COM strcpy(&p[2], fspath); 639*7693SVallish.Vaidyeshwara@Sun.COM do { 640*7693SVallish.Vaidyeshwara@Sun.COM p[1] = (char)(1+snego->cnt); /* sec index */ 641*7693SVallish.Vaidyeshwara@Sun.COM arg.what.name = p; 642*7693SVallish.Vaidyeshwara@Sun.COM memset((char *)&res, 0, 643*7693SVallish.Vaidyeshwara@Sun.COM sizeof (WNL_LOOKUP3res)); 644*7693SVallish.Vaidyeshwara@Sun.COM if (wnlproc3_lookup_3(&arg, &res, clnt) != 645*7693SVallish.Vaidyeshwara@Sun.COM RPC_SUCCESS || res.status != WNL3_OK) { 646*7693SVallish.Vaidyeshwara@Sun.COM free(p); 647*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 648*7693SVallish.Vaidyeshwara@Sun.COM } 6490Sstevel@tonic-gate 650*7693SVallish.Vaidyeshwara@Sun.COM /* 651*7693SVallish.Vaidyeshwara@Sun.COM * retrieve flavors from filehandle: 652*7693SVallish.Vaidyeshwara@Sun.COM * 653*7693SVallish.Vaidyeshwara@Sun.COM * 1st byte: status 654*7693SVallish.Vaidyeshwara@Sun.COM * 2nd thru 4th: pad 655*7693SVallish.Vaidyeshwara@Sun.COM * 5th and after: sec flavors. 656*7693SVallish.Vaidyeshwara@Sun.COM */ 657*7693SVallish.Vaidyeshwara@Sun.COM { 658*7693SVallish.Vaidyeshwara@Sun.COM char *c = (char *)&res.WNL_LOOKUP3res_u. 659*7693SVallish.Vaidyeshwara@Sun.COM res_ok.object.data.data_val; 660*7693SVallish.Vaidyeshwara@Sun.COM int ii; 661*7693SVallish.Vaidyeshwara@Sun.COM int len = res.WNL_LOOKUP3res_u.res_ok. 662*7693SVallish.Vaidyeshwara@Sun.COM object.data.data_len; 663*7693SVallish.Vaidyeshwara@Sun.COM int cnt; 664*7693SVallish.Vaidyeshwara@Sun.COM /* LINTED pointer alignment */ 665*7693SVallish.Vaidyeshwara@Sun.COM int *ip = (int *)(c+sizeof (int)); 6660Sstevel@tonic-gate 667*7693SVallish.Vaidyeshwara@Sun.COM cnt = len/sizeof (uint_t) - 1; 668*7693SVallish.Vaidyeshwara@Sun.COM tot += cnt; 669*7693SVallish.Vaidyeshwara@Sun.COM if (tot >= MAX_FLAVORS) { 670*7693SVallish.Vaidyeshwara@Sun.COM free(p); 671*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_ARRAY_TOO_SMALL); 672*7693SVallish.Vaidyeshwara@Sun.COM } 673*7693SVallish.Vaidyeshwara@Sun.COM status = (int)(*c); 674*7693SVallish.Vaidyeshwara@Sun.COM if (cnt > MAX_V3_CNT || cnt < 0) { 675*7693SVallish.Vaidyeshwara@Sun.COM free(p); 676*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_FAILURE); 677*7693SVallish.Vaidyeshwara@Sun.COM } 678*7693SVallish.Vaidyeshwara@Sun.COM for (ii = 0; ii < cnt; ii++) 679*7693SVallish.Vaidyeshwara@Sun.COM snego->array[snego->cnt+ii] = 680*7693SVallish.Vaidyeshwara@Sun.COM ntohl(*(ip+ii)); 681*7693SVallish.Vaidyeshwara@Sun.COM snego->cnt += cnt; 682*7693SVallish.Vaidyeshwara@Sun.COM } 683*7693SVallish.Vaidyeshwara@Sun.COM } while (status); 684*7693SVallish.Vaidyeshwara@Sun.COM free(p); 685*7693SVallish.Vaidyeshwara@Sun.COM return (SNEGO_SUCCESS); 686*7693SVallish.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 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)) { 714*7693SVallish.Vaidyeshwara@Sun.COM if (!(blank(line) || comment(line))) { 715*7693SVallish.Vaidyeshwara@Sun.COM switch (whichway) { 716*7693SVallish.Vaidyeshwara@Sun.COM case GETBYNAME: 717*7693SVallish.Vaidyeshwara@Sun.COM if (matchname(line, name, entryp)) { 718*7693SVallish.Vaidyeshwara@Sun.COM goto found; 719*7693SVallish.Vaidyeshwara@Sun.COM } 720*7693SVallish.Vaidyeshwara@Sun.COM break; 7210Sstevel@tonic-gate 722*7693SVallish.Vaidyeshwara@Sun.COM case GETBYNUM: 723*7693SVallish.Vaidyeshwara@Sun.COM if (matchnum(line, num, entryp)) { 724*7693SVallish.Vaidyeshwara@Sun.COM goto found; 725*7693SVallish.Vaidyeshwara@Sun.COM } 726*7693SVallish.Vaidyeshwara@Sun.COM break; 727*7693SVallish.Vaidyeshwara@Sun.COM 728*7693SVallish.Vaidyeshwara@Sun.COM default: 729*7693SVallish.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 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, 757*7693SVallish.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 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, 773*7693SVallish.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 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 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) { 810*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_UNIX: 811*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_NONE: 812*7693SVallish.Vaidyeshwara@Sun.COM break; 8130Sstevel@tonic-gate 814*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_DES: 815*7693SVallish.Vaidyeshwara@Sun.COM /* LINTED pointer alignment */ 816*7693SVallish.Vaidyeshwara@Sun.COM dkdata = (dh_k4_clntdata_t *)secdata->data; 817*7693SVallish.Vaidyeshwara@Sun.COM if (dkdata) { 818*7693SVallish.Vaidyeshwara@Sun.COM if (dkdata->netname) 819*7693SVallish.Vaidyeshwara@Sun.COM free(dkdata->netname); 820*7693SVallish.Vaidyeshwara@Sun.COM if (dkdata->syncaddr.buf) 821*7693SVallish.Vaidyeshwara@Sun.COM free(dkdata->syncaddr.buf); 822*7693SVallish.Vaidyeshwara@Sun.COM free(dkdata); 823*7693SVallish.Vaidyeshwara@Sun.COM } 824*7693SVallish.Vaidyeshwara@Sun.COM break; 8250Sstevel@tonic-gate 826*7693SVallish.Vaidyeshwara@Sun.COM case RPCSEC_GSS: 827*7693SVallish.Vaidyeshwara@Sun.COM /* LINTED pointer alignment */ 828*7693SVallish.Vaidyeshwara@Sun.COM gdata = (gss_clntdata_t *)secdata->data; 829*7693SVallish.Vaidyeshwara@Sun.COM if (gdata) { 830*7693SVallish.Vaidyeshwara@Sun.COM if (gdata->mechanism.elements) 831*7693SVallish.Vaidyeshwara@Sun.COM free(gdata->mechanism.elements); 832*7693SVallish.Vaidyeshwara@Sun.COM free(gdata); 833*7693SVallish.Vaidyeshwara@Sun.COM } 834*7693SVallish.Vaidyeshwara@Sun.COM break; 8350Sstevel@tonic-gate 836*7693SVallish.Vaidyeshwara@Sun.COM default: 837*7693SVallish.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 * 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) { 891*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_UNIX: 892*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_NONE: 893*7693SVallish.Vaidyeshwara@Sun.COM secdata->data = NULL; 894*7693SVallish.Vaidyeshwara@Sun.COM break; 8950Sstevel@tonic-gate 896*7693SVallish.Vaidyeshwara@Sun.COM case AUTH_DES: 897*7693SVallish.Vaidyeshwara@Sun.COM /* 898*7693SVallish.Vaidyeshwara@Sun.COM * If hostname is in the format of host.nisdomain 899*7693SVallish.Vaidyeshwara@Sun.COM * the netname will be constructed with 900*7693SVallish.Vaidyeshwara@Sun.COM * this nisdomain name rather than the default 901*7693SVallish.Vaidyeshwara@Sun.COM * domain of the machine. 902*7693SVallish.Vaidyeshwara@Sun.COM */ 903*7693SVallish.Vaidyeshwara@Sun.COM if (!host2netname(netname, hostname, NULL)) { 904*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, "host2netname: %s: unknown\n", 905*7693SVallish.Vaidyeshwara@Sun.COM hostname); 906*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 907*7693SVallish.Vaidyeshwara@Sun.COM } 908*7693SVallish.Vaidyeshwara@Sun.COM dkdata = malloc(sizeof (dh_k4_clntdata_t)); 909*7693SVallish.Vaidyeshwara@Sun.COM if (!dkdata) { 910*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 911*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: no memory\n"); 912*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 913*7693SVallish.Vaidyeshwara@Sun.COM } 914*7693SVallish.Vaidyeshwara@Sun.COM (void) memset((char *)dkdata, 0, 915*7693SVallish.Vaidyeshwara@Sun.COM sizeof (dh_k4_clntdata_t)); 916*7693SVallish.Vaidyeshwara@Sun.COM if ((dkdata->netname = strdup(netname)) == NULL) { 917*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 918*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: no memory\n"); 919*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 920*7693SVallish.Vaidyeshwara@Sun.COM } 921*7693SVallish.Vaidyeshwara@Sun.COM dkdata->netnamelen = strlen(netname); 922*7693SVallish.Vaidyeshwara@Sun.COM dkdata->knconf = knconf; 923*7693SVallish.Vaidyeshwara@Sun.COM dkdata->syncaddr = *syncaddr; 924*7693SVallish.Vaidyeshwara@Sun.COM dkdata->syncaddr.buf = malloc(syncaddr->len); 925*7693SVallish.Vaidyeshwara@Sun.COM if (dkdata->syncaddr.buf == NULL) { 926*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 927*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: no memory\n"); 928*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 929*7693SVallish.Vaidyeshwara@Sun.COM } 930*7693SVallish.Vaidyeshwara@Sun.COM (void) memcpy(dkdata->syncaddr.buf, syncaddr->buf, 931*7693SVallish.Vaidyeshwara@Sun.COM syncaddr->len); 932*7693SVallish.Vaidyeshwara@Sun.COM secdata->data = (caddr_t)dkdata; 933*7693SVallish.Vaidyeshwara@Sun.COM break; 9340Sstevel@tonic-gate 935*7693SVallish.Vaidyeshwara@Sun.COM case RPCSEC_GSS: 936*7693SVallish.Vaidyeshwara@Sun.COM if (secp->sc_gss_mech_type == NULL) { 937*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 938*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: need mechanism information\n"); 939*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 940*7693SVallish.Vaidyeshwara@Sun.COM } 941*7693SVallish.Vaidyeshwara@Sun.COM 942*7693SVallish.Vaidyeshwara@Sun.COM gdata = malloc(sizeof (gss_clntdata_t)); 943*7693SVallish.Vaidyeshwara@Sun.COM if (!gdata) { 944*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 945*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: no memory\n"); 946*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 947*7693SVallish.Vaidyeshwara@Sun.COM } 9480Sstevel@tonic-gate 949*7693SVallish.Vaidyeshwara@Sun.COM (void) strcpy(gdata->uname, "nfs"); 950*7693SVallish.Vaidyeshwara@Sun.COM if (!parsehostname(hostname, gdata->inst, 951*7693SVallish.Vaidyeshwara@Sun.COM gdata->realm)) { 952*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 953*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: bad host name\n"); 954*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 955*7693SVallish.Vaidyeshwara@Sun.COM } 9560Sstevel@tonic-gate 957*7693SVallish.Vaidyeshwara@Sun.COM gdata->mechanism.length = 958*7693SVallish.Vaidyeshwara@Sun.COM secp->sc_gss_mech_type->length; 959*7693SVallish.Vaidyeshwara@Sun.COM if (!(gdata->mechanism.elements = 960*7693SVallish.Vaidyeshwara@Sun.COM malloc(secp->sc_gss_mech_type->length))) { 961*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 962*7693SVallish.Vaidyeshwara@Sun.COM "nfs_clnt_secdata: no memory\n"); 963*7693SVallish.Vaidyeshwara@Sun.COM goto err_out; 964*7693SVallish.Vaidyeshwara@Sun.COM } 965*7693SVallish.Vaidyeshwara@Sun.COM (void) memcpy(gdata->mechanism.elements, 966*7693SVallish.Vaidyeshwara@Sun.COM secp->sc_gss_mech_type->elements, 967*7693SVallish.Vaidyeshwara@Sun.COM secp->sc_gss_mech_type->length); 968*7693SVallish.Vaidyeshwara@Sun.COM 969*7693SVallish.Vaidyeshwara@Sun.COM gdata->qop = secp->sc_qop; 970*7693SVallish.Vaidyeshwara@Sun.COM gdata->service = secp->sc_service; 971*7693SVallish.Vaidyeshwara@Sun.COM secdata->data = (caddr_t)gdata; 972*7693SVallish.Vaidyeshwara@Sun.COM break; 973*7693SVallish.Vaidyeshwara@Sun.COM 974*7693SVallish.Vaidyeshwara@Sun.COM default: 975*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, "nfs_clnt_secdata: unknown flavor\n"); 976*7693SVallish.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 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: 1010*7693SVallish.Vaidyeshwara@Sun.COM if (!host2netname(netname, host, NULL)) { 1011*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 10120Sstevel@tonic-gate "nfs_get_root_principal: unknown host: %s\n", host); 1013*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 1014*7693SVallish.Vaidyeshwara@Sun.COM } 1015*7693SVallish.Vaidyeshwara@Sun.COM *rootname_p = strdup(netname); 1016*7693SVallish.Vaidyeshwara@Sun.COM if (!*rootname_p) { 1017*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 1018*7693SVallish.Vaidyeshwara@Sun.COM "nfs_get_root_principal: no memory\n"); 1019*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 1020*7693SVallish.Vaidyeshwara@Sun.COM } 1021*7693SVallish.Vaidyeshwara@Sun.COM break; 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate case RPCSEC_GSS: 1024*7693SVallish.Vaidyeshwara@Sun.COM if (!parsehostname(host, node, secdomain)) { 1025*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 1026*7693SVallish.Vaidyeshwara@Sun.COM "nfs_get_root_principal: bad host name\n"); 1027*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 1028*7693SVallish.Vaidyeshwara@Sun.COM } 1029*7693SVallish.Vaidyeshwara@Sun.COM if (!rpc_gss_get_principal_name(&gssname, 1030*7693SVallish.Vaidyeshwara@Sun.COM seconfig->sc_gss_mech, "root", node, secdomain)) { 1031*7693SVallish.Vaidyeshwara@Sun.COM syslog(LOG_ERR, 10320Sstevel@tonic-gate "nfs_get_root_principal: can not get principal name : %s\n", host); 1033*7693SVallish.Vaidyeshwara@Sun.COM return (FALSE); 1034*7693SVallish.Vaidyeshwara@Sun.COM } 10350Sstevel@tonic-gate 1036*7693SVallish.Vaidyeshwara@Sun.COM *rootname_p = (caddr_t)gssname; 1037*7693SVallish.Vaidyeshwara@Sun.COM break; 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate default: 1040*7693SVallish.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 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