make clientwr not try to connect (left to reader), changed some timing stuff, issue...
authorvenaas <venaas>
Tue, 23 Sep 2008 15:21:50 +0000 (15:21 +0000)
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>
Tue, 23 Sep 2008 15:21:50 +0000 (15:21 +0000)
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@398 e88ac4ed-0b26-0410-9574-a7f39faa03bf

dtls.c
radsecproxy.c
radsecproxy.h
tcp.c
tls.c

diff --git a/dtls.c b/dtls.c
index 0b26bbf..ed5e44e 100644 (file)
--- 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;
index 71d8856..9c44328 100644 (file)
@@ -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) {
index 8c17c96..4cb102b 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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) {