16007Sthurlow /*
26007Sthurlow * Copyright (c) 2000, Boris Popov
36007Sthurlow * All rights reserved.
46007Sthurlow *
56007Sthurlow * Redistribution and use in source and binary forms, with or without
66007Sthurlow * modification, are permitted provided that the following conditions
76007Sthurlow * are met:
86007Sthurlow * 1. Redistributions of source code must retain the above copyright
96007Sthurlow * notice, this list of conditions and the following disclaimer.
106007Sthurlow * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow * notice, this list of conditions and the following disclaimer in the
126007Sthurlow * documentation and/or other materials provided with the distribution.
136007Sthurlow * 3. All advertising materials mentioning features or use of this software
146007Sthurlow * must display the following acknowledgement:
156007Sthurlow * This product includes software developed by Boris Popov.
166007Sthurlow * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow * may be used to endorse or promote products derived from this software
186007Sthurlow * without specific prior written permission.
196007Sthurlow *
206007Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow * SUCH DAMAGE.
316007Sthurlow *
326007Sthurlow * $Id: subr.c,v 1.19 2005/02/09 00:23:45 lindak Exp $
336007Sthurlow */
346007Sthurlow
356007Sthurlow #include <sys/types.h>
366007Sthurlow #include <sys/errno.h>
378271SGordon.Ross@Sun.COM #include <sys/time.h>
386007Sthurlow
396007Sthurlow #include <unistd.h>
406007Sthurlow #include <ctype.h>
416007Sthurlow #include <string.h>
426007Sthurlow #include <stdio.h>
436007Sthurlow #include <stdlib.h>
446007Sthurlow #include <stdarg.h>
456007Sthurlow #include <errno.h>
466007Sthurlow #include <sysexits.h>
476007Sthurlow #include <libintl.h>
486007Sthurlow
496007Sthurlow #include <netsmb/netbios.h>
506007Sthurlow #include <netsmb/smb_lib.h>
516007Sthurlow #include <netsmb/nb_lib.h>
52*10023SGordon.Ross@Sun.COM
536007Sthurlow #include <err.h>
546007Sthurlow
55*10023SGordon.Ross@Sun.COM #include "private.h"
566007Sthurlow
576007Sthurlow static int smblib_initialized;
586007Sthurlow
596007Sthurlow int
smb_lib_init(void)606007Sthurlow smb_lib_init(void)
616007Sthurlow {
626007Sthurlow int error;
636007Sthurlow
646007Sthurlow if (smblib_initialized)
656007Sthurlow return (0);
666007Sthurlow if ((error = nls_setlocale("")) != 0) {
676007Sthurlow fprintf(stdout, dgettext(TEXT_DOMAIN,
686007Sthurlow "%s: can't initialise locale\n"), __progname);
696007Sthurlow return (error);
706007Sthurlow }
716007Sthurlow smblib_initialized++;
726007Sthurlow return (0);
736007Sthurlow }
746007Sthurlow
75*10023SGordon.Ross@Sun.COM int
smb_getlocalname(char ** namepp)76*10023SGordon.Ross@Sun.COM smb_getlocalname(char **namepp)
77*10023SGordon.Ross@Sun.COM {
78*10023SGordon.Ross@Sun.COM char buf[SMBIOC_MAX_NAME], *cp;
79*10023SGordon.Ross@Sun.COM
80*10023SGordon.Ross@Sun.COM if (gethostname(buf, sizeof (buf)) != 0)
81*10023SGordon.Ross@Sun.COM return (errno);
82*10023SGordon.Ross@Sun.COM cp = strchr(buf, '.');
83*10023SGordon.Ross@Sun.COM if (cp)
84*10023SGordon.Ross@Sun.COM *cp = '\0';
85*10023SGordon.Ross@Sun.COM cp = strdup(buf);
86*10023SGordon.Ross@Sun.COM if (cp == NULL)
87*10023SGordon.Ross@Sun.COM return (ENOMEM);
88*10023SGordon.Ross@Sun.COM *namepp = cp;
89*10023SGordon.Ross@Sun.COM return (0);
90*10023SGordon.Ross@Sun.COM }
91*10023SGordon.Ross@Sun.COM
926007Sthurlow /*
936007Sthurlow * Private version of strerror(3C) that
946007Sthurlow * knows our special error codes.
956007Sthurlow */
966007Sthurlow char *
smb_strerror(int err)976007Sthurlow smb_strerror(int err)
986007Sthurlow {
996007Sthurlow char *msg;
1006007Sthurlow
1016007Sthurlow switch (err) {
1026007Sthurlow case EBADRPC:
1036007Sthurlow msg = dgettext(TEXT_DOMAIN,
1046007Sthurlow "remote call failed");
1056007Sthurlow break;
1066007Sthurlow case EAUTH:
1076007Sthurlow msg = dgettext(TEXT_DOMAIN,
1086007Sthurlow "authentication failed");
1096007Sthurlow break;
1106007Sthurlow default:
1116007Sthurlow msg = strerror(err);
1126007Sthurlow break;
1136007Sthurlow }
1146007Sthurlow
1156007Sthurlow return (msg);
1166007Sthurlow }
1176007Sthurlow
1186007Sthurlow /*
1196007Sthurlow * Print a (descriptive) error message
1206007Sthurlow * error values:
1216007Sthurlow * 0 - no specific error code available;
1226007Sthurlow * 1..32767 - system error
1236007Sthurlow */
1246007Sthurlow void
smb_error(const char * fmt,int error,...)1256007Sthurlow smb_error(const char *fmt, int error, ...) {
1266007Sthurlow va_list ap;
1276007Sthurlow const char *cp;
1286007Sthurlow int errtype;
1296007Sthurlow
1306007Sthurlow fprintf(stderr, "%s: ", __progname);
1316007Sthurlow va_start(ap, error);
1326007Sthurlow vfprintf(stderr, fmt, ap);
1336007Sthurlow va_end(ap);
1346007Sthurlow if (error == -1) {
1356007Sthurlow error = errno;
1366007Sthurlow errtype = SMB_SYS_ERROR;
1376007Sthurlow } else {
1386007Sthurlow errtype = error & SMB_ERRTYPE_MASK;
1396007Sthurlow error &= ~SMB_ERRTYPE_MASK;
1406007Sthurlow }
1416007Sthurlow switch (errtype) {
1426007Sthurlow case SMB_SYS_ERROR:
1436007Sthurlow if (error)
1446007Sthurlow fprintf(stderr, ": syserr = %s\n", smb_strerror(error));
1456007Sthurlow else
1466007Sthurlow fprintf(stderr, "\n");
1476007Sthurlow break;
1486007Sthurlow case SMB_RAP_ERROR:
1496007Sthurlow fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
1506007Sthurlow break;
1516007Sthurlow case SMB_NB_ERROR:
1526007Sthurlow cp = nb_strerror(error);
1536007Sthurlow if (cp == NULL)
1546007Sthurlow fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
1556007Sthurlow else
1566007Sthurlow fprintf(stderr, ": nberr = %s\n", cp);
1576007Sthurlow break;
1586007Sthurlow default:
1596007Sthurlow fprintf(stderr, "\n");
1606007Sthurlow }
1616007Sthurlow }
1626007Sthurlow
1636007Sthurlow char *
smb_printb(char * dest,int flags,const struct smb_bitname * bnp)1646007Sthurlow smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
1656007Sthurlow int first = 1;
1666007Sthurlow
1676007Sthurlow strcpy(dest, "<");
1686007Sthurlow for (; bnp->bn_bit; bnp++) {
1696007Sthurlow if (flags & bnp->bn_bit) {
1706007Sthurlow strcat(dest, bnp->bn_name);
1716007Sthurlow first = 0;
1726007Sthurlow }
1736007Sthurlow if (!first && (flags & bnp[1].bn_bit))
1746007Sthurlow strcat(dest, "|");
1756007Sthurlow }
1766007Sthurlow strcat(dest, ">");
1776007Sthurlow return (dest);
1786007Sthurlow }
1796007Sthurlow
1806007Sthurlow void
smb_simplecrypt(char * dst,const char * src)1816007Sthurlow smb_simplecrypt(char *dst, const char *src)
1826007Sthurlow {
1836007Sthurlow int ch, pos;
1846007Sthurlow
1856007Sthurlow *dst++ = '$';
1866007Sthurlow *dst++ = '$';
1876007Sthurlow *dst++ = '1';
1886007Sthurlow pos = 27;
1896007Sthurlow while (*src) {
1906007Sthurlow ch = *src++;
1916007Sthurlow if (isascii(ch))
1926007Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
1936007Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
1946007Sthurlow ch ^= pos;
1956007Sthurlow pos += 13;
1966007Sthurlow sprintf(dst, "%02x", ch);
1976007Sthurlow dst += 2;
1986007Sthurlow }
1996007Sthurlow *dst = 0;
2006007Sthurlow }
2016007Sthurlow
2026007Sthurlow int
smb_simpledecrypt(char * dst,const char * src)2036007Sthurlow smb_simpledecrypt(char *dst, const char *src)
2046007Sthurlow {
2056007Sthurlow char *ep, hexval[3];
2066007Sthurlow int len, ch, pos;
2076007Sthurlow
2086007Sthurlow if (strncmp(src, "$$1", 3) != 0)
2096007Sthurlow return (EINVAL);
2106007Sthurlow src += 3;
2116007Sthurlow len = strlen(src);
2126007Sthurlow if (len & 1)
2136007Sthurlow return (EINVAL);
2146007Sthurlow len /= 2;
2156007Sthurlow hexval[2] = 0;
2166007Sthurlow pos = 27;
2176007Sthurlow while (len--) {
2186007Sthurlow hexval[0] = *src++;
2196007Sthurlow hexval[1] = *src++;
2206007Sthurlow ch = strtoul(hexval, &ep, 16);
2216007Sthurlow if (*ep != 0)
2226007Sthurlow return (EINVAL);
2236007Sthurlow ch ^= pos;
2246007Sthurlow pos += 13;
2256007Sthurlow if (isascii(ch))
2266007Sthurlow ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
2276007Sthurlow islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
2286007Sthurlow *dst++ = ch;
2296007Sthurlow }
2306007Sthurlow *dst = 0;
2316007Sthurlow return (0);
2326007Sthurlow }
2336007Sthurlow
234*10023SGordon.Ross@Sun.COM /*
235*10023SGordon.Ross@Sun.COM * Number of seconds between 1970 and 1601 year
236*10023SGordon.Ross@Sun.COM * (134774 * 24 * 60 * 60)
237*10023SGordon.Ross@Sun.COM */
238*10023SGordon.Ross@Sun.COM static const uint64_t DIFF1970TO1601 = 11644473600ULL;
239*10023SGordon.Ross@Sun.COM
240*10023SGordon.Ross@Sun.COM void
smb_time_local2server(struct timeval * tsp,int tzoff,long * seconds)241*10023SGordon.Ross@Sun.COM smb_time_local2server(struct timeval *tsp, int tzoff, long *seconds)
242*10023SGordon.Ross@Sun.COM {
243*10023SGordon.Ross@Sun.COM *seconds = tsp->tv_sec - tzoff * 60;
244*10023SGordon.Ross@Sun.COM }
245*10023SGordon.Ross@Sun.COM
246*10023SGordon.Ross@Sun.COM void
smb_time_server2local(ulong_t seconds,int tzoff,struct timeval * tsp)247*10023SGordon.Ross@Sun.COM smb_time_server2local(ulong_t seconds, int tzoff, struct timeval *tsp)
248*10023SGordon.Ross@Sun.COM {
249*10023SGordon.Ross@Sun.COM tsp->tv_sec = seconds + tzoff * 60;
250*10023SGordon.Ross@Sun.COM tsp->tv_usec = 0;
251*10023SGordon.Ross@Sun.COM }
252*10023SGordon.Ross@Sun.COM
253*10023SGordon.Ross@Sun.COM /*
254*10023SGordon.Ross@Sun.COM * Time from server comes as UTC, so no need to use tz
255*10023SGordon.Ross@Sun.COM */
256*10023SGordon.Ross@Sun.COM /*ARGSUSED*/
257*10023SGordon.Ross@Sun.COM void
smb_time_NT2local(uint64_t nsec,int tzoff,struct timeval * tsp)258*10023SGordon.Ross@Sun.COM smb_time_NT2local(uint64_t nsec, int tzoff, struct timeval *tsp)
259*10023SGordon.Ross@Sun.COM {
260*10023SGordon.Ross@Sun.COM smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp);
261*10023SGordon.Ross@Sun.COM }
262*10023SGordon.Ross@Sun.COM
263*10023SGordon.Ross@Sun.COM /*ARGSUSED*/
264*10023SGordon.Ross@Sun.COM void
smb_time_local2NT(struct timeval * tsp,int tzoff,uint64_t * nsec)265*10023SGordon.Ross@Sun.COM smb_time_local2NT(struct timeval *tsp, int tzoff, uint64_t *nsec)
266*10023SGordon.Ross@Sun.COM {
267*10023SGordon.Ross@Sun.COM long seconds;
268*10023SGordon.Ross@Sun.COM
269*10023SGordon.Ross@Sun.COM smb_time_local2server(tsp, 0, &seconds);
270*10023SGordon.Ross@Sun.COM *nsec = (((uint64_t)(seconds) & ~1) + DIFF1970TO1601) *
271*10023SGordon.Ross@Sun.COM (uint64_t)10000000;
272*10023SGordon.Ross@Sun.COM }
273*10023SGordon.Ross@Sun.COM
274*10023SGordon.Ross@Sun.COM void
smb_hexdump(const void * buf,int len)275*10023SGordon.Ross@Sun.COM smb_hexdump(const void *buf, int len)
276*10023SGordon.Ross@Sun.COM {
277*10023SGordon.Ross@Sun.COM const uchar_t *p = buf;
278*10023SGordon.Ross@Sun.COM int ofs = 0;
279*10023SGordon.Ross@Sun.COM
280*10023SGordon.Ross@Sun.COM while (len--) {
281*10023SGordon.Ross@Sun.COM if (ofs % 16 == 0)
282*10023SGordon.Ross@Sun.COM fprintf(stderr, "%02X: ", ofs);
283*10023SGordon.Ross@Sun.COM fprintf(stderr, "%02x ", *p++);
284*10023SGordon.Ross@Sun.COM ofs++;
285*10023SGordon.Ross@Sun.COM if (ofs % 16 == 0)
286*10023SGordon.Ross@Sun.COM fprintf(stderr, "\n");
287*10023SGordon.Ross@Sun.COM }
288*10023SGordon.Ross@Sun.COM if (ofs % 16 != 0)
289*10023SGordon.Ross@Sun.COM fprintf(stderr, "\n");
290*10023SGordon.Ross@Sun.COM }
291*10023SGordon.Ross@Sun.COM
292*10023SGordon.Ross@Sun.COM void
dprint(const char * fname,const char * fmt,...)293*10023SGordon.Ross@Sun.COM dprint(const char *fname, const char *fmt, ...)
294*10023SGordon.Ross@Sun.COM {
295*10023SGordon.Ross@Sun.COM va_list ap;
296*10023SGordon.Ross@Sun.COM
297*10023SGordon.Ross@Sun.COM va_start(ap, fmt);
298*10023SGordon.Ross@Sun.COM
299*10023SGordon.Ross@Sun.COM if (smb_debug) {
300*10023SGordon.Ross@Sun.COM fprintf(stderr, "%s: ", fname);
301*10023SGordon.Ross@Sun.COM vfprintf(stderr, fmt, ap);
302*10023SGordon.Ross@Sun.COM fprintf(stderr, "\n");
303*10023SGordon.Ross@Sun.COM }
304*10023SGordon.Ross@Sun.COM va_end(ap);
305*10023SGordon.Ross@Sun.COM }
306*10023SGordon.Ross@Sun.COM
3076007Sthurlow #undef __progname
3086007Sthurlow
3096007Sthurlow char *__progname = NULL;
3106007Sthurlow
3116007Sthurlow char *
smb_getprogname()3126007Sthurlow smb_getprogname()
3136007Sthurlow {
3146007Sthurlow char *p;
3156007Sthurlow
3166007Sthurlow if (__progname == NULL) {
3176007Sthurlow __progname = (char *)getexecname();
3186007Sthurlow if ((p = strrchr(__progname, '/')) != 0)
3196007Sthurlow __progname = p + 1;
3206007Sthurlow }
3216007Sthurlow return (__progname);
3226007Sthurlow }
323