summaryrefslogtreecommitdiff
path: root/accel-pptpd/radius/auth.c
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-10-04 15:12:41 +0400
committerKozlov Dmitry <dima@server>2010-10-04 15:12:41 +0400
commita337b4af82fe30d568547aabc61df7bc67a8a835 (patch)
tree140437e3f4282abb39b17606750ba9bb4123711a /accel-pptpd/radius/auth.c
parent06858ad4c7468ac8b226b34126b68db2128877f1 (diff)
downloadaccel-ppp-xebd-a337b4af82fe30d568547aabc61df7bc67a8a835.tar.gz
accel-ppp-xebd-a337b4af82fe30d568547aabc61df7bc67a8a835.zip
ppp: implemented mppe
radius: implemented mppe support various improvements and bug fixes
Diffstat (limited to 'accel-pptpd/radius/auth.c')
-rw-r--r--accel-pptpd/radius/auth.c132
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: