#include #include #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 "auto_break.h" #include "buffer.h" #include "case.h" #include "str.h" #include "fmt.h" #include "stralloc.h" #include "logmsg.h" #include "srs2.h" #define WHO "srsreverse" 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 *vdomainuser = 0; stralloc vdomains = {0}; struct constmap mapvdomains; char *srsdomaininfo = 0; stralloc srsdomains = {0}; struct constmap mapsrsdomains; stralloc srserror = {0}; stralloc srshost = {0}; /** @file srsreverse.c @brief forwarding bounces 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 i, j, r; char *recipient; char *dtline; char *qqx; srs_t *srs; stralloc cookie = {0}; char separator = '='; char srsrecipient[512]; char *host = 0; sig_pipeignore(); recipient = env_get("RECIPIENT"); if (!recipient) logmsg(WHO,100,FATAL,"RECIPIENT not set"); dtline = env_get("DTLINE"); if (!dtline) logmsg(WHO,100,FATAL,"DTLINE not set"); host = env_get("HOST"); if (!host) logmsg(WHO,100,FATAL,"HOST not set"); if (chdir(auto_qmail) == -1) logmsg(WHO,111,FATAL,B("unable to chdir to: ",auto_qmail)); /* Check for particular virtual SRS domain user */ switch (control_readfile(&vdomains,"control/virtualdomains",0)) { case -1: die_control(); case 0: if (!constmap_init(&mapvdomains,"",0,1)) die_nomem(); break; case 1: if (!constmap_init(&mapvdomains,vdomains.s,vdomains.len,1)) die_nomem(); break; } j = str_len(host); for (i = 0; i <= j; ++i) if ((i == 0) || (host[i] == '.')) { if (!stralloc_copys(&srshost,"")) die_nomem(); if (!stralloc_catb(&srshost,host + i,j - i)) die_nomem(); if ((srsdomaininfo = constmap(&mapvdomains,srshost.s,srshost.len)) != 0) goto SRSDOMAINS; } if (!stralloc_copys(&srshost,host)) die_nomem(); SRSDOMAINS: 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 ((srsdomaininfo = constmap(&mapsrsdomains,srshost.s,srshost.len)) == 0) if ((srsdomaininfo = constmap(&mapsrsdomains,"*",1)) == 0) return 0; if (*srsdomaininfo) { i = str_chr(srsdomaininfo,'|'); // multiple cookies; separated by ' ' if (srsdomaininfo[i] == '|') { srsdomaininfo[i] = 0; separator = srsdomaininfo[i+1]; } if (!stralloc_copys(&cookie,srsdomaininfo)) die_nomem(); if (!stralloc_0(&cookie)) die_nomem(); } /* strip virtual user from recipient */ if ((vdomainuser = constmap(&mapvdomains,host,j))) { i = str_chr(recipient,*auto_break); if (!case_diffb(recipient,i - 1,vdomainuser)) recipient += i + 1; } /* Let's go SRS reverse */ srs = srs_new(); if (separator == '-' || separator == '+' || separator == '=') { // '=' is default r = srs_set_separator(srs,separator); 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_reverse(srs,srsrecipient,sizeof(srsrecipient),recipient)) != SRS_SUCCESS) { logmsg(WHO,100,FATAL,B("unable to reverse: ",recipient," ",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,""); qmail_to(&qqt,srsrecipient); qqx = qmail_close(&qqt); if (*qqx) logmsg(WHO,*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); logmsg(WHO,0,LOG,B(srsrecipient,": qp ",num)); }