diff --git a/Makefile.am b/Makefile.am index 6d9aeb309679fcd27de717fa3a56b6b6469ca90b..8b9c364ace05af5c6328ad84e0287db43a4c2d9a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,8 @@ test_cases = \ tests/testsuite.svtest\ tests/control-structures.svtest \ tests/exists.svtest \ + tests/header.svtest \ + tests/address.svtest \ tests/lexer.svtest \ tests/comparators/core.svtest \ tests/match-types/is.svtest \ diff --git a/TODO b/TODO index 1756bdf69c1af220668408e08f475aa12b61ae75..24573eb4e1f752e3deb414c6dffb8c701fa365a7 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,4 @@ Next (in order of descending priority/precedence): -* Fix standards compliance issues: - - 'If an address is not syntactically valid, then it will not be matched - by tests specifying ":localpart" or ":domain"'. * Fix security issues: - Impose limitations on the imapflags extension regarding the number of set flags and the length of each flag name. @@ -33,6 +30,7 @@ Next (in order of descending priority/precedence): - Body: contains various issues that need to be resolved for standards compliance. Body test support currently matches but barely exceeds the original CMU Sieve implentation in terms of standards compliance. + - Improve handling of invalid addresses in headers (requires Dovecot changes) * Imapflags: merge execution of setflags, removeflags and addflags into one common implementation. * Warn about the use of syntactically invalid header names. diff --git a/src/lib-sieve/mcht-is.c b/src/lib-sieve/mcht-is.c index dcfa35f902a26404d6f29f9a7aca2f8b19e54dc3..ecba1e8fa12cd5d23d5fe22fe82588c34af8561c 100644 --- a/src/lib-sieve/mcht-is.c +++ b/src/lib-sieve/mcht-is.c @@ -44,6 +44,8 @@ static int mcht_is_match { if ( (val == NULL || val_size == 0) ) return ( key_size == 0 ); + + printf ("VAL '%s' KEY '%s'\n", val, key); if ( mctx->comparator->compare != NULL ) return (mctx->comparator->compare(mctx->comparator, diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c index b30e60cd0c397f041ba8db4f4e1b1fb12ea14ce9..d4206dd92982eb75347c8b2034e1729c0298d29e 100644 --- a/src/lib-sieve/sieve-address-parts.c +++ b/src/lib-sieve/sieve-address-parts.c @@ -219,24 +219,46 @@ int sieve_address_match const struct message_address *addr; T_BEGIN { + bool valid = TRUE; + const struct message_address *aitem; + addr = message_address_parse (pool_datastack_create(), (const unsigned char *) data, strlen(data), 256, FALSE); - - while ( result == 0 && addr != NULL) { - /* mailbox@domain */ - struct sieve_address address; - const char *part; + + /* Check validity of all addresses simultaneously. Unfortunately, + * errorneous addresses cannot be extracted from the address list + * and therefore :all will match against the whole header value + * which is not entirely standard. + */ + aitem = addr; + while ( aitem != NULL) { + if ( aitem->invalid_syntax ) + valid = FALSE; + aitem = aitem->next; + } + + if ( !valid || addr == NULL ) { + if ( addrp == &all_address_part ) + result = sieve_match_value(mctx, data, strlen(data)); + else + result = FALSE; + } else { + while ( result == 0 && addr != NULL) { + /* mailbox@domain */ + struct sieve_address address; + const char *part; - address.local_part = addr->mailbox; - address.domain = addr->domain; + address.local_part = addr->mailbox; + address.domain = addr->domain; - part = addrp->extract_from(&address); + part = addrp->extract_from(&address); - if ( part != NULL ) - result=sieve_match_value(mctx, part, strlen(part)); + if ( part != NULL ) + result = sieve_match_value(mctx, part, strlen(part)); - addr = addr->next; + addr = addr->next; + } } } T_END; diff --git a/tests/address.svtest b/tests/address.svtest new file mode 100644 index 0000000000000000000000000000000000000000..ef6773b6340950cb7cdbd3e418dccbb1bd8a513e --- /dev/null +++ b/tests/address.svtest @@ -0,0 +1,60 @@ +require "vnd.dovecot.testsuite"; + +/* + * If an address is not syntactically valid, then it will not be matched + * by tests specifying ":localpart" or ":domain". + */ + +test_set "message" text: +From: stephan@ +To: @rename-it.nl +Cc: nonsense +Resent-To: +Subject: Invalid addresses + +Test. +. +; + +test "Invalid single addresses" { + if address :localpart "from" "stephan" { + test_fail ":localpart matched invalid address"; + } + + if address :domain "to" "rename-it.nl" { + test_fail ":domain matched invalid address"; + } + + if not address :is :all "resent-to" "" { + test_fail ":all failed to match empty address"; + } + + if not address :is :all "cc" "nonsense" { + test_fail ":all failed to match invalid address"; + } +} + +/* + * Errors in address lists + */ + +test_set "message" text: +From: stephan@ +To: nico@vestingbar.nl, @rename-it.nl +Cc: stephan@rename-it.nl, nonsense +Subject: Invalid addresses + +Test. +. +; + +test "Invalid address list" { + if address :is :localpart "to" "" { + test_fail ":localpart matched invalid address"; + } + + if address :is :domain "to" "rename-it.nl" { + test_fail ":domain matched invalid address"; + } +} +