diff options
author | Kozlov Dmitry <dima@server> | 2010-09-13 10:54:48 +0400 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-09-13 10:54:48 +0400 |
commit | 5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4 (patch) | |
tree | a2f8f9993772cf5a61c85414abf0dc4e21a4c5a9 | |
parent | 5b13315273d2b97972a0ec9883d70d71620b2978 (diff) | |
download | accel-ppp-5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4.tar.gz accel-ppp-5ef0b9025a019aeb8502cd687d17a1e0b7aa0ca4.zip |
radius: implemented mschap-v1 authorization
-rw-r--r-- | accel-pptpd/accel-pptpd.conf | 5 | ||||
-rw-r--r-- | accel-pptpd/auth/auth_mschap_v1.c | 34 | ||||
-rw-r--r-- | accel-pptpd/radius/auth.c | 108 | ||||
-rw-r--r-- | accel-pptpd/radius/dict.c | 17 | ||||
-rw-r--r-- | accel-pptpd/radius/packet.c | 54 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.h | 3 |
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); |