summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dtls.c21
-rw-r--r--radsecproxy.c67
-rw-r--r--radsecproxy.h6
-rw-r--r--tcp.c14
-rw-r--r--tls.c33
5 files changed, 102 insertions, 39 deletions
diff --git a/dtls.c b/dtls.c
index 0b26bbf..ed5e44e 100644
--- a/dtls.c
+++ b/dtls.c
@@ -297,12 +297,16 @@ void *dtlsservernew(void *arg) {
struct list_node *cur = NULL;
SSL *ssl = NULL;
X509 *cert = NULL;
+ SSL_CTX *ctx = NULL;
uint8_t delay = 60;
debug(DBG_DBG, "dtlsservernew: starting");
conf = find_clconf(RAD_DTLS, (struct sockaddr *)&params->addr, NULL);
if (conf) {
- ssl = dtlsacccon(1, conf->ssl_ctx, params->sock, (struct sockaddr *)&params->addr, params->sesscache->rbios);
+ ctx = tlsgetctx(RAD_DTLS, conf->tlsconf);
+ if (!ctx)
+ goto exit;
+ ssl = dtlsacccon(1, ctx, params->sock, (struct sockaddr *)&params->addr, params->sesscache->rbios);
if (!ssl)
goto exit;
cert = verifytlscert(ssl);
@@ -472,7 +476,8 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *
struct timeval now;
time_t elapsed;
X509 *cert;
-
+ SSL_CTX *ctx = NULL;
+
debug(DBG_DBG, "dtlsconnect: called from %s", text);
pthread_mutex_lock(&server->lock);
if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) {
@@ -510,7 +515,11 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *
debug(DBG_WARN, "dtlsconnect: trying to open DTLS connection to %s port %s", server->conf->host, server->conf->port);
SSL_free(server->ssl);
- server->ssl = dtlsacccon(0, server->conf->ssl_ctx, server->sock, server->conf->addrinfo->ai_addr, server->rbios);
+ server->ssl = NULL;
+ ctx = tlsgetctx(RAD_DTLS, server->conf->tlsconf);
+ if (!ctx)
+ continue;
+ server->ssl = dtlsacccon(0, ctx, server->sock, server->conf->addrinfo->ai_addr, server->rbios);
if (!server->ssl)
continue;
debug(DBG_DBG, "dtlsconnect: DTLS: ok");
@@ -525,6 +534,7 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *
}
X509_free(cert);
debug(DBG_WARN, "dtlsconnect: DTLS connection to %s port %s up", server->conf->host, server->conf->port);
+ server->connectionok = 1;
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
return 1;
@@ -536,12 +546,13 @@ int clientradputdtls(struct server *server, unsigned char *rad) {
unsigned long error;
struct clsrvconf *conf = server->conf;
- if (!server->ssl)
+ if (!server->connectionok)
return 0;
len = RADLEN(rad);
- while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
+ if ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
while ((error = ERR_get_error()))
debug(DBG_ERR, "clientradputdtls: DTLS: %s", ERR_error_string(error, NULL));
+ return 0;
}
debug(DBG_DBG, "clientradputdtls: Sent %d bytes, Radius packet of length %d to DTLS peer %s", cnt, len, conf->host);
return 1;
diff --git a/radsecproxy.c b/radsecproxy.c
index 71d8856..9c44328 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -1019,7 +1019,8 @@ void sendrq(struct server *to, struct request *rq) {
return;
errexit:
- rmclientrq(rq, rq->msg->id);
+ if (rq->from)
+ rmclientrq(rq, rq->msg->id);
freerq(rq);
pthread_mutex_unlock(&to->newrq_mutex);
}
@@ -2061,7 +2062,8 @@ void *clientwr(void *arg) {
struct server *server = (struct server *)arg;
struct rqout *rqout = NULL;
pthread_t clientrdth;
- int i, secs, dynconffail = 0;
+ int i, dynconffail = 0;
+ time_t secs;
uint8_t rnd;
struct timeval now, laststatsrv;
struct timespec timeout;
@@ -2107,6 +2109,8 @@ void *clientwr(void *arg) {
rnd /= 32;
if (conf->statusserver) {
secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec;
+ if (now.tv_sec - secs > STATUS_SERVER_PERIOD)
+ secs = now.tv_sec;
if (!timeout.tv_sec || timeout.tv_sec > secs + STATUS_SERVER_PERIOD + rnd)
timeout.tv_sec = secs + STATUS_SERVER_PERIOD + rnd;
} else {
@@ -2182,7 +2186,7 @@ void *clientwr(void *arg) {
conf->pdef->clientradput(server, rqout->rq->buf);
pthread_mutex_unlock(rqout->lock);
}
- if (conf->statusserver) {
+ if (conf->statusserver && server->connectionok) {
secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec;
gettimeofday(&now, NULL);
if (now.tv_sec - secs > STATUS_SERVER_PERIOD) {
@@ -2388,24 +2392,50 @@ SSL_CTX *tlscreatectx(uint8_t type, struct tls *conf) {
return ctx;
}
-SSL_CTX *tlsgetctx(uint8_t type, char *alt1, char *alt2) {
+struct tls *tlsgettls(char *alt1, char *alt2) {
struct tls *t;
t = hash_read(tlsconfs, alt1, strlen(alt1));
- if (!t) {
+ if (!t)
t = hash_read(tlsconfs, alt2, strlen(alt2));
- if (!t)
- return NULL;
- }
+ return t;
+}
+SSL_CTX *tlsgetctx(uint8_t type, struct tls *t) {
+ struct timeval now;
+
+ if (!t)
+ return NULL;
+ gettimeofday(&now, NULL);
+
switch (type) {
case RAD_TLS:
- if (!t->tlsctx)
+ if (t->tlsexpiry && t->tlsctx) {
+ if (t->tlsexpiry < now.tv_sec) {
+ t->tlsexpiry = now.tv_sec + t->cacheexpiry;
+ SSL_CTX_free(t->tlsctx);
+ return t->tlsctx = tlscreatectx(RAD_TLS, t);
+ }
+ }
+ if (!t->tlsctx) {
t->tlsctx = tlscreatectx(RAD_TLS, t);
+ if (t->cacheexpiry)
+ t->tlsexpiry = now.tv_sec + t->cacheexpiry;
+ }
return t->tlsctx;
case RAD_DTLS:
- if (!t->dtlsctx)
+ if (t->dtlsexpiry && t->dtlsctx) {
+ if (t->dtlsexpiry < now.tv_sec) {
+ t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
+ SSL_CTX_free(t->dtlsctx);
+ return t->dtlsctx = tlscreatectx(RAD_DTLS, t);
+ }
+ }
+ if (!t->dtlsctx) {
t->dtlsctx = tlscreatectx(RAD_DTLS, t);
+ if (t->cacheexpiry)
+ t->dtlsexpiry = now.tv_sec + t->cacheexpiry;
+ }
return t->dtlsctx;
}
return NULL;
@@ -3066,8 +3096,8 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
free(conftype);
if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
- conf->ssl_ctx = conf->tls ? tlsgetctx(conf->type, conf->tls, NULL) : tlsgetctx(conf->type, "defaultclient", "default");
- if (!conf->ssl_ctx)
+ conf->tlsconf = conf->tls ? tlsgettls(conf->tls, NULL) : tlsgettls("defaultclient", "default");
+ if (!conf->tlsconf)
debugx(1, DBG_ERR, "error in block %s, no tls context defined", block);
if (conf->matchcertattr && !addmatchcertattr(conf))
debugx(1, DBG_ERR, "error in block %s, invalid MatchCertificateAttributeValue", block);
@@ -3117,8 +3147,8 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
int compileserverconfig(struct clsrvconf *conf, const char *block) {
if (conf->type == RAD_TLS || conf->type == RAD_DTLS) {
- conf->ssl_ctx = conf->tls ? tlsgetctx(conf->type, conf->tls, NULL) : tlsgetctx(conf->type, "defaultserver", "default");
- if (!conf->ssl_ctx) {
+ conf->tlsconf = conf->tls ? tlsgettls(conf->tls, NULL) : tlsgettls("defaultserver", "default");
+ if (!conf->tlsconf) {
debug(DBG_ERR, "error in block %s, no tls context defined", block);
return 0;
}
@@ -3306,6 +3336,7 @@ int confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
struct tls *conf;
+ long int expiry = LONG_MIN;
debug(DBG_DBG, "conftls_cb called for %s", block);
@@ -3322,6 +3353,7 @@ int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *v
"CertificateFile", CONF_STR, &conf->certfile,
"CertificateKeyFile", CONF_STR, &conf->certkeyfile,
"CertificateKeyPassword", CONF_STR, &conf->certkeypwd,
+ "CacheExpiry", CONF_LINT, &expiry,
"CRLCheck", CONF_BLN, &conf->crlcheck,
NULL
)) {
@@ -3336,6 +3368,13 @@ int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *v
debug(DBG_ERR, "conftls_cb: CA Certificate file or path need to be specified in block %s", val);
goto errexit;
}
+ if (expiry != LONG_MIN) {
+ if (expiry < 0) {
+ debug(DBG_ERR, "error in block %s, value of option CacheExpiry is %ld, may not be negative", val, expiry);
+ goto errexit;
+ }
+ conf->cacheexpiry = expiry;
+ }
conf->name = stringcopy(val, 0);
if (!conf->name) {
diff --git a/radsecproxy.h b/radsecproxy.h
index 8c17c96..4cb102b 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -90,12 +90,12 @@ struct clsrvconf {
uint8_t retrycount;
uint8_t dupinterval;
uint8_t certnamecheck;
- SSL_CTX *ssl_ctx;
struct rewrite *rewritein;
struct rewrite *rewriteout;
struct addrinfo *addrinfo;
uint8_t prefixlen;
pthread_mutex_t *lock; /* only used for updating clients so far */
+ struct tls *tlsconf;
struct list *clients;
struct server *servers;
};
@@ -150,6 +150,9 @@ struct tls {
char *certkeyfile;
char *certkeypwd;
uint8_t crlcheck;
+ uint32_t cacheexpiry;
+ uint32_t tlsexpiry;
+ uint32_t dtlsexpiry;
SSL_CTX *tlsctx;
SSL_CTX *dtlsctx;
};
@@ -212,3 +215,4 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf);
void replyh(struct server *server, unsigned char *buf);
int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src);
int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse, int v6only);
+SSL_CTX *tlsgetctx(uint8_t type, struct tls *t);
diff --git a/tcp.c b/tcp.c
index 0d1da1c..2a4a799 100644
--- a/tcp.c
+++ b/tcp.c
@@ -75,6 +75,7 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t
debug(DBG_ERR, "tcpconnect: connecttcp failed");
}
debug(DBG_WARN, "tcpconnect: TCP connection to %s port %s up", server->conf->host, server->conf->port);
+ server->connectionok = 1;
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
return 1;
@@ -150,18 +151,15 @@ unsigned char *radtcpget(int s, int timeout) {
int clientradputtcp(struct server *server, unsigned char *rad) {
int cnt;
size_t len;
- struct timeval lastconnecttry;
struct clsrvconf *conf = server->conf;
-
+
+ if (!server->connectionok)
+ return 0;
len = RADLEN(rad);
- lastconnecttry = server->lastconnecttry;
- while ((cnt = write(server->sock, rad, len)) <= 0) {
+ if ((cnt = write(server->sock, rad, len)) <= 0) {
debug(DBG_ERR, "clientradputtcp: write error");
- tcpconnect(server, &lastconnecttry, 0, "clientradputtcp");
- lastconnecttry = server->lastconnecttry;
+ return 0;
}
-
- server->connectionok = 1;
debug(DBG_DBG, "clientradputtcp: Sent %d bytes, Radius packet of length %d to TCP peer %s", cnt, len, conf->host);
return 1;
}
diff --git a/tls.c b/tls.c
index 8ff92f9..836f3aa 100644
--- a/tls.c
+++ b/tls.c
@@ -36,6 +36,7 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t
struct timeval now;
time_t elapsed;
X509 *cert;
+ SSL_CTX *ctx = NULL;
unsigned long error;
debug(DBG_DBG, "tlsconnect: called from %s", text);
@@ -81,7 +82,14 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t
}
SSL_free(server->ssl);
- server->ssl = SSL_new(server->conf->ssl_ctx);
+ server->ssl = NULL;
+ ctx = tlsgetctx(RAD_TLS, server->conf->tlsconf);
+ if (!ctx)
+ continue;
+ server->ssl = SSL_new(ctx);
+ if (!server->ssl)
+ continue;
+
SSL_set_fd(server->ssl, server->sock);
if (SSL_connect(server->ssl) <= 0) {
while ((error = ERR_get_error()))
@@ -98,6 +106,7 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t
X509_free(cert);
}
debug(DBG_WARN, "tlsconnect: TLS connection to %s port %s up", server->conf->host, server->conf->port);
+ server->connectionok = 1;
gettimeofday(&server->lastconnecttry, NULL);
pthread_mutex_unlock(&server->lock);
return 1;
@@ -186,21 +195,17 @@ int clientradputtls(struct server *server, unsigned char *rad) {
int cnt;
size_t len;
unsigned long error;
- struct timeval lastconnecttry;
struct clsrvconf *conf = server->conf;
-
+
+ if (!server->connectionok)
+ return 0;
len = RADLEN(rad);
- lastconnecttry = server->lastconnecttry;
- while ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
+ if ((cnt = SSL_write(server->ssl, rad, len)) <= 0) {
while ((error = ERR_get_error()))
debug(DBG_ERR, "clientradputtls: TLS: %s", ERR_error_string(error, NULL));
- if (server->dynamiclookuparg)
- return 0;
- tlsconnect(server, &lastconnecttry, 0, "clientradputtls");
- lastconnecttry = server->lastconnecttry;
+ return 0;
}
- server->connectionok = 1;
debug(DBG_DBG, "clientradputtls: Sent %d bytes, Radius packet of length %d to TLS peer %s", cnt, len, conf->host);
return 1;
}
@@ -325,6 +330,7 @@ void *tlsservernew(void *arg) {
struct list_node *cur = NULL;
SSL *ssl = NULL;
X509 *cert = NULL;
+ SSL_CTX *ctx = NULL;
unsigned long error;
struct client *client;
@@ -337,7 +343,12 @@ void *tlsservernew(void *arg) {
conf = find_clconf(RAD_TLS, (struct sockaddr *)&from, &cur);
if (conf) {
- ssl = SSL_new(conf->ssl_ctx);
+ ctx = tlsgetctx(RAD_TLS, conf->tlsconf);
+ if (!ctx)
+ goto exit;
+ ssl = SSL_new(ctx);
+ if (!ssl)
+ goto exit;
SSL_set_fd(ssl, s);
if (SSL_accept(ssl) <= 0) {