📄 radsniff.c
字号:
/* * radsniff.c Display the RADIUS traffic on the network. * * Version: $Id: radsniff.c,v 1.13 2008/01/01 17:29:12 aland Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2006 The FreeRADIUS server project * Copyright 2006 Nicolas Baradakis <nicolas.baradakis@cegetel.net> */#include <freeradius-devel/ident.h>RCSID("$Id: radsniff.c,v 1.13 2008/01/01 17:29:12 aland Exp $")#define _LIBRADIUS 1#include <freeradius-devel/libradius.h>#include <pcap.h>#include <freeradius-devel/radpaths.h>#include <freeradius-devel/conf.h>#include <freeradius-devel/radsniff.h>static const char *radius_secret = "testing123";static VALUE_PAIR *filter_vps = NULL;static int debug_flag = 0;#undef DEBUG#define DEBUG if (debug_flag) printfstatic const char *packet_codes[] = { "", "Access-Request", "Access-Accept", "Access-Reject", "Accounting-Request", "Accounting-Response", "Accounting-Status", "Password-Request", "Password-Accept", "Password-Reject", "Accounting-Message", "Access-Challenge", "Status-Server", "Status-Client", "14", "15", "16", "17", "18", "19", "20", "Resource-Free-Request", "Resource-Free-Response", "Resource-Query-Request", "Resource-Query-Response", "Alternate-Resource-Reclaim-Request", "NAS-Reboot-Request", "NAS-Reboot-Response", "28", "Next-Passcode", "New-Pin", "Terminate-Session", "Password-Expired", "Event-Request", "Event-Response", "35", "36", "37", "38", "39", "Disconnect-Request", "Disconnect-ACK", "Disconnect-NAK", "CoF-Request", "CoF-ACK", "CoF-NAK", "46", "47", "48", "49", "IP-Address-Allocate", "IP-Address-Release"};static int filter_packet(RADIUS_PACKET *packet){ VALUE_PAIR *check_item; VALUE_PAIR *vp; unsigned int pass, fail; int compare; pass = fail = 0; for (vp = packet->vps; vp != NULL; vp = vp->next) { for (check_item = filter_vps; check_item != NULL; check_item = check_item->next) if ((check_item->attribute == vp->attribute) && (check_item->operator != T_OP_SET)) { compare = paircmp(check_item, vp); if (compare == 1) pass++; else fail++; } } if (fail == 0 && pass != 0) { return 0; } return 1;}static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *data){ /* Just a counter of how many packets we've had */ static int count = 1; /* Define pointers for packet's attributes */ const struct ethernet_header *ethernet; /* The ethernet header */ const struct ip_header *ip; /* The IP header */ const struct udp_header *udp; /* The UDP header */ const uint8_t *payload; /* Packet payload */ /* And define the size of the structures we're using */ int size_ethernet = sizeof(struct ethernet_header); int size_ip = sizeof(struct ip_header); int size_udp = sizeof(struct udp_header); /* For FreeRADIUS */ RADIUS_PACKET *packet; args = args; /* -Wunused */ /* Define our packet's attributes */ ethernet = (const struct ethernet_header*)(data); ip = (const struct ip_header*)(data + size_ethernet); udp = (const struct udp_header*)(data + size_ethernet + size_ip); payload = (const uint8_t *)(data + size_ethernet + size_ip + size_udp); packet = malloc(sizeof(*packet)); if (!packet) { fprintf(stderr, "Out of memory\n"); return; } memset(packet, 0, sizeof(*packet)); packet->src_ipaddr.af = AF_INET; packet->src_ipaddr.ipaddr.ip4addr.s_addr = ip->ip_src.s_addr; packet->src_port = ntohs(udp->udp_sport); packet->dst_ipaddr.af = AF_INET; packet->dst_ipaddr.ipaddr.ip4addr.s_addr = ip->ip_dst.s_addr; packet->dst_port = ntohs(udp->udp_dport); packet->data = payload; packet->data_len = header->len - size_ethernet - size_ip - size_udp; if (!rad_packet_ok(packet, 0)) { librad_perror("Packet"); free(packet); return; } /* * Decode the data without bothering to check the signatures. */ if (rad_decode(packet, NULL, radius_secret) != 0) { free(packet); librad_perror("decode"); return; } if (filter_vps && filter_packet(packet)) { free(packet); DEBUG("Packet number %d doesn't match\n", count++); return; } /* Print the RADIUS packet */ printf("Packet number %d has just been sniffed\n", count++); printf("\tFrom: %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport)); printf("\tTo: %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport)); printf("\tType: %s\n", packet_codes[packet->code]); if (packet->vps != NULL) { vp_printlist(stdout, packet->vps); pairfree(&packet->vps); } fflush(stdout); free(packet);}static void NEVER_RETURNS usage(int status){ FILE *output = status ? stderr : stdout; fprintf(output, "usage: radsniff [options]\n"); fprintf(output, "options:\n"); fprintf(output, "\t-c count\tNumber of packets to capture.\n"); fprintf(output, "\t-d directory\tDirectory where the dictionaries are found\n"); fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813 or 1814)\n"); fprintf(output, "\t-h\t\tPrint this help message.\n"); fprintf(output, "\t-i interface\tInterface to capture.\n"); fprintf(output, "\t-p port\tList for packets on port.\n"); fprintf(output, "\t-r filter\tRADIUS attribute filter.\n"); fprintf(output, "\t-s secret\tRADIUS secret.\n"); fprintf(output, "\t-X\t\tPrint out debugging information.\n"); exit(status);}int main(int argc, char *argv[]){ char *dev; /* sniffing device */ char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */ pcap_t *descr; /* sniff handler */ struct bpf_program fp; /* hold compiled program */ bpf_u_int32 maskp; /* subnet mask */ bpf_u_int32 netp; /* ip */ char buffer[1024]; char *pcap_filter = NULL; char *radius_filter = NULL; int packet_count = -1; /* how many packets to sniff */ int opt; FR_TOKEN parsecode; const char *radius_dir = RADIUS_DIR; int port = 1812; /* Default device */ dev = pcap_lookupdev(errbuf); /* Get options */ while ((opt = getopt(argc, argv, "c:d:f:hi:p:r:s:X")) != EOF) { switch (opt) { case 'c': packet_count = atoi(optarg); if (packet_count <= 0) { fprintf(stderr, "radsniff: Invalid number of packets \"%s\"\n", optarg); exit(1); } break; case 'd': radius_dir = optarg; break; case 'f': pcap_filter = optarg; break; case 'h': usage(0); break; case 'i': dev = optarg; break; case 'p': port = atoi(optarg); break; case 'r': radius_filter = optarg; break; case 's': radius_secret = optarg; break; case 'X': debug_flag = 1; break; default: usage(1); } } if (!pcap_filter) { pcap_filter = buffer; snprintf(buffer, sizeof(buffer), "udp port %d or %d or %d", port, port + 1, port + 2); } if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) { librad_perror("radsniff"); return 1; } if (radius_filter) { parsecode = userparse(radius_filter, &filter_vps); if (parsecode == T_OP_INVALID) { fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\": %s\n", optarg, librad_errstr); exit(1); } if (!filter_vps) { fprintf(stderr, "radsniff: Empty RADIUS filter \"%s\"\n", optarg); exit(1); } } /* Set our device */ pcap_lookupnet(dev, &netp, &maskp, errbuf); /* Print device to the user */ printf("Device: [%s]\n", dev); if (packet_count > 0) { printf("Num of packets: [%d]\n", packet_count); } printf("PCAP filter: [%s]\n", pcap_filter); if (filter_vps != NULL) { printf("RADIUS filter:\n"); vp_printlist(stdout, filter_vps); } printf("RADIUS secret: [%s]\n", radius_secret); /* Open the device so we can spy */ descr = pcap_open_live(dev, SNAPLEN, 1, 0, errbuf); if (descr == NULL) { printf("radsniff: pcap_open_live failed (%s)\n", errbuf); exit(1); } /* Apply the rules */ if( pcap_compile(descr, &fp, pcap_filter, 0, netp) == -1) { printf("radsniff: pcap_compile failed\n"); exit(1); } if (pcap_setfilter(descr, &fp) == -1) { printf("radsniff: pcap_setfilter failed\n"); exit(1); } /* Now we can set our callback function */ pcap_loop(descr, packet_count, got_packet, NULL); pcap_close(descr); printf("Done sniffing\n"); fflush(stdout); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -