X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Fmatch.c;h=01b52ed0e0c77bb49e2d179a5166a34095a55078;hp=7c30e056c8ab86d6beea6493f2b28ada96706f4d;hb=3c2238744f437aba7215008aed259e4c5af2c57e;hpb=c988f1f4faa9f679f79beddf3c14676c5dcb8e28 diff --git a/src/src/match.c b/src/src/match.c index 7c30e056c..01b52ed0e 100644 --- a/src/src/match.c +++ b/src/src/match.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/match.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */ +/* $Cambridge: exim/src/src/match.c,v 1.17 2007/01/08 10:50:18 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2007 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for matching strings */ @@ -74,7 +74,8 @@ Arguments: returns ERROR) Contents of the argument block: - subject the subject string to be checked + origsubject the subject in its original casing + subject the subject string to be checked, lowercased if caseless expand_setup if < 0, don't set up any numeric expansion variables; if = 0, set $0 to whole subject, and either $1 to what matches * or @@ -99,7 +100,7 @@ check_string_block *cb = (check_string_block *)arg; int search_type, partial, affixlen, starflags; int expand_setup = cb->expand_setup; uschar *affix; -uschar *s = cb->subject; +uschar *s; uschar *filename = NULL; uschar *keyquery, *result, *semicolon; void *handle; @@ -108,6 +109,12 @@ error = error; /* Keep clever compilers from complaining */ if (valueptr != NULL) *valueptr = NULL; /* For non-lookup matches */ +/* For regular expressions, use cb->origsubject rather than cb->subject so that +it works if the pattern uses (?-i) to turn off case-independence, overriding +"caseless". */ + +s = (pattern[0] == '^')? cb->origsubject : cb->subject; + /* If required to set up $0, initialize the data but don't turn on by setting expand_nmax until the match is assured. */ @@ -174,7 +181,9 @@ if (cb->at_is_special && pattern[0] == '@') int slen = Ustrlen(s); if (s[0] != '[' && s[slen-1] != ']') return FAIL; for (ip = host_find_interfaces(); ip != NULL; ip = ip->next) - if (Ustrncmp(ip->address, s+1, slen - 2) == 0) return OK; + if (Ustrncmp(ip->address, s+1, slen - 2) == 0 + && ip->address[slen - 2] == 0) + return OK; return FAIL; } @@ -266,12 +275,20 @@ up user@domain for sender rejection). There's a flag to disable it. */ if (!cb->use_partial) partial = -1; -/* Set the parameters for the two different kinds of lookup. */ +/* Set the parameters for the three different kinds of lookup. */ keyquery = semicolon + 1; while (isspace(*keyquery)) keyquery++; -if (!mac_islookup(search_type, lookup_querystyle)) +if (mac_islookup(search_type, lookup_absfilequery)) + { + filename = keyquery; + while (*keyquery != 0 && !isspace(*keyquery)) keyquery++; + filename = string_copyn(filename, keyquery - filename); + while (isspace(*keyquery)) keyquery++; + } + +else if (!mac_islookup(search_type, lookup_querystyle)) { filename = keyquery; keyquery = s; @@ -415,7 +432,7 @@ Returns: OK if matched a non-negated item FAIL if expansion force-failed FAIL if matched a negated item FAIL if hit end of list after a non-negated item - DEFER if a lookup deferred or expansion failed + DEFER if a something deferred or expansion failed */ int @@ -464,7 +481,19 @@ if (type >= MCL_NOEXPAND) } else { - list = expand_string(*listptr); + /* If we are searching a domain list, and $domain is not set, set it to the + subject that is being sought for the duration of the expansion. */ + + if (type == MCL_DOMAIN && deliver_domain == NULL) + { + check_string_block *cb = (check_string_block *)arg; + deliver_domain = cb->subject; + list = expand_string(*listptr); + deliver_domain = NULL; + } + + else list = expand_string(*listptr); + if (list == NULL) { if (expand_string_forcedfail) @@ -630,9 +659,11 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) store_pool = POOL_PERM; p = store_get(sizeof(namedlist_cacheblock)); p->key = string_copy(get_check_key(arg, type)); + + + p->data = (*valueptr == NULL)? NULL : string_copy(*valueptr); store_pool = old_pool; - p->data = *valueptr; p->next = nb->cache_data; nb->cache_data = p; if (*valueptr != NULL) @@ -695,21 +726,27 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) case DEFER: goto DEFER_RETURN; - /* The ERROR return occurs only when checking hosts, when either a - forward or reverse lookup has failed. The error string gives details of + /* The ERROR return occurs when checking hosts, when either a forward + or reverse lookup has failed. It can also occur in a match_ip list if a + non-IP address item is encountered. The error string gives details of which it was. */ case ERROR: if (ignore_unknown) { - HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown", + HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n", error); } else { HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot, include_unknown? "yes":"no", error); - if (!include_unknown) return FAIL; + if (!include_unknown) + { + if ((log_extra_selector & LX_unknown_in_list) != 0) + log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); + return FAIL; + } log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error); return OK; } @@ -780,27 +817,32 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) switch ((func)(arg, ss, valueptr, &error)) { case OK: - fclose(f); + (void)fclose(f); HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\" in %s)\n", ot, (yield == OK)? "yes" : "no", sss, filename); return file_yield; case DEFER: - fclose(f); + (void)fclose(f); goto DEFER_RETURN; case ERROR: /* host name lookup failed - this can only */ if (ignore_unknown) /* be for an incoming host (not outgoing) */ { - HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown", + HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_unknown\n", error); } else { HDEBUG(D_lists) debug_printf("%s %s (%s)\n", ot, include_unknown? "yes":"no", error); - fclose(f); - if (!include_unknown) return FAIL; + (void)fclose(f); + if (!include_unknown) + { + if ((log_extra_selector & LX_unknown_in_list) != 0) + log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); + return FAIL; + } log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error); return OK; } @@ -811,7 +853,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) for the file, in case this is the last item in the list. */ yield = file_yield; - fclose(f); + (void)fclose(f); } } /* Loop for the next item on the top-level list */ @@ -821,10 +863,10 @@ HDEBUG(D_lists) debug_printf("%s %s (end of list)\n", ot, (yield == OK)? "no":"yes"); return (yield == OK)? FAIL : OK; -/* Handle lookup defer */ +/* Something deferred */ DEFER_RETURN: -HDEBUG(D_lists) debug_printf("%s lookup deferred for %s\n", ot, sss); +HDEBUG(D_lists) debug_printf("%s list match deferred for %s\n", ot, sss); return DEFER; } @@ -932,7 +974,21 @@ error = error; /* Keep clever compilers from complaining */ DEBUG(D_lists) debug_printf("address match: subject=%s pattern=%s\n", subject, pattern); -/* Handle a regular expression, which must match the entire incoming address. +/* Find the subject's domain */ + +sdomain = Ustrrchr(subject, '@'); + +/* The only case where a subject may not have a domain is if the subject is +empty. Otherwise, a subject with no domain is a serious configuration error. */ + +if (sdomain == NULL && *subject != 0) + { + log_write(0, LOG_MAIN|LOG_PANIC, "no @ found in the subject of an " + "address list match: subject=\"%s\" pattern=\"%s\"", subject, pattern); + return FAIL; + } + +/* Handle a regular expression, which must match the entire incoming address. This may be the empty address. */ if (*pattern == '^') @@ -947,7 +1003,7 @@ for (s = pattern; isalnum(*s) || *s == '-'; s++); if (*s == '*') s++; if (*s == '@') s++; -/* If it is a straight lookup, do a lookup for the whole address. This may be +/* If it is a straight lookup, do a lookup for the whole address. This may be the empty address. Partial matching doesn't make sense here, so we ignore it, but write a panic log entry. However, *@ matching will be honoured. */ @@ -960,16 +1016,12 @@ if (*s == ';') valueptr); } -/* For the remaining cases, an empty subject matches only an empty pattern, -because other patterns expect to have a local part and a domain to match +/* For the remaining cases, an empty subject matches only an empty pattern, +because other patterns expect to have a local part and a domain to match against. */ if (*subject == 0) return (*pattern == 0)? OK : FAIL; -/* Find the subject's domain */ - -sdomain = Ustrrchr(subject, '@'); - /* If the pattern starts with "@@" we have a split lookup, where the domain is looked up to obtain a list of local parts. If the subject's local part is just "*" (called from retry) the match always fails. */