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_regex/raddb/proxy.conf 2004-11-16 14:18:00.000000000 +0100 @@ -136,6 +136,22 @@ # secret = testing123 #} +# A realm containing a regular expression, matching anything like +# "user@company2.com" as well as "user@host.company2.com" and "user@somecompany2.com". +# All requests with this realm will be handled locally. +# +# Please note that the regular expressions must be Extended POSIX +# compatible and will be matched case insensitive. +# Additionally, the regex should be the same on all servers of +# a fail-over and round-robin realm. +# +#realm company2.com { +# regex = "^.*company2\.com" +# type = radius +# authhost = LOCAL +# accthost = LOCAL +#} + # A realm entry with an optional fail-over realm. A request from # "user@isp2.com" will be sent to radius.isp2.com as "user@isp2.com", # because the 'nostrip' directive is specified for this realm. diff -ur freeradius-1.0.1/src/include/radiusd.h freeradius-1.0.1-rlm_regex/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_regex/src/include/radiusd.h 2004-11-17 12:38:14.807578329 +0100 @@ -35,6 +35,10 @@ #include #endif +#ifdef HAVE_REGEX_H +#include +#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_regex/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_regex/src/main/files.c 2004-11-17 12:35:00.566433287 +0100 @@ -33,6 +33,10 @@ # include #endif +#ifdef HAVE_REGEX_H +# include +#endif + #include #include #include @@ -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 regex + */ +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_regex/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_regex/src/main/mainconfig.c 2004-11-17 12:40:08.524930196 +0100 @@ -35,6 +35,10 @@ #include #endif +#ifdef HAVE_REGEX_H +#include +#endif + #include "radiusd.h" #include "rad_assert.h" #include "conffile.h" @@ -485,6 +489,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. + */ + char *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 for realm %s, trying to compile it", + c->realm); + c->regex = rad_malloc(sizeof(regex_t)); + + int res = regcomp(c->regex, regex, REG_NOSUB|REG_ICASE|REG_EXTENDED); + 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_regex/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_regex/src/main/proxy.c 2004-11-17 12:42:35.477830014 +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; }