X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/2c0f3ea1858d9dafc8600f9d97bc6e57594c22d0..bb07bcd32250965a896b0856dd1b839b5795e2f4:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index efab1d31e..921cb2ce8 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -22,13 +22,14 @@ enum { ACL_ACCEPT, ACL_DEFER, ACL_DENY, ACL_DISCARD, ACL_DROP, ACL_REQUIRE, /* ACL verbs */ static uschar *verbs[] = { - US"accept", - US"defer", - US"deny", - US"discard", - US"drop", - US"require", - US"warn" }; + [ACL_ACCEPT] = US"accept", + [ACL_DEFER] = US"defer", + [ACL_DENY] = US"deny", + [ACL_DISCARD] = US"discard", + [ACL_DROP] = US"drop", + [ACL_REQUIRE] = US"require", + [ACL_WARN] = US"warn" +}; /* For each verb, the conditions for which "message" or "log_message" are used are held as a bitmap. This is to avoid expanding the strings unnecessarily. For @@ -36,13 +37,13 @@ are held as a bitmap. This is to avoid expanding the strings unnecessarily. For the code. */ static int msgcond[] = { - (1<next)); -ret[ptr-1] = '\0'; /* overwrite last newline */ -return ret; +g->s[g->ptr - 1] = '\0'; /* overwrite last newline */ +return g->s; } @@ -1097,7 +1139,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; @@ -1482,6 +1524,7 @@ typedef struct { unsigned alt_opt_sep; /* >0 Non-/ option separator (custom parser) */ } verify_type_t; 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 }, @@ -1500,7 +1543,7 @@ static verify_type_t verify_type_list[] = { enum { CALLOUT_DEFER_OK, CALLOUT_NOCACHE, CALLOUT_RANDOM, CALLOUT_USE_SENDER, CALLOUT_USE_POSTMASTER, CALLOUT_POSTMASTER, CALLOUT_FULLPOSTMASTER, CALLOUT_MAILFROM, CALLOUT_POSTMASTER_MAILFROM, CALLOUT_MAXWAIT, CALLOUT_CONNECT, - CALLOUT_TIME + CALLOUT_HOLD, CALLOUT_TIME /* TIME must be last */ }; typedef struct { uschar * name; @@ -1510,6 +1553,7 @@ typedef struct { BOOL timeval; /* Has a time value */ } callout_opt_t; static callout_opt_t callout_opt_list[] = { + /* name value flag has-opt has-time */ { US"defer_ok", CALLOUT_DEFER_OK, 0, FALSE, FALSE }, { US"no_cache", CALLOUT_NOCACHE, vopt_callout_no_cache, FALSE, FALSE }, { US"random", CALLOUT_RANDOM, vopt_callout_random, FALSE, FALSE }, @@ -1521,6 +1565,7 @@ static callout_opt_t callout_opt_list[] = { { US"mailfrom", CALLOUT_MAILFROM, 0, TRUE, FALSE }, { US"maxwait", CALLOUT_MAXWAIT, 0, TRUE, TRUE }, { US"connect", CALLOUT_CONNECT, 0, TRUE, TRUE }, + { US"hold", CALLOUT_HOLD, vopt_callout_hold, FALSE, FALSE }, { NULL, CALLOUT_TIME, 0, FALSE, TRUE } }; @@ -1579,13 +1624,13 @@ if (ss == NULL) goto BAD_VERIFY; /* Handle name/address consistency verification in a separate function. */ for (vp= verify_type_list; - (char *)vp < (char *)verify_type_list + sizeof(verify_type_list); + CS vp < CS verify_type_list + sizeof(verify_type_list); vp++ ) if (vp->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) @@ -1744,8 +1789,7 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) uschar buffer[256]; while (isspace(*sublist)) sublist++; - while ((opt = string_nextinlist(&sublist, &optsep, buffer, sizeof(buffer))) - != NULL) + while ((opt = string_nextinlist(&sublist, &optsep, buffer, sizeof(buffer)))) { callout_opt_t * op; double period = 1.0F; @@ -1767,15 +1811,11 @@ while ((ss = string_nextinlist(&list, &sep, big_buffer, big_buffer_size)) } while (isspace(*opt)) opt++; } - if (op->timeval) + if (op->timeval && (period = readconf_readtime(opt, 0, FALSE)) < 0) { - period = readconf_readtime(opt, 0, FALSE); - if (period < 0) - { - *log_msgptr = string_sprintf("bad time value in ACL condition " - "\"verify %s\"", arg); - return ERROR; - } + *log_msgptr = string_sprintf("bad time value in ACL condition " + "\"verify %s\"", arg); + return ERROR; } switch(op->value) @@ -2356,8 +2396,7 @@ if (t != NULL) /* We aren't using a pre-computed rate, so get a previously recorded rate from the database, which will be updated and written back if required. */ -dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE); -if (dbm == NULL) +if (!(dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE))) { store_pool = old_pool; sender_rate = NULL; @@ -2731,8 +2770,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); @@ -3069,7 +3109,7 @@ for (; cb != NULL; cb = cb->next) break; case CONTROL_FAKEREJECT: - cancel_cutthrough_connection("fakereject"); + cancel_cutthrough_connection(TRUE, US"fakereject"); case CONTROL_FAKEDEFER: fake_response = (control_type == CONTROL_FAKEDEFER) ? DEFER : FAIL; if (*p == '/') @@ -3100,12 +3140,12 @@ for (; cb != NULL; cb = cb->next) *log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg); return ERROR; } - cancel_cutthrough_connection("item frozen"); + cancel_cutthrough_connection(TRUE, US"item frozen"); break; case CONTROL_QUEUE_ONLY: queue_only_policy = TRUE; - cancel_cutthrough_connection("queueing forced"); + cancel_cutthrough_connection(TRUE, US"queueing forced"); break; case CONTROL_SUBMISSION: @@ -3534,7 +3574,7 @@ for (; cb != NULL; cb = cb->next) break; case ACLC_RECIPIENTS: - rc = match_address_list((const uschar *)addr->address, TRUE, TRUE, &arg, NULL, -1, 0, + rc = match_address_list(CUS addr->address, TRUE, TRUE, &arg, NULL, -1, 0, CUSS &recipient_data); break; @@ -3552,14 +3592,14 @@ for (; cb != NULL; cb = cb->next) { uschar *sdomain; sdomain = Ustrrchr(sender_address, '@'); - sdomain = (sdomain == NULL)? US"" : sdomain + 1; + sdomain = sdomain ? sdomain + 1 : US""; rc = match_isinlist(sdomain, &arg, 0, &domainlist_anchor, sender_domain_cache, MCL_DOMAIN, TRUE, NULL); } break; case ACLC_SENDERS: - rc = match_address_list((const uschar *)sender_address, TRUE, TRUE, &arg, + rc = match_address_list(CUS sender_address, TRUE, TRUE, &arg, sender_address_cache, -1, 0, CUSS &sender_data); break; @@ -3891,7 +3931,7 @@ if (acl_level == 0) } else ss = s; -while (isspace(*ss))ss++; +while (isspace(*ss)) ss++; /* If we can't find a named ACL, the default is to parse it as an inline one. (Unless it begins with a slash; non-existent files give rise to an error.) */ @@ -4334,8 +4374,9 @@ switch (where) #ifndef DISABLE_PRDR case ACL_WHERE_PRDR: #endif + if (host_checking_callout) /* -bhc mode */ - cancel_cutthrough_connection("host-checking mode"); + cancel_cutthrough_connection(TRUE, US"host-checking mode"); else if ( rc == OK && cutthrough.delivery @@ -4362,13 +4403,20 @@ switch (where) if (rc == OK) cutthrough_predata(); else - cancel_cutthrough_connection("predata acl not ok"); + cancel_cutthrough_connection(TRUE, US"predata acl not ok"); break; case ACL_WHERE_QUIT: case ACL_WHERE_NOTQUIT: - cancel_cutthrough_connection("quit or notquit"); + /* Drop cutthrough conns, and drop heldopen verify conns if + the previous was not DATA */ + { + uschar prev = smtp_connection_had[smtp_ch_index-2]; + BOOL dropverify = !(prev == SCH_DATA || prev == SCH_BDAT); + + cancel_cutthrough_connection(dropverify, US"quit or conndrop"); break; + } default: break;