summaryrefslogtreecommitdiff
path: root/accel-pptpd/radius
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/radius')
-rw-r--r--accel-pptpd/radius/auth.c108
-rw-r--r--accel-pptpd/radius/dict.c17
-rw-r--r--accel-pptpd/radius/packet.c54
-rw-r--r--accel-pptpd/radius/radius.h3
4 files changed, 134 insertions, 48 deletions
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index 5792b8f1..bec89de2 100644
--- a/accel-pptpd/radius/auth.c
+++ b/accel-pptpd/radius/auth.c
@@ -43,10 +43,40 @@ static uint8_t* encrypt_password(const char *passwd, const char *secret, const u
return epasswd;
}
+static int rad_auth_send(struct rad_req_t *req)
+{
+ int i;
+
+ for(i = 0; i < conf_max_try; i++) {
+ if (rad_req_send(req))
+ goto out;
+
+ rad_req_wait(req, conf_timeout);
+
+ if (req->reply) {
+ if (req->reply->id != req->pack->id) {
+ rad_packet_free(req->reply);
+ req->reply = NULL;
+ } else
+ break;
+ }
+ }
+
+ if (!req->reply)
+ log_ppp_warn("radius:auth: no response\n");
+ else if (req->reply->code == CODE_ACCESS_ACCEPT) {
+ rad_proc_attrs(req);
+ return PWDB_SUCCESS;
+ }
+
+out:
+ return PWDB_DENIED;
+}
+
int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args)
{
struct rad_req_t *req;
- int i, r = PWDB_DENIED;
+ int r = PWDB_DENIED;
//int id = va_arg(args, int);
const char *passwd = va_arg(args, const char *);
uint8_t *epasswd;
@@ -67,25 +97,7 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args)
free(epasswd);
- for(i = 0; i < conf_max_try; i++) {
- if (rad_req_send(req))
- goto out;
-
- rad_req_wait(req, conf_timeout);
-
- if (req->reply) {
- if (req->reply->id != req->pack->id) {
- rad_packet_free(req->reply);
- req->reply = NULL;
- } else
- break;
- }
- }
-
- if (req->reply && req->reply->code == CODE_ACCESS_ACCEPT) {
- rad_proc_attrs(req);
- r = PWDB_SUCCESS;
- }
+ rad_auth_send(req);
out:
rad_req_free(req);
@@ -96,7 +108,7 @@ out:
int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list args)
{
struct rad_req_t *req;
- int i, r = PWDB_DENIED;
+ int r = PWDB_DENIED;
uint8_t chap_password[17];
int id = va_arg(args, int);
@@ -121,27 +133,7 @@ int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list arg
if (rad_packet_add_octets(req->pack, "CHAP-Password", chap_password, 17))
goto out;
- for(i = 0; i < conf_max_try; i++) {
- if (rad_req_send(req))
- goto out;
-
- rad_req_wait(req, conf_timeout);
-
- if (req->reply) {
- if (req->reply->id != req->pack->id) {
- rad_packet_free(req->reply);
- req->reply = NULL;
- } else
- break;
- }
- }
-
- if (!req->reply)
- log_ppp_warn("radius:auth: no response\n");
- else if (req->reply->code == CODE_ACCESS_ACCEPT) {
- rad_proc_attrs(req);
- r = PWDB_SUCCESS;
- }
+ r = rad_auth_send(req);
out:
rad_req_free(req);
@@ -151,12 +143,38 @@ out:
int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args)
{
- /*int id = va_arg(args, int);
+ int r;
+ struct rad_req_t *req;
+ uint8_t response[50];
+
+ int id = va_arg(args, int);
const uint8_t *challenge = va_arg(args, const uint8_t *);
+ int challenge_len = va_arg(args, int);
const uint8_t *lm_response = va_arg(args, const uint8_t *);
const uint8_t *nt_response = va_arg(args, const uint8_t *);
- int flags = va_arg(args, int);*/
- return PWDB_NO_IMPL;
+ int flags = va_arg(args, int);
+
+ req = rad_req_alloc(rpd, CODE_ACCESS_REQUEST, username);
+ if (!req)
+ return PWDB_DENIED;
+
+ response[0] = id;
+ response[1] = flags;
+ memcpy(response + 2, lm_response, 24);
+ memcpy(response + 2 + 24, nt_response, 24);
+
+ if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len))
+ goto out;
+
+ if (rad_packet_add_vendor_octets(req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response)))
+ goto out;
+
+ r = rad_auth_send(req);
+
+out:
+ rad_req_free(req);
+
+ return r;
}
int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list args)
diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c
index 27923518..54f8daa5 100644
--- a/accel-pptpd/radius/dict.c
+++ b/accel-pptpd/radius/dict.c
@@ -270,16 +270,22 @@ void rad_dict_free(struct rad_dict_t *dict)
free(dict);
}
-struct rad_dict_attr_t *rad_dict_find_attr(const char *name)
+static struct rad_dict_attr_t *dict_find_attr(struct list_head *items, const char *name)
{
struct rad_dict_attr_t *attr;
- list_for_each_entry(attr, &dict->items, entry)
+ list_for_each_entry(attr, items, entry)
if (!strcmp(attr->name, name))
return attr;
return NULL;
}
+
+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 *attr;
@@ -290,6 +296,7 @@ struct rad_dict_attr_t *rad_dict_find_attr_id(int id)
return NULL;
}
+
struct rad_dict_value_t *rad_dict_find_val_name(struct rad_dict_attr_t *attr, const char *name)
{
struct rad_dict_value_t *val;
@@ -326,3 +333,9 @@ struct rad_dict_vendor_t *rad_dict_find_vendor_name(const char *name)
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 7d418d7a..53f3885d 100644
--- a/accel-pptpd/radius/packet.c
+++ b/accel-pptpd/radius/packet.c
@@ -59,6 +59,11 @@ int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA)
memcpy(ptr, RA, 16); ptr+=16;
list_for_each_entry(attr, &pack->attrs, entry) {
+ if (attr->vendor) {
+ *ptr = 26; ptr++;
+ *ptr = attr->len + 2 + 6; ptr++;
+ *(uint32_t *)ptr = htonl(attr->vendor->id); ptr+=4;
+ }
*ptr = attr->attr->id; ptr++;
*ptr = attr->len + 2; ptr++;
switch(attr->attr->type) {
@@ -267,7 +272,10 @@ void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt,
print(" id=%x", pack->id);
list_for_each_entry(attr, &pack->attrs, entry) {
- print(" <%s ", attr->attr->name);
+ if (attr->vendor)
+ print("<%s %s ", attr->vendor->name, attr->attr->name);
+ else
+ print(" <%s ", attr->attr->name);
switch (attr->attr->type) {
case ATTR_TYPE_INTEGER:
val = rad_dict_find_val(attr->attr, attr->val);
@@ -304,6 +312,7 @@ int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val)
if (!ra)
return -1;
+ memset(ra, 0, sizeof(*ra));
ra->attr = attr;
ra->len = 4;
ra->val.integer = val;
@@ -344,6 +353,7 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *
return -1;
}
+ memset(ra, 0, sizeof(*ra));
ra->attr = attr;
ra->len = len;
ra->val.octets = malloc(len);
@@ -376,6 +386,7 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *
return -1;
}
+ memset(ra, 0, sizeof(*ra));
ra->attr = attr;
ra->len = len;
ra->val.string = malloc(len+1);
@@ -441,6 +452,7 @@ int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char *
if (!ra)
return -1;
+ memset(ra, 0, sizeof(*ra));
ra->attr = attr;
ra->len = 4;
ra->val = v->val;
@@ -503,3 +515,43 @@ int rad_packet_send(struct rad_packet_t *pack, int fd, struct sockaddr_in *addr)
return 0;
}
+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 *ra;
+ struct rad_dict_attr_t *attr;
+ struct rad_dict_vendor_t *vendor;
+
+ if (pack->len + 6 + 2 + len >= REQ_LENGTH_MAX)
+ return -1;
+
+ vendor = rad_dict_find_vendor_name(vendor_name);
+ if (!vendor)
+ return -1;
+
+ attr = rad_dict_find_vendor_attr(vendor, name);
+ if (!attr)
+ return -1;
+
+ ra = malloc(sizeof(*ra));
+ if (!ra) {
+ log_emerg("radius: out of memory\n");
+ return -1;
+ }
+
+ memset(ra, 0, sizeof(*ra));
+ ra->vendor = vendor;
+ ra->attr = attr;
+ ra->len = len;
+ ra->val.octets = malloc(len);
+ if (!ra->val.octets) {
+ log_emerg("radius: out of memory\n");
+ free(ra);
+ return -1;
+ }
+ memcpy(ra->val.octets, val, len);
+ list_add_tail(&ra->entry, &pack->attrs);
+ pack->len += 6 + 2 + len;
+
+ return 0;
+}
+
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
index f2d2f004..dcbc3cf0 100644
--- a/accel-pptpd/radius/radius.h
+++ b/accel-pptpd/radius/radius.h
@@ -92,6 +92,7 @@ struct rad_attr_t
{
struct list_head entry;
struct rad_dict_attr_t *attr;
+ struct rad_dict_vendor_t *vendor;
//struct rad_dict_value_t *val;
rad_value_t val;
int len;
@@ -145,6 +146,7 @@ struct rad_dict_attr_t *rad_dict_find_attr_id(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_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);
int rad_req_acct_fill(struct rad_req_t *);
@@ -159,6 +161,7 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *
int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, uint8_t *val, int len);
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_packet_t *rad_packet_alloc(int code);
int rad_packet_build(struct rad_packet_t *pack, uint8_t *RA);