X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postlicyd%2Fquery.c;h=4a4ae9ca8a80e6fb75f19bf03341efe3f5a5b1eb;hb=7fa8c1bc673add68529fa2bda8134be5089e8745;hp=e2511c105f9f45f31769254ada5e8bb6f8031dda;hpb=87c3b6012886b05ab8ff36098e1e92e9afb1759c;p=apps%2Fpfixtools.git diff --git a/postlicyd/query.c b/postlicyd/query.c index e2511c1..4a4ae9c 100644 --- a/postlicyd/query.c +++ b/postlicyd/query.c @@ -36,13 +36,25 @@ #include "query.h" #include "policy_tokens.h" +#include "str.h" + +const char *smtp_state_names[SMTP_count] = { + "CONNECT", + "HELO", + "MAIL", + "RCPT", + "DATA", + "END-OF-MESSAGE", + "VRFY", + "ETRN", +}; bool query_parse(query_t *query, char *p) { #define PARSE_CHECK(expr, error, ...) \ do { \ if (!(expr)) { \ - syslog(LOG_ERR, error, ##__VA_ARGS__); \ + err(error, ##__VA_ARGS__); \ return false; \ } \ } while (0) @@ -72,8 +84,6 @@ bool query_parse(query_t *query, char *p) #define CASE(up, low) case PTK_##up: query->low = v; v[vlen] = '\0'; 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); @@ -93,6 +103,24 @@ bool query_parse(query_t *query, char *p) CASE(STRESS, stress); #undef CASE + case PTK_SENDER: + query->sender = v; + v[vlen] = '\0'; + query->sender_domain = memchr(query->sender, '@', vlen); + if (query->sender_domain != NULL) { + ++query->sender_domain; + } + break; + + case PTK_RECIPIENT: + query->recipient = v; + v[vlen] = '\0'; + query->recipient_domain = memchr(query->recipient, '@', vlen); + if (query->recipient_domain != NULL) { + ++query->recipient_domain; + } + break; + case PTK_REQUEST: PARSE_CHECK(vtk == PTK_SMTPD_ACCESS_POLICY, "unexpected `request' value: %.*s", vlen, v); @@ -124,7 +152,7 @@ bool query_parse(query_t *query, char *p) break; default: - syslog(LOG_WARNING, "unexpected key, skipped: %.*s", klen, k); + warn("unexpected key, skipped: %.*s", klen, k); continue; } } @@ -133,3 +161,101 @@ bool query_parse(query_t *query, char *p) #undef PARSE_CHECK } +const char *query_field_for_id(const query_t *query, postlicyd_token id) +{ + switch (id) { +#define CASE(Up, Low) \ + case PTK_ ## Up: return query->Low; + CASE(HELO_NAME, helo_name) + CASE(QUEUE_ID, queue_id) + CASE(SENDER, sender) + CASE(SENDER_DOMAIN, sender_domain) + CASE(RECIPIENT, recipient) + CASE(RECIPIENT_DOMAIN, recipient_domain) + 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 + case PTK_PROTOCOL_NAME: + return query->esmtp ? "ESMTP" : "SMTP"; + + case PTK_PROTOCOL_STATE: + return smtp_state_names[query->state]; + + default: return NULL; + } +} + +const char *query_field_for_name(const query_t *query, const char *name) +{ + postlicyd_token id = policy_tokenize(name, strlen(name)); + if (id == PTK_UNKNOWN) { + warn("unknown query field %s", name); + return NULL; + } + return query_field_for_id(query, id); +} + +ssize_t query_format(char *dest, size_t len, const char *fmt, const query_t *query) +{ + size_t written = 0; + size_t pos = 0; + const char *end = fmt + m_strlen(fmt); + +#define WRITE(Src, Len) \ + do { \ + size_t __len = (Len); \ + if (written < len) { \ + size_t __to_write = MIN(len - written - 1, __len); \ + memcpy(dest + written, (Src), __to_write); \ + written += __to_write; \ + } \ + pos += __len; \ + } while (0) + while (*fmt != '\0') { + const char *next_format = strstr(fmt, "${"); + if (next_format == NULL) { + next_format = end; + } + WRITE(fmt, next_format - fmt); + fmt = next_format; + if (*fmt != '\0') { + fmt += 2; + next_format = strchr(fmt, '}'); + if (next_format == NULL) { + return -1; + } + + postlicyd_token tok = policy_tokenize(fmt, next_format - fmt); + if (tok == PTK_UNKNOWN) { + warn("unknown field name \"%.*s\"", (int)(next_format - fmt), fmt); + } + const char *field = query == NULL ? NULL : query_field_for_id(query, tok); + if (field == NULL) { + WRITE("(null)", 6); + } else { + WRITE(field, m_strlen(field)); + } + fmt = next_format + 1; + } + } + + if (written > 0 && len > 0) { + dest[written] = '\0'; + } + return pos; +}