Hello!

======================================
Regular expression matching in proxy.conf
enables very flexible and intiutive realm
proxying. It can reduce number of
realm entries:

realm company2.com {
      regexp          = "^.*\.company2\.com$"
      type            = radius
      authhost        = rad.company2.com
      accthost        = rad.company2.com
}

======================================
I'm operating a TLD radius server and "delegating"
certain RADIUS realms to sub-node RADIUS severs.
We have built a sort of RADIUS tree structure.

For example (radiator config):
<Handler Realm=/^subX\.tld$|^.*\.subX\.tld$/>
        <AuthBy RADIUS>
 [...]
        </AuthBy>
</Handler>

The subX.org.tld are usualy freeradius servers, that
define a subX.tld and a few subsub1.subX.tld,
subsub2.subX.tld, subsub3.subX.tld.

This can be dangerous, becouse I delegate all *.subX.tld
to the organisation and they delegate DEFAULT to me.
So for a non-existant subsub4.subX.tld we create a RADIUS
loop :)))).

I could:
- delegate realms strictly (too much administration on my part and
too restrictive for subX operators)
- implement split horizont in TLD server (I might do this,
but I prefer to enhance free software)
- imeplement regexp realm matching in freeradius (this is this
patch)

======================================
proxy.conf:

# Local realms
realm subsub1.orgX.tld {
}
realm subsub2.orgX.tld {
}
realm subsub3.orgX.tld {
}
realm NULL {
}

# this realm is matched by:
#    *.orgX.tld
#    blackhole.orgX.tld
# blackhole is handled locally (denied)
realm blackhole.orgX.tld {
        regex           = "^.*\.orgX\.tld$"
}

realm DEFAULT {
        type            = radius
        authhost        = radius.tld:1812
        accthost        = radius.tld:1813
        secret          = blah
        nostrip
}
======================================
users:
DEFAULT Realm == blackhole.orgX.tld, Auth-Type := Reject

======================================
This patch is based on this regex patch:
http://projects.nuschkys.net/patches/

I've cleaned it up a bit and did some testing.
It seems to work fine and not add overhead if
no regex is used. It also makes realm proxying
in freeradius very flexible and intiutive.

Appreciate any review :).

======================================
diff -ur freeradius-1.0.1/raddb/proxy.conf 
freeradius-1.0.1-rlm_regexp/raddb/proxy.conf
--- freeradius-1.0.1/raddb/proxy.conf   2004-02-26 17:16:32.000000000 +0100
+++ freeradius-1.0.1-rlm_regexp/raddb/proxy.conf        2004-11-17 
14:47:41.000000000 +0100
@@ -136,6 +136,22 @@
 #      secret          = testing123
 #}
 
+#  A realm containing a regular expression, matching anything like
+#  "[EMAIL PROTECTED]" as well as "[EMAIL PROTECTED]". All 
+#  requests with this realm will be handled locally.
+#
+#  Please note that the regular expressions must be POSIX compatible
+#  and will be matched case insensitive.
+#  Additionally, the regexp should be the same on all servers of
+#  a fail-over and round-robin realm.
+# 
+#realm company2.com {
+#      regexp          = "^.*\.company2\.com$"
+#      type            = radius
+#      authhost        = rad.company2.com
+#      accthost        = rad.company2.com
+#}
+
 #  A realm entry with an optional fail-over realm.  A request from
 #  "[EMAIL PROTECTED]" will be sent to radius.isp2.com as "[EMAIL PROTECTED]",
 #  because the 'nostrip' directive is specified for this realm.
diff -ur freeradius-1.0.1/src/include/radiusd.h 
freeradius-1.0.1-rlm_regexp/src/include/radiusd.h
--- freeradius-1.0.1/src/include/radiusd.h      2004-09-09 16:31:06.000000000 
+0200
+++ freeradius-1.0.1-rlm_regexp/src/include/radiusd.h   2004-11-17 
14:47:41.000000000 +0100
@@ -35,6 +35,10 @@
 #include <arpa/inet.h>
 #endif
 
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
 #include "missing.h"
 
 #define NO_SUCH_CHILD_PID (child_pid_t) (0)
@@ -139,6 +143,10 @@
        int                     acct_active;
        time_t                  acct_wakeup;
        int                     ldflag;
+#ifdef HAVE_REGEX_H
+       regex_t                 *regex;
+#endif
+
        struct _realm           *next;
 } REALM;
 
@@ -328,6 +336,7 @@
 void           clients_free(RADCLIENT *cl);
 
 /* files.c */
+int            realm_find_cmp(const REALM *rlm, const char *realm);
 REALM          *realm_find(const char *, int);
 REALM          *realm_findbyaddr(uint32_t ipno, int port);
 void           realm_free(REALM *cl);
diff -ur freeradius-1.0.1/src/main/files.c 
freeradius-1.0.1-rlm_regexp/src/main/files.c
--- freeradius-1.0.1/src/main/files.c   2004-04-06 22:43:49.000000000 +0200
+++ freeradius-1.0.1-rlm_regexp/src/main/files.c        2004-11-17 
14:47:41.000000000 +0100
@@ -33,6 +33,10 @@
 #      include <netinet/in.h>
 #endif
 
+#ifdef HAVE_REGEX_H
+#      include <regex.h>
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #include <netdb.h>
@@ -314,6 +318,12 @@
 
        while(cl) {
                next = cl->next;
+#ifdef HAVE_REGEX_H
+               if (cl->regex != NULL) {
+                       regfree(cl->regex);
+                       free(cl->regex);
+               }
+#endif
                free(cl);
                cl = next;
        }
@@ -435,6 +445,14 @@
                c->active = TRUE;
                c->acct_active = TRUE;
 
+               /*
+                * Regular expressions for realms are not supported 
+                * with the old-style realm file
+                */
+#ifdef HAVE_REGEX_H
+               c->regex = NULL;
+#endif
+
                while (getword(&p, opts, sizeof(opts))) {
                        if (strcmp(opts, "nostrip") == 0)
                                c->striprealm = FALSE;
@@ -504,6 +522,21 @@
 }
 
 /*
+ *      Compare a realm name with entry
+ *      If enabled also compare with regexp
+ */
+int realm_find_cmp(const REALM *rlm, const char *realm) {
+#ifdef HAVE_REGEX_H
+               if ((rlm->regex != NULL) &&
+                       (regexec(rlm->regex, realm, 0, NULL, 0) == 0)) {
+                       return 0;
+               }
+#endif /* HAVE_REGEX_H */
+
+        return(strcasecmp(rlm->realm, realm));
+}
+
+/*
  *     Find a realm in the REALM list.
  */
 REALM *realm_find(const char *realm, int accounting)
@@ -548,7 +581,7 @@
                         *      dead.
                         */
                        if ((!mainconfig.proxy_fallback) &&
-                           (strcasecmp(cl->realm, realm) == 0)) {
+                           (realm_find_cmp(cl, realm) == 0)) {
                                dead_match = 1;
                        }
                        continue;
@@ -562,7 +595,7 @@
                 *      scatter techniques, as that's more properly
                 *      the responsibility of the proxying code.
                 */
-               if (strcasecmp(cl->realm, realm) == 0) {
+               if (realm_find_cmp(cl, realm) == 0) {
                        return cl;
                }
 
@@ -585,7 +618,7 @@
                if (mainconfig.wake_all_if_all_dead) {
                        REALM *rcl = NULL;
                        for (cl = mainconfig.realms; cl; cl = cl->next) {
-                               if(strcasecmp(cl->realm,realm) == 0) {
+                               if(realm_find_cmp(cl,realm) == 0) {
                                        if (!accounting && !cl->active) {
                                                cl->active = TRUE;
                                                rcl = cl;
diff -ur freeradius-1.0.1/src/main/mainconfig.c 
freeradius-1.0.1-rlm_regexp/src/main/mainconfig.c
--- freeradius-1.0.1/src/main/mainconfig.c      2004-06-08 17:09:40.000000000 
+0200
+++ freeradius-1.0.1-rlm_regexp/src/main/mainconfig.c   2004-11-18 
08:04:26.000000000 +0100
@@ -35,6 +35,10 @@
 #include <arpa/inet.h>
 #endif
 
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
 #include "radiusd.h"
 #include "rad_assert.h"
 #include "conffile.h"
@@ -349,6 +353,9 @@
        REALM *c, **tail;
        char *s, *t, *authhost, *accthost;
        char *name2;
+#ifdef HAVE_REGEX_H
+       char *regex;
+#endif /* HAVE_REGEX_H */
 
        tail = &my_realms;
        for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
@@ -485,6 +492,30 @@
 
                c->striprealm = 1;
 
+#ifdef HAVE_REGEX_H
+               /*
+                *      If the realm has a regex configured, try to
+                *      precompile it and store it in the realm struct.
+                */
+               regex = cf_section_value_find(cs, "regex");
+               if (regex != NULL && strcmp(c->realm, "NULL") && 
strcmp(c->realm, "DEFAULT")) {
+                       DEBUG2("read_config_files: found a regular expression 
\"%s\" for realm %s",
+                              regex, c->realm);
+                       c->regex = rad_malloc(sizeof(regex_t));
+
+                       int res = regcomp(c->regex, regex, REG_NOSUB|REG_ICASE);
+                       if (res != 0) {
+                               char msg[128];
+
+                               regerror(res, c->regex, msg, sizeof(msg));
+                               radlog(L_ERR, "%s[%d]: Found illegal regular 
expression %s, disabling regex support for realm %s.",
+                                      filename, cf_section_lineno(cs), msg, 
c->realm);
+
+                               return -1;
+                       }
+               }
+#endif
+
                if ((cf_section_value_find(cs, "nostrip")) != NULL)
                        c->striprealm = 0;
                if ((cf_section_value_find(cs, "noacct")) != NULL)
diff -ur freeradius-1.0.1/src/main/proxy.c 
freeradius-1.0.1-rlm_regexp/src/main/proxy.c
--- freeradius-1.0.1/src/main/proxy.c   2004-05-28 23:45:07.000000000 +0200
+++ freeradius-1.0.1-rlm_regexp/src/main/proxy.c        2004-11-17 
14:47:42.000000000 +0100
@@ -150,7 +150,7 @@
                /*
                 *      The realm name doesn't match, skip it.
                 */
-               if (strcasecmp(cl->realm, realm_name) != 0) {
+               if (realm_find_cmp(cl, realm_name) != 0) {
                        continue;
                }

-- 
lep pozdrav,
Rok Papež.

-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

Reply via email to