summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--radsecproxy.c54
-rw-r--r--radsecproxy.h1
-rwxr-xr-xtools/naptr-eduroam.sh2
-rwxr-xr-xtools/radsec-dynsrv.sh2
-rw-r--r--udp.c2
6 files changed, 50 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 7b38d95..8ba0401 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,12 +12,19 @@
configured explicitly. This was implemented by Maja
Gorecka-Wolniewicz and Paweł Gołaszewski. (RADSECPROXY-29)
- Add config option PidFile. (RADSECPROXY-32)
+ - Preliminary support for DynamicLookupCommand. It's for TLS
+ servers only at this point. Also, beware of risks for memory
+ leaks.
Bug fixes:
- Stop the autoconfery from warning about defining variables
conditionally and unconditionally.
- Honour configure option --sysconfdir. (RADSECPROXY-31)
- Other bugs. (RADSECPROXY-26, -28, -34, -35, -39)
+ - Don't crash on failing DynamicLookupCommand scripts.
+ - When a DynamicLookupCommand script is failing, fall back to
+ other server(s) in the realm. The timeout depends on the kind of
+ failure.
2011-10-08 1.5
New features:
diff --git a/radsecproxy.c b/radsecproxy.c
index 88c198f..d8500c1 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -64,6 +64,7 @@
#include <libgen.h>
#include <pthread.h>
#include <errno.h>
+#include <assert.h>
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/err.h>
@@ -1306,6 +1307,8 @@ struct clsrvconf *choosesrvconf(struct list *srvconfs) {
server = (struct clsrvconf *)entry->data;
if (!server->servers)
return server;
+ if (server->servers->dynfailing)
+ continue;
if (!first)
first = server;
if (!server->servers->connectionok && !server->servers->dynstartup)
@@ -1344,11 +1347,15 @@ struct server *findserver(struct realm **realm, struct tlv *username, uint8_t ac
pthread_mutex_unlock(&(*realm)->mutex);
freerealm(*realm);
*realm = subrealm;
+ debug(DBG_DBG, "added realm: %s", (*realm)->name);
srvconf = choosesrvconf(acc ? (*realm)->accsrvconfs : (*realm)->srvconfs);
+ debug(DBG_DBG, "found conf for new realm: %s", srvconf->name);
}
}
- if (srvconf)
+ if (srvconf) {
+ debug(DBG_DBG, "found matching conf: %s", srvconf->name);
server = srvconf->servers;
+ }
exit:
free(id);
@@ -1751,18 +1758,25 @@ void *clientwr(void *arg) {
conf = server->conf;
+#define ZZZ 60
+
if (server->dynamiclookuparg && !dynamicconfig(server)) {
dynconffail = 1;
server->dynstartup = 0;
- sleep(900);
+ server->dynfailing = 1;
+ debug(DBG_WARN, "%s: dynamicconfig(%s) failed, sleeping %ds",
+ __func__, server->conf->name, ZZZ);
+ sleep(ZZZ);
goto errexit;
}
+ /* FIXME: Is resolving not always done by compileserverconfig(),
+ * either as part of static configuration setup or by
+ * dynamicconfig() above? */
if (!resolvehostports(conf->hostports, conf->pdef->socktype)) {
- debug(DBG_WARN, "clientwr: resolve failed");
- server->dynstartup = 0;
- sleep(900);
- goto errexit;
+ debug(DBG_WARN, "%s: resolve failed, sleeping %ds", __func__, ZZZ);
+ sleep(ZZZ);
+ goto errexit;
}
memset(&timeout, 0, sizeof(struct timespec));
@@ -1775,8 +1789,11 @@ void *clientwr(void *arg) {
if (conf->pdef->connecter) {
if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) {
if (server->dynamiclookuparg) {
- server->dynstartup = 0;
- sleep(900);
+ server->dynstartup = 0;
+ server->dynfailing = 1;
+ debug(DBG_WARN, "%s: connect failed, sleeping %ds",
+ __func__, ZZZ);
+ sleep(ZZZ);
}
goto errexit;
}
@@ -2173,10 +2190,17 @@ struct list *createsubrealmservers(struct realm *realm, struct list *srvconfs) {
debug(DBG_ERR, "malloc failed");
continue;
}
+ debug(DBG_DBG, "%s: copying config %s", __func__, conf->name);
*srvconf = *conf;
+ /* Shallow copy -- sharing all the pointers. addserver()
+ * will take care of servers (which btw has to be NUL) but
+ * the rest of them are shared with the config found in
+ * the srvconfs list. */
if (addserver(srvconf)) {
srvconf->servers->dynamiclookuparg = stringcopy(realm->name, 0);
srvconf->servers->dynstartup = 1;
+ debug(DBG_DBG, "%s: new client writer for %s",
+ __func__, srvconf->servers->conf->name);
if (pthread_create(&clientth, NULL, clientwr, (void *)(srvconf->servers))) {
debugerrno(errno, DBG_ERR, "pthread_create failed");
freeserver(srvconf->servers, 1);
@@ -2273,14 +2297,9 @@ int dynamicconfig(struct server *server) {
}
if (status) {
- if (WEXITSTATUS(status) == 10) {
- debug(DBG_INFO, "dynamicconfig: command signals empty config");
- }
- else {
- debug(DBG_INFO, "dynamicconfig: command exited with status %d",
- WEXITSTATUS(status));
- goto errexit;
- }
+ debug(DBG_INFO, "dynamicconfig: command exited with status %d",
+ WEXITSTATUS(status));
+ goto errexit;
}
if (ok)
@@ -2544,6 +2563,9 @@ int setttlattr(struct options *opts, char *defaultattr) {
}
void freeclsrvconf(struct clsrvconf *conf) {
+ assert(conf);
+ assert(conf->name);
+ debug(DBG_DBG, "%s: freeing %p (%s)", __func__, conf, conf->name);
free(conf->name);
if (conf->hostsrc)
freegconfmstr(conf->hostsrc);
diff --git a/radsecproxy.h b/radsecproxy.h
index 680a58d..dc09b1e 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -160,6 +160,7 @@ struct server {
uint8_t connectionok;
uint8_t lostrqs;
uint8_t dynstartup;
+ uint8_t dynfailing;
char *dynamiclookuparg;
int nextid;
struct timeval lastrcv;
diff --git a/tools/naptr-eduroam.sh b/tools/naptr-eduroam.sh
index 43d3d9f..6497549 100755
--- a/tools/naptr-eduroam.sh
+++ b/tools/naptr-eduroam.sh
@@ -70,4 +70,4 @@ if [ -n "${SERVERS}" ]; then
exit 0
fi
-exit 0
+exit 10 # No server found.
diff --git a/tools/radsec-dynsrv.sh b/tools/radsec-dynsrv.sh
index 4d00f32..3150018 100755
--- a/tools/radsec-dynsrv.sh
+++ b/tools/radsec-dynsrv.sh
@@ -48,4 +48,4 @@ if test -n "${SERVERS}" ; then
exit 0
fi
-exit 0
+exit 10 # No server found.
diff --git a/udp.c b/udp.c
index 2724a1d..7614f2e 100644
--- a/udp.c
+++ b/udp.c
@@ -24,6 +24,7 @@
#include <arpa/inet.h>
#include <regex.h>
#include <pthread.h>
+#include <assert.h>
#include "radsecproxy.h"
#include "hostport.h"
@@ -317,6 +318,7 @@ void addclientudp(struct client *client) {
}
void addserverextraudp(struct clsrvconf *conf) {
+ assert(list_first(conf->hostports) != NULL);
switch (((struct hostportres *)list_first(conf->hostports)->data)->addrinfo->ai_family) {
case AF_INET:
if (client4_sock < 0) {