Define realm_find2() where the argument is the realm name
authoraland <aland>
Fri, 18 Apr 2008 09:29:49 +0000 (09:29 +0000)
committeraland <aland>
Fri, 18 Apr 2008 09:29:49 +0000 (09:29 +0000)
previously found in realm_find().

Make the appropriate functions use it.

Document regex realms.

raddb/proxy.conf
src/include/realms.h
src/main/acct.c
src/main/auth.c
src/main/event.c
src/main/realms.c

index ded7673..fe0b603 100644 (file)
@@ -570,3 +570,64 @@ realm LOCAL {
 #      virtual_server = virtual.example.com
 #}
 #
+
+#
+#  Regular expressions may also be used as realm names.  If these are used,
+#  then the "find matching realm" process is as follows:
+#
+#    1) Look for a non-regex realm with an *exact* match for the name.
+#       If found, it is used in preference to any regex matching realm.
+#
+#    2) Look for a regex realm, in the order that they are listed
+#       in the configuration files.  Any regex match is performed in
+#      a case-insensitive fashion.
+#
+#    3) If no realm is found, return the DEFAULT realm, if any.
+#
+#  The order of the realms matters in step (2).  For example, defining
+#  two realms "*.example.com" and "*.test.example.com" will result in
+#  the second realm NEVER matching.  This is because all of the realms
+#  which match the second regex also match the first one.  Since the
+#  first regex matches, it is returned.
+#
+#  The solution is to list the realms in the opposite order,. e.g.
+#  "*.test.example.com", followed by "*.example.com".
+#
+#
+#  Some helpful rules:
+#
+#   - always place a '~' character at the start of the realm name.
+#     This signifies that it is a regex match, and not an exact match
+#     for the realm.
+#
+#   - place the regex in double quotes.  This helps the configuration
+#     file parser ignore any "special" characters in the regex.
+#     Yes, this rule is different than the normal "unlang" rules for
+#     regular expressions.  That may be fixed in a future release.
+#
+#   - use two back-slashes '\\' whenever you need one backslash in the
+#     regex.  e.g. "~*\\.example\\.com", and not "~*\.example\.com".
+#     This is because the regex is in a double-quoted string, and normal
+#     rules apply for double-quoted strings.
+#
+#   - If you are matching domain names, use two backslashes in front of
+#     every '.' (dot or period).  This is because '.' has special meaning
+#     in a regular expression: match any character.  If you do not do this,
+#     then "~*.example.com" will match "fooXexampleYcom", which is likely
+#     not what you want
+#
+#   - If you are matching domain names, put a '$' at the end of the regex
+#     that matches the domain name.  This tells the regex matching code
+#     that the realm ENDS with the domain name, so it does not match
+#     realms with the domain name in the middle.  e.g. "~*\\.example\\.com"
+#     will match "test.example.comFOO", which is likely not what you want.
+#     Using "~*\\.example\\.com$" is better.
+#
+#  The more regex realms that are defined, the more time it takes to
+#  process them.  You should define as few regex realms as possible
+#  in order to maximize server performance.
+#
+#realm "~*\\.example\\.com$" {
+#      authhost = LOCAL             # not strictly necessary
+#      accthost = LOCAL             # not strictly necessary
+#}
\ No newline at end of file
index c6d030e..b838d1f 100644 (file)
@@ -105,7 +105,8 @@ typedef struct _realm {
 
 int realms_init(CONF_SECTION *config);
 void realms_free(void);
-REALM *realm_find(const char *name);
+REALM *realm_find(const char *name); /* name is from a packet */
+REALM *realm_find2(const char *name); /* ... with name taken from realm_find */
 
 home_server *home_server_ldb(const char *realmname, home_pool_t *pool, REQUEST *request);
 home_server *home_server_find(fr_ipaddr_t *ipaddr, int port);
index f31c092..91ff87e 100644 (file)
@@ -121,7 +121,7 @@ int rad_accounting(REQUEST *request)
                         *      Check whether Proxy-To-Realm is
                         *      a LOCAL realm.
                         */
-                       realm = realm_find(vp->vp_strvalue);
+                       realm = realm_find2(vp->vp_strvalue);
                        if (realm && !realm->acct_pool) {
                                DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->name);
                                pairdelete(&request->config_items, PW_PROXY_TO_REALM);
index 33de8c7..25ebfe3 100644 (file)
@@ -589,7 +589,7 @@ autz_redo:
            ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {
                REALM *realm;
 
-               realm = realm_find(tmp->vp_strvalue);
+               realm = realm_find2(tmp->vp_strvalue);
 
                /*
                 *      Don't authenticate, as the request is going to
index 3b45a2c..5334c7c 100644 (file)
@@ -1242,7 +1242,7 @@ static int successfully_proxied_request(REQUEST *request)
 
        realmname = (char *) realmpair->vp_strvalue;
 
-       realm = realm_find(realmname);
+       realm = realm_find2(realmname);
        if (!realm) {
                DEBUG2("ERROR: Cannot proxy to unknown realm %s", realmname);
                return 0;
index f3070a6..2e51e91 100644 (file)
@@ -1279,7 +1279,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
         *      The realm MAY already exist if it's an old-style realm.
         *      In that case, merge the old-style realm with this one.
         */
-       r = realm_find(name2);
+       r = realm_find2(name2);
        if (r && (strcmp(r->name, name2) == 0)) {
                if (cf_pair_find(cs, "auth_pool") ||
                    cf_pair_find(cs, "acct_pool")) {
@@ -1368,7 +1368,7 @@ static int realm_add(realm_config_t *rc, CONF_SECTION *cs)
                last = &realms_regex;
                while (*last) last = &((*last)->next);  /* O(N^2)... sue me. */
 
-               r->name = name2 + 1; /* skip the '~' */
+               r->name = name2;
                rr->realm = r;
                rr->next = NULL;
 
@@ -1464,6 +1464,39 @@ int realms_init(CONF_SECTION *config)
        return 1;
 }
 
+/*
+ *     Find a realm where "name" might be the regex.
+ */
+REALM *realm_find2(const char *name)
+{
+       REALM myrealm;
+       REALM *realm;
+       
+       if (!name) name = "NULL";
+
+       myrealm.name = name;
+       realm = rbtree_finddata(realms_byname, &myrealm);
+       if (realm) return realm;
+
+#ifdef HAVE_REGEX_H
+       if (realms_regex) {
+               realm_regex_t *this;
+
+               for (this = realms_regex; this != NULL; this = this->next) {
+                       if (strcmp(this->realm->name, name) == 0) {
+                               return this->realm;
+                       }
+               }
+       }
+#endif
+
+       /*
+        *      Couldn't find a realm.  Look for DEFAULT.
+        */
+       myrealm.name = "DEFAULT";
+       return rbtree_finddata(realms_byname, &myrealm);
+}
+
 
 /*
  *     Find a realm in the REALM list.
@@ -1490,7 +1523,7 @@ REALM *realm_find(const char *name)
                        /*
                         *      Include substring matches.
                         */
-                       if (regcomp(&reg, this->realm->name,
+                       if (regcomp(&reg, this->realm->name + 1,
                                    REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
                                continue;
                        }