X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=radmsg.c;h=0a46e71442d11df77be922851115e2e4b77b7a4e;hb=937144b230752ac640e611cabb57387f613997bc;hp=26f8fbe7e8f11c41c6c6709dd242e4fc3f477ba4;hpb=faf8717dcbc9c2e3ed1892402133b6c9663a5e7d;p=libradsec.git diff --git a/radmsg.c b/radmsg.c index 26f8fbe..0a46e71 100644 --- a/radmsg.c +++ b/radmsg.c @@ -6,7 +6,11 @@ * copyright notice and this permission notice appear in all copies. */ +#ifdef SYS_SOLARIS9 +#include +#else #include +#endif #include #include #include @@ -16,6 +20,7 @@ #include "debug.h" #include #include +#include #define RADLEN(x) ntohs(((uint16_t *)(x))[1]) @@ -28,18 +33,24 @@ void radmsg_free(struct radmsg *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; + memset(msg, 0, sizeof(struct radmsg)); msg->attrs = list_create(); if (!msg->attrs) { free(msg); return NULL; - } + } msg->code = code; msg->id = id; - memcpy(msg->auth, auth, 16); + if (auth) + memcpy(msg->auth, auth, 16); + else if (!RAND_bytes(msg->auth, 16)) { + free(msg); + return NULL; + } return msg; } @@ -66,47 +77,13 @@ struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) { 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); @@ -130,8 +107,8 @@ int _checkmsgauth(unsigned char *rad, uint8_t *authattr, uint8_t *secret) { debug(DBG_WARN, "message authenticator, wrong value"); pthread_mutex_unlock(&lock); return 0; - } - + } + pthread_mutex_unlock(&lock); return 1; } @@ -143,7 +120,7 @@ int _validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) { unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int len; int result; - + pthread_mutex_lock(&lock); if (first) { EVP_MD_CTX_init(&mdctx); @@ -151,7 +128,7 @@ int _validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) { } len = RADLEN(rad); - + result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) && EVP_DigestUpdate(&mdctx, rad, 4) && EVP_DigestUpdate(&mdctx, reqauth, 16) && @@ -163,14 +140,113 @@ int _validauth(unsigned char *rad, unsigned char *reqauth, unsigned char *sec) { pthread_mutex_unlock(&lock); return result; } - + +int _createmessageauth(unsigned char *rad, unsigned char *authattrval, uint8_t *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((char *)secret), EVP_md5(), NULL); + HMAC_Update(&hmacctx, rad, RADLEN(rad)); + HMAC_Final(&hmacctx, authattrval, &md_len); + if (md_len != 16) { + debug(DBG_WARN, "message auth computation failed"); + pthread_mutex_unlock(&lock); + return 0; + } + pthread_mutex_unlock(&lock); + return 1; +} + +int _radsign(unsigned char *rad, unsigned char *sec) { + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static unsigned char first = 1; + static EVP_MD_CTX mdctx; + unsigned int md_len; + int result; + + pthread_mutex_lock(&lock); + if (first) { + EVP_MD_CTX_init(&mdctx); + first = 0; + } + + result = (EVP_DigestInit_ex(&mdctx, EVP_md5(), NULL) && + EVP_DigestUpdate(&mdctx, rad, RADLEN(rad)) && + EVP_DigestUpdate(&mdctx, sec, strlen((char *)sec)) && + EVP_DigestFinal_ex(&mdctx, rad + 4, &md_len) && + md_len == 16); + pthread_mutex_unlock(&lock); + return result; +} + +uint8_t *radmsg2buf(struct radmsg *msg, uint8_t *secret) { + struct list_node *node; + struct tlv *tlv; + int size; + uint8_t *buf, *p, *msgauth = NULL; + + 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; + if (tlv->t == RAD_Attr_Message_Authenticator && secret) + msgauth = p; + p += tlv->l; + } + if (msgauth && !_createmessageauth(buf, msgauth, secret)) { + free(buf); + return NULL; + } + if (secret) { + if ((msg->code == RAD_Access_Accept || msg->code == RAD_Access_Reject || msg->code == RAD_Access_Challenge || msg->code == RAD_Accounting_Response || msg->code == RAD_Accounting_Request) && !_radsign(buf, secret)) { + free(buf); + return NULL; + } + if (msg->code == RAD_Accounting_Request) + memcpy(msg->auth, buf + 4, 16); + } + return buf; +} + /* 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]; + uint8_t t, l, *v = NULL, *p, auth[16]; uint16_t len; struct tlv *attr; - + len = RADLEN(buf); if (len < 20) return NULL; @@ -187,7 +263,7 @@ struct radmsg *buf2radmsg(uint8_t *buf, uint8_t *secret, uint8_t *rqauth) { 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; @@ -211,7 +287,7 @@ struct radmsg *buf2radmsg(uint8_t *buf, uint8_t *secret, uint8_t *rqauth) { v = p; p += l; } - + if (t == RAD_Attr_Message_Authenticator && secret) { if (rqauth) memcpy(buf + 4, rqauth, 16); @@ -236,3 +312,7 @@ struct radmsg *buf2radmsg(uint8_t *buf, uint8_t *secret, uint8_t *rqauth) { } return msg; } + +/* Local Variables: */ +/* c-file-style: "stroustrup" */ +/* End: */