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 error = sysctlbyname("net.smb.version", &kv, &kvlen, NULL, 0);
79 warnx("%s: can't find kernel module\n", __FUNCTION__);
82 if (NSMB_VERSION != kv) {
83 warnx("%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NSMB_VERSION);
86 if ((error = nls_setlocale("")) != 0) {
87 warnx("%s: can't initialise locale\n", __FUNCTION__);
95 * Print a (descriptive) error message
97 * 0 - no specific error code available;
98 * 1..32767 - system error
101 smb_error(const char *fmt, int error,...) {
104 int errtype = error & SMB_ERRTYPE_MASK;
106 fprintf(stderr, "%s: ", __progname);
108 vfprintf(stderr, fmt, ap);
113 error &= ~SMB_ERRTYPE_MASK;
117 fprintf(stderr, ": syserr = %s\n", strerror(error));
119 fprintf(stderr, "\n");
122 fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
125 cp = nb_strerror(error);
127 fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
129 fprintf(stderr, ": nberr = %s\n", cp);
132 fprintf(stderr, "\n");
137 smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
141 for(; bnp->bn_bit; bnp++) {
142 if (flags & bnp->bn_bit) {
143 strcat(dest, bnp->bn_name);
146 if (!first && (flags & bnp[1].bn_bit))
154 * first read ~/.smbrc, next try to merge SMB_CFG_FILE
157 smb_open_rcfile(void)
162 home = getenv("HOME");
164 fn = malloc(strlen(home) + 20);
165 sprintf(fn, "%s/.nsmbrc", home);
166 error = rc_open(fn, "r", &smb_rc);
169 error = rc_merge(SMB_CFG_FILE, &smb_rc);
170 if (smb_rc == NULL) {
171 printf("Warning: no cfg file(s) found.\n");
185 seteuid(eff_uid); /* restore setuid root briefly */
187 error = sysctlbyname("net.smb.treedump", NULL, &len, NULL, 0);
189 seteuid(real_uid); /* and back to real user */
197 seteuid(eff_uid); /* restore setuid root briefly */
199 error = sysctlbyname("net.smb.treedump", p, &len, NULL, 0);
201 seteuid(real_uid); /* and back to real user */
211 smb_simplecrypt(char *dst, const char *src)
217 dst = malloc(4 + 2 * strlen(src));
229 ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
230 islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
233 sprintf(dst, "%02x", ch);
241 smb_simpledecrypt(char *dst, const char *src)
246 if (strncmp(src, "$$1", 3) != 0)
258 ch = strtoul(hexval, &ep, 16);
264 ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
265 islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
275 safe_execv(char *args[])
282 (void)execv(args[0], args);
283 errx(EX_OSERR, "%s: execv %s failed, %s\n", __progname,
284 args[0], strerror(errno));
287 fprintf(stderr, "%s: fork failed, %s\n", __progname,
291 if (wait4(pid, (int *)&status, 0, NULL) != pid) {
292 fprintf(stderr, "%s: BUG executing %s command\n", __progname,
295 } else if (!WIFEXITED(status)) {
296 fprintf(stderr, "%s: %s command aborted by signal %d\n",
297 __progname, args[0], WTERMSIG(status));
299 } else if (WEXITSTATUS(status)) {
300 fprintf(stderr, "%s: %s command failed, exit status %d: %s\n",
301 __progname, args[0], WEXITSTATUS(status),
302 strerror(WEXITSTATUS(status)));
312 /* drop setuid root privs asap */
321 kextisloaded(char * kextname)
323 mach_port_t kernel_port;
324 kmod_info_t *k, *loaded_modules = 0;
325 int err, loaded_count = 0;
327 /* on error return not loaded - to make loadsmbvfs fail */
329 err = task_for_pid(mach_task_self(), 0, &kernel_port);
331 fprintf(stderr, "%s: %s: %s\n", __progname,
332 "unable to get kernel task port",
333 mach_error_string(err));
336 err = kmod_get_info(kernel_port, (void *)&loaded_modules,
337 &loaded_count); /* never freed */
339 fprintf(stderr, "%s: %s: %s\n", __progname,
340 "kmod_get_info() failed",
341 mach_error_string(err));
344 for (k = loaded_modules; k; k = k->next ? k+1 : 0)
345 if (!strcmp(k->name, kextname))
351 #define KEXTLOAD_COMMAND "/sbin/kextload"
352 #define FS_KEXT_DIR "/System/Library/Extensions/smbfs.kext"
353 #define FULL_KEXTNAME "com.apple.filesystems.smbfs"
359 const char *kextargs[] = {KEXTLOAD_COMMAND, FS_KEXT_DIR, NULL};
363 * temporarily revert to root (required for kextload)
366 if (!kextisloaded(FULL_KEXTNAME)) {
367 error = safe_execv(kextargs);
369 error = !kextisloaded(FULL_KEXTNAME);
371 seteuid(real_uid); /* and back to real user */