X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fmatch.c;h=3624be9a8f15d626937d6402186fdb5eaf14dc76;hb=380e4e0ee92811b2edd87f06ad7f0d13e92882d4;hp=ae4dbe4235729a6d1bb76ffe8ec5cf83cc616a4c;hpb=d39a00392903e1a3f029ec9533abf9f11835ffd3;p=apps%2Fpfixtools.git diff --git a/postlicyd/match.c b/postlicyd/match.c index ae4dbe4..3624be9 100644 --- a/postlicyd/match.c +++ b/postlicyd/match.c @@ -16,17 +16,20 @@ /* products derived from this software without specific prior written */ /* permission. */ /* */ -/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ -/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ -/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ -/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ -/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ -/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ -/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ -/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ -/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ -/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ -/* THE POSSIBILITY OF SUCH DAMAGE. */ +/* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */ +/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ +/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ +/* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */ +/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */ +/* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */ +/* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */ +/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */ +/* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ +/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ +/* POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* Copyright (c) 2006-2008 the Authors */ +/* see AUTHORS and source files for details */ /******************************************************************************/ /* @@ -49,12 +52,20 @@ typedef struct match_condition_t { MATCH_EMPTY, } condition; - char *value; - ssize_t value_len; + static_str_t value; } match_condition_t; ARRAY(match_condition_t) -#define CONDITION_INIT { PTK_UNKNOWN, false, MATCH_UNKNOWN, NULL, 0 } +static const char *condition_names[] = { + "unknown", + "equals to", + "differs from", + "contains", + "is contained", + "is empty" +}; + +#define CONDITION_INIT { PTK_UNKNOWN, false, MATCH_UNKNOWN, { NULL, 0 } } typedef struct match_config_t { A(match_condition_t) conditions; @@ -68,8 +79,10 @@ static match_config_t *match_config_new(void) static inline void match_condition_wipe(match_condition_t *condition) { - p_delete(&condition->value); - condition->value_len = 0; + char *str = (char*)condition->value.str; + p_delete(&str); + condition->value.str = NULL; + condition->value.len = 0; } static void match_config_delete(match_config_t **config) @@ -86,8 +99,8 @@ static bool match_filter_constructor(filter_t *filter) #define PARSE_CHECK(Expr, Str, ...) \ if (!(Expr)) { \ - syslog(LOG_ERR, Str, ##__VA_ARGS__); \ - match_config_delete(&config); \ + err(Str, ##__VA_ARGS__); \ + match_config_delete(&config); \ return false; \ } @@ -124,7 +137,7 @@ static bool match_filter_constructor(filter_t *filter) condition.field = policy_tokenize(p, n - p); PARSE_CHECK(condition.field >= PTK_HELO_NAME && condition.field < PTK_SMTPD_ACCESS_POLICY, - "invalid field name %.*s", n - p, p); + "invalid field name %.*s", (int)(n - p), p); p = skipspaces(n); n = p + 1; PARSE_CHECK(IS_OP_START(*p) && IS_OP_END(*n), @@ -146,10 +159,10 @@ static bool match_filter_constructor(filter_t *filter) PARSE_CHECK(condition.condition != MATCH_UNKNOWN, "invalid operator"); if (condition.condition != MATCH_EMPTY) { - p = m_strnextsp(n + 1); + p = skipspaces(n + 1); PARSE_CHECK(*p, "no value defined to check the condition"); - condition.value_len = param->value_len - (p - param->value); - condition.value = p_dupstr(p, condition.value_len); + condition.value.len = param->value_len - (p - param->value); + condition.value.str = p_dupstr(p, condition.value.len); } array_add(config->conditions, condition); } break; @@ -173,73 +186,50 @@ static void match_filter_destructor(filter_t *filter) static inline bool match_condition(const match_condition_t *cond, const query_t *query) { - const char *field = NULL; - switch (cond->field) { -#define CASE(Up, Low) \ - case PTK_ ## Up: field = query->Low; break; - CASE(HELO_NAME, helo_name) - CASE(QUEUE_ID, queue_id) - CASE(SENDER, sender) - CASE(RECIPIENT, recipient) - CASE(RECIPIENT_COUNT, recipient_count) - CASE(CLIENT_ADDRESS, client_address) - CASE(CLIENT_NAME, client_name) - CASE(REVERSE_CLIENT_NAME, reverse_client_name) - CASE(INSTANCE, instance) - CASE(SASL_METHOD, sasl_method) - CASE(SASL_USERNAME, sasl_username) - CASE(SASL_SENDER, sasl_sender) - CASE(SIZE, size) - CASE(CCERT_SUBJECT, ccert_subject) - CASE(CCERT_ISSUER, ccert_issuer) - CASE(CCERT_FINGERPRINT, ccert_fingerprint) - CASE(ENCRYPTION_PROTOCOL, encryption_protocol) - CASE(ENCRYPTION_CIPHER, encryption_cipher) - CASE(ENCRYPTION_KEYSIZE, encryption_keysize) - CASE(ETRN_DOMAIN, etrn_domain) - CASE(STRESS, stress) -#undef CASE - default: return false; - } + const static_str_t *field = query_field_for_id(query, cond->field); + debug("running condition: \"%s\" %s %s\"%s\"", + field->str, condition_names[cond->condition], + cond->case_sensitive ? "" : "(alternative) ", + cond->value.str ? cond->value.str : "(none)"); switch (cond->condition) { case MATCH_EQUAL: case MATCH_DIFFER: - if (field == NULL) { + if (field == NULL || field->str == NULL) { return cond->condition != MATCH_DIFFER; } if (cond->case_sensitive) { - return !!((strcmp(field, cond->value) == 0) + return !!((strcmp(field->str, cond->value.str) == 0) ^ (cond->condition == MATCH_DIFFER)); } else { - return !!((ascii_strcasecmp(field, cond->value) == 0) + return !!((ascii_strcasecmp(field->str, cond->value.str) == 0) ^ (cond->condition == MATCH_DIFFER)); } break; case MATCH_CONTAINS: - if (field == NULL) { + if (field == NULL || field->str == NULL) { return false; } if (cond->case_sensitive) { - return strstr(field, cond->value); + return strstr(field->str, cond->value.str); } else { - return m_stristrn(field, cond->value, cond->value_len); + return m_stristrn(field->str, cond->value.str, cond->value.len); } break; case MATCH_CONTAINED: - if (field == NULL) { + if (field == NULL || field->str == NULL) { return false; } if (cond->case_sensitive) { - return strstr(cond->value, field); + return strstr(cond->value.str, field->str); } else { - return m_stristr(cond->value, field); + return m_stristr(cond->value.str, field->str); } break; case MATCH_EMPTY: - return !!(!!(field == NULL || *field == '\0')) ^ (!!cond->case_sensitive); + return !!((field == NULL || field->len == 0) ^ (!cond->case_sensitive)); default: assert(false && "invalid condition type"); @@ -247,20 +237,25 @@ static inline bool match_condition(const match_condition_t *cond, const query_t return true; } -static filter_result_t match_filter(const filter_t *filter, const query_t *query) +static filter_result_t match_filter(const filter_t *filter, const query_t *query, + filter_context_t *context) { const match_config_t *config = filter->data; foreach (const match_condition_t *condition, config->conditions) { bool r = match_condition(condition, query); if (!r && config->match_all) { + debug("condition failed, match_all failed"); return HTK_FAIL; } else if (r && !(config->match_all)) { + debug("condition succeed, not-match_all succeed"); return HTK_MATCH; } }} if (config->match_all) { + debug("all conditions matched, match_all succeed"); return HTK_MATCH; } else { + debug("no condition matched, not-match_all failed"); return HTK_FAIL; } } @@ -268,7 +263,8 @@ static filter_result_t match_filter(const filter_t *filter, const query_t *query static int match_init(void) { filter_type_t type = filter_register("match", match_filter_constructor, - match_filter_destructor, match_filter); + match_filter_destructor, match_filter, + NULL, NULL); /* Hooks. */ (void)filter_hook_register(type, "abort");