From d0675120761d8cd58fd621501f88b3fa5a1df49f Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Mon, 17 Sep 2018 07:36:02 +0200 Subject: [PATCH 01/11] add options for statusserver: minimal: only send statusserver if request lost auto: try autodetecting statusserver capability --- radsecproxy.c | 122 +++++++++++++++++++++++++++++++------------------- radsecproxy.h | 9 +++- 2 files changed, 85 insertions(+), 46 deletions(-) diff --git a/radsecproxy.c b/radsecproxy.c index 1c6fd54..9bd6453 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -472,7 +472,7 @@ void sendrq(struct request *rq) { if (!to) goto errexit; - start = to->conf->statusserver ? 1 : 0; + start = to->conf->statusserver == RSP_STATSRV_OFF ? 0 : 1; pthread_mutex_lock(&to->newrq_mutex); if (start && rq->msg->code == RAD_Status_Server) { if (!_internal_sendrq(to, 0, rq)) { @@ -1669,9 +1669,11 @@ void replyh(struct server *server, unsigned char *buf) { gettimeofday(&server->lastrcv, NULL); if (rqout->rq->msg->code == RAD_Status_Server) { - freerqoutdata(rqout); - debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); - goto errunlock; + freerqoutdata(rqout); + debug(DBG_NOTICE, "replyh: got status server response from %s", server->conf->name); + if (server->conf->statusserver == RSP_STATSRV_AUTO) + server->conf->statusserver = RSP_STATSRV_MINIMAL; + goto errunlock; } gettimeofday(&server->lastreply, NULL); @@ -1784,7 +1786,7 @@ void *clientwr(void *arg) { pthread_t clientrdth; int i, dynconffail = 0; time_t secs; - uint8_t rnd, do_resend = 0; + uint8_t rnd, do_resend = 0, statusserver_requested = 0; struct timeval now, laststatsrv; struct timespec timeout; struct request *statsrvrq; @@ -1816,7 +1818,7 @@ void *clientwr(void *arg) { memset(&timeout, 0, sizeof(struct timespec)); - if (conf->statusserver) { + if (conf->statusserver != RSP_STATSRV_OFF) { gettimeofday(&server->lastrcv, NULL); gettimeofday(&laststatsrv, NULL); } @@ -1840,6 +1842,9 @@ void *clientwr(void *arg) { } server->state = RSP_SERVER_STATE_CONNECTED; + if (conf->statusserver == RSP_STATSRV_AUTO) + statusserver_requested = 1; + for (;;) { pthread_mutex_lock(&server->newrq_mutex); if (!server->newrq) { @@ -1847,7 +1852,7 @@ void *clientwr(void *arg) { /* random 0-7 seconds */ RAND_bytes(&rnd, 1); rnd /= 32; - if (conf->statusserver) { + if (conf->statusserver != RSP_STATSRV_OFF) { 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; @@ -1911,24 +1916,33 @@ void *clientwr(void *arg) { continue; } - if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) { - debug(DBG_DBG, "clientwr: removing expired packet from queue"); - replylog(rqout->rq->msg, server, rqout->rq); - if (conf->statusserver) { - if (*rqout->rq->buf == RAD_Status_Server) { - debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); - if (server->lostrqs < 255) - server->lostrqs++; - } + if (rqout->tries > 0 && now.tv_sec - server->lastrcv.tv_sec > conf->retryinterval) + statusserver_requested = 1; + if (rqout->tries == (*rqout->rq->buf == RAD_Status_Server ? 1 : conf->retrycount + 1)) { + debug(DBG_DBG, "clientwr: removing expired packet from queue"); + replylog(rqout->rq->msg, server, rqout->rq); + if (conf->statusserver == RSP_STATSRV_ON || conf->statusserver == RSP_STATSRV_MINIMAL) { + if (*rqout->rq->buf == RAD_Status_Server) { + debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); + if (server->lostrqs < 255) + server->lostrqs++; + } + } else { + if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) { + if (server->lastrcv.tv_sec >= laststatsrv.tv_sec) { + debug(DBG_DBG, "clientwr: status server autodetect faild, disabling status server for %s", conf->name); + conf->statusserver = RSP_STATSRV_OFF; + } } else { - debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); - if (server->lostrqs < 255) - server->lostrqs++; - } - freerqoutdata(rqout); - pthread_mutex_unlock(rqout->lock); - continue; - } + debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); + if (server->lostrqs < 255) + server->lostrqs++; + } + } + freerqoutdata(rqout); + pthread_mutex_unlock(rqout->lock); + continue; + } rqout->expiry.tv_sec = now.tv_sec + conf->retryinterval; if (!timeout.tv_sec || rqout->expiry.tv_sec < timeout.tv_sec) @@ -1941,19 +1955,23 @@ void *clientwr(void *arg) { pthread_mutex_unlock(rqout->lock); } do_resend = 0; - if (conf->statusserver && server->state == RSP_SERVER_STATE_CONNECTED) { - 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) { - laststatsrv = now; - statsrvrq = createstatsrvrq(); - if (statsrvrq) { - statsrvrq->to = server; - debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name); - sendrq(statsrvrq); - } - } - } + if (server->state == RSP_SERVER_STATE_CONNECTED && !conf->statusserver == RSP_STATSRV_OFF) { + secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; + gettimeofday(&now, NULL); + if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - secs > STATUS_SERVER_PERIOD) || + ((conf->statusserver == RSP_STATSRV_MINIMAL || conf->statusserver == RSP_STATSRV_AUTO) && + statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD)) { + + laststatsrv = now; + statsrvrq = createstatsrvrq(); + if (statsrvrq) { + statsrvrq->to = server; + debug(DBG_DBG, "clientwr: sending %s to %s", radmsgtype2string(RAD_Status_Server), conf->name); + sendrq(statsrvrq); + } + statusserver_requested = 0; + } + } } errexit: if (server->dynamiclookuparg) { @@ -2936,7 +2954,7 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { struct clsrvconf *conf, *resconf; - char *conftype = NULL, *rewriteinalias = NULL; + char *conftype = NULL, *rewriteinalias = NULL, *statusserver = NULL; long int retryinterval = LONG_MIN, retrycount = LONG_MIN, addttl = LONG_MIN; uint8_t ipv4only = 0, ipv6only = 0, confmerged = 0; @@ -2951,10 +2969,11 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->loopprevention = UCHAR_MAX; /* Uninitialized. */ resconf = (struct clsrvconf *)arg; if (resconf) { - conf->statusserver = resconf->statusserver; - conf->certnamecheck = resconf->certnamecheck; - } else - conf->certnamecheck = 1; + conf->statusserver = resconf->statusserver; + conf->certnamecheck = resconf->certnamecheck; + } else { + conf->certnamecheck = 1; + } if (!getgenericconfig(cf, block, "type", CONF_STR, &conftype, @@ -2973,7 +2992,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char "rewrite", CONF_STR, &rewriteinalias, "rewriteIn", CONF_STR, &conf->confrewritein, "rewriteOut", CONF_STR, &conf->confrewriteout, - "StatusServer", CONF_BLN, &conf->statusserver, + "StatusServer", CONF_STR, &statusserver, "RetryInterval", CONF_LINT, &retryinterval, "RetryCount", CONF_LINT, &retrycount, "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand, @@ -3049,6 +3068,19 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char conf->addttl = (uint8_t)addttl; } + if (statusserver) { + if (strcasecmp(statusserver, "Off") == 0) + conf->statusserver = RSP_STATSRV_OFF; + else if (strcasecmp(statusserver, "On") == 0) + conf->statusserver = RSP_STATSRV_ON; + else if (strcasecmp(statusserver, "Minimal") == 0) + conf->statusserver = RSP_STATSRV_MINIMAL; + else if (strcasecmp(statusserver, "Auto") == 0) + conf->statusserver = RSP_STATSRV_AUTO; + else + debugx(1, DBG_ERR, "config error in blocck %s: invalid StatusServer value: %s", block, statusserver); + } + if (resconf) { if (!mergesrvconf(resconf, conf)) goto errexit; @@ -3222,8 +3254,8 @@ void getmainconfig(const char *configfile) { "FTicksKey", CONF_STR, &fticks_key_str, "FTicksSyslogFacility", CONF_STR, &options.ftickssyslogfacility, "FTicksPrefix", CONF_STR, &options.fticksprefix, - "IPv4Only", CONF_BLN, &options.ipv4only, - "IPv6Only", CONF_BLN, &options.ipv6only, + "IPv4Only", CONF_BLN, &options.ipv4only, + "IPv6Only", CONF_BLN, &options.ipv6only, NULL )) debugx(1, DBG_ERR, "configuration error"); diff --git a/radsecproxy.h b/radsecproxy.h index 681ba60..230dcdd 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -72,6 +72,13 @@ enum rsp_server_state { RSP_SERVER_STATE_FAILING }; +enum rsp_statsrv { + RSP_STATSRV_OFF = 0, + RSP_STATSRV_ON, + RSP_STATSRV_MINIMAL, + RSP_STATSRV_AUTO +}; + struct options { char *pidfile; char *logdestination; @@ -145,7 +152,7 @@ struct clsrvconf { char *confrewriteusername; struct modattr *rewriteusername; char *dynamiclookupcommand; - uint8_t statusserver; + enum rsp_statsrv statusserver; uint8_t retryinterval; uint8_t retrycount; uint8_t dupinterval; From 719094b985f953afda42927aea7756ca7fcb5bf3 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Mon, 17 Sep 2018 17:34:49 +0200 Subject: [PATCH 02/11] only retry statusserver-autodetect after successful traffic --- radsecproxy.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/radsecproxy.c b/radsecproxy.c index 9bd6453..61d9470 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1818,11 +1818,9 @@ void *clientwr(void *arg) { memset(&timeout, 0, sizeof(struct timespec)); - if (conf->statusserver != RSP_STATSRV_OFF) { - gettimeofday(&server->lastrcv, NULL); - gettimeofday(&laststatsrv, NULL); - } gettimeofday(&server->lastreply, NULL); + server->lastrcv = server->lastreply; + laststatsrv = server->lastreply; if (conf->pdef->connecter) { if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) { @@ -1842,9 +1840,6 @@ void *clientwr(void *arg) { } server->state = RSP_SERVER_STATE_CONNECTED; - if (conf->statusserver == RSP_STATSRV_AUTO) - statusserver_requested = 1; - for (;;) { pthread_mutex_lock(&server->newrq_mutex); if (!server->newrq) { @@ -1929,7 +1924,7 @@ void *clientwr(void *arg) { } } else { if (conf->statusserver == RSP_STATSRV_AUTO && *rqout->rq->buf == RAD_Status_Server) { - if (server->lastrcv.tv_sec >= laststatsrv.tv_sec) { + if (server->lastreply.tv_sec >= laststatsrv.tv_sec) { debug(DBG_DBG, "clientwr: status server autodetect faild, disabling status server for %s", conf->name); conf->statusserver = RSP_STATSRV_OFF; } @@ -1956,11 +1951,10 @@ void *clientwr(void *arg) { } do_resend = 0; if (server->state == RSP_SERVER_STATE_CONNECTED && !conf->statusserver == RSP_STATSRV_OFF) { - secs = server->lastrcv.tv_sec > laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec; gettimeofday(&now, NULL); - if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - secs > STATUS_SERVER_PERIOD) || - ((conf->statusserver == RSP_STATSRV_MINIMAL || conf->statusserver == RSP_STATSRV_AUTO) && - statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD)) { + if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - (laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec) > STATUS_SERVER_PERIOD) || + (conf->statusserver == RSP_STATSRV_MINIMAL && statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD) || + (conf->statusserver == RSP_STATSRV_AUTO && server->lastreply.tv_sec >= laststatsrv.tv_sec)) { laststatsrv = now; statsrvrq = createstatsrvrq(); From b732bdbffa5ea950c973cc93865a3f0b23785ccb Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Sat, 10 Nov 2018 13:20:55 +0100 Subject: [PATCH 03/11] update manpage and changelog --- ChangeLog | 4 ++++ radsecproxy.conf.5 | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 228a532..c5f21a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ changes since 1.7.2 + New features: + - Autodetect status-server capability of servers + - Minimalistic status-server + Misc: - No longer require docbook2x tools, but include plain manpages - Fail on startup if overlapping clients with different tls blocks diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index 1916f1e..ff3ca73 100644 --- a/radsecproxy.conf.5 +++ b/radsecproxy.conf.5 @@ -543,13 +543,18 @@ for the realm and then the SRV records for each NAPTR matching \&'x-eduroam:radius.tls' is provided in \fItools/naptr\-eduroam.sh\fR. .RE -.BR "StatusServer (" on | off ) -.RS -Enable the use of status-server messages for this server (default off). If -statusserver is enabled, the proxy will send regular status-server messages to -the server to verify that it is alive. Status tracking of the server will solely -depend on status-server message and ignore lost requests. This should only be -enabled if the server supports it. +.BR "StatusServer (" on | off | minimal | auto ) +.RS +Enable the use of status-server messages for this server (default \fBoff\fR). If +statusserver is enabled (\fBon\fR), the proxy will send regular status-server +messages to the server to verify that it is alive. Status tracking of the server +will solely depend on status-server message and ignore lost requests. This +should only be enabled if the server supports it. With the option \fBminimal\fR +status-server messages are only sent when regular requests have been lost and no +other replies have been received. + +The option \fBauto\fR tries to detect whether the other server supports +status-server. If so, status-server messages are enabled in \fBminimal\fR mode. .RE .BI "RetryCount " count From 34a71d3cbb6cc9198936f4db2fe8039205b495ab Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 2 Jan 2019 00:12:35 -0800 Subject: [PATCH 04/11] Switch to OpenSSL's THREADID API The old callback was deprecated in version 1.0.0 of OpenSSL Fixes compilation without deprecated APIs enabled on 1.0.2. --- tlscommon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tlscommon.c b/tlscommon.c index e429d12..623b007 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -44,8 +44,8 @@ static uint8_t cookie_secret_initialized = 0; #if OPENSSL_VERSION_NUMBER < 0x10100000 static pthread_mutex_t *ssl_locks = NULL; -unsigned long ssl_thread_id() { - return (unsigned long)pthread_self(); +void ssl_thread_id(CRYPTO_THREADID *id) { + CRYPTO_THREADID_set_numeric(id, (unsigned long)pthread_self()); } void ssl_locking_callback(int mode, int type, const char *file, int line) { @@ -69,7 +69,7 @@ void sslinit() { for (i = 0; i < CRYPTO_num_locks(); i++) { pthread_mutex_init(&ssl_locks[i], NULL); } - CRYPTO_set_id_callback(ssl_thread_id); + CRYPTO_THREADID_set_callback(ssl_thread_id); CRYPTO_set_locking_callback(ssl_locking_callback); SSL_load_error_strings(); #else From fe35459bad751de8dea9ade405ce588bd235d0a6 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 20:44:55 +0200 Subject: [PATCH 05/11] Another spelling fix conneciton -> connection --- tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tls.c b/tls.c index 10622ac..158ca43 100644 --- a/tls.c +++ b/tls.c @@ -276,7 +276,7 @@ unsigned char *radtlsget(SSL *ssl, int timeout, pthread_mutex_t *lock) { len = RADLEN(buf); if (len < 20) { - debug(DBG_ERR, "radtlsget: length too small, malformed packet! closing conneciton!"); + debug(DBG_ERR, "radtlsget: length too small, malformed packet! closing connection!"); pthread_mutex_lock(lock); SSL_shutdown(ssl); pthread_mutex_unlock(lock); From 64524860919679365ced1d0d06dc9d149df20a45 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 20:29:24 +0200 Subject: [PATCH 06/11] Replace SOL_TCP with IPPROTO_TCP SOL_TCP is deprecated and doesn't exist on all platforms (e.g. FreeBSD). IPPROTO_TCP is equivalent and portable. --- util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util.c b/util.c index df6f821..fd9f59c 100644 --- a/util.c +++ b/util.c @@ -129,15 +129,15 @@ void enable_keepalive(int socket) { debug(DBG_NOTICE, "TCP Keepalive feature might be limited on this platform"); #else optval = 3; - if(setsockopt(socket, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPCNT failed"); } optval = 10; - if(setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPIDLE %d failed", optval); } optval = 10; - if(setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { + if(setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) { debug(DBG_ERR, "enable_keepalive: setsockopt TCP_KEEPINTVL failed"); } #endif From b5439433b75733292baf4cbb3162b00a45449711 Mon Sep 17 00:00:00 2001 From: Faidon Liambotis Date: Tue, 8 Jan 2019 18:51:48 +0200 Subject: [PATCH 07/11] Use IP_RECVDSTADDR where applicable IP_PKTINFO is provided by many platforms (Linux among them), but not all. Most notably, FreeBSD does not provide this functionality, but provides a similar one with IP_RECVDSTADDR instead. Make the use of IP_PKTINFO conditional on the constant being defined, and add support for IP_RECVDSTADDR as well, restoring support for FreeBSD. Fixes: #25 --- dtls.c | 18 +++++++++++++++--- radsecproxy.c | 5 +++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/dtls.c b/dtls.c index 7c2c315..6ac1e16 100644 --- a/dtls.c +++ b/dtls.c @@ -400,12 +400,24 @@ int getConnectionInfo(int socket, struct sockaddr *from, socklen_t fromlen, stru if (getsockname(socket, to, &tolen)) return -1; for (ctrlhdr = CMSG_FIRSTHDR(&msghdr); ctrlhdr; ctrlhdr = CMSG_NXTHDR(&msghdr, ctrlhdr)) { +#if defined(IP_PKTINFO) if(ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_PKTINFO) { - debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, &((struct in_pktinfo *)CMSG_DATA(ctrlhdr))->ipi_addr, tmp, sizeof(tmp))); + struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(ctrlhdr); + debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, &(pktinfo->ipi_addr), tmp, sizeof(tmp))); - ((struct sockaddr_in *)to)->sin_addr = ((struct in_pktinfo *)CMSG_DATA(ctrlhdr))->ipi_addr; + ((struct sockaddr_in *)to)->sin_addr = pktinfo->ipi_addr; toaddrfound = 1; - } else if(ctrlhdr->cmsg_level == IPPROTO_IPV6 && ctrlhdr->cmsg_type == IPV6_RECVPKTINFO) { + } +#elif defined(IP_RECVDSTADDR) + if(ctrlhdr->cmsg_level == IPPROTO_IP && ctrlhdr->cmsg_type == IP_RECVDSTADDR) { + struct in_addr *addr = (struct in_addr *)CMSG_DATA(ctrlhdr); + debug(DBG_DBG, "udp packet to: %s", inet_ntop(AF_INET, addr, tmp, sizeof(tmp))); + + ((struct sockaddr_in *)to)->sin_addr = *addr; + toaddrfound = 1; + } +#endif + if(ctrlhdr->cmsg_level == IPPROTO_IPV6 && ctrlhdr->cmsg_type == IPV6_RECVPKTINFO) { info6 = (struct in6_pktinfo *)CMSG_DATA(ctrlhdr); debug(DBG_DBG, "udp packet to: %x", inet_ntop(AF_INET6, &info6->ipi6_addr, tmp, sizeof(tmp))); diff --git a/radsecproxy.c b/radsecproxy.c index e8d7527..70a7d6a 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1997,8 +1997,13 @@ void createlistener(uint8_t type, char *arg) { if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "craetelistener: IPV6_RECVPKTINFO"); } else if (res->ai_family == AF_INET) { +#if defined(IP_PKTINFO) if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) == -1) debugerrno(errno, DBG_WARN, "createlistener: IP_PKTINFO"); +#elif defined(IP_RECVDSTADDR) + if (setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) == -1) + debugerrno(errno, DBG_WARN, "createlistener: IP_RECVDSTADDR"); +#endif } } if (bind(s, res->ai_addr, res->ai_addrlen)) { From b72b59945a11a2d640fc47a054398f65b87430a1 Mon Sep 17 00:00:00 2001 From: Jonathan Tooker Date: Mon, 28 Jan 2019 12:29:37 -0600 Subject: [PATCH 08/11] Spelling fixes --- ChangeLog | 2 +- radsecproxy.conf.5 | 8 ++++---- tools/radsec-dynsrv.sh | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 228a532..236af7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -271,7 +271,7 @@ changes since 1.7.2 2008-10-07 1.2 listenTCP and sourceTCP options renamed to listenTLS and sourceTLS - Old options deprecated but available for backwards compatiblity + Old options deprecated but available for backwards compatibility Logging reply-message attribute from Reject messages Contribution from Arne Schwabe Rewrite blocks have new options addAttribute and modifyAttribute diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index 1916f1e..149c8b6 100644 --- a/radsecproxy.conf.5 +++ b/radsecproxy.conf.5 @@ -189,7 +189,7 @@ See \fIradsecproxy.conf\-example\fR for details. The FTicksMAC option has the same function as LogMAC for FTicks. The default for FTicksMAC is \fBVendorKeyHashed\fR which needs \fBFTicksKey\fR to be set. -Before chosing any of +Before choosing any of .BR Original , .BR FullyHashed or @@ -466,7 +466,7 @@ Apply the operations in the specified \fIrewrite\fR block on incoming (request) or outgoing (response) messages from this client. Rewriting incoming messages is done before, outgoing after other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultClient\fR or \fBdefault\fR will be -applied if defined. No default blocks are appied for \fBRewriteOut\fR. +applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BI "RewriteAttribute User-Name:/" regex / replace / @@ -576,7 +576,7 @@ Apply the operations in the specified \fIrewrite\fR block on outgoing (request) or incoming (response) messages to/from this server. Rewriting outgoing messages is done after, incoming before other processing. If the \fBRewriteIn\fR is not configured, the rewrite blocks \fBdefaultServer\fR or \fBdefault\fR will be -applied if defined. No default blocks are appied for \fBRewriteOut\fR. +applied if defined. No default blocks are applied for \fBRewriteOut\fR. .RE .BR "LoopPrevention (" on | off) @@ -806,7 +806,7 @@ block are: .BI "AddAttribute " attribute \fR: value .RS -Add an \fIattribute\fR to the radius mesage and set it to \fIvalue\fR. The +Add an \fIattribute\fR to the radius message and set it to \fIvalue\fR. The \fIattribute\fR must be specified using the numerical attribute id. The \fIvalue\fR can either be numerical, a string, or a hex value. See the \fBCONFIGURATION SYNTAX\fR section for details. diff --git a/tools/radsec-dynsrv.sh b/tools/radsec-dynsrv.sh index 2c87a33..2eff080 100755 --- a/tools/radsec-dynsrv.sh +++ b/tools/radsec-dynsrv.sh @@ -5,7 +5,7 @@ # realm given as argument, and creates a server template based # on that. It currently ignores weight markers, but does sort # servers on priority marker, lowest number first. -# For host command this is coloumn 5, for dig it is coloumn 1. +# For host command this is column 5, for dig it is column 1. usage() { echo "Usage: ${0} " From 524a096116fe828ce3cd9cd2133a17069b2e2e74 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Wed, 1 May 2019 14:45:37 +0200 Subject: [PATCH 09/11] refactor reconnect timer to avoid platform issues with time_t. Fix #28 --- dtls.c | 51 +++++++++++++++------------------------------- radsecproxy.c | 2 +- radsecproxy.h | 4 ++-- tcp.c | 56 +++++++++++++++++---------------------------------- tls.c | 53 ++++++++++++++++-------------------------------- util.c | 27 +++++++++++++++++++++++++ util.h | 1 + 7 files changed, 83 insertions(+), 111 deletions(-) diff --git a/dtls.c b/dtls.c index 6ac1e16..c4d9fd8 100644 --- a/dtls.c +++ b/dtls.c @@ -35,7 +35,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *dtlslistener(void *arg); -int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *text); +int dtlsconnect(struct server *server, int timeout, char *text); void *dtlsclientrd(void *arg); int clientradputdtls(struct server *server, unsigned char *rad); void addserverextradtls(struct clsrvconf *conf); @@ -514,9 +514,10 @@ void *dtlslistener(void *arg) { return NULL; } -int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval socktimeout, now, start = {0,0}; +int dtlsconnect(struct server *server, int timeout, char *text) { + struct timeval socktimeout, now, start; time_t wait; + int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; struct hostportres *hp; @@ -532,12 +533,7 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * pthread_mutex_unlock(&server->lock); hp = (struct hostportres *)list_first(server->conf->hostports)->data; - - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { /* ensure previous connection is properly closed */ @@ -549,30 +545,18 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * SSL_free(server->ssl); server->ssl = NULL; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - return 0; - } - - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tlsconnect: timeout"); + return 0; } - /* done sleeping */ - debug(DBG_WARN, "dtlsconnect: trying to open DTLS connection to %s port %s", hp->host, hp->port); + debug(DBG_INFO, "dtlsconnect: connecting to %s port %s", hp->host, hp->port); if ((server->sock = bindtoaddr(srcres, hp->addrinfo->ai_family, 0)) < 0) continue; @@ -617,7 +601,7 @@ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char * pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); server->conreset = 1; @@ -659,11 +643,8 @@ int clientradputdtls(struct server *server, unsigned char *rad) { void *dtlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval lastconnecttry; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = raddtlsget(server->ssl, 5, &server->lock); if (!buf) { if(SSL_get_shutdown(server->ssl) || server->lostrqs) { @@ -671,7 +652,7 @@ void *dtlsclientrd(void *arg) { debug (DBG_WARN, "tlscleintrd: connection to server %s lost", server->conf->name); else if (server->lostrqs) debug (DBG_WARN, "dtlsclientrd: server %s did not respond, closing connection.", server->conf->name); - dtlsconnect(server, &lastconnecttry, 0, "dtlsclientrd"); + dtlsconnect(server, 0, "dtlsclientrd"); server->lostrqs = 0; } continue; diff --git a/radsecproxy.c b/radsecproxy.c index 70a7d6a..38f2892 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1823,7 +1823,7 @@ void *clientwr(void *arg) { gettimeofday(&server->lastreply, NULL); if (conf->pdef->connecter) { - if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) { + if (!conf->pdef->connecter(server, server->dynamiclookuparg ? 5 : 0, "clientwr")) { server->state = RSP_SERVER_STATE_FAILING; if (server->dynamiclookuparg) { debug(DBG_WARN, "%s: connect failed, sleeping %ds", diff --git a/radsecproxy.h b/radsecproxy.h index 681ba60..78b949a 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -183,7 +183,7 @@ struct server { pthread_mutex_t lock; pthread_t clientth; uint8_t clientrdgone; - struct timeval lastconnecttry; + struct timeval connecttime; struct timeval lastreply; enum rsp_server_state state; uint8_t lostrqs; @@ -237,7 +237,7 @@ struct protodefs { void (*setprotoopts)(struct commonprotoopts *); char **(*getlistenerargs)(); void *(*listener)(void*); - int (*connecter)(struct server *, struct timeval *, int, char *); + int (*connecter)(struct server *, int, char *); void *(*clientconnreader)(void*); int (*clientradput)(struct server *, unsigned char *); void (*addclient)(struct client *); diff --git a/tcp.c b/tcp.c index 803a549..500abb2 100644 --- a/tcp.c +++ b/tcp.c @@ -29,7 +29,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *tcplistener(void *arg); -int tcpconnect(struct server *server, struct timeval *when, int timeout, char * text); +int tcpconnect(struct server *server, int timeout, char * text); void *tcpclientrd(void *arg); int clientradputtcp(struct server *server, unsigned char *rad); void tcpsetsrcres(); @@ -79,8 +79,9 @@ void tcpsetsrcres() { AF_UNSPEC, NULL, protodefs.socktype); } -int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval now, start = {0,0}; +int tcpconnect(struct server *server, int timeout, char *text) { + struct timeval now, start; + int firsttry = 1; time_t wait; debug(DBG_DBG, "tcpconnect: called from %s", text); @@ -89,43 +90,27 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { if (server->sock >= 0) close(server->sock); server->sock = -1; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; - - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - pthread_mutex_unlock(&server->lock); - return 0; - } - - /* give up lock while sleeping for next try */ - pthread_mutex_unlock(&server->lock); - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - pthread_mutex_lock(&server->lock); - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + pthread_mutex_unlock(&server->lock); + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; + + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tcpconnect: timeout"); + return 0; } + pthread_mutex_lock(&server->lock); + debug(DBG_INFO, "tcpconnect: connecting to %s", server->conf->name); if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) < 0) continue; if (server->conf->keepalive) @@ -133,7 +118,7 @@ int tcpconnect(struct server *server, struct timeval *when, int timeout, char *t break; } server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); @@ -230,16 +215,13 @@ int clientradputtcp(struct server *server, unsigned char *rad) { void *tcpclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval lastconnecttry; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = radtcpget(server->sock, server->dynamiclookuparg ? IDLE_TIMEOUT : 0); if (!buf) { if (server->dynamiclookuparg) break; - tcpconnect(server, &lastconnecttry, 0, "tcpclientrd"); + tcpconnect(server, 0, "tcpclientrd"); continue; } diff --git a/tls.c b/tls.c index 158ca43..85390c4 100644 --- a/tls.c +++ b/tls.c @@ -31,7 +31,7 @@ static void setprotoopts(struct commonprotoopts *opts); static char **getlistenerargs(); void *tlslistener(void *arg); -int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text); +int tlsconnect(struct server *server, int timeout, char *text); void *tlsclientrd(void *arg); int clientradputtls(struct server *server, unsigned char *rad); void tlssetsrcres(); @@ -82,9 +82,10 @@ void tlssetsrcres() { AF_UNSPEC, NULL, protodefs.socktype); } -int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval now, start = {0,0}; +int tlsconnect(struct server *server, int timeout, char *text) { + struct timeval now, start; time_t wait; + int firsttry = 1; X509 *cert; SSL_CTX *ctx = NULL; unsigned long error; @@ -92,17 +93,10 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t debug(DBG_DBG, "tlsconnect: called from %s", text); pthread_mutex_lock(&server->lock); - if (server->state == RSP_SERVER_STATE_CONNECTED) server->state = RSP_SERVER_STATE_RECONNECTING; - pthread_mutex_unlock(&server->lock); - - gettimeofday(&now, NULL); - if (when && (now.tv_sec - when->tv_sec) < 30 ) { - /* last connection was less than 30s ago. Delay next attempt */ - start.tv_sec = now.tv_sec + 30 - (now.tv_sec - when->tv_sec); - } + gettimeofday(&start, NULL); for (;;) { /* ensure previous connection is properly closed */ @@ -114,29 +108,18 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t SSL_free(server->ssl); server->ssl = NULL; - /* no sleep at startup or at first try */ - if (start.tv_sec) { - gettimeofday(&now, NULL); - wait = abs(now.tv_sec - start.tv_sec); - wait = wait > 60 ? 60 : wait; - - if (timeout && (now.tv_sec - start.tv_sec) > timeout) { - debug(DBG_DBG, "tlsconnect: timeout"); - return 0; - } + wait = connect_wait(start, server->connecttime, firsttry); + debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); + sleep(wait); + firsttry = 0; - if (wait < 1) - sleep(2); - else { - debug(DBG_INFO, "Next connection attempt to %s in %lds", server->conf->name, wait); - sleep(wait); - } - debug(DBG_INFO, "tlsconnect: retry connecting to %s", server->conf->name); - } else { - gettimeofday(&start, NULL); + gettimeofday(&now, NULL); + if (timeout && (now.tv_sec - start.tv_sec) > timeout) { + debug(DBG_DBG, "tlsconnect: timeout"); + return 0; } - /* done sleeping */ + debug(DBG_INFO, "tlsconnect: connecting to %s", server->conf->name); if ((server->sock = connecttcphostlist(server->conf->hostports, srcres)) < 0) continue; if (server->conf->keepalive) @@ -181,7 +164,7 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; - gettimeofday(&server->lastconnecttry, NULL); + gettimeofday(&server->connecttime, NULL); server->lostrqs = 0; pthread_mutex_unlock(&server->lock); pthread_mutex_lock(&server->newrq_mutex); @@ -357,11 +340,9 @@ int clientradputtls(struct server *server, unsigned char *rad) { void *tlsclientrd(void *arg) { struct server *server = (struct server *)arg; unsigned char *buf; - struct timeval now, lastconnecttry; + struct timeval now; for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; buf = radtlsget(server->ssl, 10, &server->lock); if (!buf) { if (SSL_get_shutdown(server->ssl) || server->lostrqs) { @@ -371,7 +352,7 @@ void *tlsclientrd(void *arg) { debug (DBG_WARN, "tlsclientrd: server %s did not respond, closing connection.", server->conf->name); if (server->dynamiclookuparg) break; - tlsconnect(server, &lastconnecttry, 0, "tlsclientrd"); + tlsconnect(server, 0, "tlsclientrd"); } if (server->dynamiclookuparg) { gettimeofday(&now, NULL); diff --git a/util.c b/util.c index fd9f59c..eadce8c 100644 --- a/util.c +++ b/util.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "debug.h" #include "util.h" @@ -251,6 +252,32 @@ int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout return s; } +time_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry) { + struct timeval now; + + gettimeofday(&now, NULL); + + if (attempt_start.tv_sec < last_success.tv_sec || + attempt_start.tv_sec > now.tv_sec) { + debug(DBG_WARN, "connect_wait: invalid timers detected!"); + return 60; + } + + if (now.tv_sec - last_success.tv_sec < 30) + return 30 - (attempt_start.tv_sec - last_success.tv_sec); + + if (firsttry) + return 0; + + if (now.tv_sec - attempt_start.tv_sec < 2) + return 2; + + if (now.tv_sec - attempt_start.tv_sec > 60) + return 60; + + return now.tv_sec - attempt_start.tv_sec; +} + /* Local Variables: */ /* c-file-style: "stroustrup" */ /* End: */ diff --git a/util.h b/util.h index 3daad3d..68b1f24 100644 --- a/util.h +++ b/util.h @@ -23,6 +23,7 @@ void disable_DF_bit(int socket, struct addrinfo *res); void enable_keepalive(int socket); int bindtoaddr(struct addrinfo *addrinfo, int family, int reuse); int connecttcp(struct addrinfo *addrinfo, struct addrinfo *src, uint16_t timeout); +time_t connect_wait(struct timeval attempt_start, struct timeval last_success, int firsttry); /* Local Variables: */ From b5978c50f92260388f2144c4dfaab942598989c9 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Tue, 14 May 2019 07:06:07 +0200 Subject: [PATCH 10/11] update ChangeLog --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 236af7f..9bd49bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ changes since 1.7.2 - No longer require docbook2x tools, but include plain manpages - Fail on startup if overlapping clients with different tls blocks + Compile fixes: + - Fix compile issues on bsd + 2018-09-03 1.7.2 Misc: - Always copy proxy-state attributes in own responses From 4e19f7ddda6ed24ccf3386b58f49be311e14b819 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Tue, 14 May 2019 07:35:54 +0200 Subject: [PATCH 11/11] fix compile issue from statusserver-auto for some platforms. --- radsecproxy.c | 2 +- tests/Makefile.am | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/radsecproxy.c b/radsecproxy.c index 86f4c4c..8861626 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1950,7 +1950,7 @@ void *clientwr(void *arg) { pthread_mutex_unlock(rqout->lock); } do_resend = 0; - if (server->state == RSP_SERVER_STATE_CONNECTED && !conf->statusserver == RSP_STATSRV_OFF) { + if (server->state == RSP_SERVER_STATE_CONNECTED && !(conf->statusserver == RSP_STATSRV_OFF)) { gettimeofday(&now, NULL); if ((conf->statusserver == RSP_STATSRV_ON && now.tv_sec - (laststatsrv.tv_sec ? server->lastrcv.tv_sec : laststatsrv.tv_sec) > STATUS_SERVER_PERIOD) || (conf->statusserver == RSP_STATSRV_MINIMAL && statusserver_requested && now.tv_sec - laststatsrv.tv_sec > STATUS_SERVER_PERIOD) || diff --git a/tests/Makefile.am b/tests/Makefile.am index b8fcd19..50f18ca 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -3,5 +3,6 @@ AUTOMAKE_OPTIONS = foreign check_PROGRAMS = t_fticks AM_CFLAGS = -g -Wall -Werror @SSL_CFLAGS@ @TARGET_CFLAGS@ LDADD = $(top_builddir)/librsp.a @SSL_LIBS@ +LDFLAGS = @SSL_LDFLAGS@ @TARGET_LDFLAGS@ TESTS = $(check_PROGRAMS)