diff options
Diffstat (limited to 'accel-pptpd/radius/auth.c')
-rw-r--r-- | accel-pptpd/radius/auth.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c index 9b61ecc..10fdd45 100644 --- a/accel-pptpd/radius/auth.c +++ b/accel-pptpd/radius/auth.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <string.h> #include <openssl/md5.h> +#include <openssl/sha.h> #include "triton.h" #include "events.h" @@ -8,9 +9,96 @@ #include "pwdb.h" #include "radius_p.h" +#include "attr_defs.h" #include "memdebug.h" +static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr, const uint8_t *challenge, uint8_t *key) +{ + MD5_CTX md5_ctx; + SHA_CTX sha1_ctx; + uint8_t md5[16]; + uint8_t plain[32]; + int i; + + if (attr->len != 32) { + log_ppp_warn("radius: %s: incorrect attribute length (%i)\n", attr->attr->name, attr->len); + return -1; + } + + memcpy(plain, attr->val.octets, 32); + + MD5_Init(&md5_ctx); + MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->pack->buf + 4, 16); + MD5_Final(md5, &md5_ctx); + + for (i = 0; i < 16; i++) + plain[i] ^= md5[i]; + + MD5_Init(&md5_ctx); + MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, attr->val.octets, 16); + MD5_Final(md5, &md5_ctx); + + for (i = 0; i < 16; i++) + plain[i + 16] ^= md5[i]; + + SHA1_Init(&sha1_ctx); + SHA1_Update(&sha1_ctx, plain + 8, 16); + SHA1_Update(&sha1_ctx, plain + 8, 16); + SHA1_Update(&sha1_ctx, challenge, 8); + SHA1_Final(key, &sha1_ctx); + + return 0; +} + +static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint8_t *key) +{ + MD5_CTX md5_ctx; + uint8_t md5[16]; + uint8_t plain[32]; + int i; + + if (attr->len != 34) { + log_ppp_warn("radius: %s: incorrect attribute length (%i)\n", attr->attr->name, attr->len); + return -1; + } + + if ((attr->val.octets[0] & 0x80) == 0) { + log_ppp_warn("radius: %s: incorrect salt value (%x)\n", attr->attr->name, attr->len); + return -1; + } + + MD5_Init(&md5_ctx); + MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->pack->buf + 4, 16); + MD5_Update(&md5_ctx, attr->val.octets, 2); + MD5_Final(md5, &md5_ctx); + + memcpy(plain, attr->val.octets + 2, 32); + + for (i = 0; i < 16; i++) + plain[i] ^= md5[i]; + + if (plain[0] != 16) { + log_ppp_warn("radius: %s: incorrect key length (%i)\n", attr->attr->name, plain[0]); + return -1; + } + + MD5_Init(&md5_ctx); + MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, attr->val.octets + 2, 16); + MD5_Final(md5, &md5_ctx); + + plain[16] ^= md5[0]; + + memcpy(key, plain + 1, 16); + + return 0; +} + + static uint8_t* encrypt_password(const char *passwd, const char *secret, const uint8_t *RA, int *epasswd_len) { uint8_t *epasswd; @@ -160,6 +248,48 @@ out: return r; } +static void setup_mppe(struct rad_req_t *req, const uint8_t *challenge) +{ + struct rad_attr_t *attr; + uint8_t mppe_recv_key[16]; + uint8_t mppe_send_key[16]; + struct ev_mppe_keys_t ev_mppe = { + .ppp = req->rpd->ppp, + }; + + list_for_each_entry(attr, &req->reply->attrs, entry) { + if (attr->vendor && attr->vendor->id == Vendor_Microsoft) { + switch (attr->attr->id) { + case MS_CHAP_MPPE_Keys: + if (decrypt_chap_mppe_keys(req, attr, challenge, mppe_recv_key)) + continue; + ev_mppe.recv_key = mppe_recv_key; + ev_mppe.send_key = mppe_recv_key; + break; + case MS_MPPE_Recv_Key: + if (decrypt_mppe_key(req, attr, mppe_recv_key)) + continue; + ev_mppe.recv_key = mppe_recv_key; + break; + case MS_MPPE_Send_Key: + if (decrypt_mppe_key(req, attr, mppe_send_key)) + continue; + ev_mppe.send_key = mppe_send_key; + break; + case MS_MPPE_Encryption_Policy: + ev_mppe.policy = attr->val.integer; + break; + case MS_MPPE_Encryption_Type: + ev_mppe.type = attr->val.integer; + break; + } + } + } + + if (ev_mppe.recv_key && ev_mppe.send_key) + triton_event_fire(EV_MPPE_KEYS, &ev_mppe); +} + int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list args) { int r; @@ -196,6 +326,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar .reply = req->reply, }; triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev); + setup_mppe(req, challenge); } out: @@ -251,6 +382,7 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar .reply = req->reply, }; triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev); + setup_mppe(req, NULL); } out: |