Merge branch 'master' into dynconf2
authorLinus Nordberg <linus@nordu.net>
Thu, 12 Apr 2012 18:20:38 +0000 (20:20 +0200)
committerLinus Nordberg <linus@nordu.net>
Thu, 12 Apr 2012 18:20:38 +0000 (20:20 +0200)
ChangeLog
radsecproxy.c
radsecproxy.h
tools/naptr-eduroam.sh
tools/radsec-dynsrv.sh
udp.c

index 7b38d95..8ba0401 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        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:
index 88c198f..d8500c1 100644 (file)
@@ -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);
index 680a58d..dc09b1e 100644 (file)
@@ -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;
index 43d3d9f..6497549 100755 (executable)
@@ -70,4 +70,4 @@ if [ -n "${SERVERS}" ]; then
     exit 0
 fi
 
-exit 0
+exit 10                                # No server found.
index 4d00f32..3150018 100755 (executable)
@@ -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 (file)
--- 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) {