Commit faf8717d authored by venaas's avatar venaas Committed by venaas

lots of changes to radsrv/reply and use of new radmsg stuff

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@373 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent a98c9b73
CFLAGS = -g -Wall -pedantic -pthread CFLAGS = -g -Wall -pedantic -pthread
LDFLAGS = -lssl LDFLAGS = -lssl
OBJ = util.o debug.o list.o hash.o gconfig.o udp.o tcp.o tls.o dtls.o radsecproxy.o OBJ = util.o debug.o list.o hash.o gconfig.o tlv11.o radmsg.o udp.o tcp.o tls.o dtls.o radsecproxy.o
all: radsecproxy all: radsecproxy
......
...@@ -6,6 +6,8 @@ radsecproxy_SOURCES = radsecproxy.c \ ...@@ -6,6 +6,8 @@ radsecproxy_SOURCES = radsecproxy.c \
debug.c \ debug.c \
list.c \ list.c \
hash.c \ hash.c \
tlv11.c \
radmsg.c \
udp.c \ udp.c \
tcp.c \ tcp.c \
tls.c \ tls.c \
...@@ -16,6 +18,8 @@ radsecproxy_SOURCES = radsecproxy.c \ ...@@ -16,6 +18,8 @@ radsecproxy_SOURCES = radsecproxy.c \
util.h \ util.h \
list.h \ list.h \
hash.h \ hash.h \
tlv11.h \
radmsg.h \
udp.h \ udp.h \
tcp.h \ tcp.h \
tls.h \ tls.h \
......
/*
* Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include "list.h"
#include "tlv11.h"
#include "radmsg.h"
#include "debug.h"
#include <pthread.h>
#include <openssl/hmac.h>
#define RADLEN(x) ntohs(((uint16_t *)(x))[1])
void radmsg_free(struct radmsg *msg) {
if (msg) {
freetlvlist(msg->attrs);
free(msg);
}
}
struct radmsg *radmsg_init(uint8_t code, uint8_t id, uint8_t *auth) {
struct radmsg *msg;
msg = malloc(sizeof(struct radmsg));
if (!msg)
return NULL;
msg->attrs = list_create();
if (!msg->attrs) {
free(msg);
return NULL;
}
msg->code = code;
msg->id = id;
memcpy(msg->auth, auth, 16);
return msg;
}
int radmsg_add(struct radmsg *msg, struct tlv *attr) {
if (!msg || !msg->attrs)
return 1;
if (!attr)
return 0;
return list_push(msg->attrs, attr);
}
/* returns first tlv of the given type */
struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
struct list_node *node;
struct tlv *tlv;
if (!msg)
return NULL;
for (node = list_first(msg->attrs); node; node = list_next(node)) {
tlv = (struct tlv *)node->data;
if (tlv->t == type)
return tlv;
}
return NULL;
}
uint8_t *radmsg2buf(struct radmsg *msg) {
struct list_node *node;
struct tlv *tlv;
int size;
uint8_t *buf, *p;
if (!msg || !msg->attrs)
return NULL;
size = 20;
for (node = list_first(msg->attrs); node; node = list_next(node))
size += 2 + ((struct tlv *)node->data)->l;
if (size > 65535)
return NULL;
buf = malloc(size);
if (!buf)
return NULL;
p = buf;
*p++ = msg->code;
*p++ = msg->id;
*(uint16_t *)p = htons(size);
p += 2;
memcpy(p, msg->auth, 16);
p += 16;
for (node = list_first(msg->attrs); node; node = list_next(node)) {
tlv = (struct tlv *)node->data;
p = tlv2buf(p, tlv);
p[-1] += 2;
p += tlv->l;
}
return buf;
}
int _checkmsgauth(unsigned char *rad, uint8_t *authattr, uint8_t *secret) {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned char first = 1;
static HMAC_CTX hmacctx;
unsigned int md_len;
uint8_t auth[16], hash[EVP_MAX_MD_SIZE];
pthread_mutex_lock(&lock);
if (first) {
HMAC_CTX_init(&hmacctx);
first = 0;
}
memcpy(auth, authattr, 16);
memset(authattr, 0, 16);
md_len = 0;
HMAC_Init_ex(&hmacctx, secret, strlen((char *)secret), EVP_md5(), NULL);
HMAC_Update(&hmacctx, rad, RADLEN(rad));
HMAC_Final(&hmacctx, hash, &md_len);
memcpy(authattr, auth, 16);
if (md_len != 16) {
debug(DBG_WARN, "message auth computation failed");
pthread_mutex_unlock(&lock);
return 0;
}
if (memcmp(auth, hash, 16)) {
debug(DBG_WARN, "message authenticator, wrong value");
pthread_mutex_unlock(&lock);
return 0;
}
pthread_mutex_unlock(&lock);
return 1;
}
int _validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned char first = 1;
static EVP_MD_CTX mdctx;
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int len;
int result;
pthread_mutex_lock(&lock);
if (first) {
EVP_MD_CTX_init(&mdctx);
first = 0;
}
len = RADLEN(rad);
result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) &&
EVP_DigestUpdate(&mdctx, rad, 4) &&
EVP_DigestUpdate(&mdctx, reqauth, 16) &&
(len <= 20 || EVP_DigestUpdate(&mdctx, rad + 20, len - 20)) &&
EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) &&
EVP_DigestFinal_ex(&mdctx, hash, &len) &&
len == 16 &&
!memcmp(hash, rad + 4, 16));
pthread_mutex_unlock(&lock);
return result;
}
/* if secret set we also validate message authenticator if present */
struct radmsg *buf2radmsg(uint8_t *buf, uint8_t *secret, uint8_t *rqauth) {
struct radmsg *msg;
uint8_t t, l, *v, *p, auth[16];
uint16_t len;
struct tlv *attr;
len = RADLEN(buf);
if (len < 20)
return NULL;
if (secret && buf[0] == RAD_Accounting_Request) {
memset(auth, 0, 16);
if (!_validauth(buf, auth, secret)) {
debug(DBG_WARN, "buf2radmsg: Accounting-Request message authentication failed");
return NULL;
}
}
if (rqauth && !_validauth(buf, rqauth, secret)) {
debug(DBG_WARN, "buf2radmsg: Invalid auth, ignoring reply");
return NULL;
}
msg = radmsg_init(buf[0], buf[1], (uint8_t *)buf + 4);
if (!msg)
return NULL;
p = buf + 20;
while (p - buf + 2 <= len) {
t = *p++;
l = *p++;
if (l < 2) {
debug(DBG_WARN, "buf2radmsg: invalid attribute length %d", l);
radmsg_free(msg);
return NULL;
}
l -= 2;
if (l) {
if (p - buf + l > len) {
debug(DBG_WARN, "buf2radmsg: attribute length %d exceeds packet length", l + 2);
radmsg_free(msg);
return NULL;
}
v = p;
p += l;
}
if (t == RAD_Attr_Message_Authenticator && secret) {
if (rqauth)
memcpy(buf + 4, rqauth, 16);
if (l != 16 || !_checkmsgauth(buf, v, secret)) {
debug(DBG_WARN, "buf2radmsg: message authentication failed");
if (rqauth)
memcpy(buf + 4, msg->auth, 16);
radmsg_free(msg);
return NULL;
}
if (rqauth)
memcpy(buf + 4, msg->auth, 16);
debug(DBG_DBG, "buf2radmsg: message auth ok");
}
attr = maketlv(t, l, v);
if (!attr || !radmsg_add(msg, attr)) {
freetlv(attr);
radmsg_free(msg);
return NULL;
}
}
return msg;
}
/*
* Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*/
#define RAD_Access_Request 1
#define RAD_Access_Accept 2
#define RAD_Access_Reject 3
#define RAD_Accounting_Request 4
#define RAD_Accounting_Response 5
#define RAD_Access_Challenge 11
#define RAD_Status_Server 12
#define RAD_Status_Client 13
#define RAD_Attr_User_Name 1
#define RAD_Attr_User_Password 2
#define RAD_Attr_Reply_Message 18
#define RAD_Attr_Vendor_Specific 26
#define RAD_Attr_Calling_Station_Id 31
#define RAD_Attr_Tunnel_Password 69
#define RAD_Attr_Message_Authenticator 80
#define RAD_VS_ATTR_MS_MPPE_Send_Key 16
#define RAD_VS_ATTR_MS_MPPE_Recv_Key 17
struct radmsg {
uint8_t code;
uint8_t id;
uint8_t auth[20];
struct list *attrs;
};
void radmsg_free(struct radmsg *);
struct radmsg *radmsg_init(uint8_t, uint8_t, uint8_t *);
int radmsg_add(struct radmsg *, struct tlv *);
struct tlv *radmsg_gettype(struct radmsg *, uint8_t);
uint8_t *radmsg2buf(struct radmsg *msg);
struct radmsg *buf2radmsg(uint8_t *, uint8_t *, uint8_t *);
This diff is collapsed.
...@@ -17,31 +17,12 @@ ...@@ -17,31 +17,12 @@
#define MAX_CERT_DEPTH 5 #define MAX_CERT_DEPTH 5
#define STATUS_SERVER_PERIOD 25 #define STATUS_SERVER_PERIOD 25
#define IDLE_TIMEOUT 300 #define IDLE_TIMEOUT 300
#define RAD_Access_Request 1
#define RAD_Access_Accept 2
#define RAD_Access_Reject 3
#define RAD_Accounting_Request 4
#define RAD_Accounting_Response 5
#define RAD_Access_Challenge 11
#define RAD_Status_Server 12
#define RAD_Status_Client 13
#define RAD_UDP 0 #define RAD_UDP 0
#define RAD_TLS 1 #define RAD_TLS 1
#define RAD_TCP 2 #define RAD_TCP 2
#define RAD_DTLS 3 #define RAD_DTLS 3
#define RAD_Attr_User_Name 1
#define RAD_Attr_User_Password 2
#define RAD_Attr_Reply_Message 18
#define RAD_Attr_Vendor_Specific 26
#define RAD_Attr_Calling_Station_Id 31
#define RAD_Attr_Tunnel_Password 69
#define RAD_Attr_Message_Authenticator 80
#define RAD_VS_ATTR_MS_MPPE_Send_Key 16
#define RAD_VS_ATTR_MS_MPPE_Recv_Key 17
struct options { struct options {
char **listenudp; char **listenudp;
char **listentcp; char **listentcp;
...@@ -166,12 +147,6 @@ struct tls { ...@@ -166,12 +147,6 @@ struct tls {
SSL_CTX *dtlsctx; SSL_CTX *dtlsctx;
}; };
struct attribute {
uint8_t t;
uint8_t l;
uint8_t *v;
};
struct modattr { struct modattr {
uint8_t t; uint8_t t;
char *replacement; char *replacement;
......
/*
* Copyright (C) 2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*/
#include <stdint.h>
#include "list.h"
#include "tlv11.h"
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
struct tlv *maketlv(uint8_t t, uint8_t l, void *v) {
struct tlv *tlv;
tlv = malloc(sizeof(struct tlv));
if (!tlv)
return NULL;
tlv->t = t;
tlv->l = l;
if (l && v) {
tlv->v = malloc(l);
if (!tlv->v) {
free(tlv);
return NULL;
}
memcpy(tlv->v, v, l);
} else
tlv->v = NULL;
return tlv;
}
struct tlv *copytlv(struct tlv *in) {
return in ? maketlv(in->t, in->l, in->v) : NULL;
}
void freetlv(struct tlv *tlv) {
if (tlv) {
free(tlv->v);
free(tlv);
}
}
int eqtlv(struct tlv *t1, struct tlv *t2) {
if (!t1 || !t2)
return t1 == t2;
if (t1->t != t2->t || t1->l != t2->l)
return 0;
return memcmp(t1->v, t2->v, t1->l) == 0;
}
struct list *copytlvlist(struct list *tlvs) {
struct list *out;
struct list_node *node;
if (!tlvs)
return NULL;
out = list_create();
if (!out)
return NULL;
for (node = list_first(tlvs); node; node = list_next(node)) {
if (!list_push(out, copytlv((struct tlv *)node->data))) {
freetlvlist(out);
return NULL;
}
}
return out;
}
void freetlvlist(struct list *tlvs) {
struct tlv *tlv;
while ((tlv = (struct tlv *)list_shift(tlvs)))
freetlv(tlv);
list_destroy(tlvs);
}
void rmtlv(struct list *tlvs, uint8_t t) {
struct list_node *n, *p;
struct tlv *tlv;
p = NULL;
n = list_first(tlvs);
while (n) {
tlv = (struct tlv *)n->data;
if (tlv->t == t) {
list_removedata(tlvs, tlv);
freetlv(tlv);
n = p ? list_next(p) : list_first(tlvs);
} else {
p = n;
n = list_next(n);
}
}
}
uint8_t *tlv2str(struct tlv *tlv) {
uint8_t *s = malloc(tlv->l + 1);
if (s) {
memcpy(s, tlv->v, tlv->l);
s[tlv->l] = '\0';
}
return s;
}
uint8_t *tlv2buf(uint8_t *p, struct tlv *tlv) {
*p++ = tlv->t;
*p++ = tlv->l;
if (tlv->l) {
if (tlv->v)
memcpy(p, tlv->v, tlv->l);
else
memset(p, 0, tlv->l);
}
return p;
}
/*
* Copyright (C) 2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*/
struct tlv {
uint8_t t;
uint8_t l;
uint8_t *v;
};
struct tlv *maketlv(uint8_t, uint8_t, void *);
struct tlv *copytlv(struct tlv *);
void freetlv(struct tlv *);
int eqtlv(struct tlv *, struct tlv *);
struct list *copytlvlist(struct list *);
void freetlvlist(struct list *);
void rmtlv(struct list *, uint8_t);
uint8_t *tlv2str(struct tlv *tlv);
uint8_t *tlv2buf(uint8_t *, struct tlv *tlv);
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include "debug.h" #include "debug.h"
#include "list.h" #include "list.h"
#include "tlv11.h"
#include "radmsg.h"
#include "util.h" #include "util.h"
#include "radsecproxy.h" #include "radsecproxy.h"
#include "tls.h" #include "tls.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment