diff options
author | Kozlov Dmitry <dima@server> | 2010-09-13 11:59:21 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-09-13 11:59:21 +0400 |
commit | a670641cc3c420bfd9026d3711501663aef88287 (patch) | |
tree | b2754ce3e83978759dd6ccfc7fbc1d0d0e1d96b7 | |
parent | 5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4 (diff) | |
download | accel-ppp-a670641cc3c420bfd9026d3711501663aef88287.tar.gz accel-ppp-a670641cc3c420bfd9026d3711501663aef88287.zip |
radius: implemnted mschap-v2 authorization
-rw-r--r-- | accel-pptpd/accel-pptpd.conf | 1 | ||||
-rw-r--r-- | accel-pptpd/auth/auth_mschap_v1.c | 6 | ||||
-rw-r--r-- | accel-pptpd/auth/auth_mschap_v2.c | 54 | ||||
-rw-r--r-- | accel-pptpd/radius/auth.c | 42 | ||||
-rw-r--r-- | accel-pptpd/radius/dict.c | 17 | ||||
-rw-r--r-- | accel-pptpd/radius/packet.c | 35 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.h | 4 |
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); |