]> The Tcpdump Group git mirrors - tcpdump/blobdiff - smbutil.c
Allow tcpdump to work with earlier libpcaps.
[tcpdump] / smbutil.c
index e3a939a72a24c5ff707890ee3a8155799c9be727..1af60106a4a61c258d27ee11763c46f7fb825550 100644 (file)
--- a/smbutil.c
+++ b/smbutil.c
@@ -9,24 +9,29 @@
 #include "config.h"
 #endif
 
+#ifndef lint
+static const char rcsid[] =
+     "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.12 2000-12-04 00:35:45 guy Exp $";
+#endif
+
 #include <sys/param.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include <net/if.h>
 
 #include <netinet/in.h>
-#include <netinet/if_ether.h>
 
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
+#include "interface.h"
 #include "smb.h"
 
-extern uchar *startbuf;
+extern const uchar *startbuf;
 
 /*******************************************************************
   interpret a 32 bit dos packed date/time to some parameters
@@ -49,7 +54,7 @@ static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *ho
 /*******************************************************************
   create a unix date from a dos date
 ********************************************************************/
-time_t make_unix_date(void *date_ptr)
+static time_t make_unix_date(const void *date_ptr)
 {
   uint32 dos_date=0;
   struct tm t;
@@ -70,7 +75,7 @@ time_t make_unix_date(void *date_ptr)
 /*******************************************************************
   create a unix date from a dos date
 ********************************************************************/
-time_t make_unix_date2(void *date_ptr)
+static time_t make_unix_date2(const void *date_ptr)
 {
   uint32 x,x2;
 
@@ -85,7 +90,7 @@ time_t make_unix_date2(void *date_ptr)
 interpret an 8 byte "filetime" structure to a time_t
 It's originally in "100ns units since jan 1st 1601"
 ****************************************************************************/
-time_t interpret_long_date(char *p)
+static time_t interpret_long_date(const char *p)
 {
   double d;
   time_t ret;
@@ -109,12 +114,18 @@ time_t interpret_long_date(char *p)
 
 
 /****************************************************************************
-interpret the weird netbios "name". Return the name type
+interpret the weird netbios "name". Return the name type, or -1 if
+we run past the end of the buffer
 ****************************************************************************/
-static int name_interpret(char *in,char *out)
+static int name_interpret(const uchar *in,const uchar *maxbuf,char *out)
 {
   int ret;
-  int len = (*in++) / 2;
+  int len;
+
+  if (in >= maxbuf)
+    return(-1);        /* name goes past the end of the buffer */
+  TCHECK2(*in, 1);
+  len = (*in++) / 2;
 
   *out=0;
 
@@ -122,6 +133,9 @@ static int name_interpret(char *in,char *out)
 
   while (len--)
     {
+      if (in + 1 >= maxbuf)
+       return(-1);     /* name goes past the end of the buffer */
+      TCHECK2(*in, 2);
       if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
        *out = 0;
        return(0);
@@ -134,50 +148,89 @@ static int name_interpret(char *in,char *out)
   ret = out[-1];
 
   return(ret);
+
+trunc:
+  return(-1);
 }
 
 /****************************************************************************
 find a pointer to a netbios name
 ****************************************************************************/
-static char *name_ptr(char *buf,int ofs)
+static const uchar *name_ptr(const uchar *buf,int ofs,const uchar *maxbuf)
 {
-  unsigned char c = *(unsigned char *)(buf+ofs);
+  const uchar *p;
+  uchar c;
 
+  p = buf+ofs;
+  if (p >= maxbuf)
+    return(NULL);      /* name goes past the end of the buffer */
+  TCHECK2(*p, 1);
+
+  c = *p;
+
+  /* XXX - this should use the same code that the DNS dissector does */
   if ((c & 0xC0) == 0xC0)
     {
       uint16 l = RSVAL(buf, ofs) & 0x3FFF;
+      if (l == 0)
+       {
+         /* We have a pointer that points to itself. */
+         return(NULL);
+       }
+      p = buf + l;
+      if (p >= maxbuf)
+       return(NULL);   /* name goes past the end of the buffer */
+      TCHECK2(*p, 1);
       return(buf + l);
     }
   else
     return(buf+ofs);
+
+trunc:
+  return(NULL);        /* name goes past the end of the buffer */
 }  
 
 /****************************************************************************
 extract a netbios name from a buf
 ****************************************************************************/
-static int name_extract(char *buf,int ofs,char *name)
+static int name_extract(const uchar *buf,int ofs,const uchar *maxbuf,char *name)
 {
-  char *p = name_ptr(buf,ofs);
-  int d = PTR_DIFF(p,buf+ofs);
+  const uchar *p = name_ptr(buf,ofs,maxbuf);
+  if (p == NULL)
+    return(-1);        /* error (probably name going past end of buffer) */
   strcpy(name,"");
-  return(name_interpret(p,name));
+  return(name_interpret(p,maxbuf,name));
 }  
   
 
 /****************************************************************************
 return the total storage length of a mangled name
 ****************************************************************************/
-static int name_len(unsigned char *s)
+static int name_len(const unsigned char *s, const unsigned char *maxbuf)
 {
-  char *s0 = s;
-  unsigned char c = *(unsigned char *)s;
+  const unsigned char *s0 = s;
+  unsigned char c;
+
+  if (s >= maxbuf)
+    return(-1);        /* name goes past the end of the buffer */
+  TCHECK2(*s, 1);
+  c = *s;
   if ((c & 0xC0) == 0xC0)
-    return(2);  
-  while (*s) s += (*s)+1;
+    return(2);
+  while (*s)
+    {
+      if (s >= maxbuf)
+       return(-1);     /* name goes past the end of the buffer */
+      TCHECK2(*s, 1);
+      s += (*s)+1;
+    }
   return(PTR_DIFF(s,s0)+1);
+
+trunc:
+  return(-1);  /* name goes past the end of the buffer */
 }
 
-void print_asc(unsigned char *buf,int len)
+static void print_asc(const unsigned char *buf,int len)
 {
   int i;
   for (i=0;i<len;i++)
@@ -199,7 +252,7 @@ static char *name_type_str(int name_type)
   return(f);
 }
 
-void print_data(unsigned char *buf,int len)
+void print_data(const unsigned char *buf, int len)
 {
   int i=0;
   if (len<=0) return;
@@ -246,7 +299,7 @@ static void write_bits(unsigned int val,char *fmt)
 }
 
 /* convert a unicode string */
-static char *unistr(char *s, int *len)
+static const char *unistr(const char *s, int *len)
 {
        static char buf[1000];
        int l=0;
@@ -283,7 +336,7 @@ static char *unistr(char *s, int *len)
        return buf;
 }
 
-uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
+static const uchar *fdata1(const uchar *buf, const char *fmt, const uchar *maxbuf)
 {
   int reverse=0;
   char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
@@ -389,7 +442,7 @@ uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
       }
     case 'S':
       {        
-             printf("%.*s",PTR_DIFF(maxbuf,buf),unistr(buf, &len));
+             printf("%.*s",(int)PTR_DIFF(maxbuf,buf),unistr(buf, &len));
              buf += len;
              fmt++;
              break;
@@ -398,8 +451,8 @@ uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
       {        
        if (*buf != 4 && *buf != 2) 
          printf("Error! ASCIIZ buffer of type %d (safety=%d)\n",
-                *buf,PTR_DIFF(maxbuf,buf));
-       printf("%.*s",PTR_DIFF(maxbuf,buf+1),unistr(buf+1, &len));
+                *buf,(int)PTR_DIFF(maxbuf,buf));
+       printf("%.*s",(int)PTR_DIFF(maxbuf,buf+1),unistr(buf+1, &len));
        buf += len+1;
        fmt++;
        break;
@@ -424,10 +477,17 @@ uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
        int t = atoi(fmt+1);
        char nbuf[255];
        int name_type;
+       int len;
        switch (t) {
        case 1:
-         name_type = name_extract(startbuf,PTR_DIFF(buf,startbuf),nbuf);
-         buf += name_len(buf);
+         name_type = name_extract(startbuf,PTR_DIFF(buf,startbuf),maxbuf,
+               nbuf);
+         if (name_type < 0)
+           goto trunc;
+         len = name_len(buf,maxbuf);
+         if (len < 0)
+           goto trunc;
+         buf += len;
          printf("%-15.15s NameType=0x%02X (%s)",
                 nbuf,name_type,name_type_str(name_type));
          break;
@@ -480,9 +540,14 @@ uchar *fdata1(uchar *buf,char *fmt,uchar *maxbuf)
     printf("END OF BUFFER\n");
 
   return(buf);
+
+trunc:
+  printf("\n");
+  printf("WARNING: Short packet. Try increasing the snap length\n");
+  return(NULL);
 }
 
-uchar *fdata(uchar *buf,char *fmt,uchar *maxbuf)
+const uchar *fdata(const uchar *buf, const char *fmt, const uchar *maxbuf)
 {
   static int depth=0;
   char s[128];
@@ -493,7 +558,7 @@ uchar *fdata(uchar *buf,char *fmt,uchar *maxbuf)
     case '*':
       fmt++;
       while (buf < maxbuf) {
-       uchar *buf2;
+       const uchar *buf2;
        depth++;
        buf2 = fdata(buf,fmt,maxbuf);
        depth--;
@@ -520,11 +585,13 @@ uchar *fdata(uchar *buf,char *fmt,uchar *maxbuf)
     case '[':
       fmt++;
       if (buf>=maxbuf) return(buf);
-      bzero(s,sizeof(s));
+      memset(s, 0, sizeof(s));
       p = strchr(fmt,']');
       strncpy(s,fmt,p-fmt);
       fmt = p+1;
       buf = fdata1(buf,s,maxbuf);
+      if (buf == NULL)
+       return(NULL);
       break;
 
     default:
@@ -675,19 +742,16 @@ char *smb_errstr(int class,int num)
            for (j=0;err[j].name;j++)
              if (num == err[j].code)
                {
-                 sprintf(ret,"%s - %s (%s)",err_classes[i].class,
+                 snprintf(ret,sizeof(ret),"%s - %s (%s)",err_classes[i].class,
                          err[j].name,err[j].message);
                  return ret;
                }
          }
 
-       sprintf(ret,"%s - %d",err_classes[i].class,num);
+       snprintf(ret,sizeof(ret),"%s - %d",err_classes[i].class,num);
        return ret;
       }
   
-  sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
+  snprintf(ret,sizeof(ret),"ERROR: Unknown error (%d,%d)",class,num);
   return(ret);
 }
-
-
-