radiusniff.c
上传用户:quanlove
上传日期:2007-01-08
资源大小:17k
文件大小:24k
源码类别:

网络截获/分析

开发平台:

Unix_Linux

  1. /*
  2.  
  3.  RADIUS traffic sNIFFer
  4.  Copyleft 2000 by FreeLSD <freelsd@freelsd.net>
  5.  
  6.  Some portion of code from snmpsniffer.c (c) by Nuno Leitao
  7.  NOTICE:
  8.  You may copy, distribute or modify this code, as long as you
  9.  keep this copyleft notice intact.
  10.  PS. dont try to run... ;)
  11.  
  12.  Greets to all ADM!@#$% and w00w00 ppl. 
  13.  
  14.  */
  15. #include <unistd.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <signal.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <netinet/in_systm.h>
  24. #include <netinet/in.h>
  25. #include <netinet/ip.h>
  26. #include <netinet/udp.h>
  27. #include <netdb.h>
  28. #include <arpa/inet.h>
  29. #include <pcap.h>
  30. #include "md5.h"
  31. #define VERSION "0.2 (lame & dirty)"
  32. #ifdef NOT_HAVE_SNPRINTF
  33. #include <stdarg.h>
  34. #define snprintf int_snprintf
  35. int int_snprintf (char *buf, int len, char *fmt,...)
  36. {
  37.   va_list args;
  38.   int ret;
  39.   va_start (args, fmt);
  40.   ret = vsprintf (buf, fmt, args);
  41.   va_end (args);
  42.   return (ret);
  43. }
  44. #endif
  45. /* ------------------------------------------------------------------ */
  46. #ifdef LINUX
  47. #include <linux/if_ether.h>
  48. #define EthernetHeader  struct ethhdr
  49. #define IPHeader        struct iphdr
  50. #define UDPHeader       struct udphdr
  51. #define UDP_SrcPort(x) (x->source)
  52. #define UDP_DstPort(x) (x->dest)
  53. #define IP_SrcAddr(x)  (x->saddr)
  54. #define IP_DstAddr(x)  (x->daddr)
  55. #endif
  56. /* The default case is Solaris. */
  57. #ifndef EthernetHeader
  58. #include <net/if.h>
  59. #include <netinet/if_ether.h>
  60. #define EthernetHeader     struct ether_header
  61. #define IPHeader           struct ip
  62. #define UDPHeader          struct udphdr
  63. #define UDP_SrcPort(x) (x->uh_sport)
  64. #define UDP_DstPort(x) (x->uh_dport)
  65. #define IP_SrcAddr(x)  (x->ip_src)
  66. #define IP_DstAddr(x)  (x->ip_dst)
  67. #endif /* EthernetHeader */
  68. #define MAXBUFFER 65536
  69. #ifndef DICTIONARY_FILENAME
  70. #define DICTIONARY_FILENAME "dictionary"
  71. #endif
  72. #ifndef CLIENTS_FILENAME
  73. #define CLIENTS_FILENAME "clients"
  74. #endif
  75. #define RADIUS_ATTR_STR      1
  76. #define RADIUS_ATTR_INT      2
  77. #define RADIUS_ATTR_DATE     3
  78. #define RADIUS_ATTR_IPADDR   4
  79. #define RADIUS_ATTR_ABINARY  5         /* Ascend specific */
  80. typedef struct _DICT_VALUE {
  81.   int value;
  82.   char *name;
  83.   char *attrname;
  84.   void *next;
  85. } DICT_VALUE;
  86. typedef struct _DICT_ATTR {
  87.   int value;
  88.   int type;
  89.   char *name;
  90.   void *next;
  91. } DICT_ATTR;
  92. /* we ignore any greater */
  93. #define MAX_SECRET_STRING 253
  94. typedef struct _CLIENTS {
  95.   struct in_addr ipaddr;
  96.   char secret[MAX_SECRET_STRING];
  97.   void *next;
  98. } CLIENTS;
  99. /* radius attr packet for parsing process */
  100. typedef struct RAD_ATTR_PACKET {
  101.   int code;
  102.   int type;
  103.   int length;
  104.   char *buff;
  105.   int buff_length;
  106.   char *name;
  107.   void *next;
  108. } RAD_ATTR_PACKET;
  109. /* radius packet struct for parsing process */
  110. typedef struct RAD_PACKET {
  111.   time_t time;
  112.   struct sockaddr_in src;
  113.   struct sockaddr_in dst;
  114.   
  115.   unsigned char code;
  116.   unsigned char ident;
  117.   unsigned short length;
  118.   unsigned char auth[16];
  119.   char buff[4096];
  120.   unsigned int buff_length;
  121.   struct RAD_ATTR_PACKET *attr;              /* parsed attr's chain */
  122. } RAD_PACKET;
  123. /* ethernet packet */
  124. struct etherpacket {
  125.   EthernetHeader eth;
  126.   IPHeader ip;
  127.   UDPHeader udp;
  128.   char buff[MAXBUFFER];
  129. } eth_packet;
  130. /* The following are hooks to the positions in the struct.
  131.  */
  132. IPHeader *ip;
  133. UDPHeader *udp;
  134. /*-------------------------------------------------------------------------*/
  135. int quiet = 0;
  136. int account = 0;  /* only accounting info */
  137. int resolve = 0;  /* dont resolve hostnames as default */
  138. int verbose = 0;  /* silence as default */
  139. pcap_t *PCAP;     /* PCAP handler for interface */
  140. char *dict_filename = DICTIONARY_FILENAME;
  141. char *clients_filename = NULL;         /* individual clients secret */
  142. CLIENTS *secret_clients = NULL;
  143. char *secret_passwd = NULL;            /* global secret passwd */
  144. DICT_ATTR *dictionary_attr = NULL;
  145. DICT_VALUE *dictionary_value = NULL;
  146. char *ParseRadiusCode(unsigned int code)
  147. {
  148.   char *ret;
  149.   
  150.   switch (code) {
  151.   case 1:   ret = "Access-Request"; break;
  152.   case 2:   ret = "Access-Accept"; break;
  153.   case 3:   ret = "Access-Reject"; break;
  154.   case 4:   ret = "Accounting-Request"; break;
  155.   case 5:   ret = "Accounting-Response"; break;
  156.   case 11:  ret = "Access-Challenge"; break;
  157.   case 12:  ret = "Status-Server (experemental)"; break;
  158.   case 13:  ret = "Status=Client (experemental)"; break;
  159.   case 255: ret = "Reserved"; break;
  160.   default:
  161.     return NULL;
  162.   }
  163.   return ret;
  164. }
  165. char *ParseRadiusAuth(char *auth)
  166. {
  167.   static char ret[80];
  168.   int i;
  169.   for (i = 0; i < 16; i++) {
  170.     snprintf(ret+i*2, 80-i*2, "%02x", (unsigned int)*( unsigned char *)(auth+i));
  171.   }
  172.   return ret;
  173. }
  174. DICT_ATTR *GetAttrFromDict(int key)
  175. {
  176.   DICT_ATTR *attr = dictionary_attr;
  177.   
  178.   while (attr != NULL) {
  179.     if (attr->value == key) return attr;
  180.     attr = attr->next;
  181.   }
  182.   return NULL;
  183. }
  184. DICT_VALUE *GetValueFromDict(int attrkey, int key)
  185. {
  186.   DICT_VALUE *value = dictionary_value;
  187.   DICT_ATTR *attr;
  188.   char *str;
  189.   
  190.   if ((attr = GetAttrFromDict(attrkey)) == NULL) return NULL;
  191.   str = attr->name;
  192.   while (value != NULL) {
  193.     if (strlen(value->attrname) == strlen(str) &&
  194.         strncmp(value->attrname, str, strlen(str)) == 0 &&
  195.         value->value == key)
  196.       return value;
  197.     value = value->next;
  198.   }
  199.   return NULL;
  200. }
  201. char *GetHostSecret(struct in_addr *ipaddr)
  202. {
  203.   CLIENTS *cur = secret_clients;
  204.   while (cur != NULL) {
  205.     if (memcmp(ipaddr, &cur->ipaddr, sizeof(struct in_addr)) == 0)
  206.       return cur->secret;
  207.     cur = cur->next;
  208.   }
  209.   
  210.   /* if global secret passwd is setted, we use it as default
  211.    for nondefined hosts */
  212.   if (secret_passwd != NULL) return secret_passwd;
  213.   return NULL;
  214. }
  215. void OutHex(unsigned char *buff, unsigned int len)
  216. {
  217.   printf("(%d) ", len);
  218.   while (len-- != 0) {
  219.     printf("%02x", (unsigned int)*buff);
  220.     buff++;
  221.   }
  222. }
  223. void OutAscii(unsigned char *buff, unsigned int len)
  224. {
  225.   while (len-- != 0 && *buff != 0) {
  226.     printf("%c", (unsigned char)*buff);
  227.     buff++;
  228.   }
  229. }
  230. void FreeRadiusPacketStruct(RAD_PACKET *rad)
  231. {
  232.   int counter = 0;
  233.   RAD_ATTR_PACKET *pkt;
  234.   if (rad == NULL) return;
  235.   while ((pkt = rad->attr) != NULL) {
  236.     rad->attr = rad->attr->next;
  237.     counter++;
  238.     free(pkt);
  239.   }
  240. #ifdef DEBUG_MALLOC
  241.   fprintf(stderr, "free %d objectsn", counter);
  242. #endif
  243. }
  244. int OutRadiusPacket(RAD_PACKET *rad)
  245. {
  246.   struct tm *curr_time;
  247.   struct hostent *host;
  248.   char src_str[128], dst_str[128];
  249.   RAD_ATTR_PACKET *attr = rad->attr;
  250.   DICT_VALUE *value;
  251.   unsigned long val;
  252.   struct sockaddr_in addr;
  253.   char str[4096], *code_str;
  254.   int empty;
  255.   curr_time = localtime(&rad->time);
  256.   memset(src_str, 0, sizeof(src_str));
  257.   strncpy(src_str, (char *)inet_ntoa(rad->src.sin_addr), 127);
  258.   memset(dst_str, 0, sizeof(dst_str));
  259.   strncpy(dst_str, (char *)inet_ntoa(rad->dst.sin_addr), 127);
  260.   if (resolve) {
  261.     if ((host = gethostbyaddr((char *) &rad->src.sin_addr,
  262.                                sizeof(rad->src.sin_addr), AF_INET)))
  263.       strncpy(src_str, host->h_name, 127);
  264.     if ((host = gethostbyaddr((char *) &rad->dst.sin_addr,
  265.                                sizeof(rad->dst.sin_addr), AF_INET)))
  266.       strncpy(dst_str, host->h_name, 127);
  267.   }
  268.   
  269.   if (!account) {
  270.     /* out all packets */
  271.     printf("%.2d:%.2d:%.2d   ", 
  272.            curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec);
  273.     printf("%s:%u > %s:%un", src_str, ntohs(rad->src.sin_port),
  274.            dst_str, ntohs(rad->dst.sin_port));
  275.     code_str = ParseRadiusCode(rad->code);
  276.     if (code_str == NULL) {
  277.       printf("    code : Undefined (%0x02X)nn", rad->code);
  278.       return -1;
  279.     }
  280.     printf("    code : %sn", ParseRadiusCode(rad->code));
  281.     if (verbose) {
  282.       printf("    iden : 0x%02xn     len : 0x%03xn    auth : %sn",
  283.              rad->ident, rad->length, ParseRadiusAuth(rad->auth));
  284.     }
  285.     while (attr) {
  286.       printf("t%s = ", attr->name);
  287.       if (attr->buff_length <= 0) empty = 1; else empty = 0;
  288.       
  289.       switch (attr->type) {
  290.       case RADIUS_ATTR_DATE:
  291.         if (empty) break;
  292.         memcpy(&val, attr->buff, sizeof(long));
  293.         val = ntohl(val);
  294.         printf("%08Xh (date)n", val);
  295.         break;
  296.       case RADIUS_ATTR_INT:
  297.         if (empty) break;
  298.         memcpy(&val, attr->buff, sizeof(long));
  299.         val = ntohl(val);
  300.         if ((value = GetValueFromDict(attr->code, val)) == NULL) {
  301.           printf("%dn", val);
  302.         } else {
  303.           printf("%sn", value->name);
  304.         }
  305.         break;
  306.       case RADIUS_ATTR_IPADDR:
  307.         if (empty) break;
  308.         memcpy ((void *) &(addr.sin_addr), (void *)(attr->buff),
  309.                 sizeof(struct in_addr));
  310.         printf("%sn", inet_ntoa(addr.sin_addr));
  311.         break;
  312.       case RADIUS_ATTR_ABINARY:
  313.         if (empty) printf("""n");
  314.         else {
  315.           if ( attr->code == 2 && GetHostSecret(&rad->src.sin_addr) != NULL ) {
  316.              /* password */
  317.              char cr[1024];
  318.              char digest[32];
  319.              char *hostsecret = GetHostSecret(&rad->src.sin_addr);
  320.              int i;
  321.              memcpy(cr, hostsecret, strlen(hostsecret));
  322.              memcpy(cr + strlen(hostsecret), rad->auth, 16);
  323.              MD5Calc(digest, cr, strlen(hostsecret) + 16);
  324.              memset(cr, 0, sizeof(cr));
  325.              printf(""");
  326.              for ( i = 0; i < attr->buff_length; i++ ) 
  327.                attr->buff[i] ^= digest[i % 16];
  328.              OutAscii(attr->buff, attr->buff_length);
  329.              printf("" ");
  330.           }  
  331.           OutHex(attr->buff, attr->buff_length);
  332.           printf("n");
  333.         }
  334.         break;
  335.       case RADIUS_ATTR_STR:
  336.         if (empty) printf("""n");
  337.         else {
  338.           memcpy(str, (attr->buff), attr->buff_length);
  339.           str[attr->buff_length] = 0;
  340.           printf(""%s"n", str);
  341.         }
  342.         break;
  343.       default:
  344.         printf("<undefined type>n");
  345.         break;
  346.       }
  347.       attr = attr->next;
  348.     }
  349.   printf("n");
  350.   } else {
  351.     /* out only short accounting packets */
  352.     if (rad->code != 4 && rad->code != 5) return 0;
  353.     printf("%.2d:%.2d:%.2d  ", 
  354.            curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec);
  355.     printf("%s:%u > %s:%u ", src_str, ntohs(rad->src.sin_port),
  356.            dst_str, ntohs(rad->dst.sin_port));
  357.     if (rad->code == 4) printf("Req ");
  358.     else printf("Res ");
  359.     while (attr) {
  360.       printf("%s = ", attr->name);
  361.       if (attr->buff_length <= 0) empty = 1; else empty = 0;
  362.       
  363.       switch (attr->type) {
  364.       case RADIUS_ATTR_DATE:
  365.         if (empty) break;
  366.         memcpy(&val, attr->buff, sizeof(long));
  367.         val = ntohl(val);
  368.         printf("%08Xh (date)", val);
  369.         break;
  370.       case RADIUS_ATTR_INT:
  371.         if (empty) break;
  372.         memcpy(&val, attr->buff, sizeof(long));
  373.         val = ntohl(val);
  374.         if ((value = GetValueFromDict(attr->code, val)) == NULL) {
  375.           printf("%d", val);
  376.         } else {
  377.           printf("%s", value->name);
  378.         }
  379.         break;
  380.       case RADIUS_ATTR_IPADDR:
  381.         if (empty) break;
  382.         memcpy ((void *) &(addr.sin_addr), (void *)(attr->buff),
  383.                 sizeof(struct in_addr));
  384.         printf("%s", inet_ntoa(addr.sin_addr));
  385.         break;
  386.       case RADIUS_ATTR_ABINARY:
  387.         if (empty) printf("""");
  388.         else {
  389.           OutHex(attr->buff, attr->buff_length);
  390.         }
  391.         break;
  392.       case RADIUS_ATTR_STR:
  393.         if (empty) printf("""");
  394.         else {
  395.           memcpy(str, (attr->buff), attr->buff_length);
  396.           str[attr->buff_length] = 0;
  397.           printf(""%s"", str);
  398.         }
  399.         break;
  400.       default:
  401.         printf("<undefined type>");
  402.         break;
  403.       }
  404.       attr = attr->next;
  405.       if (attr) printf(", ");
  406.     }
  407.   printf("n");
  408.   }
  409.   return 0;
  410. }
  411. /* redefine type for some of non ascii attributes */
  412. int HookAttr(int code, int type)
  413. {
  414.   switch (code) {
  415.   case 2:          /* Password (out like md5) */
  416.   case 3:          /* Challenge-Response (CHAP Password) */
  417.   case 17:         /* Change-Password (only for Ascend)*/
  418.   case 19:         /* Callback-Number (no ascii) */
  419.   case 20:         /* Callback-Id (no ascii) */
  420.   case 24:         /* State (no ascii) */
  421.   case 25:         /* Class (no ascii) */
  422.   case 26:         /* Vendor_Specific */
  423.   case 214:        /* Ascend-Send-Secret */
  424.   case 215:        /* Ascend-Receive-Secret */
  425.     return RADIUS_ATTR_ABINARY;
  426.   }
  427.   return type;
  428. }
  429. int ParseRadiusAttr(RAD_PACKET *rad)
  430. {
  431.   DICT_ATTR *attr;
  432.   DICT_VALUE *value;
  433.   unsigned long val;
  434.   struct sockaddr_in addr;
  435.   RAD_ATTR_PACKET *rattr, *last = NULL;
  436.   int counter = 0;
  437.   unsigned char *buff = rad->buff;
  438.   int len = rad->buff_length;
  439.   if (len <= 0) return -1;
  440.   while (len > 0) {
  441.     rattr = malloc(sizeof(RAD_ATTR_PACKET));
  442.     if (rattr == NULL) {
  443.       fprintf(stderr, "ERROR: Out of memory (while parsing in progress)n");
  444.       return -1;
  445.     }
  446.     counter++;
  447.     rattr->code = (unsigned char)*buff;
  448.     rattr->length = (unsigned char)*(buff+1);
  449.     if ((attr = GetAttrFromDict(rattr->code)) == NULL) {
  450.       fprintf(stderr, "ERROR: Undefined attr (type:%02Xh, length:%d)n",
  451.               rattr->code, rattr->length);
  452.        return -1;
  453.     }
  454.     rattr->name = attr->name;
  455.     rattr->type = HookAttr(rattr->code, attr->type);
  456.     rattr->buff = buff+2;
  457.     rattr->buff_length = rattr->length-2; /* without code and len */
  458.     rattr->next = NULL;
  459.     if (last == NULL) rad->attr = rattr;
  460.     else last->next = rattr;
  461.     last = rattr;
  462.     /* continue for next attr */
  463.     len -= rattr->length;
  464.     buff += rattr->length;
  465.   }
  466.   if (len != 0) {
  467.     fprintf(stderr, "ERROR: wrong packet... non aligned internal structn");
  468.     return -1;
  469.   }
  470. #ifdef DEBUG_MALLOC
  471.   fprintf(stderr, "malloc %d objectsn", counter);
  472. #endif
  473.   return 0;
  474. }
  475. int CheckDoublePacket(RAD_PACKET *rad)
  476. {
  477.  return 0;  /* not implemented yet */
  478. }
  479. void FilterProc(char *user_data, struct pcap_pkthdr *p_header, const char *packet)
  480. {
  481.   unsigned int packet_size = p_header->caplen;
  482.   char *rad_pkt;
  483.   int rad_pkt_len;
  484.   RAD_PACKET RAD;   /* Parsed RADIUS packet struct */
  485.   memset(&RAD, 0, sizeof(RAD));
  486.   
  487.   /* get time incoming packet */
  488.   RAD.time = time(NULL);
  489.   if (packet_size > MAXBUFFER) return;   /* prevent overrun ;) */
  490.   memcpy(&eth_packet, packet, packet_size);
  491.   
  492.   /* fill sockaddr_in */
  493.   RAD.src.sin_family = AF_INET;
  494.   RAD.src.sin_port = UDP_SrcPort (udp);
  495.   memcpy ((void *) &(RAD.src.sin_addr), (void *) &(IP_SrcAddr (ip)),
  496.           sizeof (struct in_addr));
  497.   RAD.dst.sin_family = AF_INET;
  498.   RAD.dst.sin_port = UDP_DstPort (udp);
  499.   memcpy ((void *) &(RAD.dst.sin_addr), (void *) &(IP_DstAddr (ip)),
  500.           sizeof (struct in_addr));
  501.   rad_pkt = (char *)((eth_packet.buff)-2);
  502.   rad_pkt_len = packet_size-sizeof(eth_packet.ip)-sizeof(eth_packet.udp);
  503.   /* check size of received packet and according rfc drop wrong packets */
  504.   if (rad_pkt_len < 20 || rad_pkt_len > 4096) {
  505.     fprintf(stderr, "ERROR: %s:%u > %s:%u  - non RADIUS packet (bad UDP length: %d)n",
  506.             (char *) inet_ntoa(RAD.src.sin_addr), ntohs(RAD.src.sin_port),
  507.             (char *) inet_ntoa(RAD.dst.sin_addr), ntohs(RAD.dst.sin_port),
  508.            rad_pkt_len);
  509.     return;
  510.   }
  511.   
  512.   /* fill radius packet struct */
  513.   RAD.code = *(char *)rad_pkt;
  514.   RAD.ident = *(unsigned char *)(rad_pkt+1);
  515.   RAD.length = ntohs(*(unsigned short *)(rad_pkt+2));
  516.   memcpy(RAD.auth, (char *)(rad_pkt+4), 16);
  517.   RAD.buff_length = RAD.length - 20;     /* without code,ident,length,auth */
  518.   if (RAD.buff_length >= 0 && RAD.buff_length <= 4096 - 20 )
  519.     memcpy(RAD.buff, (char *)(rad_pkt+20), RAD.buff_length);
  520.   else {
  521.     fprintf(stderr, "ERROR: %s:%u > %s:%u  - non RADIUS packet (bad length in packet: %d)n",
  522.             (char *) inet_ntoa(RAD.src.sin_addr), ntohs(RAD.src.sin_port),
  523.             (char *) inet_ntoa(RAD.dst.sin_addr), ntohs(RAD.dst.sin_port),
  524.            RAD.buff_length);
  525.     return;
  526.   }
  527.   if (quiet && CheckDoublePacket(&RAD)) return;
  528.   if (ParseRadiusAttr(&RAD) == 0) OutRadiusPacket(&RAD);
  529.   FreeRadiusPacketStruct(&RAD);
  530.   
  531.   return;
  532. }
  533. void HookProto(void)
  534. {
  535.   ip = (IPHeader *) (((unsigned long) &eth_packet.ip) - 2);
  536.   udp = (UDPHeader *) (((unsigned long) &eth_packet.udp) - 2);
  537. }
  538. pcap_t *OpenPromisc(char *eth, int snaplen, int promisc, int to_ms)
  539. {
  540.   pcap_t *h;
  541.   char ebuf[PCAP_ERRBUF_SIZE];
  542.   h = pcap_open_live(eth, snaplen, promisc, to_ms, ebuf);
  543.   if( !h )
  544.     fprintf(stderr, "ERROR: Can't open interface %s.n%sn", eth, ebuf);
  545.   return h;
  546. }
  547. void ClosePromisc(void)
  548. {
  549.   pcap_close(PCAP);
  550. }
  551. #define MAX_FILTER_STR 4096
  552. int MakeFilter(pcap_t *h, char *eth, unsigned short pradius, unsigned short pradacct, char *filter)
  553. {
  554.   struct bpf_program bpf;
  555.   bpf_u_int32 net, mask;
  556.   char ebuf[PCAP_ERRBUF_SIZE];
  557.   char buf[MAX_FILTER_STR];
  558.   if (pcap_lookupnet(eth, &net, &mask, ebuf) == -1) {
  559.     fprintf(stderr, "ERROR: Can't lookup interface %sn%sn", eth, ebuf);
  560.     return -1;
  561.   }
  562.   snprintf(buf, MAX_FILTER_STR,
  563.            "(udp and (port %d or port %d) %s)",
  564.            ntohs(pradius), ntohs(pradacct), filter);
  565.   if (pcap_compile(h, &bpf, buf, 1, mask) == -1) {
  566.     fprintf(stderr, "ERROR: Can't compile BPF filter '%s'n", buf);
  567.     return -1;
  568.   }
  569.   if (pcap_setfilter(h, &bpf) == -1) {
  570.     fprintf(stderr, "ERROR: Can't set BPF filter '%s'n", buf);
  571.   }
  572.   
  573.   return 0;
  574. }
  575. void Terminate(int signal)
  576. {
  577.   ClosePromisc();
  578.   exit(0);
  579. }
  580. int LoadDictionary(char *fname)
  581. {
  582.   FILE *in;
  583.   char buff[1024];
  584.   int line = 0;
  585.   char attrstr[512], namestr[512], valuestr[512], typestr[512];
  586.   DICT_ATTR dicta, *attr;
  587.   DICT_VALUE dictv, *value;
  588.   
  589.   
  590.   if ((in = fopen(fname,"r")) == NULL) {
  591.     fprintf(stderr, "ERROR: Can't open dictionary file '%s'n", fname);
  592.     return -1;
  593.   }
  594.   while (fgets(buff, sizeof(buff), in) != NULL) {
  595.     line++;
  596.     if (*buff == 0 || *buff == '#' || *buff == 'n') continue;
  597.     if (strncmp(buff, "ATTRIBUTE", 9) == 0) {
  598.       if (sscanf(buff, "%s%s%s%s", attrstr, namestr, valuestr, typestr) != 4) {
  599.         fprintf(stderr, "ERROR: Can't understand ATTRIBUTE on line %dn", line);
  600.         return -1;
  601.       }
  602.       if (strlen(namestr) > 31) {
  603.         fprintf(stderr, "ERROR: Invalid name length on line %dn", line);
  604.         return -1;
  605.       }
  606.       if (!isdigit(*valuestr)) {
  607.         fprintf(stderr, "ERROR: Invalid value on line %dn", line);
  608.         return -1;
  609.       }
  610.       dicta.value = atoi(valuestr);
  611.       if (strcmp(typestr, "string") == 0) dicta.type = RADIUS_ATTR_STR;
  612.       else if (strcmp(typestr, "integer") == 0) dicta.type = RADIUS_ATTR_INT;
  613.       else if (strcmp(typestr, "ipaddr") == 0) dicta.type = RADIUS_ATTR_IPADDR;
  614.       else if (strcmp(typestr, "date") == 0) dicta.type = RADIUS_ATTR_DATE;
  615.       else if (strcmp(typestr, "abinary") == 0) dicta.type = RADIUS_ATTR_ABINARY;
  616.       else {
  617.         fprintf(stderr, "ERROR: Invalid type on line %dn", line);
  618.         return -1;
  619.       }
  620.       if ((dicta.name = malloc(strlen(namestr)+1)) == NULL) {
  621.         fprintf(stderr, "ERROR: Out of memn");
  622.         return -1;
  623.       }
  624.       strncpy(dicta.name, namestr, strlen(namestr)+1);
  625.       
  626.       /* insert new ATTR */
  627.       if ((attr = malloc(sizeof(DICT_ATTR))) == NULL) {
  628.         fprintf(stderr, "ERROR: Out of memn");
  629.         return -1;
  630.       }
  631.       memcpy(attr, &dicta, sizeof(DICT_ATTR));
  632.       attr->next = dictionary_attr;
  633.       dictionary_attr = attr;
  634. #ifdef DEBUG
  635.       fprintf(stderr,"attr: %sn", attr->name);
  636. #endif
  637.     }
  638.     else if (strncmp(buff, "VALUE", 5) == 0) {
  639.       if (sscanf(buff, "%s%s%s%s", typestr, attrstr, namestr, valuestr) != 4) {
  640.         fprintf(stderr, "ERROR: Can't understand VALUE on line %dn", line);
  641.         return -1;
  642.       }
  643.       if (strlen(attrstr) > 31) {
  644.         fprintf(stderr, "ERROR: Invalid attribute length on line %dn", line);
  645.         return -1;
  646.       }
  647.       if (strlen(namestr) > 31) {
  648.         fprintf(stderr, "ERROR: Invalid name length on line %dn", line);
  649.         return -1;
  650.       }
  651.       if (!isdigit(*valuestr)) {
  652.         fprintf(stderr, "ERROR: Invalid value on line %dn", line);
  653.         return -1;
  654.       }
  655.       dictv.value = atoi(valuestr);
  656.       if ((dictv.name = malloc(strlen(namestr)+1)) == NULL) {
  657.         fprintf(stderr, "ERROR: Out of memn");
  658.         return -1;
  659.       }
  660.       strncpy(dictv.name, namestr, strlen(namestr)+1);
  661.       if ((dictv.attrname = malloc(strlen(attrstr)+1)) == NULL) {
  662.         fprintf(stderr, "ERROR: Out of memn");
  663.         return -1;
  664.       }
  665.       strncpy(dictv.attrname, attrstr, strlen(attrstr)+1);
  666.       /* insert net VALUE */
  667.       if ((value = malloc(sizeof(DICT_VALUE))) == NULL) {
  668.         fprintf(stderr, "ERROR: Out of memn");
  669.         return -1;
  670.       }
  671.       memcpy(value, &dictv, sizeof(DICT_VALUE));
  672.       value->next = dictionary_value;
  673.       dictionary_value = value;
  674. #ifdef DEBUG
  675.       fprintf(stderr,"valu: %s (attr:%s)n", value->name, value->attrname);
  676. #endif
  677.     }
  678.   }
  679.   fclose(in);
  680.   return 0;
  681. }
  682. int LoadClients(char *fname)
  683. {
  684.   FILE *in = fopen(fname,"r");
  685.   char buff[1024];
  686.   CLIENTS host, *ins_host;
  687.   int line = 0;
  688.   char ip[128], sec[512];
  689.   if (in == NULL) {
  690.     fprintf(stderr, "ERROR: Can't open clients file '%s'n", fname);
  691.     return -1;
  692.   }
  693.   while (fgets(buff, sizeof(buff), in) != NULL) {
  694.     line++;
  695.     if (*buff == 0 || *buff == '#' || *buff == 'n') continue;
  696.     if (sscanf(buff, "%s%s", ip, sec) != 2) {
  697.       fprintf(stderr, "ERROR: Can't understand line %dn", line);
  698.       return -1;
  699.     }
  700.     
  701.     if (inet_aton(ip,&host.ipaddr) == 0) {
  702.       fprintf(stderr, "ERROR: Can't convert ip addr on line %dn", line);
  703.       return -1;
  704.     }
  705.     if (sizeof(host.secret) < strlen(sec)) {
  706.       fprintf(stderr, "ERROR: Too long secret on line %dn", line);
  707.       return -1;
  708.     }
  709.     memcpy(host.secret,sec,strlen(sec)+1);
  710.     /* insert new client secret password here */
  711.     if ((ins_host = malloc(sizeof(CLIENTS))) == NULL) {
  712.       fprintf(stderr, "ERROR: Out of memn");
  713.       return -1;
  714.     }
  715.     memcpy(ins_host, &host, sizeof(CLIENTS));
  716.     ins_host->next = secret_clients;
  717.     secret_clients = ins_host;
  718.   }
  719.   fclose(in);
  720.   return 0;
  721. }
  722. int main(int argc, char *argv[])
  723. {
  724.   char *filter = "";
  725.   char ebuf[PCAP_ERRBUF_SIZE];
  726.   char *eth = NULL;
  727.   int arg, error = 0;
  728.   struct servent *serv_ent;
  729.   unsigned short radius_port, radacct_port;
  730.   /*
  731.    fprintf(stderr, "eth_packet size: %dn", sizeof(eth_packet));
  732.    */
  733.   
  734.   while ((arg = getopt(argc, argv, "Vavri:f:d:c:qp:")) != -1) {
  735.     switch( arg ) {
  736.     case 'v':    /* be verbose */
  737.       verbose++;
  738.       break;
  739.     case 'i':    /* set interface name */
  740.       eth = strdup(optarg);
  741.       break;
  742.     case 'f':    /* pcap filter expression */
  743.       filter = strdup(optarg);
  744.       break;
  745.     case 'r':    /* resolve hostnames */
  746.       resolve++;
  747.       break;
  748.     case 'd':    /* set dictonary */
  749.       dict_filename = strdup(optarg);
  750.       break;
  751.     case 'c':    /* place where i can get secret passwords */
  752.       clients_filename = strdup(optarg);
  753.       break;
  754.     case 's':    /* there u can define default secret password */
  755.       secret_passwd = strdup(optarg);
  756.       break;
  757.     case 'q':    /* quiet output */
  758.       quiet++;
  759.       break;
  760.     case 'a':    /* output accounting info only */
  761.       account++;
  762.       break;
  763.     case 'V':
  764.       fprintf(stderr, "RADIUS sNIFFer by FreeLSD. Version %sn", VERSION);
  765.       fprintf(stderr, "http://www.freelsd.net/securityn");
  766.       exit(0);
  767.     default:
  768.       error++;
  769.       break;
  770.     }
  771.   }
  772.   
  773.   if (error) {
  774.     fprintf(stderr, "Usage: radiusniff [-vVrqa] [-i interface] [-f expression]n");
  775.     fprintf(stderr, "                  [-d dictionary ] [-c clients] [-s passwd]n");
  776.     exit(1);
  777.   }
  778.   if (!eth) {
  779.     if (!(eth = pcap_lookupdev(ebuf))) {
  780.       fprintf(stderr, "ERROR: Can't find device for sniffing.n%sn",ebuf);
  781.       exit(1);
  782.     }
  783.   }
  784.   if (access(dict_filename, R_OK) != 0) {
  785.     fprintf(stderr, "ERROR: Can't access to dictonary file '%s'n", dict_filename);
  786.     exit(1);
  787.   }
  788.   if (LoadDictionary(dict_filename) != 0) exit(1);
  789.   if (clients_filename) {
  790.     if (access(clients_filename, R_OK) != 0) {
  791.       fprintf(stderr, "ERROR: Can't access to clients file '%s', ignored...n", clients_filename);
  792.       clients_filename = NULL;
  793.     } else if (LoadClients(clients_filename) != 0) exit(1);
  794.   }
  795.   
  796.   HookProto();
  797.   signal(SIGINT, Terminate);
  798.   signal(SIGTERM, Terminate);
  799.   signal(SIGKILL, Terminate);
  800.   signal(SIGQUIT, Terminate);
  801.   
  802.   serv_ent = getservbyname("radius","udp");
  803.   serv_ent ? (radius_port = serv_ent->s_port) : (radius_port = htons(1645));
  804.   serv_ent = getservbyname("radacct","udp");
  805.   serv_ent ? (radacct_port = serv_ent->s_port) : (radacct_port = htons(1646));
  806.   if (!(PCAP = OpenPromisc(eth, 10000, 1, 0))) exit(1);
  807.   if (MakeFilter(PCAP, eth, radius_port, radacct_port, filter) != 0) exit(1);
  808.   /* Let's make STDOUT line buffered */
  809.   setlinebuf(stdout);
  810.   /* start main loop */
  811.   pcap_loop(PCAP, -1, (void *)FilterProc, NULL);
  812.   
  813.   ClosePromisc();
  814. }