xref: /titanic_54/usr/src/lib/libsmbfs/smb/rcfile.c (revision 9c9af2590af49bb395bc8d2eace0f2d4ea16d165)
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>
394bff34e3Sthurlow #include <ctype.h>
404bff34e3Sthurlow #include <errno.h>
414bff34e3Sthurlow #include <stdio.h>
424bff34e3Sthurlow #include <string.h>
434bff34e3Sthurlow #include <strings.h>
444bff34e3Sthurlow #include <stdlib.h>
454bff34e3Sthurlow #include <libintl.h>
464bff34e3Sthurlow #include <pwd.h>
474bff34e3Sthurlow #include <unistd.h>
484bff34e3Sthurlow #include <sys/debug.h>
494bff34e3Sthurlow 
504bff34e3Sthurlow #include <cflib.h>
514bff34e3Sthurlow #include "rcfile_priv.h"
52*9c9af259SGordon Ross extern int smb_debug;
534bff34e3Sthurlow 
544bff34e3Sthurlow SLIST_HEAD(rcfile_head, rcfile);
554bff34e3Sthurlow static struct rcfile_head pf_head = {NULL};
564bff34e3Sthurlow 
574bff34e3Sthurlow static struct rcfile *rc_cachelookup(const char *filename);
584bff34e3Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
594bff34e3Sthurlow static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
604bff34e3Sthurlow static int rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
614bff34e3Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname);
624bff34e3Sthurlow static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
634bff34e3Sthurlow     const char *value);
644bff34e3Sthurlow static void rc_key_free(struct rckey *p);
654bff34e3Sthurlow static void rc_parse(struct rcfile *rcp);
664bff34e3Sthurlow 
674bff34e3Sthurlow int insecure_nsmbrc;
684bff34e3Sthurlow 
694bff34e3Sthurlow /*
704bff34e3Sthurlow  * open rcfile and load its content, if already open - return previous handle
714bff34e3Sthurlow  */
724bff34e3Sthurlow int
734bff34e3Sthurlow rc_open(const char *filename, const char *mode, struct rcfile **rcfile)
744bff34e3Sthurlow {
754bff34e3Sthurlow 	struct rcfile *rcp;
764bff34e3Sthurlow 	FILE *f;
774bff34e3Sthurlow 	struct stat statbuf;
784bff34e3Sthurlow 
794bff34e3Sthurlow 	rcp = rc_cachelookup(filename);
804bff34e3Sthurlow 	if (rcp) {
814bff34e3Sthurlow 		*rcfile = rcp;
824bff34e3Sthurlow 		return (0);
834bff34e3Sthurlow 	}
844bff34e3Sthurlow 	f = fopen(filename, mode);
854bff34e3Sthurlow 	if (f == NULL)
864bff34e3Sthurlow 		return (errno);
874bff34e3Sthurlow 	insecure_nsmbrc = 0;
884bff34e3Sthurlow 	if (fstat(fileno(f), &statbuf) >= 0 &&
894bff34e3Sthurlow 	    (statbuf.st_mode & 077) != 0)
904bff34e3Sthurlow 		insecure_nsmbrc = 1;
914bff34e3Sthurlow 	rcp = malloc(sizeof (struct rcfile));
924bff34e3Sthurlow 	if (rcp == NULL) {
934bff34e3Sthurlow 		fclose(f);
944bff34e3Sthurlow 		return (ENOMEM);
954bff34e3Sthurlow 	}
964bff34e3Sthurlow 	bzero(rcp, sizeof (struct rcfile));
974bff34e3Sthurlow 	rcp->rf_name = strdup(filename);
984bff34e3Sthurlow 	rcp->rf_f = f;
994bff34e3Sthurlow 	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
1004bff34e3Sthurlow 	rc_parse(rcp);
1014bff34e3Sthurlow 	*rcfile = rcp;
1024bff34e3Sthurlow 	return (0);
1034bff34e3Sthurlow }
1044bff34e3Sthurlow 
1054bff34e3Sthurlow int
1064bff34e3Sthurlow rc_merge(const char *filename, struct rcfile **rcfile)
1074bff34e3Sthurlow {
1084bff34e3Sthurlow 	struct rcfile *rcp = *rcfile;
1094bff34e3Sthurlow 	FILE *f, *t;
1104bff34e3Sthurlow 
1114bff34e3Sthurlow 	insecure_nsmbrc = 0;
1124bff34e3Sthurlow 	if (rcp == NULL) {
1134bff34e3Sthurlow 		return (rc_open(filename, "r", rcfile));
1144bff34e3Sthurlow 	}
1154bff34e3Sthurlow 	f = fopen(filename, "r");
1164bff34e3Sthurlow 	if (f == NULL)
1174bff34e3Sthurlow 		return (errno);
1184bff34e3Sthurlow 	t = rcp->rf_f;
1194bff34e3Sthurlow 	rcp->rf_f = f;
1204bff34e3Sthurlow 	rc_parse(rcp);
1214bff34e3Sthurlow 	rcp->rf_f = t;
1224bff34e3Sthurlow 	fclose(f);
1234bff34e3Sthurlow 	return (0);
1244bff34e3Sthurlow }
1254bff34e3Sthurlow 
1264bff34e3Sthurlow int
1274bff34e3Sthurlow rc_merge_pipe(const char *command, struct rcfile **rcfile)
1284bff34e3Sthurlow {
1294bff34e3Sthurlow 	struct rcfile *rcp = *rcfile;
1304bff34e3Sthurlow 	FILE *f, *t;
1314bff34e3Sthurlow 
1324bff34e3Sthurlow 	insecure_nsmbrc = 0;
1334bff34e3Sthurlow 	f = popen(command, "r");
1344bff34e3Sthurlow 	if (f == NULL)
1354bff34e3Sthurlow 		return (errno);
1364bff34e3Sthurlow 	if (rcp == NULL) {
1374bff34e3Sthurlow 		rcp = malloc(sizeof (struct rcfile));
1384bff34e3Sthurlow 		if (rcp == NULL) {
1394bff34e3Sthurlow 			fclose(f);
1404bff34e3Sthurlow 			return (ENOMEM);
1414bff34e3Sthurlow 		}
1424bff34e3Sthurlow 		*rcfile = rcp;
1434bff34e3Sthurlow 		bzero(rcp, sizeof (struct rcfile));
1444bff34e3Sthurlow 		rcp->rf_name = strdup(command);
1454bff34e3Sthurlow 		rcp->rf_f = f;
1464bff34e3Sthurlow 		SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
1474bff34e3Sthurlow 		rc_parse(rcp);
1484bff34e3Sthurlow 	} else {
1494bff34e3Sthurlow 		t = rcp->rf_f;
1504bff34e3Sthurlow 		rcp->rf_f = f;
1514bff34e3Sthurlow 		rc_parse(rcp);
1524bff34e3Sthurlow 		rcp->rf_f = t;
1534bff34e3Sthurlow 	}
1544bff34e3Sthurlow 	fclose(f);
1554bff34e3Sthurlow 	return (0);
1564bff34e3Sthurlow }
1574bff34e3Sthurlow 
1584bff34e3Sthurlow int
1594bff34e3Sthurlow rc_close(struct rcfile *rcp)
1604bff34e3Sthurlow {
1614bff34e3Sthurlow 	struct rcsection *p, *n;
1624bff34e3Sthurlow 
1634bff34e3Sthurlow 	fclose(rcp->rf_f);
1644bff34e3Sthurlow 	for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
1654bff34e3Sthurlow 		n = p;
1664bff34e3Sthurlow 		p = SLIST_NEXT(p, rs_next);
1674bff34e3Sthurlow 		rc_freesect(rcp, n);
1684bff34e3Sthurlow 	}
1694bff34e3Sthurlow 	free(rcp->rf_name);
1704bff34e3Sthurlow 	SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
1714bff34e3Sthurlow 	free(rcp);
1724bff34e3Sthurlow 	return (0);
1734bff34e3Sthurlow }
1744bff34e3Sthurlow 
1754bff34e3Sthurlow static struct rcfile *
1764bff34e3Sthurlow rc_cachelookup(const char *filename)
1774bff34e3Sthurlow {
1784bff34e3Sthurlow 	struct rcfile *p;
1794bff34e3Sthurlow 
1804bff34e3Sthurlow 	SLIST_FOREACH(p, &pf_head, rf_next)
1814bff34e3Sthurlow 		if (strcmp(filename, p->rf_name) == 0)
1824bff34e3Sthurlow 			return (p);
1834bff34e3Sthurlow 	return (0);
1844bff34e3Sthurlow }
1854bff34e3Sthurlow 
1864bff34e3Sthurlow /* static */ struct rcsection *
1874bff34e3Sthurlow rc_findsect(struct rcfile *rcp, const char *sectname)
1884bff34e3Sthurlow {
1894bff34e3Sthurlow 	struct rcsection *p;
1904bff34e3Sthurlow 
1914bff34e3Sthurlow 	SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
1924bff34e3Sthurlow 		if (strcasecmp(p->rs_name, sectname) == 0)
1934bff34e3Sthurlow 			return (p);
1944bff34e3Sthurlow 	return (NULL);
1954bff34e3Sthurlow }
1964bff34e3Sthurlow 
1974bff34e3Sthurlow static struct rcsection *
1984bff34e3Sthurlow rc_addsect(struct rcfile *rcp, const char *sectname)
1994bff34e3Sthurlow {
2004bff34e3Sthurlow 	struct rcsection *p;
2014bff34e3Sthurlow 
2024bff34e3Sthurlow 	p = rc_findsect(rcp, sectname);
2034bff34e3Sthurlow 	if (p)
2044bff34e3Sthurlow 		return (p);
2054bff34e3Sthurlow 	p = malloc(sizeof (*p));
2064bff34e3Sthurlow 	if (!p)
2074bff34e3Sthurlow 		return (NULL);
2084bff34e3Sthurlow 	p->rs_name = strdup(sectname);
2094bff34e3Sthurlow 	SLIST_INIT(&p->rs_keys);
2104bff34e3Sthurlow 	SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
2114bff34e3Sthurlow 	return (p);
2124bff34e3Sthurlow }
2134bff34e3Sthurlow 
2144bff34e3Sthurlow static int
2154bff34e3Sthurlow rc_freesect(struct rcfile *rcp, struct rcsection *rsp)
2164bff34e3Sthurlow {
2174bff34e3Sthurlow 	struct rckey *p, *n;
2184bff34e3Sthurlow 
2194bff34e3Sthurlow 	SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next);
2204bff34e3Sthurlow 	for (p = SLIST_FIRST(&rsp->rs_keys); p; ) {
2214bff34e3Sthurlow 		n = p;
2224bff34e3Sthurlow 		p = SLIST_NEXT(p, rk_next);
2234bff34e3Sthurlow 		rc_key_free(n);
2244bff34e3Sthurlow 	}
2254bff34e3Sthurlow 	free(rsp->rs_name);
2264bff34e3Sthurlow 	free(rsp);
2274bff34e3Sthurlow 	return (0);
2284bff34e3Sthurlow }
2294bff34e3Sthurlow 
2304bff34e3Sthurlow /* static */ struct rckey *
2314bff34e3Sthurlow rc_sect_findkey(struct rcsection *rsp, const char *keyname)
2324bff34e3Sthurlow {
2334bff34e3Sthurlow 	struct rckey *p;
2344bff34e3Sthurlow 
2354bff34e3Sthurlow 	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
2364bff34e3Sthurlow 		if (strcmp(p->rk_name, keyname) == 0)
2374bff34e3Sthurlow 			return (p);
2384bff34e3Sthurlow 	return (NULL);
2394bff34e3Sthurlow }
2404bff34e3Sthurlow 
2414bff34e3Sthurlow static struct rckey *
2424bff34e3Sthurlow rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value)
2434bff34e3Sthurlow {
2444bff34e3Sthurlow 	struct rckey *p;
2454bff34e3Sthurlow 
2464bff34e3Sthurlow 	p = rc_sect_findkey(rsp, name);
2474bff34e3Sthurlow 	if (!p) {
2484bff34e3Sthurlow 		p = malloc(sizeof (*p));
2494bff34e3Sthurlow 		if (!p)
2504bff34e3Sthurlow 			return (NULL);
2514bff34e3Sthurlow 		SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
2524bff34e3Sthurlow 		p->rk_name = strdup(name);
2534bff34e3Sthurlow 		p->rk_value = value ? strdup(value) : strdup("");
2544bff34e3Sthurlow 	}
2554bff34e3Sthurlow 	return (p);
2564bff34e3Sthurlow }
2574bff34e3Sthurlow 
2584bff34e3Sthurlow #if 0
2594bff34e3Sthurlow void
2604bff34e3Sthurlow rc_sect_delkey(struct rcsection *rsp, struct rckey *p)
2614bff34e3Sthurlow {
2624bff34e3Sthurlow 
2634bff34e3Sthurlow 	SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next);
2644bff34e3Sthurlow 	rc_key_free(p);
2654bff34e3Sthurlow }
2664bff34e3Sthurlow #endif
2674bff34e3Sthurlow 
2684bff34e3Sthurlow static void
2694bff34e3Sthurlow rc_key_free(struct rckey *p)
2704bff34e3Sthurlow {
2714bff34e3Sthurlow 	free(p->rk_value);
2724bff34e3Sthurlow 	free(p->rk_name);
2734bff34e3Sthurlow 	free(p);
2744bff34e3Sthurlow }
2754bff34e3Sthurlow 
2764bff34e3Sthurlow enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
2774bff34e3Sthurlow 
2784bff34e3Sthurlow int home_nsmbrc = 0;
2794bff34e3Sthurlow 
2804bff34e3Sthurlow static char *minauth[] = {
2814bff34e3Sthurlow 	"kerberos",
2824bff34e3Sthurlow 	"ntlmv2",
2834bff34e3Sthurlow 	"ntlm",
2844bff34e3Sthurlow 	"lm",
2854bff34e3Sthurlow 	"none",
2864bff34e3Sthurlow 	NULL
2874bff34e3Sthurlow };
2884bff34e3Sthurlow 
2894bff34e3Sthurlow static int
2904bff34e3Sthurlow eval_minauth(char *auth)
2914bff34e3Sthurlow {
2924bff34e3Sthurlow 	int i;
2934bff34e3Sthurlow 
2944bff34e3Sthurlow 	for (i = 0; minauth[i]; i++)
2954bff34e3Sthurlow 		if (strcmp(auth, minauth[i]) == 0)
2964bff34e3Sthurlow 			break;
2974bff34e3Sthurlow 	return (i);
2984bff34e3Sthurlow }
2994bff34e3Sthurlow 
3004bff34e3Sthurlow /*
3014bff34e3Sthurlow  * Ensure that "minauth" is set to the highest level (lowest array offset)
3024bff34e3Sthurlow  */
3034bff34e3Sthurlow static void
3044bff34e3Sthurlow set_value(struct rcfile *rcp, struct rcsection *rsp, struct rckey *rkp,
3054bff34e3Sthurlow     char *ptr)
3064bff34e3Sthurlow {
3074bff34e3Sthurlow 	int now, new;
3084bff34e3Sthurlow 
3094bff34e3Sthurlow 	if (strcmp(rkp->rk_name, "minauth") == 0) {
3104bff34e3Sthurlow 		now = eval_minauth(rkp->rk_value);
3114bff34e3Sthurlow 		new = eval_minauth(ptr);
3124bff34e3Sthurlow 		if (new >= now) {
3134bff34e3Sthurlow #ifdef DEBUG
314*9c9af259SGordon Ross 			if (smb_debug)
315*9c9af259SGordon Ross 				printf(
316*9c9af259SGordon Ross 				    "set_value: rejecting %s=%s from %s\n",
317*9c9af259SGordon Ross 				    rkp->rk_name, ptr, home_nsmbrc ?
318*9c9af259SGordon Ross 				    "user file" : "SMF");
3194bff34e3Sthurlow #endif
3204bff34e3Sthurlow 			return;
3214bff34e3Sthurlow 		}
3224bff34e3Sthurlow 	}
3234bff34e3Sthurlow #ifdef DEBUG
324*9c9af259SGordon Ross 	if (smb_debug)
3254bff34e3Sthurlow 		printf("set_value: applying %s=%s from %s\n",
3264bff34e3Sthurlow 		    rkp->rk_name, ptr, home_nsmbrc ? "user file" : "SMF");
3274bff34e3Sthurlow #endif
3284bff34e3Sthurlow 	rkp->rk_value = strdup(ptr);
3294bff34e3Sthurlow }
3304bff34e3Sthurlow 
3314bff34e3Sthurlow static void
3324bff34e3Sthurlow rc_parse(struct rcfile *rcp)
3334bff34e3Sthurlow {
3344bff34e3Sthurlow 	FILE *f = rcp->rf_f;
3354bff34e3Sthurlow 	int state = stNewLine, c;
3364bff34e3Sthurlow 	struct rcsection *rsp = NULL;
3374bff34e3Sthurlow 	struct rckey *rkp = NULL;
3384bff34e3Sthurlow 	char buf[2048];
3394bff34e3Sthurlow 	char *next = buf, *last = &buf[sizeof (buf)-1];
3404bff34e3Sthurlow 
3414bff34e3Sthurlow 	while ((c = getc(f)) != EOF) {
3424bff34e3Sthurlow 		if (c == '\r')
3434bff34e3Sthurlow 			continue;
3444bff34e3Sthurlow 		if (state == stNewLine) {
3454bff34e3Sthurlow 			next = buf;
3464bff34e3Sthurlow 			if (isspace(c))
3474bff34e3Sthurlow 				continue;	/* skip leading junk */
3484bff34e3Sthurlow 			if (c == '[') {
3494bff34e3Sthurlow 				state = stHeader;
3504bff34e3Sthurlow 				rsp = NULL;
3514bff34e3Sthurlow 				continue;
3524bff34e3Sthurlow 			}
3534bff34e3Sthurlow 			if (c == '#' || c == ';') {
3544bff34e3Sthurlow 				state = stSkipToEOL;
3554bff34e3Sthurlow 			} else {		/* something meaningfull */
3564bff34e3Sthurlow 				state = stGetKey;
3574bff34e3Sthurlow 			}
3584bff34e3Sthurlow 		}
3594bff34e3Sthurlow 		/* ignore long lines */
3604bff34e3Sthurlow 		if (state == stSkipToEOL || next == last) {
3614bff34e3Sthurlow 			if (c == '\n') {
3624bff34e3Sthurlow 				state = stNewLine;
3634bff34e3Sthurlow 				next = buf;
3644bff34e3Sthurlow 			}
3654bff34e3Sthurlow 			continue;
3664bff34e3Sthurlow 		}
3674bff34e3Sthurlow 		if (state == stHeader) {
3684bff34e3Sthurlow 			if (c == ']') {
3694bff34e3Sthurlow 				*next = 0;
3704bff34e3Sthurlow 				next = buf;
3714bff34e3Sthurlow 				rsp = rc_addsect(rcp, buf);
3724bff34e3Sthurlow 				state = stSkipToEOL;
3734bff34e3Sthurlow 			} else
3744bff34e3Sthurlow 				*next++ = c;
3754bff34e3Sthurlow 			continue;
3764bff34e3Sthurlow 		}
3774bff34e3Sthurlow 		if (state == stGetKey) {
3784bff34e3Sthurlow 			/* side effect: 'key name=' */
3794bff34e3Sthurlow 			if (c == ' ' || c == '\t')
3804bff34e3Sthurlow 				continue;	/* become 'keyname=' */
3814bff34e3Sthurlow 			if (c == '\n') {	/* silently ignore ... */
3824bff34e3Sthurlow 				state = stNewLine;
3834bff34e3Sthurlow 				continue;
3844bff34e3Sthurlow 			}
3854bff34e3Sthurlow 			if (c != '=') {
3864bff34e3Sthurlow 				*next++ = c;
3874bff34e3Sthurlow 				continue;
3884bff34e3Sthurlow 			}
3894bff34e3Sthurlow 			*next = 0;
3904bff34e3Sthurlow 			if (rsp == NULL) {
3914bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
3924bff34e3Sthurlow 				    "Key '%s' defined before section\n"), buf);
3934bff34e3Sthurlow 				state = stSkipToEOL;
3944bff34e3Sthurlow 				continue;
3954bff34e3Sthurlow 			}
3964bff34e3Sthurlow 			if (home_nsmbrc &&
3974bff34e3Sthurlow 			    (strcmp(buf, "nbns") == 0 ||
3984bff34e3Sthurlow 			    strcmp(buf, "nbns_enable") == 0 ||
399*9c9af259SGordon Ross 			    strcmp(buf, "nbns_broadcast") == 0 ||
400*9c9af259SGordon Ross 			    strcmp(buf, "signing") == 0)) {
4014bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4024bff34e3Sthurlow 				    "option %s may not be set "
4034bff34e3Sthurlow 				    "in user .nsmbrc file\n"), buf);
4044bff34e3Sthurlow 				next = buf;
4054bff34e3Sthurlow 				state = stNewLine;
4064bff34e3Sthurlow 				continue;
4074bff34e3Sthurlow 			}
4084bff34e3Sthurlow 			if (insecure_nsmbrc && (strcmp(buf, "password") == 0)) {
4094bff34e3Sthurlow 				fprintf(stderr, dgettext(TEXT_DOMAIN,
4104bff34e3Sthurlow 				    "Warning: .nsmbrc file not secure, "
4114bff34e3Sthurlow 				    "ignoring passwords\n"));
4124bff34e3Sthurlow 				next = buf;
4134bff34e3Sthurlow 				state = stNewLine;
4144bff34e3Sthurlow 				continue;
4154bff34e3Sthurlow 			}
4164bff34e3Sthurlow 			rkp = rc_sect_addkey(rsp, buf, NULL);
4174bff34e3Sthurlow 			next = buf;
4184bff34e3Sthurlow 			state = stGetValue;
4194bff34e3Sthurlow 			continue;
4204bff34e3Sthurlow 		}
4214bff34e3Sthurlow 		/* only stGetValue left */
4224bff34e3Sthurlow 		if (state != stGetValue) {
4234bff34e3Sthurlow 			fprintf(stderr, dgettext(TEXT_DOMAIN,
4244bff34e3Sthurlow 			    "Well, I can't parse file '%s'\n"), rcp->rf_name);
4254bff34e3Sthurlow 			state = stSkipToEOL;
4264bff34e3Sthurlow 		}
4274bff34e3Sthurlow 		if (c != '\n') {
4284bff34e3Sthurlow 			*next++ = c;
4294bff34e3Sthurlow 			continue;
4304bff34e3Sthurlow 		}
4314bff34e3Sthurlow 		*next = 0;
4324bff34e3Sthurlow 		set_value(rcp, rsp, rkp, buf);
4334bff34e3Sthurlow 		state = stNewLine;
4344bff34e3Sthurlow 		rkp = NULL;
4354bff34e3Sthurlow 	} 	/* while */
4364bff34e3Sthurlow 	if (c == EOF && state == stGetValue) {
4374bff34e3Sthurlow 		*next = 0;
4384bff34e3Sthurlow 		set_value(rcp, rsp, rkp, buf);
4394bff34e3Sthurlow 	}
4404bff34e3Sthurlow }
4414bff34e3Sthurlow 
4424bff34e3Sthurlow int
4434bff34e3Sthurlow rc_getstringptr(struct rcfile *rcp, const char *section, const char *key,
4444bff34e3Sthurlow 	char **dest)
4454bff34e3Sthurlow {
4464bff34e3Sthurlow 	struct rcsection *rsp;
4474bff34e3Sthurlow 	struct rckey *rkp;
4484bff34e3Sthurlow 
4494bff34e3Sthurlow 	*dest = NULL;
4504bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
4514bff34e3Sthurlow 	if (!rsp)
4524bff34e3Sthurlow 		return (ENOENT);
4534bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
4544bff34e3Sthurlow 	if (!rkp)
4554bff34e3Sthurlow 		return (ENOENT);
4564bff34e3Sthurlow 	*dest = rkp->rk_value;
4574bff34e3Sthurlow 	return (0);
4584bff34e3Sthurlow }
4594bff34e3Sthurlow 
4604bff34e3Sthurlow int
4614bff34e3Sthurlow rc_getstring(struct rcfile *rcp, const char *section, const char *key,
4624bff34e3Sthurlow 	size_t maxlen, char *dest)
4634bff34e3Sthurlow {
4644bff34e3Sthurlow 	char *value;
4654bff34e3Sthurlow 	int error;
4664bff34e3Sthurlow 
4674bff34e3Sthurlow 	error = rc_getstringptr(rcp, section, key, &value);
4684bff34e3Sthurlow 	if (error)
4694bff34e3Sthurlow 		return (error);
4704bff34e3Sthurlow 	if (strlen(value) >= maxlen) {
4714bff34e3Sthurlow 		fprintf(stdout, dgettext(TEXT_DOMAIN,
4724bff34e3Sthurlow 		    "line too long for key '%s' in section '%s', max = %d\n"),
4734bff34e3Sthurlow 		    key, section, maxlen);
4744bff34e3Sthurlow 		return (EINVAL);
4754bff34e3Sthurlow 	}
4764bff34e3Sthurlow 	strcpy(dest, value);
4774bff34e3Sthurlow 	return (0);
4784bff34e3Sthurlow }
4794bff34e3Sthurlow 
4804bff34e3Sthurlow int
4814bff34e3Sthurlow rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value)
4824bff34e3Sthurlow {
4834bff34e3Sthurlow 	struct rcsection *rsp;
4844bff34e3Sthurlow 	struct rckey *rkp;
4854bff34e3Sthurlow 
4864bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
4874bff34e3Sthurlow 	if (!rsp)
4884bff34e3Sthurlow 		return (ENOENT);
4894bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
4904bff34e3Sthurlow 	if (!rkp)
4914bff34e3Sthurlow 		return (ENOENT);
4924bff34e3Sthurlow 	errno = 0;
4934bff34e3Sthurlow 	*value = strtol(rkp->rk_value, NULL, 0);
4944bff34e3Sthurlow 	if (errno) {
4954bff34e3Sthurlow 		fprintf(stdout, dgettext(TEXT_DOMAIN,
4964bff34e3Sthurlow 		    "invalid int value '%s' for key '%s' in section '%s'\n"),
4974bff34e3Sthurlow 		    rkp->rk_value, key, section);
4984bff34e3Sthurlow 		return (errno);
4994bff34e3Sthurlow 	}
5004bff34e3Sthurlow 	return (0);
5014bff34e3Sthurlow }
5024bff34e3Sthurlow 
5034bff34e3Sthurlow /*
5044bff34e3Sthurlow  * 1,yes,true
5054bff34e3Sthurlow  * 0,no,false
5064bff34e3Sthurlow  */
5074bff34e3Sthurlow int
5084bff34e3Sthurlow rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value)
5094bff34e3Sthurlow {
5104bff34e3Sthurlow 	struct rcsection *rsp;
5114bff34e3Sthurlow 	struct rckey *rkp;
5124bff34e3Sthurlow 	char *p;
5134bff34e3Sthurlow 
5144bff34e3Sthurlow 	rsp = rc_findsect(rcp, section);
5154bff34e3Sthurlow 	if (!rsp)
5164bff34e3Sthurlow 		return (ENOENT);
5174bff34e3Sthurlow 	rkp = rc_sect_findkey(rsp, key);
5184bff34e3Sthurlow 	if (!rkp)
5194bff34e3Sthurlow 		return (ENOENT);
5204bff34e3Sthurlow 	p = rkp->rk_value;
5214bff34e3Sthurlow 	while (*p && isspace(*p)) p++;
5224bff34e3Sthurlow 	if (*p == '0' ||
5234bff34e3Sthurlow 	    strcasecmp(p, "no") == 0 ||
5244bff34e3Sthurlow 	    strcasecmp(p, "false") == 0) {
5254bff34e3Sthurlow 		*value = 0;
5264bff34e3Sthurlow 		return (0);
5274bff34e3Sthurlow 	}
5284bff34e3Sthurlow 	if (*p == '1' ||
5294bff34e3Sthurlow 	    strcasecmp(p, "yes") == 0 ||
5304bff34e3Sthurlow 	    strcasecmp(p, "true") == 0) {
5314bff34e3Sthurlow 		*value = 1;
5324bff34e3Sthurlow 		return (0);
5334bff34e3Sthurlow 	}
5344bff34e3Sthurlow 	fprintf(stderr, dgettext(TEXT_DOMAIN,
5354bff34e3Sthurlow 	    "invalid boolean value '%s' for key '%s' in section '%s' \n"),
5364bff34e3Sthurlow 	    p, key, section);
5374bff34e3Sthurlow 	return (EINVAL);
5384bff34e3Sthurlow }
5394bff34e3Sthurlow 
5404bff34e3Sthurlow /*
5414bff34e3Sthurlow  * Unified command line/rc file parser
5424bff34e3Sthurlow  */
5434bff34e3Sthurlow int
5444bff34e3Sthurlow opt_args_parse(struct rcfile *rcp, struct opt_args *ap, const char *sect,
5454bff34e3Sthurlow 	opt_callback_t *callback)
5464bff34e3Sthurlow {
5474bff34e3Sthurlow 	int len, error;
5484bff34e3Sthurlow 
5494bff34e3Sthurlow 	for (; ap->opt; ap++) {
5504bff34e3Sthurlow 		switch (ap->type) {
5514bff34e3Sthurlow 		case OPTARG_STR:
5524bff34e3Sthurlow 			if (rc_getstringptr(rcp, sect, ap->name, &ap->str) != 0)
5534bff34e3Sthurlow 				break;
5544bff34e3Sthurlow 			len = strlen(ap->str);
5554bff34e3Sthurlow 			if (len > ap->ival) {
5564bff34e3Sthurlow 				fprintf(stdout, dgettext(TEXT_DOMAIN,
5574bff34e3Sthurlow 			"rc: argument for option '%c' (%s) too long\n"),
5584bff34e3Sthurlow 				    ap->opt, ap->name);
5594bff34e3Sthurlow 				return (EINVAL);
5604bff34e3Sthurlow 			}
5614bff34e3Sthurlow 			callback(ap);
5624bff34e3Sthurlow 			break;
5634bff34e3Sthurlow 		case OPTARG_BOOL:
5644bff34e3Sthurlow 			error = rc_getbool(rcp, sect, ap->name, &ap->ival);
5654bff34e3Sthurlow 			if (error == ENOENT)
5664bff34e3Sthurlow 				break;
5674bff34e3Sthurlow 			if (error)
5684bff34e3Sthurlow 				return (EINVAL);
5694bff34e3Sthurlow 			callback(ap);
5704bff34e3Sthurlow 			break;
5714bff34e3Sthurlow 		case OPTARG_INT:
5724bff34e3Sthurlow 			if (rc_getint(rcp, sect, ap->name, &ap->ival) != 0)
5734bff34e3Sthurlow 				break;
5744bff34e3Sthurlow 			if (((ap->flag & OPTFL_HAVEMIN) &&
5754bff34e3Sthurlow 			    ap->ival < ap->min) ||
5764bff34e3Sthurlow 			    ((ap->flag & OPTFL_HAVEMAX) &&
5774bff34e3Sthurlow 			    ap->ival > ap->max)) {
5784bff34e3Sthurlow 				fprintf(stdout, dgettext(TEXT_DOMAIN,
5794bff34e3Sthurlow 				    "rc: argument for option '%c' (%s) "
5804bff34e3Sthurlow 				    "should be in [%d-%d] range\n"),
5814bff34e3Sthurlow 				    ap->opt, ap->name, ap->min, ap->max);
5824bff34e3Sthurlow 				return (EINVAL);
5834bff34e3Sthurlow 			}
5844bff34e3Sthurlow 			callback(ap);
5854bff34e3Sthurlow 			break;
5864bff34e3Sthurlow 		default:
5874bff34e3Sthurlow 			break;
5884bff34e3Sthurlow 		}
5894bff34e3Sthurlow 	}
5904bff34e3Sthurlow 	return (0);
5914bff34e3Sthurlow }
5924bff34e3Sthurlow 
5934bff34e3Sthurlow int
5944bff34e3Sthurlow opt_args_parseopt(struct opt_args *ap, int opt, char *arg,
5954bff34e3Sthurlow 	opt_callback_t *callback)
5964bff34e3Sthurlow {
5974bff34e3Sthurlow 	int len;
5984bff34e3Sthurlow 
5994bff34e3Sthurlow 	for (; ap->opt; ap++) {
6004bff34e3Sthurlow 		if (ap->opt != opt)
6014bff34e3Sthurlow 			continue;
6024bff34e3Sthurlow 		switch (ap->type) {
6034bff34e3Sthurlow 		case OPTARG_STR:
6044bff34e3Sthurlow 			ap->str = arg;
6054bff34e3Sthurlow 			if (arg) {
6064bff34e3Sthurlow 				len = strlen(ap->str);
6074bff34e3Sthurlow 				if (len > ap->ival) {
6084bff34e3Sthurlow 					fprintf(stdout, dgettext(TEXT_DOMAIN,
6094bff34e3Sthurlow 			"opt: Argument for option '%c' (%s) too long\n"),
6104bff34e3Sthurlow 					    ap->opt, ap->name);
6114bff34e3Sthurlow 					return (EINVAL);
6124bff34e3Sthurlow 				}
6134bff34e3Sthurlow 				callback(ap);
6144bff34e3Sthurlow 			}
6154bff34e3Sthurlow 			break;
6164bff34e3Sthurlow 		case OPTARG_BOOL:
6174bff34e3Sthurlow 			ap->ival = 0;
6184bff34e3Sthurlow 			callback(ap);
6194bff34e3Sthurlow 			break;
6204bff34e3Sthurlow 		case OPTARG_INT:
6214bff34e3Sthurlow 			errno = 0;
6224bff34e3Sthurlow 			ap->ival = strtol(arg, NULL, 0);
6234bff34e3Sthurlow 			if (errno) {
6244bff34e3Sthurlow 				fprintf(stdout, dgettext(TEXT_DOMAIN,
6254bff34e3Sthurlow 				    "opt: Invalid integer value for "
6264bff34e3Sthurlow 				    "option '%c' (%s).\n"),
6274bff34e3Sthurlow 				    ap->opt, ap->name);
6284bff34e3Sthurlow 				return (EINVAL);
6294bff34e3Sthurlow 			}
6304bff34e3Sthurlow 			if (((ap->flag & OPTFL_HAVEMIN) &&
6314bff34e3Sthurlow 			    (ap->ival < ap->min)) ||
6324bff34e3Sthurlow 			    ((ap->flag & OPTFL_HAVEMAX) &&
6334bff34e3Sthurlow 			    (ap->ival > ap->max))) {
6344bff34e3Sthurlow 				fprintf(stdout, dgettext(TEXT_DOMAIN,
6354bff34e3Sthurlow 				    "opt: Argument for option '%c' (%s) "
6364bff34e3Sthurlow 				    "should be in [%d-%d] range\n"),
6374bff34e3Sthurlow 				    ap->opt, ap->name, ap->min, ap->max);
6384bff34e3Sthurlow 				return (EINVAL);
6394bff34e3Sthurlow 			}
6404bff34e3Sthurlow 			callback(ap);
6414bff34e3Sthurlow 			break;
6424bff34e3Sthurlow 		default:
6434bff34e3Sthurlow 			break;
6444bff34e3Sthurlow 		}
6454bff34e3Sthurlow 		break;
6464bff34e3Sthurlow 	}
6474bff34e3Sthurlow 	return (0);
6484bff34e3Sthurlow }
649