diff options
author | Kozlov Dmitry <dima@server> | 2010-09-08 15:51:29 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-09-08 15:51:29 +0400 |
commit | 4c6469a9fd820db713251a645ac2499782f796ed (patch) | |
tree | fd7c4926eb2a3e2aa047bd14da429f3d6a5f8e6f /accel-pptpd/radius/packet.c | |
parent | ec759f72fcf7d517fdfe8d043c75d0218363bc78 (diff) | |
download | accel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.tar.gz accel-ppp-4c6469a9fd820db713251a645ac2499782f796ed.zip |
radius: implemented packet exchange
radius: implemented PAP authorization
radius: implemented IP assigning
triton: implemented userspace context switching
and other stuff
Diffstat (limited to 'accel-pptpd/radius/packet.c')
-rw-r--r-- | accel-pptpd/radius/packet.c | 169 |
1 files changed, 121 insertions, 48 deletions
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c index f1b4ebea..627b6c5e 100644 --- a/accel-pptpd/radius/packet.c +++ b/accel-pptpd/radius/packet.c @@ -4,14 +4,40 @@ #include <errno.h> #include <stdio.h> #include <unistd.h> +#include <fcntl.h> #include "log.h" #include "radius.h" -static int urandom_fd; +struct rad_packet_t *rad_packet_alloc(int code) +{ + struct rad_packet_t *pack; + + pack = malloc(sizeof(*pack)); + if (!pack) { + log_error("radius:packet: out of memory\n"); + return NULL; + } + + memset(pack, 0, sizeof(*pack)); + pack->code = code; + pack->len = 20; + pack->id = 1; + INIT_LIST_HEAD(&pack->attrs); + + return pack; +} -int rad_packet_build(struct rad_packet_t *pack) +void print_buf(uint8_t *buf,int size) +{ + int i; + for(i=0;i<size;i++) + printf("%x ",buf[i]); + printf("\n"); +} + +int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA) { struct rad_req_attr_t *attr; uint8_t *ptr; @@ -22,26 +48,18 @@ int rad_packet_build(struct rad_packet_t *pack) return -1; } + pack->buf = ptr; *ptr = pack->code; ptr++; *ptr = pack->id; ptr++; - *(uint16_t*)ptr = pack->len; ptr+= 2; - while (1) { - if (read(urandom_fd, ptr, 16) != 16) { - if (errno == EINTR) - continue; - log_error("radius:packet:read urandom: %s\n", strerror(errno)); - goto out_err; - } - break; - } - ptr+=16; + *(uint16_t*)ptr = htons(pack->len); ptr+= 2; + memcpy(ptr, RA, 16); ptr+=16; list_for_each_entry(attr, &pack->attrs, entry) { - *ptr = attr->attr->type; ptr++; - *ptr = attr->len; ptr++; + *ptr = attr->attr->id; ptr++; + *ptr = attr->len + 2; ptr++; switch(attr->attr->type) { case ATTR_TYPE_INTEGER: - *(uint32_t*)ptr = attr->val.integer; + *(uint32_t*)ptr = htonl(attr->val.integer); break; case ATTR_TYPE_STRING: memcpy(ptr, attr->val.string, attr->len); @@ -50,20 +68,18 @@ int rad_packet_build(struct rad_packet_t *pack) *(in_addr_t*)ptr = attr->val.ipaddr; break; case ATTR_TYPE_DATE: - *(uint32_t*)ptr = attr->val.date; + *(uint32_t*)ptr = htonl(attr->val.date); break; default: - log_error("radius:packet: unknown attribute type\n"); + log_error("radius:packet:BUG: unknown attribute type\n"); abort(); } ptr += attr->len; } - return 0; + print_buf(pack->buf, pack->len); -out_err: - free(ptr); - return -1; + return 0; } struct rad_packet_t *rad_packet_recv(int fd) @@ -72,22 +88,16 @@ struct rad_packet_t *rad_packet_recv(int fd) struct rad_req_attr_t *attr; struct rad_dict_attr_t *da; uint8_t *ptr; - int n, type, len; - - pack = malloc(sizeof(*pack)); - if (!pack) { - log_error("radius:packet: out of memory\n"); - return NULL; - } + int n, id, len; - memset(pack, 0, sizeof(*pack)); - INIT_LIST_HEAD(&pack->attrs); + pack = rad_packet_alloc(0); + if (!pack) + return NULL; pack->buf = malloc(REQ_LENGTH_MAX); if (!pack->buf) { log_error("radius:packet: out of memory\n"); - free(pack); - return NULL; + goto out_err; } while (1) { @@ -110,7 +120,7 @@ struct rad_packet_t *rad_packet_recv(int fd) pack->code = *ptr; ptr++; pack->id = *ptr; ptr++; - pack->len = *(uint16_t*)ptr; ptr += 2; + pack->len = ntohs(*(uint16_t*)ptr); ptr += 2; if (pack->len > n) { log_warn("radius:packet: short packet received %i, expected %i\n", pack->len, n); @@ -121,13 +131,17 @@ struct rad_packet_t *rad_packet_recv(int fd) n -= 20; while (n>0) { - type = *ptr; ptr++; - len = *ptr; ptr++; + id = *ptr; ptr++; + len = *ptr - 2; ptr++; + if (len < 0) { + log_warn("radius:packet short attribute len received\n"); + goto out_err; + } if (2 + len > n) { - log_error("radius:packet: too long attribute received (%i, %i)\n", type, len); + log_warn("radius:packet: too long attribute received (%i, %i)\n", id, len); goto out_err; } - da = rad_dict_find_attr_type(type); + da = rad_dict_find_attr_id(id); if (da) { attr = malloc(sizeof(*attr)); if (!attr) { @@ -136,18 +150,28 @@ struct rad_packet_t *rad_packet_recv(int fd) } attr->attr = da; attr->len = len; - if (type == ATTR_TYPE_STRING) { - attr->val.string = malloc(len); - if (!attr->val.string) { - log_error("radius:packet: out of memory\n"); - free(attr); - goto out_err; - } - } else - memcpy(&attr->val.integer, ptr, 4); + switch (da->type) { + case ATTR_TYPE_STRING: + attr->val.string = malloc(len+1); + if (!attr->val.string) { + log_error("radius:packet: out of memory\n"); + free(attr); + goto out_err; + } + memcpy(attr->val.string, ptr, len); + attr->val.string[len] = 0; + break; + case ATTR_TYPE_DATE: + case ATTR_TYPE_INTEGER: + attr->val.integer = ntohl(*(uint32_t*)ptr); + break; + case ATTR_TYPE_IPADDR: + attr->val.integer = *(uint32_t*)ptr; + break; + } list_add_tail(&attr->entry, &pack->attrs); } else - log_warn("radius:packet: unknown attribute type received (%i)\n", type); + log_warn("radius:packet: unknown attribute received (%i)\n", id); ptr += len; n -= 2 + len; } @@ -176,3 +200,52 @@ void rad_packet_free(struct rad_packet_t *pack) free(pack); } + +void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, ...)) +{ + struct rad_req_attr_t *attr; + struct rad_dict_value_t *val; + + print("[RADIUS "); + switch(pack->code) { + case CODE_ACCESS_REQUEST: + print("Access-Request"); + break; + case CODE_ACCESS_CHALLENGE: + print("Access-Challenge"); + break; + case CODE_ACCESS_ACCEPT: + print("Access-Accept"); + break; + case CODE_ACCESS_REJECT: + print("Access-Reject"); + break; + default: + print("Unknown (%i)", pack->code); + } + print(" id=%x", pack->id); + + list_for_each_entry(attr, &pack->attrs, entry) { + print(" <%s ", attr->attr->name); + if (attr->printable) { + switch (attr->attr->type) { + case ATTR_TYPE_INTEGER: + val = rad_dict_find_val(attr->attr, attr->val); + if (val) + print("%s", val->name); + else + print("%i", attr->val.integer); + break; + case ATTR_TYPE_STRING: + print("\"%s\"", attr->val.string); + break; + case ATTR_TYPE_IPADDR: + print("%i.%i.%i.%i", attr->val.ipaddr & 0xff, (attr->val.ipaddr >> 8) & 0xff, (attr->val.ipaddr >> 16) & 0xff, (attr->val.ipaddr >> 24) & 0xff); + break; + } + } + print(">"); + } + print("]\n"); +} + |