xref: /titanic_51/usr/src/lib/libsmbfs/smb/rcfile.c (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2000, Boris Popov
34bff34e3Sthurlow  * All rights reserved.
44bff34e3Sthurlow  *
54bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
64bff34e3Sthurlow  * modification, are permitted provided that the following conditions
74bff34e3Sthurlow  * are met:
84bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
94bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
104bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
114bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
124bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
134bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
144bff34e3Sthurlow  *    must display the following acknowledgement:
154bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
164bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
174bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
184bff34e3Sthurlow  *    without specific prior written permission.
194bff34e3Sthurlow  *
204bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
214bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
244bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304bff34e3Sthurlow  * SUCH DAMAGE.
314bff34e3Sthurlow  *
324bff34e3Sthurlow  * $Id: rcfile.c,v 1.1.1.2 2001/07/06 22:38:43 conrad Exp $
334bff34e3Sthurlow  */
344bff34e3Sthurlow 
354bff34e3Sthurlow #include <fcntl.h>
364bff34e3Sthurlow #include <sys/types.h>
374bff34e3Sthurlow #include <sys/queue.h>
384bff34e3Sthurlow #include <sys/stat.h>
39*613a2f6bSGordon Ross 
404bff34e3Sthurlow #include <ctype.h>
414bff34e3Sthurlow #include <errno.h>
424bff34e3Sthurlow #include <stdio.h>
434bff34e3Sthurlow #include <string.h>
444bff34e3Sthurlow #include <strings.h>
454bff34e3Sthurlow #include <stdlib.h>
46*613a2f6bSGordon Ross #include <synch.h>
474bff34e3Sthurlow #include <unistd.h>
48*613a2f6bSGordon Ross #include <pwd.h>
49*613a2f6bSGordon Ross #include <libintl.h>
504bff34e3Sthurlow 
514bff34e3Sthurlow #include <cflib.h>
524bff34e3Sthurlow #include "rcfile_priv.h"
53*613a2f6bSGordon Ross 
54*613a2f6bSGordon Ross #include <assert.h>
55*613a2f6bSGordon Ross 
56*613a2f6bSGordon Ross #if 0 /* before SMF */
57*613a2f6bSGordon Ross #define	SMB_CFG_FILE	"/etc/nsmb.conf"
58*613a2f6bSGordon Ross #define	OLD_SMB_CFG_FILE	"/usr/local/etc/nsmb.conf"
59*613a2f6bSGordon Ross #endif
60*613a2f6bSGordon Ross #define	SMBFS_SHARECTL_CMD	"/usr/sbin/sharectl get smbfs"
61*613a2f6bSGordon Ross 
629c9af259SGordon Ross extern int smb_debug;
634bff34e3Sthurlow 
644bff34e3Sthurlow static struct rcfile *rc_cachelookup(const char *filename);
65*613a2f6bSGordon Ross static struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
664bff34e3Sthurlow static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
674bff34e3Sthurlow static int		rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
68*613a2f6bSGordon Ross static struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *key);
694bff34e3Sthurlow static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
704bff34e3Sthurlow     const char *value);
714bff34e3Sthurlow static void rc_key_free(struct rckey *p);
724bff34e3Sthurlow static void rc_parse(struct rcfile *rcp);
734bff34e3Sthurlow 
74*613a2f6bSGordon Ross /* lock for the variables below */
75*613a2f6bSGordon Ross mutex_t rcfile_mutex = DEFAULTMUTEX;
76*613a2f6bSGordon Ross 
77*613a2f6bSGordon Ross SLIST_HEAD(rcfile_head, rcfile);
78*613a2f6bSGordon Ross static struct rcfile_head pf_head = {NULL};
79*613a2f6bSGordon Ross struct rcfile *smb_rc;
80*613a2f6bSGordon Ross int home_nsmbrc;
814bff34e3Sthurlow int insecure_nsmbrc;
824bff34e3Sthurlow 
834bff34e3Sthurlow /*
844bff34e3Sthurlow  * open rcfile and load its content, if already open - return previous handle
854bff34e3Sthurlow  */
86*613a2f6bSGordon Ross static int
874bff34e3Sthurlow rc_open(const char *filename, const char *mode, struct rcfile **rcfile)
884bff34e3Sthurlow {
89*613a2f6bSGordon Ross 	struct stat statbuf;
904bff34e3Sthurlow 	struct rcfile *rcp;
914bff34e3Sthurlow 	FILE *f;
92*613a2f6bSGordon Ross 
93*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
944bff34e3Sthurlow 
954bff34e3Sthurlow 	rcp = rc_cachelookup(filename);
964bff34e3Sthurlow 	if (rcp) {
974bff34e3Sthurlow 		*rcfile = rcp;
984bff34e3Sthurlow 		return (0);
994bff34e3Sthurlow 	}
1004bff34e3Sthurlow 	f = fopen(filename, mode);
1014bff34e3Sthurlow 	if (f == NULL)
1024bff34e3Sthurlow 		return (errno);
1034bff34e3Sthurlow 	insecure_nsmbrc = 0;
1044bff34e3Sthurlow 	if (fstat(fileno(f), &statbuf) >= 0 &&
1054bff34e3Sthurlow 	    (statbuf.st_mode & 077) != 0)
1064bff34e3Sthurlow 		insecure_nsmbrc = 1;
1074bff34e3Sthurlow 	rcp = malloc(sizeof (struct rcfile));
1084bff34e3Sthurlow 	if (rcp == NULL) {
1094bff34e3Sthurlow 		fclose(f);
1104bff34e3Sthurlow 		return (ENOMEM);
1114bff34e3Sthurlow 	}
1124bff34e3Sthurlow 	bzero(rcp, sizeof (struct rcfile));
1134bff34e3Sthurlow 	rcp->rf_name = strdup(filename);
1144bff34e3Sthurlow 	rcp->rf_f = f;
1154bff34e3Sthurlow 	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
1164bff34e3Sthurlow 	rc_parse(rcp);
1174bff34e3Sthurlow 	*rcfile = rcp;
1184bff34e3Sthurlow 	return (0);
1194bff34e3Sthurlow }
1204bff34e3Sthurlow 
121*613a2f6bSGordon Ross static int
1224bff34e3Sthurlow rc_merge(const char *filename, struct rcfile **rcfile)
1234bff34e3Sthurlow {
124*613a2f6bSGordon Ross 	struct stat statbuf;
1254bff34e3Sthurlow 	struct rcfile *rcp = *rcfile;
1264bff34e3Sthurlow 	FILE *f, *t;
1274bff34e3Sthurlow 
128*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
129*613a2f6bSGordon Ross 
1304bff34e3Sthurlow 	insecure_nsmbrc = 0;
1314bff34e3Sthurlow 	if (rcp == NULL) {
1324bff34e3Sthurlow 		return (rc_open(filename, "r", rcfile));
1334bff34e3Sthurlow 	}
1344bff34e3Sthurlow 	f = fopen(filename, "r");
1354bff34e3Sthurlow 	if (f == NULL)
1364bff34e3Sthurlow 		return (errno);
137*613a2f6bSGordon Ross 	insecure_nsmbrc = 0;
138*613a2f6bSGordon Ross 	if (fstat(fileno(f), &statbuf) >= 0 &&
139*613a2f6bSGordon Ross 	    (statbuf.st_mode & 077) != 0)
140*613a2f6bSGordon Ross 		insecure_nsmbrc = 1;
1414bff34e3Sthurlow 	t = rcp->rf_f;
1424bff34e3Sthurlow 	rcp->rf_f = f;
1434bff34e3Sthurlow 	rc_parse(rcp);
1444bff34e3Sthurlow 	rcp->rf_f = t;
1454bff34e3Sthurlow 	fclose(f);
1464bff34e3Sthurlow 	return (0);
1474bff34e3Sthurlow }
1484bff34e3Sthurlow 
149*613a2f6bSGordon Ross /*
150*613a2f6bSGordon Ross  * Like rc_open, but does popen of command:
151*613a2f6bSGordon Ross  * sharectl get smbfs
152*613a2f6bSGordon Ross  */
153*613a2f6bSGordon Ross static int
154*613a2f6bSGordon Ross rc_popen_cmd(const char *command, struct rcfile **rcfile)
1554bff34e3Sthurlow {
156*613a2f6bSGordon Ross 	struct rcfile *rcp;
157*613a2f6bSGordon Ross 	FILE *f;
1584bff34e3Sthurlow 
159*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
160*613a2f6bSGordon Ross 
1614bff34e3Sthurlow 	f = popen(command, "r");
1624bff34e3Sthurlow 	if (f == NULL)
1634bff34e3Sthurlow 		return (errno);
164*613a2f6bSGordon Ross 	insecure_nsmbrc = 0;
165*613a2f6bSGordon Ross 
1664bff34e3Sthurlow 	rcp = malloc(sizeof (struct rcfile));
1674bff34e3Sthurlow 	if (rcp == NULL) {
1684bff34e3Sthurlow 		fclose(f);
1694bff34e3Sthurlow 		return (ENOMEM);
1704bff34e3Sthurlow 	}
1714bff34e3Sthurlow 	bzero(rcp, sizeof (struct rcfile));
1724bff34e3Sthurlow 	rcp->rf_name = strdup(command);
1734bff34e3Sthurlow 	rcp->rf_f = f;
1744bff34e3Sthurlow 	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
1754bff34e3Sthurlow 	rc_parse(rcp);
176*613a2f6bSGordon Ross 	*rcfile = rcp;
177*613a2f6bSGordon Ross 	/* fclose(f) in rc_close */
1784bff34e3Sthurlow 	return (0);
1794bff34e3Sthurlow }
1804bff34e3Sthurlow 
181*613a2f6bSGordon Ross static int
1824bff34e3Sthurlow rc_close(struct rcfile *rcp)
1834bff34e3Sthurlow {
1844bff34e3Sthurlow 	struct rcsection *p, *n;
1854bff34e3Sthurlow 
186*613a2f6bSGordon Ross 	mutex_lock(&rcfile_mutex);
187*613a2f6bSGordon Ross 
1884bff34e3Sthurlow 	fclose(rcp->rf_f);
1894bff34e3Sthurlow 	for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
1904bff34e3Sthurlow 		n = p;
1914bff34e3Sthurlow 		p = SLIST_NEXT(p, rs_next);
1924bff34e3Sthurlow 		rc_freesect(rcp, n);
1934bff34e3Sthurlow 	}
1944bff34e3Sthurlow 	free(rcp->rf_name);
1954bff34e3Sthurlow 	SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
1964bff34e3Sthurlow 	free(rcp);
197*613a2f6bSGordon Ross 
198*613a2f6bSGordon Ross 	mutex_unlock(&rcfile_mutex);
1994bff34e3Sthurlow 	return (0);
2004bff34e3Sthurlow }
2014bff34e3Sthurlow 
2024bff34e3Sthurlow static struct rcfile *
2034bff34e3Sthurlow rc_cachelookup(const char *filename)
2044bff34e3Sthurlow {
2054bff34e3Sthurlow 	struct rcfile *p;
2064bff34e3Sthurlow 
207*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
208*613a2f6bSGordon Ross 
2094bff34e3Sthurlow 	SLIST_FOREACH(p, &pf_head, rf_next)
2104bff34e3Sthurlow 		if (strcmp(filename, p->rf_name) == 0)
2114bff34e3Sthurlow 			return (p);
2124bff34e3Sthurlow 	return (0);
2134bff34e3Sthurlow }
2144bff34e3Sthurlow 
215*613a2f6bSGordon Ross static struct rcsection *
2164bff34e3Sthurlow rc_findsect(struct rcfile *rcp, const char *sectname)
2174bff34e3Sthurlow {
2184bff34e3Sthurlow 	struct rcsection *p;
2194bff34e3Sthurlow 
220*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
221*613a2f6bSGordon Ross 
2224bff34e3Sthurlow 	SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
2234bff34e3Sthurlow 		if (strcasecmp(p->rs_name, sectname) == 0)
2244bff34e3Sthurlow 			return (p);
2254bff34e3Sthurlow 	return (NULL);
2264bff34e3Sthurlow }
2274bff34e3Sthurlow 
2284bff34e3Sthurlow static struct rcsection *
2294bff34e3Sthurlow rc_addsect(struct rcfile *rcp, const char *sectname)
2304bff34e3Sthurlow {
2314bff34e3Sthurlow 	struct rcsection *p;
2324bff34e3Sthurlow 
233*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
234*613a2f6bSGordon Ross 
2354bff34e3Sthurlow 	p = rc_findsect(rcp, sectname);
2364bff34e3Sthurlow 	if (p)
2374bff34e3Sthurlow 		return (p);
2384bff34e3Sthurlow 	p = malloc(sizeof (*p));
2394bff34e3Sthurlow 	if (!p)
2404bff34e3Sthurlow 		return (NULL);
2414bff34e3Sthurlow 	p->rs_name = strdup(sectname);
2424bff34e3Sthurlow 	SLIST_INIT(&p->rs_keys);
2434bff34e3Sthurlow 	SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
2444bff34e3Sthurlow 	return (p);
2454bff34e3Sthurlow }
2464bff34e3Sthurlow 
2474bff34e3Sthurlow static int
2484bff34e3Sthurlow rc_freesect(struct rcfile *rcp, struct rcsection *rsp)
2494bff34e3Sthurlow {
2504bff34e3Sthurlow 	struct rckey *p, *n;
2514bff34e3Sthurlow 
252*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
253*613a2f6bSGordon Ross 
2544bff34e3Sthurlow 	SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next);
2554bff34e3Sthurlow 	for (p = SLIST_FIRST(&rsp->rs_keys); p; ) {
2564bff34e3Sthurlow 		n = p;
2574bff34e3Sthurlow 		p = SLIST_NEXT(p, rk_next);
2584bff34e3Sthurlow 		rc_key_free(n);
2594bff34e3Sthurlow 	}
2604bff34e3Sthurlow 	free(rsp->rs_name);
2614bff34e3Sthurlow 	free(rsp);
2624bff34e3Sthurlow 	return (0);
2634bff34e3Sthurlow }
2644bff34e3Sthurlow 
265*613a2f6bSGordon Ross static struct rckey *
2664bff34e3Sthurlow rc_sect_findkey(struct rcsection *rsp, const char *keyname)
2674bff34e3Sthurlow {
2684bff34e3Sthurlow 	struct rckey *p;
2694bff34e3Sthurlow 
270*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
271*613a2f6bSGordon Ross 
2724bff34e3Sthurlow 	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
2734bff34e3Sthurlow 		if (strcmp(p->rk_name, keyname) == 0)
2744bff34e3Sthurlow 			return (p);
2754bff34e3Sthurlow 	return (NULL);
2764bff34e3Sthurlow }
2774bff34e3Sthurlow 
2784bff34e3Sthurlow static struct rckey *
2794bff34e3Sthurlow rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value)
2804bff34e3Sthurlow {
2814bff34e3Sthurlow 	struct rckey *p;
2824bff34e3Sthurlow 
283*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
284*613a2f6bSGordon Ross 
2854bff34e3Sthurlow 	p = rc_sect_findkey(rsp, name);
2864bff34e3Sthurlow 	if (!p) {
2874bff34e3Sthurlow 		p = malloc(sizeof (*p));
2884bff34e3Sthurlow 		if (!p)
2894bff34e3Sthurlow 			return (NULL);
2904bff34e3Sthurlow 		SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
2914bff34e3Sthurlow 		p->rk_name = strdup(name);
2924bff34e3Sthurlow 		p->rk_value = value ? strdup(value) : strdup("");
2934bff34e3Sthurlow 	}
2944bff34e3Sthurlow 	return (p);
2954bff34e3Sthurlow }
2964bff34e3Sthurlow 
2974bff34e3Sthurlow #if 0
2984bff34e3Sthurlow void
2994bff34e3Sthurlow rc_sect_delkey(struct rcsection *rsp, struct rckey *p)
3004bff34e3Sthurlow {
3014bff34e3Sthurlow 
3024bff34e3Sthurlow 	SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next);
3034bff34e3Sthurlow 	rc_key_free(p);
3044bff34e3Sthurlow }
3054bff34e3Sthurlow #endif
3064bff34e3Sthurlow 
3074bff34e3Sthurlow static void
3084bff34e3Sthurlow rc_key_free(struct rckey *p)
3094bff34e3Sthurlow {
3104bff34e3Sthurlow 	free(p->rk_value);
3114bff34e3Sthurlow 	free(p->rk_name);
3124bff34e3Sthurlow 	free(p);
3134bff34e3Sthurlow }
3144bff34e3Sthurlow 
3154bff34e3Sthurlow 
316*613a2f6bSGordon Ross static char *minauth_values[] = {
3174bff34e3Sthurlow 	"none",
318*613a2f6bSGordon Ross 	"lm",
319*613a2f6bSGordon Ross 	"ntlm",
320*613a2f6bSGordon Ross 	"ntlmv2",
321*613a2f6bSGordon Ross 	"kerberos",
3224bff34e3Sthurlow 	NULL
3234bff34e3Sthurlow };
3244bff34e3Sthurlow 
3254bff34e3Sthurlow static int
3264bff34e3Sthurlow eval_minauth(char *auth)
3274bff34e3Sthurlow {
3284bff34e3Sthurlow 	int i;
3294bff34e3Sthurlow 
330*613a2f6bSGordon Ross 	for (i = 0; minauth_values[i]; i++)
331*613a2f6bSGordon Ross 		if (strcmp(auth, minauth_values[i]) == 0)
3324bff34e3Sthurlow 			return (i);
333*613a2f6bSGordon Ross 	return (-1);
3344bff34e3Sthurlow }
3354bff34e3Sthurlow 
3364bff34e3Sthurlow /*
337*613a2f6bSGordon Ross  * Ensure that "minauth" is set to the highest level
3384bff34e3Sthurlow  */
339*613a2f6bSGordon Ross /*ARGSUSED*/
3404bff34e3Sthurlow static void
3414bff34e3Sthurlow set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
3424bff34e3Sthurlow     char *ptr)
3434bff34e3Sthurlow {
3444bff34e3Sthurlow 	int now, new;
345*613a2f6bSGordon Ross #ifdef DEBUG
346*613a2f6bSGordon Ross 	char *from;
347*613a2f6bSGordon Ross 
348*613a2f6bSGordon Ross 	if (smb_debug)
349*613a2f6bSGordon Ross 		from = (home_nsmbrc) ?
350*613a2f6bSGordon Ross 		    "user file" : "SMF";
351*613a2f6bSGordon Ross #endif
3524bff34e3Sthurlow 
3534bff34e3Sthurlow 	if (strcmp(rkp->rk_name, "minauth") == 0) {
3544bff34e3Sthurlow 		now = eval_minauth(rkp->rk_value);
3554bff34e3Sthurlow 		new = eval_minauth(ptr);
356*613a2f6bSGordon Ross 		if (new <= now) {
3574bff34e3Sthurlow #ifdef DEBUG
3589c9af259SGordon Ross 			if (smb_debug)
359*613a2f6bSGordon Ross 				fprintf(stderr,
360*613a2f6bSGordon Ross 				    "set_value: rejecting %s=%s"
361*613a2f6bSGordon Ross 				    " in %s from %s\n",
362*613a2f6bSGordon Ross 				    rkp->rk_name, ptr,
363*613a2f6bSGordon Ross 				    rsp->rs_name, from);
3644bff34e3Sthurlow #endif
3654bff34e3Sthurlow 			return;
3664bff34e3Sthurlow 		}
3674bff34e3Sthurlow 	}
3684bff34e3Sthurlow #ifdef DEBUG
3699c9af259SGordon Ross 	if (smb_debug)
370*613a2f6bSGordon Ross 		fprintf(stderr,
371*613a2f6bSGordon Ross 		    "set_value: applying %s=%s in %s from %s\n",
372*613a2f6bSGordon Ross 		    rkp->rk_name, ptr, rsp->rs_name, from);
3734bff34e3Sthurlow #endif
3744bff34e3Sthurlow 	rkp->rk_value = strdup(ptr);
3754bff34e3Sthurlow }
3764bff34e3Sthurlow 
377*613a2f6bSGordon Ross 
378*613a2f6bSGordon Ross /* states in rc_parse */
379*613a2f6bSGordon Ross enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
380*613a2f6bSGordon Ross 
3814bff34e3Sthurlow static void
3824bff34e3Sthurlow rc_parse(struct rcfile *rcp)
3834bff34e3Sthurlow {
3844bff34e3Sthurlow 	FILE *f = rcp->rf_f;
3854bff34e3Sthurlow 	int state = stNewLine, c;
3864bff34e3Sthurlow 	struct rcsection *rsp = NULL;
3874bff34e3Sthurlow 	struct rckey *rkp = NULL;
3884bff34e3Sthurlow 	char buf[2048];
3894bff34e3Sthurlow 	char *next = buf, *last = &buf[sizeof (buf)-1];
3904bff34e3Sthurlow 
391*613a2f6bSGordon Ross 	assert(MUTEX_HELD(&rcfile_mutex));
392*613a2f6bSGordon Ross 
3934bff34e3Sthurlow 	while ((c = getc(f)) != EOF) {
3944bff34e3Sthurlow 		if (c == '\r')
3954bff34e3Sthurlow 			continue;
3964bff34e3Sthurlow 		if (state == stNewLine) {
3974bff34e3Sthurlow 			next = buf;
3984bff34e3Sthurlow 			if (isspace(c))
3994bff34e3Sthurlow 				continue;	/* skip leading junk */
4004bff34e3Sthurlow 			if (c == '[') {
4014bff34e3Sthurlow 				state = stHeader;
4024bff34e3Sthurlow 				rsp = NULL;
4034bff34e3Sthurlow 				continue;
4044bff34e3Sthurlow 			}
4054bff34e3Sthurlow 			if (c == '#' || c == ';') {
4064bff34e3Sthurlow 				state = stSkipToEOL;
4074bff34e3Sthurlow 			} else {		/* something meaningfull */
4084bff34e3Sthurlow 				state = stGetKey;
4094bff34e3Sthurlow 			}
4104bff34e3Sthurlow 		}
4114bff34e3Sthurlow 		/* ignore long lines */
4124bff34e3Sthurlow 		if (state == stSkipToEOL || next == last) {
4134bff34e3Sthurlow 			if (c == '\n') {
4144bff34e3Sthurlow 				state = stNewLine;
4154bff34e3Sthurlow 				next = buf;
4164bff34e3Sthurlow 			}
4174bff34e3Sthurlow 			continue;
4184bff34e3Sthurlow 		}
4194bff34e3Sthurlow 		if (state == stHeader) {
4204bff34e3Sthurlow 			if (c == ']') {
4214bff34e3Sthurlow 				*next = 0;
4224bff34e3Sthurlow 				next = buf;
4234bff34e3Sthurlow 				rsp = rc_addsect(rcp, buf);
4244bff34e3Sthurlow 				state = stSkipToEOL;
4254bff34e3Sthurlow 			} else
4264bff34e3Sthurlow 				*next++ = c;
4274bff34e3Sthurlow 			continue;
4284bff34e3Sthurlow 		}
4294bff34e3Sthurlow 		if (state == stGetKey) {
4304bff34e3Sthurlow 			/* side effect: 'key name=' */
4314bff34e3Sthurlow 			if (c == ' ' || c == '\t')
4324bff34e3Sthurlow 				continue;	/* become 'keyname=' */
4334bff34e3Sthurlow 			if (c == '\n') {	/* silently ignore ... */
4344bff34e3Sthurlow 				state = stNewLine;
4354bff34e3Sthurlow 				continue;
4364bff34e3Sthurlow 			}
4374bff34e3Sthurlow 			if (c != '=') {
4384bff34e3Sthurlow 				*next++ = c;
4394bff34e3Sthurlow 				continue;
4404bff34e3Sthurlow 			}
4414bff34e3Sthurlow 			*next = 0;
4424bff34e3Sthurlow 			if (rsp == NULL) {
4434bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4444bff34e3Sthurlow 				    "Key '%s' defined before section\n"), buf);
4454bff34e3Sthurlow 				state = stSkipToEOL;
4464bff34e3Sthurlow 				continue;
4474bff34e3Sthurlow 			}
448*613a2f6bSGordon Ross 			if (home_nsmbrc != 0 && (
449*613a2f6bSGordon Ross 			    strcmp(buf, "nbns") == 0 ||
4504bff34e3Sthurlow 			    strcmp(buf, "nbns_enable") == 0 ||
4519c9af259SGordon Ross 			    strcmp(buf, "nbns_broadcast") == 0 ||
4529c9af259SGordon Ross 			    strcmp(buf, "signing") == 0)) {
4534bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4544bff34e3Sthurlow 				    "option %s may not be set "
4554bff34e3Sthurlow 				    "in user .nsmbrc file\n"), buf);
4564bff34e3Sthurlow 				next = buf;
4574bff34e3Sthurlow 				state = stNewLine;
4584bff34e3Sthurlow 				continue;
4594bff34e3Sthurlow 			}
460*613a2f6bSGordon Ross 			if (insecure_nsmbrc != 0 &&
461*613a2f6bSGordon Ross 			    strcmp(buf, "password") == 0) {
4624bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4634bff34e3Sthurlow 				    "Warning: .nsmbrc file not secure, "
4644bff34e3Sthurlow 				    "ignoring passwords\n"));
4654bff34e3Sthurlow 				next = buf;
4664bff34e3Sthurlow 				state = stNewLine;
4674bff34e3Sthurlow 				continue;
4684bff34e3Sthurlow 			}
4694bff34e3Sthurlow 			rkp = rc_sect_addkey(rsp, buf, NULL);
4704bff34e3Sthurlow 			next = buf;
4714bff34e3Sthurlow 			state = stGetValue;
4724bff34e3Sthurlow 			continue;
4734bff34e3Sthurlow 		}
4744bff34e3Sthurlow 		/* only stGetValue left */
4754bff34e3Sthurlow 		if (state != stGetValue) {
4764bff34e3Sthurlow 			fprintf(stderr, dgettext(TEXT_DOMAIN,
4774bff34e3Sthurlow 			    "Well, I can't parse file '%s'\n"), rcp->rf_name);
4784bff34e3Sthurlow 			state = stSkipToEOL;
4794bff34e3Sthurlow 		}
4804bff34e3Sthurlow 		if (c != '\n') {
4814bff34e3Sthurlow 			*next++ = c;
4824bff34e3Sthurlow 			continue;
4834bff34e3Sthurlow 		}
4844bff34e3Sthurlow 		*next = 0;
4854bff34e3Sthurlow 		set_value(rcp, rsp, rkp, buf);
4864bff34e3Sthurlow 		state = stNewLine;
4874bff34e3Sthurlow 		rkp = NULL;
4884bff34e3Sthurlow 	} 	/* while */
4894bff34e3Sthurlow 	if (c == EOF && state == stGetValue) {
4904bff34e3Sthurlow 		*next = 0;
4914bff34e3Sthurlow 		set_value(rcp, rsp, rkp, buf);
4924bff34e3Sthurlow 	}
4934bff34e3Sthurlow }
4944bff34e3Sthurlow 
4954bff34e3Sthurlow int
4964bff34e3Sthurlow rc_getstringptr(struct rcfile *rcp, const char *section, const char *key,
4974bff34e3Sthurlow 	char **dest)
4984bff34e3Sthurlow {
4994bff34e3Sthurlow 	struct rcsection *rsp;
5004bff34e3Sthurlow 	struct rckey *rkp;
501*613a2f6bSGordon Ross 	int err;
502*613a2f6bSGordon Ross 
503*613a2f6bSGordon Ross 	mutex_lock(&rcfile_mutex);
5044bff34e3Sthurlow 
5054bff34e3Sthurlow 	*dest = NULL;
5064bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
507*613a2f6bSGordon Ross 	if (!rsp) {
508*613a2f6bSGordon Ross 		err = ENOENT;
509*613a2f6bSGordon Ross 		goto out;
510*613a2f6bSGordon Ross 	}
5114bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
512*613a2f6bSGordon Ross 	if (!rkp) {
513*613a2f6bSGordon Ross 		err = ENOENT;
514*613a2f6bSGordon Ross 		goto out;
515*613a2f6bSGordon Ross 	}
5164bff34e3Sthurlow 	*dest = rkp->rk_value;
517*613a2f6bSGordon Ross 	err = 0;
518*613a2f6bSGordon Ross 
519*613a2f6bSGordon Ross out:
520*613a2f6bSGordon Ross 	mutex_unlock(&rcfile_mutex);
521*613a2f6bSGordon Ross 	return (err);
5224bff34e3Sthurlow }
5234bff34e3Sthurlow 
5244bff34e3Sthurlow int
5254bff34e3Sthurlow rc_getstring(struct rcfile *rcp, const char *section, const char *key,
5264bff34e3Sthurlow 	size_t maxlen, char *dest)
5274bff34e3Sthurlow {
5284bff34e3Sthurlow 	char *value;
5294bff34e3Sthurlow 	int error;
5304bff34e3Sthurlow 
5314bff34e3Sthurlow 	error = rc_getstringptr(rcp, section, key, &value);
5324bff34e3Sthurlow 	if (error)
5334bff34e3Sthurlow 		return (error);
5344bff34e3Sthurlow 	if (strlen(value) >= maxlen) {
535*613a2f6bSGordon Ross 		fprintf(stderr, dgettext(TEXT_DOMAIN,
5364bff34e3Sthurlow 		    "line too long for key '%s' in section '%s', max = %d\n"),
5374bff34e3Sthurlow 		    key, section, maxlen);
5384bff34e3Sthurlow 		return (EINVAL);
5394bff34e3Sthurlow 	}
5404bff34e3Sthurlow 	strcpy(dest, value);
5414bff34e3Sthurlow 	return (0);
5424bff34e3Sthurlow }
5434bff34e3Sthurlow 
5444bff34e3Sthurlow int
5454bff34e3Sthurlow rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value)
5464bff34e3Sthurlow {
5474bff34e3Sthurlow 	struct rcsection *rsp;
5484bff34e3Sthurlow 	struct rckey *rkp;
549*613a2f6bSGordon Ross 	int err;
550*613a2f6bSGordon Ross 
551*613a2f6bSGordon Ross 	mutex_lock(&rcfile_mutex);
5524bff34e3Sthurlow 
5534bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
554*613a2f6bSGordon Ross 	if (!rsp) {
555*613a2f6bSGordon Ross 		err = ENOENT;
556*613a2f6bSGordon Ross 		goto out;
557*613a2f6bSGordon Ross 	}
5584bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
559*613a2f6bSGordon Ross 	if (!rkp) {
560*613a2f6bSGordon Ross 		err = ENOENT;
561*613a2f6bSGordon Ross 		goto out;
562*613a2f6bSGordon Ross 	}
5634bff34e3Sthurlow 	errno = 0;
5644bff34e3Sthurlow 	*value = strtol(rkp->rk_value, NULL, 0);
565*613a2f6bSGordon Ross 	if ((err = errno) != 0) {
566*613a2f6bSGordon Ross 		fprintf(stderr, dgettext(TEXT_DOMAIN,
5674bff34e3Sthurlow 		    "invalid int value '%s' for key '%s' in section '%s'\n"),
5684bff34e3Sthurlow 		    rkp->rk_value, key, section);
5694bff34e3Sthurlow 	}
570*613a2f6bSGordon Ross 
571*613a2f6bSGordon Ross out:
572*613a2f6bSGordon Ross 	mutex_unlock(&rcfile_mutex);
573*613a2f6bSGordon Ross 	return (err);
5744bff34e3Sthurlow }
5754bff34e3Sthurlow 
5764bff34e3Sthurlow /*
5774bff34e3Sthurlow  * 1,yes,true
5784bff34e3Sthurlow  * 0,no,false
5794bff34e3Sthurlow  */
5804bff34e3Sthurlow int
5814bff34e3Sthurlow rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value)
5824bff34e3Sthurlow {
5834bff34e3Sthurlow 	struct rcsection *rsp;
5844bff34e3Sthurlow 	struct rckey *rkp;
5854bff34e3Sthurlow 	char *p;
586*613a2f6bSGordon Ross 	int err;
587*613a2f6bSGordon Ross 
588*613a2f6bSGordon Ross 	mutex_lock(&rcfile_mutex);
5894bff34e3Sthurlow 
5904bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
591*613a2f6bSGordon Ross 	if (!rsp) {
592*613a2f6bSGordon Ross 		err = ENOENT;
593*613a2f6bSGordon Ross 		goto out;
594*613a2f6bSGordon Ross 	}
5954bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
596*613a2f6bSGordon Ross 	if (!rkp) {
597*613a2f6bSGordon Ross 		err = ENOENT;
598*613a2f6bSGordon Ross 		goto out;
599*613a2f6bSGordon Ross 	}
6004bff34e3Sthurlow 	p = rkp->rk_value;
6014bff34e3Sthurlow 	while (*p && isspace(*p)) p++;
6024bff34e3Sthurlow 	if (*p == '0' ||
6034bff34e3Sthurlow 	    strcasecmp(p, "no") == 0 ||
6044bff34e3Sthurlow 	    strcasecmp(p, "false") == 0) {
6054bff34e3Sthurlow 		*value = 0;
606*613a2f6bSGordon Ross 		err = 0;
607*613a2f6bSGordon Ross 		goto out;
6084bff34e3Sthurlow 	}
6094bff34e3Sthurlow 	if (*p == '1' ||
6104bff34e3Sthurlow 	    strcasecmp(p, "yes") == 0 ||
6114bff34e3Sthurlow 	    strcasecmp(p, "true") == 0) {
6124bff34e3Sthurlow 		*value = 1;
613*613a2f6bSGordon Ross 		err = 0;
614*613a2f6bSGordon Ross 		goto out;
6154bff34e3Sthurlow 	}
6164bff34e3Sthurlow 	fprintf(stderr, dgettext(TEXT_DOMAIN,
6174bff34e3Sthurlow 	    "invalid boolean value '%s' for key '%s' in section '%s' \n"),
6184bff34e3Sthurlow 	    p, key, section);
619*613a2f6bSGordon Ross 	err = EINVAL;
620*613a2f6bSGordon Ross 
621*613a2f6bSGordon Ross out:
622*613a2f6bSGordon Ross 	mutex_unlock(&rcfile_mutex);
623*613a2f6bSGordon Ross 	return (err);
624*613a2f6bSGordon Ross }
625*613a2f6bSGordon Ross 
626*613a2f6bSGordon Ross #ifdef DEBUG
627*613a2f6bSGordon Ross void
628*613a2f6bSGordon Ross dump_props(char *where)
629*613a2f6bSGordon Ross {
630*613a2f6bSGordon Ross 	struct rcsection *rsp = NULL;
631*613a2f6bSGordon Ross 	struct rckey *rkp = NULL;
632*613a2f6bSGordon Ross 
633*613a2f6bSGordon Ross 	fprintf(stderr, "Settings %s\n", where);
634*613a2f6bSGordon Ross 	SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) {
635*613a2f6bSGordon Ross 		fprintf(stderr, "section=%s\n", rsp->rs_name);
636*613a2f6bSGordon Ross 		fflush(stderr);
637*613a2f6bSGordon Ross 
638*613a2f6bSGordon Ross 		SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) {
639*613a2f6bSGordon Ross 			fprintf(stderr, "  key=%s, value=%s\n",
640*613a2f6bSGordon Ross 			    rkp->rk_name, rkp->rk_value);
641*613a2f6bSGordon Ross 			fflush(stderr);
642*613a2f6bSGordon Ross 		}
643*613a2f6bSGordon Ross 	}
644*613a2f6bSGordon Ross }
645*613a2f6bSGordon Ross #endif
646*613a2f6bSGordon Ross 
647*613a2f6bSGordon Ross /*
648*613a2f6bSGordon Ross  * first parse "sharectl get smbfs, then $HOME/.nsmbrc
649*613a2f6bSGordon Ross  * This is called by library consumers (commands)
650*613a2f6bSGordon Ross  */
651*613a2f6bSGordon Ross int
652*613a2f6bSGordon Ross smb_open_rcfile(char *home)
653*613a2f6bSGordon Ross {
654*613a2f6bSGordon Ross 	char *fn;
655*613a2f6bSGordon Ross 	int len, error = 0;
656*613a2f6bSGordon Ross 
657*613a2f6bSGordon Ross 	mutex_lock(&rcfile_mutex);
658*613a2f6bSGordon Ross 
659*613a2f6bSGordon Ross 	smb_rc = NULL;
660*613a2f6bSGordon Ross #if 0	/* before SMF */
661*613a2f6bSGordon Ross 	fn = SMB_CFG_FILE;
662*613a2f6bSGordon Ross 	error = rc_open(fn, &smb_rc);
663*613a2f6bSGordon Ross #else
664*613a2f6bSGordon Ross 	fn = SMBFS_SHARECTL_CMD;
665*613a2f6bSGordon Ross 	error = rc_popen_cmd(fn, &smb_rc);
666*613a2f6bSGordon Ross #endif
667*613a2f6bSGordon Ross 	if (error != 0 && error != ENOENT) {
668*613a2f6bSGordon Ross 		/* Error from fopen. strerror is OK. */
669*613a2f6bSGordon Ross 		fprintf(stderr, dgettext(TEXT_DOMAIN,
670*613a2f6bSGordon Ross 		    "Can't open %s: %s\n"), fn, strerror(errno));
671*613a2f6bSGordon Ross 	}
672*613a2f6bSGordon Ross #ifdef DEBUG
673*613a2f6bSGordon Ross 	if (smb_debug)
674*613a2f6bSGordon Ross 		dump_props(fn);
675*613a2f6bSGordon Ross #endif
676*613a2f6bSGordon Ross 
677*613a2f6bSGordon Ross 	if (home) {
678*613a2f6bSGordon Ross 		len = strlen(home) + 20;
679*613a2f6bSGordon Ross 		fn = malloc(len);
680*613a2f6bSGordon Ross 		snprintf(fn, len, "%s/.nsmbrc", home);
681*613a2f6bSGordon Ross 		home_nsmbrc = 1;
682*613a2f6bSGordon Ross 		error = rc_merge(fn, &smb_rc);
683*613a2f6bSGordon Ross 		if (error != 0 && error != ENOENT) {
684*613a2f6bSGordon Ross 			fprintf(stderr, dgettext(TEXT_DOMAIN,
685*613a2f6bSGordon Ross 			    "Can't open %s: %s\n"), fn, strerror(errno));
686*613a2f6bSGordon Ross 		}
687*613a2f6bSGordon Ross 		home_nsmbrc = 0;
688*613a2f6bSGordon Ross #ifdef DEBUG
689*613a2f6bSGordon Ross 		if (smb_debug)
690*613a2f6bSGordon Ross 			dump_props(fn);
691*613a2f6bSGordon Ross #endif
692*613a2f6bSGordon Ross 		free(fn);
693*613a2f6bSGordon Ross 	}
694*613a2f6bSGordon Ross 
695*613a2f6bSGordon Ross 	/* Mostly ignore error returns above. */
696*613a2f6bSGordon Ross 	if (smb_rc == NULL)
697*613a2f6bSGordon Ross 		error = ENOENT;
698*613a2f6bSGordon Ross 	else
699*613a2f6bSGordon Ross 		error = 0;
700*613a2f6bSGordon Ross 
701*613a2f6bSGordon Ross 	mutex_unlock(&rcfile_mutex);
702*613a2f6bSGordon Ross 
703*613a2f6bSGordon Ross 	return (error);
7044bff34e3Sthurlow }
7054bff34e3Sthurlow 
7064bff34e3Sthurlow /*
707*613a2f6bSGordon Ross  * This is called by library consumers (commands)
7084bff34e3Sthurlow  */
709*613a2f6bSGordon Ross void
710*613a2f6bSGordon Ross smb_close_rcfile(void)
7114bff34e3Sthurlow {
712*613a2f6bSGordon Ross 	struct rcfile *rcp;
7134bff34e3Sthurlow 
714*613a2f6bSGordon Ross 	if ((rcp = smb_rc) != NULL) {
715*613a2f6bSGordon Ross 		smb_rc = NULL;
716*613a2f6bSGordon Ross 		rc_close(rcp);
7174bff34e3Sthurlow 	}
7184bff34e3Sthurlow }
719