summaryrefslogtreecommitdiff
path: root/accel-pptpd/radius
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/radius')
-rw-r--r--accel-pptpd/radius/auth.c42
-rw-r--r--accel-pptpd/radius/dict.c17
-rw-r--r--accel-pptpd/radius/packet.c35
-rw-r--r--accel-pptpd/radius/radius.h4
4 files changed, 90 insertions, 8 deletions
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index bec89de2..29c6efd3 100644
--- a/accel-pptpd/radius/auth.c
+++ b/accel-pptpd/radius/auth.c
@@ -179,13 +179,49 @@ out:
int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list args)
{
- /*int id = va_arg(args, int);
+ int r;
+ struct rad_req_t *req;
+ struct rad_attr_t *ra;
+ uint8_t mschap_response[50];
+
+ int id = va_arg(args, int);
const uint8_t *challenge = va_arg(args, const uint8_t *);
const uint8_t *peer_challenge = va_arg(args, const uint8_t *);
+ const uint8_t *reserved = va_arg(args, const uint8_t *);
const uint8_t *response = va_arg(args, const uint8_t *);
int flags = va_arg(args, int);
- uint8_t *authenticator = va_arg(args, uint8_t *);*/
- return PWDB_NO_IMPL;
+ uint8_t *authenticator = va_arg(args, uint8_t *);
+
+ req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ if (!req)
+ return PWDB_DENIED;
+
+ mschap_response[0] = id;
+ mschap_response[1] = flags;
+ memcpy(mschap_response + 2, peer_challenge, 16);
+ memcpy(mschap_response + 2 + 16, reserved, 8);
+ memcpy(mschap_response + 2 + 16 + 8, response, 24);
+
+ if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16))
+ goto out;
+
+ if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response)))
+ goto out;
+
+ r = rad_auth_send(req);
+ if (r == PWDB_SUCCESS) {
+ ra = rad_packet_find_vendor_attr(req->reply, "Microsoft", "MS-CHAP2-Success");
+ if (!ra) {
+ log_error("radius:auth:mschap-v2: 'MS-CHAP-Success' not found in radius response\n");
+ r = PWDB_DENIED;
+ } else
+ memcpy(authenticator, ra->val.octets + 3, 40);
+ }
+
+out:
+ rad_req_free(req);
+
+ return r;
}
diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c
index 54f8daa5..6db77813 100644
--- a/accel-pptpd/radius/dict.c
+++ b/accel-pptpd/radius/dict.c
@@ -286,11 +286,12 @@ struct rad_dict_attr_t *rad_dict_find_attr(const char *name)
return dict_find_attr(&dict->items, name);
}
-struct rad_dict_attr_t *rad_dict_find_attr_id(int id)
+struct rad_dict_attr_t *rad_dict_find_attr_id(struct rad_dict_vendor_t *vendor, int id)
{
struct rad_dict_attr_t *attr;
+ struct list_head *items = vendor ? &vendor->items : &dict->items;
- list_for_each_entry(attr, &dict->items, entry)
+ list_for_each_entry(attr, items, entry)
if (attr->id == id)
return attr;
@@ -334,6 +335,18 @@ struct rad_dict_vendor_t *rad_dict_find_vendor_name(const char *name)
return NULL;
}
+struct rad_dict_vendor_t *rad_dict_find_vendor_id(int id)
+{
+ struct rad_dict_vendor_t *vendor;
+
+ list_for_each_entry(vendor, &dict->vendors, entry) {
+ if (vendor->id == id)
+ return vendor;
+ }
+
+ return NULL;
+}
+
struct rad_dict_attr_t *rad_dict_find_vendor_attr(struct rad_dict_vendor_t *vendor, const char *name)
{
return dict_find_attr(&vendor->items, name);
diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c
index 53f3885d..0aeafa54 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -96,8 +96,9 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr)
struct rad_packet_t *pack;
struct rad_attr_t *attr;
struct rad_dict_attr_t *da;
+ struct rad_dict_vendor_t *vendor;
uint8_t *ptr;
- int n, id, len;
+ int n, id, len, vendor_id;
socklen_t addr_len = sizeof(*addr);
pack = rad_packet_alloc(0);
@@ -154,13 +155,26 @@ struct rad_packet_t *rad_packet_recv(int fd, struct sockaddr_in *addr)
log_ppp_warn("radius:packet: too long attribute received (%i, %i)\n", id, len);
goto out_err;
}
- da = rad_dict_find_attr_id(id);
+ if (id == 26) {
+ vendor_id = ntohl(*(uint32_t *)ptr);
+ vendor = rad_dict_find_vendor_id(vendor_id);
+ if (vendor) {
+ ptr += 4;
+ id = *ptr; ptr++;
+ len = *ptr - 2; ptr++;
+ n -= 2 + len;
+ } else
+ log_ppp_warn("radius:packet: vendor %s not found\n", id);
+ }
+ da = rad_dict_find_attr_id(vendor, id);
if (da) {
attr = malloc(sizeof(*attr));
if (!attr) {
log_emerg("radius:packet: out of memory\n");
goto out_err;
}
+ memset(attr, 0, sizeof(*attr));
+ attr->vendor = vendor;
attr->attr = da;
attr->len = len;
switch (da->type) {
@@ -555,3 +569,20 @@ int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_n
return 0;
}
+struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name)
+{
+ struct rad_attr_t *ra;
+
+ list_for_each_entry(ra, &pack->attrs, entry) {
+ if (!ra->vendor)
+ continue;
+ if (strcmp(ra->vendor->name, vendor_name))
+ continue;
+ if (strcmp(ra->attr->name, name))
+ continue;
+
+ return ra;
+ }
+
+ return NULL;
+}
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
index dcbc3cf0..8403b339 100644
--- a/accel-pptpd/radius/radius.h
+++ b/accel-pptpd/radius/radius.h
@@ -142,10 +142,11 @@ struct radius_pd_t *rad_find_session_pack(struct rad_packet_t *pack);
int rad_dict_load(const char *fname);
void rad_dict_free(struct rad_dict_t *dict);
struct rad_dict_attr_t *rad_dict_find_attr(const char *name);
-struct rad_dict_attr_t *rad_dict_find_attr_id(int type);
+struct rad_dict_attr_t *rad_dict_find_attr_id(struct rad_dict_vendor_t *vendor, int type);
struct rad_dict_value_t *rad_dict_find_val_name(struct rad_dict_attr_t *, const char *name);
struct rad_dict_value_t *rad_dict_find_val(struct rad_dict_attr_t *, rad_value_t val);
struct rad_dict_vendor_t *rad_dict_find_vendor_name(const char *name);
+struct rad_dict_vendor_t *rad_dict_find_vendor_id(int id);
struct rad_dict_attr_t *rad_dict_find_vendor_attr(struct rad_dict_vendor_t *vendor, const char *name);
struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *username);
@@ -162,6 +163,7 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *
int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val);
int rad_packet_change_val(struct rad_packet_t *pack, const char *name, const char *val);
int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len);
+struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name);
struct rad_packet_t *rad_packet_alloc(int code);
int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA);