2 * Copyright (c) 2000, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: subr.c,v 1.12 2001/08/22 03:31:37 bp Exp $
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/errno.h>
38 #include <sys/sysctl.h>
39 #include <sys/syscall.h>
48 #include <netsmb/netbios.h>
49 #include <netsmb/smb_lib.h>
50 #include <netsmb/nb_lib.h>
56 #include <mach/mach.h>
57 #include <mach/mach_error.h>
59 uid_t real_uid, eff_uid;
62 extern char *__progname;
64 static int smblib_initialized;
66 struct rcfile *smb_rc;
73 size_t kvlen = sizeof(kv);
75 if (smblib_initialized)
77 #if __FreeBSD_version > 400000
78 error = sysctlbyname("net.smb.version", &kv, &kvlen, NULL, 0);
80 warnx("%s: can't find kernel module\n", __FUNCTION__);
83 if (NSMB_VERSION != kv) {
84 warnx("%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NSMB_VERSION);
88 if ((error = nls_setlocale("")) != 0) {
89 warnx("%s: can't initialise locale\n", __FUNCTION__);
97 * Print a (descriptive) error message
99 * 0 - no specific error code available;
100 * 1..32767 - system error
103 smb_error(const char *fmt, int error,...) {
106 int errtype = error & SMB_ERRTYPE_MASK;
108 fprintf(stderr, "%s: ", __progname);
110 vfprintf(stderr, fmt, ap);
115 error &= ~SMB_ERRTYPE_MASK;
119 fprintf(stderr, ": syserr = %s\n", strerror(error));
121 fprintf(stderr, "\n");
124 fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
127 cp = nb_strerror(error);
129 fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
131 fprintf(stderr, ": nberr = %s\n", cp);
134 fprintf(stderr, "\n");
139 smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
143 for(; bnp->bn_bit; bnp++) {
144 if (flags & bnp->bn_bit) {
145 strcat(dest, bnp->bn_name);
148 if (!first && (flags & bnp[1].bn_bit))
156 * first read ~/.smbrc, next try to merge SMB_CFG_FILE
159 smb_open_rcfile(void)
164 home = getenv("HOME");
166 fn = malloc(strlen(home) + 20);
167 sprintf(fn, "%s/.nsmbrc", home);
168 error = rc_open(fn, "r", &smb_rc);
171 error = rc_merge(SMB_CFG_FILE, &smb_rc);
172 if (smb_rc == NULL) {
173 printf("Warning: no cfg file(s) found.\n");
187 seteuid(eff_uid); /* restore setuid root briefly */
189 error = sysctlbyname("net.smb.treedump", NULL, &len, NULL, 0);
191 seteuid(real_uid); /* and back to real user */
199 seteuid(eff_uid); /* restore setuid root briefly */
201 error = sysctlbyname("net.smb.treedump", p, &len, NULL, 0);
203 seteuid(real_uid); /* and back to real user */
213 smb_simplecrypt(char *dst, const char *src)
219 dst = malloc(4 + 2 * strlen(src));
231 ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
232 islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
235 sprintf(dst, "%02x", ch);
243 smb_simpledecrypt(char *dst, const char *src)
248 if (strncmp(src, "$$1", 3) != 0)
260 ch = strtoul(hexval, &ep, 16);
266 ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
267 islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
277 safe_execv(char *args[])
284 (void)execv(args[0], args);
285 errx(EX_OSERR, "%s: execv %s failed, %s\n", __progname,
286 args[0], strerror(errno));
289 fprintf(stderr, "%s: fork failed, %s\n", __progname,
293 if (wait4(pid, (int *)&status, 0, NULL) != pid) {
294 fprintf(stderr, "%s: BUG executing %s command\n", __progname,
297 } else if (!WIFEXITED(status)) {
298 fprintf(stderr, "%s: %s command aborted by signal %d\n",
299 __progname, args[0], WTERMSIG(status));
301 } else if (WEXITSTATUS(status)) {
302 fprintf(stderr, "%s: %s command failed, exit status %d: %s\n",
303 __progname, args[0], WEXITSTATUS(status),
304 strerror(WEXITSTATUS(status)));
314 /* drop setuid root privs asap */
323 kextisloaded(char * kextname)
325 mach_port_t kernel_port;
326 kmod_info_t *k, *loaded_modules = 0;
327 int err, loaded_count = 0;
329 /* on error return not loaded - to make loadsmbvfs fail */
331 err = task_for_pid(mach_task_self(), 0, &kernel_port);
333 fprintf(stderr, "%s: %s: %s\n", __progname,
334 "unable to get kernel task port",
335 mach_error_string(err));
338 err = kmod_get_info(kernel_port, (void *)&loaded_modules,
339 &loaded_count); /* never freed */
341 fprintf(stderr, "%s: %s: %s\n", __progname,
342 "kmod_get_info() failed",
343 mach_error_string(err));
346 for (k = loaded_modules; k; k = k->next ? k+1 : 0)
347 if (!strcmp(k->name, kextname))
353 #define KEXTLOAD_COMMAND "/sbin/kextload"
354 #define FS_KEXT_DIR "/System/Library/Extensions/smbfs.kext"
355 #define FULL_KEXTNAME "com.apple.filesystems.smbfs"
361 const char *kextargs[] = {KEXTLOAD_COMMAND, FS_KEXT_DIR, NULL};
365 * temporarily revert to root (required for kextload)
368 if (!kextisloaded(FULL_KEXTNAME)) {
369 error = safe_execv(kextargs);
371 error = !kextisloaded(FULL_KEXTNAME);
373 seteuid(real_uid); /* and back to real user */