aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa_supplicant/radius.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa_supplicant/radius.c')
-rw-r--r--contrib/wpa_supplicant/radius.c219
1 files changed, 127 insertions, 92 deletions
diff --git a/contrib/wpa_supplicant/radius.c b/contrib/wpa_supplicant/radius.c
index 5fd323d65c85..ce79a62c141c 100644
--- a/contrib/wpa_supplicant/radius.c
+++ b/contrib/wpa_supplicant/radius.c
@@ -16,18 +16,20 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
-#include <netinet/in.h>
#include <string.h>
-#include <sys/ioctl.h>
#include <signal.h>
#include <sys/time.h>
+#ifndef CONFIG_NATIVE_WINDOWS
+#include <netinet/in.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-
+#endif /* CONFIG_NATIVE_WINDOWS */
#include "common.h"
#include "radius.h"
#include "md5.h"
+#include "crypto.h"
struct radius_msg *radius_msg_new(u8 code, u8 identifier)
@@ -124,8 +126,10 @@ static const char *radius_code_string(u8 code)
struct radius_attr_type {
u8 type;
char *name;
- enum { RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP,
- RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32 } data_type;
+ enum {
+ RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP,
+ RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32, RADIUS_ATTR_IPV6
+ } data_type;
};
static struct radius_attr_type radius_attrs[] =
@@ -179,8 +183,8 @@ static struct radius_attr_type radius_attrs[] =
{ RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator",
RADIUS_ATTR_UNDIST },
{ RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval",
- RADIUS_ATTR_INT32 }
-
+ RADIUS_ATTR_INT32 },
+ { RADIUS_ATTR_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", RADIUS_ATTR_IPV6 },
};
#define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0]))
@@ -231,6 +235,19 @@ static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
printf(" Invalid IP address length %d\n", len);
break;
+#ifdef CONFIG_IPV6
+ case RADIUS_ATTR_IPV6:
+ if (len == 16) {
+ char buf[128];
+ const char *atxt;
+ struct in6_addr *addr = (struct in6_addr *) pos;
+ atxt = inet_ntop(AF_INET6, addr, buf, sizeof(buf));
+ printf(" Value: %s\n", atxt ? atxt : "?");
+ } else
+ printf(" Invalid IPv6 address length %d\n", len);
+ break;
+#endif /* CONFIG_IPV6 */
+
case RADIUS_ATTR_HEXDUMP:
case RADIUS_ATTR_UNDIST:
printf(" Value:");
@@ -242,7 +259,8 @@ static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
case RADIUS_ATTR_INT32:
if (len == 4) {
u32 *val = (u32 *) pos;
- printf(" Value: %d\n", ntohl(*val));
+ printf(" Value: %u\n",
+ (unsigned int) ntohl(*val));
} else
printf(" Invalid INT32 length %d\n", len);
break;
@@ -302,7 +320,8 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
{
u8 auth[MD5_MAC_LEN];
struct radius_attr_hdr *attr;
- MD5_CTX context;
+ const u8 *addr[4];
+ size_t len[4];
memset(auth, 0, MD5_MAC_LEN);
attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
@@ -318,13 +337,15 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
(u8 *) (attr + 1));
/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
- MD5Init(&context);
- MD5Update(&context, (u8 *) msg->hdr, 1 + 1 + 2);
- MD5Update(&context, req_authenticator, MD5_MAC_LEN);
- MD5Update(&context, (u8 *) (msg->hdr + 1),
- msg->buf_used - sizeof(*msg->hdr));
- MD5Update(&context, secret, secret_len);
- MD5Final(msg->hdr->authenticator, &context);
+ addr[0] = (u8 *) msg->hdr;
+ len[0] = 1 + 1 + 2;
+ addr[1] = req_authenticator;
+ len[1] = MD5_MAC_LEN;
+ addr[2] = (u8 *) (msg->hdr + 1);
+ len[2] = msg->buf_used - sizeof(*msg->hdr);
+ addr[3] = secret;
+ len[3] = secret_len;
+ md5_vector(4, addr, len, msg->hdr->authenticator);
if (msg->buf_used > 0xffff) {
printf("WARNING: too long RADIUS message (%lu)\n",
@@ -338,14 +359,16 @@ int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret,
size_t secret_len)
{
- MD5_CTX context;
+ const u8 *addr[2];
+ size_t len[2];
msg->hdr->length = htons(msg->buf_used);
memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
- MD5Init(&context);
- MD5Update(&context, msg->buf, msg->buf_used);
- MD5Update(&context, secret, secret_len);
- MD5Final(msg->hdr->authenticator, &context);
+ addr[0] = msg->buf;
+ len[0] = msg->buf_used;
+ addr[1] = secret;
+ len[1] = secret_len;
+ md5_vector(2, addr, len, msg->hdr->authenticator);
if (msg->buf_used > 0xffff) {
printf("WARNING: too long RADIUS messages (%lu)\n",
@@ -378,7 +401,7 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg,
struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
- u8 *data, size_t data_len)
+ const u8 *data, size_t data_len)
{
size_t buf_needed;
struct radius_attr_hdr *attr;
@@ -493,9 +516,9 @@ struct radius_msg *radius_msg_parse(const u8 *data, size_t len)
}
-int radius_msg_add_eap(struct radius_msg *msg, u8 *data, size_t data_len)
+int radius_msg_add_eap(struct radius_msg *msg, const u8 *data, size_t data_len)
{
- u8 *pos = data;
+ const u8 *pos = data;
size_t left = data_len;
while (left > 0) {
@@ -605,10 +628,11 @@ int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
}
-int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len,
- struct radius_msg *sent_msg)
+int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
+ size_t secret_len, struct radius_msg *sent_msg, int auth)
{
- MD5_CTX context;
+ const u8 *addr[4];
+ size_t len[4];
u8 hash[MD5_MAC_LEN];
if (sent_msg == NULL) {
@@ -616,19 +640,22 @@ int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len,
return 1;
}
- if (radius_msg_verify_msg_auth(msg, secret, secret_len,
+ if (auth &&
+ radius_msg_verify_msg_auth(msg, secret, secret_len,
sent_msg->hdr->authenticator)) {
return 1;
}
/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
- MD5Init(&context);
- MD5Update(&context, (u8 *) msg->hdr, 1 + 1 + 2);
- MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN);
- MD5Update(&context, (u8 *) (msg->hdr + 1),
- msg->buf_used - sizeof(*msg->hdr));
- MD5Update(&context, secret, secret_len);
- MD5Final(hash, &context);
+ addr[0] = (u8 *) msg->hdr;
+ len[0] = 1 + 1 + 2;
+ addr[1] = sent_msg->hdr->authenticator;
+ len[1] = MD5_MAC_LEN;
+ addr[2] = (u8 *) (msg->hdr + 1);
+ len[2] = msg->buf_used - sizeof(*msg->hdr);
+ addr[3] = secret;
+ len[3] = secret_len;
+ md5_vector(4, addr, len, hash);
if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
printf("Response Authenticator invalid!\n");
return 1;
@@ -639,29 +666,6 @@ int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len,
}
-int radius_msg_verify_acct(struct radius_msg *msg, u8 *secret,
- size_t secret_len, struct radius_msg *sent_msg)
-{
- MD5_CTX context;
- u8 hash[MD5_MAC_LEN];
-
- MD5Init(&context);
- MD5Update(&context, msg->buf, 4);
- MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN);
- if (msg->buf_used > sizeof(struct radius_hdr))
- MD5Update(&context, msg->buf + sizeof(struct radius_hdr),
- msg->buf_used - sizeof(struct radius_hdr));
- MD5Update(&context, secret, secret_len);
- MD5Final(hash, &context);
- if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
- printf("Response Authenticator invalid!\n");
- return 1;
- }
-
- return 0;
-}
-
-
int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
u8 type)
{
@@ -694,16 +698,19 @@ void radius_msg_make_authenticator(struct radius_msg *msg,
u8 *data, size_t len)
{
struct timeval tv;
- MD5_CTX context;
long int l;
+ const u8 *addr[3];
+ size_t elen[3];
gettimeofday(&tv, NULL);
l = random();
- MD5Init(&context);
- MD5Update(&context, (u8 *) &tv, sizeof(tv));
- MD5Update(&context, data, len);
- MD5Update(&context, (u8 *) &l, sizeof(l));
- MD5Final(msg->hdr->authenticator, &context);
+ addr[0] = (u8 *) &tv;
+ elen[0] = sizeof(tv);
+ addr[1] = data;
+ elen[1] = len;
+ addr[2] = (u8 *) &l;
+ elen[2] = sizeof(l);
+ md5_vector(3, addr, elen, msg->hdr->authenticator);
}
@@ -780,8 +787,9 @@ static u8 * decrypt_ms_key(const u8 *key, size_t len,
const u8 *pos;
size_t left, plen;
u8 hash[MD5_MAC_LEN];
- MD5_CTX context;
int i, first = 1;
+ const u8 *addr[3];
+ size_t elen[3];
/* key: 16-bit salt followed by encrypted key info */
@@ -804,15 +812,19 @@ static u8 * decrypt_ms_key(const u8 *key, size_t len,
/* b(1) = MD5(Secret + Request-Authenticator + Salt)
* b(i) = MD5(Secret + c(i - 1)) for i > 1 */
- MD5Init(&context);
- MD5Update(&context, secret, secret_len);
+ addr[0] = secret;
+ elen[0] = secret_len;
if (first) {
- MD5Update(&context, req_authenticator, MD5_MAC_LEN);
- MD5Update(&context, key, 2); /* Salt */
- first = 0;
- } else
- MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN);
- MD5Final(hash, &context);
+ addr[1] = req_authenticator;
+ elen[1] = MD5_MAC_LEN;
+ addr[2] = key;
+ elen[2] = 2; /* Salt */
+ } else {
+ addr[1] = pos - MD5_MAC_LEN;
+ elen[1] = MD5_MAC_LEN;
+ }
+ md5_vector(first ? 3 : 2, addr, elen, hash);
+ first = 0;
for (i = 0; i < MD5_MAC_LEN; i++)
*ppos++ = *pos++ ^ hash[i];
@@ -845,7 +857,8 @@ static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt,
{
int i, len, first = 1;
u8 hash[MD5_MAC_LEN], saltbuf[2], *pos;
- MD5_CTX context;
+ const u8 *addr[3];
+ size_t _len[3];
saltbuf[0] = salt >> 8;
saltbuf[1] = salt;
@@ -864,16 +877,19 @@ static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt,
while (len > 0) {
/* b(1) = MD5(Secret + Request-Authenticator + Salt)
* b(i) = MD5(Secret + c(i - 1)) for i > 1 */
- MD5Init(&context);
- MD5Update(&context, secret, secret_len);
+ addr[0] = secret;
+ _len[0] = secret_len;
if (first) {
- MD5Update(&context, req_authenticator, MD5_MAC_LEN);
- MD5Update(&context, saltbuf, sizeof(saltbuf));
- first = 0;
+ addr[1] = req_authenticator;
+ _len[1] = MD5_MAC_LEN;
+ addr[2] = saltbuf;
+ _len[2] = sizeof(saltbuf);
} else {
- MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN);
+ addr[1] = pos - MD5_MAC_LEN;
+ _len[1] = MD5_MAC_LEN;
}
- MD5Final(hash, &context);
+ md5_vector(first ? 3 : 2, addr, _len, hash);
+ first = 0;
for (i = 0; i < MD5_MAC_LEN; i++)
*pos++ ^= hash[i];
@@ -1037,8 +1053,9 @@ radius_msg_add_attr_user_password(struct radius_msg *msg,
{
u8 buf[128];
int padlen, i, pos;
- MD5_CTX context;
size_t buf_len;
+ const u8 *addr[2];
+ size_t len[2];
u8 hash[16];
if (data_len > 128)
@@ -1054,20 +1071,22 @@ radius_msg_add_attr_user_password(struct radius_msg *msg,
buf_len += padlen;
}
- MD5Init(&context);
- MD5Update(&context, secret, secret_len);
- MD5Update(&context, msg->hdr->authenticator, 16);
- MD5Final(hash, &context);
+ addr[0] = secret;
+ len[0] = secret_len;
+ addr[1] = msg->hdr->authenticator;
+ len[1] = 16;
+ md5_vector(2, addr, len, hash);
for (i = 0; i < 16; i++)
buf[i] ^= hash[i];
pos = 16;
while (pos < buf_len) {
- MD5Init(&context);
- MD5Update(&context, secret, secret_len);
- MD5Update(&context, &buf[pos - 16], 16);
- MD5Final(hash, &context);
+ addr[0] = secret;
+ len[0] = secret_len;
+ addr[1] = &buf[pos - 16];
+ len[1] = 16;
+ md5_vector(2, addr, len, hash);
for (i = 0; i < 16; i++)
buf[pos + i] ^= hash[i];
@@ -1104,13 +1123,14 @@ int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len)
int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
- size_t *len)
+ size_t *len, const u8 *start)
{
int i;
struct radius_attr_hdr *attr = NULL;
for (i = 0; i < msg->attr_used; i++) {
- if (msg->attrs[i]->type == type) {
+ if (msg->attrs[i]->type == type &&
+ (start == NULL || (u8 *) msg->attrs[i] > start)) {
attr = msg->attrs[i];
break;
}
@@ -1123,3 +1143,18 @@ int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf,
*len = attr->length - sizeof(*attr);
return 0;
}
+
+
+int radius_msg_count_attr(struct radius_msg *msg, u8 type, int min_len)
+{
+ int i, count;
+
+ for (count = 0, i = 0; i < msg->attr_used; i++) {
+ if (msg->attrs[i]->type == type &&
+ msg->attrs[i]->length >=
+ sizeof(struct radius_attr_hdr) + min_len)
+ count++;
+ }
+
+ return count;
+}