# 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
* 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")) {
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;
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.
/*
* Include substring matches.
*/
- if (regcomp(®, this->realm->name,
+ if (regcomp(®, this->realm->name + 1,
REG_EXTENDED | REG_NOSUB | REG_ICASE) != 0) {
continue;
}