/[pkg-mixmaster]/trunk/Mix/Src/mail.c
ViewVC logotype

Contents of /trunk/Mix/Src/mail.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 120 - (hide annotations) (download)
Sat Aug 3 17:08:02 2002 UTC (10 years, 9 months ago) by weaselp
File MIME type: text/plain
File size: 16126 byte(s)
Submitted By: Sami Farin (safari):
Included correct header files.

Src/main.c had incorrect param to buf_appendf.

Added buf_write_sync() (used by Src/rem.c:mix_pool()).
Should a mixmaster machine crash, pool file can contain
any random data after reboot/journal recovery (at least
when using reiserfs).

Maybe not relevant, but strrchr should be used instead of
strchr when looking for domain part.

Src/pgpdata.c:pgp_elgdecrypt() passes uninitialized values
to BN_free if BN_CTX_new fails.

Src/pgpdata.c:pgp_elgencrypt() passes uninitialized value
to BN_free if the third mpi_get(key, i) fails.

Src/random.c does not check return value of read().

Src/rndseed.c does not check return value of read().
1 rabbi 1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2    
3     Mixmaster may be redistributed and modified under certain conditions.
4     This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5     ANY KIND, either express or implied. See the file COPYRIGHT for
6     details.
7    
8     Socket-based mail transport services
9 weaselp 120 $Id: mail.c,v 1.5 2002/08/03 17:08:01 weaselp Exp $ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include <stdio.h>
14     #include <stdlib.h>
15     #include <string.h>
16    
17     #if defined(UNIX) && defined(USE_SOCK)
18     #include <unistd.h>
19     #include <sys/types.h>
20     #include <sys/socket.h>
21     #include <netinet/in.h>
22     #include <arpa/inet.h>
23     #include <netdb.h>
24     #include <fcntl.h>
25     #endif
26    
27     int sendinfofile(char *name, char *logname, BUFFER *address, BUFFER *header)
28     {
29     FILE *f, *log = NULL;
30     BUFFER *msg, *addr;
31     char line[LINELEN];
32     int ret = -1;
33    
34     if (bufeq(address, ANONNAME))
35     return (0); /* don't reply to our own anon messages */
36     f = mix_openfile(name, "r");
37     if (f == NULL)
38     return (-1);
39    
40     addr = buf_new();
41     rfc822_addr(address, addr);
42     if (addr->length == 0)
43     buf_set(addr, address), buf_nl(addr);
44    
45     if (logname != NULL) {
46     if ((log = mix_openfile(logname, "r+")) != NULL) {
47     /* log recipients to prevent mail loop */
48     while (fgets(line, sizeof(line), log) != NULL)
49     if (strieq(line, addr->data))
50     goto end;
51     } else if ((log = mix_openfile(logname, "w")) == NULL) {
52     errlog(ERRORMSG, "Can't create %s.\n", logname);
53     ret = -1;
54     goto end;
55     }
56     fprintf(log, "%s", addr->data);
57     }
58     msg = buf_new();
59     if (header)
60     buf_cat(msg, header), buf_nl(msg);
61     while (fgets(line, sizeof(line), f) != NULL) {
62     if (streq(line, "DESTINATION-BLOCK\n"))
63     buf_appendf(msg, "destination-block %b", addr);
64     else
65     buf_appends(msg, line);
66     }
67     ret = sendmail(msg, REMAILERNAME, address);
68     fclose(f);
69     buf_free(msg);
70     end:
71     if (log)
72     fclose(log);
73     buf_free(addr);
74     return (ret);
75     }
76    
77     int smtpsend(BUFFER *head, BUFFER *message, char *from);
78    
79 weaselp 116
80     int sendmail_loop(BUFFER *message, char *from, BUFFER *address)
81     {
82     BUFFER *msg;
83     int err;
84    
85     msg = buf_new();
86     buf_appendf(msg, "X-Loop: %s\n", REMAILERADDR);
87     buf_cat(msg, message);
88     err = sendmail(msg, from, address);
89     buf_free(msg);
90    
91     return(err);
92     };
93    
94 rabbi 1 int sendmail(BUFFER *message, char *from, BUFFER *address)
95     {
96     /* returns: 0: ok 1: problem, try again -1: failed */
97    
98     BUFFER *head, *block;
99     FILE *f;
100     int err = -1;
101    
102     head = buf_new();
103    
104     block = readdestblk( );
105     if ( !block ) block = buf_new( );
106    
107     if (address != NULL &&
108     (address->length == 0 || doblock(address, block, 1) == -1))
109     goto end;
110    
111     if (from != NULL) {
112     buf_setf(head, "From: %s", from);
113     hdr_encode(head, 255);
114     buf_nl(head);
115     }
116     if (address != NULL)
117     buf_appendf(head, "To: %b\n", address);
118    
119     buf_rewind(message);
120    
121     if (SMTPRELAY[0])
122     err = smtpsend(head, message, from);
123     else if (strieq(SENDMAIL, "outfile")) {
124     char path[PATHMAX];
125     FILE *f = NULL;
126     int i;
127    
128     for (i = 0; i < 10000; i++) {
129 rabbi 11 sprintf(path, "%s%cout%i.txt", POOLDIR, DIRSEP, i);
130 rabbi 1 f = fopen(path, "r");
131     if (f)
132     fclose(f);
133     else
134     break;
135     }
136     f = fopen(path, "w");
137     if (f != NULL) {
138     err = buf_write(head, f);
139     err = buf_write(message, f);
140     fclose(f);
141     } else
142     errlog(ERRORMSG, "Can't create %s!\n", path);
143     } else {
144     if (SENDANONMAIL[0] != '\0' && (from == NULL || streq(from, ANONNAME)))
145     f = openpipe(SENDANONMAIL);
146     else
147     f = openpipe(SENDMAIL);
148     if (f != NULL) {
149     err = buf_write(head, f);
150     err = buf_write(message, f);
151     closepipe(f);
152     }
153     }
154     if (err != 0)
155     err = 1; /* error while sending, retry later */
156     end:
157     buf_free(block);
158     buf_free(head);
159     return (err);
160     }
161    
162     /* socket communication **********************************************/
163    
164     #ifdef USE_SOCK
165     #ifdef WIN32
166     WSADATA w;
167    
168     int sock_init()
169     {
170     if (WSAStartup(MAKEWORD(2, 0), &w) != 0) {
171     errlog(ERRORMSG, "Unable to initialize WINSOCK.\n");
172     return 0;
173     }
174     return 1;
175     }
176    
177     void sock_exit(void)
178     {
179     WSACleanup();
180     }
181     #endif
182    
183     SOCKET opensocket(char *hostname, int port)
184     {
185     struct hostent *hp;
186     struct sockaddr_in server;
187     SOCKET s;
188    
189     if ((hp = gethostbyname(hostname)) == NULL)
190     return (INVALID_SOCKET);
191    
192     memset((char *) &server, 0, sizeof(server));
193     server.sin_family = AF_INET;
194     server.sin_addr.s_addr = *(unsigned long *) hp->h_addr;
195     server.sin_port = htons((unsigned short) port);
196    
197     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
198     if (s != INVALID_SOCKET)
199     if (connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) {
200     closesocket(s);
201     return (INVALID_SOCKET);
202     }
203     return (s);
204     }
205    
206     #ifndef WIN32
207     int closesocket(SOCKET s)
208     {
209     return (close(s));
210     }
211     #endif
212    
213     int sock_getline(SOCKET s, BUFFER *line)
214     {
215     char c;
216     int ok;
217    
218     buf_clear(line);
219     while ((ok = recv(s, &c, 1, 0)) > 0) {
220     if (c == '\n')
221     break;
222     if (c != '\r')
223     buf_appendc(line, c);
224     }
225     if (ok <= 0)
226     return (-1);
227     if (line->length == 0)
228     return (1);
229     return (0);
230     }
231    
232     int sock_cat(SOCKET s, BUFFER *b)
233     {
234     int p = 0, n;
235    
236     do {
237     n = send(s, b->data, b->length, 0);
238     if (n < 0)
239     return (-1);
240     p += n;
241     } while (p < b->length);
242     return (0);
243     }
244     #else
245     SOCKET opensocket(char *hostname, int port)
246     {
247     return (INVALID_SOCKET);
248     }
249    
250     int closesocket(SOCKET s)
251     {
252     return (INVALID_SOCKET);
253     }
254    
255     int sock_getline(SOCKET s, BUFFER *line)
256     {
257     return (-1);
258     }
259    
260     int sock_cat(SOCKET s, BUFFER *b)
261     {
262     return (-1);
263     }
264     #endif
265    
266     /* send messages by SMTP ************************************************/
267    
268     static int sock_getsmtp(SOCKET s, BUFFER *line)
269     {
270     int ret;
271    
272     do
273     ret = sock_getline(s, line);
274     while (line->length >= 4 && line->data[3] == '-');
275     return (ret);
276     }
277    
278     SOCKET smtp_open(void)
279     {
280     int s = INVALID_SOCKET;
281     BUFFER *line;
282    
283     #ifdef USE_SOCK
284     if (SMTPRELAY[0] != '\0')
285     s = opensocket(SMTPRELAY, 25);
286     if (s != INVALID_SOCKET) {
287     line = buf_new();
288     sock_getsmtp(s, line);
289     if (line->data[0] != '2') {
290     errlog(ERRORMSG, "SMTP relay not ready. %b\n", line);
291     closesocket(s);
292     s = INVALID_SOCKET;
293     } else {
294     errlog(DEBUGINFO, "Opening SMTP connection.\n");
295     buf_sets(line, "HELO ");
296     if (HELONAME[0])
297     buf_appends(line, HELONAME);
298     else if (strchr(ENVFROM, '@'))
299     buf_appends(line, strchr(ENVFROM, '@') + 1);
300     else {
301     struct sockaddr_in sa;
302     int len = sizeof(sa);
303     struct hostent *hp;
304    
305     if (getsockname(s, (struct sockaddr *) &sa, &len) == 0 &&
306     (hp = gethostbyaddr((char *) &sa.sin_addr, sizeof(sa.sin_addr),
307     AF_INET)) != NULL)
308     buf_appends(line, (char *) hp->h_name);
309     else if (strchr(REMAILERADDR, '@'))
310     buf_appends(line, strchr(REMAILERADDR, '@') + 1);
311     else
312     buf_appends(line, SHORTNAME);
313     }
314     buf_appends(line, "\r\n");
315     sock_cat(s, line);
316     sock_getsmtp(s, line);
317     if (line->data[0] != '2') {
318     errlog(ERRORMSG, "SMTP relay refuses HELO: %b\n", line);
319     closesocket(s);
320     s = INVALID_SOCKET;
321     }
322     }
323     buf_free(line);
324     }
325     #endif
326     return (s);
327     }
328    
329     int smtp_close(SOCKET s)
330     {
331     BUFFER *line;
332     int ret = -1;
333    
334     #ifdef USE_SOCK
335     line = buf_new();
336     buf_sets(line, "QUIT\r\n");
337     sock_cat(s, line);
338     if (sock_getsmtp(s, line) == 0 && line->data[0] == '2') {
339     errlog(DEBUGINFO, "Closing SMTP connection.\n");
340     ret = 0;
341     } else
342     errlog(WARNING, "SMTP quit failed: %b\n", line);
343     closesocket(s);
344     buf_free(line);
345     #endif
346     return (ret);
347     }
348    
349     int smtp_send(SOCKET relay, BUFFER *head, BUFFER *message, char *from)
350     {
351     BUFFER *rcpt, *line, *field, *content;
352     int ret = -1;
353    
354     #ifdef USE_SOCK
355     line = buf_new();
356     field = buf_new();
357     content = buf_new();
358     rcpt = buf_new();
359    
360     while (buf_getheader(head, field, content) == 0)
361     if (bufieq(field, "to"))
362 rabbi 29 #ifdef BROKEN_MTA
363     if (!bufifind(rcpt, content->data))
364     /* Do not add the same recipient twice.
365     Needed for brain-dead MTAs. */
366     #endif //BROKEN_MTA
367     rfc822_addr(content, rcpt);
368 rabbi 1 buf_rewind(head);
369    
370 weaselp 116 while (buf_isheader(message) && buf_getheader(message, field, content) == 0) {
371 rabbi 1 if (bufieq(field, "to") || bufieq(field, "cc") || bufieq(field, "bcc")) {
372 rabbi 29 #ifdef BROKEN_MTA
373     if (!bufifind(rcpt, content->data))
374     /* Do not add the same recipient twice.
375     Needed for brain-dead MTAs. */
376     #endif //BROKEN_MTA
377     rfc822_addr(content, rcpt);
378 rabbi 1 }
379     if (!bufieq(field, "bcc"))
380     buf_appendheader(head, field, content);
381     }
382     buf_nl(head);
383    
384     buf_clear(content);
385     if (from) {
386     buf_sets(line, from);
387     rfc822_addr(line, content);
388     buf_chop(content);
389     }
390     if (bufieq(content, REMAILERADDR) || bufieq(content, ANONADDR))
391     buf_clear(content);
392     if (content->length == 0)
393     buf_sets(content, ENVFROM[0] ? ENVFROM : ANONADDR);
394    
395     buf_setf(line, "MAIL FROM:<%b>\r\n", content);
396     sock_cat(relay, line);
397     sock_getsmtp(relay, line);
398     if (!line->data[0] == '2') {
399     errlog(ERRORMSG, "SMTP relay does not accept mail: %b\n", line);
400     goto end;
401     }
402     while (buf_getline(rcpt, content) == 0) {
403     buf_setf(line, "RCPT TO:<%b>\r\n", content);
404     sock_cat(relay, line);
405     sock_getsmtp(relay, line);
406     if (bufleft(line, "421")) {
407     errlog(ERRORMSG, "SMTP relay error: %b\n", line);
408     goto end;
409     }
410     }
411    
412     buf_sets(line, "DATA\r\n");
413     sock_cat(relay, line);
414     sock_getsmtp(relay, line);
415     if (!bufleft(line, "354")) {
416     errlog(WARNING, "SMTP relay does not accept message: %b\n", line);
417     goto end;
418     }
419     while (buf_getline(head, line) >= 0) {
420     buf_appends(line, "\r\n");
421     if (bufleft(line, ".")) {
422     buf_setf(content, ".%b", line);
423     buf_move(line, content);
424     }
425     sock_cat(relay, line);
426     }
427     while (buf_getline(message, line) >= 0) {
428     buf_appends(line, "\r\n");
429     if (bufleft(line, ".")) {
430     buf_setf(content, ".%b", line);
431     buf_move(line, content);
432     }
433     sock_cat(relay, line);
434     }
435     buf_sets(line, ".\r\n");
436     sock_cat(relay, line);
437     sock_getsmtp(relay, line);
438     if (bufleft(line, "2"))
439     ret = 0;
440     else
441     errlog(WARNING, "SMTP relay will not send message: %b\n", line);
442     end:
443     buf_free(line);
444     buf_free(field);
445     buf_free(content);
446     buf_free(rcpt);
447     #endif
448     return (ret);
449     }
450    
451     static SOCKET sendmail_state = INVALID_SOCKET;
452    
453     void sendmail_begin(void)
454     {
455     /* begin mail sending session */
456     if (sendmail_state == INVALID_SOCKET)
457     sendmail_state = smtp_open();
458     }
459     void sendmail_end(void)
460     {
461     /* end mail sending session */
462     if (sendmail_state != INVALID_SOCKET) {
463     smtp_close(sendmail_state);
464     sendmail_state = INVALID_SOCKET;
465     }
466     }
467    
468     int smtpsend(BUFFER *head, BUFFER *message, char *from)
469     {
470     SOCKET s;
471     int ret = -1;
472    
473     if (sendmail_state != INVALID_SOCKET)
474     ret = smtp_send(sendmail_state, head, message, from);
475     else {
476     s = smtp_open();
477     if (s != INVALID_SOCKET) {
478     ret = smtp_send(s, head, message, from);
479     smtp_close(s);
480     }
481     }
482     return (ret);
483     }
484    
485     /* retrieve mail with POP3 **********************************************/
486     #ifdef USE_SOCK
487     int pop3_close(SOCKET s);
488    
489     #define POP3_ANY 0
490     #define POP3_APOP 1
491     #define POP3_PASS 2
492    
493     SOCKET pop3_open(char *user, char *host, char *pass, int auth)
494     {
495     SOCKET server = INVALID_SOCKET;
496     BUFFER *line;
497     int authenticated = 0;
498     char c, md[33];
499    
500     line = buf_new();
501     server = opensocket(host, 110);
502     if (server == INVALID_SOCKET)
503     errlog(NOTICE, "Can't connect to POP3 server %s.\n", host);
504     else {
505     sock_getline(server, line);
506     if (!bufleft(line, "+")) {
507     errlog(WARNING, "No POP3 service at %s.\n", host);
508     closesocket(server);
509 rabbi 11 server = INVALID_SOCKET;
510 rabbi 1 }
511     }
512     if (server != INVALID_SOCKET) {
513     errlog(DEBUGINFO, "Opening POP3 connection to %s.\n", host);
514     do
515     c = buf_getc(line);
516     while (c != '<' && c != -1);
517     while (c != '>' && c != -1) {
518     buf_appendc(line, c);
519     c = buf_getc(line);
520     }
521     if (c == '>' && (auth == POP3_ANY || auth == POP3_APOP)) {
522     buf_appendc(line, c);
523     buf_appends(line, pass);
524     digest_md5(line, line);
525     id_encode(line->data, md);
526     buf_setf(line, "APOP %s %s\r\n", user, md);
527     sock_cat(server, line);
528     sock_getline(server, line);
529     if (bufleft(line, "+"))
530     authenticated = 1;
531     else {
532     errlog(auth == POP3_APOP ? ERRORMSG : NOTICE,
533     "POP3 APOP auth at %s failed: %b\n", host, line);
534     buf_sets(line, "QUIT\r\n");
535     sock_cat(server, line);
536     closesocket(server);
537     server = pop3_open(user, host, pass, POP3_PASS);
538     goto end;
539     }
540     }
541     if (!authenticated) {
542     buf_setf(line, "USER %s\r\n", user);
543     sock_cat(server, line);
544     sock_getline(server, line);
545     if (!bufleft(line, "+"))
546     errlog(ERRORMSG, "POP3 USER command at %s failed: %b\n", host, line);
547     else {
548     buf_setf(line, "PASS %s\r\n", pass);
549     sock_cat(server, line);
550     sock_getline(server, line);
551     if (bufleft(line, "+"))
552     authenticated = 1;
553     else
554     errlog(ERRORMSG, "POP3 auth at %s failed: %b\n", host, line);
555     }
556     }
557     if (!authenticated) {
558     pop3_close(server);
559 rabbi 11 closesocket(server);
560 rabbi 1 server = INVALID_SOCKET;
561     }
562     }
563     end:
564     buf_free(line);
565     return (server);
566     }
567    
568     int pop3_close(SOCKET s)
569     {
570     BUFFER *line;
571     int ret = -1;
572    
573     line = buf_new();
574     buf_sets(line, "QUIT\r\n");
575     sock_cat(s, line);
576     sock_getline(s, line);
577     if (bufleft(line, "+")) {
578     ret = 0;
579     errlog(DEBUGINFO, "Closing POP3 connection.\n");
580     } else
581     errlog(ERRORMSG, "POP3 QUIT failed:\n", line->data);
582     buf_free(line);
583     return (ret);
584     }
585    
586     int pop3_stat(SOCKET s)
587     {
588     BUFFER *line;
589     int val = -1;
590    
591     line = buf_new();
592     buf_sets(line, "STAT\r\n");
593     sock_cat(s, line);
594     sock_getline(s, line);
595     if (bufleft(line, "+"))
596     sscanf(line->data, "+%*s %d", &val);
597     buf_free(line);
598     return (val);
599     }
600    
601     int pop3_list(SOCKET s, int n)
602     {
603     BUFFER *line;
604     int val = -1;
605    
606     line = buf_new();
607     buf_setf(line, "LIST %d\r\n", n);
608     sock_cat(s, line);
609     sock_getline(s, line);
610     if (bufleft(line, "+"))
611     sscanf(line->data, "+%*s %d", &val);
612     buf_free(line);
613     return (val);
614     }
615    
616     int pop3_dele(SOCKET s, int n)
617     {
618     BUFFER *line;
619     int ret = 0;
620    
621     line = buf_new();
622     buf_setf(line, "DELE %d\r\n", n);
623     sock_cat(s, line);
624     sock_getline(s, line);
625     if (!bufleft(line, "+"))
626     ret = -1;
627     buf_free(line);
628     return (ret);
629     }
630    
631     int pop3_retr(SOCKET s, int n, BUFFER *msg)
632     {
633     BUFFER *line;
634     int ret = -1;
635    
636     line = buf_new();
637     buf_clear(msg);
638     buf_setf(line, "RETR %d\r\n", n);
639     sock_cat(s, line);
640     sock_getline(s, line);
641     if (bufleft(line, "+")) {
642     for (;;) {
643     if (sock_getline(s, line) == -1)
644     break;
645     if (bufeq(line, ".")) {
646     ret = 0;
647     break;
648     } else if (bufleft(line, ".")) {
649     buf_append(msg, line->data + 1, line->length - 1);
650     } else
651     buf_cat(msg, line);
652     buf_nl(msg);
653     }
654     }
655     buf_free(line);
656     return (ret);
657     }
658    
659     void pop3get(void)
660     {
661     FILE *f;
662     char cfg[LINELEN], user[LINELEN], host[LINELEN], pass[LINELEN], auth[5];
663     SOCKET server;
664     BUFFER *line, *msg;
665     int i = 0, num = 0;
666    
667     line = buf_new();
668     msg = buf_new();
669     f = mix_openfile(POP3CONF, "r");
670     if (f != NULL)
671     while (fgets(cfg, sizeof(cfg), f) != NULL) {
672     if (strchr(cfg, '@'))
673     strchr(cfg, '@')[0] = ' ';
674     if (sscanf(cfg, "%127s %127s %127s %4s", user, host, pass, auth) < 3)
675     continue;
676     i = POP3_ANY;
677     if (strileft(auth, "apop"))
678     i = POP3_APOP;
679     if (strileft(auth, "pass"))
680     i = POP3_PASS;
681     server = pop3_open(user, host, pass, i);
682     if (server != INVALID_SOCKET) {
683     num = pop3_stat(server);
684     if (num < 0)
685     errlog(WARNING, "POP3 protocol error at %s.\n", host);
686     else if (num == 0)
687     errlog(DEBUGINFO, "No mail at %s.\n", host);
688     else
689     for (i = 1; i <= num; i++) {
690     if (POP3SIZELIMIT > 0 &&
691     pop3_list(server, i) > POP3SIZELIMIT * 1024) {
692     errlog(WARNING, "Over size message on %s.", host);
693     if (POP3DEL == 1)
694     pop3_dele(server, i);
695     } else {
696     if (pop3_retr(server, i, msg) == 0 &&
697     pool_add(msg, "inf") == 0)
698     pop3_dele(server, i);
699     else {
700     errlog(WARNING, "POP3 error while getting mail from %s.",
701     host);
702     closesocket(server);
703     goto end;
704     }
705     }
706     }
707     pop3_close(server);
708 rabbi 11 closesocket(server);
709 rabbi 1 }
710     }
711     end:
712 rabbi 11 if (f != NULL)
713     fclose(f);
714 rabbi 1 buf_free(line);
715     buf_free(msg);
716     }
717     #endif

  ViewVC Help
Powered by ViewVC 1.1.5