Home | History | Annotate | Download | only in smb
      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
     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
     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 *
     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
    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 *
    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
    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
    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
    241 smb_time_local2server(struct timeval *tsp, int tzoff, long *seconds)
    242 {
    243 	*seconds = tsp->tv_sec - tzoff * 60;
    244 }
    245 
    246 void
    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
    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
    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
    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
    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 *
    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