]> diplodocus.org Git - nmh/blob - mts/smtp/smtp.c
Added NMH_ADDL_CPPFLAGS macro in new m4/cppflags.m4, to remove
[nmh] / mts / smtp / smtp.c
1 /*
2 * smtp.c -- nmh SMTP interface
3 *
4 * This code is Copyright (c) 2002, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include "smtp.h"
11 #include <h/mts.h>
12 #include <h/signals.h>
13 #include <h/utils.h>
14 #include <h/oauth.h>
15
16 #ifdef CYRUS_SASL
17 #include <sasl/sasl.h>
18 #include <sasl/saslutil.h>
19 # if SASL_VERSION_FULL < 0x020125
20 /* Cyrus SASL 2.1.25 introduced the sasl_callback_ft prototype,
21 which has an explicit void parameter list, according to best
22 practice. So we need to cast to avoid compile warnings.
23 Provide this prototype for earlier versions. */
24 typedef int (*sasl_callback_ft)();
25 # endif /* SASL_VERSION_FULL < 0x020125 */
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30 #endif /* CYRUS_SASL */
31
32 #ifdef TLS_SUPPORT
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #endif /* TLS_SUPPORT */
36
37 /*
38 * This module implements an interface to SendMail very similar
39 * to the MMDF mm_(3) routines. The sm_() routines herein talk
40 * SMTP to a sendmail process, mapping SMTP reply codes into
41 * RP_-style codes.
42 */
43
44 /*
45 * On older 4.2BSD machines without the POSIX function `sigaction',
46 * the alarm handing stuff for time-outs will NOT work due to the way
47 * syscalls get restarted. This is not really crucial, since SendMail
48 * is generally well-behaved in this area.
49 */
50
51 #ifdef SENDMAILBUG
52 /*
53 * It appears that some versions of Sendmail will return Code 451
54 * when they don't really want to indicate a failure.
55 * "Code 451 almost always means sendmail has deferred; we don't
56 * really want bomb out at this point since sendmail will rectify
57 * things later." So, if you define SENDMAILBUG, Code 451 is
58 * considered the same as Code 250. Yuck!
59 */
60 #endif
61
62 #define TRUE 1
63 #define FALSE 0
64
65 #define NBITS ((sizeof (int)) * 8)
66
67 /*
68 * these codes must all be different!
69 */
70 #define SM_OPEN 300 /* Changed to 5 minutes to comply with a SHOULD in RFC 1123 */
71 #define SM_HELO 20
72 #define SM_RSET 15
73 #define SM_MAIL 301 /* changed to 5 minutes and a second (for uniqueness), see above */
74 #define SM_RCPT 302 /* see above */
75 #define SM_DATA 120 /* see above */
76 #define SM_TEXT 180 /* see above */
77 #define SM_DOT 600 /* see above */
78 #define SM_QUIT 30
79 #define SM_CLOS 10
80 #define SM_AUTH 45
81
82 static int sm_addrs = 0;
83 static int sm_alarmed = 0;
84 static int sm_child = NOTOK;
85 static int sm_debug = 0;
86 static int sm_nl = TRUE;
87 static int sm_verbose = 0;
88
89 static FILE *sm_rfp = NULL;
90 static FILE *sm_wfp = NULL;
91
92 static int next_line_encoded = 0;
93
94 #ifdef CYRUS_SASL
95 /*
96 * Some globals needed by SASL
97 */
98
99 static sasl_conn_t *conn = NULL; /* SASL connection state */
100 static int sasl_complete = 0; /* Has authentication succeeded? */
101 static sasl_ssf_t sasl_ssf; /* Our security strength factor */
102 static int maxoutbuf; /* Maximum crypto output buffer */
103 static char *sasl_outbuffer; /* SASL output buffer for encryption */
104 static int sasl_outbuflen; /* Current length of data in outbuf */
105 static int sm_get_user(void *, int, const char **, unsigned *);
106 static int sm_get_pass(sasl_conn_t *, void *, int, sasl_secret_t **);
107
108 static sasl_callback_t callbacks[] = {
109 { SASL_CB_USER, (sasl_callback_ft) sm_get_user, NULL },
110 #define SM_SASL_N_CB_USER 0
111 { SASL_CB_AUTHNAME, (sasl_callback_ft) sm_get_user, NULL },
112 #define SM_SASL_N_CB_AUTHNAME 1
113 { SASL_CB_PASS, (sasl_callback_ft) sm_get_pass, NULL },
114 #define SM_SASL_N_CB_PASS 2
115 { SASL_CB_LIST_END, NULL, NULL },
116 };
117
118 #else /* CYRUS_SASL */
119 int sasl_ssf = 0;
120 #endif /* CYRUS_SASL */
121
122 #ifdef TLS_SUPPORT
123 static SSL_CTX *sslctx = NULL;
124 static SSL *ssl = NULL;
125 static BIO *sbior = NULL;
126 static BIO *sbiow = NULL;
127 static BIO *io = NULL;
128
129 static int tls_negotiate(void);
130 #endif /* TLS_SUPPORT */
131
132 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
133 #define SASL_MAXRECVBUF 65536
134 static int sm_fgetc(FILE *);
135 static char *sasl_inbuffer; /* SASL input buffer for encryption */
136 static char *sasl_inptr; /* Pointer to current inbuf position */
137 static int sasl_inbuflen; /* Current length of data in inbuf */
138 #else
139 #define sm_fgetc fgetc
140 #endif
141
142 static int tls_active = 0;
143
144 static char *sm_noreply = "No reply text given";
145 static char *sm_moreply = "; ";
146 static struct smtp sm_reply;
147
148 #define MAXEHLO 20
149
150 static int doingEHLO;
151 static char *EHLOkeys[MAXEHLO + 1];
152
153 /*
154 * static prototypes
155 */
156 static int smtp_init (char *, char *, char *, int, int, int, int, int,
157 char *, char *, const char *, int);
158 static int sendmail_init (char *, char *, int, int, int, int, int,
159 char *, char *);
160
161 static int rclient (char *, char *);
162 static int sm_ierror (char *fmt, ...);
163 static int smtalk (int time, char *fmt, ...);
164 static int sm_wrecord (char *, int);
165 static int sm_wstream (char *, int);
166 static int sm_werror (void);
167 static int smhear (void);
168 static int sm_rrecord (char *, int *);
169 static int sm_rerror (int);
170 static void alrmser (int);
171 static char *EHLOset (char *);
172 static char *prepare_for_display (const char *, int *);
173 static int sm_fwrite(char *, int);
174 static int sm_fputs(char *);
175 static int sm_fputc(int);
176 static void sm_fflush(void);
177 static int sm_fgets(char *, int, FILE *);
178 static int sm_auth_xoauth2(const char *, const char *, int);
179
180 #ifdef CYRUS_SASL
181 /*
182 * Function prototypes needed for SASL
183 */
184
185 static int sm_auth_sasl(char *, int, char *, char *);
186 #endif /* CYRUS_SASL */
187
188 int
189 sm_init (char *client, char *server, char *port, int watch, int verbose,
190 int debug, int sasl, int saslssf, char *saslmech, char *user,
191 const char *oauth_svc, int tls)
192 {
193 if (sm_mts == MTS_SMTP)
194 return smtp_init (client, server, port, watch, verbose,
195 debug, sasl, saslssf, saslmech, user,
196 oauth_svc, tls);
197 else
198 return sendmail_init (client, server, watch, verbose,
199 debug, sasl, saslssf, saslmech, user);
200 }
201
202 static int
203 smtp_init (char *client, char *server, char *port, int watch, int verbose,
204 int debug,
205 int sasl, int saslssf, char *saslmech, char *user,
206 const char *oauth_svc, int tls)
207 {
208 int result, sd1, sd2;
209 #ifndef CYRUS_SASL
210 NMH_UNUSED (sasl);
211 NMH_UNUSED (saslssf);
212 NMH_UNUSED (saslmech);
213 NMH_UNUSED (user);
214 #endif /* CYRUS_SASL */
215
216 if (watch)
217 verbose = TRUE;
218
219 sm_verbose = verbose;
220 sm_debug = debug;
221
222 if (sm_rfp != NULL && sm_wfp != NULL)
223 goto send_options;
224
225 if (client == NULL || *client == '\0') {
226 if (clientname) {
227 client = clientname;
228 } else {
229 client = LocalName(1); /* no clientname -> LocalName */
230 }
231 }
232
233 /*
234 * Last-ditch check just in case client still isn't set to anything
235 */
236
237 if (client == NULL || *client == '\0')
238 client = "localhost";
239
240 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
241 sasl_inbuffer = malloc(SASL_MAXRECVBUF);
242 if (!sasl_inbuffer)
243 return sm_ierror("Unable to allocate %d bytes for read buffer",
244 SASL_MAXRECVBUF);
245 #endif /* CYRUS_SASL || TLS_SUPPORT */
246
247 if ((sd1 = rclient (server, port)) == NOTOK)
248 return RP_BHST;
249
250 if ((sd2 = dup (sd1)) == NOTOK) {
251 close (sd1);
252 return sm_ierror ("unable to dup");
253 }
254
255 SIGNAL (SIGALRM, alrmser);
256 SIGNAL (SIGPIPE, SIG_IGN);
257
258 if ((sm_rfp = fdopen (sd1, "r")) == NULL
259 || (sm_wfp = fdopen (sd2, "w")) == NULL) {
260 close (sd1);
261 close (sd2);
262 sm_rfp = sm_wfp = NULL;
263 return sm_ierror ("unable to fdopen");
264 }
265
266 tls_active = 0;
267
268 #ifdef TLS_SUPPORT
269 /*
270 * If tls == 2, that means that the user requested "initial" TLS,
271 * which happens right after the connection has opened. Do that
272 * negotiation now
273 */
274
275 if (tls == 2) {
276 result = tls_negotiate();
277
278 /*
279 * Note: if tls_negotiate() fails it will call sm_end() for us,
280 * which closes the connection.
281 */
282 if (result != RP_OK)
283 return result;
284 }
285 #endif /* TLS_SUPPORT */
286
287 sm_alarmed = 0;
288 alarm (SM_OPEN);
289 result = smhear ();
290 alarm (0);
291
292 switch (result) {
293 case 220:
294 break;
295
296 default:
297 sm_end (NOTOK);
298 return RP_RPLY;
299 }
300
301 /*
302 * Give EHLO or HELO command
303 */
304
305 doingEHLO = 1;
306 result = smtalk (SM_HELO, "EHLO %s", client);
307 doingEHLO = 0;
308
309 if (result >= 500 && result <= 599)
310 result = smtalk (SM_HELO, "HELO %s", client);
311
312 if (result != 250) {
313 sm_end (NOTOK);
314 return RP_RPLY;
315 }
316
317 #ifdef TLS_SUPPORT
318 /*
319 * If the user requested TLS support, then try to do the STARTTLS command
320 * as part of the initial dialog. Assuming this works, we then need to
321 * restart the EHLO dialog after TLS negotiation is complete.
322 */
323
324 if (tls == 1) {
325 if (! EHLOset("STARTTLS")) {
326 sm_end(NOTOK);
327 return sm_ierror("SMTP server does not support TLS");
328 }
329
330 result = smtalk(SM_HELO, "STARTTLS");
331
332 if (result != 220) {
333 sm_end(NOTOK);
334 return RP_RPLY;
335 }
336
337 /*
338 * Okay, the other side should be waiting for us to start TLS
339 * negotiation. Oblige them.
340 */
341
342 result = tls_negotiate();
343
344 if (result != RP_OK)
345 return result;
346
347 doingEHLO = 1;
348 result = smtalk (SM_HELO, "EHLO %s", client);
349 doingEHLO = 0;
350
351 if (result != 250) {
352 sm_end (NOTOK);
353 return RP_RPLY;
354 }
355 }
356 #else /* TLS_SUPPORT */
357 NMH_UNUSED (tls);
358 #endif /* TLS_SUPPORT */
359
360 #ifdef CYRUS_SASL
361 /*
362 * If the user asked for SASL, then check to see if the SMTP server
363 * supports it. Otherwise, error out (because the SMTP server
364 * might have been spoofed; we don't want to just silently not
365 * do authentication
366 */
367
368 if (sasl) {
369 char *server_mechs;
370 if (! (server_mechs = EHLOset("AUTH"))) {
371 sm_end(NOTOK);
372 return sm_ierror("SMTP server does not support SASL");
373 }
374
375 if (saslmech && stringdex(saslmech, server_mechs) == -1) {
376 sm_end(NOTOK);
377 return sm_ierror("Requested SASL mech \"%s\" is not in the "
378 "list of supported mechanisms:\n%s",
379 saslmech, server_mechs);
380 }
381
382 /* Don't call sm_auth_sasl() for XAUTH2 with -sasl. Instead, call
383 sm_auth_xoauth2() below. */
384 if (oauth_svc == NULL &&
385 sm_auth_sasl(user, saslssf, saslmech ? saslmech : server_mechs,
386 server) != RP_OK) {
387 sm_end(NOTOK);
388 return NOTOK;
389 }
390 }
391 #endif /* CYRUS_SASL */
392
393 if (oauth_svc != NULL) {
394 char *server_mechs;
395 if ((server_mechs = EHLOset("AUTH")) == NULL
396 || stringdex("XOAUTH2", server_mechs) == -1) {
397 sm_end(NOTOK);
398 return sm_ierror("SMTP server does not support SASL XOAUTH2");
399 }
400 if (sm_auth_xoauth2(user, oauth_svc, debug) != RP_OK) {
401 sm_end(NOTOK);
402 return NOTOK;
403 }
404 }
405
406 send_options: ;
407 if (watch && EHLOset ("XVRB"))
408 smtalk (SM_HELO, "VERB on");
409
410 return RP_OK;
411 }
412
413 int
414 sendmail_init (char *client, char *server, int watch, int verbose,
415 int debug, int sasl, int saslssf, char *saslmech, char *user)
416 {
417 unsigned int i, result, vecp;
418 int pdi[2], pdo[2];
419 char *vec[15];
420 #ifdef CYRUS_SASL
421 char *server_mechs;
422 #else /* CYRUS_SASL */
423 NMH_UNUSED (server);
424 NMH_UNUSED (sasl);
425 NMH_UNUSED (saslssf);
426 NMH_UNUSED (saslmech);
427 NMH_UNUSED (user);
428 #endif /* CYRUS_SASL */
429
430 if (watch)
431 verbose = TRUE;
432
433 sm_verbose = verbose;
434 sm_debug = debug;
435 if (sm_rfp != NULL && sm_wfp != NULL)
436 return RP_OK;
437
438 if (client == NULL || *client == '\0') {
439 if (clientname)
440 client = clientname;
441 else
442 client = LocalName(1); /* no clientname -> LocalName */
443 }
444
445 /*
446 * Last-ditch check just in case client still isn't set to anything
447 */
448
449 if (client == NULL || *client == '\0')
450 client = "localhost";
451
452 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
453 sasl_inbuffer = malloc(SASL_MAXRECVBUF);
454 if (!sasl_inbuffer)
455 return sm_ierror("Unable to allocate %d bytes for read buffer",
456 SASL_MAXRECVBUF);
457 #endif /* CYRUS_SASL || TLS_SUPPORT */
458
459 if (pipe (pdi) == NOTOK)
460 return sm_ierror ("no pipes");
461 if (pipe (pdo) == NOTOK) {
462 close (pdi[0]);
463 close (pdi[1]);
464 return sm_ierror ("no pipes");
465 }
466
467 for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++)
468 sleep (5);
469
470 switch (sm_child) {
471 case NOTOK:
472 close (pdo[0]);
473 close (pdo[1]);
474 close (pdi[0]);
475 close (pdi[1]);
476 return sm_ierror ("unable to fork");
477
478 case OK:
479 if (pdo[0] != fileno (stdin))
480 dup2 (pdo[0], fileno (stdin));
481 if (pdi[1] != fileno (stdout))
482 dup2 (pdi[1], fileno (stdout));
483 if (pdi[1] != fileno (stderr))
484 dup2 (pdi[1], fileno (stderr));
485 for (i = fileno (stderr) + 1; i < NBITS; i++)
486 close (i);
487
488 vecp = 0;
489 vec[vecp++] = r1bindex (sendmail, '/');
490 vec[vecp++] = "-bs";
491 vec[vecp++] = watch ? "-odi" : "-odb";
492 vec[vecp++] = "-oem";
493 vec[vecp++] = "-om";
494 if (verbose)
495 vec[vecp++] = "-ov";
496 vec[vecp++] = NULL;
497
498 execvp (sendmail, vec);
499 fprintf (stderr, "unable to exec ");
500 perror (sendmail);
501 _exit (-1); /* NOTREACHED */
502
503 default:
504 SIGNAL (SIGALRM, alrmser);
505 SIGNAL (SIGPIPE, SIG_IGN);
506
507 close (pdi[1]);
508 close (pdo[0]);
509 if ((sm_rfp = fdopen (pdi[0], "r")) == NULL
510 || (sm_wfp = fdopen (pdo[1], "w")) == NULL) {
511 close (pdi[0]);
512 close (pdo[1]);
513 sm_rfp = sm_wfp = NULL;
514 return sm_ierror ("unable to fdopen");
515 }
516 sm_alarmed = 0;
517 alarm (SM_OPEN);
518 result = smhear ();
519 alarm (0);
520 switch (result) {
521 case 220:
522 break;
523
524 default:
525 sm_end (NOTOK);
526 return RP_RPLY;
527 }
528
529 doingEHLO = 1;
530 result = smtalk (SM_HELO, "EHLO %s", client);
531 doingEHLO = 0;
532
533 if (500 <= result && result <= 599)
534 result = smtalk (SM_HELO, "HELO %s", client);
535
536 switch (result) {
537 case 250:
538 break;
539
540 default:
541 sm_end (NOTOK);
542 return RP_RPLY;
543 }
544
545 #ifdef CYRUS_SASL
546 /*
547 * If the user asked for SASL, then check to see if the SMTP server
548 * supports it. Otherwise, error out (because the SMTP server
549 * might have been spoofed; we don't want to just silently not
550 * do authentication
551 */
552
553 if (sasl) {
554 if (! (server_mechs = EHLOset("AUTH"))) {
555 sm_end(NOTOK);
556 return sm_ierror("SMTP server does not support SASL");
557 }
558
559 if (saslmech && stringdex(saslmech, server_mechs) == -1) {
560 sm_end(NOTOK);
561 return sm_ierror("Requested SASL mech \"%s\" is not in the "
562 "list of supported mechanisms:\n%s",
563 saslmech, server_mechs);
564 }
565
566 if (sm_auth_sasl(user, saslssf, saslmech ? saslmech : server_mechs,
567 server) != RP_OK) {
568 sm_end(NOTOK);
569 return NOTOK;
570 }
571 }
572 #endif /* CYRUS_SASL */
573
574 if (watch)
575 smtalk (SM_HELO, "VERB on");
576
577 return RP_OK;
578 }
579 }
580
581 static int
582 rclient (char *server, char *service)
583 {
584 int sd;
585 char response[BUFSIZ];
586
587 if ((sd = client (server, service, response, sizeof(response),
588 sm_debug)) != NOTOK)
589 return sd;
590
591 sm_ierror ("%s", response);
592 return NOTOK;
593 }
594
595 int
596 sm_winit (char *from)
597 {
598 switch (smtalk (SM_MAIL, "MAIL FROM:<%s>", from)) {
599 case 250:
600 sm_addrs = 0;
601 return RP_OK;
602
603 case 500:
604 case 501:
605 case 552:
606 return RP_PARM;
607
608 default:
609 return RP_RPLY;
610 }
611 }
612
613
614 int
615 sm_wadr (char *mbox, char *host, char *path)
616 {
617 switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@%s>"
618 : "RCPT TO:<%s%s>",
619 path ? path : "", mbox, host)) {
620 case 250:
621 case 251:
622 sm_addrs++;
623 return RP_OK;
624
625 case 451:
626 #ifdef SENDMAILBUG
627 sm_addrs++;
628 return RP_OK;
629 #endif /* SENDMAILBUG */
630 case 421:
631 case 450:
632 case 452:
633 return RP_NO;
634
635 case 500:
636 case 501:
637 return RP_PARM;
638
639 case 550:
640 case 551:
641 case 552:
642 case 553:
643 return RP_USER;
644
645 default:
646 return RP_RPLY;
647 }
648 }
649
650
651 int
652 sm_waend (void)
653 {
654 switch (smtalk (SM_DATA, "DATA")) {
655 case 354:
656 sm_nl = TRUE;
657 return RP_OK;
658
659 case 451:
660 #ifdef SENDMAILBUG
661 sm_nl = TRUE;
662 return RP_OK;
663 #endif /* SENDMAILBUG */
664 case 421:
665 return RP_NO;
666
667 case 500:
668 case 501:
669 case 503:
670 case 554:
671 return RP_NDEL;
672
673 default:
674 return RP_RPLY;
675 }
676 }
677
678
679 int
680 sm_wtxt (char *buffer, int len)
681 {
682 int result;
683
684 sm_alarmed = 0;
685 alarm (SM_TEXT);
686 result = sm_wstream (buffer, len);
687 alarm (0);
688
689 return (result == NOTOK ? RP_BHST : RP_OK);
690 }
691
692
693 int
694 sm_wtend (void)
695 {
696 if (sm_wstream ((char *) NULL, 0) == NOTOK)
697 return RP_BHST;
698
699 switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) {
700 case 250:
701 case 251:
702 return RP_OK;
703
704 case 451:
705 #ifdef SENDMAILBUG
706 return RP_OK;
707 #endif /* SENDMAILBUG */
708 case 452:
709 default:
710 return RP_NO;
711
712 case 552:
713 case 554:
714 return RP_NDEL;
715 }
716 }
717
718
719 int
720 sm_end (int type)
721 {
722 int status;
723 struct smtp sm_note;
724
725 if (sm_mts == MTS_SENDMAIL_SMTP) {
726 switch (sm_child) {
727 case NOTOK:
728 case OK:
729 return RP_OK;
730
731 default:
732 break;
733 }
734 }
735
736 if (sm_rfp == NULL && sm_wfp == NULL)
737 return RP_OK;
738
739 switch (type) {
740 case OK:
741 smtalk (SM_QUIT, "QUIT");
742 break;
743
744 case NOTOK:
745 sm_note.code = sm_reply.code;
746 sm_note.length = sm_reply.length;
747 memcpy (sm_note.text, sm_reply.text, sm_reply.length + 1);/* fall */
748 case DONE:
749 if (smtalk (SM_RSET, "RSET") == 250 && type == DONE)
750 return RP_OK;
751 if (sm_mts == MTS_SMTP)
752 smtalk (SM_QUIT, "QUIT");
753 else {
754 /* The SIGPIPE block replaces old calls to discard ().
755 We're not sure what the discard () calls were for,
756 maybe to prevent deadlock on old systems. In any
757 case, blocking SIGPIPE should be harmless.
758 Because the file handles are closed below, leave it
759 blocked. */
760 sigset_t set, oset;
761 sigemptyset (&set);
762 sigaddset (&set, SIGPIPE);
763 sigprocmask (SIG_BLOCK, &set, &oset);
764
765 kill (sm_child, SIGKILL);
766 sm_child = NOTOK;
767 }
768 if (type == NOTOK) {
769 sm_reply.code = sm_note.code;
770 sm_reply.length = sm_note.length;
771 memcpy (sm_reply.text, sm_note.text, sm_note.length + 1);
772 }
773 break;
774 }
775
776 #ifdef TLS_SUPPORT
777 if (tls_active) {
778 BIO_ssl_shutdown(io);
779 BIO_free_all(io);
780 }
781 #endif /* TLS_SUPPORT */
782
783 if (sm_rfp != NULL) {
784 alarm (SM_CLOS);
785 fclose (sm_rfp);
786 alarm (0);
787 }
788 if (sm_wfp != NULL) {
789 alarm (SM_CLOS);
790 fclose (sm_wfp);
791 alarm (0);
792 }
793
794 if (sm_mts == MTS_SMTP) {
795 status = 0;
796 #ifdef CYRUS_SASL
797 if (conn) {
798 sasl_dispose(&conn);
799 if (sasl_outbuffer) {
800 free(sasl_outbuffer);
801 }
802 }
803 if (sasl_inbuffer)
804 free(sasl_inbuffer);
805 #endif /* CYRUS_SASL */
806 } else if (sm_child != NOTOK) {
807 status = pidwait (sm_child, OK);
808 sm_child = NOTOK;
809 } else {
810 status = OK;
811 }
812
813 sm_rfp = sm_wfp = NULL;
814 return (status ? RP_BHST : RP_OK);
815 }
816
817 #ifdef CYRUS_SASL
818 /*
819 * This function implements SASL authentication for SMTP. If this function
820 * completes successfully, then authentication is successful and we've
821 * (optionally) negotiated a security layer.
822 */
823
824 #define CHECKB64SIZE(insize, outbuf, outsize) \
825 { size_t wantout = (((insize + 2) / 3) * 4) + 32; \
826 if (wantout > outsize) { \
827 outbuf = mh_xrealloc(outbuf, outsize = wantout); \
828 } \
829 }
830
831 static int
832 sm_auth_sasl(char *user, int saslssf, char *mechlist, char *inhost)
833 {
834 int result, status;
835 unsigned int buflen, outlen;
836 char *buf, *outbuf = NULL, host[NI_MAXHOST];
837 const char *chosen_mech;
838 sasl_security_properties_t secprops;
839 sasl_ssf_t *ssf;
840 int *outbufmax;
841 struct nmh_creds creds = { 0, 0, 0 };
842 size_t outbufsize = 0;
843
844 /*
845 * Initialize the callback contexts
846 */
847
848 /*
849 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
850 * to us on the command line, then call getpeername and do a
851 * reverse-address lookup on the IP address to get the name.
852 */
853
854 memset(host, 0, sizeof(host));
855
856 if (!inhost) {
857 struct sockaddr_storage sin;
858 socklen_t len = sizeof(sin);
859 int result;
860
861 if (getpeername(fileno(sm_wfp), (struct sockaddr *) &sin, &len) < 0) {
862 sm_ierror("getpeername on SMTP socket failed: %s",
863 strerror(errno));
864 return NOTOK;
865 }
866
867 result = getnameinfo((struct sockaddr *) &sin, len, host, sizeof(host),
868 NULL, 0, NI_NAMEREQD);
869 if (result != 0) {
870 sm_ierror("Unable to look up name of connected host: %s",
871 gai_strerror(result));
872 return NOTOK;
873 }
874 } else {
875 strncpy(host, inhost, sizeof(host) - 1);
876 }
877
878 /* It's OK to copy the addresses here. The callbacks that use
879 them will only be called before this function returns. */
880 creds.host = host;
881 creds.user = user;
882 callbacks[SM_SASL_N_CB_USER].context = &creds;
883 callbacks[SM_SASL_N_CB_AUTHNAME].context = &creds;
884 callbacks[SM_SASL_N_CB_PASS].context = &creds;
885
886 result = sasl_client_init(callbacks);
887
888 if (result != SASL_OK) {
889 sm_ierror("SASL library initialization failed: %s",
890 sasl_errstring(result, NULL, NULL));
891 return NOTOK;
892 }
893
894 result = sasl_client_new("smtp", host, NULL, NULL, NULL, 0, &conn);
895
896 if (result != SASL_OK) {
897 sm_ierror("SASL client initialization failed: %s",
898 sasl_errstring(result, NULL, NULL));
899 return NOTOK;
900 }
901
902 /*
903 * Initialize the security properties. But if TLS is active, then
904 * don't negotiate encryption here.
905 */
906
907 memset(&secprops, 0, sizeof(secprops));
908 secprops.maxbufsize = SASL_MAXRECVBUF;
909 secprops.max_ssf =
910 tls_active ? 0 : (saslssf != -1 ? (unsigned int) saslssf : UINT_MAX);
911
912 result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
913
914 if (result != SASL_OK) {
915 sm_ierror("SASL security property initialization failed: %s",
916 sasl_errstring(result, NULL, NULL));
917 return NOTOK;
918 }
919
920 /*
921 * Start the actual protocol. Feed the mech list into the library
922 * and get out a possible initial challenge
923 */
924
925 result = sasl_client_start(conn, mechlist, NULL, (const char **) &buf,
926 &buflen, (const char **) &chosen_mech);
927
928 if (result != SASL_OK && result != SASL_CONTINUE) {
929 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn));
930 return NOTOK;
931 }
932
933 /*
934 * If we got an initial challenge, send it as part of the AUTH
935 * command; otherwise, just send a plain AUTH command.
936 */
937
938 if (buflen) {
939 CHECKB64SIZE(buflen, outbuf, outbufsize);
940 status = sasl_encode64(buf, buflen, outbuf, outbufsize, NULL);
941 if (status != SASL_OK) {
942 sm_ierror("SASL base64 encode failed: %s",
943 sasl_errstring(status, NULL, NULL));
944 if (outbuf)
945 free(outbuf);
946 return NOTOK;
947 }
948
949 status = smtalk(SM_AUTH, "AUTH %s %s", chosen_mech, outbuf);
950 } else
951 status = smtalk(SM_AUTH, "AUTH %s", chosen_mech);
952
953 /*
954 * Now we loop until we either fail, get a SASL_OK, or a 235
955 * response code. Receive the challenges and process them until
956 * we're all done.
957 */
958
959 while (result == SASL_CONTINUE) {
960
961 /*
962 * If we get a 235 response, that means authentication has
963 * succeeded and we need to break out of the loop (yes, even if
964 * we still get SASL_CONTINUE from sasl_client_step()).
965 *
966 * Otherwise, if we get a message that doesn't seem to be a
967 * valid response, then abort
968 */
969
970 if (status == 235)
971 break;
972 else if (status < 300 || status > 399) {
973 if (outbuf)
974 free(outbuf);
975 return RP_BHST;
976 }
977
978 /*
979 * Special case; a zero-length response from the SMTP server
980 * is returned as a single =. If we get that, then set buflen
981 * to be zero. Otherwise, just decode the response.
982 */
983
984 if (strcmp("=", sm_reply.text) == 0) {
985 outlen = 0;
986 } else {
987 if (sm_reply.length > (int) outbufsize) {
988 outbuf = mh_xrealloc(outbuf, outbufsize = sm_reply.length);
989 }
990
991 result = sasl_decode64(sm_reply.text, sm_reply.length,
992 outbuf, outbufsize, &outlen);
993 if (result != SASL_OK) {
994 smtalk(SM_AUTH, "*");
995 sm_ierror("SASL base64 decode failed: %s",
996 sasl_errstring(result, NULL, NULL));
997 if (outbuf)
998 free(outbuf);
999 return NOTOK;
1000 }
1001 }
1002
1003 result = sasl_client_step(conn, outbuf, outlen, NULL,
1004 (const char **) &buf, &buflen);
1005
1006 if (result != SASL_OK && result != SASL_CONTINUE) {
1007 smtalk(SM_AUTH, "*");
1008 sm_ierror("SASL client negotiation failed: %s",
1009 sasl_errstring(result, NULL, NULL));
1010 if (outbuf)
1011 free(outbuf);
1012 return NOTOK;
1013 }
1014
1015 CHECKB64SIZE(buflen, outbuf, outbufsize);
1016 status = sasl_encode64(buf, buflen, outbuf, outbufsize, NULL);
1017
1018 if (status != SASL_OK) {
1019 smtalk(SM_AUTH, "*");
1020 sm_ierror("SASL base64 encode failed: %s",
1021 sasl_errstring(status, NULL, NULL));
1022 if (outbuf)
1023 free(outbuf);
1024 return NOTOK;
1025 }
1026
1027 status = smtalk(SM_AUTH, outbuf);
1028 }
1029
1030 if (outbuf)
1031 free(outbuf);
1032
1033 /*
1034 * Make sure that we got the correct response
1035 */
1036
1037 if (status < 200 || status > 299)
1038 return RP_BHST;
1039
1040 /*
1041 * We _should_ have completed the authentication successfully.
1042 * Get a few properties from the authentication exchange.
1043 */
1044
1045 result = sasl_getprop(conn, SASL_MAXOUTBUF, (const void **) &outbufmax);
1046
1047 if (result != SASL_OK) {
1048 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
1049 sasl_errstring(result, NULL, NULL));
1050 return NOTOK;
1051 }
1052
1053 maxoutbuf = *outbufmax;
1054
1055 result = sasl_getprop(conn, SASL_SSF, (const void **) &ssf);
1056
1057 sasl_ssf = *ssf;
1058
1059 if (result != SASL_OK) {
1060 sm_ierror("Cannot retrieve SASL negotiated security strength "
1061 "factor: %s", sasl_errstring(result, NULL, NULL));
1062 return NOTOK;
1063 }
1064
1065 if (sasl_ssf > 0) {
1066 sasl_outbuffer = malloc(maxoutbuf);
1067
1068 if (sasl_outbuffer == NULL) {
1069 sm_ierror("Unable to allocate %d bytes for SASL output "
1070 "buffer", maxoutbuf);
1071 return NOTOK;
1072 }
1073 sasl_outbuflen = 0;
1074 sasl_inbuflen = 0;
1075 sasl_inptr = sasl_inbuffer;
1076 } else {
1077 sasl_outbuffer = NULL;
1078 /* Don't NULL out sasl_inbuffer because it could be used in
1079 sm_fgetc (). */
1080 }
1081
1082 sasl_complete = 1;
1083
1084 return RP_OK;
1085 }
1086
1087 /*
1088 * Our callback functions to feed data to the SASL library
1089 */
1090
1091 static int
1092 sm_get_user(void *context, int id, const char **result, unsigned *len)
1093 {
1094 nmh_creds_t creds = (nmh_creds_t) context;
1095
1096 if (! result || ((id != SASL_CB_USER) && (id != SASL_CB_AUTHNAME)))
1097 return SASL_BADPARAM;
1098
1099 if (creds->user == NULL) {
1100 /*
1101 * Pass the 1 third argument to nmh_get_credentials() so
1102 * that a default user if the -user switch to send(1)/post(8)
1103 * wasn't used, and so that a default password will be supplied.
1104 * That's used when those values really don't matter, and only
1105 * with legacy/.netrc, i.e., with a credentials profile entry.
1106 */
1107 if (nmh_get_credentials (creds->host, creds->user, 1, creds) != OK) {
1108 return SASL_BADPARAM;
1109 }
1110 }
1111
1112 *result = creds->user;
1113 if (len)
1114 *len = strlen(creds->user);
1115
1116 return SASL_OK;
1117 }
1118
1119 static int
1120 sm_get_pass(sasl_conn_t *conn, void *context, int id,
1121 sasl_secret_t **psecret)
1122 {
1123 nmh_creds_t creds = (nmh_creds_t) context;
1124 int len;
1125
1126 NMH_UNUSED (conn);
1127
1128 if (! psecret || id != SASL_CB_PASS)
1129 return SASL_BADPARAM;
1130
1131 if (creds->password == NULL) {
1132 /*
1133 * Pass the 0 third argument to nmh_get_credentials() so
1134 * that the default password isn't used. With legacy/.netrc
1135 * credentials support, we'll only get here if the -user
1136 * switch to send(1)/post(8) wasn't used.
1137 */
1138 if (nmh_get_credentials (creds->host, creds->user, 0, creds) != OK) {
1139 return SASL_BADPARAM;
1140 }
1141 }
1142
1143 len = strlen (creds->password);
1144
1145 if (! (*psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len))) {
1146 return SASL_NOMEM;
1147 }
1148
1149 (*psecret)->len = len;
1150 strcpy((char *) (*psecret)->data, creds->password);
1151
1152 return SASL_OK;
1153 }
1154 #endif /* CYRUS_SASL */
1155
1156 /* https://developers.google.com/gmail/xoauth2_protocol */
1157 static int
1158 sm_auth_xoauth2(const char *user, const char *oauth_svc, int snoop)
1159 {
1160 const char *xoauth_client_res;
1161 int status;
1162
1163 #ifdef OAUTH_SUPPORT
1164 xoauth_client_res = mh_oauth_do_xoauth(user, oauth_svc,
1165 snoop ? stderr : NULL);
1166
1167 if (xoauth_client_res == NULL) {
1168 return sm_ierror("Internal error: mh_oauth_do_xoauth() returned NULL");
1169 }
1170 #else
1171 NMH_UNUSED(user);
1172 NMH_UNUSED(snoop);
1173 adios(NULL, "sendfrom built without OAUTH_SUPPORT, "
1174 "so oauth_svc %s is not supported", oauth_svc);
1175 #endif /* OAUTH_SUPPORT */
1176
1177 status = smtalk(SM_AUTH, "AUTH XOAUTH2 %s", xoauth_client_res);
1178 if (status == 235) {
1179 /* It worked! */
1180 return RP_OK;
1181 }
1182
1183 /*
1184 * Status is 334 and sm_reply.text contains base64-encoded JSON. As far as
1185 * epg can tell, no matter the error, the JSON is always the same:
1186 * {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
1187 * I tried these errors:
1188 * - garbage token
1189 * - expired token
1190 * - wrong scope
1191 * - wrong username
1192 */
1193 /* Then we're supposed to send an empty response ("\r\n"). */
1194 smtalk(SM_AUTH, "");
1195 /*
1196 * And now we always get this, again, no matter the error:
1197 * 535-5.7.8 Username and Password not accepted. Learn more at
1198 * 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257
1199 */
1200 return RP_BHST;
1201 }
1202
1203 static int
1204 sm_ierror (char *fmt, ...)
1205 {
1206 va_list ap;
1207
1208 va_start(ap, fmt);
1209 vsnprintf (sm_reply.text, sizeof(sm_reply.text), fmt, ap);
1210 va_end(ap);
1211
1212 sm_reply.length = strlen (sm_reply.text);
1213 sm_reply.code = NOTOK;
1214
1215 return RP_BHST;
1216 }
1217
1218 static int
1219 smtalk (int time, char *fmt, ...)
1220 {
1221 va_list ap;
1222 int result;
1223 char *buffer;
1224 size_t bufsize = BUFSIZ;
1225
1226 buffer = mh_xmalloc(bufsize);
1227
1228 va_start(ap, fmt);
1229 result = vsnprintf (buffer, bufsize, fmt, ap);
1230 va_end(ap);
1231
1232 if (result > (int) bufsize) {
1233 buffer = mh_xrealloc(buffer, bufsize = result + 1);
1234 va_start(ap, fmt);
1235 vsnprintf (buffer, bufsize, fmt, ap);
1236 va_end(ap);
1237 }
1238
1239 if (sm_debug) {
1240 char *decoded_buffer =
1241 prepare_for_display (buffer, &next_line_encoded);
1242
1243 if (sasl_ssf)
1244 printf("(sasl-encrypted) ");
1245 if (tls_active)
1246 printf("(tls-encrypted) ");
1247 printf ("=> %s\n", decoded_buffer);
1248 free (decoded_buffer);
1249 fflush (stdout);
1250 }
1251
1252 sm_alarmed = 0;
1253 alarm ((unsigned) time);
1254 if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK)
1255 result = smhear ();
1256 alarm (0);
1257
1258 free(buffer);
1259
1260 return result;
1261 }
1262
1263
1264 /*
1265 * write the buffer to the open SMTP channel
1266 */
1267
1268 static int
1269 sm_wrecord (char *buffer, int len)
1270 {
1271 if (sm_wfp == NULL)
1272 return sm_werror ();
1273
1274 sm_fwrite (buffer, len);
1275 sm_fputs ("\r\n");
1276 sm_fflush ();
1277
1278 return (ferror (sm_wfp) ? sm_werror () : OK);
1279 }
1280
1281
1282 static int
1283 sm_wstream (char *buffer, int len)
1284 {
1285 char *bp;
1286 static char lc = '\0';
1287
1288 if (sm_wfp == NULL)
1289 return sm_werror ();
1290
1291 if (buffer == NULL && len == 0) {
1292 if (lc != '\n')
1293 sm_fputs ("\r\n");
1294 lc = '\0';
1295 return (ferror (sm_wfp) ? sm_werror () : OK);
1296 }
1297
1298 for (bp = buffer; bp && len > 0; bp++, len--) {
1299 switch (*bp) {
1300 case '\n':
1301 sm_nl = TRUE;
1302 sm_fputc ('\r');
1303 break;
1304
1305 case '.':
1306 if (sm_nl)
1307 sm_fputc ('.');/* FALL THROUGH */
1308 default:
1309 sm_nl = FALSE;
1310 }
1311 sm_fputc (*bp);
1312 if (ferror (sm_wfp))
1313 return sm_werror ();
1314 }
1315
1316 if (bp > buffer)
1317 lc = *--bp;
1318 return (ferror (sm_wfp) ? sm_werror () : OK);
1319 }
1320
1321 /*
1322 * Write out to the network, but do buffering for SASL (if enabled)
1323 */
1324
1325 static int
1326 sm_fwrite(char *buffer, int len)
1327 {
1328 #ifdef CYRUS_SASL
1329 const char *output;
1330 unsigned int outputlen;
1331
1332 if (sasl_complete == 0 || sasl_ssf == 0) {
1333 #endif /* CYRUS_SASL */
1334 #ifdef TLS_SUPPORT
1335 if (tls_active) {
1336 int ret;
1337
1338 ret = BIO_write(io, buffer, len);
1339
1340 if (ret <= 0) {
1341 sm_ierror("TLS error during write: %s",
1342 ERR_error_string(ERR_get_error(), NULL));
1343 return NOTOK;
1344 }
1345 } else
1346 #endif /* TLS_SUPPORT */
1347 if ((int) fwrite(buffer, sizeof(*buffer), len, sm_wfp) < len) {
1348 advise ("sm_fwrite", "fwrite");
1349 }
1350 #ifdef CYRUS_SASL
1351 } else {
1352 while (len >= maxoutbuf - sasl_outbuflen) {
1353 memcpy(sasl_outbuffer + sasl_outbuflen, buffer,
1354 maxoutbuf - sasl_outbuflen);
1355 len -= maxoutbuf - sasl_outbuflen;
1356 sasl_outbuflen = 0;
1357
1358 if (sasl_encode(conn, sasl_outbuffer, maxoutbuf,
1359 &output, &outputlen) != SASL_OK) {
1360 sm_ierror("Unable to SASL encode connection data: %s",
1361 sasl_errdetail(conn));
1362 return NOTOK;
1363 }
1364
1365 if (fwrite(output, sizeof(*output), outputlen, sm_wfp) <
1366 outputlen) {
1367 advise ("sm_fwrite", "fwrite");
1368 }
1369 }
1370
1371 if (len > 0) {
1372 memcpy(sasl_outbuffer + sasl_outbuflen, buffer, len);
1373 sasl_outbuflen += len;
1374 }
1375 }
1376 #endif /* CYRUS_SASL */
1377 return ferror(sm_wfp) ? NOTOK : RP_OK;
1378 }
1379
1380 #ifdef TLS_SUPPORT
1381 /*
1382 * Negotiate Transport Layer Security
1383 */
1384
1385 static int
1386 tls_negotiate(void)
1387 {
1388 BIO *ssl_bio;
1389
1390 if (! sslctx) {
1391 const SSL_METHOD *method;
1392
1393 SSL_library_init();
1394 SSL_load_error_strings();
1395
1396 method = TLSv1_client_method(); /* Not sure about this */
1397
1398 /* Older ssl takes a non-const arg. */
1399 sslctx = SSL_CTX_new((SSL_METHOD *) method);
1400
1401 if (! sslctx) {
1402 sm_end(NOTOK);
1403 return sm_ierror("Unable to initialize OpenSSL context: %s",
1404 ERR_error_string(ERR_get_error(), NULL));
1405 }
1406 }
1407
1408 ssl = SSL_new(sslctx);
1409
1410 if (! ssl) {
1411 sm_end(NOTOK);
1412 return sm_ierror("Unable to create SSL connection: %s",
1413 ERR_error_string(ERR_get_error(), NULL));
1414 }
1415
1416 sbior = BIO_new_socket(fileno(sm_rfp), BIO_NOCLOSE);
1417 sbiow = BIO_new_socket(fileno(sm_wfp), BIO_NOCLOSE);
1418
1419 if (sbior == NULL || sbiow == NULL) {
1420 sm_end(NOTOK);
1421 return sm_ierror("Unable to create BIO endpoints: %s",
1422 ERR_error_string(ERR_get_error(), NULL));
1423 }
1424
1425 SSL_set_bio(ssl, sbior, sbiow);
1426 SSL_set_connect_state(ssl);
1427
1428 /*
1429 * Set up a BIO to handle buffering for us
1430 */
1431
1432 io = BIO_new(BIO_f_buffer());
1433
1434 if (! io) {
1435 sm_end(NOTOK);
1436 return sm_ierror("Unable to create a buffer BIO: %s",
1437 ERR_error_string(ERR_get_error(), NULL));
1438 }
1439
1440 ssl_bio = BIO_new(BIO_f_ssl());
1441
1442 if (! ssl_bio) {
1443 sm_end(NOTOK);
1444 return sm_ierror("Unable to create a SSL BIO: %s",
1445 ERR_error_string(ERR_get_error(), NULL));
1446 }
1447
1448 BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
1449 BIO_push(io, ssl_bio);
1450
1451 /*
1452 * Try doing the handshake now
1453 */
1454
1455 if (BIO_do_handshake(io) < 1) {
1456 sm_end(NOTOK);
1457 return sm_ierror("Unable to negotiate SSL connection: %s",
1458 ERR_error_string(ERR_get_error(), NULL));
1459 }
1460
1461 if (sm_debug) {
1462 const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
1463 printf("SSL negotiation successful: %s(%d) %s\n",
1464 SSL_CIPHER_get_name(cipher),
1465 SSL_CIPHER_get_bits(cipher, NULL),
1466 SSL_CIPHER_get_version(cipher));
1467
1468 }
1469
1470 tls_active = 1;
1471
1472 return RP_OK;
1473 }
1474 #endif /* TLS_SUPPORT */
1475
1476 /*
1477 * Convenience functions to replace occurrences of fputs() and fputc()
1478 */
1479
1480 static int
1481 sm_fputs(char *buffer)
1482 {
1483 return sm_fwrite(buffer, strlen(buffer));
1484 }
1485
1486 static int
1487 sm_fputc(int c)
1488 {
1489 char h = c;
1490
1491 return sm_fwrite(&h, 1);
1492 }
1493
1494 /*
1495 * Flush out any pending data on the connection
1496 */
1497
1498 static void
1499 sm_fflush(void)
1500 {
1501 #ifdef CYRUS_SASL
1502 const char *output;
1503 unsigned int outputlen;
1504 int result;
1505
1506 if (sasl_complete == 1 && sasl_ssf > 0 && sasl_outbuflen > 0) {
1507 result = sasl_encode(conn, sasl_outbuffer, sasl_outbuflen,
1508 &output, &outputlen);
1509 if (result != SASL_OK) {
1510 sm_ierror("Unable to SASL encode connection data: %s",
1511 sasl_errdetail(conn));
1512 return;
1513 }
1514
1515 if (fwrite(output, sizeof(*output), outputlen, sm_wfp) < outputlen) {
1516 advise ("sm_fflush", "fwrite");
1517 }
1518 sasl_outbuflen = 0;
1519 }
1520 #endif /* CYRUS_SASL */
1521
1522 #ifdef TLS_SUPPORT
1523 if (tls_active) {
1524 (void) BIO_flush(io);
1525 }
1526 #endif /* TLS_SUPPORT */
1527
1528 fflush(sm_wfp);
1529 }
1530
1531 static int
1532 sm_werror (void)
1533 {
1534 sm_reply.length =
1535 strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened"
1536 : sm_alarmed ? "write to socket timed out"
1537 : "error writing to socket"));
1538
1539 return (sm_reply.code = NOTOK);
1540 }
1541
1542
1543 static int
1544 smhear (void)
1545 {
1546 int i, code, cont, bc = 0, rc, more;
1547 unsigned char *bp;
1548 char *rp;
1549 char **ehlo = EHLOkeys, buffer[BUFSIZ];
1550
1551 if (doingEHLO) {
1552 static int at_least_once = 0;
1553
1554 if (at_least_once) {
1555 char *ep;
1556
1557 for (ehlo = EHLOkeys; *ehlo; ehlo++) {
1558 ep = *ehlo;
1559 free (ep);
1560 }
1561 } else {
1562 at_least_once = 1;
1563 }
1564
1565 ehlo = EHLOkeys;
1566 *ehlo = NULL;
1567 }
1568
1569 again: ;
1570
1571 sm_reply.length = 0;
1572 sm_reply.text[0] = 0;
1573 rp = sm_reply.text;
1574 rc = sizeof(sm_reply.text) - 1;
1575
1576 for (more = FALSE; sm_rrecord ((char *) (bp = (unsigned char *) buffer),
1577 &bc) != NOTOK ; ) {
1578 if (sm_debug) {
1579 char *decoded_buffer =
1580 prepare_for_display (buffer, &next_line_encoded);
1581
1582 if (sasl_ssf > 0)
1583 printf("(sasl-decrypted) ");
1584 if (tls_active)
1585 printf("(tls-decrypted) ");
1586 printf ("<= %s\n", decoded_buffer);
1587 free (decoded_buffer);
1588 fflush (stdout);
1589 }
1590
1591 if (doingEHLO
1592 && strncmp (buffer, "250", sizeof("250") - 1) == 0
1593 && (buffer[3] == '-' || doingEHLO == 2)
1594 && buffer[4]) {
1595 if (doingEHLO == 2) {
1596 if ((*ehlo = malloc ((size_t) (strlen (buffer + 4) + 1)))) {
1597 strcpy (*ehlo++, buffer + 4);
1598 *ehlo = NULL;
1599 if (ehlo >= EHLOkeys + MAXEHLO)
1600 doingEHLO = 0;
1601 }
1602 else
1603 doingEHLO = 0;
1604 }
1605 else
1606 doingEHLO = 2;
1607 }
1608
1609 for (; bc > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, bc--)
1610 continue;
1611
1612 cont = FALSE;
1613 code = atoi ((char *) bp);
1614 bp += 3, bc -= 3;
1615 for (; bc > 0 && isspace (*bp); bp++, bc--)
1616 continue;
1617 if (bc > 0 && *bp == '-') {
1618 cont = TRUE;
1619 bp++, bc--;
1620 for (; bc > 0 && isspace (*bp); bp++, bc--)
1621 continue;
1622 }
1623
1624 if (more) {
1625 if (code != sm_reply.code || cont)
1626 continue;
1627 more = FALSE;
1628 } else {
1629 sm_reply.code = code;
1630 more = cont;
1631 if (bc <= 0) {
1632 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1633 strncpy (buffer, sm_noreply, sizeof(buffer));
1634 bp = (unsigned char *) buffer;
1635 bc = strlen (sm_noreply);
1636 }
1637 }
1638
1639 if ((i = min (bc, rc)) > 0) {
1640 memcpy (rp, bp, i);
1641 rp += i;
1642 rc -= i;
1643 i = strlen(sm_moreply);
1644 if (more && rc > i + 1) {
1645 memcpy (rp, sm_moreply, i); /* safe because of check in if() */
1646 rp += i;
1647 rc -= i;
1648 }
1649 }
1650 if (more)
1651 continue;
1652 if (sm_reply.code < 100) {
1653 if (sm_verbose) {
1654 printf ("%s\n", sm_reply.text);
1655 fflush (stdout);
1656 }
1657 goto again;
1658 }
1659
1660 sm_reply.length = rp - sm_reply.text;
1661 sm_reply.text[sm_reply.length] = 0;
1662 return sm_reply.code;
1663 }
1664 return NOTOK;
1665 }
1666
1667
1668 static int
1669 sm_rrecord (char *buffer, int *len)
1670 {
1671 int retval;
1672
1673 if (sm_rfp == NULL)
1674 return sm_rerror(0);
1675
1676 buffer[*len = 0] = 0;
1677
1678 if ((retval = sm_fgets (buffer, BUFSIZ, sm_rfp)) != RP_OK)
1679 return sm_rerror (retval);
1680 *len = strlen (buffer);
1681 /* *len should be >0 except on EOF, but check for safety's sake */
1682 if (*len == 0)
1683 return sm_rerror (RP_EOF);
1684 if (buffer[*len - 1] != '\n')
1685 while ((retval = sm_fgetc (sm_rfp)) != '\n' && retval != EOF &&
1686 retval != -2)
1687 continue;
1688 else
1689 if ((*len > 1) && (buffer[*len - 2] == '\r'))
1690 *len -= 1;
1691 *len -= 1;
1692 buffer[*len] = 0;
1693
1694 return OK;
1695 }
1696
1697 /*
1698 * Our version of fgets, which calls our private fgetc function
1699 */
1700
1701 static int
1702 sm_fgets(char *buffer, int size, FILE *f)
1703 {
1704 int c;
1705
1706 do {
1707 c = sm_fgetc(f);
1708
1709 if (c == EOF)
1710 return RP_EOF;
1711
1712 if (c == -2)
1713 return NOTOK;
1714
1715 *buffer++ = c;
1716 } while (size > 1 && c != '\n');
1717
1718 *buffer = '\0';
1719
1720 return RP_OK;
1721 }
1722
1723
1724 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1725 /*
1726 * Read from the network, but do SASL or TLS encryption
1727 */
1728
1729 static int
1730 sm_fgetc(FILE *f)
1731 {
1732 char tmpbuf[BUFSIZ], *retbuf;
1733 unsigned int retbufsize = 0;
1734 int cc, result;
1735
1736 /*
1737 * If we have leftover data, return it
1738 */
1739
1740 if (sasl_inbuflen) {
1741 sasl_inbuflen--;
1742 return (int) *sasl_inptr++;
1743 }
1744
1745 /*
1746 * If not, read from the network until we have some data to return
1747 */
1748
1749 while (retbufsize == 0) {
1750
1751 #ifdef TLS_SUPPORT
1752 if (tls_active) {
1753 cc = SSL_read(ssl, tmpbuf, sizeof(tmpbuf));
1754
1755 if (cc == 0) {
1756 result = SSL_get_error(ssl, cc);
1757
1758 if (result != SSL_ERROR_ZERO_RETURN) {
1759 sm_ierror("TLS peer aborted connection");
1760 }
1761
1762 return EOF;
1763 }
1764
1765 if (cc < 0) {
1766 sm_ierror("SSL_read failed: %s",
1767 ERR_error_string(ERR_get_error(), NULL));
1768 return -2;
1769 }
1770 } else
1771 #endif /* TLS_SUPPORT */
1772
1773 cc = read(fileno(f), tmpbuf, sizeof(tmpbuf));
1774
1775 if (cc == 0)
1776 return EOF;
1777
1778 if (cc < 0) {
1779 sm_ierror("Unable to read from network: %s", strerror(errno));
1780 return -2;
1781 }
1782
1783 /*
1784 * Don't call sasl_decode unless sasl is complete and we have
1785 * encryption working
1786 */
1787
1788 #ifdef CYRUS_SASL
1789 if (sasl_complete == 0 || sasl_ssf == 0) {
1790 retbuf = tmpbuf;
1791 retbufsize = cc;
1792 } else {
1793 result = sasl_decode(conn, tmpbuf, cc, (const char **) &retbuf,
1794 &retbufsize);
1795
1796 if (result != SASL_OK) {
1797 sm_ierror("Unable to decode SASL network data: %s",
1798 sasl_errdetail(conn));
1799 return -2;
1800 }
1801 }
1802 #else /* ! CYRUS_SASL */
1803 retbuf = tmpbuf;
1804 retbufsize = cc;
1805 #endif /* CYRUS_SASL */
1806 }
1807
1808 if (retbufsize > SASL_MAXRECVBUF) {
1809 sm_ierror("Received data (%d bytes) is larger than the buffer "
1810 "size (%d bytes)", retbufsize, SASL_MAXRECVBUF);
1811 return -2;
1812 }
1813
1814 memcpy(sasl_inbuffer, retbuf, retbufsize);
1815 sasl_inptr = sasl_inbuffer + 1;
1816 sasl_inbuflen = retbufsize - 1;
1817
1818 return (int) sasl_inbuffer[0];
1819 }
1820 #endif /* CYRUS_SASL || TLS_SUPPORT */
1821
1822 static int
1823 sm_rerror (int rc)
1824 {
1825 if (sm_mts == MTS_SMTP)
1826 sm_reply.length =
1827 strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no socket opened"
1828 : sm_alarmed ? "read from socket timed out"
1829 : rc == RP_EOF ? "premature end-of-file on socket"
1830 : "error reading from socket"));
1831 else
1832 sm_reply.length =
1833 strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no pipe opened"
1834 : sm_alarmed ? "read from pipe timed out"
1835 : rc == RP_EOF ? "premature end-of-file on pipe"
1836 : "error reading from pipe"));
1837
1838 return (sm_reply.code = NOTOK);
1839 }
1840
1841
1842 static void
1843 alrmser (int i)
1844 {
1845 NMH_UNUSED (i);
1846
1847 #ifndef RELIABLE_SIGNALS
1848 SIGNAL (SIGALRM, alrmser);
1849 #endif
1850
1851 sm_alarmed++;
1852 if (sm_debug) {
1853 printf ("timed out...\n");
1854 fflush (stdout);
1855 }
1856 }
1857
1858
1859 char *
1860 rp_string (int code)
1861 {
1862 char *text;
1863 static char buffer[BUFSIZ];
1864
1865 switch (sm_reply.code != NOTOK ? code : NOTOK) {
1866 case RP_AOK:
1867 text = "AOK";
1868 break;
1869
1870 case RP_MOK:
1871 text = "MOK";
1872 break;
1873
1874 case RP_OK:
1875 text = "OK";
1876 break;
1877
1878 case RP_RPLY:
1879 text = "RPLY";
1880 break;
1881
1882 case RP_BHST:
1883 default:
1884 text = "BHST";
1885 snprintf (buffer, sizeof(buffer), "[%s] %s", text, sm_reply.text);
1886 return buffer;
1887
1888 case RP_PARM:
1889 text = "PARM";
1890 break;
1891
1892 case RP_NO:
1893 text = "NO";
1894 break;
1895
1896 case RP_USER:
1897 text = "USER";
1898 break;
1899
1900 case RP_NDEL:
1901 text = "NDEL";
1902 break;
1903 }
1904
1905 snprintf (buffer, sizeof(buffer), "[%s] %3d %s",
1906 text, sm_reply.code, sm_reply.text);
1907 return buffer;
1908 }
1909
1910 static char *
1911 EHLOset (char *s)
1912 {
1913 size_t len;
1914 char *ep, **ehlo;
1915
1916 len = strlen (s);
1917
1918 for (ehlo = EHLOkeys; *ehlo; ehlo++) {
1919 ep = *ehlo;
1920 if (strncmp (ep, s, len) == 0) {
1921 for (ep += len; *ep == ' '; ep++)
1922 continue;
1923 return ep;
1924 }
1925 }
1926
1927 return 0;
1928 }
1929
1930
1931 /*
1932 * Detects, using heuristics, if an SMTP server or client response string
1933 * contains a base64-encoded portion. If it does, decodes it and replaces
1934 * any non-printable characters with a hex representation. Caller is
1935 * responsible for free'ing return value. If the decode fails, a copy of
1936 * the input string is returned.
1937 */
1938 static
1939 char *
1940 prepare_for_display (const char *string, int *next_line_encoded) {
1941 const char *start = NULL;
1942 const char *decoded;
1943 size_t decoded_len;
1944 int prefix_len = -1;
1945
1946 if (strncmp (string, "AUTH ", 5) == 0) {
1947 /* AUTH line: the mechanism isn't encoded. If there's an initial
1948 response, it must be base64 encoded.. */
1949 char *mechanism = strchr (string + 5, ' ');
1950
1951 if (mechanism != NULL) {
1952 prefix_len = (int) (mechanism - string + 1);
1953 } /* else no space following the mechanism, so no initial response */
1954 *next_line_encoded = 0;
1955 } else if (strncmp (string, "334 ", 4) == 0) {
1956 /* 334 is the server's request for user or password. */
1957 prefix_len = 4;
1958 /* The next (client response) line must be base64 encoded. */
1959 *next_line_encoded = 1;
1960 } else if (*next_line_encoded) {
1961 /* "next" line now refers to this line, which is a base64-encoded
1962 client response. */
1963 prefix_len = 0;
1964 *next_line_encoded = 0;
1965 } else {
1966 *next_line_encoded = 0;
1967 }
1968
1969 /* Don't attempt to decoded unencoded initial response ('=') or cancel
1970 response ('*'). */
1971 if (prefix_len > -1 &&
1972 string[prefix_len] != '=' && string[prefix_len] != '*') {
1973 start = string + prefix_len;
1974 }
1975
1976 if (start && decodeBase64 (start, &decoded, &decoded_len, 1, NULL) == OK) {
1977 char *hexified;
1978 char *prefix = mh_xmalloc(prefix_len + 1);
1979 char *display_string;
1980
1981 /* prefix is the beginning portion, which isn't base64 encoded. */
1982 snprintf (prefix, prefix_len + 1, "%*s", prefix_len, string);
1983 hexify ((const unsigned char *) decoded, decoded_len, &hexified);
1984 /* Wrap the decoded portion in "b64<>". */
1985 display_string = concat (prefix, "b64<", hexified, ">", NULL);
1986 free (hexified);
1987 free (prefix);
1988 free ((char *) decoded);
1989
1990 return display_string;
1991 } else {
1992 return getcpy (string);
1993 }
1994 }