X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/95d1f782e772c5dd39d718409edabe1eca92690d..555ae6af39312f43b1d38d8da05cf4368b933015:/src/src/match.c diff --git a/src/src/match.c b/src/src/match.c index ace8e016e..792581790 100644 --- a/src/src/match.c +++ b/src/src/match.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/match.c,v 1.10 2005/09/12 14:03:42 ph10 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for matching strings */ @@ -74,7 +72,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 +98,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 +107,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. */ @@ -425,7 +430,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 @@ -437,6 +442,8 @@ int yield = OK; unsigned int *original_cache_bits = *cache_ptr; BOOL include_unknown = FALSE; BOOL ignore_unknown = FALSE; +BOOL include_defer = FALSE; +BOOL ignore_defer = FALSE; uschar *list; uschar *sss; uschar *ot = NULL; @@ -474,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) @@ -534,10 +553,11 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) } } - /* If the host item is "+include_unknown", remember it in case there's a - subsequent failed reverse lookup. */ + /* If the host item is "+include_unknown" or "+ignore_unknown", remember it + in case there's a subsequent failed reverse lookup. There is similar + processing for "defer". */ - else if (type == MCL_HOST) + else if (type == MCL_HOST && *ss == '+') { if (Ustrcmp(ss, "+include_unknown") == 0) { @@ -551,6 +571,18 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) include_unknown = FALSE; continue; } + if (Ustrcmp(ss, "+include_defer") == 0) + { + include_defer = TRUE; + ignore_defer = FALSE; + continue; + } + if (Ustrcmp(ss, "+ignore_defer") == 0) + { + ignore_defer = TRUE; + include_defer = FALSE; + continue; + } } /* Starting with ! specifies a negative item. It is theoretically possible @@ -696,7 +728,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) else { - uschar *error; + uschar *error = NULL; switch ((func)(arg, ss, valueptr, &error)) { case OK: @@ -705,6 +737,19 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) return yield; case DEFER: + if (error == NULL) + error = string_sprintf("DNS lookup of %s deferred", ss); + if (ignore_defer) + { + HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n", + error); + break; + } + if (include_defer) + { + log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error); + return OK; + } goto DEFER_RETURN; /* The ERROR return occurs when checking hosts, when either a forward @@ -715,7 +760,7 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) 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 @@ -804,13 +849,26 @@ while ((sss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) return file_yield; case DEFER: + if (error == NULL) + error = string_sprintf("DNS lookup of %s deferred", ss); + if (ignore_defer) + { + HDEBUG(D_lists) debug_printf("%s: item ignored by +ignore_defer\n", + error); + break; + } (void)fclose(f); + if (include_defer) + { + log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error); + return OK; + } 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 @@ -844,10 +902,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; } @@ -955,6 +1013,20 @@ error = error; /* Keep clever compilers from complaining */ DEBUG(D_lists) debug_printf("address match: subject=%s pattern=%s\n", subject, pattern); +/* 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. */ @@ -989,10 +1061,6 @@ 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. */