#include #include #include "buffer.h" #include "constmap.h" #include "env.h" #include "fmt.h" #include "logmsg.h" #include "sig.h" #include "str.h" #include "stralloc.h" #include "control.h" #include "qmail.h" #include "srs2.h" #ifdef USE_CONFIG #include "fehsqm-config.h" #else #include "auto_qmail.h" #endif #define WHO "srsforward" static void die_nomem() { logmsg(WHO, 111, FATAL, "out of memory"); } static void die_control() { logmsg(WHO, 110, FATAL, "Unable to read control files"); } struct qmail qqt; char *srsdomaininfo = 0; stralloc srsdomains = {0}; struct constmap mapsrsdomains; stralloc srshost = {0}; stralloc srserror = {0}; /** @file srsforward.c @brief forwarding mails with SRS enhanced addresss @return 0 on success (forwarded or not) -3 SRS error with error output 111 no memory / processing error 110 control file not readable */ static int srserror_str(int code) { if (!stralloc_copys(&srserror, "SRS: ")) die_nomem(); if (!stralloc_cats(&srserror, srs_strerror(code))) die_nomem(); if (!stralloc_0(&srserror)) die_nomem(); return -3; } static ssize_t mywrite(int fd, char *buf, int len) { qmail_put(&qqt, buf, len); return len; } char inbuf[BUFFER_INSIZE]; char outbuf[1]; buffer bi = BUFFER_INIT(read, 0, inbuf, sizeof(inbuf)); buffer bo = BUFFER_INIT(mywrite, -1, outbuf, sizeof(outbuf)); char num[FMT_ULONG]; int main(int argc, char **argv) { int i, j, r; char *qqx; srs_t *srs; stralloc cookie = {0}; char separator = '='; char srssender[512]; char *host = 0; char *sender = 0; char *dtline = 0; char *sendhost = 0; int alwaysrewrite = 0; sig_pipeignore(); sender = env_get("NEWSENDER"); if (!sender) logmsg(WHO, 100, FATAL, "NEWSENDER not set"); host = env_get("HOST"); if (!host) logmsg(WHO, 100, FATAL, "HOST not set"); dtline = env_get("DTLINE"); if (!dtline) logmsg(WHO, 100, FATAL, "DTLINE not set"); if (chdir(auto_qmail) == -1) logmsg(WHO, 111, FATAL, B("unable to chdir to: ", auto_qmail)); if (!stralloc_cats(&srshost, "!")) die_nomem(); if (!stralloc_cats(&srshost, host)) die_nomem(); switch (control_readfile(&srsdomains, "control/srsdomains", 0)) { case -1: die_control(); case 0: if (!constmap_init(&mapsrsdomains, "", 0, 1)) die_nomem(); break; case 1: if (!constmap_init(&mapsrsdomains, srsdomains.s, srsdomains.len, 1)) die_nomem(); break; } if (constmap(&mapsrsdomains, srshost.s, srshost.len)) return 0; // domain blacklisted if ((srsdomaininfo = constmap(&mapsrsdomains, host, str_len(host))) == 0) { if ((srsdomaininfo = constmap(&mapsrsdomains, "*", 1)) == 0) return 0; // '*' means always SRS else alwaysrewrite = 1; } if (*srsdomaininfo) { i = str_chr(srsdomaininfo, '|'); // multiple cookies; separated by ' ' if (srsdomaininfo[i] == '|') { srsdomaininfo[i] = 0; j = str_chr(srsdomaininfo + i + 1, '|'); if (srsdomaininfo[i + j + 1] == '|') { srsdomaininfo[i + j + 1] = 0; sendhost = srsdomaininfo + i + j + 2; // separator: - + = } separator = srsdomaininfo[i + 1]; } if (!stralloc_copys(&cookie, srsdomaininfo)) die_nomem(); if (!stralloc_0(&cookie)) die_nomem(); if (!stralloc_copys(&srshost, "")) die_nomem(); if (*sendhost) { j = str_len(sendhost); if (sendhost[j - 1] == '.') { if (!stralloc_copys(&srshost, sendhost)) die_nomem(); if (!stralloc_cats(&srshost, host)) die_nomem(); } else if (!stralloc_copys(&srshost, sendhost)) { die_nomem(); } } else if (!stralloc_copys(&srshost, host)) { die_nomem(); } if (!stralloc_0(&srshost)) die_nomem(); } else { die_control(); } /* Let's go SRS rewrite */ srs = srs_new(); if (separator == '-' || separator == '+' || separator == '=') { // '=' is default r = srs_set_separator(srs, separator); if (r != SRS_SUCCESS) return srserror_str(r); } if (alwaysrewrite) { r = srs_set_alwaysrewrite(srs, alwaysrewrite); if (r != SRS_SUCCESS) return srserror_str(r); } for (j = 0, i = 0; j < cookie.len; j++) { if (cookie.s[j] == ' ' || cookie.s[j] == '\0') { cookie.s[j] = '\0'; r = srs_add_secret(srs, cookie.s + i); if (r != SRS_SUCCESS) return srserror_str(r); i = j + 1; if (cookie.s[i] == ' ') { j++; continue; } } } if ((r = srs_forward(srs, srssender, sizeof(srssender), sender, srshost.s)) != SRS_SUCCESS) logmsg(WHO, 100, FATAL, B("Unable to forward: ", sender, " ", srs_strerror(r))); if (qmail_open(&qqt) == -1) logmsg(WHO, 111, FATAL, "unable to fork: "); qmail_puts(&qqt, dtline); if (buffer_copy(&bo, &bi) != 0) logmsg(WHO, 111, FATAL, "unable to read message: "); buffer_flush(&bo); num[fmt_ulong(num, qmail_qp(&qqt))] = 0; qmail_from(&qqt, srssender); while (*++argv) qmail_to(&qqt, *argv); qqx = qmail_close(&qqt); if (*qqx) logmsg(WHO, *qqx == 'D' ? 100 : 111, FATAL, qqx + 1); logmsg(WHO, 0, LOG, B(srssender, ": qp ", num)); }