Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include "smtpd.h"
3 5cdb1798 2005-10-29 devnull #include "smtp.h"
4 5cdb1798 2005-10-29 devnull #include <ctype.h>
5 5cdb1798 2005-10-29 devnull #include <ip.h>
6 5cdb1798 2005-10-29 devnull #include <ndb.h>
7 5cdb1798 2005-10-29 devnull #include <mp.h>
8 5cdb1798 2005-10-29 devnull #include <libsec.h>
9 5cdb1798 2005-10-29 devnull #include <auth.h>
10 5cc53af9 2006-02-12 devnull #include <thread.h>
11 a79cd783 2006-02-12 devnull #include "../smtp/rfc822.tab.h"
12 5cdb1798 2005-10-29 devnull
13 5cdb1798 2005-10-29 devnull #define DBGMX 1
14 5cdb1798 2005-10-29 devnull
15 5cdb1798 2005-10-29 devnull char *me;
16 5cdb1798 2005-10-29 devnull char *him="";
17 5cdb1798 2005-10-29 devnull char *dom;
18 5cdb1798 2005-10-29 devnull process *pp;
19 5cdb1798 2005-10-29 devnull String *mailer;
20 5cdb1798 2005-10-29 devnull NetConnInfo *nci;
21 5cdb1798 2005-10-29 devnull
22 5cdb1798 2005-10-29 devnull int filterstate = ACCEPT;
23 5cdb1798 2005-10-29 devnull int trusted;
24 5cdb1798 2005-10-29 devnull int logged;
25 5cdb1798 2005-10-29 devnull int rejectcount;
26 5cdb1798 2005-10-29 devnull int hardreject;
27 5cdb1798 2005-10-29 devnull
28 5cdb1798 2005-10-29 devnull Biobuf bin;
29 5cdb1798 2005-10-29 devnull
30 5cdb1798 2005-10-29 devnull int debug;
31 5cdb1798 2005-10-29 devnull int Dflag;
32 5cdb1798 2005-10-29 devnull int fflag;
33 5cdb1798 2005-10-29 devnull int gflag;
34 5cdb1798 2005-10-29 devnull int rflag;
35 5cdb1798 2005-10-29 devnull int sflag;
36 5cdb1798 2005-10-29 devnull int authenticate;
37 5cdb1798 2005-10-29 devnull int authenticated;
38 5cdb1798 2005-10-29 devnull int passwordinclear;
39 5cdb1798 2005-10-29 devnull char *tlscert;
40 5cdb1798 2005-10-29 devnull
41 5cdb1798 2005-10-29 devnull List senders;
42 5cdb1798 2005-10-29 devnull List rcvers;
43 5cdb1798 2005-10-29 devnull
44 5cdb1798 2005-10-29 devnull char pipbuf[ERRMAX];
45 5cdb1798 2005-10-29 devnull char *piperror;
46 5cdb1798 2005-10-29 devnull int pipemsg(int*);
47 5cdb1798 2005-10-29 devnull String* startcmd(void);
48 5cdb1798 2005-10-29 devnull int rejectcheck(void);
49 5cdb1798 2005-10-29 devnull String* mailerpath(char*);
50 5cdb1798 2005-10-29 devnull
51 5cdb1798 2005-10-29 devnull static int
52 5cdb1798 2005-10-29 devnull catchalarm(void *a, char *msg)
53 5cdb1798 2005-10-29 devnull {
54 5cdb1798 2005-10-29 devnull int rv = 1;
55 5cdb1798 2005-10-29 devnull
56 5cdb1798 2005-10-29 devnull USED(a);
57 5cdb1798 2005-10-29 devnull
58 5cdb1798 2005-10-29 devnull /* log alarms but continue */
59 5cdb1798 2005-10-29 devnull if(strstr(msg, "alarm")){
60 5cdb1798 2005-10-29 devnull if(senders.first && rcvers.first)
61 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "note: %s->%s: %s", s_to_c(senders.first->p),
62 5cdb1798 2005-10-29 devnull s_to_c(rcvers.first->p), msg);
63 5cdb1798 2005-10-29 devnull else
64 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "note: %s", msg);
65 5cdb1798 2005-10-29 devnull rv = 0;
66 5cdb1798 2005-10-29 devnull }
67 5cdb1798 2005-10-29 devnull
68 5cdb1798 2005-10-29 devnull /* kill the children if there are any */
69 5cdb1798 2005-10-29 devnull if(pp)
70 5cdb1798 2005-10-29 devnull syskillpg(pp->pid);
71 5cdb1798 2005-10-29 devnull
72 5cdb1798 2005-10-29 devnull return rv;
73 5cdb1798 2005-10-29 devnull }
74 5cdb1798 2005-10-29 devnull
75 5cdb1798 2005-10-29 devnull /* override string error functions to do something reasonable */
76 5cdb1798 2005-10-29 devnull void
77 5cdb1798 2005-10-29 devnull s_error(char *f, char *status)
78 5cdb1798 2005-10-29 devnull {
79 5cdb1798 2005-10-29 devnull char errbuf[Errlen];
80 5cdb1798 2005-10-29 devnull
81 5cdb1798 2005-10-29 devnull errbuf[0] = 0;
82 5cdb1798 2005-10-29 devnull rerrstr(errbuf, sizeof(errbuf));
83 5cdb1798 2005-10-29 devnull if(f && *f)
84 5cdb1798 2005-10-29 devnull reply("452 out of memory %s: %s\r\n", f, errbuf);
85 5cdb1798 2005-10-29 devnull else
86 5cdb1798 2005-10-29 devnull reply("452 out of memory %s\r\n", errbuf);
87 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys);
88 5cc53af9 2006-02-12 devnull threadexitsall(status);
89 5cdb1798 2005-10-29 devnull }
90 5cdb1798 2005-10-29 devnull
91 5cdb1798 2005-10-29 devnull void
92 5cc53af9 2006-02-12 devnull threadmain(int argc, char **argv)
93 5cdb1798 2005-10-29 devnull {
94 5cdb1798 2005-10-29 devnull char *p, buf[1024];
95 5cdb1798 2005-10-29 devnull char *netdir;
96 5cdb1798 2005-10-29 devnull
97 5cdb1798 2005-10-29 devnull netdir = nil;
98 5cdb1798 2005-10-29 devnull quotefmtinstall();
99 5cdb1798 2005-10-29 devnull ARGBEGIN{
100 5cdb1798 2005-10-29 devnull case 'D':
101 5cdb1798 2005-10-29 devnull Dflag++;
102 5cdb1798 2005-10-29 devnull break;
103 5cdb1798 2005-10-29 devnull case 'd':
104 5cdb1798 2005-10-29 devnull debug++;
105 5cdb1798 2005-10-29 devnull break;
106 5cdb1798 2005-10-29 devnull case 'n': /* log peer ip address */
107 5cdb1798 2005-10-29 devnull netdir = ARGF();
108 5cdb1798 2005-10-29 devnull break;
109 5cdb1798 2005-10-29 devnull case 'f': /* disallow relaying */
110 5cdb1798 2005-10-29 devnull fflag = 1;
111 5cdb1798 2005-10-29 devnull break;
112 5cdb1798 2005-10-29 devnull case 'g':
113 5cdb1798 2005-10-29 devnull gflag = 1;
114 5cdb1798 2005-10-29 devnull break;
115 5cdb1798 2005-10-29 devnull case 'h': /* default domain name */
116 5cdb1798 2005-10-29 devnull dom = ARGF();
117 5cdb1798 2005-10-29 devnull break;
118 5cdb1798 2005-10-29 devnull case 'k': /* prohibited ip address */
119 5cdb1798 2005-10-29 devnull p = ARGF();
120 5cdb1798 2005-10-29 devnull if (p)
121 5cdb1798 2005-10-29 devnull addbadguy(p);
122 5cdb1798 2005-10-29 devnull break;
123 5cdb1798 2005-10-29 devnull case 'm': /* set mail command */
124 5cdb1798 2005-10-29 devnull p = ARGF();
125 5cdb1798 2005-10-29 devnull if(p)
126 5cdb1798 2005-10-29 devnull mailer = mailerpath(p);
127 5cdb1798 2005-10-29 devnull break;
128 5cdb1798 2005-10-29 devnull case 'r':
129 5cdb1798 2005-10-29 devnull rflag = 1; /* verify sender's domain */
130 5cdb1798 2005-10-29 devnull break;
131 5cdb1798 2005-10-29 devnull case 's': /* save blocked messages */
132 5cdb1798 2005-10-29 devnull sflag = 1;
133 5cdb1798 2005-10-29 devnull break;
134 5cdb1798 2005-10-29 devnull case 'a':
135 5cdb1798 2005-10-29 devnull authenticate = 1;
136 5cdb1798 2005-10-29 devnull break;
137 5cdb1798 2005-10-29 devnull case 'p':
138 5cdb1798 2005-10-29 devnull passwordinclear = 1;
139 5cdb1798 2005-10-29 devnull break;
140 5cdb1798 2005-10-29 devnull case 'c':
141 5cc53af9 2006-02-12 devnull fprint(2, "tls is not available\n");
142 5cc53af9 2006-02-12 devnull threadexitsall("no tls");
143 5cdb1798 2005-10-29 devnull tlscert = ARGF();
144 5cdb1798 2005-10-29 devnull break;
145 5cdb1798 2005-10-29 devnull case 't':
146 5cdb1798 2005-10-29 devnull fprint(2, "%s: the -t option is no longer supported, see -c\n", argv0);
147 5cdb1798 2005-10-29 devnull tlscert = "/sys/lib/ssl/smtpd-cert.pem";
148 5cdb1798 2005-10-29 devnull break;
149 5cdb1798 2005-10-29 devnull default:
150 5cdb1798 2005-10-29 devnull fprint(2, "usage: smtpd [-dfhrs] [-n net] [-c cert]\n");
151 5cc53af9 2006-02-12 devnull threadexitsall("usage");
152 5cdb1798 2005-10-29 devnull }ARGEND;
153 5cdb1798 2005-10-29 devnull
154 5cdb1798 2005-10-29 devnull nci = getnetconninfo(netdir, 0);
155 5cdb1798 2005-10-29 devnull if(nci == nil)
156 5cdb1798 2005-10-29 devnull sysfatal("can't get remote system's address");
157 5cdb1798 2005-10-29 devnull
158 5cdb1798 2005-10-29 devnull if(mailer == nil)
159 5cdb1798 2005-10-29 devnull mailer = mailerpath("send");
160 5cdb1798 2005-10-29 devnull
161 5cdb1798 2005-10-29 devnull if(debug){
162 5cdb1798 2005-10-29 devnull close(2);
163 b5f65921 2006-02-11 devnull snprint(buf, sizeof(buf), "%s/smtpd.db", UPASLOG);
164 5cdb1798 2005-10-29 devnull if (open(buf, OWRITE) >= 0) {
165 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
166 5cdb1798 2005-10-29 devnull fprint(2, "%d smtpd %s\n", getpid(), thedate());
167 5cdb1798 2005-10-29 devnull } else
168 5cdb1798 2005-10-29 devnull debug = 0;
169 5cdb1798 2005-10-29 devnull }
170 5cdb1798 2005-10-29 devnull getconf();
171 5cdb1798 2005-10-29 devnull Binit(&bin, 0, OREAD);
172 5cdb1798 2005-10-29 devnull
173 5cdb1798 2005-10-29 devnull chdir(UPASLOG);
174 5cdb1798 2005-10-29 devnull me = sysname_read();
175 5cdb1798 2005-10-29 devnull if(dom == 0 || dom[0] == 0)
176 5cdb1798 2005-10-29 devnull dom = domainname_read();
177 5cdb1798 2005-10-29 devnull if(dom == 0 || dom[0] == 0)
178 5cdb1798 2005-10-29 devnull dom = me;
179 5cdb1798 2005-10-29 devnull sayhi();
180 5cdb1798 2005-10-29 devnull parseinit();
181 5cdb1798 2005-10-29 devnull /* allow 45 minutes to parse the header */
182 5cdb1798 2005-10-29 devnull atnotify(catchalarm, 1);
183 5cdb1798 2005-10-29 devnull alarm(45*60*1000);
184 5cdb1798 2005-10-29 devnull zzparse();
185 5cc53af9 2006-02-12 devnull threadexitsall(0);
186 5cdb1798 2005-10-29 devnull }
187 5cdb1798 2005-10-29 devnull
188 5cdb1798 2005-10-29 devnull void
189 5cdb1798 2005-10-29 devnull listfree(List *l)
190 5cdb1798 2005-10-29 devnull {
191 5cdb1798 2005-10-29 devnull Link *lp;
192 5cdb1798 2005-10-29 devnull Link *next;
193 5cdb1798 2005-10-29 devnull
194 5cdb1798 2005-10-29 devnull for(lp = l->first; lp; lp = next){
195 5cdb1798 2005-10-29 devnull next = lp->next;
196 5cdb1798 2005-10-29 devnull s_free(lp->p);
197 5cdb1798 2005-10-29 devnull free(lp);
198 5cdb1798 2005-10-29 devnull }
199 5cdb1798 2005-10-29 devnull l->first = l->last = 0;
200 5cdb1798 2005-10-29 devnull }
201 5cdb1798 2005-10-29 devnull
202 5cdb1798 2005-10-29 devnull void
203 5cdb1798 2005-10-29 devnull listadd(List *l, String *path)
204 5cdb1798 2005-10-29 devnull {
205 5cdb1798 2005-10-29 devnull Link *lp;
206 5cdb1798 2005-10-29 devnull
207 5cdb1798 2005-10-29 devnull lp = (Link *)malloc(sizeof(Link));
208 5cdb1798 2005-10-29 devnull lp->p = path;
209 5cdb1798 2005-10-29 devnull lp->next = 0;
210 5cdb1798 2005-10-29 devnull
211 5cdb1798 2005-10-29 devnull if(l->last)
212 5cdb1798 2005-10-29 devnull l->last->next = lp;
213 5cdb1798 2005-10-29 devnull else
214 5cdb1798 2005-10-29 devnull l->first = lp;
215 5cdb1798 2005-10-29 devnull l->last = lp;
216 5cdb1798 2005-10-29 devnull }
217 5cdb1798 2005-10-29 devnull
218 5cdb1798 2005-10-29 devnull #define SIZE 4096
219 5cdb1798 2005-10-29 devnull int
220 5cdb1798 2005-10-29 devnull reply(char *fmt, ...)
221 5cdb1798 2005-10-29 devnull {
222 5cdb1798 2005-10-29 devnull char buf[SIZE], *out;
223 5cdb1798 2005-10-29 devnull va_list arg;
224 5cdb1798 2005-10-29 devnull int n;
225 5cdb1798 2005-10-29 devnull
226 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
227 5cdb1798 2005-10-29 devnull out = vseprint(buf, buf+SIZE, fmt, arg);
228 5cdb1798 2005-10-29 devnull va_end(arg);
229 5cdb1798 2005-10-29 devnull n = (long)(out-buf);
230 5cdb1798 2005-10-29 devnull if(debug) {
231 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
232 5cdb1798 2005-10-29 devnull write(2, buf, n);
233 5cdb1798 2005-10-29 devnull }
234 5cdb1798 2005-10-29 devnull write(1, buf, n);
235 5cdb1798 2005-10-29 devnull return n;
236 5cdb1798 2005-10-29 devnull }
237 5cdb1798 2005-10-29 devnull
238 5cdb1798 2005-10-29 devnull void
239 5cdb1798 2005-10-29 devnull reset(void)
240 5cdb1798 2005-10-29 devnull {
241 5cdb1798 2005-10-29 devnull if(rejectcheck())
242 5cdb1798 2005-10-29 devnull return;
243 5cdb1798 2005-10-29 devnull listfree(&rcvers);
244 5cdb1798 2005-10-29 devnull listfree(&senders);
245 5cdb1798 2005-10-29 devnull if(filterstate != DIALUP){
246 5cdb1798 2005-10-29 devnull logged = 0;
247 5cdb1798 2005-10-29 devnull filterstate = ACCEPT;
248 5cdb1798 2005-10-29 devnull }
249 5cdb1798 2005-10-29 devnull reply("250 ok\r\n");
250 5cdb1798 2005-10-29 devnull }
251 5cdb1798 2005-10-29 devnull
252 5cdb1798 2005-10-29 devnull void
253 5cdb1798 2005-10-29 devnull sayhi(void)
254 5cdb1798 2005-10-29 devnull {
255 5cdb1798 2005-10-29 devnull reply("220 %s SMTP\r\n", dom);
256 5cdb1798 2005-10-29 devnull }
257 5cdb1798 2005-10-29 devnull
258 5cdb1798 2005-10-29 devnull void
259 5cdb1798 2005-10-29 devnull hello(String *himp, int extended)
260 5cdb1798 2005-10-29 devnull {
261 5cdb1798 2005-10-29 devnull char **mynames;
262 5cdb1798 2005-10-29 devnull
263 5cdb1798 2005-10-29 devnull him = s_to_c(himp);
264 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "%s from %s as %s", extended ? "ehlo" : "helo", nci->rsys, him);
265 5cdb1798 2005-10-29 devnull if(rejectcheck())
266 5cdb1798 2005-10-29 devnull return;
267 5cdb1798 2005-10-29 devnull
268 5cdb1798 2005-10-29 devnull if(strchr(him, '.') && nci && !trusted && fflag && strcmp(nci->rsys, nci->lsys) != 0){
269 5cdb1798 2005-10-29 devnull /*
270 5cdb1798 2005-10-29 devnull * We don't care if he lies about who he is, but it is
271 5cdb1798 2005-10-29 devnull * not okay to pretend to be us. Many viruses do this,
272 5cdb1798 2005-10-29 devnull * just parroting back what we say in the greeting.
273 5cdb1798 2005-10-29 devnull */
274 5cdb1798 2005-10-29 devnull if(strcmp(him, dom) == 0)
275 5cdb1798 2005-10-29 devnull goto Liarliar;
276 5cdb1798 2005-10-29 devnull for(mynames=sysnames_read(); mynames && *mynames; mynames++){
277 5cdb1798 2005-10-29 devnull if(cistrcmp(*mynames, him) == 0){
278 5cdb1798 2005-10-29 devnull Liarliar:
279 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "Hung up on %s; claimed to be %s",
280 5cdb1798 2005-10-29 devnull nci->rsys, him);
281 5cdb1798 2005-10-29 devnull reply("554 Liar!\r\n");
282 5cc53af9 2006-02-12 devnull threadexitsall("client pretended to be us");
283 5cdb1798 2005-10-29 devnull return;
284 5cdb1798 2005-10-29 devnull }
285 5cdb1798 2005-10-29 devnull }
286 5cdb1798 2005-10-29 devnull }
287 5cdb1798 2005-10-29 devnull /*
288 5cdb1798 2005-10-29 devnull * it is never acceptable to claim to be "localhost",
289 5cdb1798 2005-10-29 devnull * "localhost.localdomain" or "localhost.example.com"; only spammers
290 5cdb1798 2005-10-29 devnull * do this. it should be unacceptable to claim any string that doesn't
291 5cdb1798 2005-10-29 devnull * look like a domain name (e.g., has at least one dot in it), but
292 5cdb1798 2005-10-29 devnull * Microsoft mail software gets this wrong.
293 5cdb1798 2005-10-29 devnull */
294 5cdb1798 2005-10-29 devnull if (strcmp(him, "localhost") == 0 ||
295 5cdb1798 2005-10-29 devnull strcmp(him, "localhost.localdomain") == 0 ||
296 5cdb1798 2005-10-29 devnull strcmp(him, "localhost.example.com") == 0)
297 5cdb1798 2005-10-29 devnull goto Liarliar;
298 5cdb1798 2005-10-29 devnull if(strchr(him, '.') == 0 && nci != nil && strchr(nci->rsys, '.') != nil)
299 5cdb1798 2005-10-29 devnull him = nci->rsys;
300 5cdb1798 2005-10-29 devnull
301 5cdb1798 2005-10-29 devnull if(Dflag)
302 5cdb1798 2005-10-29 devnull sleep(15*1000);
303 5cdb1798 2005-10-29 devnull reply("250%c%s you are %s\r\n", extended ? '-' : ' ', dom, him);
304 5cdb1798 2005-10-29 devnull if (extended) {
305 5cdb1798 2005-10-29 devnull if(tlscert != nil)
306 5cdb1798 2005-10-29 devnull reply("250-STARTTLS\r\n");
307 5cdb1798 2005-10-29 devnull if (passwordinclear)
308 5cdb1798 2005-10-29 devnull reply("250 AUTH CRAM-MD5 PLAIN LOGIN\r\n");
309 5cdb1798 2005-10-29 devnull else
310 5cdb1798 2005-10-29 devnull reply("250 AUTH CRAM-MD5\r\n");
311 5cdb1798 2005-10-29 devnull }
312 5cdb1798 2005-10-29 devnull }
313 5cdb1798 2005-10-29 devnull
314 5cdb1798 2005-10-29 devnull void
315 5cdb1798 2005-10-29 devnull sender(String *path)
316 5cdb1798 2005-10-29 devnull {
317 5cdb1798 2005-10-29 devnull String *s;
318 5cdb1798 2005-10-29 devnull static char *lastsender;
319 5cdb1798 2005-10-29 devnull
320 5cdb1798 2005-10-29 devnull if(rejectcheck())
321 5cdb1798 2005-10-29 devnull return;
322 5cdb1798 2005-10-29 devnull if (authenticate && !authenticated) {
323 5cdb1798 2005-10-29 devnull rejectcount++;
324 5cdb1798 2005-10-29 devnull reply("530 Authentication required\r\n");
325 5cdb1798 2005-10-29 devnull return;
326 5cdb1798 2005-10-29 devnull }
327 5cdb1798 2005-10-29 devnull if(him == 0 || *him == 0){
328 5cdb1798 2005-10-29 devnull rejectcount++;
329 5cdb1798 2005-10-29 devnull reply("503 Start by saying HELO, please.\r\n", s_to_c(path));
330 5cdb1798 2005-10-29 devnull return;
331 5cdb1798 2005-10-29 devnull }
332 5cdb1798 2005-10-29 devnull
333 5cdb1798 2005-10-29 devnull /* don't add the domain onto black holes or we will loop */
334 5cdb1798 2005-10-29 devnull if(strchr(s_to_c(path), '!') == 0 && strcmp(s_to_c(path), "/dev/null") != 0){
335 5cdb1798 2005-10-29 devnull s = s_new();
336 5cdb1798 2005-10-29 devnull s_append(s, him);
337 5cdb1798 2005-10-29 devnull s_append(s, "!");
338 5cdb1798 2005-10-29 devnull s_append(s, s_to_c(path));
339 5cdb1798 2005-10-29 devnull s_terminate(s);
340 5cdb1798 2005-10-29 devnull s_free(path);
341 5cdb1798 2005-10-29 devnull path = s;
342 5cdb1798 2005-10-29 devnull }
343 5cdb1798 2005-10-29 devnull if(shellchars(s_to_c(path))){
344 5cdb1798 2005-10-29 devnull rejectcount++;
345 5cdb1798 2005-10-29 devnull reply("503 Bad character in sender address %s.\r\n", s_to_c(path));
346 5cdb1798 2005-10-29 devnull return;
347 5cdb1798 2005-10-29 devnull }
348 5cdb1798 2005-10-29 devnull
349 5cdb1798 2005-10-29 devnull /*
350 5cdb1798 2005-10-29 devnull * if the last sender address resulted in a rejection because the sending
351 5cdb1798 2005-10-29 devnull * domain didn't exist and this sender has the same domain, reject immediately.
352 5cdb1798 2005-10-29 devnull */
353 5cdb1798 2005-10-29 devnull if(lastsender){
354 5cdb1798 2005-10-29 devnull if (strncmp(lastsender, s_to_c(path), strlen(lastsender)) == 0){
355 5cdb1798 2005-10-29 devnull filterstate = REFUSED;
356 5cdb1798 2005-10-29 devnull rejectcount++;
357 5cdb1798 2005-10-29 devnull reply("554 Sender domain must exist: %s\r\n", s_to_c(path));
358 5cdb1798 2005-10-29 devnull return;
359 5cdb1798 2005-10-29 devnull }
360 5cdb1798 2005-10-29 devnull free(lastsender); /* different sender domain */
361 5cdb1798 2005-10-29 devnull lastsender = 0;
362 5cdb1798 2005-10-29 devnull }
363 5cdb1798 2005-10-29 devnull
364 5cdb1798 2005-10-29 devnull /*
365 5cdb1798 2005-10-29 devnull * see if this ip address, domain name, user name or account is blocked
366 5cdb1798 2005-10-29 devnull */
367 5cdb1798 2005-10-29 devnull filterstate = blocked(path);
368 5cdb1798 2005-10-29 devnull
369 5cdb1798 2005-10-29 devnull logged = 0;
370 5cdb1798 2005-10-29 devnull listadd(&senders, path);
371 5cdb1798 2005-10-29 devnull reply("250 sender is %s\r\n", s_to_c(path));
372 5cdb1798 2005-10-29 devnull }
373 5cdb1798 2005-10-29 devnull
374 5cdb1798 2005-10-29 devnull enum { Rcpt, Domain, Ntoks };
375 5cdb1798 2005-10-29 devnull
376 5cdb1798 2005-10-29 devnull typedef struct Sender Sender;
377 5cdb1798 2005-10-29 devnull struct Sender {
378 5cdb1798 2005-10-29 devnull Sender *next;
379 5cdb1798 2005-10-29 devnull char *rcpt;
380 5cdb1798 2005-10-29 devnull char *domain;
381 5cdb1798 2005-10-29 devnull };
382 5cdb1798 2005-10-29 devnull static Sender *sendlist, *sendlast;
383 5cdb1798 2005-10-29 devnull static uchar rsysip[IPaddrlen];
384 5cdb1798 2005-10-29 devnull
385 5cdb1798 2005-10-29 devnull static int
386 5cdb1798 2005-10-29 devnull rdsenders(void)
387 5cdb1798 2005-10-29 devnull {
388 5cdb1798 2005-10-29 devnull int lnlen, nf, ok = 1;
389 5cdb1798 2005-10-29 devnull char *line, *senderfile;
390 5cdb1798 2005-10-29 devnull char *toks[Ntoks];
391 5cdb1798 2005-10-29 devnull Biobuf *sf;
392 5cdb1798 2005-10-29 devnull Sender *snd;
393 5cdb1798 2005-10-29 devnull static int beenhere = 0;
394 5cdb1798 2005-10-29 devnull
395 5cdb1798 2005-10-29 devnull if (beenhere)
396 5cdb1798 2005-10-29 devnull return 1;
397 5cdb1798 2005-10-29 devnull beenhere = 1;
398 5cdb1798 2005-10-29 devnull
399 5cdb1798 2005-10-29 devnull fmtinstall('I', eipfmt);
400 5cdb1798 2005-10-29 devnull parseip(rsysip, nci->rsys);
401 5cdb1798 2005-10-29 devnull
402 5cdb1798 2005-10-29 devnull /*
403 5cdb1798 2005-10-29 devnull * we're sticking with a system-wide sender list because
404 5cdb1798 2005-10-29 devnull * per-user lists would require fully resolving recipient
405 5cdb1798 2005-10-29 devnull * addresses to determine which users they correspond to
406 5cdb1798 2005-10-29 devnull * (barring syntactic conventions).
407 5cdb1798 2005-10-29 devnull */
408 5cdb1798 2005-10-29 devnull senderfile = smprint("%s/senders", UPASLIB);
409 5cdb1798 2005-10-29 devnull sf = Bopen(senderfile, OREAD);
410 5cdb1798 2005-10-29 devnull free(senderfile);
411 5cdb1798 2005-10-29 devnull if (sf == nil)
412 5cdb1798 2005-10-29 devnull return 1;
413 5cdb1798 2005-10-29 devnull while ((line = Brdline(sf, '\n')) != nil) {
414 5cdb1798 2005-10-29 devnull if (line[0] == '#' || line[0] == '\n')
415 5cdb1798 2005-10-29 devnull continue;
416 5cdb1798 2005-10-29 devnull lnlen = Blinelen(sf);
417 5cdb1798 2005-10-29 devnull line[lnlen-1] = '\0'; /* clobber newline */
418 5cdb1798 2005-10-29 devnull nf = tokenize(line, toks, nelem(toks));
419 5cdb1798 2005-10-29 devnull if (nf != nelem(toks))
420 5cdb1798 2005-10-29 devnull continue; /* malformed line */
421 5cdb1798 2005-10-29 devnull
422 5cdb1798 2005-10-29 devnull snd = malloc(sizeof *snd);
423 5cdb1798 2005-10-29 devnull if (snd == nil)
424 5cdb1798 2005-10-29 devnull sysfatal("out of memory: %r");
425 5cdb1798 2005-10-29 devnull memset(snd, 0, sizeof *snd);
426 5cdb1798 2005-10-29 devnull snd->next = nil;
427 5cdb1798 2005-10-29 devnull
428 5cdb1798 2005-10-29 devnull if (sendlast == nil)
429 5cdb1798 2005-10-29 devnull sendlist = snd;
430 5cdb1798 2005-10-29 devnull else
431 5cdb1798 2005-10-29 devnull sendlast->next = snd;
432 5cdb1798 2005-10-29 devnull sendlast = snd;
433 5cdb1798 2005-10-29 devnull snd->rcpt = strdup(toks[Rcpt]);
434 5cdb1798 2005-10-29 devnull snd->domain = strdup(toks[Domain]);
435 5cdb1798 2005-10-29 devnull }
436 5cdb1798 2005-10-29 devnull Bterm(sf);
437 5cdb1798 2005-10-29 devnull return ok;
438 5cdb1798 2005-10-29 devnull }
439 5cdb1798 2005-10-29 devnull
440 5cdb1798 2005-10-29 devnull /*
441 5cdb1798 2005-10-29 devnull * read (recipient, sender's DNS) pairs from /mail/lib/senders.
442 5cdb1798 2005-10-29 devnull * Only allow mail to recipient from any of sender's IPs.
443 5cdb1798 2005-10-29 devnull * A recipient not mentioned in the file is always permitted.
444 5cdb1798 2005-10-29 devnull */
445 5cdb1798 2005-10-29 devnull static int
446 5cdb1798 2005-10-29 devnull senderok(char *rcpt)
447 5cdb1798 2005-10-29 devnull {
448 5cdb1798 2005-10-29 devnull int mentioned = 0, matched = 0;
449 5cdb1798 2005-10-29 devnull uchar dnsip[IPaddrlen];
450 5cdb1798 2005-10-29 devnull Sender *snd;
451 5cdb1798 2005-10-29 devnull Ndbtuple *nt, *next, *first;
452 5cdb1798 2005-10-29 devnull
453 5cdb1798 2005-10-29 devnull rdsenders();
454 5cdb1798 2005-10-29 devnull for (snd = sendlist; snd != nil; snd = snd->next) {
455 5cdb1798 2005-10-29 devnull if (strcmp(rcpt, snd->rcpt) != 0)
456 5cdb1798 2005-10-29 devnull continue;
457 5cdb1798 2005-10-29 devnull /*
458 5cdb1798 2005-10-29 devnull * see if this domain's ips match nci->rsys.
459 5cdb1798 2005-10-29 devnull * if not, perhaps a later entry's domain will.
460 5cdb1798 2005-10-29 devnull */
461 5cdb1798 2005-10-29 devnull mentioned = 1;
462 5cdb1798 2005-10-29 devnull if (parseip(dnsip, snd->domain) != -1 &&
463 5cdb1798 2005-10-29 devnull memcmp(rsysip, dnsip, IPaddrlen) == 0)
464 5cdb1798 2005-10-29 devnull return 1;
465 5cdb1798 2005-10-29 devnull /*
466 5cdb1798 2005-10-29 devnull * NB: nt->line links form a circular list(!).
467 5cdb1798 2005-10-29 devnull * we need to make one complete pass over it to free it all.
468 5cdb1798 2005-10-29 devnull */
469 5cdb1798 2005-10-29 devnull first = nt = dnsquery(nci->root, snd->domain, "ip");
470 5cdb1798 2005-10-29 devnull if (first == nil)
471 5cdb1798 2005-10-29 devnull continue;
472 5cdb1798 2005-10-29 devnull do {
473 5cdb1798 2005-10-29 devnull if (strcmp(nt->attr, "ip") == 0 &&
474 5cdb1798 2005-10-29 devnull parseip(dnsip, nt->val) != -1 &&
475 5cdb1798 2005-10-29 devnull memcmp(rsysip, dnsip, IPaddrlen) == 0)
476 5cdb1798 2005-10-29 devnull matched = 1;
477 5cdb1798 2005-10-29 devnull next = nt->line;
478 5cdb1798 2005-10-29 devnull free(nt);
479 5cdb1798 2005-10-29 devnull nt = next;
480 5cdb1798 2005-10-29 devnull } while (nt != first);
481 5cdb1798 2005-10-29 devnull }
482 5cdb1798 2005-10-29 devnull if (matched)
483 5cdb1798 2005-10-29 devnull return 1;
484 5cdb1798 2005-10-29 devnull else
485 5cdb1798 2005-10-29 devnull return !mentioned;
486 5cdb1798 2005-10-29 devnull }
487 5cdb1798 2005-10-29 devnull
488 5cdb1798 2005-10-29 devnull void
489 5cdb1798 2005-10-29 devnull receiver(String *path)
490 5cdb1798 2005-10-29 devnull {
491 5cdb1798 2005-10-29 devnull char *sender, *rcpt;
492 5cdb1798 2005-10-29 devnull
493 5cdb1798 2005-10-29 devnull if(rejectcheck())
494 5cdb1798 2005-10-29 devnull return;
495 5cdb1798 2005-10-29 devnull if(him == 0 || *him == 0){
496 5cdb1798 2005-10-29 devnull rejectcount++;
497 5cdb1798 2005-10-29 devnull reply("503 Start by saying HELO, please\r\n");
498 5cdb1798 2005-10-29 devnull return;
499 5cdb1798 2005-10-29 devnull }
500 5cdb1798 2005-10-29 devnull if(senders.last)
501 5cdb1798 2005-10-29 devnull sender = s_to_c(senders.last->p);
502 5cdb1798 2005-10-29 devnull else
503 5cdb1798 2005-10-29 devnull sender = "<unknown>";
504 5cdb1798 2005-10-29 devnull
505 5cdb1798 2005-10-29 devnull if(!recipok(s_to_c(path))){
506 5cdb1798 2005-10-29 devnull rejectcount++;
507 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "Disallowed %s (%s/%s) to blocked name %s",
508 5cdb1798 2005-10-29 devnull sender, him, nci->rsys, s_to_c(path));
509 5cdb1798 2005-10-29 devnull reply("550 %s ... user unknown\r\n", s_to_c(path));
510 5cdb1798 2005-10-29 devnull return;
511 5cdb1798 2005-10-29 devnull }
512 5cdb1798 2005-10-29 devnull rcpt = s_to_c(path);
513 5cdb1798 2005-10-29 devnull if (!senderok(rcpt)) {
514 5cdb1798 2005-10-29 devnull rejectcount++;
515 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "Disallowed sending IP of %s (%s/%s) to %s",
516 5cdb1798 2005-10-29 devnull sender, him, nci->rsys, rcpt);
517 5cdb1798 2005-10-29 devnull reply("550 %s ... sending system not allowed\r\n", rcpt);
518 5cdb1798 2005-10-29 devnull return;
519 5cdb1798 2005-10-29 devnull }
520 5cdb1798 2005-10-29 devnull
521 5cdb1798 2005-10-29 devnull logged = 0;
522 5cdb1798 2005-10-29 devnull /* forwarding() can modify 'path' on loopback request */
523 5cdb1798 2005-10-29 devnull if(filterstate == ACCEPT && (fflag && !authenticated) && forwarding(path)) {
524 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "Bad Forward %s (%s/%s) (%s)",
525 5cdb1798 2005-10-29 devnull s_to_c(senders.last->p), him, nci->rsys, s_to_c(path));
526 5cdb1798 2005-10-29 devnull rejectcount++;
527 5cdb1798 2005-10-29 devnull reply("550 we don't relay. send to your-path@[] for loopback.\r\n");
528 5cdb1798 2005-10-29 devnull return;
529 5cdb1798 2005-10-29 devnull }
530 5cdb1798 2005-10-29 devnull listadd(&rcvers, path);
531 5cdb1798 2005-10-29 devnull reply("250 receiver is %s\r\n", s_to_c(path));
532 5cdb1798 2005-10-29 devnull }
533 5cdb1798 2005-10-29 devnull
534 5cdb1798 2005-10-29 devnull void
535 5cdb1798 2005-10-29 devnull quit(void)
536 5cdb1798 2005-10-29 devnull {
537 5cdb1798 2005-10-29 devnull reply("221 Successful termination\r\n");
538 5cdb1798 2005-10-29 devnull close(0);
539 5cc53af9 2006-02-12 devnull threadexitsall(0);
540 5cdb1798 2005-10-29 devnull }
541 5cdb1798 2005-10-29 devnull
542 5cdb1798 2005-10-29 devnull void
543 5cdb1798 2005-10-29 devnull turn(void)
544 5cdb1798 2005-10-29 devnull {
545 5cdb1798 2005-10-29 devnull if(rejectcheck())
546 5cdb1798 2005-10-29 devnull return;
547 5cdb1798 2005-10-29 devnull reply("502 TURN unimplemented\r\n");
548 5cdb1798 2005-10-29 devnull }
549 5cdb1798 2005-10-29 devnull
550 5cdb1798 2005-10-29 devnull void
551 5cdb1798 2005-10-29 devnull noop(void)
552 5cdb1798 2005-10-29 devnull {
553 5cdb1798 2005-10-29 devnull if(rejectcheck())
554 5cdb1798 2005-10-29 devnull return;
555 5cdb1798 2005-10-29 devnull reply("250 Stop wasting my time!\r\n");
556 5cdb1798 2005-10-29 devnull }
557 5cdb1798 2005-10-29 devnull
558 5cdb1798 2005-10-29 devnull void
559 5cdb1798 2005-10-29 devnull help(String *cmd)
560 5cdb1798 2005-10-29 devnull {
561 5cdb1798 2005-10-29 devnull if(rejectcheck())
562 5cdb1798 2005-10-29 devnull return;
563 5cdb1798 2005-10-29 devnull if(cmd)
564 5cdb1798 2005-10-29 devnull s_free(cmd);
565 5cdb1798 2005-10-29 devnull reply("250 Read rfc821 and stop wasting my time\r\n");
566 5cdb1798 2005-10-29 devnull }
567 5cdb1798 2005-10-29 devnull
568 5cdb1798 2005-10-29 devnull void
569 5cdb1798 2005-10-29 devnull verify(String *path)
570 5cdb1798 2005-10-29 devnull {
571 5cdb1798 2005-10-29 devnull char *p, *q;
572 5cdb1798 2005-10-29 devnull char *av[4];
573 5cdb1798 2005-10-29 devnull
574 5cdb1798 2005-10-29 devnull if(rejectcheck())
575 5cdb1798 2005-10-29 devnull return;
576 5cdb1798 2005-10-29 devnull if(shellchars(s_to_c(path))){
577 5cdb1798 2005-10-29 devnull reply("503 Bad character in address %s.\r\n", s_to_c(path));
578 5cdb1798 2005-10-29 devnull return;
579 5cdb1798 2005-10-29 devnull }
580 5cdb1798 2005-10-29 devnull av[0] = s_to_c(mailer);
581 5cdb1798 2005-10-29 devnull av[1] = "-x";
582 5cdb1798 2005-10-29 devnull av[2] = s_to_c(path);
583 5cdb1798 2005-10-29 devnull av[3] = 0;
584 5cdb1798 2005-10-29 devnull
585 5cdb1798 2005-10-29 devnull pp = noshell_proc_start(av, (stream *)0, outstream(), (stream *)0, 1, 0);
586 5cdb1798 2005-10-29 devnull if (pp == 0) {
587 5cdb1798 2005-10-29 devnull reply("450 We're busy right now, try later\r\n");
588 5cdb1798 2005-10-29 devnull return;
589 5cdb1798 2005-10-29 devnull }
590 5cdb1798 2005-10-29 devnull
591 5cdb1798 2005-10-29 devnull p = Brdline(pp->std[1]->fp, '\n');
592 5cdb1798 2005-10-29 devnull if(p == 0){
593 5cdb1798 2005-10-29 devnull reply("550 String does not match anything.\r\n");
594 5cdb1798 2005-10-29 devnull } else {
595 5cdb1798 2005-10-29 devnull p[Blinelen(pp->std[1]->fp)-1] = 0;
596 5cdb1798 2005-10-29 devnull if(strchr(p, ':'))
597 5cdb1798 2005-10-29 devnull reply("550 String does not match anything.\r\n");
598 5cdb1798 2005-10-29 devnull else{
599 5cdb1798 2005-10-29 devnull q = strrchr(p, '!');
600 5cdb1798 2005-10-29 devnull if(q)
601 5cdb1798 2005-10-29 devnull p = q+1;
602 5cdb1798 2005-10-29 devnull reply("250 %s <%s@%s>\r\n", s_to_c(path), p, dom);
603 5cdb1798 2005-10-29 devnull }
604 5cdb1798 2005-10-29 devnull }
605 5cdb1798 2005-10-29 devnull proc_wait(pp);
606 5cdb1798 2005-10-29 devnull proc_free(pp);
607 5cdb1798 2005-10-29 devnull pp = 0;
608 5cdb1798 2005-10-29 devnull }
609 5cdb1798 2005-10-29 devnull
610 5cdb1798 2005-10-29 devnull /*
611 5cdb1798 2005-10-29 devnull * get a line that ends in crnl or cr, turn terminating crnl into a nl
612 5cdb1798 2005-10-29 devnull *
613 5cdb1798 2005-10-29 devnull * return 0 on EOF
614 5cdb1798 2005-10-29 devnull */
615 5cdb1798 2005-10-29 devnull static int
616 5cdb1798 2005-10-29 devnull getcrnl(String *s, Biobuf *fp)
617 5cdb1798 2005-10-29 devnull {
618 5cdb1798 2005-10-29 devnull int c;
619 5cdb1798 2005-10-29 devnull
620 5cdb1798 2005-10-29 devnull for(;;){
621 5cdb1798 2005-10-29 devnull c = Bgetc(fp);
622 5cdb1798 2005-10-29 devnull if(debug) {
623 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
624 5cdb1798 2005-10-29 devnull fprint(2, "%c", c);
625 5cdb1798 2005-10-29 devnull }
626 5cdb1798 2005-10-29 devnull switch(c){
627 5cdb1798 2005-10-29 devnull case -1:
628 5cdb1798 2005-10-29 devnull goto out;
629 5cdb1798 2005-10-29 devnull case '\r':
630 5cdb1798 2005-10-29 devnull c = Bgetc(fp);
631 5cdb1798 2005-10-29 devnull if(c == '\n'){
632 5cdb1798 2005-10-29 devnull if(debug) {
633 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
634 5cdb1798 2005-10-29 devnull fprint(2, "%c", c);
635 5cdb1798 2005-10-29 devnull }
636 5cdb1798 2005-10-29 devnull s_putc(s, '\n');
637 5cdb1798 2005-10-29 devnull goto out;
638 5cdb1798 2005-10-29 devnull }
639 5cdb1798 2005-10-29 devnull Bungetc(fp);
640 5cdb1798 2005-10-29 devnull s_putc(s, '\r');
641 5cdb1798 2005-10-29 devnull break;
642 5cdb1798 2005-10-29 devnull case '\n':
643 5cdb1798 2005-10-29 devnull s_putc(s, c);
644 5cdb1798 2005-10-29 devnull goto out;
645 5cdb1798 2005-10-29 devnull default:
646 5cdb1798 2005-10-29 devnull s_putc(s, c);
647 5cdb1798 2005-10-29 devnull break;
648 5cdb1798 2005-10-29 devnull }
649 5cdb1798 2005-10-29 devnull }
650 5cdb1798 2005-10-29 devnull out:
651 5cdb1798 2005-10-29 devnull s_terminate(s);
652 5cdb1798 2005-10-29 devnull return s_len(s);
653 5cdb1798 2005-10-29 devnull }
654 5cdb1798 2005-10-29 devnull
655 5cdb1798 2005-10-29 devnull void
656 5cdb1798 2005-10-29 devnull logcall(int nbytes)
657 5cdb1798 2005-10-29 devnull {
658 5cdb1798 2005-10-29 devnull Link *l;
659 5cdb1798 2005-10-29 devnull String *to, *from;
660 5cdb1798 2005-10-29 devnull
661 5cdb1798 2005-10-29 devnull to = s_new();
662 5cdb1798 2005-10-29 devnull from = s_new();
663 5cdb1798 2005-10-29 devnull for(l = senders.first; l; l = l->next){
664 5cdb1798 2005-10-29 devnull if(l != senders.first)
665 5cdb1798 2005-10-29 devnull s_append(from, ", ");
666 5cdb1798 2005-10-29 devnull s_append(from, s_to_c(l->p));
667 5cdb1798 2005-10-29 devnull }
668 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next){
669 5cdb1798 2005-10-29 devnull if(l != rcvers.first)
670 5cdb1798 2005-10-29 devnull s_append(to, ", ");
671 5cdb1798 2005-10-29 devnull s_append(to, s_to_c(l->p));
672 5cdb1798 2005-10-29 devnull }
673 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "[%s/%s] %s sent %d bytes to %s", him, nci->rsys,
674 5cdb1798 2005-10-29 devnull s_to_c(from), nbytes, s_to_c(to));
675 5cdb1798 2005-10-29 devnull s_free(to);
676 5cdb1798 2005-10-29 devnull s_free(from);
677 5cdb1798 2005-10-29 devnull }
678 5cdb1798 2005-10-29 devnull
679 5cdb1798 2005-10-29 devnull static void
680 5cdb1798 2005-10-29 devnull logmsg(char *action)
681 5cdb1798 2005-10-29 devnull {
682 5cdb1798 2005-10-29 devnull Link *l;
683 5cdb1798 2005-10-29 devnull
684 5cdb1798 2005-10-29 devnull if(logged)
685 5cdb1798 2005-10-29 devnull return;
686 5cdb1798 2005-10-29 devnull
687 5cdb1798 2005-10-29 devnull logged = 1;
688 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next)
689 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "%s %s (%s/%s) (%s)", action,
690 5cdb1798 2005-10-29 devnull s_to_c(senders.last->p), him, nci->rsys, s_to_c(l->p));
691 5cdb1798 2005-10-29 devnull }
692 5cdb1798 2005-10-29 devnull
693 5cdb1798 2005-10-29 devnull static int
694 5cdb1798 2005-10-29 devnull optoutall(int filterstate)
695 5cdb1798 2005-10-29 devnull {
696 5cdb1798 2005-10-29 devnull Link *l;
697 5cdb1798 2005-10-29 devnull
698 5cdb1798 2005-10-29 devnull switch(filterstate){
699 5cdb1798 2005-10-29 devnull case ACCEPT:
700 5cdb1798 2005-10-29 devnull case TRUSTED:
701 5cdb1798 2005-10-29 devnull return filterstate;
702 5cdb1798 2005-10-29 devnull }
703 5cdb1798 2005-10-29 devnull
704 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next)
705 5cdb1798 2005-10-29 devnull if(!optoutofspamfilter(s_to_c(l->p)))
706 5cdb1798 2005-10-29 devnull return filterstate;
707 5cdb1798 2005-10-29 devnull
708 5cdb1798 2005-10-29 devnull return ACCEPT;
709 5cdb1798 2005-10-29 devnull }
710 5cdb1798 2005-10-29 devnull
711 5cdb1798 2005-10-29 devnull String*
712 5cdb1798 2005-10-29 devnull startcmd(void)
713 5cdb1798 2005-10-29 devnull {
714 5cdb1798 2005-10-29 devnull int n;
715 5cdb1798 2005-10-29 devnull Link *l;
716 5cdb1798 2005-10-29 devnull char **av;
717 5cdb1798 2005-10-29 devnull String *cmd;
718 5cdb1798 2005-10-29 devnull char *filename;
719 5cdb1798 2005-10-29 devnull
720 5cdb1798 2005-10-29 devnull /*
721 5cdb1798 2005-10-29 devnull * ignore the filterstate if the all the receivers prefer it.
722 5cdb1798 2005-10-29 devnull */
723 5cdb1798 2005-10-29 devnull filterstate = optoutall(filterstate);
724 5cdb1798 2005-10-29 devnull
725 5cdb1798 2005-10-29 devnull switch (filterstate){
726 5cdb1798 2005-10-29 devnull case BLOCKED:
727 5cdb1798 2005-10-29 devnull case DELAY:
728 5cdb1798 2005-10-29 devnull rejectcount++;
729 5cdb1798 2005-10-29 devnull logmsg("Blocked");
730 5cdb1798 2005-10-29 devnull filename = dumpfile(s_to_c(senders.last->p));
731 5cdb1798 2005-10-29 devnull cmd = s_new();
732 5cdb1798 2005-10-29 devnull s_append(cmd, "cat > ");
733 5cdb1798 2005-10-29 devnull s_append(cmd, filename);
734 5cdb1798 2005-10-29 devnull pp = proc_start(s_to_c(cmd), instream(), 0, outstream(), 0, 0);
735 5cdb1798 2005-10-29 devnull break;
736 5cdb1798 2005-10-29 devnull case DIALUP:
737 5cdb1798 2005-10-29 devnull logmsg("Dialup");
738 5cdb1798 2005-10-29 devnull rejectcount++;
739 5cdb1798 2005-10-29 devnull reply("554 We don't accept mail from dial-up ports.\r\n");
740 5cdb1798 2005-10-29 devnull /*
741 5cdb1798 2005-10-29 devnull * we could exit here, because we're never going to accept mail from this
742 5cdb1798 2005-10-29 devnull * ip address, but it's unclear that RFC821 allows that. Instead we set
743 5cdb1798 2005-10-29 devnull * the hardreject flag and go stupid.
744 5cdb1798 2005-10-29 devnull */
745 5cdb1798 2005-10-29 devnull hardreject = 1;
746 5cdb1798 2005-10-29 devnull return 0;
747 5cdb1798 2005-10-29 devnull case DENIED:
748 5cdb1798 2005-10-29 devnull logmsg("Denied");
749 5cdb1798 2005-10-29 devnull rejectcount++;
750 5cdb1798 2005-10-29 devnull reply("554-We don't accept mail from %s.\r\n", s_to_c(senders.last->p));
751 5cdb1798 2005-10-29 devnull reply("554 Contact postmaster@%s for more information.\r\n", dom);
752 5cdb1798 2005-10-29 devnull return 0;
753 5cdb1798 2005-10-29 devnull case REFUSED:
754 5cdb1798 2005-10-29 devnull logmsg("Refused");
755 5cdb1798 2005-10-29 devnull rejectcount++;
756 5cdb1798 2005-10-29 devnull reply("554 Sender domain must exist: %s\r\n", s_to_c(senders.last->p));
757 5cdb1798 2005-10-29 devnull return 0;
758 5cdb1798 2005-10-29 devnull default:
759 5cdb1798 2005-10-29 devnull case NONE:
760 5cdb1798 2005-10-29 devnull logmsg("Confused");
761 5cdb1798 2005-10-29 devnull rejectcount++;
762 5cdb1798 2005-10-29 devnull reply("554-We have had an internal mailer error classifying your message.\r\n");
763 5cdb1798 2005-10-29 devnull reply("554-Filterstate is %d\r\n", filterstate);
764 5cdb1798 2005-10-29 devnull reply("554 Contact postmaster@%s for more information.\r\n", dom);
765 5cdb1798 2005-10-29 devnull return 0;
766 5cdb1798 2005-10-29 devnull case ACCEPT:
767 5cdb1798 2005-10-29 devnull case TRUSTED:
768 5cdb1798 2005-10-29 devnull /*
769 5cdb1798 2005-10-29 devnull * now that all other filters have been passed,
770 5cdb1798 2005-10-29 devnull * do grey-list processing.
771 5cdb1798 2005-10-29 devnull */
772 5cdb1798 2005-10-29 devnull if(gflag)
773 5cdb1798 2005-10-29 devnull vfysenderhostok();
774 5cdb1798 2005-10-29 devnull
775 5cdb1798 2005-10-29 devnull /*
776 5cdb1798 2005-10-29 devnull * set up mail command
777 5cdb1798 2005-10-29 devnull */
778 5cdb1798 2005-10-29 devnull cmd = s_clone(mailer);
779 5cdb1798 2005-10-29 devnull n = 3;
780 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next)
781 5cdb1798 2005-10-29 devnull n++;
782 5cdb1798 2005-10-29 devnull av = malloc(n*sizeof(char*));
783 5cdb1798 2005-10-29 devnull if(av == nil){
784 5cdb1798 2005-10-29 devnull reply("450 We're busy right now, try later\n");
785 5cdb1798 2005-10-29 devnull s_free(cmd);
786 5cdb1798 2005-10-29 devnull return 0;
787 5cdb1798 2005-10-29 devnull }
788 5cdb1798 2005-10-29 devnull
789 5cdb1798 2005-10-29 devnull n = 0;
790 5cdb1798 2005-10-29 devnull av[n++] = s_to_c(cmd);
791 5cdb1798 2005-10-29 devnull av[n++] = "-r";
792 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next)
793 5cdb1798 2005-10-29 devnull av[n++] = s_to_c(l->p);
794 5cdb1798 2005-10-29 devnull av[n] = 0;
795 5cdb1798 2005-10-29 devnull /*
796 5cdb1798 2005-10-29 devnull * start mail process
797 5cdb1798 2005-10-29 devnull */
798 5cdb1798 2005-10-29 devnull pp = noshell_proc_start(av, instream(), outstream(), outstream(), 0, 0);
799 5cdb1798 2005-10-29 devnull free(av);
800 5cdb1798 2005-10-29 devnull break;
801 5cdb1798 2005-10-29 devnull }
802 5cdb1798 2005-10-29 devnull if(pp == 0) {
803 5cdb1798 2005-10-29 devnull reply("450 We're busy right now, try later\n");
804 5cdb1798 2005-10-29 devnull s_free(cmd);
805 5cdb1798 2005-10-29 devnull return 0;
806 5cdb1798 2005-10-29 devnull }
807 5cdb1798 2005-10-29 devnull return cmd;
808 5cdb1798 2005-10-29 devnull }
809 5cdb1798 2005-10-29 devnull
810 5cdb1798 2005-10-29 devnull /*
811 5cdb1798 2005-10-29 devnull * print out a header line, expanding any domainless addresses into
812 5cdb1798 2005-10-29 devnull * address@him
813 5cdb1798 2005-10-29 devnull */
814 5cdb1798 2005-10-29 devnull char*
815 5cdb1798 2005-10-29 devnull bprintnode(Biobuf *b, Node *p)
816 5cdb1798 2005-10-29 devnull {
817 5cdb1798 2005-10-29 devnull if(p->s){
818 5cdb1798 2005-10-29 devnull if(p->addr && strchr(s_to_c(p->s), '@') == nil){
819 5cdb1798 2005-10-29 devnull if(Bprint(b, "%s@%s", s_to_c(p->s), him) < 0)
820 5cdb1798 2005-10-29 devnull return nil;
821 5cdb1798 2005-10-29 devnull } else {
822 5cdb1798 2005-10-29 devnull if(Bwrite(b, s_to_c(p->s), s_len(p->s)) < 0)
823 5cdb1798 2005-10-29 devnull return nil;
824 5cdb1798 2005-10-29 devnull }
825 5cdb1798 2005-10-29 devnull }else{
826 5cdb1798 2005-10-29 devnull if(Bputc(b, p->c) < 0)
827 5cdb1798 2005-10-29 devnull return nil;
828 5cdb1798 2005-10-29 devnull }
829 5cdb1798 2005-10-29 devnull if(p->white)
830 5cdb1798 2005-10-29 devnull if(Bwrite(b, s_to_c(p->white), s_len(p->white)) < 0)
831 5cdb1798 2005-10-29 devnull return nil;
832 5cdb1798 2005-10-29 devnull return p->end+1;
833 5cdb1798 2005-10-29 devnull }
834 5cdb1798 2005-10-29 devnull
835 5cdb1798 2005-10-29 devnull static String*
836 5cdb1798 2005-10-29 devnull getaddr(Node *p)
837 5cdb1798 2005-10-29 devnull {
838 5cdb1798 2005-10-29 devnull for(; p; p = p->next)
839 5cdb1798 2005-10-29 devnull if(p->s && p->addr)
840 5cdb1798 2005-10-29 devnull return p->s;
841 5cdb1798 2005-10-29 devnull return nil;
842 5cdb1798 2005-10-29 devnull }
843 5cdb1798 2005-10-29 devnull
844 5cdb1798 2005-10-29 devnull /*
845 5cdb1798 2005-10-29 devnull * add waring headers of the form
846 5cdb1798 2005-10-29 devnull * X-warning: <reason>
847 5cdb1798 2005-10-29 devnull * for any headers that looked like they might be forged.
848 5cdb1798 2005-10-29 devnull *
849 5cdb1798 2005-10-29 devnull * return byte count of new headers
850 5cdb1798 2005-10-29 devnull */
851 5cdb1798 2005-10-29 devnull static int
852 5cdb1798 2005-10-29 devnull forgedheaderwarnings(void)
853 5cdb1798 2005-10-29 devnull {
854 5cdb1798 2005-10-29 devnull int nbytes;
855 5cdb1798 2005-10-29 devnull Field *f;
856 5cdb1798 2005-10-29 devnull
857 5cdb1798 2005-10-29 devnull nbytes = 0;
858 5cdb1798 2005-10-29 devnull
859 5cdb1798 2005-10-29 devnull /* warn about envelope sender */
860 5cdb1798 2005-10-29 devnull if(strcmp(s_to_c(senders.last->p), "/dev/null") != 0 && masquerade(senders.last->p, nil))
861 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect envelope domain\n");
862 5cdb1798 2005-10-29 devnull
863 5cdb1798 2005-10-29 devnull /*
864 5cdb1798 2005-10-29 devnull * check Sender: field. If it's OK, ignore the others because this is an
865 5cdb1798 2005-10-29 devnull * exploded mailing list.
866 5cdb1798 2005-10-29 devnull */
867 5cdb1798 2005-10-29 devnull for(f = firstfield; f; f = f->next){
868 5cdb1798 2005-10-29 devnull if(f->node->c == SENDER){
869 5cdb1798 2005-10-29 devnull if(masquerade(getaddr(f->node), him))
870 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect Sender: domain\n");
871 5cdb1798 2005-10-29 devnull else
872 5cdb1798 2005-10-29 devnull return nbytes;
873 5cdb1798 2005-10-29 devnull }
874 5cdb1798 2005-10-29 devnull }
875 5cdb1798 2005-10-29 devnull
876 5cdb1798 2005-10-29 devnull /* check From: */
877 5cdb1798 2005-10-29 devnull for(f = firstfield; f; f = f->next){
878 5cdb1798 2005-10-29 devnull if(f->node->c == FROM && masquerade(getaddr(f->node), him))
879 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect From: domain\n");
880 5cdb1798 2005-10-29 devnull }
881 5cdb1798 2005-10-29 devnull return nbytes;
882 5cdb1798 2005-10-29 devnull }
883 5cdb1798 2005-10-29 devnull
884 5cdb1798 2005-10-29 devnull /*
885 5cdb1798 2005-10-29 devnull * pipe message to mailer with the following transformations:
886 5cdb1798 2005-10-29 devnull * - change \r\n into \n.
887 5cdb1798 2005-10-29 devnull * - add sender's domain to any addrs with no domain
888 5cdb1798 2005-10-29 devnull * - add a From: if none of From:, Sender:, or Replyto: exists
889 5cdb1798 2005-10-29 devnull * - add a Received: line
890 5cdb1798 2005-10-29 devnull */
891 5cdb1798 2005-10-29 devnull int
892 5cdb1798 2005-10-29 devnull pipemsg(int *byteswritten)
893 5cdb1798 2005-10-29 devnull {
894 5cdb1798 2005-10-29 devnull int status;
895 5cdb1798 2005-10-29 devnull char *cp;
896 5cdb1798 2005-10-29 devnull String *line;
897 5cdb1798 2005-10-29 devnull String *hdr;
898 5cdb1798 2005-10-29 devnull int n, nbytes;
899 5cdb1798 2005-10-29 devnull int sawdot;
900 5cdb1798 2005-10-29 devnull Field *f;
901 5cdb1798 2005-10-29 devnull Node *p;
902 5cdb1798 2005-10-29 devnull Link *l;
903 5cdb1798 2005-10-29 devnull
904 5cdb1798 2005-10-29 devnull pipesig(&status); /* set status to 1 on write to closed pipe */
905 5cdb1798 2005-10-29 devnull sawdot = 0;
906 5cdb1798 2005-10-29 devnull status = 0;
907 5cdb1798 2005-10-29 devnull
908 5cdb1798 2005-10-29 devnull /*
909 5cdb1798 2005-10-29 devnull * add a 'From ' line as envelope
910 5cdb1798 2005-10-29 devnull */
911 5cdb1798 2005-10-29 devnull nbytes = 0;
912 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
913 5cdb1798 2005-10-29 devnull s_to_c(senders.first->p), thedate());
914 5cdb1798 2005-10-29 devnull
915 5cdb1798 2005-10-29 devnull /*
916 5cdb1798 2005-10-29 devnull * add our own Received: stamp
917 5cdb1798 2005-10-29 devnull */
918 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
919 5cdb1798 2005-10-29 devnull if(nci->rsys)
920 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
921 5cdb1798 2005-10-29 devnull nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());
922 5cdb1798 2005-10-29 devnull
923 5cdb1798 2005-10-29 devnull /*
924 5cdb1798 2005-10-29 devnull * read first 16k obeying '.' escape. we're assuming
925 5cdb1798 2005-10-29 devnull * the header will all be there.
926 5cdb1798 2005-10-29 devnull */
927 5cdb1798 2005-10-29 devnull line = s_new();
928 5cdb1798 2005-10-29 devnull hdr = s_new();
929 5cdb1798 2005-10-29 devnull while(sawdot == 0 && s_len(hdr) < 16*1024){
930 5cdb1798 2005-10-29 devnull n = getcrnl(s_reset(line), &bin);
931 5cdb1798 2005-10-29 devnull
932 5cdb1798 2005-10-29 devnull /* eof or error ends the message */
933 5cdb1798 2005-10-29 devnull if(n <= 0)
934 5cdb1798 2005-10-29 devnull break;
935 5cdb1798 2005-10-29 devnull
936 5cdb1798 2005-10-29 devnull /* a line with only a '.' ends the message */
937 5cdb1798 2005-10-29 devnull cp = s_to_c(line);
938 5cdb1798 2005-10-29 devnull if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
939 5cdb1798 2005-10-29 devnull sawdot = 1;
940 5cdb1798 2005-10-29 devnull break;
941 5cdb1798 2005-10-29 devnull }
942 5cdb1798 2005-10-29 devnull
943 5cdb1798 2005-10-29 devnull s_append(hdr, *cp == '.' ? cp+1 : cp);
944 5cdb1798 2005-10-29 devnull }
945 5cdb1798 2005-10-29 devnull
946 5cdb1798 2005-10-29 devnull /*
947 5cdb1798 2005-10-29 devnull * parse header
948 5cdb1798 2005-10-29 devnull */
949 5cdb1798 2005-10-29 devnull yyinit(s_to_c(hdr), s_len(hdr));
950 5cdb1798 2005-10-29 devnull yyparse();
951 5cdb1798 2005-10-29 devnull
952 5cdb1798 2005-10-29 devnull /*
953 5cdb1798 2005-10-29 devnull * Look for masquerades. Let Sender: trump From: to allow mailing list
954 5cdb1798 2005-10-29 devnull * forwarded messages.
955 5cdb1798 2005-10-29 devnull */
956 5cdb1798 2005-10-29 devnull if(fflag)
957 5cdb1798 2005-10-29 devnull nbytes += forgedheaderwarnings();
958 5cdb1798 2005-10-29 devnull
959 5cdb1798 2005-10-29 devnull /*
960 5cdb1798 2005-10-29 devnull * add an orginator and/or destination if either is missing
961 5cdb1798 2005-10-29 devnull */
962 5cdb1798 2005-10-29 devnull if(originator == 0){
963 5cdb1798 2005-10-29 devnull if(senders.last == nil)
964 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, "From: /dev/null@%s\n", him);
965 5cdb1798 2005-10-29 devnull else
966 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, "From: %s\n", s_to_c(senders.last->p));
967 5cdb1798 2005-10-29 devnull }
968 5cdb1798 2005-10-29 devnull if(destination == 0){
969 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, "To: ");
970 5cdb1798 2005-10-29 devnull for(l = rcvers.first; l; l = l->next){
971 5cdb1798 2005-10-29 devnull if(l != rcvers.first)
972 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, ", ");
973 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, "%s", s_to_c(l->p));
974 5cdb1798 2005-10-29 devnull }
975 5cdb1798 2005-10-29 devnull Bprint(pp->std[0]->fp, "\n");
976 5cdb1798 2005-10-29 devnull }
977 5cdb1798 2005-10-29 devnull
978 5cdb1798 2005-10-29 devnull /*
979 5cdb1798 2005-10-29 devnull * add sender's domain to any domainless addresses
980 5cdb1798 2005-10-29 devnull * (to avoid forging local addresses)
981 5cdb1798 2005-10-29 devnull */
982 5cdb1798 2005-10-29 devnull cp = s_to_c(hdr);
983 5cdb1798 2005-10-29 devnull for(f = firstfield; cp != nil && f; f = f->next){
984 5cdb1798 2005-10-29 devnull for(p = f->node; cp != 0 && p; p = p->next)
985 5cdb1798 2005-10-29 devnull cp = bprintnode(pp->std[0]->fp, p);
986 5cdb1798 2005-10-29 devnull if(status == 0 && Bprint(pp->std[0]->fp, "\n") < 0){
987 5cdb1798 2005-10-29 devnull piperror = "write error";
988 5cdb1798 2005-10-29 devnull status = 1;
989 5cdb1798 2005-10-29 devnull }
990 5cdb1798 2005-10-29 devnull }
991 5cdb1798 2005-10-29 devnull if(cp == nil){
992 5cdb1798 2005-10-29 devnull piperror = "sender domain";
993 5cdb1798 2005-10-29 devnull status = 1;
994 5cdb1798 2005-10-29 devnull }
995 5cdb1798 2005-10-29 devnull
996 5cdb1798 2005-10-29 devnull /* write anything we read following the header */
997 5cdb1798 2005-10-29 devnull if(status == 0 && Bwrite(pp->std[0]->fp, cp, s_to_c(hdr) + s_len(hdr) - cp) < 0){
998 5cdb1798 2005-10-29 devnull piperror = "write error 2";
999 5cdb1798 2005-10-29 devnull status = 1;
1000 5cdb1798 2005-10-29 devnull }
1001 5cdb1798 2005-10-29 devnull s_free(hdr);
1002 5cdb1798 2005-10-29 devnull
1003 5cdb1798 2005-10-29 devnull /*
1004 5cdb1798 2005-10-29 devnull * pass rest of message to mailer. take care of '.'
1005 5cdb1798 2005-10-29 devnull * escapes.
1006 5cdb1798 2005-10-29 devnull */
1007 5cdb1798 2005-10-29 devnull while(sawdot == 0){
1008 5cdb1798 2005-10-29 devnull n = getcrnl(s_reset(line), &bin);
1009 5cdb1798 2005-10-29 devnull
1010 5cdb1798 2005-10-29 devnull /* eof or error ends the message */
1011 5cdb1798 2005-10-29 devnull if(n <= 0)
1012 5cdb1798 2005-10-29 devnull break;
1013 5cdb1798 2005-10-29 devnull
1014 5cdb1798 2005-10-29 devnull /* a line with only a '.' ends the message */
1015 5cdb1798 2005-10-29 devnull cp = s_to_c(line);
1016 5cdb1798 2005-10-29 devnull if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
1017 5cdb1798 2005-10-29 devnull sawdot = 1;
1018 5cdb1798 2005-10-29 devnull break;
1019 5cdb1798 2005-10-29 devnull }
1020 5cdb1798 2005-10-29 devnull nbytes += n;
1021 5cdb1798 2005-10-29 devnull if(status == 0 && Bwrite(pp->std[0]->fp, *cp == '.' ? cp+1 : cp, n) < 0){
1022 5cdb1798 2005-10-29 devnull piperror = "write error 3";
1023 5cdb1798 2005-10-29 devnull status = 1;
1024 5cdb1798 2005-10-29 devnull }
1025 5cdb1798 2005-10-29 devnull }
1026 5cdb1798 2005-10-29 devnull s_free(line);
1027 5cdb1798 2005-10-29 devnull if(sawdot == 0){
1028 5cdb1798 2005-10-29 devnull /* message did not terminate normally */
1029 5cdb1798 2005-10-29 devnull snprint(pipbuf, sizeof pipbuf, "network eof: %r");
1030 5cdb1798 2005-10-29 devnull piperror = pipbuf;
1031 5cdb1798 2005-10-29 devnull syskillpg(pp->pid);
1032 5cdb1798 2005-10-29 devnull status = 1;
1033 5cdb1798 2005-10-29 devnull }
1034 5cdb1798 2005-10-29 devnull
1035 5cdb1798 2005-10-29 devnull if(status == 0 && Bflush(pp->std[0]->fp) < 0){
1036 5cdb1798 2005-10-29 devnull piperror = "write error 4";
1037 5cdb1798 2005-10-29 devnull status = 1;
1038 5cdb1798 2005-10-29 devnull }
1039 5cdb1798 2005-10-29 devnull stream_free(pp->std[0]);
1040 5cdb1798 2005-10-29 devnull pp->std[0] = 0;
1041 5cdb1798 2005-10-29 devnull *byteswritten = nbytes;
1042 5cdb1798 2005-10-29 devnull pipesigoff();
1043 5cdb1798 2005-10-29 devnull if(status && !piperror)
1044 5cdb1798 2005-10-29 devnull piperror = "write on closed pipe";
1045 5cdb1798 2005-10-29 devnull return status;
1046 5cdb1798 2005-10-29 devnull }
1047 5cdb1798 2005-10-29 devnull
1048 5cdb1798 2005-10-29 devnull char*
1049 5cdb1798 2005-10-29 devnull firstline(char *x)
1050 5cdb1798 2005-10-29 devnull {
1051 5cdb1798 2005-10-29 devnull static char buf[128];
1052 5cdb1798 2005-10-29 devnull char *p;
1053 5cdb1798 2005-10-29 devnull
1054 5cdb1798 2005-10-29 devnull strncpy(buf, x, sizeof(buf));
1055 5cdb1798 2005-10-29 devnull buf[sizeof(buf)-1] = 0;
1056 5cdb1798 2005-10-29 devnull p = strchr(buf, '\n');
1057 5cdb1798 2005-10-29 devnull if(p)
1058 5cdb1798 2005-10-29 devnull *p = 0;
1059 5cdb1798 2005-10-29 devnull return buf;
1060 5cdb1798 2005-10-29 devnull }
1061 5cdb1798 2005-10-29 devnull
1062 5cdb1798 2005-10-29 devnull int
1063 5cdb1798 2005-10-29 devnull sendermxcheck(void)
1064 5cdb1798 2005-10-29 devnull {
1065 5cdb1798 2005-10-29 devnull char *cp, *senddom, *user;
1066 5cdb1798 2005-10-29 devnull char *who;
1067 5cdb1798 2005-10-29 devnull int pid;
1068 5cdb1798 2005-10-29 devnull Waitmsg *w;
1069 5cc53af9 2006-02-12 devnull static char *validate;
1070 5cdb1798 2005-10-29 devnull
1071 5cdb1798 2005-10-29 devnull who = s_to_c(senders.first->p);
1072 5cdb1798 2005-10-29 devnull if(strcmp(who, "/dev/null") == 0){
1073 5cdb1798 2005-10-29 devnull /* /dev/null can only send to one rcpt at a time */
1074 5cdb1798 2005-10-29 devnull if(rcvers.first != rcvers.last){
1075 5cdb1798 2005-10-29 devnull werrstr("rejected: /dev/null sending to multiple recipients");
1076 5cdb1798 2005-10-29 devnull return -1;
1077 5cdb1798 2005-10-29 devnull }
1078 5cdb1798 2005-10-29 devnull return 0;
1079 5cdb1798 2005-10-29 devnull }
1080 5cdb1798 2005-10-29 devnull
1081 5cc53af9 2006-02-12 devnull if(validate == nil)
1082 5cc53af9 2006-02-12 devnull validate = unsharp("#9/mail/lib/validatesender");
1083 5cc53af9 2006-02-12 devnull if(access(validate, AEXEC) < 0)
1084 5cdb1798 2005-10-29 devnull return 0;
1085 5cdb1798 2005-10-29 devnull
1086 5cdb1798 2005-10-29 devnull senddom = strdup(who);
1087 5cdb1798 2005-10-29 devnull if((cp = strchr(senddom, '!')) == nil){
1088 5cdb1798 2005-10-29 devnull werrstr("rejected: domainless sender %s", who);
1089 5cdb1798 2005-10-29 devnull free(senddom);
1090 5cdb1798 2005-10-29 devnull return -1;
1091 5cdb1798 2005-10-29 devnull }
1092 5cdb1798 2005-10-29 devnull *cp++ = 0;
1093 5cdb1798 2005-10-29 devnull user = cp;
1094 5cdb1798 2005-10-29 devnull
1095 5cdb1798 2005-10-29 devnull switch(pid = fork()){
1096 5cdb1798 2005-10-29 devnull case -1:
1097 5cdb1798 2005-10-29 devnull werrstr("deferred: fork: %r");
1098 5cdb1798 2005-10-29 devnull return -1;
1099 5cdb1798 2005-10-29 devnull case 0:
1100 5cdb1798 2005-10-29 devnull /*
1101 5cdb1798 2005-10-29 devnull * Could add an option with the remote IP address
1102 5cdb1798 2005-10-29 devnull * to allow validatesender to implement SPF eventually.
1103 5cdb1798 2005-10-29 devnull */
1104 5cc53af9 2006-02-12 devnull execl(validate, "validatesender",
1105 5cdb1798 2005-10-29 devnull "-n", nci->root, senddom, user, nil);
1106 5cc53af9 2006-02-12 devnull threadexitsall("exec validatesender: %r");
1107 5cdb1798 2005-10-29 devnull default:
1108 5cdb1798 2005-10-29 devnull break;
1109 5cdb1798 2005-10-29 devnull }
1110 5cdb1798 2005-10-29 devnull
1111 5cdb1798 2005-10-29 devnull free(senddom);
1112 5cdb1798 2005-10-29 devnull w = wait();
1113 5cdb1798 2005-10-29 devnull if(w == nil){
1114 5cdb1798 2005-10-29 devnull werrstr("deferred: wait failed: %r");
1115 5cdb1798 2005-10-29 devnull return -1;
1116 5cdb1798 2005-10-29 devnull }
1117 5cdb1798 2005-10-29 devnull if(w->pid != pid){
1118 5cdb1798 2005-10-29 devnull werrstr("deferred: wait returned wrong pid %d != %d", w->pid, pid);
1119 5cdb1798 2005-10-29 devnull free(w);
1120 5cdb1798 2005-10-29 devnull return -1;
1121 5cdb1798 2005-10-29 devnull }
1122 5cdb1798 2005-10-29 devnull if(w->msg[0] == 0){
1123 5cdb1798 2005-10-29 devnull free(w);
1124 5cdb1798 2005-10-29 devnull return 0;
1125 5cdb1798 2005-10-29 devnull }
1126 5cdb1798 2005-10-29 devnull /*
1127 5cdb1798 2005-10-29 devnull * skip over validatesender 143123132: prefix from rc.
1128 5cdb1798 2005-10-29 devnull */
1129 5cdb1798 2005-10-29 devnull cp = strchr(w->msg, ':');
1130 5cdb1798 2005-10-29 devnull if(cp && *(cp+1) == ' ')
1131 5cdb1798 2005-10-29 devnull werrstr("%s", cp+2);
1132 5cdb1798 2005-10-29 devnull else
1133 5cdb1798 2005-10-29 devnull werrstr("%s", w->msg);
1134 5cdb1798 2005-10-29 devnull free(w);
1135 5cdb1798 2005-10-29 devnull return -1;
1136 5cdb1798 2005-10-29 devnull }
1137 5cdb1798 2005-10-29 devnull
1138 5cdb1798 2005-10-29 devnull void
1139 5cdb1798 2005-10-29 devnull data(void)
1140 5cdb1798 2005-10-29 devnull {
1141 5cdb1798 2005-10-29 devnull String *cmd;
1142 5cdb1798 2005-10-29 devnull String *err;
1143 5cdb1798 2005-10-29 devnull int status, nbytes;
1144 5cdb1798 2005-10-29 devnull char *cp, *ep;
1145 5cdb1798 2005-10-29 devnull char errx[ERRMAX];
1146 5cdb1798 2005-10-29 devnull Link *l;
1147 5cdb1798 2005-10-29 devnull
1148 5cdb1798 2005-10-29 devnull if(rejectcheck())
1149 5cdb1798 2005-10-29 devnull return;
1150 5cdb1798 2005-10-29 devnull if(senders.last == 0){
1151 5cdb1798 2005-10-29 devnull reply("503 Data without MAIL FROM:\r\n");
1152 5cdb1798 2005-10-29 devnull rejectcount++;
1153 5cdb1798 2005-10-29 devnull return;
1154 5cdb1798 2005-10-29 devnull }
1155 5cdb1798 2005-10-29 devnull if(rcvers.last == 0){
1156 5cdb1798 2005-10-29 devnull reply("503 Data without RCPT TO:\r\n");
1157 5cdb1798 2005-10-29 devnull rejectcount++;
1158 5cdb1798 2005-10-29 devnull return;
1159 5cdb1798 2005-10-29 devnull }
1160 5cdb1798 2005-10-29 devnull if(sendermxcheck()){
1161 5cdb1798 2005-10-29 devnull rerrstr(errx, sizeof errx);
1162 5cdb1798 2005-10-29 devnull if(strncmp(errx, "rejected:", 9) == 0)
1163 5cdb1798 2005-10-29 devnull reply("554 %s\r\n", errx);
1164 5cdb1798 2005-10-29 devnull else
1165 5cdb1798 2005-10-29 devnull reply("450 %s\r\n", errx);
1166 5cdb1798 2005-10-29 devnull for(l=rcvers.first; l; l=l->next)
1167 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "[%s/%s] %s -> %s sendercheck: %s",
1168 5cdb1798 2005-10-29 devnull him, nci->rsys, s_to_c(senders.first->p),
1169 5cdb1798 2005-10-29 devnull s_to_c(l->p), errx);
1170 5cdb1798 2005-10-29 devnull rejectcount++;
1171 5cdb1798 2005-10-29 devnull return;
1172 5cdb1798 2005-10-29 devnull }
1173 5cdb1798 2005-10-29 devnull
1174 5cdb1798 2005-10-29 devnull cmd = startcmd();
1175 5cdb1798 2005-10-29 devnull if(cmd == 0)
1176 5cdb1798 2005-10-29 devnull return;
1177 5cdb1798 2005-10-29 devnull
1178 5cdb1798 2005-10-29 devnull reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
1179 5cdb1798 2005-10-29 devnull
1180 5cdb1798 2005-10-29 devnull /*
1181 5cdb1798 2005-10-29 devnull * allow 145 more minutes to move the data
1182 5cdb1798 2005-10-29 devnull */
1183 5cdb1798 2005-10-29 devnull alarm(145*60*1000);
1184 5cdb1798 2005-10-29 devnull
1185 5cdb1798 2005-10-29 devnull status = pipemsg(&nbytes);
1186 5cdb1798 2005-10-29 devnull
1187 5cdb1798 2005-10-29 devnull /*
1188 5cdb1798 2005-10-29 devnull * read any error messages
1189 5cdb1798 2005-10-29 devnull */
1190 5cdb1798 2005-10-29 devnull err = s_new();
1191 5cdb1798 2005-10-29 devnull while(s_read_line(pp->std[2]->fp, err))
1192 5cdb1798 2005-10-29 devnull ;
1193 5cdb1798 2005-10-29 devnull
1194 5cdb1798 2005-10-29 devnull alarm(0);
1195 5cdb1798 2005-10-29 devnull atnotify(catchalarm, 0);
1196 5cdb1798 2005-10-29 devnull
1197 5cdb1798 2005-10-29 devnull status |= proc_wait(pp);
1198 5cdb1798 2005-10-29 devnull if(debug){
1199 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
1200 5cdb1798 2005-10-29 devnull fprint(2, "%d status %ux\n", getpid(), status);
1201 5cdb1798 2005-10-29 devnull if(*s_to_c(err))
1202 5cdb1798 2005-10-29 devnull fprint(2, "%d error %s\n", getpid(), s_to_c(err));
1203 5cdb1798 2005-10-29 devnull }
1204 5cdb1798 2005-10-29 devnull
1205 5cdb1798 2005-10-29 devnull /*
1206 5cdb1798 2005-10-29 devnull * if process terminated abnormally, send back error message
1207 5cdb1798 2005-10-29 devnull */
1208 5cdb1798 2005-10-29 devnull if(status){
1209 5cdb1798 2005-10-29 devnull int code;
1210 5cdb1798 2005-10-29 devnull
1211 5cdb1798 2005-10-29 devnull if(strstr(s_to_c(err), "mail refused")){
1212 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "++[%s/%s] %s %s refused: %s", him, nci->rsys,
1213 5cdb1798 2005-10-29 devnull s_to_c(senders.first->p), s_to_c(cmd), firstline(s_to_c(err)));
1214 5cdb1798 2005-10-29 devnull code = 554;
1215 5cdb1798 2005-10-29 devnull } else {
1216 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "++[%s/%s] %s %s %s%s%sreturned %#q %s", him, nci->rsys,
1217 5cdb1798 2005-10-29 devnull s_to_c(senders.first->p), s_to_c(cmd),
1218 5cdb1798 2005-10-29 devnull piperror ? "error during pipemsg: " : "",
1219 5cdb1798 2005-10-29 devnull piperror ? piperror : "",
1220 5cdb1798 2005-10-29 devnull piperror ? "; " : "",
1221 5cdb1798 2005-10-29 devnull pp->waitmsg->msg, firstline(s_to_c(err)));
1222 5cdb1798 2005-10-29 devnull code = 450;
1223 5cdb1798 2005-10-29 devnull }
1224 5cdb1798 2005-10-29 devnull for(cp = s_to_c(err); ep = strchr(cp, '\n'); cp = ep){
1225 5cdb1798 2005-10-29 devnull *ep++ = 0;
1226 5cdb1798 2005-10-29 devnull reply("%d-%s\r\n", code, cp);
1227 5cdb1798 2005-10-29 devnull }
1228 5cdb1798 2005-10-29 devnull reply("%d mail process terminated abnormally\r\n", code);
1229 5cdb1798 2005-10-29 devnull } else {
1230 b5f65921 2006-02-11 devnull /*
1231 b5f65921 2006-02-11 devnull * if a message appeared on stderr, despite good status,
1232 b5f65921 2006-02-11 devnull * log it. this can happen if rewrite.in contains a bad
1233 b5f65921 2006-02-11 devnull * r.e., for example.
1234 b5f65921 2006-02-11 devnull */
1235 b5f65921 2006-02-11 devnull if(*s_to_c(err))
1236 b5f65921 2006-02-11 devnull syslog(0, "smtpd",
1237 b5f65921 2006-02-11 devnull "%s returned good status, but said: %s",
1238 b5f65921 2006-02-11 devnull s_to_c(mailer), s_to_c(err));
1239 b5f65921 2006-02-11 devnull
1240 5cdb1798 2005-10-29 devnull if(filterstate == BLOCKED)
1241 5cdb1798 2005-10-29 devnull reply("554 we believe this is spam. we don't accept it.\r\n");
1242 5cdb1798 2005-10-29 devnull else
1243 5cdb1798 2005-10-29 devnull if(filterstate == DELAY)
1244 5cdb1798 2005-10-29 devnull reply("554 There will be a delay in delivery of this message.\r\n");
1245 5cdb1798 2005-10-29 devnull else {
1246 5cdb1798 2005-10-29 devnull reply("250 sent\r\n");
1247 5cdb1798 2005-10-29 devnull logcall(nbytes);
1248 5cdb1798 2005-10-29 devnull }
1249 5cdb1798 2005-10-29 devnull }
1250 5cdb1798 2005-10-29 devnull proc_free(pp);
1251 5cdb1798 2005-10-29 devnull pp = 0;
1252 5cdb1798 2005-10-29 devnull s_free(cmd);
1253 5cdb1798 2005-10-29 devnull s_free(err);
1254 5cdb1798 2005-10-29 devnull
1255 5cdb1798 2005-10-29 devnull listfree(&senders);
1256 5cdb1798 2005-10-29 devnull listfree(&rcvers);
1257 5cdb1798 2005-10-29 devnull }
1258 5cdb1798 2005-10-29 devnull
1259 5cdb1798 2005-10-29 devnull /*
1260 5cdb1798 2005-10-29 devnull * when we have blocked a transaction based on IP address, there is nothing
1261 5cdb1798 2005-10-29 devnull * that the sender can do to convince us to take the message. after the
1262 5cdb1798 2005-10-29 devnull * first rejection, some spammers continually RSET and give a new MAIL FROM:
1263 5cdb1798 2005-10-29 devnull * filling our logs with rejections. rejectcheck() limits the retries and
1264 5cdb1798 2005-10-29 devnull * swiftly rejects all further commands after the first 500-series message
1265 5cdb1798 2005-10-29 devnull * is issued.
1266 5cdb1798 2005-10-29 devnull */
1267 5cdb1798 2005-10-29 devnull int
1268 5cdb1798 2005-10-29 devnull rejectcheck(void)
1269 5cdb1798 2005-10-29 devnull {
1270 5cdb1798 2005-10-29 devnull
1271 5cdb1798 2005-10-29 devnull if(rejectcount > MAXREJECTS){
1272 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "Rejected (%s/%s)", him, nci->rsys);
1273 5cdb1798 2005-10-29 devnull reply("554 too many errors. transaction failed.\r\n");
1274 5cc53af9 2006-02-12 devnull threadexitsall("errcount");
1275 5cdb1798 2005-10-29 devnull }
1276 5cdb1798 2005-10-29 devnull if(hardreject){
1277 5cdb1798 2005-10-29 devnull rejectcount++;
1278 5cdb1798 2005-10-29 devnull reply("554 We don't accept mail from dial-up ports.\r\n");
1279 5cdb1798 2005-10-29 devnull }
1280 5cdb1798 2005-10-29 devnull return hardreject;
1281 5cdb1798 2005-10-29 devnull }
1282 5cdb1798 2005-10-29 devnull
1283 5cdb1798 2005-10-29 devnull /*
1284 5cdb1798 2005-10-29 devnull * create abs path of the mailer
1285 5cdb1798 2005-10-29 devnull */
1286 5cdb1798 2005-10-29 devnull String*
1287 5cdb1798 2005-10-29 devnull mailerpath(char *p)
1288 5cdb1798 2005-10-29 devnull {
1289 5cdb1798 2005-10-29 devnull String *s;
1290 5cdb1798 2005-10-29 devnull
1291 5cdb1798 2005-10-29 devnull if(p == nil)
1292 5cdb1798 2005-10-29 devnull return nil;
1293 5cdb1798 2005-10-29 devnull if(*p == '/')
1294 5cdb1798 2005-10-29 devnull return s_copy(p);
1295 5cdb1798 2005-10-29 devnull s = s_new();
1296 5cdb1798 2005-10-29 devnull s_append(s, UPASBIN);
1297 5cdb1798 2005-10-29 devnull s_append(s, "/");
1298 5cdb1798 2005-10-29 devnull s_append(s, p);
1299 5cdb1798 2005-10-29 devnull return s;
1300 5cdb1798 2005-10-29 devnull }
1301 5cdb1798 2005-10-29 devnull
1302 5cdb1798 2005-10-29 devnull String *
1303 5cdb1798 2005-10-29 devnull s_dec64(String *sin)
1304 5cdb1798 2005-10-29 devnull {
1305 5cdb1798 2005-10-29 devnull String *sout;
1306 5cdb1798 2005-10-29 devnull int lin, lout;
1307 5cdb1798 2005-10-29 devnull lin = s_len(sin);
1308 5cdb1798 2005-10-29 devnull
1309 5cdb1798 2005-10-29 devnull /*
1310 5cdb1798 2005-10-29 devnull * if the string is coming from smtpd.y, it will have no nl.
1311 5cdb1798 2005-10-29 devnull * if it is coming from getcrnl below, it will have an nl.
1312 5cdb1798 2005-10-29 devnull */
1313 5cdb1798 2005-10-29 devnull if (*(s_to_c(sin)+lin-1) == '\n')
1314 5cdb1798 2005-10-29 devnull lin--;
1315 5cdb1798 2005-10-29 devnull sout = s_newalloc(lin+1);
1316 5cdb1798 2005-10-29 devnull lout = dec64((uchar *)s_to_c(sout), lin, s_to_c(sin), lin);
1317 5cdb1798 2005-10-29 devnull if (lout < 0) {
1318 5cdb1798 2005-10-29 devnull s_free(sout);
1319 5cdb1798 2005-10-29 devnull return nil;
1320 5cdb1798 2005-10-29 devnull }
1321 5cdb1798 2005-10-29 devnull sout->ptr = sout->base + lout;
1322 5cdb1798 2005-10-29 devnull s_terminate(sout);
1323 5cdb1798 2005-10-29 devnull return sout;
1324 5cdb1798 2005-10-29 devnull }
1325 5cdb1798 2005-10-29 devnull
1326 5cdb1798 2005-10-29 devnull void
1327 5cdb1798 2005-10-29 devnull starttls(void)
1328 5cdb1798 2005-10-29 devnull {
1329 5cdb1798 2005-10-29 devnull uchar *cert;
1330 5cdb1798 2005-10-29 devnull int certlen, fd;
1331 5cdb1798 2005-10-29 devnull TLSconn *conn;
1332 5cdb1798 2005-10-29 devnull
1333 5cdb1798 2005-10-29 devnull conn = mallocz(sizeof *conn, 1);
1334 5cdb1798 2005-10-29 devnull cert = readcert(tlscert, &certlen);
1335 5cdb1798 2005-10-29 devnull if (conn == nil || cert == nil) {
1336 5cdb1798 2005-10-29 devnull if (conn != nil)
1337 5cdb1798 2005-10-29 devnull free(conn);
1338 5cdb1798 2005-10-29 devnull reply("454 TLS not available\r\n");
1339 5cdb1798 2005-10-29 devnull return;
1340 5cdb1798 2005-10-29 devnull }
1341 5cdb1798 2005-10-29 devnull reply("220 Go ahead make my day\r\n");
1342 5cdb1798 2005-10-29 devnull conn->cert = cert;
1343 5cdb1798 2005-10-29 devnull conn->certlen = certlen;
1344 5cdb1798 2005-10-29 devnull fd = tlsServer(Bfildes(&bin), conn);
1345 5cdb1798 2005-10-29 devnull if (fd < 0) {
1346 5cdb1798 2005-10-29 devnull free(cert);
1347 5cdb1798 2005-10-29 devnull free(conn);
1348 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "TLS start-up failed with %s", him);
1349 5cdb1798 2005-10-29 devnull
1350 5cdb1798 2005-10-29 devnull /* force the client to hang up */
1351 5cdb1798 2005-10-29 devnull close(Bfildes(&bin)); /* probably fd 0 */
1352 5cdb1798 2005-10-29 devnull close(1);
1353 5cc53af9 2006-02-12 devnull threadexitsall("tls failed");
1354 5cdb1798 2005-10-29 devnull }
1355 5cdb1798 2005-10-29 devnull Bterm(&bin);
1356 5cdb1798 2005-10-29 devnull Binit(&bin, fd, OREAD);
1357 5cdb1798 2005-10-29 devnull if (dup(fd, 1) < 0)
1358 5cdb1798 2005-10-29 devnull fprint(2, "dup of %d failed: %r\n", fd);
1359 5cdb1798 2005-10-29 devnull passwordinclear = 1;
1360 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "started TLS with %s", him);
1361 5cdb1798 2005-10-29 devnull }
1362 5cdb1798 2005-10-29 devnull
1363 5cdb1798 2005-10-29 devnull void
1364 5cdb1798 2005-10-29 devnull auth(String *mech, String *resp)
1365 5cdb1798 2005-10-29 devnull {
1366 5cdb1798 2005-10-29 devnull Chalstate *chs = nil;
1367 5cdb1798 2005-10-29 devnull AuthInfo *ai = nil;
1368 5cdb1798 2005-10-29 devnull String *s_resp1_64 = nil;
1369 5cdb1798 2005-10-29 devnull String *s_resp2_64 = nil;
1370 5cdb1798 2005-10-29 devnull String *s_resp1 = nil;
1371 5cdb1798 2005-10-29 devnull String *s_resp2 = nil;
1372 5cdb1798 2005-10-29 devnull char *scratch = nil;
1373 5cdb1798 2005-10-29 devnull char *user, *pass;
1374 5cdb1798 2005-10-29 devnull
1375 5cdb1798 2005-10-29 devnull if (rejectcheck())
1376 5cdb1798 2005-10-29 devnull goto bomb_out;
1377 5cdb1798 2005-10-29 devnull
1378 5cdb1798 2005-10-29 devnull syslog(0, "smtpd", "auth(%s, %s) from %s", s_to_c(mech),
1379 5cdb1798 2005-10-29 devnull "(protected)", him);
1380 5cdb1798 2005-10-29 devnull
1381 5cdb1798 2005-10-29 devnull if (authenticated) {
1382 5cdb1798 2005-10-29 devnull bad_sequence:
1383 5cdb1798 2005-10-29 devnull rejectcount++;
1384 5cdb1798 2005-10-29 devnull reply("503 Bad sequence of commands\r\n");
1385 5cdb1798 2005-10-29 devnull goto bomb_out;
1386 5cdb1798 2005-10-29 devnull }
1387 5cdb1798 2005-10-29 devnull if (cistrcmp(s_to_c(mech), "plain") == 0) {
1388 5cdb1798 2005-10-29 devnull
1389 5cdb1798 2005-10-29 devnull if (!passwordinclear) {
1390 5cdb1798 2005-10-29 devnull rejectcount++;
1391 5cdb1798 2005-10-29 devnull reply("538 Encryption required for requested authentication mechanism\r\n");
1392 5cdb1798 2005-10-29 devnull goto bomb_out;
1393 5cdb1798 2005-10-29 devnull }
1394 5cdb1798 2005-10-29 devnull s_resp1_64 = resp;
1395 5cdb1798 2005-10-29 devnull if (s_resp1_64 == nil) {
1396 5cdb1798 2005-10-29 devnull reply("334 \r\n");
1397 5cdb1798 2005-10-29 devnull s_resp1_64 = s_new();
1398 5cdb1798 2005-10-29 devnull if (getcrnl(s_resp1_64, &bin) <= 0) {
1399 5cdb1798 2005-10-29 devnull goto bad_sequence;
1400 5cdb1798 2005-10-29 devnull }
1401 5cdb1798 2005-10-29 devnull }
1402 5cdb1798 2005-10-29 devnull s_resp1 = s_dec64(s_resp1_64);
1403 5cdb1798 2005-10-29 devnull if (s_resp1 == nil) {
1404 5cdb1798 2005-10-29 devnull rejectcount++;
1405 5cdb1798 2005-10-29 devnull reply("501 Cannot decode base64\r\n");
1406 5cdb1798 2005-10-29 devnull goto bomb_out;
1407 5cdb1798 2005-10-29 devnull }
1408 5cdb1798 2005-10-29 devnull memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
1409 5cdb1798 2005-10-29 devnull user = (s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1);
1410 5cdb1798 2005-10-29 devnull pass = user + (strlen(user) + 1);
1411 5cdb1798 2005-10-29 devnull ai = auth_userpasswd(user, pass);
1412 5cdb1798 2005-10-29 devnull authenticated = ai != nil;
1413 5cdb1798 2005-10-29 devnull memset(pass, 'X', strlen(pass));
1414 5cdb1798 2005-10-29 devnull goto windup;
1415 5cdb1798 2005-10-29 devnull }
1416 5cdb1798 2005-10-29 devnull else if (cistrcmp(s_to_c(mech), "login") == 0) {
1417 5cdb1798 2005-10-29 devnull
1418 5cdb1798 2005-10-29 devnull if (!passwordinclear) {
1419 5cdb1798 2005-10-29 devnull rejectcount++;
1420 5cdb1798 2005-10-29 devnull reply("538 Encryption required for requested authentication mechanism\r\n");
1421 5cdb1798 2005-10-29 devnull goto bomb_out;
1422 5cdb1798 2005-10-29 devnull }
1423 5cdb1798 2005-10-29 devnull if (resp == nil) {
1424 5cdb1798 2005-10-29 devnull reply("334 VXNlcm5hbWU6\r\n");
1425 5cdb1798 2005-10-29 devnull s_resp1_64 = s_new();
1426 5cdb1798 2005-10-29 devnull if (getcrnl(s_resp1_64, &bin) <= 0)
1427 5cdb1798 2005-10-29 devnull goto bad_sequence;
1428 5cdb1798 2005-10-29 devnull }
1429 5cdb1798 2005-10-29 devnull reply("334 UGFzc3dvcmQ6\r\n");
1430 5cdb1798 2005-10-29 devnull s_resp2_64 = s_new();
1431 5cdb1798 2005-10-29 devnull if (getcrnl(s_resp2_64, &bin) <= 0)
1432 5cdb1798 2005-10-29 devnull goto bad_sequence;
1433 5cdb1798 2005-10-29 devnull s_resp1 = s_dec64(s_resp1_64);
1434 5cdb1798 2005-10-29 devnull s_resp2 = s_dec64(s_resp2_64);
1435 5cdb1798 2005-10-29 devnull memset(s_to_c(s_resp2_64), 'X', s_len(s_resp2_64));
1436 5cdb1798 2005-10-29 devnull if (s_resp1 == nil || s_resp2 == nil) {
1437 5cdb1798 2005-10-29 devnull rejectcount++;
1438 5cdb1798 2005-10-29 devnull reply("501 Cannot decode base64\r\n");
1439 5cdb1798 2005-10-29 devnull goto bomb_out;
1440 5cdb1798 2005-10-29 devnull }
1441 5cdb1798 2005-10-29 devnull ai = auth_userpasswd(s_to_c(s_resp1), s_to_c(s_resp2));
1442 5cdb1798 2005-10-29 devnull authenticated = ai != nil;
1443 5cdb1798 2005-10-29 devnull memset(s_to_c(s_resp2), 'X', s_len(s_resp2));
1444 5cdb1798 2005-10-29 devnull windup:
1445 5cdb1798 2005-10-29 devnull if (authenticated)
1446 5cdb1798 2005-10-29 devnull reply("235 Authentication successful\r\n");
1447 5cdb1798 2005-10-29 devnull else {
1448 5cdb1798 2005-10-29 devnull rejectcount++;
1449 5cdb1798 2005-10-29 devnull reply("535 Authentication failed\r\n");
1450 5cdb1798 2005-10-29 devnull }
1451 5cdb1798 2005-10-29 devnull goto bomb_out;
1452 5cdb1798 2005-10-29 devnull }
1453 5cdb1798 2005-10-29 devnull else if (cistrcmp(s_to_c(mech), "cram-md5") == 0) {
1454 5cdb1798 2005-10-29 devnull char *resp;
1455 5cdb1798 2005-10-29 devnull int chal64n;
1456 5cdb1798 2005-10-29 devnull char *t;
1457 5cdb1798 2005-10-29 devnull
1458 5cdb1798 2005-10-29 devnull chs = auth_challenge("proto=cram role=server");
1459 5cdb1798 2005-10-29 devnull if (chs == nil) {
1460 5cdb1798 2005-10-29 devnull rejectcount++;
1461 5cdb1798 2005-10-29 devnull reply("501 Couldn't get CRAM-MD5 challenge\r\n");
1462 5cdb1798 2005-10-29 devnull goto bomb_out;
1463 5cdb1798 2005-10-29 devnull }
1464 5cdb1798 2005-10-29 devnull scratch = malloc(chs->nchal * 2 + 1);
1465 5cdb1798 2005-10-29 devnull chal64n = enc64(scratch, chs->nchal * 2, (uchar *)chs->chal, chs->nchal);
1466 5cdb1798 2005-10-29 devnull scratch[chal64n] = 0;
1467 5cdb1798 2005-10-29 devnull reply("334 %s\r\n", scratch);
1468 5cdb1798 2005-10-29 devnull s_resp1_64 = s_new();
1469 5cdb1798 2005-10-29 devnull if (getcrnl(s_resp1_64, &bin) <= 0)
1470 5cdb1798 2005-10-29 devnull goto bad_sequence;
1471 5cdb1798 2005-10-29 devnull s_resp1 = s_dec64(s_resp1_64);
1472 5cdb1798 2005-10-29 devnull if (s_resp1 == nil) {
1473 5cdb1798 2005-10-29 devnull rejectcount++;
1474 5cdb1798 2005-10-29 devnull reply("501 Cannot decode base64\r\n");
1475 5cdb1798 2005-10-29 devnull goto bomb_out;
1476 5cdb1798 2005-10-29 devnull }
1477 5cdb1798 2005-10-29 devnull /* should be of form <user><space><response> */
1478 5cdb1798 2005-10-29 devnull resp = s_to_c(s_resp1);
1479 5cdb1798 2005-10-29 devnull t = strchr(resp, ' ');
1480 5cdb1798 2005-10-29 devnull if (t == nil) {
1481 5cdb1798 2005-10-29 devnull rejectcount++;
1482 5cdb1798 2005-10-29 devnull reply("501 Poorly formed CRAM-MD5 response\r\n");
1483 5cdb1798 2005-10-29 devnull goto bomb_out;
1484 5cdb1798 2005-10-29 devnull }
1485 5cdb1798 2005-10-29 devnull *t++ = 0;
1486 5cdb1798 2005-10-29 devnull chs->user = resp;
1487 5cdb1798 2005-10-29 devnull chs->resp = t;
1488 5cdb1798 2005-10-29 devnull chs->nresp = strlen(t);
1489 5cdb1798 2005-10-29 devnull ai = auth_response(chs);
1490 5cdb1798 2005-10-29 devnull authenticated = ai != nil;
1491 5cdb1798 2005-10-29 devnull goto windup;
1492 5cdb1798 2005-10-29 devnull }
1493 5cdb1798 2005-10-29 devnull rejectcount++;
1494 5cdb1798 2005-10-29 devnull reply("501 Unrecognised authentication type %s\r\n", s_to_c(mech));
1495 5cdb1798 2005-10-29 devnull bomb_out:
1496 5cdb1798 2005-10-29 devnull if (ai)
1497 5cdb1798 2005-10-29 devnull auth_freeAI(ai);
1498 5cdb1798 2005-10-29 devnull if (chs)
1499 5cdb1798 2005-10-29 devnull auth_freechal(chs);
1500 5cdb1798 2005-10-29 devnull if (scratch)
1501 5cdb1798 2005-10-29 devnull free(scratch);
1502 5cdb1798 2005-10-29 devnull if (s_resp1)
1503 5cdb1798 2005-10-29 devnull s_free(s_resp1);
1504 5cdb1798 2005-10-29 devnull if (s_resp2)
1505 5cdb1798 2005-10-29 devnull s_free(s_resp2);
1506 5cdb1798 2005-10-29 devnull if (s_resp1_64)
1507 5cdb1798 2005-10-29 devnull s_free(s_resp1_64);
1508 5cdb1798 2005-10-29 devnull if (s_resp2_64)
1509 5cdb1798 2005-10-29 devnull s_free(s_resp2_64);
1510 5cdb1798 2005-10-29 devnull }