git://git.exim.org
/
exim.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Move the TLS resumption support from Experimental to mainline
[exim.git]
/
src
/
src
/
acl.c
diff --git
a/src/src/acl.c
b/src/src/acl.c
index 938bea7d9eb13baf55f1928bf09e10d50e36a018..c1d60bbd965f18798a61797da8fcdc0be37ad49b 100644
(file)
--- a/
src/src/acl.c
+++ b/
src/src/acl.c
@@
-3,6
+3,7
@@
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for handling Access Control Lists (ACLs) */
/* See the file NOTICE for conditions of use and distribution. */
/* Code for handling Access Control Lists (ACLs) */
@@
-112,7
+113,8
@@
enum { ACLC_ACL,
/* ACL conditions/modifiers: "delay", "control", "continue", "endpass",
"message", "log_message", "log_reject_target", "logwrite", "queue" and "set" are
modifiers that look like conditions but always return TRUE. They are used for
/* ACL conditions/modifiers: "delay", "control", "continue", "endpass",
"message", "log_message", "log_reject_target", "logwrite", "queue" and "set" are
modifiers that look like conditions but always return TRUE. They are used for
-their side effects. */
+their side effects. Do not invent new modifier names that result in one name
+being the prefix of another; the binary-search in the list will go wrong. */
typedef struct condition_def {
uschar *name;
typedef struct condition_def {
uschar *name;
@@
-366,7
+368,7
@@
enum {
CONTROL_NO_MULTILINE,
CONTROL_NO_PIPELINING,
CONTROL_NO_MULTILINE,
CONTROL_NO_PIPELINING,
- CONTROL_QUEUE
_ONLY
,
+ CONTROL_QUEUE,
CONTROL_SUBMISSION,
CONTROL_SUPPRESS_LOCAL_FIXUPS,
#ifdef SUPPORT_I18N
CONTROL_SUBMISSION,
CONTROL_SUPPRESS_LOCAL_FIXUPS,
#ifdef SUPPORT_I18N
@@
-502,8
+504,8
@@
static control_def controls_list[] = {
ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START
},
ACL_BIT_NOTSMTP | ACL_BIT_NOTSMTP_START
},
-[CONTROL_QUEUE
_ONLY
] =
- { US"queue
_only", FALS
E,
+[CONTROL_QUEUE] =
+ { US"queue
", TRU
E,
(unsigned)
~(ACL_BIT_MAIL | ACL_BIT_RCPT |
ACL_BIT_PREDATA | ACL_BIT_DATA |
(unsigned)
~(ACL_BIT_MAIL | ACL_BIT_RCPT |
ACL_BIT_PREDATA | ACL_BIT_DATA |
@@
-511,7
+513,6
@@
static control_def controls_list[] = {
ACL_BIT_NOTSMTP | ACL_BIT_MIME)
},
ACL_BIT_NOTSMTP | ACL_BIT_MIME)
},
-
[CONTROL_SUBMISSION] =
{ US"submission", TRUE,
(unsigned)
[CONTROL_SUBMISSION] =
{ US"submission", TRUE,
(unsigned)
@@
-732,7
+733,7
@@
uschar * s;
*error = NULL;
*error = NULL;
-while ((s = (*func)())
!= NULL
)
+while ((s = (*func)()))
{
int v, c;
BOOL negated = FALSE;
{
int v, c;
BOOL negated = FALSE;
@@
-742,8
+743,7
@@
while ((s = (*func)()) != NULL)
/* Conditions (but not verbs) are allowed to be negated by an initial
exclamation mark. */
/* Conditions (but not verbs) are allowed to be negated by an initial
exclamation mark. */
- while (isspace(*s)) s++;
- if (*s == '!')
+ if (Uskip_whitespace(&s) == '!')
{
negated = TRUE;
s++;
{
negated = TRUE;
s++;
@@
-859,7
+859,7
@@
while ((s = (*func)()) != NULL)
}
cond->u.varname = string_copyn(s, 18);
s = endptr;
}
cond->u.varname = string_copyn(s, 18);
s = endptr;
-
while (isspace(*s)) s++
;
+
Uskip_whitespace(&s)
;
}
else
#endif
}
else
#endif
@@
-895,7
+895,7
@@
while ((s = (*func)()) != NULL)
cond->u.varname = string_copyn(s + 4, endptr - s - 4);
s = endptr;
cond->u.varname = string_copyn(s + 4, endptr - s - 4);
s = endptr;
-
while (isspace(*s)) s++
;
+
Uskip_whitespace(&s)
;
}
/* For "set", we are now positioned for the data. For the others, only
}
/* For "set", we are now positioned for the data. For the others, only
@@
-909,7
+909,7
@@
while ((s = (*func)()) != NULL)
conditions[c].is_modifier ? US"modifier" : US"condition");
return NULL;
}
conditions[c].is_modifier ? US"modifier" : US"condition");
return NULL;
}
-
while (isspace(*s)) s++
;
+
Uskip_whitespace(&s)
;
cond->arg = string_copy(s);
}
}
cond->arg = string_copy(s);
}
}
@@
-1601,7
+1601,7
@@
an error if options are given for items that don't expect them.
uschar *slash = Ustrchr(arg, '/');
const uschar *list = arg;
uschar *slash = Ustrchr(arg, '/');
const uschar *list = arg;
-uschar *ss = string_nextinlist(&list, &sep,
big_buffer, big_buffer_size
);
+uschar *ss = string_nextinlist(&list, &sep,
NULL, 0
);
verify_type_t * vp;
if (!ss) goto BAD_VERIFY;
verify_type_t * vp;
if (!ss) goto BAD_VERIFY;
@@
-2113,7
+2113,9
@@
return ERROR;
* Check argument for control= modifier *
*************************************************/
* Check argument for control= modifier *
*************************************************/
-/* Called from acl_check_condition() below
+/* Called from acl_check_condition() below.
+To handle the case "queue_only" we accept an _ in the
+initial / option-switch position.
Arguments:
arg the argument string for control=
Arguments:
arg the argument string for control=
@@
-2129,10
+2131,11
@@
decode_control(const uschar *arg, const uschar **pptr, int where, uschar **log_m
{
int idx, len;
control_def * d;
{
int idx, len;
control_def * d;
+uschar c;
if ( (idx = find_control(arg, controls_list, nelem(controls_list))) < 0
if ( (idx = find_control(arg, controls_list, nelem(controls_list))) < 0
- || (
arg[len = Ustrlen((d = controls_list+idx)->name)]
!= 0
- && (!d->has_option ||
arg[len] != '/
')
+ || (
(c = arg[len = Ustrlen((d = controls_list+idx)->name)])
!= 0
+ && (!d->has_option ||
c != '/' && c != '_
')
) )
{
*log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
) )
{
*log_msgptr = string_sprintf("syntax error in \"control=%s\"", arg);
@@
-2258,7
+2261,7
@@
count = 1.0;
/* Parse the other options. */
/* Parse the other options. */
-while ((ss = string_nextinlist(&arg, &sep,
big_buffer, big_buffer_size
)))
+while ((ss = string_nextinlist(&arg, &sep,
NULL, 0
)))
{
if (strcmpic(ss, US"leaky") == 0) leaky = TRUE;
else if (strcmpic(ss, US"strict") == 0) strict = TRUE;
{
if (strcmpic(ss, US"leaky") == 0) leaky = TRUE;
else if (strcmpic(ss, US"strict") == 0) strict = TRUE;
@@
-3158,8
+3161,17
@@
for (; cb; cb = cb->next)
cancel_cutthrough_connection(TRUE, US"item frozen");
break;
cancel_cutthrough_connection(TRUE, US"item frozen");
break;
- case CONTROL_QUEUE
_ONLY
:
+ case CONTROL_QUEUE:
f.queue_only_policy = TRUE;
f.queue_only_policy = TRUE;
+ if (Ustrcmp(p, "_only") == 0)
+ p += 5;
+ else while (*p == '/')
+ if (Ustrncmp(p, "/only", 5) == 0)
+ { p += 5; f.queue_smtp = FALSE; }
+ else if (Ustrncmp(p, "/first_pass_route", 17) == 0)
+ { p += 17; f.queue_smtp = TRUE; }
+ else
+ break;
cancel_cutthrough_connection(TRUE, US"queueing forced");
break;
cancel_cutthrough_connection(TRUE, US"queueing forced");
break;
@@
-3466,13
+3478,13
@@
for (; cb; cb = cb->next)
{
uschar *endcipher = NULL;
uschar *cipher = Ustrchr(tls_in.cipher, ':');
{
uschar *endcipher = NULL;
uschar *cipher = Ustrchr(tls_in.cipher, ':');
- if (
cipher == NULL
) cipher = tls_in.cipher; else
+ if (
!cipher
) cipher = tls_in.cipher; else
{
endcipher = Ustrchr(++cipher, ':');
{
endcipher = Ustrchr(++cipher, ':');
- if (endcipher
!= NULL
) *endcipher = 0;
+ if (endcipher) *endcipher = 0;
}
rc = match_isinlist(cipher, &arg, 0, NULL, NULL, MCL_STRING, TRUE, NULL);
}
rc = match_isinlist(cipher, &arg, 0, NULL, NULL, MCL_STRING, TRUE, NULL);
- if (endcipher
!= NULL
) *endcipher = ':';
+ if (endcipher) *endcipher = ':';
}
break;
}
break;
@@
-3485,8
+3497,7
@@
for (; cb; cb = cb->next)
case ACLC_HOSTS:
rc = verify_check_this_host(&arg, sender_host_cache, NULL,
case ACLC_HOSTS:
rc = verify_check_this_host(&arg, sender_host_cache, NULL,
- (sender_host_address == NULL)? US"" : sender_host_address,
- CUSS &host_data);
+ sender_host_address ? sender_host_address : US"", CUSS &host_data);
if (rc == DEFER) *log_msgptr = search_error_message;
if (host_data) host_data = string_copy_perm(host_data, TRUE);
break;
if (rc == DEFER) *log_msgptr = search_error_message;
if (host_data) host_data = string_copy_perm(host_data, TRUE);
break;
@@
-3831,16
+3842,16
@@
uschar *yield;
for(;;)
{
for(;;)
{
-
while (isspace(*acl_text)) acl_text++;
/* Leading spaces/empty lines */
- if (
*acl_text == 0
) return NULL; /* No more data */
- yield = acl_text;
/* Potential data line */
+
Uskip_whitespace(&acl_text);
/* Leading spaces/empty lines */
+ if (
!*acl_text
) return NULL; /* No more data */
+ yield = acl_text; /* Potential data line */
while (*acl_text && *acl_text != '\n') acl_text++;
/* If we hit the end before a newline, we have the whole logical line. If
it's a comment, there's no more data to be given. Otherwise, yield it. */
while (*acl_text && *acl_text != '\n') acl_text++;
/* If we hit the end before a newline, we have the whole logical line. If
it's a comment, there's no more data to be given. Otherwise, yield it. */
- if (
*acl_text == 0) return (*yield == '#')
? NULL : yield;
+ if (
!*acl_text) return *yield == '#'
? NULL : yield;
/* After reaching a newline, end this loop if the physical line does not
start with '#'. If it does, it's a comment, and the loop continues. */
/* After reaching a newline, end this loop if the physical line does not
start with '#'. If it does, it's a comment, and the loop continues. */