Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
keep up with master
  • Loading branch information
Fabian Mauchle committed May 14, 2019
2 parents b3a25b9 + 4e19f7d commit 17f1715
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 179 deletions.
7 changes: 6 additions & 1 deletion ChangeLog
Expand Up @@ -3,11 +3,16 @@ changes since 1.7.2
- Rewrite: supplement attribute (add attribute if not present) (#19)
- Rewrite: modify vendor attribute
- Rewrite whitelist mode
- 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

Compile fixes:
- Fix compile issues on bsd

Bug fixes:
- Handle %00 in config correctly (#31)

Expand Down Expand Up @@ -279,7 +284,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
Expand Down
69 changes: 31 additions & 38 deletions dtls.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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)));

Expand Down Expand Up @@ -502,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;
Expand All @@ -520,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 */
Expand All @@ -537,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;

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_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;
Expand Down Expand Up @@ -605,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;
Expand Down Expand Up @@ -647,19 +643,16 @@ 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) {
if (SSL_get_shutdown(server->ssl))
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;
Expand Down
129 changes: 80 additions & 49 deletions radsecproxy.c
Expand Up @@ -471,7 +471,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)) {
Expand Down Expand Up @@ -1422,9 +1422,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);
Expand Down Expand Up @@ -1537,7 +1539,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;
Expand Down Expand Up @@ -1569,14 +1571,12 @@ void *clientwr(void *arg) {

memset(&timeout, 0, sizeof(struct timespec));

if (conf->statusserver) {
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")) {
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",
Expand All @@ -1600,7 +1600,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;
Expand Down Expand Up @@ -1664,24 +1664,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->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;
}
} 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)
Expand All @@ -1694,19 +1703,22 @@ 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)) {
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) ||
(conf->statusserver == RSP_STATSRV_AUTO && server->lastreply.tv_sec >= laststatsrv.tv_sec)) {

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) {
Expand Down Expand Up @@ -1750,8 +1762,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)) {
Expand Down Expand Up @@ -2462,7 +2479,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;

Expand All @@ -2477,10 +2494,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,
Expand All @@ -2499,7 +2517,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,
Expand Down Expand Up @@ -2575,6 +2593,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;
Expand Down Expand Up @@ -2759,8 +2790,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");
Expand Down

0 comments on commit 17f1715

Please sign in to comment.