X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f2ed27cf5f913cc437401c7e005c2886b7dc1a55..6741531cf79cbd3b403b8a52ed07635fe543cd3a:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 42292eb82..fb8b75bc7 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 - 2016 */ +/* 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<u.varname = string_copyn(s, 18); + s = endptr; + while (isspace(*s)) s++; + } + else +#endif { uschar *endptr; @@ -1036,9 +1047,7 @@ for (p = q; *p != 0; ) uschar * fn_hdrs_added(void) { -uschar * ret = NULL; -int size = 0; -int ptr = 0; +gstring * g = NULL; header_line * h = acl_added_headers; uschar * s; uschar * cp; @@ -1053,18 +1062,19 @@ do if (cp[1] == '\0') break; /* contains embedded newline; needs doubling */ - ret = string_catn(ret, &size, &ptr, s, cp-s+1); - ret = string_catn(ret, &size, &ptr, US"\n", 1); + g = string_catn(g, s, cp-s+1); + g = string_catn(g, US"\n", 1); s = cp+1; } /* last bit of header */ - ret = string_catn(ret, &size, &ptr, s, cp-s+1); /* newline-sep list */ +/*XXX could we use add_listele? */ + g = string_catn(g, s, cp-s+1); /* newline-sep list */ } while((h = h->next)); -ret[ptr-1] = '\0'; /* overwrite last newline */ -return ret; +g->s[g->ptr - 1] = '\0'; /* overwrite last newline */ +return g->s; } @@ -1140,7 +1150,7 @@ if (log_message != NULL && log_message != user_message) int length = Ustrlen(text) + 1; log_write(0, LOG_MAIN, "%s", text); logged = store_malloc(sizeof(string_item) + length); - logged->text = (uschar *)logged + sizeof(string_item); + logged->text = US logged + sizeof(string_item); memcpy(logged->text, text, length); logged->next = acl_warn_logged; acl_warn_logged = logged; @@ -1515,7 +1525,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; @@ -1527,17 +1537,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<alt_opt_sep ? strncmpic(ss, vp->name, vp->alt_opt_sep) == 0 : strcmpic (ss, vp->name) == 0) break; -if ((char *)vp >= (char *)verify_type_list + sizeof(verify_type_list)) +if (CS vp >= 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) @@ -1683,7 +1697,7 @@ switch(vp->value) return csa_return_code[rc]; 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). */ @@ -2771,8 +2785,9 @@ if (r == HOST_FIND_FAILED || r == HOST_FIND_AGAIN) HDEBUG(D_acl) debug_printf_indent("udpsend [%s]:%d %s\n", h->address, portnum, arg); +/*XXX this could better use sendto */ r = s = ip_connectedsocket(SOCK_DGRAM, h->address, portnum, portnum, - 1, NULL, &errstr); + 1, NULL, &errstr, NULL); if (r < 0) goto defer; len = Ustrlen(arg); r = send(s, arg, len, 0); @@ -2899,8 +2914,19 @@ for (; cb != NULL; cb = cb->next) if (cb->type == ACLC_SET) { - debug_printf("acl_%s ", cb->u.varname); - lhswidth += 5 + Ustrlen(cb->u.varname); +#ifndef DISABLE_DKIM + if ( Ustrcmp(cb->u.varname, "dkim_verify_status") == 0 + || Ustrcmp(cb->u.varname, "dkim_verify_reason") == 0) + { + debug_printf("%s ", cb->u.varname); + lhswidth += 19; + } + else +#endif + { + debug_printf("acl_%s ", cb->u.varname); + lhswidth += 5 + Ustrlen(cb->u.varname); + } } debug_printf("= %s\n", cb->arg); @@ -3226,6 +3252,8 @@ for (; cb != NULL; cb = cb->next) break; case CONTROL_CUTTHROUGH_DELIVERY: + { + uschar * ignored = NULL; #ifndef DISABLE_PRDR if (prdr_requested) #else @@ -3234,20 +3262,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; @@ -3262,12 +3290,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: @@ -3402,7 +3432,7 @@ for (; cb != NULL; cb = cb->next) #ifndef DISABLE_DKIM case ACLC_DKIM_SIGNER: - if (dkim_cur_signer != NULL) + if (dkim_cur_signer) rc = match_isinlist(dkim_cur_signer, &arg,0,NULL,NULL,MCL_STRING,TRUE,NULL); else @@ -3410,7 +3440,7 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_DKIM_STATUS: - rc = match_isinlist(dkim_exim_expand_query(DKIM_VERIFY_STATUS), + rc = match_isinlist(dkim_verify_status, &arg,0,NULL,NULL,MCL_STRING,TRUE,NULL); break; #endif @@ -3566,6 +3596,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; @@ -3609,45 +3645,50 @@ for (; cb != NULL; cb = cb->next) { int old_pool = store_pool; if ( cb->u.varname[0] == 'c' +#ifndef DISABLE_DKIM + || cb->u.varname[0] == 'd' +#endif #ifndef DISABLE_EVENT || event_name /* An event is being delivered */ #endif ) store_pool = POOL_PERM; - acl_var_create(cb->u.varname)->data.ptr = string_copy(arg); +#ifndef DISABLE_DKIM /* Overwriteable dkim result variables */ + if (Ustrcmp(cb->u.varname, "dkim_verify_status") == 0) + dkim_verify_status = string_copy(arg); + else if (Ustrcmp(cb->u.varname, "dkim_verify_reason") == 0) + dkim_verify_reason = string_copy(arg); + else +#endif + acl_var_create(cb->u.varname)->data.ptr = string_copy(arg); store_pool = old_pool; } 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); @@ -3700,7 +3741,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: