xref: /onnv-gate/usr/src/lib/libsmbfs/smb/rcfile.c (revision 10023:71bf38dba3d6)
16007Sthurlow /*
26007Sthurlow  * Copyright (c) 2000, Boris Popov
36007Sthurlow  * All rights reserved.
46007Sthurlow  *
56007Sthurlow  * Redistribution and use in source and binary forms, with or without
66007Sthurlow  * modification, are permitted provided that the following conditions
76007Sthurlow  * are met:
86007Sthurlow  * 1. Redistributions of source code must retain the above copyright
96007Sthurlow  *    notice, this list of conditions and the following disclaimer.
106007Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow  *    notice, this list of conditions and the following disclaimer in the
126007Sthurlow  *    documentation and/or other materials provided with the distribution.
136007Sthurlow  * 3. All advertising materials mentioning features or use of this software
146007Sthurlow  *    must display the following acknowledgement:
156007Sthurlow  *    This product includes software developed by Boris Popov.
166007Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow  *    may be used to endorse or promote products derived from this software
186007Sthurlow  *    without specific prior written permission.
196007Sthurlow  *
206007Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow  * SUCH DAMAGE.
316007Sthurlow  *
326007Sthurlow  * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $
336007Sthurlow  */
346007Sthurlow 
356007Sthurlow #include <fcntl.h>
366007Sthurlow #include <sys/types.h>
376007Sthurlow #include <sys/queue.h>
386007Sthurlow #include <sys/stat.h>
39*10023SGordon.Ross@Sun.COM 
406007Sthurlow #include <ctype.h>
416007Sthurlow #include <errno.h>
426007Sthurlow #include <stdio.h>
436007Sthurlow #include <string.h>
446007Sthurlow #include <strings.h>
456007Sthurlow #include <stdlib.h>
46*10023SGordon.Ross@Sun.COM #include <synch.h>
47*10023SGordon.Ross@Sun.COM #include <unistd.h>
486007Sthurlow #include <pwd.h>
49*10023SGordon.Ross@Sun.COM #include <libintl.h>
506007Sthurlow 
516007Sthurlow #include <cflib.h>
526007Sthurlow #include "rcfile_priv.h"
53*10023SGordon.Ross@Sun.COM 
54*10023SGordon.Ross@Sun.COM #include <assert.h>
55*10023SGordon.Ross@Sun.COM 
56*10023SGordon.Ross@Sun.COM #if 0 /* before SMF */
57*10023SGordon.Ross@Sun.COM #define	SMB_CFG_FILE	"/etc/nsmb.conf"
58*10023SGordon.Ross@Sun.COM #define	OLD_SMB_CFG_FILE	"/usr/local/etc/nsmb.conf"
59*10023SGordon.Ross@Sun.COM #endif
60*10023SGordon.Ross@Sun.COM #define	SMBFS_SHARECTL_CMD	"/usr/sbin/sharectl get smbfs"
61*10023SGordon.Ross@Sun.COM 
628271SGordon.Ross@Sun.COM extern int smb_debug;
636007Sthurlow 
646007Sthurlow static struct rcfile *rc_cachelookup(const char *filename);
65*10023SGordon.Ross@Sun.COM static struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
666007Sthurlow static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
67*10023SGordon.Ross@Sun.COM static int		rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
68*10023SGordon.Ross@Sun.COM static struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *key);
696007Sthurlow static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
706007Sthurlow     const char *value);
716007Sthurlow static void rc_key_free(struct rckey *p);
726007Sthurlow static void rc_parse(struct rcfile *rcp);
736007Sthurlow 
74*10023SGordon.Ross@Sun.COM /* lock for the variables below */
75*10023SGordon.Ross@Sun.COM mutex_t rcfile_mutex = DEFAULTMUTEX;
76*10023SGordon.Ross@Sun.COM 
77*10023SGordon.Ross@Sun.COM SLIST_HEAD(rcfile_head, rcfile);
78*10023SGordon.Ross@Sun.COM static struct rcfile_head pf_head = {NULL};
79*10023SGordon.Ross@Sun.COM struct rcfile *smb_rc;
80*10023SGordon.Ross@Sun.COM int home_nsmbrc;
816007Sthurlow int insecure_nsmbrc;
826007Sthurlow 
836007Sthurlow /*
846007Sthurlow  * open rcfile and load its content, if already open - return previous handle
856007Sthurlow  */
86*10023SGordon.Ross@Sun.COM static int
rc_open(const char * filename,const char * mode,struct rcfile ** rcfile)876007Sthurlow rc_open(const char *filename, const char *mode, struct rcfile **rcfile)
886007Sthurlow {
89*10023SGordon.Ross@Sun.COM 	struct stat statbuf;
906007Sthurlow 	struct rcfile *rcp;
916007Sthurlow 	FILE *f;
92*10023SGordon.Ross@Sun.COM 
93*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
946007Sthurlow 
956007Sthurlow 	rcp = rc_cachelookup(filename);
966007Sthurlow 	if (rcp) {
976007Sthurlow 		*rcfile = rcp;
986007Sthurlow 		return (0);
996007Sthurlow 	}
1006007Sthurlow 	f = fopen(filename, mode);
1016007Sthurlow 	if (f == NULL)
1026007Sthurlow 		return (errno);
1036007Sthurlow 	insecure_nsmbrc = 0;
1046007Sthurlow 	if (fstat(fileno(f), &statbuf) >= 0 &&
1056007Sthurlow 	    (statbuf.st_mode & 077) != 0)
1066007Sthurlow 		insecure_nsmbrc = 1;
1076007Sthurlow 	rcp = malloc(sizeof (struct rcfile));
1086007Sthurlow 	if (rcp == NULL) {
1096007Sthurlow 		fclose(f);
1106007Sthurlow 		return (ENOMEM);
1116007Sthurlow 	}
1126007Sthurlow 	bzero(rcp, sizeof (struct rcfile));
1136007Sthurlow 	rcp->rf_name = strdup(filename);
1146007Sthurlow 	rcp->rf_f = f;
1156007Sthurlow 	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
1166007Sthurlow 	rc_parse(rcp);
1176007Sthurlow 	*rcfile = rcp;
1186007Sthurlow 	return (0);
1196007Sthurlow }
1206007Sthurlow 
121*10023SGordon.Ross@Sun.COM static int
rc_merge(const char * filename,struct rcfile ** rcfile)1226007Sthurlow rc_merge(const char *filename, struct rcfile **rcfile)
1236007Sthurlow {
124*10023SGordon.Ross@Sun.COM 	struct stat statbuf;
1256007Sthurlow 	struct rcfile *rcp = *rcfile;
1266007Sthurlow 	FILE *f, *t;
1276007Sthurlow 
128*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
129*10023SGordon.Ross@Sun.COM 
1306007Sthurlow 	insecure_nsmbrc = 0;
1316007Sthurlow 	if (rcp == NULL) {
1326007Sthurlow 		return (rc_open(filename, "r", rcfile));
1336007Sthurlow 	}
1346007Sthurlow 	f = fopen(filename, "r");
1356007Sthurlow 	if (f == NULL)
1366007Sthurlow 		return (errno);
137*10023SGordon.Ross@Sun.COM 	insecure_nsmbrc = 0;
138*10023SGordon.Ross@Sun.COM 	if (fstat(fileno(f), &statbuf) >= 0 &&
139*10023SGordon.Ross@Sun.COM 	    (statbuf.st_mode & 077) != 0)
140*10023SGordon.Ross@Sun.COM 		insecure_nsmbrc = 1;
1416007Sthurlow 	t = rcp->rf_f;
1426007Sthurlow 	rcp->rf_f = f;
1436007Sthurlow 	rc_parse(rcp);
1446007Sthurlow 	rcp->rf_f = t;
1456007Sthurlow 	fclose(f);
1466007Sthurlow 	return (0);
1476007Sthurlow }
1486007Sthurlow 
149*10023SGordon.Ross@Sun.COM /*
150*10023SGordon.Ross@Sun.COM  * Like rc_open, but does popen of command:
151*10023SGordon.Ross@Sun.COM  * sharectl get smbfs
152*10023SGordon.Ross@Sun.COM  */
153*10023SGordon.Ross@Sun.COM static int
rc_popen_cmd(const char * command,struct rcfile ** rcfile)154*10023SGordon.Ross@Sun.COM rc_popen_cmd(const char *command, struct rcfile **rcfile)
1556007Sthurlow {
156*10023SGordon.Ross@Sun.COM 	struct rcfile *rcp;
157*10023SGordon.Ross@Sun.COM 	FILE *f;
1586007Sthurlow 
159*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
160*10023SGordon.Ross@Sun.COM 
1616007Sthurlow 	f = popen(command, "r");
1626007Sthurlow 	if (f == NULL)
1636007Sthurlow 		return (errno);
164*10023SGordon.Ross@Sun.COM 	insecure_nsmbrc = 0;
165*10023SGordon.Ross@Sun.COM 
166*10023SGordon.Ross@Sun.COM 	rcp = malloc(sizeof (struct rcfile));
1676007Sthurlow 	if (rcp == NULL) {
168*10023SGordon.Ross@Sun.COM 		fclose(f);
169*10023SGordon.Ross@Sun.COM 		return (ENOMEM);
1706007Sthurlow 	}
171*10023SGordon.Ross@Sun.COM 	bzero(rcp, sizeof (struct rcfile));
172*10023SGordon.Ross@Sun.COM 	rcp->rf_name = strdup(command);
173*10023SGordon.Ross@Sun.COM 	rcp->rf_f = f;
174*10023SGordon.Ross@Sun.COM 	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
175*10023SGordon.Ross@Sun.COM 	rc_parse(rcp);
176*10023SGordon.Ross@Sun.COM 	*rcfile = rcp;
177*10023SGordon.Ross@Sun.COM 	/* fclose(f) in rc_close */
1786007Sthurlow 	return (0);
1796007Sthurlow }
1806007Sthurlow 
181*10023SGordon.Ross@Sun.COM static int
rc_close(struct rcfile * rcp)1826007Sthurlow rc_close(struct rcfile *rcp)
1836007Sthurlow {
1846007Sthurlow 	struct rcsection *p, *n;
1856007Sthurlow 
186*10023SGordon.Ross@Sun.COM 	mutex_lock(&rcfile_mutex);
187*10023SGordon.Ross@Sun.COM 
1886007Sthurlow 	fclose(rcp->rf_f);
1896007Sthurlow 	for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
1906007Sthurlow 		n = p;
1916007Sthurlow 		p = SLIST_NEXT(p, rs_next);
1926007Sthurlow 		rc_freesect(rcp, n);
1936007Sthurlow 	}
1946007Sthurlow 	free(rcp->rf_name);
1956007Sthurlow 	SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
1966007Sthurlow 	free(rcp);
197*10023SGordon.Ross@Sun.COM 
198*10023SGordon.Ross@Sun.COM 	mutex_unlock(&rcfile_mutex);
1996007Sthurlow 	return (0);
2006007Sthurlow }
2016007Sthurlow 
2026007Sthurlow static struct rcfile *
rc_cachelookup(const char * filename)2036007Sthurlow rc_cachelookup(const char *filename)
2046007Sthurlow {
2056007Sthurlow 	struct rcfile *p;
2066007Sthurlow 
207*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
208*10023SGordon.Ross@Sun.COM 
2096007Sthurlow 	SLIST_FOREACH(p, &pf_head, rf_next)
2106007Sthurlow 		if (strcmp(filename, p->rf_name) == 0)
2116007Sthurlow 			return (p);
2126007Sthurlow 	return (0);
2136007Sthurlow }
2146007Sthurlow 
215*10023SGordon.Ross@Sun.COM static struct rcsection *
rc_findsect(struct rcfile * rcp,const char * sectname)2166007Sthurlow rc_findsect(struct rcfile *rcp, const char *sectname)
2176007Sthurlow {
2186007Sthurlow 	struct rcsection *p;
2196007Sthurlow 
220*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
221*10023SGordon.Ross@Sun.COM 
2226007Sthurlow 	SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
2236007Sthurlow 		if (strcasecmp(p->rs_name, sectname) == 0)
2246007Sthurlow 			return (p);
2256007Sthurlow 	return (NULL);
2266007Sthurlow }
2276007Sthurlow 
2286007Sthurlow static struct rcsection *
rc_addsect(struct rcfile * rcp,const char * sectname)2296007Sthurlow rc_addsect(struct rcfile *rcp, const char *sectname)
2306007Sthurlow {
2316007Sthurlow 	struct rcsection *p;
2326007Sthurlow 
233*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
234*10023SGordon.Ross@Sun.COM 
2356007Sthurlow 	p = rc_findsect(rcp, sectname);
2366007Sthurlow 	if (p)
2376007Sthurlow 		return (p);
2386007Sthurlow 	p = malloc(sizeof (*p));
2396007Sthurlow 	if (!p)
2406007Sthurlow 		return (NULL);
2416007Sthurlow 	p->rs_name = strdup(sectname);
2426007Sthurlow 	SLIST_INIT(&p->rs_keys);
2436007Sthurlow 	SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
2446007Sthurlow 	return (p);
2456007Sthurlow }
2466007Sthurlow 
2476007Sthurlow static int
rc_freesect(struct rcfile * rcp,struct rcsection * rsp)2486007Sthurlow rc_freesect(struct rcfile *rcp, struct rcsection *rsp)
2496007Sthurlow {
2506007Sthurlow 	struct rckey *p, *n;
2516007Sthurlow 
252*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
253*10023SGordon.Ross@Sun.COM 
2546007Sthurlow 	SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next);
2556007Sthurlow 	for (p = SLIST_FIRST(&rsp->rs_keys); p; ) {
2566007Sthurlow 		n = p;
2576007Sthurlow 		p = SLIST_NEXT(p, rk_next);
2586007Sthurlow 		rc_key_free(n);
2596007Sthurlow 	}
2606007Sthurlow 	free(rsp->rs_name);
2616007Sthurlow 	free(rsp);
2626007Sthurlow 	return (0);
2636007Sthurlow }
2646007Sthurlow 
265*10023SGordon.Ross@Sun.COM static struct rckey *
rc_sect_findkey(struct rcsection * rsp,const char * keyname)2666007Sthurlow rc_sect_findkey(struct rcsection *rsp, const char *keyname)
2676007Sthurlow {
2686007Sthurlow 	struct rckey *p;
2696007Sthurlow 
270*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
271*10023SGordon.Ross@Sun.COM 
2726007Sthurlow 	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
2736007Sthurlow 		if (strcmp(p->rk_name, keyname) == 0)
2746007Sthurlow 			return (p);
2756007Sthurlow 	return (NULL);
2766007Sthurlow }
2776007Sthurlow 
2786007Sthurlow static struct rckey *
rc_sect_addkey(struct rcsection * rsp,const char * name,const char * value)2796007Sthurlow rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value)
2806007Sthurlow {
2816007Sthurlow 	struct rckey *p;
2826007Sthurlow 
283*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
284*10023SGordon.Ross@Sun.COM 
2856007Sthurlow 	p = rc_sect_findkey(rsp, name);
2866007Sthurlow 	if (!p) {
2876007Sthurlow 		p = malloc(sizeof (*p));
2886007Sthurlow 		if (!p)
2896007Sthurlow 			return (NULL);
2906007Sthurlow 		SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
2916007Sthurlow 		p->rk_name = strdup(name);
2926007Sthurlow 		p->rk_value = value ? strdup(value) : strdup("");
2936007Sthurlow 	}
2946007Sthurlow 	return (p);
2956007Sthurlow }
2966007Sthurlow 
2976007Sthurlow #if 0
2986007Sthurlow void
2996007Sthurlow rc_sect_delkey(struct rcsection *rsp, struct rckey *p)
3006007Sthurlow {
3016007Sthurlow 
3026007Sthurlow 	SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next);
3036007Sthurlow 	rc_key_free(p);
3046007Sthurlow }
3056007Sthurlow #endif
3066007Sthurlow 
3076007Sthurlow static void
rc_key_free(struct rckey * p)3086007Sthurlow rc_key_free(struct rckey *p)
3096007Sthurlow {
3106007Sthurlow 	free(p->rk_value);
3116007Sthurlow 	free(p->rk_name);
3126007Sthurlow 	free(p);
3136007Sthurlow }
3146007Sthurlow 
3156007Sthurlow 
316*10023SGordon.Ross@Sun.COM static char *minauth_values[] = {
317*10023SGordon.Ross@Sun.COM 	"none",
318*10023SGordon.Ross@Sun.COM 	"lm",
319*10023SGordon.Ross@Sun.COM 	"ntlm",
320*10023SGordon.Ross@Sun.COM 	"ntlmv2",
3216007Sthurlow 	"kerberos",
3226007Sthurlow 	NULL
3236007Sthurlow };
3246007Sthurlow 
3256007Sthurlow static int
eval_minauth(char * auth)3266007Sthurlow eval_minauth(char *auth)
3276007Sthurlow {
3286007Sthurlow 	int i;
3296007Sthurlow 
330*10023SGordon.Ross@Sun.COM 	for (i = 0; minauth_values[i]; i++)
331*10023SGordon.Ross@Sun.COM 		if (strcmp(auth, minauth_values[i]) == 0)
332*10023SGordon.Ross@Sun.COM 			return (i);
333*10023SGordon.Ross@Sun.COM 	return (-1);
3346007Sthurlow }
3356007Sthurlow 
3366007Sthurlow /*
337*10023SGordon.Ross@Sun.COM  * Ensure that "minauth" is set to the highest level
3386007Sthurlow  */
339*10023SGordon.Ross@Sun.COM /*ARGSUSED*/
3406007Sthurlow static void
set_value(struct rcfile * rcp,struct rcsection * rsp,struct rckey * rkp,char * ptr)3416007Sthurlow set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
3426007Sthurlow     char *ptr)
3436007Sthurlow {
3446007Sthurlow 	int now, new;
345*10023SGordon.Ross@Sun.COM #ifdef DEBUG
346*10023SGordon.Ross@Sun.COM 	char *from;
347*10023SGordon.Ross@Sun.COM 
348*10023SGordon.Ross@Sun.COM 	if (smb_debug)
349*10023SGordon.Ross@Sun.COM 		from = (home_nsmbrc) ?
350*10023SGordon.Ross@Sun.COM 		    "user file" : "SMF";
351*10023SGordon.Ross@Sun.COM #endif
3526007Sthurlow 
3536007Sthurlow 	if (strcmp(rkp->rk_name, "minauth") == 0) {
3546007Sthurlow 		now = eval_minauth(rkp->rk_value);
3556007Sthurlow 		new = eval_minauth(ptr);
356*10023SGordon.Ross@Sun.COM 		if (new <= now) {
3576007Sthurlow #ifdef DEBUG
3588271SGordon.Ross@Sun.COM 			if (smb_debug)
359*10023SGordon.Ross@Sun.COM 				fprintf(stderr,
360*10023SGordon.Ross@Sun.COM 				    "set_value: rejecting %s=%s"
361*10023SGordon.Ross@Sun.COM 				    " in %s from %s\n",
362*10023SGordon.Ross@Sun.COM 				    rkp->rk_name, ptr,
363*10023SGordon.Ross@Sun.COM 				    rsp->rs_name, from);
3646007Sthurlow #endif
3656007Sthurlow 			return;
3666007Sthurlow 		}
3676007Sthurlow 	}
3686007Sthurlow #ifdef DEBUG
3698271SGordon.Ross@Sun.COM 	if (smb_debug)
370*10023SGordon.Ross@Sun.COM 		fprintf(stderr,
371*10023SGordon.Ross@Sun.COM 		    "set_value: applying %s=%s in %s from %s\n",
372*10023SGordon.Ross@Sun.COM 		    rkp->rk_name, ptr, rsp->rs_name, from);
3736007Sthurlow #endif
3746007Sthurlow 	rkp->rk_value = strdup(ptr);
3756007Sthurlow }
3766007Sthurlow 
377*10023SGordon.Ross@Sun.COM 
378*10023SGordon.Ross@Sun.COM /* states in rc_parse */
379*10023SGordon.Ross@Sun.COM enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
380*10023SGordon.Ross@Sun.COM 
3816007Sthurlow static void
rc_parse(struct rcfile * rcp)3826007Sthurlow rc_parse(struct rcfile *rcp)
3836007Sthurlow {
3846007Sthurlow 	FILE *f = rcp->rf_f;
3856007Sthurlow 	int state = stNewLine, c;
3866007Sthurlow 	struct rcsection *rsp = NULL;
3876007Sthurlow 	struct rckey *rkp = NULL;
3886007Sthurlow 	char buf[2048];
3896007Sthurlow 	char *next = buf, *last = &buf[sizeof (buf)-1];
3906007Sthurlow 
391*10023SGordon.Ross@Sun.COM 	assert(MUTEX_HELD(&rcfile_mutex));
392*10023SGordon.Ross@Sun.COM 
3936007Sthurlow 	while ((c = getc(f)) != EOF) {
3946007Sthurlow 		if (c == '\r')
3956007Sthurlow 			continue;
3966007Sthurlow 		if (state == stNewLine) {
3976007Sthurlow 			next = buf;
3986007Sthurlow 			if (isspace(c))
3996007Sthurlow 				continue;	/* skip leading junk */
4006007Sthurlow 			if (c == '[') {
4016007Sthurlow 				state = stHeader;
4026007Sthurlow 				rsp = NULL;
4036007Sthurlow 				continue;
4046007Sthurlow 			}
4056007Sthurlow 			if (c == '#' || c == ';') {
4066007Sthurlow 				state = stSkipToEOL;
4076007Sthurlow 			} else {		/* something meaningfull */
4086007Sthurlow 				state = stGetKey;
4096007Sthurlow 			}
4106007Sthurlow 		}
4116007Sthurlow 		/* ignore long lines */
4126007Sthurlow 		if (state == stSkipToEOL || next == last) {
4136007Sthurlow 			if (c == '\n') {
4146007Sthurlow 				state = stNewLine;
4156007Sthurlow 				next = buf;
4166007Sthurlow 			}
4176007Sthurlow 			continue;
4186007Sthurlow 		}
4196007Sthurlow 		if (state == stHeader) {
4206007Sthurlow 			if (c == ']') {
4216007Sthurlow 				*next = 0;
4226007Sthurlow 				next = buf;
4236007Sthurlow 				rsp = rc_addsect(rcp, buf);
4246007Sthurlow 				state = stSkipToEOL;
4256007Sthurlow 			} else
4266007Sthurlow 				*next++ = c;
4276007Sthurlow 			continue;
4286007Sthurlow 		}
4296007Sthurlow 		if (state == stGetKey) {
4306007Sthurlow 			/* side effect: 'key name=' */
4316007Sthurlow 			if (c == ' ' || c == '\t')
4326007Sthurlow 				continue;	/* become 'keyname=' */
4336007Sthurlow 			if (c == '\n') {	/* silently ignore ... */
4346007Sthurlow 				state = stNewLine;
4356007Sthurlow 				continue;
4366007Sthurlow 			}
4376007Sthurlow 			if (c != '=') {
4386007Sthurlow 				*next++ = c;
4396007Sthurlow 				continue;
4406007Sthurlow 			}
4416007Sthurlow 			*next = 0;
4426007Sthurlow 			if (rsp == NULL) {
4436007Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4446007Sthurlow 				    "Key '%s' defined before section\n"), buf);
4456007Sthurlow 				state = stSkipToEOL;
4466007Sthurlow 				continue;
4476007Sthurlow 			}
448*10023SGordon.Ross@Sun.COM 			if (home_nsmbrc != 0 && (
449*10023SGordon.Ross@Sun.COM 			    strcmp(buf, "nbns") == 0 ||
4506007Sthurlow 			    strcmp(buf, "nbns_enable") == 0 ||
4518271SGordon.Ross@Sun.COM 			    strcmp(buf, "nbns_broadcast") == 0 ||
4528271SGordon.Ross@Sun.COM 			    strcmp(buf, "signing") == 0)) {
4536007Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4546007Sthurlow 				    "option %s may not be set "
4556007Sthurlow 				    "in user .nsmbrc file\n"), buf);
4566007Sthurlow 				next = buf;
4576007Sthurlow 				state = stNewLine;
4586007Sthurlow 				continue;
4596007Sthurlow 			}
460*10023SGordon.Ross@Sun.COM 			if (insecure_nsmbrc != 0 &&
461*10023SGordon.Ross@Sun.COM 			    strcmp(buf, "password") == 0) {
4626007Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4636007Sthurlow 				    "Warning: .nsmbrc file not secure, "
4646007Sthurlow 				    "ignoring passwords\n"));
4656007Sthurlow 				next = buf;
4666007Sthurlow 				state = stNewLine;
4676007Sthurlow 				continue;
4686007Sthurlow 			}
4696007Sthurlow 			rkp = rc_sect_addkey(rsp, buf, NULL);
4706007Sthurlow 			next = buf;
4716007Sthurlow 			state = stGetValue;
4726007Sthurlow 			continue;
4736007Sthurlow 		}
4746007Sthurlow 		/* only stGetValue left */
4756007Sthurlow 		if (state != stGetValue) {
4766007Sthurlow 			fprintf(stderr, dgettext(TEXT_DOMAIN,
4776007Sthurlow 			    "Well, I can't parse file '%s'\n"), rcp->rf_name);
4786007Sthurlow 			state = stSkipToEOL;
4796007Sthurlow 		}
4806007Sthurlow 		if (c != '\n') {
4816007Sthurlow 			*next++ = c;
4826007Sthurlow 			continue;
4836007Sthurlow 		}
4846007Sthurlow 		*next = 0;
4856007Sthurlow 		set_value(rcp, rsp, rkp, buf);
4866007Sthurlow 		state = stNewLine;
4876007Sthurlow 		rkp = NULL;
4886007Sthurlow 	} 	/* while */
4896007Sthurlow 	if (c == EOF && state == stGetValue) {
4906007Sthurlow 		*next = 0;
4916007Sthurlow 		set_value(rcp, rsp, rkp, buf);
4926007Sthurlow 	}
4936007Sthurlow }
4946007Sthurlow 
4956007Sthurlow int
rc_getstringptr(struct rcfile * rcp,const char * section,const char * key,char ** dest)4966007Sthurlow rc_getstringptr(struct rcfile *rcp, const char *section, const char *key,
4976007Sthurlow 	char **dest)
4986007Sthurlow {
4996007Sthurlow 	struct rcsection *rsp;
5006007Sthurlow 	struct rckey *rkp;
501*10023SGordon.Ross@Sun.COM 	int err;
502*10023SGordon.Ross@Sun.COM 
503*10023SGordon.Ross@Sun.COM 	mutex_lock(&rcfile_mutex);
5046007Sthurlow 
5056007Sthurlow 	*dest = NULL;
5066007Sthurlow 	rsp = rc_findsect(rcp, section);
507*10023SGordon.Ross@Sun.COM 	if (!rsp) {
508*10023SGordon.Ross@Sun.COM 		err = ENOENT;
509*10023SGordon.Ross@Sun.COM 		goto out;
510*10023SGordon.Ross@Sun.COM 	}
5116007Sthurlow 	rkp = rc_sect_findkey(rsp, key);
512*10023SGordon.Ross@Sun.COM 	if (!rkp) {
513*10023SGordon.Ross@Sun.COM 		err = ENOENT;
514*10023SGordon.Ross@Sun.COM 		goto out;
515*10023SGordon.Ross@Sun.COM 	}
5166007Sthurlow 	*dest = rkp->rk_value;
517*10023SGordon.Ross@Sun.COM 	err = 0;
518*10023SGordon.Ross@Sun.COM 
519*10023SGordon.Ross@Sun.COM out:
520*10023SGordon.Ross@Sun.COM 	mutex_unlock(&rcfile_mutex);
521*10023SGordon.Ross@Sun.COM 	return (err);
5226007Sthurlow }
5236007Sthurlow 
5246007Sthurlow int
rc_getstring(struct rcfile * rcp,const char * section,const char * key,size_t maxlen,char * dest)5256007Sthurlow rc_getstring(struct rcfile *rcp, const char *section, const char *key,
5266007Sthurlow 	size_t maxlen, char *dest)
5276007Sthurlow {
5286007Sthurlow 	char *value;
5296007Sthurlow 	int error;
5306007Sthurlow 
5316007Sthurlow 	error = rc_getstringptr(rcp, section, key, &value);
5326007Sthurlow 	if (error)
5336007Sthurlow 		return (error);
5346007Sthurlow 	if (strlen(value) >= maxlen) {
535*10023SGordon.Ross@Sun.COM 		fprintf(stderr, dgettext(TEXT_DOMAIN,
5366007Sthurlow 		    "line too long for key '%s' in section '%s', max = %d\n"),
5376007Sthurlow 		    key, section, maxlen);
5386007Sthurlow 		return (EINVAL);
5396007Sthurlow 	}
5406007Sthurlow 	strcpy(dest, value);
5416007Sthurlow 	return (0);
5426007Sthurlow }
5436007Sthurlow 
5446007Sthurlow int
rc_getint(struct rcfile * rcp,const char * section,const char * key,int * value)5456007Sthurlow rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value)
5466007Sthurlow {
5476007Sthurlow 	struct rcsection *rsp;
5486007Sthurlow 	struct rckey *rkp;
549*10023SGordon.Ross@Sun.COM 	int err;
550*10023SGordon.Ross@Sun.COM 
551*10023SGordon.Ross@Sun.COM 	mutex_lock(&rcfile_mutex);
5526007Sthurlow 
5536007Sthurlow 	rsp = rc_findsect(rcp, section);
554*10023SGordon.Ross@Sun.COM 	if (!rsp) {
555*10023SGordon.Ross@Sun.COM 		err = ENOENT;
556*10023SGordon.Ross@Sun.COM 		goto out;
557*10023SGordon.Ross@Sun.COM 	}
5586007Sthurlow 	rkp = rc_sect_findkey(rsp, key);
559*10023SGordon.Ross@Sun.COM 	if (!rkp) {
560*10023SGordon.Ross@Sun.COM 		err = ENOENT;
561*10023SGordon.Ross@Sun.COM 		goto out;
562*10023SGordon.Ross@Sun.COM 	}
5636007Sthurlow 	errno = 0;
5646007Sthurlow 	*value = strtol(rkp->rk_value, NULL, 0);
565*10023SGordon.Ross@Sun.COM 	if ((err = errno) != 0) {
566*10023SGordon.Ross@Sun.COM 		fprintf(stderr, dgettext(TEXT_DOMAIN,
5676007Sthurlow 		    "invalid int value '%s' for key '%s' in section '%s'\n"),
5686007Sthurlow 		    rkp->rk_value, key, section);
5696007Sthurlow 	}
570*10023SGordon.Ross@Sun.COM 
571*10023SGordon.Ross@Sun.COM out:
572*10023SGordon.Ross@Sun.COM 	mutex_unlock(&rcfile_mutex);
573*10023SGordon.Ross@Sun.COM 	return (err);
5746007Sthurlow }
5756007Sthurlow 
5766007Sthurlow /*
5776007Sthurlow  * 1,yes,true
5786007Sthurlow  * 0,no,false
5796007Sthurlow  */
5806007Sthurlow int
rc_getbool(struct rcfile * rcp,const char * section,const char * key,int * value)5816007Sthurlow rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value)
5826007Sthurlow {
5836007Sthurlow 	struct rcsection *rsp;
5846007Sthurlow 	struct rckey *rkp;
5856007Sthurlow 	char *p;
586*10023SGordon.Ross@Sun.COM 	int err;
587*10023SGordon.Ross@Sun.COM 
588*10023SGordon.Ross@Sun.COM 	mutex_lock(&rcfile_mutex);
5896007Sthurlow 
5906007Sthurlow 	rsp = rc_findsect(rcp, section);
591*10023SGordon.Ross@Sun.COM 	if (!rsp) {
592*10023SGordon.Ross@Sun.COM 		err = ENOENT;
593*10023SGordon.Ross@Sun.COM 		goto out;
594*10023SGordon.Ross@Sun.COM 	}
5956007Sthurlow 	rkp = rc_sect_findkey(rsp, key);
596*10023SGordon.Ross@Sun.COM 	if (!rkp) {
597*10023SGordon.Ross@Sun.COM 		err = ENOENT;
598*10023SGordon.Ross@Sun.COM 		goto out;
599*10023SGordon.Ross@Sun.COM 	}
6006007Sthurlow 	p = rkp->rk_value;
6016007Sthurlow 	while (*p && isspace(*p)) p++;
6026007Sthurlow 	if (*p == '0' ||
6036007Sthurlow 	    strcasecmp(p, "no") == 0 ||
6046007Sthurlow 	    strcasecmp(p, "false") == 0) {
6056007Sthurlow 		*value = 0;
606*10023SGordon.Ross@Sun.COM 		err = 0;
607*10023SGordon.Ross@Sun.COM 		goto out;
6086007Sthurlow 	}
6096007Sthurlow 	if (*p == '1' ||
6106007Sthurlow 	    strcasecmp(p, "yes") == 0 ||
6116007Sthurlow 	    strcasecmp(p, "true") == 0) {
6126007Sthurlow 		*value = 1;
613*10023SGordon.Ross@Sun.COM 		err = 0;
614*10023SGordon.Ross@Sun.COM 		goto out;
6156007Sthurlow 	}
6166007Sthurlow 	fprintf(stderr, dgettext(TEXT_DOMAIN,
6176007Sthurlow 	    "invalid boolean value '%s' for key '%s' in section '%s' \n"),
6186007Sthurlow 	    p, key, section);
619*10023SGordon.Ross@Sun.COM 	err = EINVAL;
620*10023SGordon.Ross@Sun.COM 
621*10023SGordon.Ross@Sun.COM out:
622*10023SGordon.Ross@Sun.COM 	mutex_unlock(&rcfile_mutex);
623*10023SGordon.Ross@Sun.COM 	return (err);
624*10023SGordon.Ross@Sun.COM }
625*10023SGordon.Ross@Sun.COM 
626*10023SGordon.Ross@Sun.COM #ifdef DEBUG
627*10023SGordon.Ross@Sun.COM void
dump_props(char * where)628*10023SGordon.Ross@Sun.COM dump_props(char *where)
629*10023SGordon.Ross@Sun.COM {
630*10023SGordon.Ross@Sun.COM 	struct rcsection *rsp = NULL;
631*10023SGordon.Ross@Sun.COM 	struct rckey *rkp = NULL;
632*10023SGordon.Ross@Sun.COM 
633*10023SGordon.Ross@Sun.COM 	fprintf(stderr, "Settings %s\n", where);
634*10023SGordon.Ross@Sun.COM 	SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) {
635*10023SGordon.Ross@Sun.COM 		fprintf(stderr, "section=%s\n", rsp->rs_name);
636*10023SGordon.Ross@Sun.COM 		fflush(stderr);
637*10023SGordon.Ross@Sun.COM 
638*10023SGordon.Ross@Sun.COM 		SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) {
639*10023SGordon.Ross@Sun.COM 			fprintf(stderr, "  key=%s, value=%s\n",
640*10023SGordon.Ross@Sun.COM 			    rkp->rk_name, rkp->rk_value);
641*10023SGordon.Ross@Sun.COM 			fflush(stderr);
642*10023SGordon.Ross@Sun.COM 		}
643*10023SGordon.Ross@Sun.COM 	}
644*10023SGordon.Ross@Sun.COM }
645*10023SGordon.Ross@Sun.COM #endif
646*10023SGordon.Ross@Sun.COM 
647*10023SGordon.Ross@Sun.COM /*
648*10023SGordon.Ross@Sun.COM  * first parse "sharectl get smbfs, then $HOME/.nsmbrc
649*10023SGordon.Ross@Sun.COM  * This is called by library consumers (commands)
650*10023SGordon.Ross@Sun.COM  */
651*10023SGordon.Ross@Sun.COM int
smb_open_rcfile(char * home)652*10023SGordon.Ross@Sun.COM smb_open_rcfile(char *home)
653*10023SGordon.Ross@Sun.COM {
654*10023SGordon.Ross@Sun.COM 	char *fn;
655*10023SGordon.Ross@Sun.COM 	int len, error = 0;
656*10023SGordon.Ross@Sun.COM 
657*10023SGordon.Ross@Sun.COM 	mutex_lock(&rcfile_mutex);
658*10023SGordon.Ross@Sun.COM 
659*10023SGordon.Ross@Sun.COM 	smb_rc = NULL;
660*10023SGordon.Ross@Sun.COM #if 0	/* before SMF */
661*10023SGordon.Ross@Sun.COM 	fn = SMB_CFG_FILE;
662*10023SGordon.Ross@Sun.COM 	error = rc_open(fn, &smb_rc);
663*10023SGordon.Ross@Sun.COM #else
664*10023SGordon.Ross@Sun.COM 	fn = SMBFS_SHARECTL_CMD;
665*10023SGordon.Ross@Sun.COM 	error = rc_popen_cmd(fn, &smb_rc);
666*10023SGordon.Ross@Sun.COM #endif
667*10023SGordon.Ross@Sun.COM 	if (error != 0 && error != ENOENT) {
668*10023SGordon.Ross@Sun.COM 		/* Error from fopen. strerror is OK. */
669*10023SGordon.Ross@Sun.COM 		fprintf(stderr, dgettext(TEXT_DOMAIN,
670*10023SGordon.Ross@Sun.COM 		    "Can't open %s: %s\n"), fn, strerror(errno));
671*10023SGordon.Ross@Sun.COM 	}
672*10023SGordon.Ross@Sun.COM #ifdef DEBUG
673*10023SGordon.Ross@Sun.COM 	if (smb_debug)
674*10023SGordon.Ross@Sun.COM 		dump_props(fn);
675*10023SGordon.Ross@Sun.COM #endif
676*10023SGordon.Ross@Sun.COM 
677*10023SGordon.Ross@Sun.COM 	if (home) {
678*10023SGordon.Ross@Sun.COM 		len = strlen(home) + 20;
679*10023SGordon.Ross@Sun.COM 		fn = malloc(len);
680*10023SGordon.Ross@Sun.COM 		snprintf(fn, len, "%s/.nsmbrc", home);
681*10023SGordon.Ross@Sun.COM 		home_nsmbrc = 1;
682*10023SGordon.Ross@Sun.COM 		error = rc_merge(fn, &smb_rc);
683*10023SGordon.Ross@Sun.COM 		if (error != 0 && error != ENOENT) {
684*10023SGordon.Ross@Sun.COM 			fprintf(stderr, dgettext(TEXT_DOMAIN,
685*10023SGordon.Ross@Sun.COM 			    "Can't open %s: %s\n"), fn, strerror(errno));
686*10023SGordon.Ross@Sun.COM 		}
687*10023SGordon.Ross@Sun.COM 		home_nsmbrc = 0;
688*10023SGordon.Ross@Sun.COM #ifdef DEBUG
689*10023SGordon.Ross@Sun.COM 		if (smb_debug)
690*10023SGordon.Ross@Sun.COM 			dump_props(fn);
691*10023SGordon.Ross@Sun.COM #endif
692*10023SGordon.Ross@Sun.COM 		free(fn);
693*10023SGordon.Ross@Sun.COM 	}
694*10023SGordon.Ross@Sun.COM 
695*10023SGordon.Ross@Sun.COM 	/* Mostly ignore error returns above. */
696*10023SGordon.Ross@Sun.COM 	if (smb_rc == NULL)
697*10023SGordon.Ross@Sun.COM 		error = ENOENT;
698*10023SGordon.Ross@Sun.COM 	else
699*10023SGordon.Ross@Sun.COM 		error = 0;
700*10023SGordon.Ross@Sun.COM 
701*10023SGordon.Ross@Sun.COM 	mutex_unlock(&rcfile_mutex);
702*10023SGordon.Ross@Sun.COM 
703*10023SGordon.Ross@Sun.COM 	return (error);
7046007Sthurlow }
7056007Sthurlow 
7066007Sthurlow /*
707*10023SGordon.Ross@Sun.COM  * This is called by library consumers (commands)
7086007Sthurlow  */
709*10023SGordon.Ross@Sun.COM void
smb_close_rcfile(void)710*10023SGordon.Ross@Sun.COM smb_close_rcfile(void)
7116007Sthurlow {
712*10023SGordon.Ross@Sun.COM 	struct rcfile *rcp;
7136007Sthurlow 
714*10023SGordon.Ross@Sun.COM 	if ((rcp = smb_rc) != NULL) {
715*10023SGordon.Ross@Sun.COM 		smb_rc = NULL;
716*10023SGordon.Ross@Sun.COM 		rc_close(rcp);
7176007Sthurlow 	}
7186007Sthurlow }
719