File: from.c

package info (click to toggle)
procmail 3.22-24
  • links: PTS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 2,104 kB
  • sloc: ansic: 9,885; sh: 1,957; makefile: 132
file content (187 lines) | stat: -rw-r--r-- 6,596 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/************************************************************************
 *	From_ line routines used by procmail				*
 *									*
 *	Copyright (c) 1990-1999, S.R. van den Berg, The Netherlands	*
 *	Copyright (c) 2000, Philip Guenther, The United States		*
 *							of America	*
 *	#include "../README"						*
 ************************************************************************/
#ifdef RCS
static /*const*/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"				/* for nlog */
#include "from.h"

static int privs;			     /* can we change the From_ line */
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;
}
			  /* tries to locate the timestamp on the From_ line */
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");	/* jump over address */
  if(skpspace(start)>=end)			       /* enough space left? */
     return (char*)start;	 /* no, too small for a timestamp, stop here */
  while(!(end[13]==':'&&end[16]==':')&&--end>start);	  /* search for :..: */
  ;{ int spc=0;						 /* found it perhaps */
     while(end-->start)		      /* now skip over the space to the left */
      { switch(*end)
	 { case ' ':case '\t':spc=1;
	      continue;
	 }
	if(!spc)
	   continue;
	break;
      }
     return (char*)end+1;	   /* this should be right after the address */
   }
}

size_t ctime2buf2 P((void))
{ time_t t=time((time_t*)0);				 /* the current time */
  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;	  /* if -f user is the same as the invoker, allow it */
     else if(privs==-1&&from)
      { if(verbose)
	   nlog(insufprivs);			      /* ignore the bogus -f */
	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);					    /* we're not yet sharing */
  rstart=thebody=themail.p;
  if(!Deliverymode&&!from)	       /* need to peek for a leading From_ ? */
      return;							     /* nope */
  r=ctime2buf2();
  lfr+=STRLEN(From_)+r;			   /* length of requested From_ line */
  if(tstamp)
     tstamp=r;					   /* save time stamp length */
  if(privs>0)						 /* privileged user? */
     linv=0;				 /* yes, so no need to insert >From_ */
  else
     linv+=STRLEN(Fakefield)+r;			    /* length of >From_ line */
  extra=0;
  if(Deliverymode!=2)					      /* if not LMTP */
   { while(1==(r=rread(STDIN,themail.p,1)))	  /* then read in first line */
	if(themail.p[0]!='\n')			    /* skip leading newlines */
	   break;
     if(r>0&&STRLEN(From_)<=(extra=1+rread(	      /* is it a From_ line? */
      STDIN,rstart+1,(int)(linebuf-2-1)))&&eqFrom_(themail.p))
      { rstart[extra]='\0';
	if(!(rstart=strchr(rstart,'\n')))
	 { do					     /* drop long From_ line */
	    { if((extra=rread(STDIN,themail.p,(int)(linebuf-2)))<=0)
		 break;
	      themail.p[extra]='\0';		  /* terminate it for strchr */
	    }
	   while(!(rstart=strchr(themail.p,'\n')));
	   extra=rstart?extra-(++rstart-themail.p):0;
	 }
	else
	 { size_t tfrl= ++rstart-themail.p; /* length of existing From_ line */
	   extra-=tfrl;					     /* demarcate it */
	   if(Deliverymode&&privs<0)
	    { if(verbose)			  /* discard the bogus From_ */
		 nlog(insufprivs);
	      syslog(LOG_ERR,slogstr,attemptst,fwhom);
	    }
	   else
	    { if(tstamp)
		 lfr=findtstamp(themail.p+STRLEN(From_),rstart)
		  -themail.p+tstamp;
	      else if(!from)		       /* leave the From_ line alone */
		 if(linv)				      /* fake alert? */
		    lfr=tfrl;	     /* yes, so separate From_ from the rest */
		 else
		    lfr=0,extra+=tfrl;		/* no, tack it onto the rest */
	      goto got_from;
	    }
	 }
      }
   }
  tstamp=0;			   /* no existing From_, so nothing to stamp */
  if(!from)							  /* no -f ? */
     linv=0;					  /* then it can't be a fake */
got_from:
  filled=lfr+linv+extra;			    /* From_ + >From_ + rest */
  if(lfr||linv)			     /* move read text beyond our From_ line */
   { r= *rstart;tmemmove(themail.p+lfr+linv,rstart,extra);
     rstart=themail.p+lfr;		      /* skip the From_ line, if any */
     if(!linv)						    /* no fake alert */
      { rstart[-tstamp]='\0';			       /* where do we append */
	if(!tstamp)			 /* no timestamp, so generate it all */
	   strcat(strcpy(themail.p,From_),fwhom);		/* From user */
      }
     else
      { if(lfr)					/* did we skip a From_ line? */
	   if(tstamp)			 /* copy the timestamp over the tail */
	      strcpy(rstart-tstamp,buf2);
	   else if(from)				 /* whole new From_? */
	      strcat(strcat(strcpy(themail.p,From_),fwhom),buf2);
	strcat(strcpy(rstart,Fakefield),invoker);	       /* fake alert */
      }					  /* overwrite the trailing \0 again */
     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;					/* assume they're privileged */
  if(Deliverymode&&*trusted_ids&&uid!=euid)
   { struct group*grp;const char*const*kp;
     if(logname)			      /* check out the invoker's uid */
	for(kp=trusted_ids;*kp;kp++)
	   if(!strcmp(logname,*kp))	    /* is it amongst the privileged? */
	      goto privileged;
     if(grp=getgrgid(gid))		      /* check out the invoker's gid */
	for(logname=grp->gr_name,kp=trusted_ids;*kp;kp++)
	   if(!strcmp(logname,*kp))	      /* is it among the privileged? */
	      goto privileged;
     privs= -override;		/* override only matters when not privileged */
   }
privileged:
  endgrent();
}