X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postfix.c;h=0b5f84aa7c3679a799f00722805240bcb4f295b5;hb=6a966ebc32006b64216715314ce21a506ef1f7c4;hp=46d2708a73e05ac10f2eae9085c9c1c21083e45d;hpb=14330fbdf398c3786803a001f0130b0d9ab70b46;p=apps%2Fpfixtools.git diff --git a/postfix.c b/postfix.c index 46d2708..0b5f84a 100644 --- a/postfix.c +++ b/postfix.c @@ -1,5 +1,5 @@ /******************************************************************************/ -/* postlicyd: a postfix policy daemon with a lot of features */ +/* pfixtools: a collection of postfix related tools */ /* ~~~~~~~~~ */ /* ________________________________________________________________________ */ /* */ @@ -33,78 +33,136 @@ * Copyright © 2006-2007 Pierre Habouzit */ -#include -#include -#include -#include -#include - -#include "job.h" +#include "common.h" #include "postfix.h" #include "buffer.h" #include "tokens.h" -struct jpriv_t { +#if 0 + +#define ishspace(c) ((c) == ' ' || (c) == '\t') + +typedef struct jpriv_t { buffer_t ibuf; buffer_t obuf; -}; + query_t query; +} jpriv_t; static jpriv_t *postfix_jpriv_init(jpriv_t *jp) { buffer_init(&jp->ibuf); buffer_init(&jp->obuf); + query_init(&jp->query); return jp; } static void postfix_jpriv_wipe(jpriv_t *jp) { + query_wipe(&jp->query); buffer_wipe(&jp->ibuf); buffer_wipe(&jp->obuf); } DO_NEW(jpriv_t, postfix_jpriv); DO_DELETE(jpriv_t, postfix_jpriv); -static void postfix_stop(job_t *job) +static int postfix_parsejob(query_t *query) { - postfix_jpriv_delete(&job->jdata); -} +#define PARSE_CHECK(expr, error, ...) \ + do { \ + if (!(expr)) { \ + syslog(LOG_ERR, error, ##__VA_ARGS__); \ + return -1; \ + } \ + } while (0) -static int postfix_parsejob(job_t *job) -{ - const char *p = skipspaces(job->jdata->ibuf.data); + char *p = vskipspaces(query->data.data); - for (;;) { - const char *k, *v; - int klen, vlen; + while (*p) { + char *k, *v; + int klen, vlen, vtk; - while (*p == ' ' || *p == '\t') + while (ishspace(*p)) p++; - p = strchrnul(k = p, '='); - if (!*p) - return -1; - for (klen = p - k; k[klen] == ' ' || k[klen] == '\t'; klen--); + p = strchr(k = p, '='); + PARSE_CHECK(p, "could not find '=' in line"); + for (klen = p - k; klen && ishspace(k[klen]); klen--); p += 1; /* skip = */ - while (*p == ' ' || *p == '\t') + while (ishspace(*p)) p++; p = strstr(v = p, "\r\n"); - if (!p) - return -1; - for (vlen = p - v; v[vlen] == ' ' || v[vlen] == '\t'; vlen--); + PARSE_CHECK(p, "could not find final \\r\\n in line"); + for (vlen = p - v; vlen && ishspace(v[vlen]); vlen--); p += 2; /* skip \r\n */ - /* do sth with (k,v) */ + vtk = tokenize(v, vlen); + switch (tokenize(k, klen)) { +#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); + CASE(RCLIENT_NAME, rclient_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(CCSERT_FINGERPRINT, ccsert_fingerprint); + CASE(ENCRYPTION_PROTOCOL, encryption_protocol); + CASE(ENCRYPTION_CIPHER, encryption_cipher); + CASE(ENCRYPTION_KEYSIZE, encryption_keysize); + CASE(ETRN_DOMAIN, etrn_domain); +#undef CASE + + case PTK_REQUEST: + PARSE_CHECK(vtk == PTK_SMTPD_ACCESS_POLICY, + "unexpected `request' value: %.*s", vlen, v); + break; + + case PTK_PROTOCOL_NAME: + PARSE_CHECK(vtk == PTK_SMTP || vtk == PTK_ESMTP, + "unexpected `protocol_name' value: %.*s", vlen, v); + query->esmtp = vtk == PTK_ESMTP; + break; - assert (p[0] && p[1]); - if (p[0] == '\r' && p[1] == '\n') + case PTK_PROTOCOL_STATE: + switch (vtk) { +#define CASE(name) case PTK_##name: query->state = SMTP_##name; break; + CASE(CONNECT); + CASE(EHLO); + CASE(HELO); + CASE(MAIL); + CASE(RCPT); + CASE(DATA); + CASE(END_OF_MESSAGE); + CASE(VRFY); + CASE(ETRN); + default: + PARSE_CHECK(false, "unexpected `protocol_state` value: %.*s", + vlen, v); +#undef CASE + } break; + + default: + return -1; + } } - return -1; + return query->state == SMTP_UNKNOWN ? -1 : 0; + +#undef PARSE_CHECK } static void postfix_process(job_t *job) { int nb; + const char *p; switch (job->mode) { case JOB_LISTEN: @@ -128,8 +186,6 @@ static void postfix_process(job_t *job) if (job->jdata->obuf.len) return; - job_update_mode(job, JOB_READ); - /* fall through */ case JOB_READ: @@ -146,22 +202,26 @@ static void postfix_process(job_t *job) return; } - if (!strstr(skipspaces(job->jdata->ibuf.data), "\r\n\r\n")) { + p = strstr(skipspaces(job->jdata->ibuf.data), "\r\n\r\n"); + if (!p) { if (job->jdata->ibuf.len > SHRT_MAX) { syslog(LOG_ERR, "too much data without CRLFCRLF"); job->error = true; } return; } + p += 4; - if (postfix_parsejob(job) < 0) { - syslog(LOG_ERR, "could not parse postfix request"); + query_reset(&job->jdata->query); + buffer_add(&job->jdata->query.data, job->jdata->ibuf.data, + p - 2 - job->jdata->ibuf.data); + buffer_consume(&job->jdata->query.data, p - job->jdata->ibuf.data); + + if (postfix_parsejob(&job->jdata->query) < 0) { job->error = true; return; } - job_update_mode(job, JOB_IDLE); - /* TODO: run the scenario */ return; @@ -170,3 +230,4 @@ static void postfix_process(job_t *job) return; } } +#endif