X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/42855d71446546dd9914cadc25fb3781e184ac96..6a8f9482e9c8fc26565a6c404b3936d67c56da16:/src/src/acl.c diff --git a/src/src/acl.c b/src/src/acl.c index 41058afa7..e0f01694b 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/acl.c,v 1.75 2007/03/01 11:17:00 ph10 Exp $ */ +/* $Cambridge: exim/src/src/acl.c,v 1.81 2008/01/17 13:03:35 tom Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -55,6 +55,9 @@ enum { ACLC_ACL, ACLC_CONDITION, ACLC_CONTINUE, ACLC_CONTROL, +#ifdef EXPERIMENTAL_DCC + ACLC_DCC, +#endif #ifdef WITH_CONTENT_SCAN ACLC_DECODE, #endif @@ -117,6 +120,9 @@ static uschar *conditions[] = { US"condition", US"continue", US"control", +#ifdef EXPERIMENTAL_DCC + US"dcc", +#endif #ifdef WITH_CONTENT_SCAN US"decode", #endif @@ -174,6 +180,9 @@ enum { #ifdef EXPERIMENTAL_DOMAINKEYS CONTROL_DK_VERIFY, #endif + #ifdef EXPERIMENTAL_DKIM + CONTROL_DKIM_VERIFY, + #endif CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART, @@ -207,6 +216,9 @@ static uschar *controls[] = { #ifdef EXPERIMENTAL_DOMAINKEYS US"dk_verify", #endif + #ifdef EXPERIMENTAL_DKIM + US"dkim_verify", + #endif US"error", US"caseful_local_part", US"caselower_local_part", @@ -221,7 +233,7 @@ static uschar *controls[] = { #endif US"fakedefer", US"fakereject", - US"no_multiline", + US"no_multiline_responses", US"no_pipelining", US"no_delay_flush", US"no_callout_flush" @@ -241,6 +253,9 @@ static uschar cond_expand_at_top[] = { TRUE, /* condition */ TRUE, /* continue */ TRUE, /* control */ +#ifdef EXPERIMENTAL_DCC + TRUE, /* dcc */ +#endif #ifdef WITH_CONTENT_SCAN TRUE, /* decode */ #endif @@ -301,6 +316,9 @@ static uschar cond_modifiers[] = { FALSE, /* condition */ TRUE, /* continue */ TRUE, /* control */ +#ifdef EXPERIMENTAL_DCC + FALSE, /* dcc */ +#endif #ifdef WITH_CONTENT_SCAN FALSE, /* decode */ #endif @@ -350,8 +368,9 @@ static uschar cond_modifiers[] = { }; /* Bit map vector of which conditions and modifiers are not allowed at certain -times. For each condition, there's a bitmap of dis-allowed times. For some, it -is easier to specify the negation of a small number of allowed times. */ +times. For each condition and modifier, there's a bitmap of dis-allowed times. +For some, it is easier to specify the negation of a small number of allowed +times. */ static unsigned int cond_forbids[] = { 0, /* acl */ @@ -386,12 +405,17 @@ static unsigned int cond_forbids[] = { 0, /* control */ + #ifdef EXPERIMENTAL_DCC + (unsigned int) + ~((1< 1 || per_byte + per_cmd + per_conn + per_mail > 1) { *log_msgptr = US"conflicting options for \"ratelimit\" condition"; @@ -2206,21 +2235,32 @@ if (leaky + strict > 1 || per_byte + per_cmd + per_conn + per_mail > 1) } /* Default option values */ + if (!strict) leaky = TRUE; if (!per_byte && !per_cmd && !per_conn) per_mail = TRUE; -/* If there is no explicit key, use the sender_host_address. If there is no -sender_host_address (e.g. -bs or acl_not_smtp) then we simply omit it. */ +/* Create the lookup key. If there is no explicit key, use sender_host_address. +If there is no sender_host_address (e.g. -bs or acl_not_smtp) then we simply +omit it. The smoothing constant (sender_rate_period) and the per_xxx options +are added to the key because they alter the meaning of the stored data. */ + +if (key == NULL) + key = (sender_host_address == NULL)? US"" : sender_host_address; -if (!have_key && sender_host_address != NULL) - key = string_sprintf("%s / %s", key, sender_host_address); +key = string_sprintf("%s/%s/%s/%s", + sender_rate_period, + per_byte? US"per_byte" : + per_cmd? US"per_cmd" : + per_mail? US"per_mail" : US"per_conn", + strict? US"strict" : US"leaky", + key); HDEBUG(D_acl) debug_printf("ratelimit condition limit=%.0f period=%.0f key=%s\n", limit, period, key); -/* See if we have already computed the rate by looking in the relevant tree. For -per-connection rate limiting, store tree nodes and dbdata in the permanent pool -so that they survive across resets. */ +/* See if we have already computed the rate by looking in the relevant tree. +For per-connection rate limiting, store tree nodes and dbdata in the permanent +pool so that they survive across resets. */ anchor = NULL; old_pool = store_pool; @@ -2239,8 +2279,7 @@ if (anchor != NULL && (t = tree_search(*anchor, key)) != NULL) { dbd = t->data.ptr; /* The following few lines duplicate some of the code below. */ - if (dbd->rate < limit) rc = FAIL; - else rc = OK; + rc = (dbd->rate < limit)? FAIL : OK; store_pool = old_pool; sender_rate = string_sprintf("%.1f", dbd->rate); HDEBUG(D_acl) @@ -2249,8 +2288,8 @@ if (anchor != NULL && (t = tree_search(*anchor, key)) != NULL) } /* We aren't using a pre-computed rate, so get a previously recorded -rate from the database, update it, and write it back. If there's no -previous rate for this key, create one. */ +rate from the database, update it, and write it back when required. If there's +no previous rate for this key, create one. */ dbm = dbfn_open(US"ratelimit", O_RDWR, &dbblock, TRUE); if (dbm == NULL) @@ -2355,21 +2394,30 @@ matters for edge cases such the first message sent by a client (which gets the initial rate of 0.0) when the rate limit is zero (i.e. the client should be completely blocked). */ -if (dbd->rate < limit) rc = FAIL; - else rc = OK; +rc = (dbd->rate < limit)? FAIL : OK; /* Update the state if the rate is low or if we are being strict. If we are in leaky mode and the sender's rate is too high, we do not update the recorded rate in order to avoid an over-aggressive sender's retry -rate preventing them from getting any email through. */ +rate preventing them from getting any email through. If noupdate is set, +do not do any updates. */ -if (rc == FAIL || !leaky) +if ((rc == FAIL || !leaky) && !noupdate) + { dbfn_write(dbm, key, dbd, sizeof(dbdata_ratelimit)); + HDEBUG(D_acl) debug_printf("ratelimit db updated\n"); + } +else + { + HDEBUG(D_acl) debug_printf("ratelimit db not updated: %s\n", + noupdate? "noupdate set" : "over the limit, but leaky"); + } + dbfn_close(dbm); /* Store the result in the tree for future reference, if necessary. */ -if (anchor != NULL) +if (anchor != NULL && !noupdate) { t = store_get(sizeof(tree_node) + Ustrlen(key)); t->data.ptr = dbd; @@ -2596,6 +2644,12 @@ for (; cb != NULL; cb = cb->next) break; #endif + #ifdef EXPERIMENTAL_DKIM + case CONTROL_DKIM_VERIFY: + dkim_do_verify = 1; + break; + #endif + case CONTROL_ERROR: return ERROR; @@ -2717,6 +2771,26 @@ for (; cb != NULL; cb = cb->next) } break; + #ifdef EXPERIMENTAL_DCC + case ACLC_DCC: + { + /* Seperate the regular expression and any optional parameters. */ + uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size); + /* Run the dcc backend. */ + rc = dcc_process(&ss); + /* Modify return code based upon the existance of options. */ + while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size)) + != NULL) { + if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER) + { + /* FAIL so that the message is passed to the next ACL */ + rc = FAIL; + } + } + } + break; + #endif + #ifdef WITH_CONTENT_SCAN case ACLC_DECODE: rc = mime_decode(&arg); @@ -3439,11 +3513,11 @@ while (acl != NULL) *log_msgptr = *user_msgptr = NULL; acl_temp_details = FALSE; - if (where == ACL_WHERE_QUIT && + if ((where == ACL_WHERE_QUIT || where == ACL_WHERE_NOTQUIT) && acl->verb != ACL_ACCEPT && acl->verb != ACL_WARN) { - *log_msgptr = string_sprintf("\"%s\" is not allowed in a QUIT ACL", + *log_msgptr = string_sprintf("\"%s\" is not allowed in a QUIT or not-QUIT ACL", verbs[acl->verb]); return ERROR; }