xref: /illumos-gate/usr/src/lib/libsmbfs/smb/subr.c (revision 613a2f6b)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2000, Boris Popov
34bff34e3Sthurlow  * All rights reserved.
44bff34e3Sthurlow  *
54bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
64bff34e3Sthurlow  * modification, are permitted provided that the following conditions
74bff34e3Sthurlow  * are met:
84bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
94bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
104bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
114bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
124bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
134bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
144bff34e3Sthurlow  *    must display the following acknowledgement:
154bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
164bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
174bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
184bff34e3Sthurlow  *    without specific prior written permission.
194bff34e3Sthurlow  *
204bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
214bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
244bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304bff34e3Sthurlow  * SUCH DAMAGE.
314bff34e3Sthurlow  *
324bff34e3Sthurlow  * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
334bff34e3Sthurlow  */
344bff34e3Sthurlow 
354bff34e3Sthurlow #include <sys/types.h>
364bff34e3Sthurlow #include <sys/errno.h>
379c9af259SGordon Ross #include <sys/time.h>
384bff34e3Sthurlow 
394bff34e3Sthurlow #include <unistd.h>
404bff34e3Sthurlow #include <ctype.h>
414bff34e3Sthurlow #include <string.h>
424bff34e3Sthurlow #include <stdio.h>
434bff34e3Sthurlow #include <stdlib.h>
444bff34e3Sthurlow #include <stdarg.h>
454bff34e3Sthurlow #include <errno.h>
464bff34e3Sthurlow #include <sysexits.h>
474bff34e3Sthurlow #include <libintl.h>
484bff34e3Sthurlow 
494bff34e3Sthurlow #include <netsmb/netbios.h>
504bff34e3Sthurlow #include <netsmb/smb_lib.h>
514bff34e3Sthurlow #include <netsmb/nb_lib.h>
52*613a2f6bSGordon Ross 
534bff34e3Sthurlow #include <err.h>
544bff34e3Sthurlow 
55*613a2f6bSGordon Ross #include "private.h"
564bff34e3Sthurlow 
574bff34e3Sthurlow static int smblib_initialized;
584bff34e3Sthurlow 
594bff34e3Sthurlow int
smb_lib_init(void)604bff34e3Sthurlow smb_lib_init(void)
614bff34e3Sthurlow {
624bff34e3Sthurlow 	int error;
634bff34e3Sthurlow 
644bff34e3Sthurlow 	if (smblib_initialized)
654bff34e3Sthurlow 		return (0);
664bff34e3Sthurlow 	if ((error = nls_setlocale("")) != 0) {
674bff34e3Sthurlow 		fprintf(stdout, dgettext(TEXT_DOMAIN,
684bff34e3Sthurlow 		    "%s: can't initialise locale\n"), __progname);
694bff34e3Sthurlow 		return (error);
704bff34e3Sthurlow 	}
714bff34e3Sthurlow 	smblib_initialized++;
724bff34e3Sthurlow 	return (0);
734bff34e3Sthurlow }
744bff34e3Sthurlow 
75*613a2f6bSGordon Ross int
smb_getlocalname(char ** namepp)76*613a2f6bSGordon Ross smb_getlocalname(char **namepp)
77*613a2f6bSGordon Ross {
78*613a2f6bSGordon Ross 	char buf[SMBIOC_MAX_NAME], *cp;
79*613a2f6bSGordon Ross 
80*613a2f6bSGordon Ross 	if (gethostname(buf, sizeof (buf)) != 0)
81*613a2f6bSGordon Ross 		return (errno);
82*613a2f6bSGordon Ross 	cp = strchr(buf, '.');
83*613a2f6bSGordon Ross 	if (cp)
84*613a2f6bSGordon Ross 		*cp = '\0';
85*613a2f6bSGordon Ross 	cp = strdup(buf);
86*613a2f6bSGordon Ross 	if (cp == NULL)
87*613a2f6bSGordon Ross 		return (ENOMEM);
88*613a2f6bSGordon Ross 	*namepp = cp;
89*613a2f6bSGordon Ross 	return (0);
90*613a2f6bSGordon Ross }
91*613a2f6bSGordon Ross 
924bff34e3Sthurlow /*
934bff34e3Sthurlow  * Private version of strerror(3C) that
944bff34e3Sthurlow  * knows our special error codes.
954bff34e3Sthurlow  */
964bff34e3Sthurlow char *
smb_strerror(int err)974bff34e3Sthurlow smb_strerror(int err)
984bff34e3Sthurlow {
994bff34e3Sthurlow 	char *msg;
1004bff34e3Sthurlow 
1014bff34e3Sthurlow 	switch (err) {
1024bff34e3Sthurlow 	case EBADRPC:
1034bff34e3Sthurlow 		msg = dgettext(TEXT_DOMAIN,
1044bff34e3Sthurlow 		    "remote call failed");
1054bff34e3Sthurlow 		break;
1064bff34e3Sthurlow 	case EAUTH:
1074bff34e3Sthurlow 		msg = dgettext(TEXT_DOMAIN,
1084bff34e3Sthurlow 		    "authentication failed");
1094bff34e3Sthurlow 		break;
1104bff34e3Sthurlow 	default:
1114bff34e3Sthurlow 		msg = strerror(err);
1124bff34e3Sthurlow 		break;
1134bff34e3Sthurlow 	}
1144bff34e3Sthurlow 
1154bff34e3Sthurlow 	return (msg);
1164bff34e3Sthurlow }
1174bff34e3Sthurlow 
1184bff34e3Sthurlow /*
1194bff34e3Sthurlow  * Print a (descriptive) error message
1204bff34e3Sthurlow  * error values:
1214bff34e3Sthurlow  *         0 - no specific error code available;
1224bff34e3Sthurlow  *  1..32767 - system error
1234bff34e3Sthurlow  */
1244bff34e3Sthurlow void
smb_error(const char * fmt,int error,...)1254bff34e3Sthurlow smb_error(const char *fmt, int error, ...) {
1264bff34e3Sthurlow 	va_list ap;
1274bff34e3Sthurlow 	const char *cp;
1284bff34e3Sthurlow 	int errtype;
1294bff34e3Sthurlow 
1304bff34e3Sthurlow 	fprintf(stderr, "%s: ", __progname);
1314bff34e3Sthurlow 	va_start(ap, error);
1324bff34e3Sthurlow 	vfprintf(stderr, fmt, ap);
1334bff34e3Sthurlow 	va_end(ap);
1344bff34e3Sthurlow 	if (error == -1) {
1354bff34e3Sthurlow 		error = errno;
1364bff34e3Sthurlow 		errtype = SMB_SYS_ERROR;
1374bff34e3Sthurlow 	} else {
1384bff34e3Sthurlow 		errtype = error & SMB_ERRTYPE_MASK;
1394bff34e3Sthurlow 		error &= ~SMB_ERRTYPE_MASK;
1404bff34e3Sthurlow 	}
1414bff34e3Sthurlow 	switch (errtype) {
1424bff34e3Sthurlow 	    case SMB_SYS_ERROR:
1434bff34e3Sthurlow 		if (error)
1444bff34e3Sthurlow 			fprintf(stderr, ": syserr = %s\n", smb_strerror(error));
1454bff34e3Sthurlow 		else
1464bff34e3Sthurlow 			fprintf(stderr, "\n");
1474bff34e3Sthurlow 		break;
1484bff34e3Sthurlow 	    case SMB_RAP_ERROR:
1494bff34e3Sthurlow 		fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
1504bff34e3Sthurlow 		break;
1514bff34e3Sthurlow 	    case SMB_NB_ERROR:
1524bff34e3Sthurlow 		cp = nb_strerror(error);
1534bff34e3Sthurlow 		if (cp == NULL)
1544bff34e3Sthurlow 			fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
1554bff34e3Sthurlow 		else
1564bff34e3Sthurlow 			fprintf(stderr, ": nberr = %s\n", cp);
1574bff34e3Sthurlow 		break;
1584bff34e3Sthurlow 	    default:
1594bff34e3Sthurlow 		fprintf(stderr, "\n");
1604bff34e3Sthurlow 	}
1614bff34e3Sthurlow }
1624bff34e3Sthurlow 
1634bff34e3Sthurlow char *
smb_printb(char * dest,int flags,const struct smb_bitname * bnp)1644bff34e3Sthurlow smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
1654bff34e3Sthurlow 	int first = 1;
1664bff34e3Sthurlow 
1674bff34e3Sthurlow 	strcpy(dest, "<");
1684bff34e3Sthurlow 	for (; bnp->bn_bit; bnp++) {
1694bff34e3Sthurlow 		if (flags & bnp->bn_bit) {
1704bff34e3Sthurlow 			strcat(dest, bnp->bn_name);
1714bff34e3Sthurlow 			first = 0;
1724bff34e3Sthurlow 		}
1734bff34e3Sthurlow 		if (!first && (flags & bnp[1].bn_bit))
1744bff34e3Sthurlow 			strcat(dest, "|");
1754bff34e3Sthurlow 	}
1764bff34e3Sthurlow 	strcat(dest, ">");
1774bff34e3Sthurlow 	return (dest);
1784bff34e3Sthurlow }
1794bff34e3Sthurlow 
1804bff34e3Sthurlow void
smb_simplecrypt(char * dst,const char * src)1814bff34e3Sthurlow smb_simplecrypt(char *dst, const char *src)
1824bff34e3Sthurlow {
1834bff34e3Sthurlow 	int ch, pos;
1844bff34e3Sthurlow 
1854bff34e3Sthurlow 	*dst++ = '$';
1864bff34e3Sthurlow 	*dst++ = '$';
1874bff34e3Sthurlow 	*dst++ = '1';
1884bff34e3Sthurlow 	pos = 27;
1894bff34e3Sthurlow 	while (*src) {
1904bff34e3Sthurlow 		ch = *src++;
1914bff34e3Sthurlow 		if (isascii(ch))
1924bff34e3Sthurlow 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
1934bff34e3Sthurlow 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
1944bff34e3Sthurlow 		ch ^= pos;
1954bff34e3Sthurlow 		pos += 13;
1964bff34e3Sthurlow 		sprintf(dst, "%02x", ch);
1974bff34e3Sthurlow 		dst += 2;
1984bff34e3Sthurlow 	}
1994bff34e3Sthurlow 	*dst = 0;
2004bff34e3Sthurlow }
2014bff34e3Sthurlow 
2024bff34e3Sthurlow int
smb_simpledecrypt(char * dst,const char * src)2034bff34e3Sthurlow smb_simpledecrypt(char *dst, const char *src)
2044bff34e3Sthurlow {
2054bff34e3Sthurlow 	char *ep, hexval[3];
2064bff34e3Sthurlow 	int len, ch, pos;
2074bff34e3Sthurlow 
2084bff34e3Sthurlow 	if (strncmp(src, "$$1", 3) != 0)
2094bff34e3Sthurlow 		return (EINVAL);
2104bff34e3Sthurlow 	src += 3;
2114bff34e3Sthurlow 	len = strlen(src);
2124bff34e3Sthurlow 	if (len & 1)
2134bff34e3Sthurlow 		return (EINVAL);
2144bff34e3Sthurlow 	len /= 2;
2154bff34e3Sthurlow 	hexval[2] = 0;
2164bff34e3Sthurlow 	pos = 27;
2174bff34e3Sthurlow 	while (len--) {
2184bff34e3Sthurlow 		hexval[0] = *src++;
2194bff34e3Sthurlow 		hexval[1] = *src++;
2204bff34e3Sthurlow 		ch = strtoul(hexval, &ep, 16);
2214bff34e3Sthurlow 		if (*ep != 0)
2224bff34e3Sthurlow 			return (EINVAL);
2234bff34e3Sthurlow 		ch ^= pos;
2244bff34e3Sthurlow 		pos += 13;
2254bff34e3Sthurlow 		if (isascii(ch))
2264bff34e3Sthurlow 			ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
2274bff34e3Sthurlow 			    islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
2284bff34e3Sthurlow 		*dst++ = ch;
2294bff34e3Sthurlow 	}
2304bff34e3Sthurlow 	*dst = 0;
2314bff34e3Sthurlow 	return (0);
2324bff34e3Sthurlow }
2334bff34e3Sthurlow 
234*613a2f6bSGordon Ross /*
235*613a2f6bSGordon Ross  * Number of seconds between 1970 and 1601 year
236*613a2f6bSGordon Ross  * (134774 * 24 * 60 * 60)
237*613a2f6bSGordon Ross  */
238*613a2f6bSGordon Ross static const uint64_t DIFF1970TO1601 = 11644473600ULL;
239*613a2f6bSGordon Ross 
240*613a2f6bSGordon Ross void
smb_time_local2server(struct timeval * tsp,int tzoff,long * seconds)241*613a2f6bSGordon Ross smb_time_local2server(struct timeval *tsp, int tzoff, long *seconds)
242*613a2f6bSGordon Ross {
243*613a2f6bSGordon Ross 	*seconds = tsp->tv_sec - tzoff * 60;
244*613a2f6bSGordon Ross }
245*613a2f6bSGordon Ross 
246*613a2f6bSGordon Ross void
smb_time_server2local(ulong_t seconds,int tzoff,struct timeval * tsp)247*613a2f6bSGordon Ross smb_time_server2local(ulong_t seconds, int tzoff, struct timeval *tsp)
248*613a2f6bSGordon Ross {
249*613a2f6bSGordon Ross 	tsp->tv_sec = seconds + tzoff * 60;
250*613a2f6bSGordon Ross 	tsp->tv_usec = 0;
251*613a2f6bSGordon Ross }
252*613a2f6bSGordon Ross 
253*613a2f6bSGordon Ross /*
254*613a2f6bSGordon Ross  * Time from server comes as UTC, so no need to use tz
255*613a2f6bSGordon Ross  */
256*613a2f6bSGordon Ross /*ARGSUSED*/
257*613a2f6bSGordon Ross void
smb_time_NT2local(uint64_t nsec,int tzoff,struct timeval * tsp)258*613a2f6bSGordon Ross smb_time_NT2local(uint64_t nsec, int tzoff, struct timeval *tsp)
259*613a2f6bSGordon Ross {
260*613a2f6bSGordon Ross 	smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
261*613a2f6bSGordon Ross }
262*613a2f6bSGordon Ross 
263*613a2f6bSGordon Ross /*ARGSUSED*/
264*613a2f6bSGordon Ross void
smb_time_local2NT(struct timeval * tsp,int tzoff,uint64_t * nsec)265*613a2f6bSGordon Ross smb_time_local2NT(struct timeval *tsp, int tzoff, uint64_t *nsec)
266*613a2f6bSGordon Ross {
267*613a2f6bSGordon Ross 	long seconds;
268*613a2f6bSGordon Ross 
269*613a2f6bSGordon Ross 	smb_time_local2server(tsp, 0, &seconds);
270*613a2f6bSGordon Ross 	*nsec = (((uint64_t)(seconds) & ~1) + DIFF1970TO1601) *
271*613a2f6bSGordon Ross 	    (uint64_t)10000000;
272*613a2f6bSGordon Ross }
273*613a2f6bSGordon Ross 
274*613a2f6bSGordon Ross void
smb_hexdump(const void * buf,int len)275*613a2f6bSGordon Ross smb_hexdump(const void *buf, int len)
276*613a2f6bSGordon Ross {
277*613a2f6bSGordon Ross 	const uchar_t *p = buf;
278*613a2f6bSGordon Ross 	int ofs = 0;
279*613a2f6bSGordon Ross 
280*613a2f6bSGordon Ross 	while (len--) {
281*613a2f6bSGordon Ross 		if (ofs % 16 == 0)
282*613a2f6bSGordon Ross 			fprintf(stderr, "%02X: ", ofs);
283*613a2f6bSGordon Ross 		fprintf(stderr, "%02x ", *p++);
284*613a2f6bSGordon Ross 		ofs++;
285*613a2f6bSGordon Ross 		if (ofs % 16 == 0)
286*613a2f6bSGordon Ross 			fprintf(stderr, "\n");
287*613a2f6bSGordon Ross 	}
288*613a2f6bSGordon Ross 	if (ofs % 16 != 0)
289*613a2f6bSGordon Ross 		fprintf(stderr, "\n");
290*613a2f6bSGordon Ross }
291*613a2f6bSGordon Ross 
292*613a2f6bSGordon Ross void
dprint(const char * fname,const char * fmt,...)293*613a2f6bSGordon Ross dprint(const char *fname, const char *fmt, ...)
294*613a2f6bSGordon Ross {
295*613a2f6bSGordon Ross 	va_list ap;
296*613a2f6bSGordon Ross 
297*613a2f6bSGordon Ross 	va_start(ap, fmt);
298*613a2f6bSGordon Ross 
299*613a2f6bSGordon Ross 	if (smb_debug) {
300*613a2f6bSGordon Ross 		fprintf(stderr, "%s: ", fname);
301*613a2f6bSGordon Ross 		vfprintf(stderr, fmt, ap);
302*613a2f6bSGordon Ross 		fprintf(stderr, "\n");
303*613a2f6bSGordon Ross 	}
304*613a2f6bSGordon Ross 	va_end(ap);
305*613a2f6bSGordon Ross }
306*613a2f6bSGordon Ross 
3074bff34e3Sthurlow #undef __progname
3084bff34e3Sthurlow 
3094bff34e3Sthurlow char *__progname = NULL;
3104bff34e3Sthurlow 
3114bff34e3Sthurlow char *
smb_getprogname()3124bff34e3Sthurlow smb_getprogname()
3134bff34e3Sthurlow {
3144bff34e3Sthurlow 	char *p;
3154bff34e3Sthurlow 
3164bff34e3Sthurlow 	if (__progname == NULL) {
3174bff34e3Sthurlow 		__progname = (char *)getexecname();
3184bff34e3Sthurlow 		if ((p = strrchr(__progname, '/')) != 0)
3194bff34e3Sthurlow 			__progname = p + 1;
3204bff34e3Sthurlow 	}
3214bff34e3Sthurlow 	return (__progname);
3224bff34e3Sthurlow }
323