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