X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=postfix.c;h=0b5f84aa7c3679a799f00722805240bcb4f295b5;hb=6a966ebc32006b64216715314ce21a506ef1f7c4;hp=f88feba795c579b171679c26767e13da4ff51a13;hpb=59c1f51ef38081d87885a37873545154c7a23e2d;p=apps%2Fpfixtools.git diff --git a/postfix.c b/postfix.c index f88feba..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,42 +33,136 @@ * Copyright © 2006-2007 Pierre Habouzit */ -#include -#include -#include -#include - -#include "job.h" +#include "common.h" #include "postfix.h" #include "buffer.h" +#include "tokens.h" + +#if 0 + +#define ishspace(c) ((c) == ' ' || (c) == '\t') -struct jpriv_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) + + char *p = vskipspaces(query->data.data); + + while (*p) { + char *k, *v; + int klen, vlen, vtk; + + while (ishspace(*p)) + p++; + 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 (ishspace(*p)) + p++; + p = strstr(v = p, "\r\n"); + 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 */ + + 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; + + 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 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: @@ -92,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: @@ -110,11 +202,27 @@ static void postfix_process(job_t *job) return; } - if (!strstr(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; + + 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; + } - /* TODO: do the parse */ - job_update_mode(job, JOB_IDLE); + /* TODO: run the scenario */ return; default: @@ -122,3 +230,4 @@ static void postfix_process(job_t *job) return; } } +#endif