summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-13 10:54:48 +0400
committerKozlov Dmitry <dima@server>2010-09-13 10:54:48 +0400
commit5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4 (patch)
treea2f8f9993772cf5a61c85414abf0dc4e21a4c5a9
parent5b13315273d2b97972a0ec9883d70d71620b2978 (diff)
downloadaccel-ppp-5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4.tar.gz
accel-ppp-5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4.zip
radius: implemented mschap-v1 authorization
-rw-r--r--accel-pptpd/accel-pptpd.conf5
-rw-r--r--accel-pptpd/auth/auth_mschap_v1.c34
-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
6 files changed, 154 insertions, 67 deletions
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 7d711e0..8edfebe 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -1,9 +1,10 @@
[modules]
./liblog_file.so
-./liblog_pgsql.so
+#./liblog_pgsql.so
./libpptp.so
./libauth_pap.so
./libauth_chap_md5.so
+./libauth_mschap_v1.so
./libradius.so
[core]
@@ -20,7 +21,7 @@ echo-failure=3
echo-interval=3
[radius]
-dictionary=../radius/etc/dictionary
+dictionary=../radius/dict/dictionary
nas-identifier=pptp
nas-ip-address=127.0.0.1
gw-ip-address=192.168.100.100
diff --git a/accel-pptpd/auth/auth_mschap_v1.c b/accel-pptpd/auth/auth_mschap_v1.c
index 3a75d67..bf7c212 100644
--- a/accel-pptpd/auth/auth_mschap_v1.c
+++ b/accel-pptpd/auth/auth_mschap_v1.c
@@ -17,6 +17,8 @@
#include "ppp_lcp.h"
#include "pwdb.h"
+#define MSCHAP_V1 0x80
+
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
@@ -54,7 +56,7 @@ struct chap_response_t
uint8_t val_size;
uint8_t lm_hash[24];
uint8_t nt_hash[24];
- uint8_t use_nt_hash;
+ uint8_t flags;
char name[0];
} __attribute__((packed));
@@ -82,7 +84,7 @@ struct chap_auth_data_t
static void chap_send_challenge(struct chap_auth_data_t *ad);
static void chap_recv(struct ppp_handler_t *h);
-static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *res, char *name);
+static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *res, const char *name);
static void print_buf(const uint8_t *buf,int size)
{
@@ -97,8 +99,6 @@ static void print_str(const char *buf,int size)
log_ppp_debug("%c",buf[i]);
}
-
-
static struct auth_data_t* auth_data_init(struct ppp_t *ppp)
{
struct chap_auth_data_t *d=malloc(sizeof(*d));
@@ -142,13 +142,13 @@ static int chap_finish(struct ppp_t *ppp, struct auth_data_t *auth)
static int lcp_send_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
- *ptr=0x80;
+ *ptr=MSCHAP_V1;
return 1;
}
static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
- if (*ptr==0x80)
+ if (*ptr==MSCHAP_V1)
return LCP_OPT_ACK;
return LCP_OPT_NAK;
}
@@ -210,12 +210,13 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
{
struct chap_response_t *msg=(struct chap_response_t*)hdr;
char *name;
+ int r;
log_ppp_debug("recv [MSCHAP-v1 Response id=%x <", msg->hdr.id);
print_buf(msg->lm_hash,24);
log_ppp_debug(">, <");
print_buf(msg->nt_hash,24);
- log_ppp_debug(">, F=%i, name=\"",msg->use_nt_hash);
+ log_ppp_debug(">, F=%i, name=\"",msg->flags);
print_str(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
log_ppp_debug("\"]\n");
@@ -234,14 +235,15 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
}
name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
-
- if (chap_check_response(ad, msg, name))
- {
+ r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V1, ad->id, ad->val, VALUE_SIZE, msg->lm_hash, msg->nt_hash, msg->flags);
+ if (r == PWDB_NO_IMPL)
+ r = chap_check_response(ad, msg, name);
+
+ if (r == PWDB_DENIED) {
chap_send_failure(ad);
auth_failed(ad->ppp);
free(name);
- }else
- {
+ } else {
chap_send_success(ad);
auth_successed(ad->ppp, name);
}
@@ -276,7 +278,7 @@ static void des_encrypt(const uint8_t *input, const uint8_t *key, uint8_t *outpu
memcpy(output,res,8);
}
-static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, char *name)
+static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name)
{
MD4_CTX md4_ctx;
uint8_t z_hash[21];
@@ -288,10 +290,9 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
passwd = pwdb_get_passwd(ad->ppp,name);
if (!passwd)
{
- free(name);
log_ppp_debug("mschap-v1: user not found\n");
chap_send_failure(ad);
- return -1;
+ return PWDB_DENIED;
}
u_passwd=malloc(strlen(passwd)*2);
@@ -310,11 +311,10 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
des_encrypt(ad->val,z_hash+7,nt_hash+8);
des_encrypt(ad->val,z_hash+14,nt_hash+16);
- free(name);
free(passwd);
free(u_passwd);
- return memcmp(nt_hash,msg->nt_hash,24);
+ return memcmp(nt_hash,msg->nt_hash,24) ? PWDB_DENIED : PWDB_SUCCESS;
}
static struct ppp_auth_handler_t chap=
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c
index 5792b8f..bec89de 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 2792351..54f8daa 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 7d418d7..53f3885 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 f2d2f00..dcbc3cf 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);