#ifdef RCS
static char rcsid[]=
"$Id: from.c,v 1.2 2000/10/27 20:03:58 guenther Exp $";
#endif
#include "procmail.h"
#include "robust.h"
#include "shell.h"
#include "memblk.h"
#include "common.h"
#include "misc.h"
#include "from.h"
static int privs;
static const char From_[]=FROM,Fakefield[]=FAKE_FIELD,
attemptst[]="Attempt to fake stamp by";
int eqFrom_(a)const char*const a;
{ return !strncmp(a,From_,STRLEN(From_));
}
const char*skipFrom_(startchar,tobesentp)const char*startchar;long*tobesentp;
{ if(eqFrom_(startchar))
{ long tobesent;char c;
tobesent= *tobesentp;
do
while(c= *startchar++,--tobesent&&c!='\n');
while(*startchar=='>');
*tobesentp=tobesent;
}
return startchar;
}
static char*findtstamp(start,end)const char*start,*end;
{ end-=25;
if(*start==' '&&(++start==end||*start==' '&&++start==end))
return (char*)start-1;
start=skpspace(start);start+=strcspn(start," \t\n");
if(skpspace(start)>=end)
return (char*)start;
while(!(end[13]==':'&&end[16]==':')&&--end>start);
;{ int spc=0;
while(end-->start)
{ switch(*end)
{ case ' ':case '\t':spc=1;
continue;
}
if(!spc)
continue;
break;
}
return (char*)end+1;
}
}
size_t ctime2buf2 P((void))
{ time_t t=time((time_t*)0);
buf2[0]=buf2[1]=' ';strcpy(buf2+2,ctime(&t));
return strlen(buf2);
}
void makeFrom(from,invoker)const char*from,*const invoker;
{ static const char mdaemon[]=MAILERDAEMON;
const char*fwhom;char*rstart;size_t lfr,linv;int tstamp,extra,r;
if(Deliverymode!=2)
{ tstamp=from&&*from==REFRESH_TIME&&!from[1];
fwhom=from;
}
else
{ tstamp=0;
fwhom= *from?from:mdaemon;
}
if(from&&!tstamp)
{ if(privs!=1&&!strcmp(from,invoker))
privs=1;
else if(privs==-1&&from)
{ if(verbose)
nlog(insufprivs);
syslog(LOG_ERR,slogstr,attemptst,invoker);from=0;
fwhom=invoker;
}
}
else
fwhom=invoker;
makeblock(&themail,2*linebuf+(lfr=strlen(fwhom))+(linv=strlen(invoker)));
private(1);
rstart=thebody=themail.p;
if(!Deliverymode&&!from)
return;
r=ctime2buf2();
lfr+=STRLEN(From_)+r;
if(tstamp)
tstamp=r;
if(privs>0)
linv=0;
else
linv+=STRLEN(Fakefield)+r;
extra=0;
if(Deliverymode!=2)
{ while(1==(r=rread(STDIN,themail.p,1)))
if(themail.p[0]!='\n')
break;
if(r>0&&STRLEN(From_)<=(extra=1+rread(
STDIN,rstart+1,(int)(linebuf-2-1)))&&eqFrom_(themail.p))
{ rstart[extra]='\0';
if(!(rstart=strchr(rstart,'\n')))
{ do
{ if((extra=rread(STDIN,themail.p,(int)(linebuf-2)))<=0)
break;
themail.p[extra]='\0';
}
while(!(rstart=strchr(themail.p,'\n')));
extra=rstart?extra-(++rstart-themail.p):0;
}
else
{ size_t tfrl= ++rstart-themail.p;
extra-=tfrl;
if(Deliverymode&&privs<0)
{ if(verbose)
nlog(insufprivs);
syslog(LOG_ERR,slogstr,attemptst,fwhom);
}
else
{ if(tstamp)
lfr=findtstamp(themail.p+STRLEN(From_),rstart)
-themail.p+tstamp;
else if(!from)
if(linv)
lfr=tfrl;
else
lfr=0,extra+=tfrl;
goto got_from;
}
}
}
}
tstamp=0;
if(!from)
linv=0;
got_from:
filled=lfr+linv+extra;
if(lfr||linv)
{ r= *rstart;tmemmove(themail.p+lfr+linv,rstart,extra);
rstart=themail.p+lfr;
if(!linv)
{ rstart[-tstamp]='\0';
if(!tstamp)
strcat(strcpy(themail.p,From_),fwhom);
}
else
{ if(lfr)
if(tstamp)
strcpy(rstart-tstamp,buf2);
else if(from)
strcat(strcat(strcpy(themail.p,From_),fwhom),buf2);
strcat(strcpy(rstart,Fakefield),invoker);
}
strcat(themail.p,buf2);themail.p[lfr+linv]=r;
}
}
void checkprivFrom_(euid,logname,override)uid_t euid;const char*logname;
int override;
{ static const char*const trusted_ids[]=TRUSTED_IDS;
privs=1;
if(Deliverymode&&*trusted_ids&&uid!=euid)
{ struct group*grp;const char*const*kp;
if(logname)
for(kp=trusted_ids;*kp;kp++)
if(!strcmp(logname,*kp))
goto privileged;
if(grp=getgrgid(gid))
for(logname=grp->gr_name,kp=trusted_ids;*kp;kp++)
if(!strcmp(logname,*kp))
goto privileged;
privs= -override;
}
privileged:
endgrent();
}