xref: /illumos-gate/usr/src/lib/libsmbfs/smb/subr.c (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
1 /*
2  * Copyright (c) 2000, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
19  *
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
30  * SUCH DAMAGE.
31  *
32  * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
33  */
34 
35 #include <sys/types.h>
36 #include <sys/errno.h>
37 #include <sys/time.h>
38 
39 #include <unistd.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <stdarg.h>
45 #include <errno.h>
46 #include <sysexits.h>
47 #include <libintl.h>
48 
49 #include <netsmb/netbios.h>
50 #include <netsmb/smb_lib.h>
51 #include <netsmb/nb_lib.h>
52 
53 #include <err.h>
54 
55 #include "private.h"
56 
57 static int smblib_initialized;
58 
59 int
smb_lib_init(void)60 smb_lib_init(void)
61 {
62 	int error;
63 
64 	if (smblib_initialized)
65 		return (0);
66 	if ((error = nls_setlocale("")) != 0) {
67 		fprintf(stdout, dgettext(TEXT_DOMAIN,
68 		    "%s: can't initialise locale\n"), __progname);
69 		return (error);
70 	}
71 	smblib_initialized++;
72 	return (0);
73 }
74 
75 int
smb_getlocalname(char ** namepp)76 smb_getlocalname(char **namepp)
77 {
78 	char buf[SMBIOC_MAX_NAME], *cp;
79 
80 	if (gethostname(buf, sizeof (buf)) != 0)
81 		return (errno);
82 	cp = strchr(buf, '.');
83 	if (cp)
84 		*cp = '\0';
85 	cp = strdup(buf);
86 	if (cp == NULL)
87 		return (ENOMEM);
88 	*namepp = cp;
89 	return (0);
90 }
91 
92 /*
93  * Private version of strerror(3C) that
94  * knows our special error codes.
95  */
96 char *
smb_strerror(int err)97 smb_strerror(int err)
98 {
99 	char *msg;
100 
101 	switch (err) {
102 	case EBADRPC:
103 		msg = dgettext(TEXT_DOMAIN,
104 		    "remote call failed");
105 		break;
106 	case EAUTH:
107 		msg = dgettext(TEXT_DOMAIN,
108 		    "authentication failed");
109 		break;
110 	default:
111 		msg = strerror(err);
112 		break;
113 	}
114 
115 	return (msg);
116 }
117 
118 /*
119  * Print a (descriptive) error message
120  * error values:
121  *         0 - no specific error code available;
122  *  1..32767 - system error
123  */
124 void
smb_error(const char * fmt,int error,...)125 smb_error(const char *fmt, int error, ...) {
126 	va_list ap;
127 	const char *cp;
128 	int errtype;
129 
130 	fprintf(stderr, "%s: ", __progname);
131 	va_start(ap, error);
132 	vfprintf(stderr, fmt, ap);
133 	va_end(ap);
134 	if (error == -1) {
135 		error = errno;
136 		errtype = SMB_SYS_ERROR;
137 	} else {
138 		errtype = error & SMB_ERRTYPE_MASK;
139 		error &= ~SMB_ERRTYPE_MASK;
140 	}
141 	switch (errtype) {
142 	    case SMB_SYS_ERROR:
143 		if (error)
144 			fprintf(stderr, ": syserr = %s\n", smb_strerror(error));
145 		else
146 			fprintf(stderr, "\n");
147 		break;
148 	    case SMB_RAP_ERROR:
149 		fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
150 		break;
151 	    case SMB_NB_ERROR:
152 		cp = nb_strerror(error);
153 		if (cp == NULL)
154 			fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
155 		else
156 			fprintf(stderr, ": nberr = %s\n", cp);
157 		break;
158 	    default:
159 		fprintf(stderr, "\n");
160 	}
161 }
162 
163 char *
smb_printb(char * dest,int flags,const struct smb_bitname * bnp)164 smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
165 	int first = 1;
166 
167 	strcpy(dest, "<");
168 	for (; bnp->bn_bit; bnp++) {
169 		if (flags & bnp->bn_bit) {
170 			strcat(dest, bnp->bn_name);
171 			first = 0;
172 		}
173 		if (!first && (flags & bnp[1].bn_bit))
174 			strcat(dest, "|");
175 	}
176 	strcat(dest, ">");
177 	return (dest);
178 }
179 
180 void
smb_simplecrypt(char * dst,const char * src)181 smb_simplecrypt(char *dst, const char *src)
182 {
183 	int ch, pos;
184 
185 	*dst++ = '$';
186 	*dst++ = '$';
187 	*dst++ = '1';
188 	pos = 27;
189 	while (*src) {
190 		ch = *src++;
191 		if (isascii(ch))
192 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
193 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
194 		ch ^= pos;
195 		pos += 13;
196 		sprintf(dst, "%02x", ch);
197 		dst += 2;
198 	}
199 	*dst = 0;
200 }
201 
202 int
smb_simpledecrypt(char * dst,const char * src)203 smb_simpledecrypt(char *dst, const char *src)
204 {
205 	char *ep, hexval[3];
206 	int len, ch, pos;
207 
208 	if (strncmp(src, "$$1", 3) != 0)
209 		return (EINVAL);
210 	src += 3;
211 	len = strlen(src);
212 	if (len & 1)
213 		return (EINVAL);
214 	len /= 2;
215 	hexval[2] = 0;
216 	pos = 27;
217 	while (len--) {
218 		hexval[0] = *src++;
219 		hexval[1] = *src++;
220 		ch = strtoul(hexval, &ep, 16);
221 		if (*ep != 0)
222 			return (EINVAL);
223 		ch ^= pos;
224 		pos += 13;
225 		if (isascii(ch))
226 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
227 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
228 		*dst++ = ch;
229 	}
230 	*dst = 0;
231 	return (0);
232 }
233 
234 /*
235  * Number of seconds between 1970 and 1601 year
236  * (134774 * 24 * 60 * 60)
237  */
238 static const uint64_t DIFF1970TO1601 = 11644473600ULL;
239 
240 void
smb_time_local2server(struct timeval * tsp,int tzoff,long * seconds)241 smb_time_local2server(struct timeval *tsp, int tzoff, long *seconds)
242 {
243 	*seconds = tsp->tv_sec - tzoff * 60;
244 }
245 
246 void
smb_time_server2local(ulong_t seconds,int tzoff,struct timeval * tsp)247 smb_time_server2local(ulong_t seconds, int tzoff, struct timeval *tsp)
248 {
249 	tsp->tv_sec = seconds + tzoff * 60;
250 	tsp->tv_usec = 0;
251 }
252 
253 /*
254  * Time from server comes as UTC, so no need to use tz
255  */
256 /*ARGSUSED*/
257 void
smb_time_NT2local(uint64_t nsec,int tzoff,struct timeval * tsp)258 smb_time_NT2local(uint64_t nsec, int tzoff, struct timeval *tsp)
259 {
260 	smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
261 }
262 
263 /*ARGSUSED*/
264 void
smb_time_local2NT(struct timeval * tsp,int tzoff,uint64_t * nsec)265 smb_time_local2NT(struct timeval *tsp, int tzoff, uint64_t *nsec)
266 {
267 	long seconds;
268 
269 	smb_time_local2server(tsp, 0, &seconds);
270 	*nsec = (((uint64_t)(seconds) & ~1) + DIFF1970TO1601) *
271 	    (uint64_t)10000000;
272 }
273 
274 void
smb_hexdump(const void * buf,int len)275 smb_hexdump(const void *buf, int len)
276 {
277 	const uchar_t *p = buf;
278 	int ofs = 0;
279 
280 	while (len--) {
281 		if (ofs % 16 == 0)
282 			fprintf(stderr, "%02X: ", ofs);
283 		fprintf(stderr, "%02x ", *p++);
284 		ofs++;
285 		if (ofs % 16 == 0)
286 			fprintf(stderr, "\n");
287 	}
288 	if (ofs % 16 != 0)
289 		fprintf(stderr, "\n");
290 }
291 
292 void
dprint(const char * fname,const char * fmt,...)293 dprint(const char *fname, const char *fmt, ...)
294 {
295 	va_list ap;
296 
297 	va_start(ap, fmt);
298 
299 	if (smb_debug) {
300 		fprintf(stderr, "%s: ", fname);
301 		vfprintf(stderr, fmt, ap);
302 		fprintf(stderr, "\n");
303 	}
304 	va_end(ap);
305 }
306 
307 #undef __progname
308 
309 char *__progname = NULL;
310 
311 char *
smb_getprogname()312 smb_getprogname()
313 {
314 	char *p;
315 
316 	if (__progname == NULL) {
317 		__progname = (char *)getexecname();
318 		if ((p = strrchr(__progname, '/')) != 0)
319 			__progname = p + 1;
320 	}
321 	return (__progname);
322 }
323