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