#include #include #include #include #define SERVERNAME "smtp.rewrite.proxy" FILE*fout; char tempfilename[256]="/tmp/smtpreid.XXXXXX"; long dataoffset=0; long maildataoffset=0; char mailfrom[256]=""; char mailenvelopefrom[256]=""; int resentfrom=0; char*pineaddrbook=NULL; char configfile[]="/etc/smtpreident.conf"; char configuserfile[]="/etc/smtpreident.conf.%s"; /* * silly implementation for the strcasestr funcion, from somewhere on the Net * */ char *strcasestr(char *hailstack, char *needle) { register int lneed = strlen(needle); register int lhail = strlen(hailstack); register int i; for (i = 0; i < lhail; i++) if (!strncasecmp(hailstack + i, needle, lneed)) return hailstack + i; return NULL; } char*xstrncpy(char*s,char*s1,int n) { strncpy(s,s1,n);s[n-1]=0;return s;} int stripcrlf(char*s) { char*sp; int t=0; sp=strrchr(s,'\n');if(sp)if(!sp[1]){sp[0]=0;t=1;} sp=strrchr(s,'\r');if(sp)if(!sp[1]){sp[0]=0;t=1;} return t; } void stripparentheses(char*s) { char*sp; sp=strchr(s,'>');if(sp)sp[0]=0; if(s[0]=='<'){memmove(s,s+1,strlen(s));} } void handlemailfrom(char*s) { stripcrlf(s); stripparentheses(s); //syslog(LOG_WARNING,"FROM:%s",s); fprintf(fout,"FROM:%s\n",s); xstrncpy(mailfrom,s,256); } void handlercptto(char*s) { stripcrlf(s); stripparentheses(s); //syslog(LOG_WARNING,"TO:%s",s); fprintf(fout,"TO:%s\n",s); } void handledata(FILE*f) { char s[256]; int isheader=1; dataoffset=ftell(fout); while(!feof(f)) {s[0]=0;fgets(s,256,f); if(!strcmp(s,".\r\n"))break; if(!strcmp(s,".\n"))break; if(stripcrlf(s))fprintf(fout,"%s\n",s); else fprintf(fout,"%s",s); if(!strcmp(s,""))if(isheader){maildataoffset=ftell(fout);isheader=0;} if(!strncasecmp(s,"ReSent-From:",12))resentfrom=1; } } // read pine addressbook, retrieve the alias int getaliasformail(char*alias,char*addr) { FILE*f; char s[512],*sp,*sp1,*sp2; alias[0]=0; if(!pineaddrbook)return 0; // f=fopen("./addressbook","r");if(!f)return 0; f=fopen(pineaddrbook,"r");if(!f)return 0; while(!feof(f)) {s[0]=0;fgets(s,256,f); sp=strrchr(s,'\t');if(sp)if(sp[1]=='\n'){fgets(sp+1,256,f);}//for two-lined records sp=strchr(s,'\t');if(!sp)continue;sp[0]=0;sp++; sp2=strcasestr(sp,addr);if(!sp2)continue; sp1=sp;while(sp1[0]){if(!isalnum(sp1[0]))if(sp1[0]!='@')sp1[0]=' ';sp1++;} sp1--;if(sp1[0]!=' ')continue;sp1++; xstrncpy(alias,s,256);fclose(f);return 1; } fclose(f);return 0; } char configline[256]=""; char rewrite_from[256]=""; char rewrite_to[256]=""; int remove_headers=0; int remove_resent_headers=0; int remove_received_headers=0; int remove_deliveredto_headers=0; int remove_xshad_headers=0; int remove_xspam_headers=0; char variables[1024]=""; #define FILTER_MAX 1024 char filter[FILTER_MAX]=""; void replacegrepvar(char*s) { char s1[256]; snprintf(s1,255,"\n%s=",s); } void addvar(char*s1) { strcat(variables,"\n"); strcat(variables,s1); } void addfilter(char*s1) { strcat(filter,s1); strcat(filter,"|"); } int compareto(char*s,char*to,char*toalias) { int n=0; char*sp; if(!strncmp(s,"*",1))n=1; if(toalias)if(toalias[0])if(!strncasecmp(s,toalias,strlen(toalias)))n=strlen(toalias); if(to)if(to[0])if(!strncasecmp(s,to,strlen(to)))n=strlen(to); if(s[0]=='@'){sp=strchr(to,'@');if(sp)if(!strncasecmp(s,sp,strlen(sp)))n=strlen(sp);} //syslog(LOG_WARNING,"%s - %s - %s - %d - %s",s,to,toalias,n,s+n); if(!n)return 0; if(s[n]==':')return n+1; return 0; } void readconfigfile_file(char*conffile,char*from,char*to) { char s1[256],s2[256]; char s[256]; char alias[256]; char*sp,*sp2; int n,n1,n2; FILE*f; f=fopen(conffile,"r"); if(!f) {//syslog(LOG_WARNING,"Cannot open config file %s",conffile); return;} if(getaliasformail(alias,to))syslog(LOG_WARNING,"alias:%s",alias); while(!feof(f)) {s[0]=0;fgets(s,256,f);stripcrlf(s); if(s[0]=='#')continue; if(s[0]=='$'){if(s[1]=='=')xstrncpy(configline,s+2,256);else addvar(s);continue;} if(!strncasecmp(s,"to:",3)) {if(strchr(s,':'))if(strchr(s,':')==strrchr(s,':'))strcat(s,":"); // add trailing : if no : present, to simplify syntax n=compareto(s+3,to,alias);if(!n)continue; sp=s+3+n; if((!sp[0])||(!strcmp(sp,"$")))xstrncpy(sp,configline,255-(sp-s)); while(sp) {sp2=strchr(sp,';');if(sp2){sp2[0]=0;sp2++;} if(!strncasecmp(sp,"from:",5))xstrncpy(rewrite_from,sp+5,256); else if(!strncasecmp(sp,"to:",3))xstrncpy(rewrite_to,sp+3,256); else if(!strncasecmp(sp,"fromenv:",8))xstrncpy(mailenvelopefrom,sp+8,256); else if(!strncasecmp(sp,"filter:",7))addfilter(sp+7); else if(!strcasecmp(sp,"noresent"))remove_resent_headers=1; else if(!strcasecmp(sp,"noreceived"))remove_received_headers=1; else if(!strcasecmp(sp,"noxshad"))remove_xshad_headers=1; else if(!strcasecmp(sp,"noxspam"))remove_xspam_headers=1; else if(!strcasecmp(sp,"nodeliveredto"))remove_deliveredto_headers=1; sp=sp2;} } } if(resentfrom)rewrite_from[0]=0; // FIXME: Probably obsolete because of the acct-specific config files syslog(LOG_WARNING,"rewrite_from:%s %i",rewrite_from,resentfrom); } void readconfigfile(char*from,char*to) { char s[256]; configline[0]=0; rewrite_from[0]=0; rewrite_to[0]=0; mailenvelopefrom[0]=0; filter[0]=0; remove_headers=0; remove_resent_headers=0; remove_received_headers=0; remove_xshad_headers=0; remove_xspam_headers=0; remove_deliveredto_headers=0; // readconfigfile_file(configfile,from,to); snprintf(s,256,configuserfile,from); syslog(LOG_WARNING,"userfile:%s",s); readconfigfile_file(s,from,to); } int remove_next_header=0; void rewriteheaderline(char*s) { if((s[0]==' ')||(s[0]=='\t')){if(remove_next_header){s[0]=0;return;}}else remove_next_header=0; if(rewrite_from[0])if(!strncasecmp(s,"From:",5)){if(!strstr(s,"MAILER-DAEMON"))sprintf(s,"From: %s\n",rewrite_from);remove_next_header=1;return;} if(remove_resent_headers)if(!strncasecmp(s,"ReSent-",7)){s[0]=0;remove_next_header=1;return;} if(remove_deliveredto_headers)if(!strncasecmp(s,"Delivered-To:",13)){s[0]=0;remove_next_header=1;return;} if(remove_received_headers)if(!strncasecmp(s,"Received:",9)){s[0]=0;remove_next_header=1;return;} if(remove_received_headers)if(!strncasecmp(s,"X-Received:",11)){s[0]=0;remove_next_header=1;return;} if(remove_xshad_headers)if(!strncasecmp(s,"X-Shad-",7)){s[0]=0;remove_next_header=1;return;} if(remove_xspam_headers)if(!strncasecmp(s,"X-Spam-",7)){s[0]=0;remove_next_header=1;return;} } void sendmail(char*to) { FILE*f; char s[256]; int isheader=1; readconfigfile(mailfrom,to); if(!mailenvelopefrom[0])xstrncpy(mailenvelopefrom,mailfrom,256); if(rewrite_to[0])xstrncpy(to,rewrite_to,256); sprintf(s,"%s/usr/sbin/sendmail -f '%s' '%s'",filter,mailenvelopefrom,to); // inhibit sending mails, for test purposes f=fopen("./nosend","r"); if(f){syslog(LOG_WARNING,"Mail send inhibited by configuration.",s); syslog(LOG_WARNING,"From rewrite set to %s.",rewrite_from); fclose(f);return;} // if(!strcasecmp(to,"nobody")) {syslog(LOG_WARNING,"Mail thrown away."); return;} syslog(LOG_WARNING,"%s",s); f=popen(s,"w");if(!f)return; fseek(fout,dataoffset,SEEK_SET); while(!feof(fout)) {s[0]=0; fgets(s,256,fout); if(!strcmp(s,"\n"))isheader=0;else if(!strcmp(s,""))isheader=0; if(isheader)rewriteheaderline(s); fputs(s,f);} pclose(f); } void dumpdatatosendmail() { FILE*f; char s[256]; char sfrom[256]=""; long pos; fseek(fout,0,SEEK_SET); fgets(s,256,fout);//ignore the FROM: line pos=ftell(fout); while(pos