summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-13 11:59:21 +0400
committerKozlov Dmitry <dima@server>2010-09-13 11:59:21 +0400
commita670641cc3c420bfd9026d3711501663aef88287 (patch)
treeb2754ce3e83978759dd6ccfc7fbc1d0d0e1d96b7
parent5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4 (diff)
downloadaccel-ppp-a670641cc3c420bfd9026d3711501663aef88287.tar.gz
accel-ppp-a670641cc3c420bfd9026d3711501663aef88287.zip
radius: implemnted mschap-v2 authorization
-rw-r--r--accel-pptpd/accel-pptpd.conf1
-rw-r--r--accel-pptpd/auth/auth_mschap_v1.c6
-rw-r--r--accel-pptpd/auth/auth_mschap_v2.c54
-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
7 files changed, 124 insertions, 35 deletions
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index 8edfebe9..eaa4dafe 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -5,6 +5,7 @@
./libauth_pap.so
./libauth_chap_md5.so
./libauth_mschap_v1.so
+./libauth_mschap_v2.so
./libradius.so
[core]
diff --git a/accel-pptpd/auth/auth_mschap_v1.c b/accel-pptpd/auth/auth_mschap_v1.c
index bf7c2120..bc54ed46 100644
--- a/accel-pptpd/auth/auth_mschap_v1.c
+++ b/accel-pptpd/auth/auth_mschap_v1.c
@@ -235,6 +235,12 @@ 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 (!name) {
+ log_emerg("mschap-v2: out of memory\n");
+ auth_failed(ad->ppp);
+ return;
+ }
+
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);
diff --git a/accel-pptpd/auth/auth_mschap_v2.c b/accel-pptpd/auth/auth_mschap_v2.c
index 6bd2c658..798f6eed 100644
--- a/accel-pptpd/auth/auth_mschap_v2.c
+++ b/accel-pptpd/auth/auth_mschap_v2.c
@@ -18,6 +18,8 @@
#include "ppp_lcp.h"
#include "pwdb.h"
+#define MSCHAP_V2 0x81
+
#define CHAP_CHALLENGE 1
#define CHAP_RESPONSE 2
#define CHAP_SUCCESS 3
@@ -95,7 +97,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 *msg, const char *name);
static void print_buf(const uint8_t *buf,int size)
{
@@ -155,13 +157,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=0x81;
+ *ptr = MSCHAP_V2;
return 1;
}
static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t *ptr)
{
- if (*ptr==0x81)
+ if (*ptr == MSCHAP_V2)
return LCP_OPT_ACK;
return LCP_OPT_NAK;
}
@@ -182,24 +184,20 @@ static void chap_send_failure(struct chap_auth_data_t *ad)
ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2);
}
-static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, uint8_t *response)
+static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name, char *authenticator)
{
MD4_CTX md4_ctx;
SHA_CTX sha_ctx;
char *passwd;
char *u_passwd;
- char *name;
uint8_t pw_hash[MD4_DIGEST_LENGTH];
uint8_t c_hash[SHA_DIGEST_LENGTH];
+ uint8_t response[SHA_DIGEST_LENGTH];
int i;
- name = strndup(msg->name,ntohs(msg->hdr.len)-sizeof(*msg)+2);
passwd = pwdb_get_passwd(ad->ppp,name);
if (!passwd)
- {
- free(name);
return -1;
- }
u_passwd=malloc(strlen(passwd)*2);
for(i=0; i<strlen(passwd); i++)
@@ -234,14 +232,16 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t
SHA1_Update(&sha_ctx,magic2,41);
SHA1_Final(response,&sha_ctx);
- free(name);
+ for(i=0; i<20; i++)
+ sprintf(authenticator+i*2,"%02X",response[i]);
+
free(passwd);
free(u_passwd);
return 0;
}
-static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_t *res_msg)
+static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_t *res_msg, const char *authenticator)
{
struct chap_success_t msg=
{
@@ -251,15 +251,9 @@ static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_
.hdr.len=htons(sizeof(msg)-1-2),
.message=MSG_SUCCESS,
};
- uint8_t response[20];
- int i;
- if (generate_response(ad,res_msg,response))
- return;
- for(i=0; i<20; i++)
- sprintf(msg.message+2+i*2,"%02X",response[i]);
- msg.message[2+i*2]=' ';
-
+ memcpy(msg.message + 2, authenticator, 40);
+
log_ppp_debug("send [MSCHAP-v2 Success id=%x \"%s\"]\n",msg.hdr.id,msg.message);
ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2);
@@ -290,6 +284,8 @@ 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;
+ char authenticator[40];
+ int r;
log_ppp_debug("recv [MSCHAP-v2 Response id=%x <", msg->hdr.id);
print_buf(msg->peer_challenge,16);
@@ -319,15 +315,21 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h
auth_failed(ad->ppp);
return;
}
+
+ r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V2, ad->id, ad->val, msg->peer_challenge, msg->reserved, msg->nt_hash, msg->flags, authenticator);
- if (chap_check_response(ad, msg, name))
- {
+ if (r == PWDB_NO_IMPL) {
+ r = chap_check_response(ad, msg, name);
+ if (generate_response(ad, msg, name, authenticator))
+ r = PWDB_DENIED;
+ }
+
+ if (r == PWDB_DENIED) {
chap_send_failure(ad);
auth_failed(ad->ppp);
free(name);
- }else
- {
- chap_send_success(ad,msg);
+ } else {
+ chap_send_success(ad, msg, authenticator);
auth_successed(ad->ppp, name);
}
}
@@ -361,7 +363,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;
SHA_CTX sha_ctx;
@@ -375,7 +377,6 @@ 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-v2: user not found\n");
chap_send_failure(ad);
return -1;
@@ -403,7 +404,6 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response
des_encrypt(c_hash,z_hash+7,nt_hash+8);
des_encrypt(c_hash,z_hash+14,nt_hash+16);
- free(name);
free(passwd);
free(u_passwd);
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);