summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvenaas <venaas>2007-01-05 15:15:16 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2007-01-05 15:15:16 +0000
commit575d20abb9c2726039ecb3d0dfc9718866953b5f (patch)
tree8792fe9388c6e647f6ec373d296e14a43100d816
parentcb999c284b82a6d50ada6ed23cf2d1d659463090 (diff)
ok, but trying some test code keeping original id, to be changed back later
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@30 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r--radsecproxy.c214
-rw-r--r--radsecproxy.h4
2 files changed, 151 insertions, 67 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index 042c54f..2ecf4b0 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -11,12 +11,8 @@
*/
/* TODO:
- * Among other things:
- * timer based client retrans or maybe no retrans and just a timer...
- * make our server ignore client retrans?
- * tls keep alives
- * routing based on id....
- * need to also encrypt Tunnel-Password and Message-Authenticator attrs
+ * make our server ignore client retrans and do its own instead?
+ * tls keep alives (server status)
* tls certificate validation
*/
@@ -418,10 +414,77 @@ int validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) {
return result;
}
+int checkmessageauth(char *rad, uint8_t *authattr, char *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(secret), EVP_md5(), NULL);
+ HMAC_Update(&hmacctx, rad, RADLEN(rad));
+ HMAC_Final(&hmacctx, hash, &md_len);
+ if (md_len != 16) {
+ printf("message auth computation failed\n");
+ pthread_mutex_unlock(&lock);
+ return 0;
+ }
+
+ if (memcmp(auth, hash, 16)) {
+ printf("message authenticator, wrong value\n");
+ pthread_mutex_unlock(&lock);
+ return 0;
+ }
+
+ pthread_mutex_unlock(&lock);
+ return 1;
+}
+
+int createmessageauth(char *rad, char *authattrval, char *secret) {
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+ static unsigned char first = 1;
+ static HMAC_CTX hmacctx;
+ unsigned int md_len;
+
+ if (!authattrval)
+ return 1;
+
+ pthread_mutex_lock(&lock);
+ if (first) {
+ HMAC_CTX_init(&hmacctx);
+ first = 0;
+ }
+
+ memset(authattrval, 0, 16);
+ md_len = 0;
+ HMAC_Init_ex(&hmacctx, secret, strlen(secret), EVP_md5(), NULL);
+ HMAC_Update(&hmacctx, rad, RADLEN(rad));
+ HMAC_Final(&hmacctx, authattrval, &md_len);
+ if (md_len != 16) {
+ printf("message auth computation failed\n");
+ pthread_mutex_unlock(&lock);
+ return 0;
+ }
+
+ pthread_mutex_unlock(&lock);
+ return 1;
+}
+
void sendrq(struct server *to, struct client *from, struct request *rq) {
int i;
-
+
pthread_mutex_lock(&to->newrq_mutex);
+#if 0
+ /* temporary hack */
for (i = 0; i < MAX_REQUESTS; i++)
if (!to->requests[i].buf)
break;
@@ -430,8 +493,13 @@ void sendrq(struct server *to, struct client *from, struct request *rq) {
pthread_mutex_unlock(&to->newrq_mutex);
return;
}
-
rq->buf[1] = (char)i;
+#endif
+ i = rq->buf[1];
+ if (!createmessageauth(rq->buf, rq->messageauthattrval, to->peer.secret))
+ return;
+ gettimeofday(&rq->expiry, NULL);
+ rq->expiry.tv_sec += 30;
to->requests[i] = *rq;
if (!to->newrq) {
@@ -524,51 +592,6 @@ struct server *id2server(char *id, uint8_t len) {
return NULL;
}
-int messageauth(char *rad, uint8_t *authattr, uint8_t *newauth, struct peer *from, struct peer *to) {
- 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, from->secret, strlen(from->secret), EVP_md5(), NULL);
- HMAC_Update(&hmacctx, rad, RADLEN(rad));
- HMAC_Final(&hmacctx, hash, &md_len);
- if (md_len != 16) {
- printf("message auth computation failed\n");
- pthread_mutex_unlock(&lock);
- return 0;
- }
-
- if (memcmp(auth, hash, 16)) {
- printf("message authenticator, wrong value\n");
- pthread_mutex_unlock(&lock);
- return 0;
- }
-
- md_len = 0;
- HMAC_Init_ex(&hmacctx, to->secret, strlen(to->secret), EVP_md5(), NULL);
- HMAC_Update(&hmacctx, rad, RADLEN(rad));
- HMAC_Final(&hmacctx, authattr, &md_len);
- if (md_len != 16) {
- printf("message auth re-computation failed\n");
- pthread_mutex_unlock(&lock);
- return 0;
- }
-
- pthread_mutex_unlock(&lock);
- return 1;
-}
-
struct server *radsrv(struct request *rq, char *buf, struct client *from) {
uint8_t code, id, *auth, *attr, pwd[128], attrvallen;
uint8_t *usernameattr = NULL, *userpwdattr = NULL, *tunnelpwdattr = NULL, *messageauthattr = NULL;
@@ -637,7 +660,7 @@ struct server *radsrv(struct request *rq, char *buf, struct client *from) {
}
if (messageauthattr && (messageauthattr[RAD_Attr_Length] != 18 ||
- !messageauth(buf, &messageauthattr[RAD_Attr_Value], newauth, &from->peer, &to->peer))) {
+ !checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))) {
printf("radsrv: message authentication failed\n");
return NULL;
}
@@ -689,6 +712,7 @@ struct server *radsrv(struct request *rq, char *buf, struct client *from) {
rq->buf = buf;
rq->from = from;
rq->origid = id;
+ rq->messageauthattrval = (messageauthattr ? &messageauthattr[RAD_Attr_Value] : NULL);
memcpy(rq->origauth, auth, 16);
memcpy(rq->buf + 4, newauth, 16);
return to;
@@ -697,8 +721,8 @@ struct server *radsrv(struct request *rq, char *buf, struct client *from) {
void *clientrd(void *arg) {
struct server *server = (struct server *)arg;
struct client *from;
- int i;
- unsigned char *buf;
+ int i, left;
+ unsigned char *buf, *messageauthattr, *attr;
struct sockaddr_storage fromsa;
struct timeval lastconnecttry;
@@ -711,6 +735,11 @@ void *clientrd(void *arg) {
}
server->connectionok = 1;
+
+ if (*buf != RAD_Access_Accept && *buf != RAD_Access_Reject && *buf != RAD_Access_Challenge) {
+ printf("clientrd: discarding, only accept access accept, access reject and access challenge messages\n");
+ continue;
+ }
i = buf[1]; /* i is the id */
@@ -720,23 +749,59 @@ void *clientrd(void *arg) {
printf("clientrd: no matching request sent with this id, ignoring\n");
continue;
}
-
+
if (server->requests[i].received) {
pthread_mutex_unlock(&server->newrq_mutex);
printf("clientrd: already received, ignoring\n");
continue;
}
-
+
if (!validauth(buf, server->requests[i].buf + 4, server->peer.secret)) {
pthread_mutex_unlock(&server->newrq_mutex);
printf("clientrd: invalid auth, ignoring\n");
continue;
}
+
+ from = server->requests[i].from;
+
+ /* messageauthattr present? */
+ messageauthattr = NULL;
+ left = RADLEN(buf) - 20;
+ attr = buf + 20;
+ while (left > 1) {
+ left -= attr[RAD_Attr_Length];
+ if (left < 0) {
+ printf("radsrv: attribute length exceeds packet length, ignoring packet\n");
+ continue;
+ }
+ if (attr[RAD_Attr_Type] == RAD_Attr_Message_Authenticator) {
+ messageauthattr = attr;
+ break;
+ }
+ attr += attr[RAD_Attr_Length];
+ }
+ if (messageauthattr) {
+ if (messageauthattr[RAD_Attr_Length] != 18)
+ continue;
+ memcpy(buf + 4, server->requests[i].buf + 4, 16);
+ if (!checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], server->peer.secret)) {
+ printf("clientrd: message authentication failed\n");
+ continue;
+ }
+ printf("clientrd: message auth ok\n");
+ }
+
/* once we set received = 1, requests[i] may be reused */
buf[1] = (char)server->requests[i].origid;
memcpy(buf + 4, server->requests[i].origauth, 16);
- from = server->requests[i].from;
+
+ if (messageauthattr) {
+ if (!createmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))
+ continue;
+ printf("clientrd: computed messageauthattr\n");
+ }
+
if (from->peer.type == 'U')
fromsa = server->requests[i].fromsa;
server->requests[i].received = 1;
@@ -746,7 +811,7 @@ void *clientrd(void *arg) {
printf("clientrd: failed to sign message\n");
continue;
}
-
+
printf("clientrd: giving packet back to where it came from\n");
sendreply(from, server, buf, from->peer.type == 'U' ? &fromsa : NULL);
}
@@ -754,9 +819,11 @@ void *clientrd(void *arg) {
void *clientwr(void *arg) {
struct server *server = (struct server *)arg;
+ struct request *rq;
pthread_t clientrdth;
int i;
-
+ struct timeval now;
+
if (server->peer.type == 'U') {
if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0) {
printf("clientwr: connecttoserver failed\n");
@@ -787,17 +854,32 @@ void *clientwr(void *arg) {
break;
}
- /* already received or too many tries */
- if (server->requests[i].received || server->requests[i].tries > 2) {
- free(server->requests[i].buf);
+ gettimeofday(&now, NULL);
+ rq = server->requests + i;
+
+ if (rq->received) {
+ printf("clientwr: removing received packet from queue\n");
+ free(rq->buf);
+ /* setting this to NULL means that it can be reused */
+ rq->buf = NULL;
+ pthread_mutex_unlock(&server->newrq_mutex);
+ continue;
+ }
+ if (now.tv_sec > rq->expiry.tv_sec) {
+ printf("clientwr: removing expired packet from queue\n");
+ free(rq->buf);
/* setting this to NULL means that it can be reused */
- server->requests[i].buf = NULL;
+ rq->buf = NULL;
pthread_mutex_unlock(&server->newrq_mutex);
continue;
}
+
+ if (rq->tries)
+ continue; // not re-sending (yet)
+
+ rq->tries++;
pthread_mutex_unlock(&server->newrq_mutex);
- server->requests[i].tries++;
clientradput(server, server->requests[i].buf);
}
}
diff --git a/radsecproxy.h b/radsecproxy.h
index 55325b0..548ac98 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -18,6 +18,7 @@
#define DEFAULT_TLS_SECRET "mysecret"
#define DEFAULT_UDP_PORT "1812"
#define DEFAULT_TLS_PORT "2083"
+#define REQUEST_TIMEOUT 5
#define RAD_Access_Request 1
#define RAD_Access_Accept 2
@@ -42,8 +43,9 @@ struct request {
unsigned char *buf;
uint8_t tries;
uint8_t received;
- struct timeval timeout;
+ struct timeval expiry;
struct client *from;
+ char *messageauthattrval;
uint8_t origid; /* used by servwr */
char origauth[16]; /* used by servwr */
struct sockaddr_storage fromsa; /* used by udpservwr */