#include #include "buffer.h" #include "byte.h" #include "case.h" #include "env.h" #include "exit.h" #include "fmt.h" #include "ip.h" #include "sig.h" #include "str.h" #include "now.h" #include "qmail.h" #include "received.h" #ifdef USE_CONFIG #include "fehsqm-config.h" #else #include "auto_qmail.h" #endif #define PORT_QMQP "628" static void resources() { _exit(111); } static ssize_t safewrite(int fd, char *buf, int len) { int r; r = write(fd, buf, len); if (r <= 0) _exit(0); return r; } static ssize_t saferead(int fd, char *buf, int len) { int r; r = read(fd, buf, len); if (r <= 0) _exit(0); return r; } char inbuf[512]; buffer bi = BUFFER_INIT(saferead, 0, inbuf, sizeof(inbuf)); char outbuf[256]; buffer bo = BUFFER_INIT(safewrite, 1, outbuf, sizeof(outbuf)); unsigned long bytesleft = 100; static void getbyte(char *ch) { if (!bytesleft--) _exit(100); buffer_get(&bi, ch, 1); } static unsigned long getlen() { unsigned long len = 0; char ch; for (;;) { getbyte(&ch); if (ch == ':') return len; if (len > 200000000) resources(); len = 10 * len + (ch - '0'); } } static void getcomma() { char ch; getbyte(&ch); if (ch != ',') _exit(100); } struct qmail qq; static void identify() { char *remotehost; char *remoteinfo; char *remoteip; char *local; char *localport; remotehost = env_get("TCP6REMOTEHOST"); if (!remotehost) remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCP6REMOTEINFO"); if (!remoteinfo) remoteinfo = env_get("TCPREMOTEINFO"); remoteip = env_get("TCP6REMOTEIP"); if (remoteip && byte_equal(remoteip, 7, V4MAPPREFIX)) remoteip = remoteip + 7; if (!remoteip) remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; local = env_get("TCP6LOCALHOST"); if (!local) local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCP6LOCALIP"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; localport = env_get("TCP6LOCALPORT"); if (!localport) localport = env_get("TCPLOCALPORT"); if (!localport) localport = "0"; received(&qq, "QMQP", local, remoteip, remotehost, remoteinfo, (char *)0, (char *)0, (char *)0); } char buf[1000]; char strnum[FMT_ULONG]; static int getbuf() { unsigned long len; int i; len = getlen(); if (len >= 1000) { for (i = 0; i < len; ++i) getbyte(buf); getcomma(); buf[0] = 0; return 0; } for (i = 0; i < len; ++i) getbyte(buf + i); getcomma(); buf[len] = 0; return byte_chr(buf, len, '\0') == len; } int flagok = 1; int main() { char *result; unsigned long qp; unsigned long len; char ch; sig_pipeignore(); sig_alarmcatch(resources); alarm(3600); bytesleft = getlen(); len = getlen(); if (chdir(auto_qmail) == -1) resources(); if (qmail_open(&qq) == -1) resources(); qp = qmail_qp(&qq); identify(); while (len > 0) { /* XXX: could speed this up */ getbyte(&ch); --len; qmail_put(&qq, &ch, 1); } getcomma(); if (getbuf()) { qmail_from(&qq, buf); } else { qmail_from(&qq, ""); qmail_fail(&qq); flagok = 0; } while (bytesleft) { if (getbuf()) { qmail_to(&qq, buf); } else { qmail_fail(&qq); flagok = 0; } } bytesleft = 1; getcomma(); result = qmail_close(&qq); if (!*result) { len = fmt_str(buf, "Kok "); len += fmt_ulong(buf + len, (unsigned long)now()); len += fmt_str(buf + len, " qp "); len += fmt_ulong(buf + len, qp); buf[len] = 0; result = buf; } if (!flagok) result = "Dsorry, I can't accept addresses like that (#5.1.3)"; buffer_put(&bo, strnum, fmt_ulong(strnum, (unsigned long)str_len(result))); buffer_puts(&bo, ":"); buffer_puts(&bo, result); buffer_puts(&bo, ","); buffer_flush(&bo); _exit(0); }