Add MessageAuthenticator support
To address RadiusBLAST vulnerability. Fixes #16
This commit is contained in:
parent
42ef80e0b4
commit
cc012e18fa
8 changed files with 149 additions and 2 deletions
99
radius.c
99
radius.c
|
|
@ -32,6 +32,10 @@ extern ip_filtert *ip_filters;
|
|||
|
||||
static const hasht zero;
|
||||
|
||||
static enum {
|
||||
MAYBE = 0, YES, NO,
|
||||
} radius_sends_message_authenticator[MAXRADSERVER];
|
||||
|
||||
static void calc_auth(const void *buf, size_t len, const uint8_t *in, uint8_t *out)
|
||||
{
|
||||
MD5_CTX ctx;
|
||||
|
|
@ -163,7 +167,7 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
uint8_t b[4096]; // RADIUS packet
|
||||
char pass[129];
|
||||
int pl;
|
||||
uint8_t *p;
|
||||
uint8_t *p, *ma = NULL;
|
||||
sessionidt s;
|
||||
|
||||
CSTAT(radiussend);
|
||||
|
|
@ -237,6 +241,16 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
memcpy(b + 4, radius[r].auth, 16);
|
||||
|
||||
p = b + 20;
|
||||
|
||||
if (state == RADIUSAUTH || state == RADIUSJUSTAUTH)
|
||||
{
|
||||
*p = 80; // MessageAuthenticator
|
||||
p[1] = 18; // length
|
||||
ma = p+2;
|
||||
memset(ma, 0, 16); // Zero for the computation
|
||||
p += p[1];
|
||||
}
|
||||
|
||||
if (s)
|
||||
{
|
||||
*p = 1; // user name
|
||||
|
|
@ -464,12 +478,18 @@ void radiussend(uint16_t r, uint8_t state)
|
|||
|
||||
// All AVpairs added
|
||||
*(uint16_t *) (b + 2) = htons(p - b);
|
||||
|
||||
if (state != RADIUSAUTH && state != RADIUSJUSTAUTH)
|
||||
{
|
||||
// Build auth for accounting packet
|
||||
calc_auth(b, p - b, zero, b + 4);
|
||||
memcpy(radius[r].auth, b + 4, 16);
|
||||
}
|
||||
|
||||
// Compute MessageAuthenticator
|
||||
if (ma)
|
||||
MD5_Hmac(ma, b, p-b, config->radiussecret, strlen(config->radiussecret));
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
*(uint32_t *) & addr.sin_addr = config->radiusserver[(radius[r].try - 1) % config->numradiusservers];
|
||||
|
|
@ -587,6 +607,83 @@ void processrad(uint8_t *buf, int len, char socket_index)
|
|||
|
||||
if (radius[r].state == RADIUSAUTH || radius[r].state == RADIUSJUSTAUTH)
|
||||
{
|
||||
// First check MessageAuthenticator
|
||||
{
|
||||
uint8_t *p = buf + 20;
|
||||
uint8_t *e = buf + len;
|
||||
int seen = 0, want;
|
||||
|
||||
for (; p + 2 <= e && p[1] && p + p[1] <= e; p += p[1])
|
||||
{
|
||||
if (*p == 80)
|
||||
{
|
||||
// MessageAuthenticator
|
||||
uint8_t auth[16];
|
||||
uint8_t authcheck[16];
|
||||
uint8_t vector[16];
|
||||
|
||||
/* Set original vector for computation */
|
||||
memcpy(vector, buf+4, 16);
|
||||
memcpy(buf+4, radius[r].auth, 16);
|
||||
|
||||
/* Set authenticator to zero for computation */
|
||||
memcpy(auth, p+2, 16);
|
||||
memset(p+2, 0, 16);
|
||||
|
||||
MD5_Hmac(authcheck, buf, len, config->radiussecret, strlen(config->radiussecret));
|
||||
if (memcmp(auth, authcheck, 16) != 0)
|
||||
{
|
||||
LOG(1, 0, 0, "Incorrect MessageAuthenticator in Access reply (wrong secret in radius config?)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restore vector */
|
||||
memcpy(buf+4, vector, 16);
|
||||
|
||||
/* Restore authenticator */
|
||||
memcpy(p+2, auth, 16);
|
||||
|
||||
seen = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(config->radius_require_message_authenticator, "no"))
|
||||
want = 0;
|
||||
else if (!strcmp(config->radius_require_message_authenticator, "yes"))
|
||||
want = 1;
|
||||
else
|
||||
{
|
||||
if (config->radius_require_message_authenticator[0]
|
||||
&& strcmp(config->radius_require_message_authenticator, "auto"))
|
||||
LOG(1, 0, 0, "Unrecognized radius_require_message_authenticator '%s', assuming auto\n",
|
||||
config->radius_require_message_authenticator);
|
||||
|
||||
int num = radius[r].try % config->numradiusservers;
|
||||
|
||||
switch (radius_sends_message_authenticator[num]) {
|
||||
case YES:
|
||||
want = 1;
|
||||
break;
|
||||
case NO:
|
||||
want = 0;
|
||||
break;
|
||||
case MAYBE:
|
||||
want = seen;
|
||||
if (seen)
|
||||
radius_sends_message_authenticator[num] = YES;
|
||||
else
|
||||
radius_sends_message_authenticator[num] = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (want && !seen)
|
||||
{
|
||||
LOG(1, 0, 0, "Missing MessageAuthenticator in Access reply\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// run post-auth plugin
|
||||
struct param_post_auth packet = {
|
||||
&tunnel[t],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue