1*4bff34e3Sthurlow /* 2*4bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 3*4bff34e3Sthurlow * All rights reserved. 4*4bff34e3Sthurlow * 5*4bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 6*4bff34e3Sthurlow * modification, are permitted provided that the following conditions 7*4bff34e3Sthurlow * are met: 8*4bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 9*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 10*4bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 11*4bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 12*4bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 13*4bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 14*4bff34e3Sthurlow * must display the following acknowledgement: 15*4bff34e3Sthurlow * This product includes software developed by Boris Popov. 16*4bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 17*4bff34e3Sthurlow * may be used to endorse or promote products derived from this software 18*4bff34e3Sthurlow * without specific prior written permission. 19*4bff34e3Sthurlow * 20*4bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4bff34e3Sthurlow * SUCH DAMAGE. 31*4bff34e3Sthurlow * 32*4bff34e3Sthurlow * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $ 33*4bff34e3Sthurlow */ 34*4bff34e3Sthurlow 35*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 36*4bff34e3Sthurlow 37*4bff34e3Sthurlow #include <sys/param.h> 38*4bff34e3Sthurlow #include <sys/types.h> 39*4bff34e3Sthurlow #include <sys/errno.h> 40*4bff34e3Sthurlow #include <sys/syscall.h> 41*4bff34e3Sthurlow #include <sys/wait.h> 42*4bff34e3Sthurlow #include <sys/debug.h> 43*4bff34e3Sthurlow 44*4bff34e3Sthurlow #include <unistd.h> 45*4bff34e3Sthurlow #include <ctype.h> 46*4bff34e3Sthurlow #include <string.h> 47*4bff34e3Sthurlow #include <stdio.h> 48*4bff34e3Sthurlow #include <stdlib.h> 49*4bff34e3Sthurlow #include <stdarg.h> 50*4bff34e3Sthurlow #include <errno.h> 51*4bff34e3Sthurlow #include <sysexits.h> 52*4bff34e3Sthurlow #include <libintl.h> 53*4bff34e3Sthurlow 54*4bff34e3Sthurlow #include <netsmb/netbios.h> 55*4bff34e3Sthurlow #include <netsmb/smb_lib.h> 56*4bff34e3Sthurlow #include <netsmb/nb_lib.h> 57*4bff34e3Sthurlow #include <cflib.h> 58*4bff34e3Sthurlow #include <err.h> 59*4bff34e3Sthurlow 60*4bff34e3Sthurlow uid_t real_uid, eff_uid; 61*4bff34e3Sthurlow 62*4bff34e3Sthurlow static int smblib_initialized; 63*4bff34e3Sthurlow 64*4bff34e3Sthurlow struct rcfile *smb_rc; 65*4bff34e3Sthurlow 66*4bff34e3Sthurlow int 67*4bff34e3Sthurlow smb_lib_init(void) 68*4bff34e3Sthurlow { 69*4bff34e3Sthurlow int error; 70*4bff34e3Sthurlow 71*4bff34e3Sthurlow if (smblib_initialized) 72*4bff34e3Sthurlow return (0); 73*4bff34e3Sthurlow if ((error = nls_setlocale("")) != 0) { 74*4bff34e3Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN, 75*4bff34e3Sthurlow "%s: can't initialise locale\n"), __progname); 76*4bff34e3Sthurlow return (error); 77*4bff34e3Sthurlow } 78*4bff34e3Sthurlow smblib_initialized++; 79*4bff34e3Sthurlow return (0); 80*4bff34e3Sthurlow } 81*4bff34e3Sthurlow 82*4bff34e3Sthurlow /* 83*4bff34e3Sthurlow * Private version of strerror(3C) that 84*4bff34e3Sthurlow * knows our special error codes. 85*4bff34e3Sthurlow */ 86*4bff34e3Sthurlow char * 87*4bff34e3Sthurlow smb_strerror(int err) 88*4bff34e3Sthurlow { 89*4bff34e3Sthurlow char *msg; 90*4bff34e3Sthurlow 91*4bff34e3Sthurlow switch (err) { 92*4bff34e3Sthurlow case EBADRPC: 93*4bff34e3Sthurlow msg = dgettext(TEXT_DOMAIN, 94*4bff34e3Sthurlow "remote call failed"); 95*4bff34e3Sthurlow break; 96*4bff34e3Sthurlow case EAUTH: 97*4bff34e3Sthurlow msg = dgettext(TEXT_DOMAIN, 98*4bff34e3Sthurlow "authentication failed"); 99*4bff34e3Sthurlow break; 100*4bff34e3Sthurlow default: 101*4bff34e3Sthurlow msg = strerror(err); 102*4bff34e3Sthurlow break; 103*4bff34e3Sthurlow } 104*4bff34e3Sthurlow 105*4bff34e3Sthurlow return (msg); 106*4bff34e3Sthurlow } 107*4bff34e3Sthurlow 108*4bff34e3Sthurlow /* 109*4bff34e3Sthurlow * Print a (descriptive) error message 110*4bff34e3Sthurlow * error values: 111*4bff34e3Sthurlow * 0 - no specific error code available; 112*4bff34e3Sthurlow * 1..32767 - system error 113*4bff34e3Sthurlow */ 114*4bff34e3Sthurlow void 115*4bff34e3Sthurlow smb_error(const char *fmt, int error, ...) { 116*4bff34e3Sthurlow va_list ap; 117*4bff34e3Sthurlow const char *cp; 118*4bff34e3Sthurlow int errtype; 119*4bff34e3Sthurlow 120*4bff34e3Sthurlow fprintf(stderr, "%s: ", __progname); 121*4bff34e3Sthurlow va_start(ap, error); 122*4bff34e3Sthurlow vfprintf(stderr, fmt, ap); 123*4bff34e3Sthurlow va_end(ap); 124*4bff34e3Sthurlow if (error == -1) { 125*4bff34e3Sthurlow error = errno; 126*4bff34e3Sthurlow errtype = SMB_SYS_ERROR; 127*4bff34e3Sthurlow } else { 128*4bff34e3Sthurlow errtype = error & SMB_ERRTYPE_MASK; 129*4bff34e3Sthurlow error &= ~SMB_ERRTYPE_MASK; 130*4bff34e3Sthurlow } 131*4bff34e3Sthurlow switch (errtype) { 132*4bff34e3Sthurlow case SMB_SYS_ERROR: 133*4bff34e3Sthurlow if (error) 134*4bff34e3Sthurlow fprintf(stderr, ": syserr = %s\n", smb_strerror(error)); 135*4bff34e3Sthurlow else 136*4bff34e3Sthurlow fprintf(stderr, "\n"); 137*4bff34e3Sthurlow break; 138*4bff34e3Sthurlow case SMB_RAP_ERROR: 139*4bff34e3Sthurlow fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error); 140*4bff34e3Sthurlow break; 141*4bff34e3Sthurlow case SMB_NB_ERROR: 142*4bff34e3Sthurlow cp = nb_strerror(error); 143*4bff34e3Sthurlow if (cp == NULL) 144*4bff34e3Sthurlow fprintf(stderr, ": nberr = unknown (0x%04x)\n", error); 145*4bff34e3Sthurlow else 146*4bff34e3Sthurlow fprintf(stderr, ": nberr = %s\n", cp); 147*4bff34e3Sthurlow break; 148*4bff34e3Sthurlow default: 149*4bff34e3Sthurlow fprintf(stderr, "\n"); 150*4bff34e3Sthurlow } 151*4bff34e3Sthurlow } 152*4bff34e3Sthurlow 153*4bff34e3Sthurlow char * 154*4bff34e3Sthurlow smb_printb(char *dest, int flags, const struct smb_bitname *bnp) { 155*4bff34e3Sthurlow int first = 1; 156*4bff34e3Sthurlow 157*4bff34e3Sthurlow strcpy(dest, "<"); 158*4bff34e3Sthurlow for (; bnp->bn_bit; bnp++) { 159*4bff34e3Sthurlow if (flags & bnp->bn_bit) { 160*4bff34e3Sthurlow strcat(dest, bnp->bn_name); 161*4bff34e3Sthurlow first = 0; 162*4bff34e3Sthurlow } 163*4bff34e3Sthurlow if (!first && (flags & bnp[1].bn_bit)) 164*4bff34e3Sthurlow strcat(dest, "|"); 165*4bff34e3Sthurlow } 166*4bff34e3Sthurlow strcat(dest, ">"); 167*4bff34e3Sthurlow return (dest); 168*4bff34e3Sthurlow } 169*4bff34e3Sthurlow 170*4bff34e3Sthurlow extern int home_nsmbrc; 171*4bff34e3Sthurlow 172*4bff34e3Sthurlow #ifdef DEBUG 173*4bff34e3Sthurlow #include "queue.h" 174*4bff34e3Sthurlow #include "rcfile_priv.h" 175*4bff34e3Sthurlow 176*4bff34e3Sthurlow struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname); 177*4bff34e3Sthurlow struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname); 178*4bff34e3Sthurlow 179*4bff34e3Sthurlow void 180*4bff34e3Sthurlow dump_props(char *where) 181*4bff34e3Sthurlow { 182*4bff34e3Sthurlow struct rcsection *rsp = NULL; 183*4bff34e3Sthurlow struct rckey *rkp = NULL; 184*4bff34e3Sthurlow 185*4bff34e3Sthurlow printf("Settings %s\n", where); 186*4bff34e3Sthurlow SLIST_FOREACH(rsp, &smb_rc->rf_sect, rs_next) { 187*4bff34e3Sthurlow printf("section=%s\n", rsp->rs_name); 188*4bff34e3Sthurlow fflush(stdout); 189*4bff34e3Sthurlow 190*4bff34e3Sthurlow SLIST_FOREACH(rkp, &rsp->rs_keys, rk_next) { 191*4bff34e3Sthurlow printf(" key=%s, value=%s\n", 192*4bff34e3Sthurlow rkp->rk_name, rkp->rk_value); 193*4bff34e3Sthurlow fflush(stdout); 194*4bff34e3Sthurlow } 195*4bff34e3Sthurlow } 196*4bff34e3Sthurlow } 197*4bff34e3Sthurlow #endif 198*4bff34e3Sthurlow 199*4bff34e3Sthurlow /* 200*4bff34e3Sthurlow * first read ~/.smbrc, next try to merge SMB_CFG_FILE - if that fails 201*4bff34e3Sthurlow * because SMB_CFG_FILE doesn't exist, try to merge OLD_SMB_CFG_FILE 202*4bff34e3Sthurlow */ 203*4bff34e3Sthurlow int 204*4bff34e3Sthurlow smb_open_rcfile(struct smb_ctx *ctx) 205*4bff34e3Sthurlow { 206*4bff34e3Sthurlow char *home, *fn; 207*4bff34e3Sthurlow int error, len; 208*4bff34e3Sthurlow 209*4bff34e3Sthurlow smb_rc = NULL; 210*4bff34e3Sthurlow #ifdef DEPRECATED 211*4bff34e3Sthurlow fn = SMB_CFG_FILE; 212*4bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 213*4bff34e3Sthurlow if (error == ENOENT) { 214*4bff34e3Sthurlow /* 215*4bff34e3Sthurlow * OK, try to read a config file in the old location. 216*4bff34e3Sthurlow */ 217*4bff34e3Sthurlow fn = OLD_SMB_CFG_FILE; 218*4bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 219*4bff34e3Sthurlow } 220*4bff34e3Sthurlow #endif 221*4bff34e3Sthurlow fn = "/usr/sbin/sharectl get smbfs"; 222*4bff34e3Sthurlow error = rc_merge_pipe(fn, &smb_rc); 223*4bff34e3Sthurlow if (error != 0 && error != ENOENT) 224*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 225*4bff34e3Sthurlow "Can't open %s: %s\n"), fn, smb_strerror(errno)); 226*4bff34e3Sthurlow #ifdef DEBUG 227*4bff34e3Sthurlow dump_props("after reading global repository"); 228*4bff34e3Sthurlow #endif 229*4bff34e3Sthurlow 230*4bff34e3Sthurlow home = getenv("HOME"); 231*4bff34e3Sthurlow if (home == NULL && ctx && ctx->ct_home) 232*4bff34e3Sthurlow home = ctx->ct_home; 233*4bff34e3Sthurlow if (home) { 234*4bff34e3Sthurlow len = strlen(home) + 20; 235*4bff34e3Sthurlow fn = malloc(len); 236*4bff34e3Sthurlow snprintf(fn, len, "%s/.nsmbrc", home); 237*4bff34e3Sthurlow home_nsmbrc = 1; 238*4bff34e3Sthurlow error = rc_merge(fn, &smb_rc); 239*4bff34e3Sthurlow if (error != 0 && error != ENOENT) { 240*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 241*4bff34e3Sthurlow "Can't open %s: %s\n"), fn, smb_strerror(errno)); 242*4bff34e3Sthurlow } 243*4bff34e3Sthurlow free(fn); 244*4bff34e3Sthurlow } 245*4bff34e3Sthurlow home_nsmbrc = 0; 246*4bff34e3Sthurlow #ifdef DEBUG 247*4bff34e3Sthurlow dump_props("after reading user settings"); 248*4bff34e3Sthurlow #endif 249*4bff34e3Sthurlow if (smb_rc == NULL) { 250*4bff34e3Sthurlow return (ENOENT); 251*4bff34e3Sthurlow } 252*4bff34e3Sthurlow return (0); 253*4bff34e3Sthurlow } 254*4bff34e3Sthurlow 255*4bff34e3Sthurlow void 256*4bff34e3Sthurlow smb_simplecrypt(char *dst, const char *src) 257*4bff34e3Sthurlow { 258*4bff34e3Sthurlow int ch, pos; 259*4bff34e3Sthurlow 260*4bff34e3Sthurlow *dst++ = '$'; 261*4bff34e3Sthurlow *dst++ = '$'; 262*4bff34e3Sthurlow *dst++ = '1'; 263*4bff34e3Sthurlow pos = 27; 264*4bff34e3Sthurlow while (*src) { 265*4bff34e3Sthurlow ch = *src++; 266*4bff34e3Sthurlow if (isascii(ch)) 267*4bff34e3Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) : 268*4bff34e3Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch); 269*4bff34e3Sthurlow ch ^= pos; 270*4bff34e3Sthurlow pos += 13; 271*4bff34e3Sthurlow sprintf(dst, "%02x", ch); 272*4bff34e3Sthurlow dst += 2; 273*4bff34e3Sthurlow } 274*4bff34e3Sthurlow *dst = 0; 275*4bff34e3Sthurlow } 276*4bff34e3Sthurlow 277*4bff34e3Sthurlow int 278*4bff34e3Sthurlow smb_simpledecrypt(char *dst, const char *src) 279*4bff34e3Sthurlow { 280*4bff34e3Sthurlow char *ep, hexval[3]; 281*4bff34e3Sthurlow int len, ch, pos; 282*4bff34e3Sthurlow 283*4bff34e3Sthurlow if (strncmp(src, "$$1", 3) != 0) 284*4bff34e3Sthurlow return (EINVAL); 285*4bff34e3Sthurlow src += 3; 286*4bff34e3Sthurlow len = strlen(src); 287*4bff34e3Sthurlow if (len & 1) 288*4bff34e3Sthurlow return (EINVAL); 289*4bff34e3Sthurlow len /= 2; 290*4bff34e3Sthurlow hexval[2] = 0; 291*4bff34e3Sthurlow pos = 27; 292*4bff34e3Sthurlow while (len--) { 293*4bff34e3Sthurlow hexval[0] = *src++; 294*4bff34e3Sthurlow hexval[1] = *src++; 295*4bff34e3Sthurlow ch = strtoul(hexval, &ep, 16); 296*4bff34e3Sthurlow if (*ep != 0) 297*4bff34e3Sthurlow return (EINVAL); 298*4bff34e3Sthurlow ch ^= pos; 299*4bff34e3Sthurlow pos += 13; 300*4bff34e3Sthurlow if (isascii(ch)) 301*4bff34e3Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) : 302*4bff34e3Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch); 303*4bff34e3Sthurlow *dst++ = ch; 304*4bff34e3Sthurlow } 305*4bff34e3Sthurlow *dst = 0; 306*4bff34e3Sthurlow return (0); 307*4bff34e3Sthurlow } 308*4bff34e3Sthurlow 309*4bff34e3Sthurlow 310*4bff34e3Sthurlow static int 311*4bff34e3Sthurlow safe_execv(char *args[]) 312*4bff34e3Sthurlow { 313*4bff34e3Sthurlow int pid; 314*4bff34e3Sthurlow int status; 315*4bff34e3Sthurlow 316*4bff34e3Sthurlow pid = fork(); 317*4bff34e3Sthurlow if (pid == 0) { 318*4bff34e3Sthurlow (void) execv(args[0], args); 319*4bff34e3Sthurlow /* Changed from errx() to fprintf(stderr) -Pavan */ 320*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 321*4bff34e3Sthurlow "%s: execv %s failed, %s\n"), __progname, 322*4bff34e3Sthurlow args[0], smb_strerror(errno)); 323*4bff34e3Sthurlow } 324*4bff34e3Sthurlow if (pid == -1) { 325*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, "%s: fork failed, %s\n"), 326*4bff34e3Sthurlow __progname, smb_strerror(errno)); 327*4bff34e3Sthurlow return (1); 328*4bff34e3Sthurlow } 329*4bff34e3Sthurlow if (wait4(pid, &status, 0, NULL) != pid) { 330*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 331*4bff34e3Sthurlow "%s: BUG executing %s command\n"), __progname, args[0]); 332*4bff34e3Sthurlow return (1); 333*4bff34e3Sthurlow } else if (!WIFEXITED(status)) { 334*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 335*4bff34e3Sthurlow "%s: %s command aborted by signal %d\n"), 336*4bff34e3Sthurlow __progname, args[0], WTERMSIG(status)); 337*4bff34e3Sthurlow return (1); 338*4bff34e3Sthurlow } else if (WEXITSTATUS(status)) { 339*4bff34e3Sthurlow fprintf(stderr, dgettext(TEXT_DOMAIN, 340*4bff34e3Sthurlow "%s: %s command failed, exit status %d: %s\n"), 341*4bff34e3Sthurlow __progname, args[0], WEXITSTATUS(status), 342*4bff34e3Sthurlow smb_strerror(WEXITSTATUS(status))); 343*4bff34e3Sthurlow return (1); 344*4bff34e3Sthurlow } 345*4bff34e3Sthurlow return (0); 346*4bff34e3Sthurlow } 347*4bff34e3Sthurlow 348*4bff34e3Sthurlow 349*4bff34e3Sthurlow void 350*4bff34e3Sthurlow dropsuid() 351*4bff34e3Sthurlow { 352*4bff34e3Sthurlow /* drop setuid root privs asap */ 353*4bff34e3Sthurlow eff_uid = geteuid(); 354*4bff34e3Sthurlow real_uid = getuid(); 355*4bff34e3Sthurlow seteuid(real_uid); 356*4bff34e3Sthurlow } 357*4bff34e3Sthurlow 358*4bff34e3Sthurlow 359*4bff34e3Sthurlow #define KEXTLOAD_COMMAND "/sbin/kextload" 360*4bff34e3Sthurlow #define FS_KEXT_DIR "/System/Library/Extensions/smbfs.kext" 361*4bff34e3Sthurlow #define FULL_KEXTNAME "com.apple.filesystems.smbfs" 362*4bff34e3Sthurlow 363*4bff34e3Sthurlow 364*4bff34e3Sthurlow int 365*4bff34e3Sthurlow loadsmbvfs() 366*4bff34e3Sthurlow { 367*4bff34e3Sthurlow char *kextargs[] = {KEXTLOAD_COMMAND, FS_KEXT_DIR, NULL}; 368*4bff34e3Sthurlow int error = 0; 369*4bff34e3Sthurlow 370*4bff34e3Sthurlow /* 371*4bff34e3Sthurlow * temporarily revert to root (required for kextload) 372*4bff34e3Sthurlow */ 373*4bff34e3Sthurlow seteuid(eff_uid); 374*4bff34e3Sthurlow error = safe_execv(kextargs); 375*4bff34e3Sthurlow seteuid(real_uid); /* and back to real user */ 376*4bff34e3Sthurlow return (error); 377*4bff34e3Sthurlow } 378*4bff34e3Sthurlow 379*4bff34e3Sthurlow #undef __progname 380*4bff34e3Sthurlow 381*4bff34e3Sthurlow char *__progname = NULL; 382*4bff34e3Sthurlow 383*4bff34e3Sthurlow char * 384*4bff34e3Sthurlow smb_getprogname() 385*4bff34e3Sthurlow { 386*4bff34e3Sthurlow char *p; 387*4bff34e3Sthurlow 388*4bff34e3Sthurlow if (__progname == NULL) { 389*4bff34e3Sthurlow __progname = (char *)getexecname(); 390*4bff34e3Sthurlow if ((p = strrchr(__progname, '/')) != 0) 391*4bff34e3Sthurlow __progname = p + 1; 392*4bff34e3Sthurlow } 393*4bff34e3Sthurlow return (__progname); 394*4bff34e3Sthurlow } 395