X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/a79d883474c84fa2a286b7797a7664b599912fcd..d9cb3c4537f82c8663c19c391bd727235916db6c:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 739cd91ae..4be5e071a 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2017 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* Code for handling Access Control Lists (ACLs) */ @@ -37,13 +37,13 @@ are held as a bitmap. This is to avoid expanding the strings unnecessarily. For the code. */ static int msgcond[] = { - [ACL_ACCEPT] = (1<text, hdr, hlen) == 0) break; - hptr = &((*hptr)->next); + hptr = &(*hptr)->next; } /* Add if not previously present */ - if (*hptr == NULL) + if (!*hptr) { header_line *h = store_get(sizeof(header_line)); h->text = hdr; @@ -1039,12 +1028,8 @@ for (p = q; *p != 0; ) h->type = newtype; h->slen = hlen; *hptr = h; - hptr = &(h->next); + hptr = &h->next; } - - /* Advance for next header line within the string */ - - p = q; } } @@ -1534,7 +1519,7 @@ switch (dns_lookup(&dnsa, target, type, NULL)) enum { VERIFY_REV_HOST_LKUP, VERIFY_CERT, VERIFY_HELO, VERIFY_CSA, VERIFY_HDR_SYNTAX, VERIFY_NOT_BLIND, VERIFY_HDR_SNDR, VERIFY_SNDR, VERIFY_RCPT, - VERIFY_HDR_NAMES_ASCII + VERIFY_HDR_NAMES_ASCII, VERIFY_ARC }; typedef struct { uschar * name; @@ -1546,17 +1531,20 @@ typedef struct { static verify_type_t verify_type_list[] = { /* name value where no-opt opt-sep */ { US"reverse_host_lookup", VERIFY_REV_HOST_LKUP, ~0, FALSE, 0 }, - { US"certificate", VERIFY_CERT, ~0, TRUE, 0 }, - { US"helo", VERIFY_HELO, ~0, TRUE, 0 }, + { US"certificate", VERIFY_CERT, ~0, TRUE, 0 }, + { US"helo", VERIFY_HELO, ~0, TRUE, 0 }, { US"csa", VERIFY_CSA, ~0, FALSE, 0 }, - { US"header_syntax", VERIFY_HDR_SYNTAX, (1<= CS verify_type_list + sizeof(verify_type_list)) goto BAD_VERIFY; -if (vp->no_options && slash != NULL) +if (vp->no_options && slash) { *log_msgptr = string_sprintf("unexpected '/' found in \"%s\" " "(this verify item has no options)", arg); return ERROR; } -if (!(vp->where_allowed & (1<where_allowed & BIT(where))) { - *log_msgptr = string_sprintf("cannot verify %s in ACL for %s", vp->name, acl_wherenames[where]); + *log_msgptr = string_sprintf("cannot verify %s in ACL for %s", + vp->name, acl_wherenames[where]); return ERROR; } switch(vp->value) { case VERIFY_REV_HOST_LKUP: - if (sender_host_address == NULL) return OK; + if (!sender_host_address) return OK; if ((rc = acl_verify_reverse(user_msgptr, log_msgptr)) == DEFER) - while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))) + while ((ss = string_nextinlist(&list, &sep, NULL, 0))) if (strcmpic(ss, US"defer_ok") == 0) return OK; return rc; @@ -1688,7 +1677,7 @@ switch(vp->value) occurred earlier. If not, we can attempt the verification now. */ if (!helo_verified && !helo_verify_failed) smtp_verify_helo(); - return helo_verified? OK : FAIL; + return helo_verified ? OK : FAIL; case VERIFY_CSA: /* Do Client SMTP Authorization checks in a separate function, and turn the @@ -1701,8 +1690,25 @@ switch(vp->value) DEBUG(D_acl) debug_printf_indent("CSA result %s\n", csa_status); return csa_return_code[rc]; +#ifdef EXPERIMENTAL_ARC + case VERIFY_ARC: + { /* Do Authenticated Received Chain checks in a separate function. */ + const uschar * condlist = CUS string_nextinlist(&list, &sep, NULL, 0); + int csep = 0; + uschar * cond; + + if (!(arc_state = acl_verify_arc())) return DEFER; + DEBUG(D_acl) debug_printf_indent("ARC verify result %s\n", arc_state); + + if (!condlist) condlist = US"none:pass"; + while ((cond = string_nextinlist(&condlist, &csep, NULL, 0))) + if (Ustrcmp(arc_state, cond) == 0) return OK; + return FAIL; + } +#endif + case VERIFY_HDR_SYNTAX: - /* Check that all relevant header lines have the correct syntax. If there is + /* Check that all relevant header lines have the correct 5322-syntax. If there is a syntax error, we return details of the error to the sender if configured to send out full details. (But a "message" setting on the ACL can override, as always). */ @@ -1720,7 +1726,7 @@ switch(vp->value) See RFC 5322, 2.2. and RFC 6532, 3. */ rc = verify_check_header_names_ascii(log_msgptr); - if (rc != OK && smtp_return_error_details && *log_msgptr != NULL) + if (rc != OK && smtp_return_error_details && *log_msgptr) *user_msgptr = string_sprintf("Rejected after DATA: %s", *log_msgptr); return rc; @@ -1728,8 +1734,7 @@ switch(vp->value) /* Check that no recipient of this message is "blind", that is, every envelope recipient must be mentioned in either To: or Cc:. */ - rc = verify_check_notblind(); - if (rc != OK) + if ((rc = verify_check_notblind()) != OK) { *log_msgptr = string_sprintf("bcc recipient detected"); if (smtp_return_error_details) @@ -2975,9 +2980,8 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_AUTHENTICATED: - rc = (sender_host_authenticated == NULL)? FAIL : - match_isinlist(sender_host_authenticated, &arg, 0, NULL, NULL, MCL_STRING, - TRUE, NULL); + rc = sender_host_authenticated ? match_isinlist(sender_host_authenticated, + &arg, 0, NULL, NULL, MCL_STRING, TRUE, NULL) : FAIL; break; #ifdef EXPERIMENTAL_BRIGHTMAIL @@ -3257,6 +3261,8 @@ for (; cb != NULL; cb = cb->next) break; case CONTROL_CUTTHROUGH_DELIVERY: + { + uschar * ignored = NULL; #ifndef DISABLE_PRDR if (prdr_requested) #else @@ -3265,20 +3271,20 @@ for (; cb != NULL; cb = cb->next) /* Too hard to think about for now. We might in future cutthrough the case where both sides handle prdr and this-node prdr acl is "accept" */ - *log_msgptr = string_sprintf("PRDR on %s reception\n", arg); + ignored = US"PRDR active"; else { if (deliver_freeze) - *log_msgptr = US"frozen"; + ignored = US"frozen"; else if (queue_only_policy) - *log_msgptr = US"queue-only"; + ignored = US"queue-only"; else if (fake_response == FAIL) - *log_msgptr = US"fakereject"; + ignored = US"fakereject"; else { if (rcpt_count == 1) { - cutthrough.delivery = TRUE; + cutthrough.delivery = TRUE; /* control accepted */ while (*p == '/') { const uschar * pp = p+1; @@ -3293,12 +3299,14 @@ for (; cb != NULL; cb = cb->next) p = pp; } } - break; + else + ignored = US"nonfirst rcpt"; } - *log_msgptr = string_sprintf("\"control=%s\" on %s item", - arg, *log_msgptr); } - return ERROR; + DEBUG(D_acl) if (ignored) + debug_printf(" cutthrough request ignored on %s item\n", ignored); + } + break; #ifdef SUPPORT_I18N case CONTROL_UTF8_DOWNCONVERT: @@ -3597,6 +3605,12 @@ for (; cb != NULL; cb = cb->next) #endif case ACLC_QUEUE: + if (Ustrchr(arg, '/')) + { + *log_msgptr = string_sprintf( + "Directory separator not permitted in queue name: '%s'", arg); + return ERROR; + } queue_name = string_copy_malloc(arg); break; @@ -3660,35 +3674,30 @@ for (; cb != NULL; cb = cb->next) } break; - #ifdef WITH_CONTENT_SCAN +#ifdef WITH_CONTENT_SCAN case ACLC_SPAM: { /* Separate the regular expression and any optional parameters. */ const uschar * list = arg; uschar *ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); - /* Run the spam backend. */ + rc = spam(CUSS &ss); /* Modify return code based upon the existence of options. */ - while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) - != NULL) { + while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))) if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) - { - /* FAIL so that the message is passed to the next ACL */ - rc = FAIL; - } - } + rc = FAIL; /* FAIL so that the message is passed to the next ACL */ } break; - #endif +#endif - #ifdef EXPERIMENTAL_SPF +#ifdef SUPPORT_SPF case ACLC_SPF: rc = spf_process(&arg, sender_address, SPF_PROCESS_NORMAL); break; case ACLC_SPF_GUESS: rc = spf_process(&arg, sender_address, SPF_PROCESS_GUESS); break; - #endif +#endif case ACLC_UDPSEND: rc = acl_udpsend(arg, log_msgptr); @@ -3741,7 +3750,7 @@ present. */ if (*epp && rc == OK) user_message = NULL; -if (((1< cutthrough.nrcpt - && (rc = open_cutthrough_connection(addr)) == DEFER ) - if (cutthrough.defer_pass) - { - uschar * s = addr->message; - /* Horrid kludge to recover target's SMTP message */ - while (*s) s++; - do --s; while (!isdigit(*s)); - if (*--s && isdigit(*s) && *--s && isdigit(*s)) *user_msgptr = s; - acl_temp_details = TRUE; - } - else - { - HDEBUG(D_acl) debug_printf_indent("cutthrough defer; will spool\n"); - rc = OK; - } + { + if ((rc = open_cutthrough_connection(addr)) == DEFER) + if (cutthrough.defer_pass) + { + uschar * s = addr->message; + /* Horrid kludge to recover target's SMTP message */ + while (*s) s++; + do --s; while (!isdigit(*s)); + if (*--s && isdigit(*s) && *--s && isdigit(*s)) *user_msgptr = s; + acl_temp_details = TRUE; + } + else + { + HDEBUG(D_acl) debug_printf_indent("cutthrough defer; will spool\n"); + rc = OK; + } + } + else HDEBUG(D_acl) if (cutthrough.delivery) + if (rcpt_count <= cutthrough.nrcpt) + debug_printf_indent("ignore cutthrough request; nonfirst message\n"); + else if (rc != OK) + debug_printf_indent("ignore cutthrough request; ACL did not accept\n"); break; case ACL_WHERE_PREDATA: