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

added logging to file and syslog (need to add support for specifying facility)

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@72 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent f32f6b2e
......@@ -10,22 +10,101 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <sys/time.h>
#include <syslog.h>
#include <errno.h>
#include "debug.h"
static char *debug_ident = NULL;
static uint8_t debug_level = DBG_WARN;
static FILE *debug_file = NULL;
static int debug_syslogfacility = 0;
void debug_init(char *ident) {
debug_file = stderr;
setvbuf(debug_file, NULL, _IONBF, 0);
debug_ident = ident;
}
void debug_set_level(uint8_t level) {
debug_level = level;
}
uint8_t debug_get_level() {
return debug_level;
}
int debug_set_destination(char *dest) {
extern int errno;
if (!strncasecmp(dest, "file:///", 8)) {
debug_file = fopen(dest + 7, "a");
if (!debug_file)
debugx(1, DBG_ERR, "Failed to open logfile %s\n%s",
dest + 7, strerror(errno));
setvbuf(debug_file, NULL, _IONBF, 0);
return 1;
}
if (!strcasecmp(dest, "x-syslog://")) {
debug_syslogfacility = LOG_DAEMON;
openlog(debug_ident, LOG_PID, debug_syslogfacility);
return 1;
}
return 0;
}
void debug_logit(uint8_t level, const char *format, va_list ap) {
struct timeval now;
char *timebuf;
int priority;
if (debug_syslogfacility) {
switch (level) {
case DBG_INFO:
priority = LOG_INFO;
break;
case DBG_WARN:
priority = LOG_WARNING;
break;
case DBG_ERR:
priority = LOG_ERR;
break;
default:
priority = LOG_DEBUG;
}
vsyslog(priority, format, ap);
} else {
timebuf = malloc(256);
if (timebuf) {
gettimeofday(&now, NULL);
ctime_r(&now.tv_sec, timebuf);
timebuf[strlen(timebuf) - 1] = '\0';
fprintf(debug_file, "%s: ", timebuf);
free(timebuf);
}
vfprintf(debug_file, format, ap);
fprintf(debug_file, "\n");
}
}
void debug(uint8_t level, char *format, ...) {
va_list ap;
if (level < debug_level)
return;
va_start(ap, format);
debug_logit(level, format, ap);
va_end(ap);
}
void debugx(int status, uint8_t level, char *format, ...) {
if (level >= debug_level) {
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
debug_logit(level, format, ap);
va_end(ap);
fprintf(stderr, "\n");
}
if (level >= DBG_ERR)
exit(1);
exit(status);
}
......@@ -10,5 +10,9 @@
#define DBG_WARN 32
#define DBG_ERR 64
void debug_init(char *ident);
void debug_set_level(uint8_t level);
uint8_t debug_get_level();
void debug(uint8_t level, char *format, ...);
void debugx(int status, uint8_t level, char *format, ...);
int debug_set_destination(char *dest);
......@@ -110,26 +110,28 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) {
if (!ok) {
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
printf("verify error: num=%d:%s:depth=%d:%s\n", err, X509_verify_cert_error_string(err), depth, buf);
debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf);
switch (err) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
printf("issuer=%s\n", buf);
debug(DBG_WARN, "\tIssuer=%s", buf);
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
printf("Certificate not yet valid\n");
debug(DBG_WARN, "\tCertificate not yet valid");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
printf("Certificate has expired\n");
debug(DBG_WARN, "Certificate has expired");
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
printf("Certificate no longer valid (after notAfter)\n");
debug(DBG_WARN, "Certificate no longer valid (after notAfter)");
break;
}
}
/* printf("certificate verify returns %d\n", ok); */
#ifdef DEBUG
printf("certificate verify returns %d\n", ok);
#endif
return ok;
}
......@@ -139,10 +141,10 @@ SSL_CTX *ssl_init() {
unsigned long error;
if (!options.tlscertificatefile || !options.tlscertificatekeyfile)
debug(DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified for TLS");
debugx(1, DBG_ERR, "TLSCertificateFile and TLSCertificateKeyFile must be specified for TLS");
if (!options.tlscacertificatefile && !options.tlscacertificatepath)
debug(DBG_ERR, "CA Certificate file/path need to be configured");
debugx(1, DBG_ERR, "CA Certificate file/path need to be configured");
ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
......@@ -178,10 +180,12 @@ SSL_CTX *ssl_init() {
}
while ((error = ERR_get_error()))
debug(DBG_WARN, "SSL: %s", ERR_error_string(error, NULL));
debug(DBG_ERR, "SSL: %s", ERR_error_string(error, NULL));
debug(DBG_ERR, "Error initialising SSL/TLS");
exit(1);
}
#ifdef DEBUG
void printauth(char *s, unsigned char *t) {
int i;
printf("%s:", s);
......@@ -189,6 +193,7 @@ void printauth(char *s, unsigned char *t) {
printf("%02x ", t[i]);
printf("\n");
}
#endif
int resolvepeer(struct peer *peer, int ai_flags) {
struct addrinfo hints, *addrinfo;
......@@ -215,12 +220,12 @@ int connecttoserver(struct addrinfo *addrinfo) {
for (res = addrinfo; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
err("connecttoserver: socket failed");
debug(DBG_WARN, "connecttoserver: socket failed");
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) == 0)
break;
err("connecttoserver: connect failed");
debug(DBG_WARN, "connecttoserver: connect failed");
close(s);
s = -1;
}
......@@ -234,13 +239,13 @@ int bindtoaddr(struct addrinfo *addrinfo) {
for (res = addrinfo; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
err("bindtoaddr: socket failed");
debug(DBG_WARN, "bindtoaddr: socket failed");
continue;
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (!bind(s, res->ai_addr, res->ai_addrlen))
return s;
err("bindtoaddr: bind failed");
debug(DBG_WARN, "bindtoaddr: bind failed");
close(s);
}
return -1;
......@@ -323,37 +328,37 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
for (;;) {
cnt = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
if (cnt == -1) {
err("radudpget: recv failed");
debug(DBG_WARN, "radudpget: recv failed");
continue;
}
printf("radudpget: got %d bytes from %s\n", cnt, addr2string((struct sockaddr *)&from, fromlen));
debug(DBG_INFO, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
if (cnt < 20) {
printf("radudpget: packet too small\n");
debug(DBG_WARN, "radudpget: packet too small");
continue;
}
len = RADLEN(buf);
if (cnt < len) {
printf("radudpget: packet smaller than length field in radius header\n");
debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
continue;
}
if (cnt > len)
printf("radudpget: packet was padded with %d bytes\n", cnt - len);
debug(DBG_INFO, "radudpget: packet was padded with %d bytes", cnt - len);
f = (client
? (void *)find_client('U', (struct sockaddr *)&from, *client)
: (void *)find_server('U', (struct sockaddr *)&from, *server));
if (!f) {
printf("radudpget: got packet from wrong or unknown UDP peer, ignoring\n");
debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer, ignoring");
continue;
}
rad = malloc(len);
if (rad)
break;
err("radudpget: malloc failed");
debug(DBG_ERR, "radudpget: malloc failed");
}
memcpy(rad, buf, len);
if (client)
......@@ -366,24 +371,23 @@ unsigned char *radudpget(int s, struct client **client, struct server **server,
}
int tlsverifycert(struct peer *peer) {
int i, l, loc;
int l, loc;
X509 *cert;
X509_NAME *nm;
X509_NAME_ENTRY *e;
unsigned char *v;
unsigned long error;
#if 1
if (SSL_get_verify_result(peer->ssl) != X509_V_OK) {
printf("tlsverifycert: basic validation failed\n");
debug(DBG_ERR, "tlsverifycert: basic validation failed");
while ((error = ERR_get_error()))
err("clientwr: TLS: %s", ERR_error_string(error, NULL));
debug(DBG_ERR, "tlsverifycert: TLS: %s", ERR_error_string(error, NULL));
return 0;
}
#endif
cert = SSL_get_peer_certificate(peer->ssl);
if (!cert) {
printf("tlsverifycert: failed to obtain certificate\n");
debug(DBG_ERR, "tlsverifycert: failed to obtain certificate");
return 0;
}
nm = X509_get_subject_name(cert);
......@@ -396,15 +400,20 @@ int tlsverifycert(struct peer *peer) {
l = ASN1_STRING_to_UTF8(&v, X509_NAME_ENTRY_get_data(e));
if (l < 0)
continue;
printf("cn: ");
for (i = 0; i < l; i++)
printf("%c", v[i]);
printf("\n");
#ifdef DEBUG
{
int i;
printf("cn: ");
for (i = 0; i < l; i++)
printf("%c", v[i]);
printf("\n");
}
#endif
if (l == strlen(peer->host) && !strncasecmp(peer->host, (char *)v, l)) {
printf("tlsverifycert: Found cn matching host %s, All OK\n", peer->host);
debug(DBG_INFO, "tlsverifycert: Found cn matching host %s, All OK", peer->host);
return 1;
}
printf("tlsverifycert: cn not matching host %s\n", peer->host);
debug(DBG_ERR, "tlsverifycert: cn not matching host %s", peer->host);
}
X509_free(cert);
return 0;
......@@ -414,16 +423,16 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
struct timeval now;
time_t elapsed;
printf("tlsconnect called from %s\n", text);
debug(DBG_INFO, "tlsconnect called from %s", text);
pthread_mutex_lock(&server->lock);
if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
/* already reconnected, nothing to do */
printf("tlsconnect(%s): seems already reconnected\n", text);
debug(DBG_INFO, "tlsconnect(%s): seems already reconnected", text);
pthread_mutex_unlock(&server->lock);
return;
}
printf("tlsconnect %s\n", text);
debug(DBG_INFO, "tlsconnect %s", text);
for (;;) {
gettimeofday(&now, NULL);
......@@ -434,25 +443,28 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
} else if (elapsed < 5)
sleep(10);
else if (elapsed < 600) {
printf("tlsconnect: sleeping %lds\n", elapsed);
debug(DBG_WARN, "tlsconnect: sleeping %lds", elapsed);
sleep(elapsed);
} else if (elapsed < 1000) {
printf("tlsconnect: sleeping %ds\n", 900);
debug(DBG_WARN, "tlsconnect: sleeping %ds", 900);
sleep(900);
} else
server->lastconnecttry.tv_sec = now.tv_sec; /* no sleep at startup */
printf("tlsconnect: trying to open TLS connection to %s port %s\n", server->peer.host, server->peer.port);
debug(DBG_WARN, "tlsconnect: trying to open TLS connection to %s port %s", server->peer.host, server->peer.port);
if (server->sock >= 0)
close(server->sock);
if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0)
if ((server->sock = connecttoserver(server->peer.addrinfo)) < 0) {
debug(DBG_ERR, "tlsconnect: connecttoserver failed");
continue;
}
SSL_free(server->peer.ssl);
server->peer.ssl = SSL_new(ssl_ctx);
SSL_set_fd(server->peer.ssl, server->sock);
if (SSL_connect(server->peer.ssl) > 0 && tlsverifycert(&server->peer))
break;
}
printf("tlsconnect: TLS connection to %s port %s up\n", server->peer.host, server->peer.port);
debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->peer.host, server->peer.port);
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
}
......@@ -465,7 +477,7 @@ unsigned char *radtlsget(SSL *ssl) {
for (total = 0; total < 4; total += cnt) {
cnt = SSL_read(ssl, buf + total, 4 - total);
if (cnt <= 0) {
printf("radtlsget: connection lost\n");
debug(DBG_ERR, "radtlsget: connection lost");
if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
/* remote end sent close_notify, send one back */
SSL_shutdown(ssl);
......@@ -477,7 +489,7 @@ unsigned char *radtlsget(SSL *ssl) {
len = RADLEN(buf);
rad = malloc(len);
if (!rad) {
err("radtlsget: malloc failed");
debug(DBG_ERR, "radtlsget: malloc failed");
continue;
}
memcpy(rad, buf, 4);
......@@ -485,7 +497,7 @@ unsigned char *radtlsget(SSL *ssl) {
for (; total < len; total += cnt) {
cnt = SSL_read(ssl, rad + total, len - total);
if (cnt <= 0) {
printf("radtlsget: connection lost\n");
debug(DBG_ERR, "radtlsget: connection lost");
if (SSL_get_error(ssl, cnt) == SSL_ERROR_ZERO_RETURN) {
/* remote end sent close_notify, send one back */
SSL_shutdown(ssl);
......@@ -499,10 +511,10 @@ unsigned char *radtlsget(SSL *ssl) {
break;
free(rad);
printf("radtlsget: packet smaller than minimum radius size\n");
debug(DBG_WARN, "radtlsget: packet smaller than minimum radius size");
}
printf("radtlsget: got %d bytes\n", total);
debug(DBG_INFO, "radtlsget: got %d bytes", total);
return rad;
}
......@@ -515,23 +527,23 @@ int clientradput(struct server *server, unsigned char *rad) {
len = RADLEN(rad);
if (server->peer.type == 'U') {
if (send(server->sock, rad, len, 0) >= 0) {
printf("clienradput: sent UDP of length %d to %s port %s\n", len, server->peer.host, server->peer.port);
debug(DBG_INFO, "clienradput: sent UDP of length %d to %s port %s", len, server->peer.host, server->peer.port);
return 1;
}
err("clientradput: send failed");
debug(DBG_WARN, "clientradput: send failed");
return 0;
}
lastconnecttry = server->lastconnecttry;
while ((cnt = SSL_write(server->peer.ssl, rad, len)) <= 0) {
while ((error = ERR_get_error()))
err("clientradput: TLS: %s", ERR_error_string(error, NULL));
debug(DBG_ERR, "clientradput: TLS: %s", ERR_error_string(error, NULL));
tlsconnect(server, &lastconnecttry, "clientradput");
lastconnecttry = server->lastconnecttry;
}
server->connectionok = 1;
printf("clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s\n",
debug(DBG_INFO, "clientradput: Sent %d bytes, Radius packet of length %d to TLS peer %s",
cnt, len, server->peer.host);
return 1;
}
......@@ -607,13 +619,13 @@ int checkmessageauth(unsigned char *rad, uint8_t *authattr, char *secret) {
HMAC_Final(&hmacctx, hash, &md_len);
memcpy(authattr, auth, 16);
if (md_len != 16) {
printf("message auth computation failed\n");
debug(DBG_WARN, "message auth computation failed");
pthread_mutex_unlock(&lock);
return 0;
}
if (memcmp(auth, hash, 16)) {
printf("message authenticator, wrong value\n");
debug(DBG_WARN, "message authenticator, wrong value");
pthread_mutex_unlock(&lock);
return 0;
}
......@@ -643,7 +655,7 @@ int createmessageauth(unsigned char *rad, unsigned char *authattrval, char *secr
HMAC_Update(&hmacctx, rad, RADLEN(rad));
HMAC_Final(&hmacctx, authattrval, &md_len);
if (md_len != 16) {
printf("message auth computation failed\n");
debug(DBG_WARN, "message auth computation failed");
pthread_mutex_unlock(&lock);
return 0;
}
......@@ -665,7 +677,7 @@ void sendrq(struct server *to, struct client *from, struct request *rq) {
if (!to->requests[i].buf)
break;
if (i == to->nextid) {
printf("No room in queue, dropping request\n");
debug(DBG_WARN, "No room in queue, dropping request");
pthread_mutex_unlock(&to->newrq_mutex);
return;
}
......@@ -673,7 +685,7 @@ void sendrq(struct server *to, struct client *from, struct request *rq) {
to->nextid = i + 1;
rq->buf[1] = (char)i;
printf("sendrq: inserting packet with id %d in queue for %s\n", i, to->peer.host);
debug(DBG_INFO, "sendrq: inserting packet with id %d in queue for %s", i, to->peer.host);
if (!createmessageauth(rq->buf, rq->messageauthattrval, to->peer.secret))
return;
......@@ -682,7 +694,7 @@ void sendrq(struct server *to, struct client *from, struct request *rq) {
if (!to->newrq) {
to->newrq = 1;
printf("signalling client writer\n");
debug(DBG_INFO, "signalling client writer");
pthread_cond_signal(&to->newrq_cond);
}
pthread_mutex_unlock(&to->newrq_mutex);
......@@ -693,7 +705,7 @@ void sendreply(struct client *to, struct server *from, unsigned char *buf, struc
pthread_mutex_lock(&replyq->count_mutex);
if (replyq->count == replyq->size) {
printf("No room in queue, dropping request\n");
debug(DBG_WARN, "No room in queue, dropping request");
pthread_mutex_unlock(&replyq->count_mutex);
return;
}
......@@ -704,7 +716,7 @@ void sendreply(struct client *to, struct server *from, unsigned char *buf, struc
replyq->count++;
if (replyq->count == 1) {
printf("signalling client writer\n");
debug(DBG_INFO, "signalling client writer");
pthread_cond_signal(&replyq->count_cond);
}
pthread_mutex_unlock(&replyq->count_mutex);
......@@ -974,7 +986,7 @@ struct server *id2server(char *id, uint8_t len) {
for (realm = servers[i].realms; *realm; realm++) {
if ((strlen(*realm) == 1 && **realm == '*') ||
(strlen(*realm) == len && !memcmp(idrealm, *realm, len))) {
printf("found matching realm: %s, host %s\n", *realm, servers[i].peer.host);
debug(DBG_INFO, "found matching realm: %s, host %s", *realm, servers[i].peer.host);
return servers + i;
}
}
......@@ -993,25 +1005,27 @@ int rqinqueue(struct server *to, struct client *from, uint8_t id) {
return i < MAX_REQUESTS;
}
struct server *radsrv(struct request *rq, unsigned char *buf, struct client *from) {
uint8_t code, id, *auth, *attr, attrvallen;
uint8_t *usernameattr = NULL, *userpwdattr = NULL, *tunnelpwdattr = NULL, *messageauthattr = NULL;
int i;
uint16_t len;
int left;
struct server *to;
unsigned char newauth[16];
#ifdef DEBUG
int i;
#endif
code = *(uint8_t *)buf;
id = *(uint8_t *)(buf + 1);
len = RADLEN(buf);
auth = (uint8_t *)(buf + 4);
printf("radsrv: code %d, id %d, length %d\n", code, id, len);
debug(DBG_INFO, "radsrv: code %d, id %d, length %d", code, id, len);
if (code != RAD_Access_Request) {
printf("radsrv: server currently accepts only access-requests, ignoring\n");
debug(DBG_WARN, "radsrv: server currently accepts only access-requests, ignoring");
return NULL;
}
......@@ -1021,7 +1035,7 @@ struct server *radsrv(struct request *rq, unsigned char *buf, struct client *fro
while (left > 1) {
left -= attr[RAD_Attr_Length];
if (left < 0) {
printf("radsrv: attribute length exceeds packet length, ignoring packet\n");
debug(DBG_WARN, "radsrv: attribute length exceeds packet length, ignoring packet");
return NULL;
}
switch (attr[RAD_Attr_Type]) {
......@@ -1041,80 +1055,88 @@ struct server *radsrv(struct request *rq, unsigned char *buf, struct client *fro
attr += attr[RAD_Attr_Length];
}
if (left)
printf("radsrv: malformed packet? remaining byte after last attribute\n");
debug(DBG_WARN, "radsrv: malformed packet? remaining byte after last attribute");
#ifdef DEBUG
if (usernameattr) {
printf("radsrv: Username: ");
for (i = 0; i < usernameattr[RAD_Attr_Length] - 2; i++)
printf("%c", usernameattr[RAD_Attr_Value + i]);
printf("\n");
}
#endif
to = id2server((char *)&usernameattr[RAD_Attr_Value], usernameattr[RAD_Attr_Length] - 2);
if (!to) {
printf("radsrv: ignoring request, don't know where to send it\n");
debug(DBG_WARN, "radsrv: ignoring request, don't know where to send it");
return NULL;
}
if (rqinqueue(to, from, id)) {
printf("radsrv: ignoring request from host %s with id %d, already got one\n", from->peer.host, id);
debug(DBG_WARN, "radsrv: ignoring request from host %s with id %d, already got one", from->peer.host, id);
return NULL;
}
if (messageauthattr && (messageauthattr[RAD_Attr_Length] != 18 ||
!checkmessageauth(buf, &messageauthattr[RAD_Attr_Value], from->peer.secret))) {
printf("radsrv: message authentication failed\n");
debug(DBG_WARN, "radsrv: message authentication failed");
return NULL;
}
if (!RAND_bytes(newauth, 16)) {
printf("radsrv: failed to generate random auth\n");
debug(DBG_WARN, "radsrv: failed to generate random auth");
return NULL;
}
#ifdef DEBUG
printauth("auth", auth);
printauth("newauth", newauth);
#endif
if (userpwdattr) {
printf("radsrv: found userpwdattr of length %d\n", userpwdattr[RAD_Attr_Length]);
debug(DBG_INFO, "radsrv: found userpwdattr of length %d", userpwdattr[RAD_Attr_Length]);
attrvallen = userpwdattr[RAD_Attr_Length] - 2;
if (attrvallen < 16 || attrvallen > 128 || attrvallen % 16) {
printf("radsrv: invalid user password length\n");
debug(DBG_WARN, "radsrv: invalid user password length");
return NULL;
}
if (!pwddecrypt(&userpwdattr[RAD_Attr_Value], attrvallen, from->peer.secret, strlen(from->peer.secret), auth)) {
printf("radsrv: cannot decrypt password\n");
debug(DBG_WARN, "radsrv: cannot decrypt password");
return NULL;
}
#ifdef DEBUG
printf("radsrv: password: ");
for (i = 0; i < attrvallen; i++)
printf("%02x ", userpwdattr[RAD_Attr_Value + i]);
printf("\n");
#endif
if (!pwdencrypt(&userpwdattr[RAD_Attr_Value], attrvallen, to->peer.secret, strlen(to->peer.secret), newauth)) {
printf("radsrv: cannot encrypt password\n");
debug(DBG_WARN, "radsrv: cannot encrypt password");
return NULL;
}
}
if (tunnelpwdattr) {
printf("radsrv: found tunnelpwdattr of length %d\n", tunnelpwdattr[RAD_Attr_Length]);
debug(DBG_INFO, "radsrv: found tunnelpwdattr of length %d", tunnelpwdattr[RAD_Attr_Length]);
attrvallen = tunnelpwdattr[RAD_Attr_Length] - 2;
if (attrvallen < 16 || attrvallen > 128 || attrvallen % 16) {
printf("radsrv: invalid user password length\n");
debug(DBG_WARN, "radsrv: invalid user password length");
return NULL;
}
if (!pwddecrypt(&tunnelpwdattr[RAD_Attr_Value], attrvallen, from->peer.secret, strlen(from->peer.secret), auth)) {
printf("radsrv: cannot decrypt password\n");
debug(DBG_WARN, "radsrv: cannot decrypt password");
return NULL;
}
#ifdef DEBUG
printf("radsrv: password: ");
for (i = 0; i < attrvallen; i++)
printf("%02x ", tunnelpwdattr[RAD_Attr_Value + i]);
printf("\n");
#endif
if (!pwdencrypt(&tunnelpwdattr[RAD_Attr_Value], attrvallen, to->peer.secret, strlen(to->peer.secret), newauth)) {
printf("radsrv: cannot encrypt password\n");
debug(DBG_WARN, "radsrv: cannot encrypt password");
return NULL;
}
}
......@@ -1125,8 +1147,10 @@ struct server *radsrv(struct request *rq, unsigned char *buf, struct client *fro
rq->messageauthattrval = (messageauthattr ? &messageauthattr[RAD_Attr_Value] : NULL);
memcpy(rq->origauth, auth, 16);
memcpy(auth, newauth, 16);
#ifdef DEBUG
printauth("rq->origauth", (unsigned char *)rq->origauth);
printauth("auth", auth);
#endif
return to;
}
......@@ -1151,30 +1175,30 @@ 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");
debug(DBG_WARN, "clientrd: discarding, only accept access accept, access reject and access challenge messages");
continue;
}
printf("got message type: %d, id: %d\n", buf[0], buf[1]);
debug(DBG_INFO, "got message type: %d, id: %d", buf[0], buf[1]);
i = buf[1]; /* i is the id */
pthread_mutex_lock(&server->newrq_mutex);
if (!server->requests[i].buf || !server->requests[i].tries) {
pthread_mutex_unlock(&server->newrq_mutex);
printf("clientrd: no matching request sent with this id, ignoring\n");
debug(DBG_WARN, "clientrd: no matching request sent with this id, ignoring");
continue;
}
if (server->requests[i].received) {
pthread_mutex_unlock(&server->newrq_mutex);
printf("clientrd: already received, ignoring\n");
debug(DBG_WARN, "clientrd: already received, ignoring");
continue;
}
if (!validauth(buf, server->requests[i].buf + 4, (unsigned char *)server->peer.secret)) {
pthread_mutex_unlock(&server->newrq_mutex);
printf("clientrd: invalid auth, ignoring\n");
debug(DBG_WARN, "clientrd: invalid auth, ignoring");
continue;
}
......@@ -1187,22 +1211,22 @@ void *clientrd(void *arg) {
while (left > 1) {
left -= attr[RAD_Attr_Length];
if (left < 0) {
printf("clientrd: attribute length exceeds packet length, ignoring packet\n");
debug(DBG_WARN, "clientrd: attribute length exceeds packet length, ignoring packet");
goto getnext;
}
if (attr[RAD_Attr_Type] == RAD_Attr_Message_Authenticator) {
if (attr[RAD_Attr_Length] != 18) {
printf("clientrd: illegal message auth attribute length, ignoring packet\n");
debug(DBG_WARN, "clientrd: illegal message auth attribute length, ignoring packet");
goto getnext;
}
memcpy(tmp, buf + 4, 16);
memcpy(buf + 4, server->requests[i].buf + 4, 16);
if (!checkmessageauth(buf, &attr[RAD_Attr_Value], server->peer.secret)) {
printf("clientrd: message authentication failed\n");
debug(DBG_WARN, "clientrd: message authentication failed");
goto getnext;
}
memcpy(buf + 4, tmp, 16);
printf("clientrd: message auth ok\n");
debug(DBG_INFO, "clientrd: message auth ok");
messageauthattr = attr;