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 * from: Id: subr.c,v 1.12 2001/08/22 03:31:37 bp Exp
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: subr.c,v 1.4 2003/04/11 17:31:58 jdolecek Exp $");
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/errno.h>
41 #include <sys/sysctl.h>
42 #include <sys/syscall.h>
52 #include <netsmb/netbios.h>
53 #include <netsmb/smb_lib.h>
54 #include <netsmb/nb_lib.h>
60 #include <mach/mach.h>
61 #include <mach/mach_error.h>
63 uid_t real_uid
, eff_uid
;
66 extern char *__progname
;
68 static int smblib_initialized
;
70 struct rcfile
*smb_rc
;
76 #if __FreeBSD_version > 400000
78 size_t kvlen
= sizeof(kv
);
81 if (smblib_initialized
)
83 #if __FreeBSD_version > 400000
84 error
= sysctlbyname("net.smb.version", &kv
, &kvlen
, NULL
, 0);
86 warnx("%s: can't find kernel module\n", __FUNCTION__
);
89 if (NSMB_VERSION
!= kv
) {
90 warnx("%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__
, kv
, NSMB_VERSION
);
94 if ((error
= nls_setlocale("")) != 0) {
95 warnx("%s: can't initialise locale\n", __func__
);
103 * Print a (descriptive) error message
105 * 0 - no specific error code available;
106 * 1..32767 - system error
109 smb_error(const char *fmt
, int error
,...) {
112 int errtype
= error
& SMB_ERRTYPE_MASK
;
114 fprintf(stderr
, "%s: ", __progname
);
116 vfprintf(stderr
, fmt
, ap
);
121 error
&= ~SMB_ERRTYPE_MASK
;
125 fprintf(stderr
, ": syserr = %s\n", strerror(error
));
127 fprintf(stderr
, "\n");
130 fprintf(stderr
, ": raperr = %d (0x%04x)\n", error
, error
);
133 cp
= nb_strerror(error
);
135 fprintf(stderr
, ": nberr = unknown (0x%04x)\n", error
);
137 fprintf(stderr
, ": nberr = %s\n", cp
);
140 fprintf(stderr
, "\n");
145 smb_printb(char *dest
, int flags
, const struct smb_bitname
*bnp
) {
149 for(; bnp
->bn_bit
; bnp
++) {
150 if (flags
& bnp
->bn_bit
) {
151 strcat(dest
, bnp
->bn_name
);
154 if (!first
&& (flags
& bnp
[1].bn_bit
))
162 * first read ~/.smbrc, next try to merge SMB_CFG_FILE
165 smb_open_rcfile(void)
170 home
= getenv("HOME");
172 fn
= malloc(strlen(home
) + 20);
173 sprintf(fn
, "%s/.nsmbrc", home
);
174 error
= rc_open(fn
, "r", &smb_rc
);
177 error
= rc_merge(SMB_CFG_FILE
, &smb_rc
);
187 /* XXX not supported on NetBSD */
195 seteuid(eff_uid
); /* restore setuid root briefly */
197 error
= sysctlbyname("net.smb.treedump", NULL
, &len
, NULL
, 0);
199 seteuid(real_uid
); /* and back to real user */
207 seteuid(eff_uid
); /* restore setuid root briefly */
209 error
= sysctlbyname("net.smb.treedump", p
, &len
, NULL
, 0);
211 seteuid(real_uid
); /* and back to real user */
218 #endif /* __NetBSD__ */
222 smb_simplecrypt(char *dst
, const char *src
)
228 dst
= malloc(4 + 2 * strlen(src
));
240 ch
= (isupper(ch
) ? ('A' + (ch
- 'A' + 13) % 26) :
241 islower(ch
) ? ('a' + (ch
- 'a' + 13) % 26) : ch
);
244 sprintf(dst
, "%02x", ch
);
252 smb_simpledecrypt(char *dst
, const char *src
)
257 if (strncmp(src
, "$$1", 3) != 0)
269 ch
= strtoul(hexval
, &ep
, 16);
275 ch
= (isupper(ch
) ? ('A' + (ch
- 'A' + 13) % 26) :
276 islower(ch
) ? ('a' + (ch
- 'a' + 13) % 26) : ch
);
286 safe_execv(char *args
[])
293 (void)execv(args
[0], args
);
294 errx(EX_OSERR
, "%s: execv %s failed, %s\n", __progname
,
295 args
[0], strerror(errno
));
298 fprintf(stderr
, "%s: fork failed, %s\n", __progname
,
302 if (wait4(pid
, (int *)&status
, 0, NULL
) != pid
) {
303 fprintf(stderr
, "%s: BUG executing %s command\n", __progname
,
306 } else if (!WIFEXITED(status
)) {
307 fprintf(stderr
, "%s: %s command aborted by signal %d\n",
308 __progname
, args
[0], WTERMSIG(status
));
310 } else if (WEXITSTATUS(status
)) {
311 fprintf(stderr
, "%s: %s command failed, exit status %d: %s\n",
312 __progname
, args
[0], WEXITSTATUS(status
),
313 strerror(WEXITSTATUS(status
)));
323 /* drop setuid root privs asap */
332 kextisloaded(char * kextname
)
334 mach_port_t kernel_port
;
335 kmod_info_t
*k
, *loaded_modules
= 0;
336 int err
, loaded_count
= 0;
338 /* on error return not loaded - to make loadsmbvfs fail */
340 err
= task_for_pid(mach_task_self(), 0, &kernel_port
);
342 fprintf(stderr
, "%s: %s: %s\n", __progname
,
343 "unable to get kernel task port",
344 mach_error_string(err
));
347 err
= kmod_get_info(kernel_port
, (void *)&loaded_modules
,
348 &loaded_count
); /* never freed */
350 fprintf(stderr
, "%s: %s: %s\n", __progname
,
351 "kmod_get_info() failed",
352 mach_error_string(err
));
355 for (k
= loaded_modules
; k
; k
= k
->next
? k
+1 : 0)
356 if (!strcmp(k
->name
, kextname
))
362 #define KEXTLOAD_COMMAND "/sbin/kextload"
363 #define FS_KEXT_DIR "/System/Library/Extensions/smbfs.kext"
364 #define FULL_KEXTNAME "com.apple.filesystems.smbfs"
370 const char *kextargs
[] = {KEXTLOAD_COMMAND
, FS_KEXT_DIR
, NULL
};
374 * temporarily revert to root (required for kextload)
377 if (!kextisloaded(FULL_KEXTNAME
)) {
378 error
= safe_execv(kextargs
);
380 error
= !kextisloaded(FULL_KEXTNAME
);
382 seteuid(real_uid
); /* and back to real user */