#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.31 2004-12-28 20:38:27 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.34 2004-12-29 05:27:27 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
#include "extract.h"
#include "smb.h"
+static u_int32_t stringlen;
extern const u_char *startbuf;
/*
double d;
time_t ret;
- TCHECK2(p[4], 4);
-
/* this gives us seconds since jan 1st 1601 (approx) */
d = (EXTRACT_LE_32BITS(p + 4) * 256.0 + p[3]) * (1.0e-7 * (1 << 24));
ret = (time_t)d;
return(ret);
-trunc:
- return(0);
}
/*
/* XXX - this should use the same code that the DNS dissector does */
if ((c & 0xC0) == 0xC0) {
- u_int16_t l = EXTRACT_16BITS(buf + ofs) & 0x3FFF;
+ u_int16_t l;
+
+ TCHECK2(*p, 2);
+ if ((p + 1) >= maxbuf)
+ return(NULL); /* name goes past the end of the buffer */
+ l = EXTRACT_16BITS(p) & 0x3FFF;
if (l == 0) {
/* We have a pointer that points to itself. */
return(NULL);
if (p >= maxbuf)
return(NULL); /* name goes past the end of the buffer */
TCHECK2(*p, 1);
- return(buf + l);
- } else
- return(buf + ofs);
+ }
+ return(p);
trunc:
return(NULL); /* name goes past the end of the buffer */
}
/* convert a UCS2 string into iso-8859-1 string */
+#define MAX_UNISTR_SIZE 1000
static const char *
-unistr(const u_char *s, int *len)
+unistr(const u_char *s, u_int32_t *len, int use_unicode)
{
- static char buf[1000];
- int l=0;
- static int use_unicode = -1;
-
- if (use_unicode == -1) {
- char *p = getenv("USE_UNICODE");
- if (p && (atoi(p) == 1))
- use_unicode = 1;
- else
- use_unicode = 0;
- }
-
- /* maybe it isn't unicode - a cheap trick */
- if (!use_unicode || (s[0] && s[1])) {
- *len = strlen((const char *)s) + 1;
- return (const char *)s;
+ static char buf[MAX_UNISTR_SIZE+1];
+ size_t l = 0;
+ u_int32_t strsize;
+ const u_char *sp;
+
+ if (use_unicode) {
+ /*
+ * Skip padding that puts the string on an even boundary.
+ */
+ if (((s - startbuf) % 2) != 0) {
+ TCHECK(s[0]);
+ s++;
+ }
}
-
- *len = 0;
-
- if (s[0] == 0 && s[1] != 0) {
- s++;
- *len = 1;
+ if (*len == 0) {
+ /*
+ * Null-terminated string.
+ */
+ strsize = 0;
+ sp = s;
+ if (!use_unicode) {
+ for (;;) {
+ TCHECK(sp[0]);
+ *len += 1;
+ if (sp[0] == 0)
+ break;
+ sp++;
+ }
+ strsize = *len - 1;
+ } else {
+ for (;;) {
+ TCHECK2(sp[0], 2);
+ *len += 2;
+ if (sp[0] == 0 && sp[1] == 0)
+ break;
+ sp += 2;
+ }
+ strsize = *len - 2;
+ }
+ } else {
+ /*
+ * Counted string.
+ */
+ strsize = *len;
}
-
- while (l < (int)(sizeof(buf) - 1) && s[0] && s[1] == 0) {
- buf[l] = s[0];
- s += 2;
- l++;
- *len += 2;
+ if (!use_unicode) {
+ while (strsize != 0) {
+ TCHECK(s[0]);
+ if (l >= MAX_UNISTR_SIZE)
+ break;
+ if (isprint(s[0]))
+ buf[l] = s[0];
+ else {
+ if (s[0] == 0)
+ break;
+ buf[l] = '.';
+ }
+ l++;
+ s++;
+ strsize--;
+ }
+ } else {
+ while (strsize != 0) {
+ TCHECK2(s[0], 2);
+ if (l >= MAX_UNISTR_SIZE)
+ break;
+ if (s[1] == 0 && isprint(s[0])) {
+ /* It's a printable ASCII character */
+ buf[l] = s[0];
+ } else {
+ /* It's a non-ASCII character or a non-printable ASCII character */
+ if (s[0] == 0 && s[1] == 0)
+ break;
+ buf[l] = '.';
+ }
+ l++;
+ s += 2;
+ if (strsize == 1)
+ break;
+ strsize -= 2;
+ }
}
buf[l] = 0;
- *len += 2;
return buf;
+
+trunc:
+ return NULL;
}
static const u_char *
-smb_fdata1(const u_char *buf, const char *fmt, const u_char *maxbuf)
+smb_fdata1(const u_char *buf, const char *fmt, const u_char *maxbuf,
+ int unicodestr)
{
int reverse = 0;
const char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
while (*fmt && buf<maxbuf) {
switch (*fmt) {
case 'a':
+ TCHECK(buf[0]);
write_bits(buf[0], attrib_fmt);
buf++;
fmt++;
break;
case 'A':
+ TCHECK2(buf[0], 2);
write_bits(EXTRACT_LE_16BITS(buf), attrib_fmt);
buf += 2;
fmt++;
strncpy(bitfmt, fmt, l);
bitfmt[l] = '\0';
fmt = p + 1;
+ TCHECK(buf[0]);
write_bits(buf[0], bitfmt);
buf++;
break;
case 'P':
{
int l = atoi(fmt + 1);
+ TCHECK2(buf[0], l);
buf += l;
fmt++;
while (isdigit((unsigned char)*fmt))
fmt++;
break;
}
+ case 'l':
+ {
+ fmt++;
+ switch (*fmt) {
+
+ case 'b':
+ TCHECK(buf[0]);
+ stringlen = buf[0];
+ printf("%u", stringlen);
+ buf += 1;
+ break;
+
+ case 'd':
+ TCHECK2(buf[0], 2);
+ stringlen = reverse ? EXTRACT_16BITS(buf) :
+ EXTRACT_LE_16BITS(buf);
+ printf("%u", stringlen);
+ buf += 2;
+ break;
+
+ case 'D':
+ TCHECK2(buf[0], 4);
+ stringlen = reverse ? EXTRACT_32BITS(buf) :
+ EXTRACT_LE_32BITS(buf);
+ printf("%u", stringlen);
+ buf += 4;
+ break;
+ }
+ fmt++;
+ break;
+ }
case 'S':
+ case 'R': /* like 'S', but always ASCII */
{
/*XXX unistr() */
- printf("%.*s", (int)PTR_DIFF(maxbuf, buf), unistr(buf, &len));
+ const char *s;
+ len = 0;
+ s = unistr(buf, &len, (*fmt == 'R') ? 0 : unicodestr);
+ if (s == NULL)
+ goto trunc;
+ printf("%s", s);
buf += len;
fmt++;
break;
}
case 'Z':
+ case 'Y': /* like 'Z', but always ASCII */
{
- if (*buf != 4 && *buf != 2)
- printf("Error! ASCIIZ buffer of type %u (safety=%lu)\n", *buf,
- (unsigned long)PTR_DIFF(maxbuf, buf));
- printf("%.*s", (int)PTR_DIFF(maxbuf, buf + 1),
- unistr(buf + 1, &len));
+ const char *s;
+ TCHECK(*buf);
+ if (*buf != 4 && *buf != 2) {
+ printf("Error! ASCIIZ buffer of type %u", *buf);
+ return maxbuf; /* give up */
+ }
+ len = 0;
+ s = unistr(buf + 1, &len, (*fmt == 'Y') ? 0 : unicodestr);
+ if (s == NULL)
+ goto trunc;
+ printf("%s", s);
buf += len + 1;
fmt++;
break;
case 's':
{
int l = atoi(fmt + 1);
+ TCHECK2(*buf, l);
printf("%-*.*s", l, l, buf);
buf += l;
fmt++;
fmt++;
break;
}
+ case 'c':
+ {
+ TCHECK2(*buf, stringlen);
+ printf("%-*.*s", stringlen, stringlen, buf);
+ buf += stringlen;
+ fmt++;
+ while (isdigit((unsigned char)*fmt))
+ fmt++;
+ break;
+ }
+ case 'C':
+ {
+ const char *s;
+ s = unistr(buf, &stringlen, unicodestr);
+ if (s == NULL)
+ goto trunc;
+ printf("%s", s);
+ buf += stringlen;
+ fmt++;
+ break;
+ }
case 'h':
{
int l = atoi(fmt + 1);
+ TCHECK2(*buf, l);
while (l--)
printf("%02x", *buf++);
fmt++;
name_type_str(name_type));
break;
case 2:
+ TCHECK(buf[15]);
name_type = buf[15];
printf("%-15.15s NameType=0x%02X (%s)", buf, name_type,
name_type_str(name_type));
struct tm *lt;
const char *tstring;
u_int32_t x;
- x = EXTRACT_LE_32BITS(buf);
switch (atoi(fmt + 1)) {
case 1:
+ TCHECK2(buf[0], 4);
+ x = EXTRACT_LE_32BITS(buf);
if (x == 0 || x == 0xFFFFFFFF)
t = 0;
else
buf += 4;
break;
case 2:
+ TCHECK2(buf[0], 4);
+ x = EXTRACT_LE_32BITS(buf);
if (x == 0 || x == 0xFFFFFFFF)
t = 0;
else
buf += 4;
break;
case 3:
+ TCHECK2(buf[0], 8);
t = interpret_long_date(buf);
buf += 8;
break;
}
const u_char *
-smb_fdata(const u_char *buf, const char *fmt, const u_char *maxbuf)
+smb_fdata(const u_char *buf, const char *fmt, const u_char *maxbuf,
+ int unicodestr)
{
static int depth = 0;
char s[128];
while (buf < maxbuf) {
const u_char *buf2;
depth++;
- buf2 = smb_fdata(buf, fmt, maxbuf);
+ buf2 = smb_fdata(buf, fmt, maxbuf, unicodestr);
depth--;
if (buf2 == NULL)
return(NULL);
strncpy(s, fmt, p - fmt);
s[p - fmt] = '\0';
fmt = p + 1;
- buf = smb_fdata1(buf, s, maxbuf);
+ buf = smb_fdata1(buf, s, maxbuf, unicodestr);
if (buf == NULL)
return(NULL);
break;