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