summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvenaas <venaas>2008-06-04 14:55:16 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2008-06-04 14:55:16 +0000
commit9f21e9375ccb7bcbb2e6effbfd6780d1577be06e (patch)
tree7901590b4f3099c5b13202650da2b6904da3fcfe
parentcb8a46000ba1f9e8f87f4ec3a0ae38cdae93267c (diff)
fixed bugs with freeing memory when removing dynamic server, added tlsconnect timeout
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@283 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r--radsecproxy.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index a3641cb..d55834d 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -85,7 +85,8 @@ int dynamicconfig(struct server *server);
int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val);
void freerealm(struct realm *realm);
void freeclsrvconf(struct clsrvconf *conf);
-
+void freerqdata(struct request *rq);
+
/* callbacks for making OpenSSL thread safe */
unsigned long ssl_thread_id() {
return (unsigned long)pthread_self();
@@ -509,10 +510,17 @@ void removeclientrqs(struct client *client) {
}
void freeserver(struct server *server, uint8_t destroymutex) {
+ struct request *rq, *end;
+
if (!server)
return;
-
- free(server->requests);
+
+ if(server->requests) {
+ rq = server->requests;
+ for (end = rq + MAX_REQUESTS; rq < end; rq++)
+ freerqdata(rq);
+ free(server->requests);
+ }
free(server->dynamiclookuparg);
if (destroymutex) {
pthread_mutex_destroy(&server->lock);
@@ -871,7 +879,7 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) {
return 1;
}
-void tlsconnect(struct server *server, struct timeval *when, char *text) {
+int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text) {
struct timeval now;
time_t elapsed;
X509 *cert;
@@ -882,7 +890,7 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
/* already reconnected, nothing to do */
debug(DBG_DBG, "tlsconnect(%s): seems already reconnected", text);
pthread_mutex_unlock(&server->lock);
- return;
+ return 1;
}
debug(DBG_DBG, "tlsconnect %s", text);
@@ -890,6 +898,14 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
for (;;) {
gettimeofday(&now, NULL);
elapsed = now.tv_sec - server->lastconnecttry.tv_sec;
+ if (timeout && server->lastconnecttry.tv_sec && elapsed > timeout) {
+ debug(DBG_DBG, "tlsconnect: timeout");
+ if (server->sock >= 0)
+ close(server->sock);
+ SSL_free(server->ssl);
+ pthread_mutex_unlock(&server->lock);
+ return 0;
+ }
if (server->connectionok) {
server->connectionok = 0;
sleep(2);
@@ -928,6 +944,7 @@ void tlsconnect(struct server *server, struct timeval *when, char *text) {
debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
+ return 1;
}
unsigned char *radtlsget(SSL *ssl) {
@@ -1029,7 +1046,7 @@ int clientradputtls(struct server *server, unsigned char *rad) {
while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
while ((error = ERR_get_error()))
debug(DBG_ERR, "clientradputtls: TLS: %s", ERR_error_string(error, NULL));
- tlsconnect(server, &lastconnecttry, "clientradputtls");
+ tlsconnect(server, &lastconnecttry, 0, "clientradputtls");
lastconnecttry = server->lastconnecttry;
}
@@ -2254,7 +2271,7 @@ void *tlsclientrd(void *arg) {
lastconnecttry = server->lastconnecttry;
buf = radtlsget(server->ssl);
if (!buf) {
- tlsconnect(server, &lastconnecttry, "clientrd");
+ tlsconnect(server, &lastconnecttry, 0, "clientrd");
continue;
}
@@ -2268,19 +2285,21 @@ void *clientwr(void *arg) {
struct server *server = (struct server *)arg;
struct request *rq;
pthread_t tlsclientrdth;
- int i;
+ int i, dynconffail = 0;
uint8_t rnd;
struct timeval now, lastsend;
struct timespec timeout;
struct request statsrvrq;
unsigned char statsrvbuf[38];
struct clsrvconf *conf;
-
+
conf = server->conf;
- if (server->dynamiclookuparg && !dynamicconfig(server))
+ if (server->dynamiclookuparg && !dynamicconfig(server)) {
+ dynconffail = 1;
goto errexit;
-
+ }
+
if (!conf->addrinfo && !resolvepeer(conf, 0)) {
debug(DBG_WARN, "failed to resolve host %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
goto errexit;
@@ -2301,14 +2320,15 @@ void *clientwr(void *arg) {
if (conf->type == 'U') {
server->connectionok = 1;
} else {
- tlsconnect(server, NULL, "new client");
+ if (!tlsconnect(server, NULL, server->dynamiclookuparg ? 6 : 0, "clientwr"))
+ goto errexit;
server->connectionok = 1;
if (pthread_create(&tlsclientrdth, NULL, tlsclientrd, (void *)server)) {
debug(DBG_ERR, "clientwr: pthread_create failed");
goto errexit;
}
}
-
+
for (;;) {
pthread_mutex_lock(&server->newrq_mutex);
if (!server->newrq) {
@@ -2414,7 +2434,10 @@ void *clientwr(void *arg) {
conf->servers = NULL;
if (server->dynamiclookuparg) {
removeserversubrealms(realms, conf);
- freeclsrvconf(conf);
+ if (dynconffail)
+ free(conf);
+ else
+ freeclsrvconf(conf);
}
freeserver(server, 1);
return NULL;
@@ -3242,12 +3265,10 @@ void freeclsrvconf(struct clsrvconf *conf) {
regfree(conf->rewriteattrregex);
free(conf->rewriteattrreplacement);
free(conf->dynamiclookupcommand);
- if (conf->ssl_ctx)
- SSL_CTX_free(conf->ssl_ctx);
free(conf->rewrite);
if (conf->addrinfo)
freeaddrinfo(conf->addrinfo);
- /* not touching clients and servers */
+ /* not touching ssl_ctx, clients and servers */
free(conf);
}
@@ -3279,7 +3300,8 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
!mergeconfstring(&dst->secret, &src->secret) ||
!mergeconfstring(&dst->tls, &src->tls) ||
!mergeconfstring(&dst->matchcertattr, &src->matchcertattr) ||
- !mergeconfstring(&dst->confrewrite, &src->confrewrite))
+ !mergeconfstring(&dst->confrewrite, &src->confrewrite) ||
+ !mergeconfstring(&dst->dynamiclookupcommand, &src->dynamiclookupcommand))
return 0;
dst->statusserver = src->statusserver;
dst->certnamecheck = src->certnamecheck;
@@ -3439,6 +3461,10 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
goto errexit;
free(conf);
conf = resconf;
+ if (conf->dynamiclookupcommand) {
+ free(conf->dynamiclookupcommand);
+ conf->dynamiclookupcommand = NULL;
+ }
}
if (conf->conftype && !strcasecmp(conf->conftype, "udp"))