subr.c revision 87866
182498Sroberto/*
282498Sroberto * Copyright (c) 2000, Boris Popov
382498Sroberto * All rights reserved.
482498Sroberto *
582498Sroberto * Redistribution and use in source and binary forms, with or without
682498Sroberto * modification, are permitted provided that the following conditions
7285612Sdelphij * are met:
8285612Sdelphij * 1. Redistributions of source code must retain the above copyright
9285612Sdelphij *    notice, this list of conditions and the following disclaimer.
10285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
11285612Sdelphij *    notice, this list of conditions and the following disclaimer in the
12285612Sdelphij *    documentation and/or other materials provided with the distribution.
13285612Sdelphij * 3. All advertising materials mentioning features or use of this software
14285612Sdelphij *    must display the following acknowledgement:
15285612Sdelphij *    This product includes software developed by Boris Popov.
16285612Sdelphij * 4. Neither the name of the author nor the names of any co-contributors
17285612Sdelphij *    may be used to endorse or promote products derived from this software
18285612Sdelphij *    without specific prior written permission.
19285612Sdelphij *
20285612Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21285612Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22285612Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23285612Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24285612Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25285612Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26285612Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27285612Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28285612Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2982498Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3082498Sroberto * SUCH DAMAGE.
3182498Sroberto *
3282498Sroberto * $Id: subr.c,v 1.11 2001/04/16 04:33:01 bp Exp $
3382498Sroberto */
3482498Sroberto
3582498Sroberto#include <sys/param.h>
3682498Sroberto#include <sys/types.h>
3782498Sroberto#include <sys/errno.h>
3882498Sroberto#include <sys/sysctl.h>
3982498Sroberto#include <sys/syscall.h>
4082498Sroberto#include <unistd.h>
4182498Sroberto#include <ctype.h>
4282498Sroberto#include <string.h>
4382498Sroberto#include <stdio.h>
4482498Sroberto#include <stdlib.h>
4582498Sroberto#include <stdarg.h>
4682498Sroberto#include <err.h>
4782498Sroberto
4882498Sroberto#include <netsmb/netbios.h>
4982498Sroberto#include <netsmb/smb_lib.h>
5082498Sroberto#include <netsmb/nb_lib.h>
5182498Sroberto#include <cflib.h>
5282498Sroberto
5382498Srobertoextern char *__progname;
5482498Sroberto
5582498Srobertostatic int smblib_initialized;
5682498Sroberto
5782498Srobertostruct rcfile *smb_rc;
58285612Sdelphij
59285612Sdelphijint
60285612Sdelphijsmb_lib_init(void)
61285612Sdelphij{
62285612Sdelphij	int error;
63285612Sdelphij	int kv;
64285612Sdelphij	size_t kvlen = sizeof(kv);
65285612Sdelphij
66285612Sdelphij	if (smblib_initialized)
67285612Sdelphij		return 0;
6882498Sroberto#if __FreeBSD_version > 400000
69285612Sdelphij	error = sysctlbyname("net.smb.version", &kv, &kvlen, NULL, 0);
7082498Sroberto	if (error) {
7182498Sroberto		warnx("%s: can't find kernel module\n", __FUNCTION__);
7282498Sroberto		return error;
7382498Sroberto	}
7482498Sroberto	if (NSMB_VERSION != kv) {
7582498Sroberto		warnx("%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NSMB_VERSION);
76285612Sdelphij		return EINVAL;
77285612Sdelphij	}
78285612Sdelphij#endif
79285612Sdelphij	if ((error = nls_setlocale("")) != 0) {
80285612Sdelphij		warnx("%s: can't initialise locale\n", __FUNCTION__);
81285612Sdelphij		return error;
82285612Sdelphij	}
83285612Sdelphij	smblib_initialized++;
84285612Sdelphij	return 0;
85285612Sdelphij}
86285612Sdelphij
87285612Sdelphij/*
88285612Sdelphij * Print a (descriptive) error message
89285612Sdelphij * error values:
90285612Sdelphij *  	   0 - no specific error code available;
91285612Sdelphij *  1..32767 - system error
92285612Sdelphij */
9382498Srobertovoid
94285612Sdelphijsmb_error(const char *fmt, int error,...) {
95285612Sdelphij	va_list ap;
96285612Sdelphij	const char *cp;
97285612Sdelphij	int errtype = error & SMB_ERRTYPE_MASK;
98285612Sdelphij
99285612Sdelphij	fprintf(stderr, "%s: ", __progname);
100285612Sdelphij	va_start(ap, error);
101285612Sdelphij	vfprintf(stderr, fmt, ap);
102285612Sdelphij	va_end(ap);
10382498Sroberto	if (error == -1)
104		error = errno;
105	else
106		error &= ~SMB_ERRTYPE_MASK;
107	switch (errtype) {
108	    case SMB_SYS_ERROR:
109		if (error)
110			fprintf(stderr, ": syserr = %s\n", strerror(error));
111		else
112			fprintf(stderr, "\n");
113		break;
114	    case SMB_RAP_ERROR:
115		fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
116		break;
117	    case SMB_NB_ERROR:
118		cp = nb_strerror(error);
119		if (cp == NULL)
120			fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
121		else
122			fprintf(stderr, ": nberr = %s\n", cp);
123		break;
124	    default:
125		fprintf(stderr, "\n");
126	}
127}
128
129char *
130smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
131	int first = 1;
132
133	strcpy(dest, "<");
134	for(; bnp->bn_bit; bnp++) {
135		if (flags & bnp->bn_bit) {
136			strcat(dest, bnp->bn_name);
137			first = 0;
138		}
139		if (!first && (flags & bnp[1].bn_bit))
140			strcat(dest, "|");
141	}
142	strcat(dest, ">");
143	return dest;
144}
145
146/*
147 * first read ~/.smbrc, next try to merge SMB_CFG_FILE
148 */
149int
150smb_open_rcfile(void)
151{
152	char *home, *fn;
153	int error;
154
155	home = getenv("HOME");
156	if (home) {
157		fn = malloc(strlen(home) + 20);
158		sprintf(fn, "%s/.nsmbrc", home);
159		error = rc_open(fn, "r", &smb_rc);
160		free(fn);
161	}
162	error = rc_merge(SMB_CFG_FILE, &smb_rc);
163	if (smb_rc == NULL) {
164		printf("Warning: no cfg file(s) found.\n");
165		return ENOENT;
166	}
167	return 0;
168}
169
170void *
171smb_dumptree(void)
172{
173	size_t len;
174	void *p;
175	int error;
176
177	error = sysctlbyname("net.smb.treedump", NULL, &len, NULL, 0);
178	if (error)
179		return NULL;
180	p = malloc(len);
181	if (p == NULL)
182		return NULL;
183	error = sysctlbyname("net.smb.treedump", p, &len, NULL, 0);
184	if (error) {
185		free(p);
186		return NULL;
187	}
188	return p;
189}
190
191void
192smb_simplecrypt(char *dst, const char *src)
193{
194	int ch, pos;
195
196	*dst++ = '$';
197	*dst++ = '$';
198	*dst++ = '1';
199	pos = 27;
200	while (*src) {
201		ch = *src++;
202		if (isascii(ch))
203		    ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
204			  islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
205		ch ^= pos;
206		pos += 13;
207		sprintf(dst, "%02x", ch);
208		dst += 2;
209	}
210	*dst = 0;
211}
212
213int
214smb_simpledecrypt(char *dst, const char *src)
215{
216	char *ep, hexval[3];
217	int len, ch, pos;
218
219	if (strncmp(src, "$$1", 3) != 0)
220		return EINVAL;
221	src += 3;
222	len = strlen(src);
223	if (len & 1)
224		return EINVAL;
225	len /= 2;
226	hexval[2] = 0;
227	pos = 27;
228	while (len--) {
229		hexval[0] = *src++;
230		hexval[1] = *src++;
231		ch = strtoul(hexval, &ep, 16);
232		if (*ep != 0)
233			return EINVAL;
234		ch ^= pos;
235		pos += 13;
236		if (isascii(ch))
237		    ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
238			  islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
239		*dst++ = ch;
240	}
241	*dst = 0;
242	return 0;
243}
244