summaryrefslogtreecommitdiff
path: root/src/srsforward.c
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-09 11:44:11 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-09 11:44:11 +0200
commitf1b71c9fe7dbb4886588a036399cf5ebe16b7c47 (patch)
treee07786aa479c9fb6ee3e537078470aaab5454f80 /src/srsforward.c
parenta293489ee83c8b05d845a162dc2a4de026f3775d (diff)
removed top level directory
Diffstat (limited to 'src/srsforward.c')
-rw-r--r--src/srsforward.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/srsforward.c b/src/srsforward.c
new file mode 100644
index 0000000..46176b5
--- /dev/null
+++ b/src/srsforward.c
@@ -0,0 +1,169 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include "control.h"
+#include "sig.h"
+#include "constmap.h"
+#include "readwrite.h"
+#include "exit.h"
+#include "env.h"
+#include "qmail.h"
+#include "auto_qmail.h"
+#include "buffer.h"
+#include "str.h"
+#include "fmt.h"
+#include "stralloc.h"
+#include "logmsg.h"
+#include "srs2.h"
+
+#define WHO "srsforward"
+
+void die_nomem() { logmsg(WHO,111,FATAL,"out of memory"); }
+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;
+}
+
+ssize_t mywrite(int fd,char *buf,int len)
+{
+ qmail_put(&qqt,buf,len);
+ return len;
+}
+
+char inbuf[BUFSIZE_LINE];
+char outbuf[BUFSIZE_LINE];
+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));
+
+}