FAQ was updated
[obnox/wireshark/wip.git] / packet-radius.c
index 46c1f0220d639397c41ad7436b3dfbcc15ff1968..447c5b611f7da244214924319b76cb2ae58129e9 100644 (file)
@@ -1,10 +1,11 @@
 /* packet-radius.c
+ *
  * Routines for RADIUS packet disassembly
  * Copyright 1999 Johan Feyaerts
  *
  * RFC 2865, RFC 2866, RFC 2867, RFC 2868, RFC 2869
  *
- * $Id: packet-radius.c,v 1.68 2002/08/28 21:00:28 jmayer Exp $
+ * $Id: packet-radius.c,v 1.77 2003/02/13 03:05:14 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 
 #include "packet-q931.h"
 #include "packet-gtp.h"
+#include "prefs.h"
+#include "crypt-md5.h"
 
 static int proto_radius = -1;
 static int hf_radius_length = -1;
 static int hf_radius_code = -1;
 static int hf_radius_id =-1;
+static char *shared_secret = NULL;
+static gpointer authenticator = NULL;
 
 static gint ett_radius = -1;
 static gint ett_radius_avp = -1;
@@ -2359,6 +2364,79 @@ rdconvertbufftostr(gchar *dest, tvbuff_t *tvb, int offset, int length)
         dest[totlen+1]=0;
 }
 
+static void
+rddecryptpass(gchar *dest,tvbuff_t *tvb,int offset,int length)
+{
+    md5_state_t md_ctx;
+    md5_byte_t digest[16];
+    guint32 i;
+    guint32 totlen;
+    const guint8 *pd;
+    guchar c;
+
+    if (!shared_secret || !authenticator ) {
+       rdconvertbufftostr(dest,tvb,offset,length);
+       return;
+    }
+
+    dest[0] = '"';
+    dest[1] = '\0';
+    totlen = 1;
+
+    md5_init(&md_ctx);
+    md5_append(&md_ctx,shared_secret,strlen(shared_secret));
+    md5_append(&md_ctx,authenticator,16);
+    md5_finish(&md_ctx,digest);
+
+    pd = tvb_get_ptr(tvb,offset,length);
+    for( i = 0 ; i < 16 && i < (guint32)length ; i++ ) {
+       c = pd[i] ^ digest[i];
+#ifdef _WIN32
+       /*
+        * XXX - "isprint()" can return "true" for non-ASCII characters, but
+        * those don't work with GTK+ on Windows, as GTK+ on Windows assumes
+        * UTF-8 strings.  Until we fix up Ethereal to properly handle
+        * non-ASCII characters in all output (both GUI displays and text
+        * printouts) on all platforms including Windows, we work around
+        * the problem by escaping all characters that aren't printable ASCII.
+        */
+       if ( c >= 0x20 && c <= 0x7f) {
+#else
+       if ( isprint(c)) {
+#endif
+           dest[totlen] = c;
+           totlen++;
+       } else {
+           sprintf(&(dest[totlen]),"\\%03o",c);
+           totlen += strlen(&(dest[totlen]));
+       }
+    }
+    while(i<(guint32)length) {
+#ifdef _WIN32
+       /*
+        * XXX - "isprint()" can return "true" for non-ASCII characters, but
+        * those don't work with GTK+ on Windows, as GTK+ on Windows assumes
+        * UTF-8 strings.  Until we fix up Ethereal to properly handle
+        * non-ASCII characters in all output (both GUI displays and text
+        * printouts) on all platforms including Windows, we work around
+        * the problem by escaping all characters that aren't printable ASCII.
+        */
+       if ( pd[i] >= 0x20 && pd[i] <= 0x7f) {
+#else
+       if ( isprint(pd[i]) ) {
+#endif
+           dest[totlen] = (gchar)pd[i];
+           totlen++;
+       } else {
+           sprintf(&(dest[totlen]), "\\%03o", pd[i]);
+           totlen=totlen+strlen(&(dest[totlen]));
+       }
+       i++;
+    }
+    dest[totlen]='"';
+    dest[totlen+1] = '\0';
+}
+
 static void
 rdconvertbufftobinstr(gchar *dest, tvbuff_t *tvb, int offset, int length)
 {
@@ -2425,7 +2503,7 @@ static gchar *rdconvertinttostr(gchar *dest, int print_type, guint32 val)
  *
  * At last, forgive me if I've messed up some indentation...
  * */
-static gchar *rd_value_to_str_2(gchar *dest, e_avphdr *avph, tvbuff_t *tvb,
+static gchar *rd_value_to_str_2(gchar *dest, const e_avphdr *avph, tvbuff_t *tvb,
                                int offset, const value_value_string *vvs, proto_tree *tree)
 {
   int print_type;
@@ -2443,16 +2521,15 @@ static gchar *rd_value_to_str_2(gchar *dest, e_avphdr *avph, tvbuff_t *tvb,
   gchar *cont;
   value_string *valstrarr;
   guint32 intval;
+  gint32 timeval;
   const guint8 *pd;
   guint8 tag;
-  char *rtimestamp;
-  extern char *tzname[2];
 
   int vsa_length;
   int vsa_len;
   int vsa_index;
   rd_vsa_table *vsa_rvt;
-  e_avphdr *vsa_avph;
+  const e_avphdr *vsa_avph;
 
 /* prints the values of the attribute value pairs into a text buffer */
   print_type = match_numval(avph->avp_type, vvs);
@@ -2463,7 +2540,11 @@ static gchar *rd_value_to_str_2(gchar *dest, e_avphdr *avph, tvbuff_t *tvb,
   switch(print_type)
   {
         case( RADIUS_STRING ):
-               rdconvertbufftostr(cont,tvb,offset+2,avph->avp_length-2);
+               if ( avph->avp_type == 2 )  { /* User Password */
+                   rddecryptpass(cont,tvb,offset+2,avph->avp_length-2);
+               } else {
+                   rdconvertbufftostr(cont,tvb,offset+2,avph->avp_length-2);
+               }
                 break;
         case( RADIUS_BINSTRING ):
                rdconvertbufftobinstr(cont,tvb,offset+2,avph->avp_length-2);
@@ -2528,7 +2609,7 @@ static gchar *rd_value_to_str_2(gchar *dest, e_avphdr *avph, tvbuff_t *tvb,
                vsa_rvt = get_vsa_table(intval);
                do
                {
-                       vsa_avph = (e_avphdr*)tvb_get_ptr(tvb, offset+vsa_len,
+                       vsa_avph = (const e_avphdr*)tvb_get_ptr(tvb, offset+vsa_len,
                                avph->avp_length-vsa_len);
                        if (vsa_rvt)
                                next_print_type = match_numval(vsa_avph->avp_type,
@@ -2646,10 +2727,8 @@ static gchar *rd_value_to_str_2(gchar *dest, e_avphdr *avph, tvbuff_t *tvb,
                break;
 
         case( RADIUS_TIMESTAMP ):
-               intval=tvb_get_ntohl(tvb,offset+2);
-               rtimestamp=ctime((time_t*)&intval);
-               rtimestamp[strlen(rtimestamp)-1]=0;
-               sprintf(cont,"%d (%s %s)", tvb_get_ntohl(tvb,offset+2), rtimestamp, *tzname);
+               timeval=tvb_get_ntohl(tvb,offset+2);
+               sprintf(cont,"%d (%s)", timeval, abs_time_secs_to_str(timeval));
                break;
         case( RADIUS_INTEGER4_TAGGED ):
                intval = tvb_get_ntohl(tvb,offset+2);
@@ -2920,6 +2999,13 @@ static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        proto_tree_add_uint(radius_tree, hf_radius_length, tvb,
                        2, 2, rhlength);
+       if ( authenticator ) {
+           g_free(authenticator);
+       }
+       authenticator = g_malloc(AUTHENTICATOR_LENGTH);
+       if ( authenticator ) {
+           memcpy(authenticator,tvb_get_ptr(tvb,4,AUTHENTICATOR_LENGTH),AUTHENTICATOR_LENGTH);
+       }
        proto_tree_add_text(radius_tree, tvb, 4,
                        AUTHENTICATOR_LENGTH,
                          "Authenticator");
@@ -2966,10 +3052,17 @@ proto_register_radius(void)
                &ett_radius_vsa,
        };
 
+       module_t *radius_module;
+
        proto_radius = proto_register_protocol("Radius Protocol", "RADIUS",
            "radius");
        proto_register_field_array(proto_radius, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
+       
+       radius_module = prefs_register_protocol(proto_radius,NULL);
+       prefs_register_string_preference(radius_module,"shared_secret","Shared Secret",
+                                       "Shared secret used to decode User Passwords",
+                                       &shared_secret);
 }
 
 void