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: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $ 334bff34e3Sthurlow */ 344bff34e3Sthurlow 354bff34e3Sthurlow #include <sys/types.h> 364bff34e3Sthurlow #include <sys/errno.h> 37*9c9af259SGordon Ross #include <sys/time.h> 384bff34e3Sthurlow 394bff34e3Sthurlow #include <unistd.h> 404bff34e3Sthurlow #include <ctype.h> 414bff34e3Sthurlow #include <string.h> 424bff34e3Sthurlow #include <stdio.h> 434bff34e3Sthurlow #include <stdlib.h> 444bff34e3Sthurlow #include <stdarg.h> 454bff34e3Sthurlow #include <errno.h> 464bff34e3Sthurlow #include <sysexits.h> 474bff34e3Sthurlow #include <libintl.h> 484bff34e3Sthurlow 494bff34e3Sthurlow #include <netsmb/netbios.h> 504bff34e3Sthurlow #include <netsmb/smb_lib.h> 514bff34e3Sthurlow #include <netsmb/nb_lib.h> 524bff34e3Sthurlow #include <cflib.h> 534bff34e3Sthurlow #include <err.h> 544bff34e3Sthurlow 554bff34e3Sthurlow uid_t real_uid, eff_uid; 564bff34e3Sthurlow 574bff34e3Sthurlow static int smblib_initialized; 584bff34e3Sthurlow 594bff34e3Sthurlow struct rcfile *smb_rc; 604bff34e3Sthurlow 614bff34e3Sthurlow int 624bff34e3Sthurlow smb_lib_init(void) 634bff34e3Sthurlow { 644bff34e3Sthurlow int error; 654bff34e3Sthurlow 664bff34e3Sthurlow if (smblib_initialized) 674bff34e3Sthurlow return (0); 684bff34e3Sthurlow if ((error = nls_setlocale("")) != 0) { 694bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 704bff34e3Sthurlow "%s: can't initialise locale\n"), __progname); 714bff34e3Sthurlow return (error); 724bff34e3Sthurlow } 734bff34e3Sthurlow smblib_initialized++; 744bff34e3Sthurlow return (0); 754bff34e3Sthurlow } 764bff34e3Sthurlow 774bff34e3Sthurlow /* 784bff34e3Sthurlow * Private version of strerror(3C) that 794bff34e3Sthurlow * knows our special error codes. 804bff34e3Sthurlow */ 814bff34e3Sthurlow char * 824bff34e3Sthurlow smb_strerror(int err) 834bff34e3Sthurlow { 844bff34e3Sthurlow char *msg; 854bff34e3Sthurlow 864bff34e3Sthurlow switch (err) { 874bff34e3Sthurlow case EBADRPC: 884bff34e3Sthurlow msg = dgettext(TEXT_DOMAIN, 894bff34e3Sthurlow "remote call failed"); 904bff34e3Sthurlow break; 914bff34e3Sthurlow case EAUTH: 924bff34e3Sthurlow msg = dgettext(TEXT_DOMAIN, 934bff34e3Sthurlow "authentication failed"); 944bff34e3Sthurlow break; 954bff34e3Sthurlow default: 964bff34e3Sthurlow msg = strerror(err); 974bff34e3Sthurlow break; 984bff34e3Sthurlow } 994bff34e3Sthurlow 1004bff34e3Sthurlow return (msg); 1014bff34e3Sthurlow } 1024bff34e3Sthurlow 1034bff34e3Sthurlow /* 1044bff34e3Sthurlow * Print a (descriptive) error message 1054bff34e3Sthurlow * error values: 1064bff34e3Sthurlow * 0 - no specific error code available; 1074bff34e3Sthurlow * 1..32767 - system error 1084bff34e3Sthurlow */ 1094bff34e3Sthurlow void 1104bff34e3Sthurlow smb_error(const char *fmt, int error, ...) { 1114bff34e3Sthurlow va_list ap; 1124bff34e3Sthurlow const char *cp; 1134bff34e3Sthurlow int errtype; 1144bff34e3Sthurlow 1154bff34e3Sthurlow fprintf(stderr, "%s: ", __progname); 1164bff34e3Sthurlow va_start(ap, error); 1174bff34e3Sthurlow vfprintf(stderr, fmt, ap); 1184bff34e3Sthurlow va_end(ap); 1194bff34e3Sthurlow if (error == -1) { 1204bff34e3Sthurlow error = errno; 1214bff34e3Sthurlow errtype = SMB_SYS_ERROR; 1224bff34e3Sthurlow } else { 1234bff34e3Sthurlow errtype = error & SMB_ERRTYPE_MASK; 1244bff34e3Sthurlow error &= ~SMB_ERRTYPE_MASK; 1254bff34e3Sthurlow } 1264bff34e3Sthurlow switch (errtype) { 1274bff34e3Sthurlow case SMB_SYS_ERROR: 1284bff34e3Sthurlow if (error) 1294bff34e3Sthurlow fprintf(stderr, ": syserr = %s\n", smb_strerror(error)); 1304bff34e3Sthurlow else 1314bff34e3Sthurlow fprintf(stderr, "\n"); 1324bff34e3Sthurlow break; 1334bff34e3Sthurlow case SMB_RAP_ERROR: 1344bff34e3Sthurlow fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error); 1354bff34e3Sthurlow break; 1364bff34e3Sthurlow case SMB_NB_ERROR: 1374bff34e3Sthurlow cp = nb_strerror(error); 1384bff34e3Sthurlow if (cp == NULL) 1394bff34e3Sthurlow fprintf(stderr, ": nberr = unknown (0x%04x)\n", error); 1404bff34e3Sthurlow else 1414bff34e3Sthurlow fprintf(stderr, ": nberr = %s\n", cp); 1424bff34e3Sthurlow break; 1434bff34e3Sthurlow default: 1444bff34e3Sthurlow fprintf(stderr, "\n"); 1454bff34e3Sthurlow } 1464bff34e3Sthurlow } 1474bff34e3Sthurlow 1484bff34e3Sthurlow char * 1494bff34e3Sthurlow smb_printb(char *dest, int flags, const struct smb_bitname *bnp) { 1504bff34e3Sthurlow int first = 1; 1514bff34e3Sthurlow 1524bff34e3Sthurlow strcpy(dest, "<"); 1534bff34e3Sthurlow for (; bnp->bn_bit; bnp++) { 1544bff34e3Sthurlow if (flags & bnp->bn_bit) { 1554bff34e3Sthurlow strcat(dest, bnp->bn_name); 1564bff34e3Sthurlow first = 0; 1574bff34e3Sthurlow } 1584bff34e3Sthurlow if (!first && (flags & bnp[1].bn_bit)) 1594bff34e3Sthurlow strcat(dest, "|"); 1604bff34e3Sthurlow } 1614bff34e3Sthurlow strcat(dest, ">"); 1624bff34e3Sthurlow return (dest); 1634bff34e3Sthurlow } 1644bff34e3Sthurlow 1654bff34e3Sthurlow extern int home_nsmbrc; 1664bff34e3Sthurlow 1674bff34e3Sthurlow #ifdef DEBUG 1684bff34e3Sthurlow #include "queue.h" 1694bff34e3Sthurlow #include "rcfile_priv.h" 1704bff34e3Sthurlow 1714bff34e3Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname); 1724bff34e3Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname); 1734bff34e3Sthurlow 1744bff34e3Sthurlow void 1754bff34e3Sthurlow dump_props(char *where) 1764bff34e3Sthurlow { 1774bff34e3Sthurlow struct rcsection *rsp = NULL; 1784bff34e3Sthurlow struct rckey *rkp = NULL; 1794bff34e3Sthurlow 1804bff34e3Sthurlow printf("Settings %s\n", where); 1814bff34e3Sthurlow SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) { 1824bff34e3Sthurlow printf("section=%s\n", rsp->rs_name); 1834bff34e3Sthurlow fflush(stdout); 1844bff34e3Sthurlow 1854bff34e3Sthurlow SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) { 1864bff34e3Sthurlow printf(" key=%s, value=%s\n", 1874bff34e3Sthurlow rkp->rk_name, rkp->rk_value); 1884bff34e3Sthurlow fflush(stdout); 1894bff34e3Sthurlow } 1904bff34e3Sthurlow } 1914bff34e3Sthurlow } 1924bff34e3Sthurlow #endif 1934bff34e3Sthurlow 1944bff34e3Sthurlow /* 1954bff34e3Sthurlow * first read ~/.smbrc, next try to merge SMB_CFG_FILE - if that fails 1964bff34e3Sthurlow * because SMB_CFG_FILE doesn't exist, try to merge OLD_SMB_CFG_FILE 1974bff34e3Sthurlow */ 1984bff34e3Sthurlow int 1994bff34e3Sthurlow smb_open_rcfile(struct smb_ctx *ctx) 2004bff34e3Sthurlow { 2014bff34e3Sthurlow char *home, *fn; 2024bff34e3Sthurlow int error, len; 2034bff34e3Sthurlow 2044bff34e3Sthurlow smb_rc = NULL; 2054bff34e3Sthurlow #ifdef DEPRECATED 2064bff34e3Sthurlow fn = SMB_CFG_FILE; 2074bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 2084bff34e3Sthurlow if (error == ENOENT) { 2094bff34e3Sthurlow /* 2104bff34e3Sthurlow * OK, try to read a config file in the old location. 2114bff34e3Sthurlow */ 2124bff34e3Sthurlow fn = OLD_SMB_CFG_FILE; 2134bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 2144bff34e3Sthurlow } 2154bff34e3Sthurlow #endif 2164bff34e3Sthurlow fn = "/usr/sbin/sharectl get smbfs"; 2174bff34e3Sthurlow error = rc_merge_pipe(fn, &smb_rc); 2184bff34e3Sthurlow if (error != 0 && error != ENOENT) 2194bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 2204bff34e3Sthurlow "Can't open %s: %s\n"), fn, smb_strerror(errno)); 2214bff34e3Sthurlow #ifdef DEBUG 222*9c9af259SGordon Ross if (smb_debug) 2234bff34e3Sthurlow dump_props("after reading global repository"); 2244bff34e3Sthurlow #endif 2254bff34e3Sthurlow 2264bff34e3Sthurlow home = getenv("HOME"); 2274bff34e3Sthurlow if (home == NULL && ctx && ctx->ct_home) 2284bff34e3Sthurlow home = ctx->ct_home; 2294bff34e3Sthurlow if (home) { 2304bff34e3Sthurlow len = strlen(home) + 20; 2314bff34e3Sthurlow fn = malloc(len); 2324bff34e3Sthurlow snprintf(fn, len, "%s/.nsmbrc", home); 2334bff34e3Sthurlow home_nsmbrc = 1; 2344bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 2354bff34e3Sthurlow if (error != 0 && error != ENOENT) { 2364bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 2374bff34e3Sthurlow "Can't open %s: %s\n"), fn, smb_strerror(errno)); 2384bff34e3Sthurlow } 2394bff34e3Sthurlow free(fn); 2404bff34e3Sthurlow } 2414bff34e3Sthurlow home_nsmbrc = 0; 2424bff34e3Sthurlow #ifdef DEBUG 243*9c9af259SGordon Ross if (smb_debug) 2444bff34e3Sthurlow dump_props("after reading user settings"); 2454bff34e3Sthurlow #endif 2464bff34e3Sthurlow if (smb_rc == NULL) { 2474bff34e3Sthurlow return (ENOENT); 2484bff34e3Sthurlow } 2494bff34e3Sthurlow return (0); 2504bff34e3Sthurlow } 2514bff34e3Sthurlow 2524bff34e3Sthurlow void 2534bff34e3Sthurlow smb_simplecrypt(char *dst, const char *src) 2544bff34e3Sthurlow { 2554bff34e3Sthurlow int ch, pos; 2564bff34e3Sthurlow 2574bff34e3Sthurlow *dst++ = '$'; 2584bff34e3Sthurlow *dst++ = '$'; 2594bff34e3Sthurlow *dst++ = '1'; 2604bff34e3Sthurlow pos = 27; 2614bff34e3Sthurlow while (*src) { 2624bff34e3Sthurlow ch = *src++; 2634bff34e3Sthurlow if (isascii(ch)) 2644bff34e3Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) : 2654bff34e3Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch); 2664bff34e3Sthurlow ch ^= pos; 2674bff34e3Sthurlow pos += 13; 2684bff34e3Sthurlow sprintf(dst, "%02x", ch); 2694bff34e3Sthurlow dst += 2; 2704bff34e3Sthurlow } 2714bff34e3Sthurlow *dst = 0; 2724bff34e3Sthurlow } 2734bff34e3Sthurlow 2744bff34e3Sthurlow int 2754bff34e3Sthurlow smb_simpledecrypt(char *dst, const char *src) 2764bff34e3Sthurlow { 2774bff34e3Sthurlow char *ep, hexval[3]; 2784bff34e3Sthurlow int len, ch, pos; 2794bff34e3Sthurlow 2804bff34e3Sthurlow if (strncmp(src, "$$1", 3) != 0) 2814bff34e3Sthurlow return (EINVAL); 2824bff34e3Sthurlow src += 3; 2834bff34e3Sthurlow len = strlen(src); 2844bff34e3Sthurlow if (len & 1) 2854bff34e3Sthurlow return (EINVAL); 2864bff34e3Sthurlow len /= 2; 2874bff34e3Sthurlow hexval[2] = 0; 2884bff34e3Sthurlow pos = 27; 2894bff34e3Sthurlow while (len--) { 2904bff34e3Sthurlow hexval[0] = *src++; 2914bff34e3Sthurlow hexval[1] = *src++; 2924bff34e3Sthurlow ch = strtoul(hexval, &ep, 16); 2934bff34e3Sthurlow if (*ep != 0) 2944bff34e3Sthurlow return (EINVAL); 2954bff34e3Sthurlow ch ^= pos; 2964bff34e3Sthurlow pos += 13; 2974bff34e3Sthurlow if (isascii(ch)) 2984bff34e3Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) : 2994bff34e3Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch); 3004bff34e3Sthurlow *dst++ = ch; 3014bff34e3Sthurlow } 3024bff34e3Sthurlow *dst = 0; 3034bff34e3Sthurlow return (0); 3044bff34e3Sthurlow } 3054bff34e3Sthurlow 3064bff34e3Sthurlow #undef __progname 3074bff34e3Sthurlow 3084bff34e3Sthurlow char *__progname = NULL; 3094bff34e3Sthurlow 3104bff34e3Sthurlow char * 3114bff34e3Sthurlow smb_getprogname() 3124bff34e3Sthurlow { 3134bff34e3Sthurlow char *p; 3144bff34e3Sthurlow 3154bff34e3Sthurlow if (__progname == NULL) { 3164bff34e3Sthurlow __progname = (char *)getexecname(); 3174bff34e3Sthurlow if ((p = strrchr(__progname, '/')) != 0) 3184bff34e3Sthurlow __progname = p + 1; 3194bff34e3Sthurlow } 3204bff34e3Sthurlow return (__progname); 3214bff34e3Sthurlow } 322