From 0aa4b1fb04dafb9767309afa5d6ad6805391670f Mon Sep 17 00:00:00 2001 From: venaas Date: Tue, 23 Sep 2008 15:21:50 +0000 Subject: make clientwr not try to connect (left to reader), changed some timing stuff, issue with statusserver and connection down..., added optional cacheexpiry option for tls blocks git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@398 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- dtls.c | 21 ++++++++++++++----- radsecproxy.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------- radsecproxy.h | 6 +++++- tcp.c | 14 ++++++------- tls.c | 33 +++++++++++++++++++---------- 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 *)¶ms->addr, NULL); if (conf) { - ssl = dtlsacccon(1, conf->ssl_ctx, params->sock, (struct sockaddr *)¶ms->addr, params->sesscache->rbios); + ctx = tlsgetctx(RAD_DTLS, conf->tlsconf); + if (!ctx) + goto exit; + ssl = dtlsacccon(1, ctx, params->sock, (struct sockaddr *)¶ms->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) { -- cgit v1.2.3