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