X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/0f9b04830a9428a58730cc6a60faa9a169522dc3..fb2274d4a2c4398a497fbec5cacebaab7d20a127:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 97a9dbe5e..439e9d424 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.10 2005/01/02 18:22:05 ph10 Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.20 2005/03/08 15:32:02 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2005 */ /* See the file NOTICE for conditions of use and distribution. */ /* Code for handling Access Control Lists (ACLs) */ @@ -45,7 +45,15 @@ ACLC_CONDITION, ACLC_CONTROL, ACLC_DELAY, #ifdef WITH_OLD_DEMIME ACLC_DEMIME, -#endif +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS + ACLC_DK_DOMAIN_SOURCE, + ACLC_DK_POLICY, + ACLC_DK_SENDER_DOMAINS, + ACLC_DK_SENDER_LOCAL_PARTS, + ACLC_DK_SENDERS, + ACLC_DK_STATUS, +#endif ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS, ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE, #ifdef WITH_CONTENT_SCAN @@ -61,7 +69,7 @@ ACLC_CONDITION, ACLC_CONTROL, #endif ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET, #ifdef WITH_CONTENT_SCAN - ACLC_SPAM, + ACLC_SPAM, #endif #ifdef EXPERIMENTAL_SPF ACLC_SPF, @@ -77,13 +85,21 @@ static uschar *conditions[] = { US"acl", US"authenticated", US"bmi_optin", #endif US"condition", - US"control", + US"control", #ifdef WITH_CONTENT_SCAN US"decode", #endif US"delay", #ifdef WITH_OLD_DEMIME US"demime", +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS + US"dk_domain_source", + US"dk_policy", + US"dk_sender_domains", + US"dk_sender_local_parts", + US"dk_senders", + US"dk_status", #endif US"dnslists", US"domains", US"encrypted", US"endpass", US"hosts", US"local_parts", US"log_message", US"logwrite", @@ -106,12 +122,12 @@ static uschar *conditions[] = { US"acl", US"authenticated", US"spf", #endif US"verify" }; - + /* ACL control names */ static uschar *controls[] = { US"error", US"caseful_local_part", US"caselower_local_part", US"enforce_sync", US"no_enforce_sync", US"freeze", - US"queue_only", US"submission", US"no_multiline"}; + US"queue_only", US"submission", US"no_multiline"}; /* Flags to indicate for which conditions /modifiers a string expansion is done at the outer level. In the other cases, expansion already occurs in the @@ -122,7 +138,7 @@ static uschar cond_expand_at_top[] = { FALSE, /* authenticated */ #ifdef EXPERIMENTAL_BRIGHTMAIL TRUE, /* bmi_optin */ -#endif +#endif TRUE, /* condition */ TRUE, /* control */ #ifdef WITH_CONTENT_SCAN @@ -131,6 +147,14 @@ static uschar cond_expand_at_top[] = { TRUE, /* delay */ #ifdef WITH_OLD_DEMIME TRUE, /* demime */ +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS + TRUE, + TRUE, + TRUE, + TRUE, + TRUE, + TRUE, #endif TRUE, /* dnslists */ FALSE, /* domains */ @@ -170,7 +194,7 @@ static uschar cond_modifiers[] = { FALSE, /* authenticated */ #ifdef EXPERIMENTAL_BRIGHTMAIL TRUE, /* bmi_optin */ -#endif +#endif FALSE, /* condition */ TRUE, /* control */ #ifdef WITH_CONTENT_SCAN @@ -179,6 +203,14 @@ static uschar cond_modifiers[] = { TRUE, /* delay */ #ifdef WITH_OLD_DEMIME FALSE, /* demime */ +#endif +#ifdef EXPERIMENTAL_DOMAINKEYS + FALSE, + FALSE, + FALSE, + FALSE, + FALSE, + FALSE, #endif FALSE, /* dnslists */ FALSE, /* domains */ @@ -216,26 +248,27 @@ each condition, there's a bitmap of dis-allowed times. */ static unsigned int cond_forbids[] = { 0, /* acl */ + (1< 0) { newtype = htype_add_rfc; p += 14; - } + } else if (strncmpic(p, US":at_start:", 10) == 0) { newtype = htype_add_top; @@ -1052,11 +1162,11 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) uschar *opt; uschar buffer[256]; while (isspace(*ss)) ss++; - - /* This callout option handling code has become a mess as new options - have been added in an ad hoc manner. It should be tidied up into some + + /* This callout option handling code has become a mess as new options + have been added in an ad hoc manner. It should be tidied up into some kind of table-driven thing. */ - + while ((opt = string_nextinlist(&ss, &optsep, buffer, sizeof(buffer))) != NULL) { @@ -1188,13 +1298,19 @@ message if giving out verification details. */ if (verify_header_sender) { + int verrno; rc = verify_check_header_address(user_msgptr, log_msgptr, callout, - callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options); - if (smtp_return_error_details) + callout_overall, callout_connect, se_mailfrom, pm_mailfrom, verify_options, + &verrno); + if (rc != OK) { - if (*user_msgptr == NULL && *log_msgptr != NULL) - *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr); - if (rc == DEFER) acl_temp_details = TRUE; + *basic_errno = verrno; + if (smtp_return_error_details) + { + if (*user_msgptr == NULL && *log_msgptr != NULL) + *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr); + if (rc == DEFER) acl_temp_details = TRUE; + } } } @@ -1254,7 +1370,7 @@ else if (verify_sender_address != NULL) { BOOL routed = TRUE; uschar *save_address_data = deliver_address_data; - + sender_vaddr = deliver_make_addr(verify_sender_address, TRUE); if (no_details) setflag(sender_vaddr, af_sverify_told); if (verify_sender_address[0] != 0) @@ -1300,16 +1416,16 @@ else if (verify_sender_address != NULL) sender_vaddr->special_action = rc; sender_vaddr->next = sender_verified_list; sender_verified_list = sender_vaddr; - - /* Restore the recipient address data, which might have been clobbered by + + /* Restore the recipient address data, which might have been clobbered by the sender verification. */ - + deliver_address_data = save_address_data; } - + /* Put the sender address_data value into $sender_address_data */ - sender_address_data = sender_vaddr->p.address_data; + sender_address_data = sender_vaddr->p.address_data; } /* A recipient address just gets a straightforward verify; again we must handle @@ -1326,8 +1442,10 @@ else rc = verify_address(&addr2, NULL, verify_options|vopt_is_recipient, callout, callout_overall, callout_connect, se_mailfrom, pm_mailfrom, NULL); HDEBUG(D_acl) debug_printf("----------- end verify ------------\n"); + *log_msgptr = addr2.message; - *user_msgptr = addr2.user_message; + *user_msgptr = (addr2.user_message != NULL)? + addr2.user_message : addr2.message; *basic_errno = addr2.basic_errno; /* Make $address_data visible */ @@ -1476,7 +1594,7 @@ int sep = '/'; for (; cb != NULL; cb = cb->next) { uschar *arg; - int control_type; + int control_type; /* The message and log_message items set up messages to be used in case of rejection. They are expanded later. */ @@ -1612,7 +1730,7 @@ for (; cb != NULL; cb = cb->next) *log_msgptr = string_sprintf("cannot use \"control=%s\" in %s ACL", controls[control_type], acl_wherenames[where]); return ERROR; - } + } switch(control_type) { @@ -1621,7 +1739,11 @@ for (; cb != NULL; cb = cb->next) bmi_run = 1; break; #endif - +#ifdef EXPERIMENTAL_DOMAINKEYS + case CONTROL_DK_VERIFY: + dk_do_verify = 1; + break; +#endif case CONTROL_ERROR: return ERROR; @@ -1654,16 +1776,16 @@ for (; cb != NULL; cb = cb->next) case CONTROL_FAKEREJECT: fake_reject = TRUE; if (*p == '/') - { + { uschar *pp = p + 1; - while (*pp != 0) pp++; + while (*pp != 0) pp++; fake_reject_text = expand_string(string_copyn(p+1, pp-p)); p = pp; } else { /* Explicitly reset to default string */ - fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s)."; + fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legitimate message, it may still be delivered to the target recipient(s)."; } break; @@ -1679,22 +1801,22 @@ for (; cb != NULL; cb = cb->next) case CONTROL_SUBMISSION: submission_mode = TRUE; while (*p == '/') - { + { if (Ustrncmp(p, "/sender_retain", 14) == 0) { p += 14; active_local_sender_retain = TRUE; - active_local_from_check = FALSE; - } + active_local_from_check = FALSE; + } else if (Ustrncmp(p, "/domain=", 8) == 0) { uschar *pp = p + 8; - while (*pp != 0 && *pp != '/') pp++; + while (*pp != 0 && *pp != '/') pp++; submission_domain = string_copyn(p+8, pp-p); - p = pp; + p = pp; } - else break; - } + else break; + } if (*p != 0) { *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); @@ -1728,7 +1850,10 @@ for (; cb != NULL; cb = cb->next) HDEBUG(D_acl) debug_printf("delay skipped in -bh checking mode\n"); } - else sleep(delay); + else + { + while (delay > 0) delay = sleep(delay); + } } } break; @@ -1739,6 +1864,93 @@ for (; cb != NULL; cb = cb->next) break; #endif +#ifdef EXPERIMENTAL_DOMAINKEYS + case ACLC_DK_DOMAIN_SOURCE: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + /* check header source of domain against given string */ + switch (dk_verify_block->address_source) { + case DK_EXIM_ADDRESS_FROM_FROM: + rc = match_isinlist(US"from", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_ADDRESS_FROM_SENDER: + rc = match_isinlist(US"sender", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_ADDRESS_NONE: + rc = match_isinlist(US"none", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + } + break; + case ACLC_DK_POLICY: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + /* check policy against given string, default FAIL */ + rc = FAIL; + if (dk_verify_block->signsall) + rc = match_isinlist(US"signsall", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + if (dk_verify_block->testing) + rc = match_isinlist(US"testing", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case ACLC_DK_SENDER_DOMAINS: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + if (dk_verify_block->domain != NULL) + rc = match_isinlist(dk_verify_block->domain, &arg, 0, &domainlist_anchor, + NULL, MCL_DOMAIN, TRUE, NULL); + else rc = FAIL; + break; + case ACLC_DK_SENDER_LOCAL_PARTS: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + if (dk_verify_block->local_part != NULL) + rc = match_isinlist(dk_verify_block->local_part, &arg, 0, &localpartlist_anchor, + NULL, MCL_LOCALPART, TRUE, NULL); + else rc = FAIL; + break; + case ACLC_DK_SENDERS: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + if (dk_verify_block->address != NULL) + rc = match_address_list(dk_verify_block->address, TRUE, TRUE, &arg, NULL, -1, 0, NULL); + else rc = FAIL; + break; + case ACLC_DK_STATUS: + if (dk_verify_block == NULL) { rc = FAIL; break; }; + if (dk_verify_block->result > 0) { + switch(dk_verify_block->result) { + case DK_EXIM_RESULT_BAD_FORMAT: + rc = match_isinlist(US"bad format", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_NO_KEY: + rc = match_isinlist(US"no key", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_NO_SIGNATURE: + rc = match_isinlist(US"no signature", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_REVOKED: + rc = match_isinlist(US"revoked", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_NON_PARTICIPANT: + rc = match_isinlist(US"non-participant", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_GOOD: + rc = match_isinlist(US"good", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + case DK_EXIM_RESULT_BAD: + rc = match_isinlist(US"bad", &arg, 0, NULL, + NULL, MCL_STRING, TRUE, NULL); + break; + } + } + break; +#endif + case ACLC_DNSLISTS: rc = verify_check_dnsbl(&arg); break; @@ -1818,7 +2030,7 @@ for (; cb != NULL; cb = cb->next) log_write(0, logbits, "%s", string_printing(s)); } break; - + #ifdef WITH_CONTENT_SCAN case ACLC_MALWARE: {