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