1b0453382SBill Fenner /* 2a90e161bSBill Fenner * Copyright (C) Andrew Tridgell 1995-1999 3a90e161bSBill Fenner * 4a90e161bSBill Fenner * This software may be distributed either under the terms of the 5a90e161bSBill Fenner * BSD-style license that accompanies tcpdump or the GNU GPL version 2 6a90e161bSBill Fenner * or later 7a90e161bSBill Fenner */ 8b0453382SBill Fenner 9b0453382SBill Fenner #ifdef HAVE_CONFIG_H 10b0453382SBill Fenner #include "config.h" 11b0453382SBill Fenner #endif 12b0453382SBill Fenner 13b0453382SBill Fenner #ifndef lint 145b0fe478SBruce M Simpson static const char rcsid[] _U_ = 155b0fe478SBruce M Simpson "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.26.2.2 2003/11/16 08:51:56 guy Exp $"; 16b0453382SBill Fenner #endif 17b0453382SBill Fenner 185b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 19b0453382SBill Fenner 20b0453382SBill Fenner #include <stdio.h> 21b0453382SBill Fenner #include <stdlib.h> 22b0453382SBill Fenner #include <string.h> 23b0453382SBill Fenner 24b0453382SBill Fenner #include "interface.h" 25a90e161bSBill Fenner #include "extract.h" 26b0453382SBill Fenner #include "smb.h" 27b0453382SBill Fenner 28a90e161bSBill Fenner extern const u_char *startbuf; 29b0453382SBill Fenner 30a90e161bSBill Fenner /* 31a90e161bSBill Fenner * interpret a 32 bit dos packed date/time to some parameters 32a90e161bSBill Fenner */ 33a90e161bSBill Fenner static void 34a90e161bSBill Fenner interpret_dos_date(u_int32_t date, struct tm *tp) 35b0453382SBill Fenner { 36a90e161bSBill Fenner u_int32_t p0, p1, p2, p3; 37b0453382SBill Fenner 38a90e161bSBill Fenner p0 = date & 0xFF; 39a90e161bSBill Fenner p1 = ((date & 0xFF00) >> 8) & 0xFF; 40a90e161bSBill Fenner p2 = ((date & 0xFF0000) >> 16) & 0xFF; 41a90e161bSBill Fenner p3 = ((date & 0xFF000000) >> 24) & 0xFF; 42b0453382SBill Fenner 43a90e161bSBill Fenner tp->tm_sec = 2 * (p0 & 0x1F); 44a90e161bSBill Fenner tp->tm_min = ((p0 >> 5) & 0xFF) + ((p1 & 0x7) << 3); 45a90e161bSBill Fenner tp->tm_hour = (p1 >> 3) & 0xFF; 46a90e161bSBill Fenner tp->tm_mday = (p2 & 0x1F); 47a90e161bSBill Fenner tp->tm_mon = ((p2 >> 5) & 0xFF) + ((p3 & 0x1) << 3) - 1; 48a90e161bSBill Fenner tp->tm_year = ((p3 >> 1) & 0xFF) + 80; 49b0453382SBill Fenner } 50b0453382SBill Fenner 51a90e161bSBill Fenner /* 52a90e161bSBill Fenner * common portion: 53a90e161bSBill Fenner * create a unix date from a dos date 54a90e161bSBill Fenner */ 55a90e161bSBill Fenner static time_t 56a90e161bSBill Fenner int_unix_date(u_int32_t dos_date) 57b0453382SBill Fenner { 58b0453382SBill Fenner struct tm t; 59b0453382SBill Fenner 60a90e161bSBill Fenner if (dos_date == 0) 61a90e161bSBill Fenner return(0); 62b0453382SBill Fenner 63a90e161bSBill Fenner interpret_dos_date(dos_date, &t); 64b0453382SBill Fenner t.tm_wday = 1; 65b0453382SBill Fenner t.tm_yday = 1; 66b0453382SBill Fenner t.tm_isdst = 0; 67b0453382SBill Fenner 68b0453382SBill Fenner return (mktime(&t)); 69b0453382SBill Fenner } 70b0453382SBill Fenner 71a90e161bSBill Fenner /* 72a90e161bSBill Fenner * create a unix date from a dos date 73a90e161bSBill Fenner * in network byte order 74a90e161bSBill Fenner */ 75a90e161bSBill Fenner static time_t 76a90e161bSBill Fenner make_unix_date(const u_char *date_ptr) 77b0453382SBill Fenner { 78a90e161bSBill Fenner u_int32_t dos_date = 0; 79b0453382SBill Fenner 80a90e161bSBill Fenner dos_date = EXTRACT_LE_32BITS(date_ptr); 81b0453382SBill Fenner 82a90e161bSBill Fenner return int_unix_date(dos_date); 83b0453382SBill Fenner } 84b0453382SBill Fenner 85a90e161bSBill Fenner /* 86a90e161bSBill Fenner * create a unix date from a dos date 87a90e161bSBill Fenner * in halfword-swapped network byte order! 88a90e161bSBill Fenner */ 89a90e161bSBill Fenner static time_t 90a90e161bSBill Fenner make_unix_date2(const u_char *date_ptr) 91a90e161bSBill Fenner { 92a90e161bSBill Fenner u_int32_t x, x2; 93a90e161bSBill Fenner 94a90e161bSBill Fenner x = EXTRACT_LE_32BITS(date_ptr); 95a90e161bSBill Fenner x2 = ((x & 0xFFFF) << 16) | ((x & 0xFFFF0000) >> 16); 96a90e161bSBill Fenner return int_unix_date(x2); 97a90e161bSBill Fenner } 98a90e161bSBill Fenner 99a90e161bSBill Fenner /* 100a90e161bSBill Fenner * interpret an 8 byte "filetime" structure to a time_t 101a90e161bSBill Fenner * It's originally in "100ns units since jan 1st 1601" 102a90e161bSBill Fenner */ 103a90e161bSBill Fenner static time_t 104a90e161bSBill Fenner interpret_long_date(const u_char *p) 105b0453382SBill Fenner { 106b0453382SBill Fenner double d; 107b0453382SBill Fenner time_t ret; 108b0453382SBill Fenner 109a90e161bSBill Fenner TCHECK2(p[4], 4); 110a90e161bSBill Fenner 111b0453382SBill Fenner /* this gives us seconds since jan 1st 1601 (approx) */ 112a90e161bSBill Fenner d = (EXTRACT_LE_32BITS(p + 4) * 256.0 + p[3]) * (1.0e-7 * (1 << 24)); 113b0453382SBill Fenner 114b0453382SBill Fenner /* now adjust by 369 years to make the secs since 1970 */ 115b0453382SBill Fenner d -= 369.0 * 365.25 * 24 * 60 * 60; 116b0453382SBill Fenner 117b0453382SBill Fenner /* and a fudge factor as we got it wrong by a few days */ 118b0453382SBill Fenner d += (3 * 24 * 60 * 60 + 6 * 60 * 60 + 2); 119b0453382SBill Fenner 120b0453382SBill Fenner if (d < 0) 121b0453382SBill Fenner return(0); 122b0453382SBill Fenner 123b0453382SBill Fenner ret = (time_t)d; 124b0453382SBill Fenner 125b0453382SBill Fenner return(ret); 126a90e161bSBill Fenner trunc: 127a90e161bSBill Fenner return(0); 128b0453382SBill Fenner } 129b0453382SBill Fenner 130a90e161bSBill Fenner /* 131a90e161bSBill Fenner * interpret the weird netbios "name". Return the name type, or -1 if 132a90e161bSBill Fenner * we run past the end of the buffer 133a90e161bSBill Fenner */ 134a90e161bSBill Fenner static int 135a90e161bSBill Fenner name_interpret(const u_char *in, const u_char *maxbuf, char *out) 136b0453382SBill Fenner { 137b0453382SBill Fenner int ret; 138685295f4SBill Fenner int len; 139685295f4SBill Fenner 140685295f4SBill Fenner if (in >= maxbuf) 141685295f4SBill Fenner return(-1); /* name goes past the end of the buffer */ 142685295f4SBill Fenner TCHECK2(*in, 1); 143685295f4SBill Fenner len = (*in++) / 2; 144b0453382SBill Fenner 145b0453382SBill Fenner *out=0; 146b0453382SBill Fenner 147a90e161bSBill Fenner if (len > 30 || len < 1) 148a90e161bSBill Fenner return(0); 149b0453382SBill Fenner 150a90e161bSBill Fenner while (len--) { 151a90e161bSBill Fenner TCHECK2(*in, 2); 152685295f4SBill Fenner if (in + 1 >= maxbuf) 153685295f4SBill Fenner return(-1); /* name goes past the end of the buffer */ 154b0453382SBill Fenner if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') { 155b0453382SBill Fenner *out = 0; 156b0453382SBill Fenner return(0); 157b0453382SBill Fenner } 158b0453382SBill Fenner *out = ((in[0] - 'A') << 4) + (in[1] - 'A'); 159b0453382SBill Fenner in += 2; 160b0453382SBill Fenner out++; 161b0453382SBill Fenner } 162b0453382SBill Fenner *out = 0; 163b0453382SBill Fenner ret = out[-1]; 164b0453382SBill Fenner 165b0453382SBill Fenner return(ret); 166685295f4SBill Fenner 167685295f4SBill Fenner trunc: 168685295f4SBill Fenner return(-1); 169b0453382SBill Fenner } 170b0453382SBill Fenner 171a90e161bSBill Fenner /* 172a90e161bSBill Fenner * find a pointer to a netbios name 173a90e161bSBill Fenner */ 174a90e161bSBill Fenner static const u_char * 175a90e161bSBill Fenner name_ptr(const u_char *buf, int ofs, const u_char *maxbuf) 176b0453382SBill Fenner { 177a90e161bSBill Fenner const u_char *p; 178a90e161bSBill Fenner u_char c; 179b0453382SBill Fenner 180685295f4SBill Fenner p = buf + ofs; 181685295f4SBill Fenner if (p >= maxbuf) 182685295f4SBill Fenner return(NULL); /* name goes past the end of the buffer */ 183685295f4SBill Fenner TCHECK2(*p, 1); 184685295f4SBill Fenner 185685295f4SBill Fenner c = *p; 186685295f4SBill Fenner 187685295f4SBill Fenner /* XXX - this should use the same code that the DNS dissector does */ 188a90e161bSBill Fenner if ((c & 0xC0) == 0xC0) { 189a90e161bSBill Fenner u_int16_t l = EXTRACT_16BITS(buf + ofs) & 0x3FFF; 190a90e161bSBill Fenner if (l == 0) { 191685295f4SBill Fenner /* We have a pointer that points to itself. */ 192685295f4SBill Fenner return(NULL); 193685295f4SBill Fenner } 194685295f4SBill Fenner p = buf + l; 195685295f4SBill Fenner if (p >= maxbuf) 196685295f4SBill Fenner return(NULL); /* name goes past the end of the buffer */ 197685295f4SBill Fenner TCHECK2(*p, 1); 198b0453382SBill Fenner return(buf + l); 199a90e161bSBill Fenner } else 200b0453382SBill Fenner return(buf + ofs); 201685295f4SBill Fenner 202685295f4SBill Fenner trunc: 203685295f4SBill Fenner return(NULL); /* name goes past the end of the buffer */ 204b0453382SBill Fenner } 205b0453382SBill Fenner 206a90e161bSBill Fenner /* 207a90e161bSBill Fenner * extract a netbios name from a buf 208a90e161bSBill Fenner */ 209a90e161bSBill Fenner static int 210a90e161bSBill Fenner name_extract(const u_char *buf, int ofs, const u_char *maxbuf, char *name) 211b0453382SBill Fenner { 212a90e161bSBill Fenner const u_char *p = name_ptr(buf, ofs, maxbuf); 213685295f4SBill Fenner if (p == NULL) 214685295f4SBill Fenner return(-1); /* error (probably name going past end of buffer) */ 215a90e161bSBill Fenner name[0] = '\0'; 216685295f4SBill Fenner return(name_interpret(p, maxbuf, name)); 217b0453382SBill Fenner } 218b0453382SBill Fenner 219b0453382SBill Fenner 220a90e161bSBill Fenner /* 221a90e161bSBill Fenner * return the total storage length of a mangled name 222a90e161bSBill Fenner */ 223a90e161bSBill Fenner static int 224a90e161bSBill Fenner name_len(const unsigned char *s, const unsigned char *maxbuf) 225b0453382SBill Fenner { 226685295f4SBill Fenner const unsigned char *s0 = s; 227685295f4SBill Fenner unsigned char c; 228685295f4SBill Fenner 229685295f4SBill Fenner if (s >= maxbuf) 230685295f4SBill Fenner return(-1); /* name goes past the end of the buffer */ 231685295f4SBill Fenner TCHECK2(*s, 1); 232685295f4SBill Fenner c = *s; 233b0453382SBill Fenner if ((c & 0xC0) == 0xC0) 234b0453382SBill Fenner return(2); 235a90e161bSBill Fenner while (*s) { 236685295f4SBill Fenner if (s >= maxbuf) 237685295f4SBill Fenner return(-1); /* name goes past the end of the buffer */ 238685295f4SBill Fenner TCHECK2(*s, 1); 239685295f4SBill Fenner s += (*s) + 1; 240685295f4SBill Fenner } 241b0453382SBill Fenner return(PTR_DIFF(s, s0) + 1); 242685295f4SBill Fenner 243685295f4SBill Fenner trunc: 244685295f4SBill Fenner return(-1); /* name goes past the end of the buffer */ 245b0453382SBill Fenner } 246b0453382SBill Fenner 247a90e161bSBill Fenner static void 248a90e161bSBill Fenner print_asc(const unsigned char *buf, int len) 249b0453382SBill Fenner { 250b0453382SBill Fenner int i; 251b0453382SBill Fenner for (i = 0; i < len; i++) 252a90e161bSBill Fenner safeputchar(buf[i]); 253b0453382SBill Fenner } 254b0453382SBill Fenner 2555b0fe478SBruce M Simpson static const char * 256a90e161bSBill Fenner name_type_str(int name_type) 257b0453382SBill Fenner { 2585b0fe478SBruce M Simpson const char *f = NULL; 259a90e161bSBill Fenner 260b0453382SBill Fenner switch (name_type) { 261b0453382SBill Fenner case 0: f = "Workstation"; break; 262b0453382SBill Fenner case 0x03: f = "Client?"; break; 263b0453382SBill Fenner case 0x20: f = "Server"; break; 264b0453382SBill Fenner case 0x1d: f = "Master Browser"; break; 265b0453382SBill Fenner case 0x1b: f = "Domain Controller"; break; 266b0453382SBill Fenner case 0x1e: f = "Browser Server"; break; 267b0453382SBill Fenner default: f = "Unknown"; break; 268b0453382SBill Fenner } 269b0453382SBill Fenner return(f); 270b0453382SBill Fenner } 271b0453382SBill Fenner 272a90e161bSBill Fenner void 273a90e161bSBill Fenner print_data(const unsigned char *buf, int len) 274b0453382SBill Fenner { 275b0453382SBill Fenner int i = 0; 276a90e161bSBill Fenner 277a90e161bSBill Fenner if (len <= 0) 278a90e161bSBill Fenner return; 279b0453382SBill Fenner printf("[%03X] ", i); 280a90e161bSBill Fenner for (i = 0; i < len; /*nothing*/) { 281a90e161bSBill Fenner printf("%02X ", buf[i] & 0xff); 282b0453382SBill Fenner i++; 283a90e161bSBill Fenner if (i%8 == 0) 284a90e161bSBill Fenner printf(" "); 285b0453382SBill Fenner if (i % 16 == 0) { 286a90e161bSBill Fenner print_asc(&buf[i - 16], 8); 287a90e161bSBill Fenner printf(" "); 288a90e161bSBill Fenner print_asc(&buf[i - 8], 8); 289a90e161bSBill Fenner printf("\n"); 290a90e161bSBill Fenner if (i < len) 291a90e161bSBill Fenner printf("[%03X] ", i); 292b0453382SBill Fenner } 293b0453382SBill Fenner } 294b0453382SBill Fenner if (i % 16) { 295b0453382SBill Fenner int n; 296b0453382SBill Fenner 297b0453382SBill Fenner n = 16 - (i % 16); 298b0453382SBill Fenner printf(" "); 299a90e161bSBill Fenner if (n>8) 300a90e161bSBill Fenner printf(" "); 301a90e161bSBill Fenner while (n--) 302a90e161bSBill Fenner printf(" "); 303b0453382SBill Fenner 304a90e161bSBill Fenner n = SMBMIN(8, i % 16); 305a90e161bSBill Fenner print_asc(&buf[i - (i % 16)], n); 306a90e161bSBill Fenner printf(" "); 307b0453382SBill Fenner n = (i % 16) - n; 308a90e161bSBill Fenner if (n > 0) 309a90e161bSBill Fenner print_asc(&buf[i - n], n); 310b0453382SBill Fenner printf("\n"); 311b0453382SBill Fenner } 312b0453382SBill Fenner } 313b0453382SBill Fenner 314b0453382SBill Fenner 315a90e161bSBill Fenner static void 3165b0fe478SBruce M Simpson write_bits(unsigned int val, const char *fmt) 317b0453382SBill Fenner { 3185b0fe478SBruce M Simpson const char *p = fmt; 319b0453382SBill Fenner int i = 0; 320b0453382SBill Fenner 321b0453382SBill Fenner while ((p = strchr(fmt, '|'))) { 322a90e161bSBill Fenner size_t l = PTR_DIFF(p, fmt); 323b0453382SBill Fenner if (l && (val & (1 << i))) 324a90e161bSBill Fenner printf("%.*s ", (int)l, fmt); 325b0453382SBill Fenner fmt = p + 1; 326b0453382SBill Fenner i++; 327b0453382SBill Fenner } 328b0453382SBill Fenner } 329b0453382SBill Fenner 330a90e161bSBill Fenner /* convert a UCS2 string into iso-8859-1 string */ 331a90e161bSBill Fenner static const char * 3329afd0c29SBill Fenner unistr(const u_char *s, int *len) 333b0453382SBill Fenner { 334b0453382SBill Fenner static char buf[1000]; 335b0453382SBill Fenner int l=0; 336b0453382SBill Fenner static int use_unicode = -1; 337b0453382SBill Fenner 338b0453382SBill Fenner if (use_unicode == -1) { 339b0453382SBill Fenner char *p = getenv("USE_UNICODE"); 340b0453382SBill Fenner if (p && (atoi(p) == 1)) 341b0453382SBill Fenner use_unicode = 1; 342b0453382SBill Fenner else 343b0453382SBill Fenner use_unicode = 0; 344b0453382SBill Fenner } 345b0453382SBill Fenner 346b0453382SBill Fenner /* maybe it isn't unicode - a cheap trick */ 347b0453382SBill Fenner if (!use_unicode || (s[0] && s[1])) { 3489afd0c29SBill Fenner *len = strlen((const char *)s) + 1; 3499afd0c29SBill Fenner return (const char *)s; 350b0453382SBill Fenner } 351b0453382SBill Fenner 352b0453382SBill Fenner *len = 0; 353b0453382SBill Fenner 354b0453382SBill Fenner if (s[0] == 0 && s[1] != 0) { 355b0453382SBill Fenner s++; 356b0453382SBill Fenner *len = 1; 357b0453382SBill Fenner } 358b0453382SBill Fenner 3595b0fe478SBruce M Simpson while (l < (int)(sizeof(buf) - 1) && s[0] && s[1] == 0) { 360b0453382SBill Fenner buf[l] = s[0]; 361a90e161bSBill Fenner s += 2; 362a90e161bSBill Fenner l++; 363b0453382SBill Fenner *len += 2; 364b0453382SBill Fenner } 365b0453382SBill Fenner buf[l] = 0; 366b0453382SBill Fenner *len += 2; 367b0453382SBill Fenner return buf; 368b0453382SBill Fenner } 369b0453382SBill Fenner 370a90e161bSBill Fenner static const u_char * 371a90e161bSBill Fenner smb_fdata1(const u_char *buf, const char *fmt, const u_char *maxbuf) 372b0453382SBill Fenner { 373b0453382SBill Fenner int reverse = 0; 3745b0fe478SBruce M Simpson const char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|"; 375b0453382SBill Fenner int len; 376b0453382SBill Fenner 377b0453382SBill Fenner while (*fmt && buf<maxbuf) { 378b0453382SBill Fenner switch (*fmt) { 379b0453382SBill Fenner case 'a': 380a90e161bSBill Fenner write_bits(buf[0], attrib_fmt); 381a90e161bSBill Fenner buf++; 382a90e161bSBill Fenner fmt++; 383b0453382SBill Fenner break; 384b0453382SBill Fenner 385b0453382SBill Fenner case 'A': 386a90e161bSBill Fenner write_bits(EXTRACT_LE_16BITS(buf), attrib_fmt); 387a90e161bSBill Fenner buf += 2; 388a90e161bSBill Fenner fmt++; 389b0453382SBill Fenner break; 390b0453382SBill Fenner 391b0453382SBill Fenner case '{': 392b0453382SBill Fenner { 393b0453382SBill Fenner char bitfmt[128]; 3949afd0c29SBill Fenner char *p; 3959afd0c29SBill Fenner int l; 3969afd0c29SBill Fenner 3979afd0c29SBill Fenner p = strchr(++fmt, '}'); 3989afd0c29SBill Fenner l = PTR_DIFF(p, fmt); 3995b0fe478SBruce M Simpson 4005b0fe478SBruce M Simpson if ((unsigned int)l > sizeof(bitfmt) - 1) 4015b0fe478SBruce M Simpson l = sizeof(bitfmt)-1; 4025b0fe478SBruce M Simpson 403b0453382SBill Fenner strncpy(bitfmt, fmt, l); 4045b0fe478SBruce M Simpson bitfmt[l] = '\0'; 405b0453382SBill Fenner fmt = p + 1; 406a90e161bSBill Fenner write_bits(buf[0], bitfmt); 407b0453382SBill Fenner buf++; 408b0453382SBill Fenner break; 409b0453382SBill Fenner } 410b0453382SBill Fenner 411b0453382SBill Fenner case 'P': 412b0453382SBill Fenner { 413b0453382SBill Fenner int l = atoi(fmt + 1); 414b0453382SBill Fenner buf += l; 415b0453382SBill Fenner fmt++; 4169afd0c29SBill Fenner while (isdigit((unsigned char)*fmt)) 417a90e161bSBill Fenner fmt++; 418b0453382SBill Fenner break; 419b0453382SBill Fenner } 420b0453382SBill Fenner case 'r': 421b0453382SBill Fenner reverse = !reverse; 422b0453382SBill Fenner fmt++; 423b0453382SBill Fenner break; 424b0453382SBill Fenner case 'D': 425b0453382SBill Fenner { 426a90e161bSBill Fenner unsigned int x; 427a90e161bSBill Fenner 428a90e161bSBill Fenner TCHECK2(buf[0], 4); 429a90e161bSBill Fenner x = reverse ? EXTRACT_32BITS(buf) : EXTRACT_LE_32BITS(buf); 430b0453382SBill Fenner printf("%d (0x%x)", x, x); 431b0453382SBill Fenner buf += 4; 432b0453382SBill Fenner fmt++; 433b0453382SBill Fenner break; 434b0453382SBill Fenner } 435b0453382SBill Fenner case 'L': 436b0453382SBill Fenner { 437a90e161bSBill Fenner unsigned int x1, x2; 438a90e161bSBill Fenner 439a90e161bSBill Fenner TCHECK2(buf[4], 4); 440a90e161bSBill Fenner x1 = reverse ? EXTRACT_32BITS(buf) : 441a90e161bSBill Fenner EXTRACT_LE_32BITS(buf); 442a90e161bSBill Fenner x2 = reverse ? EXTRACT_32BITS(buf + 4) : 443a90e161bSBill Fenner EXTRACT_LE_32BITS(buf + 4); 444a90e161bSBill Fenner if (x2) 445b0453382SBill Fenner printf("0x%08x:%08x", x2, x1); 446a90e161bSBill Fenner else 447b0453382SBill Fenner printf("%d (0x%08x%08x)", x1, x2, x1); 448b0453382SBill Fenner buf += 8; 449b0453382SBill Fenner fmt++; 450b0453382SBill Fenner break; 451b0453382SBill Fenner } 452b0453382SBill Fenner case 'd': 453b0453382SBill Fenner { 454a90e161bSBill Fenner unsigned int x; 455a90e161bSBill Fenner TCHECK2(buf[0], 2); 456a90e161bSBill Fenner x = reverse ? EXTRACT_16BITS(buf) : 457a90e161bSBill Fenner EXTRACT_LE_16BITS(buf); 458b0453382SBill Fenner printf("%d (0x%x)", x, x); 459b0453382SBill Fenner buf += 2; 460b0453382SBill Fenner fmt++; 461b0453382SBill Fenner break; 462b0453382SBill Fenner } 463b0453382SBill Fenner case 'W': 464b0453382SBill Fenner { 465a90e161bSBill Fenner unsigned int x; 466a90e161bSBill Fenner TCHECK2(buf[0], 4); 467a90e161bSBill Fenner x = reverse ? EXTRACT_32BITS(buf) : 468a90e161bSBill Fenner EXTRACT_LE_32BITS(buf); 469b0453382SBill Fenner printf("0x%X", x); 470b0453382SBill Fenner buf += 4; 471b0453382SBill Fenner fmt++; 472b0453382SBill Fenner break; 473b0453382SBill Fenner } 474b0453382SBill Fenner case 'w': 475b0453382SBill Fenner { 476a90e161bSBill Fenner unsigned int x; 477a90e161bSBill Fenner TCHECK2(buf[0], 2); 478a90e161bSBill Fenner x = reverse ? EXTRACT_16BITS(buf) : 479a90e161bSBill Fenner EXTRACT_LE_16BITS(buf); 480b0453382SBill Fenner printf("0x%X", x); 481b0453382SBill Fenner buf += 2; 482b0453382SBill Fenner fmt++; 483b0453382SBill Fenner break; 484b0453382SBill Fenner } 485b0453382SBill Fenner case 'B': 486b0453382SBill Fenner { 487a90e161bSBill Fenner unsigned int x; 488a90e161bSBill Fenner TCHECK(buf[0]); 489a90e161bSBill Fenner x = buf[0]; 490b0453382SBill Fenner printf("0x%X", x); 491b0453382SBill Fenner buf += 1; 492b0453382SBill Fenner fmt++; 493b0453382SBill Fenner break; 494b0453382SBill Fenner } 495b0453382SBill Fenner case 'b': 496b0453382SBill Fenner { 497a90e161bSBill Fenner unsigned int x; 498a90e161bSBill Fenner TCHECK(buf[0]); 499a90e161bSBill Fenner x = buf[0]; 500a90e161bSBill Fenner printf("%u (0x%x)", x, x); 501b0453382SBill Fenner buf += 1; 502b0453382SBill Fenner fmt++; 503b0453382SBill Fenner break; 504b0453382SBill Fenner } 505b0453382SBill Fenner case 'S': 506b0453382SBill Fenner { 507a90e161bSBill Fenner /*XXX unistr() */ 508b0453382SBill Fenner printf("%.*s", (int)PTR_DIFF(maxbuf, buf), unistr(buf, &len)); 509b0453382SBill Fenner buf += len; 510b0453382SBill Fenner fmt++; 511b0453382SBill Fenner break; 512b0453382SBill Fenner } 513b0453382SBill Fenner case 'Z': 514b0453382SBill Fenner { 515b0453382SBill Fenner if (*buf != 4 && *buf != 2) 516a90e161bSBill Fenner printf("Error! ASCIIZ buffer of type %u (safety=%lu)\n", *buf, 517a90e161bSBill Fenner (unsigned long)PTR_DIFF(maxbuf, buf)); 518a90e161bSBill Fenner printf("%.*s", (int)PTR_DIFF(maxbuf, buf + 1), 519a90e161bSBill Fenner unistr(buf + 1, &len)); 520b0453382SBill Fenner buf += len + 1; 521b0453382SBill Fenner fmt++; 522b0453382SBill Fenner break; 523b0453382SBill Fenner } 524b0453382SBill Fenner case 's': 525b0453382SBill Fenner { 526b0453382SBill Fenner int l = atoi(fmt + 1); 527b0453382SBill Fenner printf("%-*.*s", l, l, buf); 528b0453382SBill Fenner buf += l; 529a90e161bSBill Fenner fmt++; 5309afd0c29SBill Fenner while (isdigit((unsigned char)*fmt)) 531a90e161bSBill Fenner fmt++; 532b0453382SBill Fenner break; 533b0453382SBill Fenner } 534b0453382SBill Fenner case 'h': 535b0453382SBill Fenner { 536b0453382SBill Fenner int l = atoi(fmt + 1); 537a90e161bSBill Fenner while (l--) 538a90e161bSBill Fenner printf("%02x", *buf++); 539a90e161bSBill Fenner fmt++; 5409afd0c29SBill Fenner while (isdigit((unsigned char)*fmt)) 541a90e161bSBill Fenner fmt++; 542b0453382SBill Fenner break; 543b0453382SBill Fenner } 544b0453382SBill Fenner case 'n': 545b0453382SBill Fenner { 546b0453382SBill Fenner int t = atoi(fmt+1); 547b0453382SBill Fenner char nbuf[255]; 548b0453382SBill Fenner int name_type; 549685295f4SBill Fenner int len; 550a90e161bSBill Fenner 551b0453382SBill Fenner switch (t) { 552b0453382SBill Fenner case 1: 553a90e161bSBill Fenner name_type = name_extract(startbuf, PTR_DIFF(buf, startbuf), 554a90e161bSBill Fenner maxbuf, nbuf); 555685295f4SBill Fenner if (name_type < 0) 556685295f4SBill Fenner goto trunc; 557685295f4SBill Fenner len = name_len(buf, maxbuf); 558685295f4SBill Fenner if (len < 0) 559685295f4SBill Fenner goto trunc; 560685295f4SBill Fenner buf += len; 561a90e161bSBill Fenner printf("%-15.15s NameType=0x%02X (%s)", nbuf, name_type, 562a90e161bSBill Fenner name_type_str(name_type)); 563b0453382SBill Fenner break; 564b0453382SBill Fenner case 2: 565b0453382SBill Fenner name_type = buf[15]; 566a90e161bSBill Fenner printf("%-15.15s NameType=0x%02X (%s)", buf, name_type, 567a90e161bSBill Fenner name_type_str(name_type)); 568b0453382SBill Fenner buf += 16; 569b0453382SBill Fenner break; 570b0453382SBill Fenner } 571a90e161bSBill Fenner fmt++; 5729afd0c29SBill Fenner while (isdigit((unsigned char)*fmt)) 573a90e161bSBill Fenner fmt++; 574b0453382SBill Fenner break; 575b0453382SBill Fenner } 576b0453382SBill Fenner case 'T': 577b0453382SBill Fenner { 578b0453382SBill Fenner time_t t; 5795b0fe478SBruce M Simpson struct tm *lt; 5805b0fe478SBruce M Simpson const char *tstring; 5815b0fe478SBruce M Simpson u_int32_t x; 582a90e161bSBill Fenner x = EXTRACT_LE_32BITS(buf); 583a90e161bSBill Fenner 584b0453382SBill Fenner switch (atoi(fmt + 1)) { 585b0453382SBill Fenner case 1: 5865b0fe478SBruce M Simpson if (x == 0 || x == 0xFFFFFFFF) 587b0453382SBill Fenner t = 0; 588b0453382SBill Fenner else 589b0453382SBill Fenner t = make_unix_date(buf); 590b0453382SBill Fenner buf += 4; 591b0453382SBill Fenner break; 592b0453382SBill Fenner case 2: 5935b0fe478SBruce M Simpson if (x == 0 || x == 0xFFFFFFFF) 594b0453382SBill Fenner t = 0; 595b0453382SBill Fenner else 596b0453382SBill Fenner t = make_unix_date2(buf); 597b0453382SBill Fenner buf += 4; 598b0453382SBill Fenner break; 599b0453382SBill Fenner case 3: 600b0453382SBill Fenner t = interpret_long_date(buf); 601b0453382SBill Fenner buf += 8; 602b0453382SBill Fenner break; 603b0453382SBill Fenner } 6045b0fe478SBruce M Simpson if (t != 0) { 6055b0fe478SBruce M Simpson lt = localtime(&t); 6065b0fe478SBruce M Simpson if (lt != NULL) 6075b0fe478SBruce M Simpson tstring = asctime(lt); 6085b0fe478SBruce M Simpson else 6095b0fe478SBruce M Simpson tstring = "(Can't convert time)\n"; 6105b0fe478SBruce M Simpson } else 6115b0fe478SBruce M Simpson tstring = "NULL\n"; 6125b0fe478SBruce M Simpson printf("%s", tstring); 613a90e161bSBill Fenner fmt++; 6149afd0c29SBill Fenner while (isdigit((unsigned char)*fmt)) 615a90e161bSBill Fenner fmt++; 616b0453382SBill Fenner break; 617b0453382SBill Fenner } 618b0453382SBill Fenner default: 619b0453382SBill Fenner putchar(*fmt); 620b0453382SBill Fenner fmt++; 621b0453382SBill Fenner break; 622b0453382SBill Fenner } 623b0453382SBill Fenner } 624b0453382SBill Fenner 625b0453382SBill Fenner if (buf >= maxbuf && *fmt) 626b0453382SBill Fenner printf("END OF BUFFER\n"); 627b0453382SBill Fenner 628b0453382SBill Fenner return(buf); 629685295f4SBill Fenner 630685295f4SBill Fenner trunc: 631685295f4SBill Fenner printf("\n"); 632685295f4SBill Fenner printf("WARNING: Short packet. Try increasing the snap length\n"); 633685295f4SBill Fenner return(NULL); 634b0453382SBill Fenner } 635b0453382SBill Fenner 636a90e161bSBill Fenner const u_char * 637a90e161bSBill Fenner smb_fdata(const u_char *buf, const char *fmt, const u_char *maxbuf) 638b0453382SBill Fenner { 639b0453382SBill Fenner static int depth = 0; 640b0453382SBill Fenner char s[128]; 641b0453382SBill Fenner char *p; 642b0453382SBill Fenner 643b0453382SBill Fenner while (*fmt) { 644b0453382SBill Fenner switch (*fmt) { 645b0453382SBill Fenner case '*': 646b0453382SBill Fenner fmt++; 647b0453382SBill Fenner while (buf < maxbuf) { 648a90e161bSBill Fenner const u_char *buf2; 649b0453382SBill Fenner depth++; 650a90e161bSBill Fenner buf2 = smb_fdata(buf, fmt, maxbuf); 651b0453382SBill Fenner depth--; 652a90e161bSBill Fenner if (buf2 == NULL) 653a90e161bSBill Fenner return(NULL); 654a90e161bSBill Fenner if (buf2 == buf) 655a90e161bSBill Fenner return(buf); 656b0453382SBill Fenner buf = buf2; 657b0453382SBill Fenner } 658a90e161bSBill Fenner return(buf); 659b0453382SBill Fenner 660b0453382SBill Fenner case '|': 661b0453382SBill Fenner fmt++; 662a90e161bSBill Fenner if (buf >= maxbuf) 663a90e161bSBill Fenner return(buf); 664b0453382SBill Fenner break; 665b0453382SBill Fenner 666b0453382SBill Fenner case '%': 667b0453382SBill Fenner fmt++; 668b0453382SBill Fenner buf = maxbuf; 669b0453382SBill Fenner break; 670b0453382SBill Fenner 671b0453382SBill Fenner case '#': 672b0453382SBill Fenner fmt++; 673b0453382SBill Fenner return(buf); 674b0453382SBill Fenner break; 675b0453382SBill Fenner 676b0453382SBill Fenner case '[': 677b0453382SBill Fenner fmt++; 678a90e161bSBill Fenner if (buf >= maxbuf) 679a90e161bSBill Fenner return(buf); 680685295f4SBill Fenner memset(s, 0, sizeof(s)); 681b0453382SBill Fenner p = strchr(fmt, ']'); 6825b0fe478SBruce M Simpson if ((size_t)(p - fmt + 1) > sizeof(s)) { 683a90e161bSBill Fenner /* overrun */ 684a90e161bSBill Fenner return(buf); 685a90e161bSBill Fenner } 686b0453382SBill Fenner strncpy(s, fmt, p - fmt); 687a90e161bSBill Fenner s[p - fmt] = '\0'; 688b0453382SBill Fenner fmt = p + 1; 689a90e161bSBill Fenner buf = smb_fdata1(buf, s, maxbuf); 690685295f4SBill Fenner if (buf == NULL) 691685295f4SBill Fenner return(NULL); 692b0453382SBill Fenner break; 693b0453382SBill Fenner 694b0453382SBill Fenner default: 695a90e161bSBill Fenner putchar(*fmt); 696a90e161bSBill Fenner fmt++; 697b0453382SBill Fenner fflush(stdout); 698b0453382SBill Fenner break; 699b0453382SBill Fenner } 700b0453382SBill Fenner } 701b0453382SBill Fenner if (!depth && buf < maxbuf) { 702a90e161bSBill Fenner size_t len = PTR_DIFF(maxbuf, buf); 703a90e161bSBill Fenner printf("Data: (%lu bytes)\n", (unsigned long)len); 704b0453382SBill Fenner print_data(buf, len); 705b0453382SBill Fenner return(buf + len); 706b0453382SBill Fenner } 707b0453382SBill Fenner return(buf); 708b0453382SBill Fenner } 709b0453382SBill Fenner 710a90e161bSBill Fenner typedef struct { 711a90e161bSBill Fenner const char *name; 712b0453382SBill Fenner int code; 713a90e161bSBill Fenner const char *message; 714b0453382SBill Fenner } err_code_struct; 715b0453382SBill Fenner 716b0453382SBill Fenner /* Dos Error Messages */ 717b0453382SBill Fenner static err_code_struct dos_msgs[] = { 718b0453382SBill Fenner { "ERRbadfunc", 1, "Invalid function." }, 719b0453382SBill Fenner { "ERRbadfile", 2, "File not found." }, 720b0453382SBill Fenner { "ERRbadpath", 3, "Directory invalid." }, 721b0453382SBill Fenner { "ERRnofids", 4, "No file descriptors available" }, 722b0453382SBill Fenner { "ERRnoaccess", 5, "Access denied." }, 723b0453382SBill Fenner { "ERRbadfid", 6, "Invalid file handle." }, 724b0453382SBill Fenner { "ERRbadmcb", 7, "Memory control blocks destroyed." }, 725b0453382SBill Fenner { "ERRnomem", 8, "Insufficient server memory to perform the requested function." }, 726b0453382SBill Fenner { "ERRbadmem", 9, "Invalid memory block address." }, 727b0453382SBill Fenner { "ERRbadenv", 10, "Invalid environment." }, 728b0453382SBill Fenner { "ERRbadformat", 11, "Invalid format." }, 729b0453382SBill Fenner { "ERRbadaccess", 12, "Invalid open mode." }, 730b0453382SBill Fenner { "ERRbaddata", 13, "Invalid data." }, 731b0453382SBill Fenner { "ERR", 14, "reserved." }, 732b0453382SBill Fenner { "ERRbaddrive", 15, "Invalid drive specified." }, 733b0453382SBill Fenner { "ERRremcd", 16, "A Delete Directory request attempted to remove the server's current directory." }, 734b0453382SBill Fenner { "ERRdiffdevice", 17, "Not same device." }, 735b0453382SBill Fenner { "ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria." }, 736b0453382SBill Fenner { "ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing FIDs on the file." }, 737b0453382SBill Fenner { "ERRlock", 33, "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process." }, 738b0453382SBill Fenner { "ERRfilexists", 80, "The file named in a Create Directory, Make New File or Link request already exists." }, 739b0453382SBill Fenner { "ERRbadpipe", 230, "Pipe invalid." }, 740b0453382SBill Fenner { "ERRpipebusy", 231, "All instances of the requested pipe are busy." }, 741b0453382SBill Fenner { "ERRpipeclosing", 232, "Pipe close in progress." }, 742b0453382SBill Fenner { "ERRnotconnected", 233, "No process on other end of pipe." }, 743b0453382SBill Fenner { "ERRmoredata", 234, "There is more data to be returned." }, 744a90e161bSBill Fenner { NULL, -1, NULL } 745a90e161bSBill Fenner }; 746b0453382SBill Fenner 747b0453382SBill Fenner /* Server Error Messages */ 748b0453382SBill Fenner err_code_struct server_msgs[] = { 749b0453382SBill Fenner { "ERRerror", 1, "Non-specific error code." }, 750b0453382SBill Fenner { "ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid." }, 751b0453382SBill Fenner { "ERRbadtype", 3, "reserved." }, 752b0453382SBill Fenner { "ERRaccess", 4, "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID." }, 753b0453382SBill Fenner { "ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid." }, 754b0453382SBill Fenner { "ERRinvnetname", 6, "Invalid network name in tree connect." }, 755b0453382SBill Fenner { "ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection." }, 756b0453382SBill Fenner { "ERRqfull", 49, "Print queue full (files) -- returned by open print file." }, 757b0453382SBill Fenner { "ERRqtoobig", 50, "Print queue full -- no space." }, 758b0453382SBill Fenner { "ERRqeof", 51, "EOF on print queue dump." }, 759b0453382SBill Fenner { "ERRinvpfid", 52, "Invalid print file FID." }, 760b0453382SBill Fenner { "ERRsmbcmd", 64, "The server did not recognize the command received." }, 761b0453382SBill Fenner { "ERRsrverror", 65, "The server encountered an internal error, e.g., system file unavailable." }, 762b0453382SBill Fenner { "ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid combination of values." }, 763b0453382SBill Fenner { "ERRreserved", 68, "reserved." }, 764b0453382SBill Fenner { "ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute." }, 765b0453382SBill Fenner { "ERRreserved", 70, "reserved." }, 766b0453382SBill Fenner { "ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid." }, 767b0453382SBill Fenner { "ERRpaused", 81, "Server is paused." }, 768b0453382SBill Fenner { "ERRmsgoff", 82, "Not receiving messages." }, 769b0453382SBill Fenner { "ERRnoroom", 83, "No room to buffer message." }, 770b0453382SBill Fenner { "ERRrmuns", 87, "Too many remote user names." }, 771b0453382SBill Fenner { "ERRtimeout", 88, "Operation timed out." }, 772b0453382SBill Fenner { "ERRnoresource", 89, "No resources currently available for request." }, 773b0453382SBill Fenner { "ERRtoomanyuids", 90, "Too many UIDs active on this session." }, 774b0453382SBill Fenner { "ERRbaduid", 91, "The UID is not known as a valid ID on this session." }, 775b0453382SBill Fenner { "ERRusempx", 250, "Temp unable to support Raw, use MPX mode." }, 776b0453382SBill Fenner { "ERRusestd", 251, "Temp unable to support Raw, use standard read/write." }, 777b0453382SBill Fenner { "ERRcontmpx", 252, "Continue in MPX mode." }, 778b0453382SBill Fenner { "ERRreserved", 253, "reserved." }, 779b0453382SBill Fenner { "ERRreserved", 254, "reserved." }, 780b0453382SBill Fenner { "ERRnosupport", 0xFFFF, "Function not supported." }, 781a90e161bSBill Fenner { NULL, -1, NULL } 782a90e161bSBill Fenner }; 783b0453382SBill Fenner 784b0453382SBill Fenner /* Hard Error Messages */ 785b0453382SBill Fenner err_code_struct hard_msgs[] = { 786b0453382SBill Fenner { "ERRnowrite", 19, "Attempt to write on write-protected diskette." }, 787b0453382SBill Fenner { "ERRbadunit", 20, "Unknown unit." }, 788b0453382SBill Fenner { "ERRnotready", 21, "Drive not ready." }, 789b0453382SBill Fenner { "ERRbadcmd", 22, "Unknown command." }, 790b0453382SBill Fenner { "ERRdata", 23, "Data error (CRC)." }, 791b0453382SBill Fenner { "ERRbadreq", 24, "Bad request structure length." }, 792b0453382SBill Fenner { "ERRseek", 25 , "Seek error." }, 793b0453382SBill Fenner { "ERRbadmedia", 26, "Unknown media type." }, 794b0453382SBill Fenner { "ERRbadsector", 27, "Sector not found." }, 795b0453382SBill Fenner { "ERRnopaper", 28, "Printer out of paper." }, 796b0453382SBill Fenner { "ERRwrite", 29, "Write fault." }, 797b0453382SBill Fenner { "ERRread", 30, "Read fault." }, 798b0453382SBill Fenner { "ERRgeneral", 31, "General failure." }, 799b0453382SBill Fenner { "ERRbadshare", 32, "A open conflicts with an existing open." }, 800b0453382SBill Fenner { "ERRlock", 33, "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process." }, 801b0453382SBill Fenner { "ERRwrongdisk", 34, "The wrong disk was found in a drive." }, 802b0453382SBill Fenner { "ERRFCBUnavail", 35, "No FCBs are available to process request." }, 803b0453382SBill Fenner { "ERRsharebufexc", 36, "A sharing buffer has been exceeded." }, 804a90e161bSBill Fenner { NULL, -1, NULL } 805a90e161bSBill Fenner }; 806b0453382SBill Fenner 807a90e161bSBill Fenner static struct { 808b0453382SBill Fenner int code; 8095b0fe478SBruce M Simpson const char *class; 810b0453382SBill Fenner err_code_struct *err_msgs; 811b0453382SBill Fenner } err_classes[] = { 812b0453382SBill Fenner { 0, "SUCCESS", NULL }, 813b0453382SBill Fenner { 0x01, "ERRDOS", dos_msgs }, 814b0453382SBill Fenner { 0x02, "ERRSRV", server_msgs }, 815b0453382SBill Fenner { 0x03, "ERRHRD", hard_msgs }, 816b0453382SBill Fenner { 0x04, "ERRXOS", NULL }, 817b0453382SBill Fenner { 0xE1, "ERRRMX1", NULL }, 818b0453382SBill Fenner { 0xE2, "ERRRMX2", NULL }, 819b0453382SBill Fenner { 0xE3, "ERRRMX3", NULL }, 820b0453382SBill Fenner { 0xFF, "ERRCMD", NULL }, 821a90e161bSBill Fenner { -1, NULL, NULL } 822a90e161bSBill Fenner }; 823b0453382SBill Fenner 824a90e161bSBill Fenner /* 825a90e161bSBill Fenner * return a SMB error string from a SMB buffer 826a90e161bSBill Fenner */ 827a90e161bSBill Fenner char * 828a90e161bSBill Fenner smb_errstr(int class, int num) 829b0453382SBill Fenner { 830b0453382SBill Fenner static char ret[128]; 831b0453382SBill Fenner int i, j; 832b0453382SBill Fenner 833b0453382SBill Fenner ret[0] = 0; 834b0453382SBill Fenner 835b0453382SBill Fenner for (i = 0; err_classes[i].class; i++) 836a90e161bSBill Fenner if (err_classes[i].code == class) { 837a90e161bSBill Fenner if (err_classes[i].err_msgs) { 838b0453382SBill Fenner err_code_struct *err = err_classes[i].err_msgs; 839b0453382SBill Fenner for (j = 0; err[j].name; j++) 840a90e161bSBill Fenner if (num == err[j].code) { 841a90e161bSBill Fenner snprintf(ret, sizeof(ret), "%s - %s (%s)", 842a90e161bSBill Fenner err_classes[i].class, err[j].name, err[j].message); 843b0453382SBill Fenner return ret; 844b0453382SBill Fenner } 845b0453382SBill Fenner } 846b0453382SBill Fenner 847685295f4SBill Fenner snprintf(ret, sizeof(ret), "%s - %d", err_classes[i].class, num); 848b0453382SBill Fenner return ret; 849b0453382SBill Fenner } 850b0453382SBill Fenner 851685295f4SBill Fenner snprintf(ret, sizeof(ret), "ERROR: Unknown error (%d,%d)", class, num); 852b0453382SBill Fenner return(ret); 853b0453382SBill Fenner } 854