]> diplodocus.org Git - nmh/blob - mts/smtp/smtp.c
Removed jsmn license from COPYRIGHT. In keeping what appears to
[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 xoauth_client_res = mh_oauth_do_xoauth(user, oauth_svc,
1164 snoop ? stderr : NULL);
1165
1166 if (xoauth_client_res == NULL)
1167 return sm_ierror("Internal error: oauth_do_xoauth() returned NULL");
1168
1169 status = smtalk(SM_AUTH, "AUTH XOAUTH2 %s", xoauth_client_res);
1170 if (status == 235) {
1171 /* It worked! */
1172 return RP_OK;
1173 }
1174
1175 /*
1176 * Status is 334 and sm_reply.text contains base64-encoded JSON. As far as
1177 * epg can tell, no matter the error, the JSON is always the same:
1178 * {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
1179 * I tried these errors:
1180 * - garbage token
1181 * - expired token
1182 * - wrong scope
1183 * - wrong username
1184 */
1185 /* Then we're supposed to send an empty response ("\r\n"). */
1186 smtalk(SM_AUTH, "");
1187 /*
1188 * And now we always get this, again, no matter the error:
1189 * 535-5.7.8 Username and Password not accepted. Learn more at
1190 * 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257
1191 */
1192 return RP_BHST;
1193 }
1194
1195 static int
1196 sm_ierror (char *fmt, ...)
1197 {
1198 va_list ap;
1199
1200 va_start(ap, fmt);
1201 vsnprintf (sm_reply.text, sizeof(sm_reply.text), fmt, ap);
1202 va_end(ap);
1203
1204 sm_reply.length = strlen (sm_reply.text);
1205 sm_reply.code = NOTOK;
1206
1207 return RP_BHST;
1208 }
1209
1210 static int
1211 smtalk (int time, char *fmt, ...)
1212 {
1213 va_list ap;
1214 int result;
1215 char *buffer;
1216 size_t bufsize = BUFSIZ;
1217
1218 buffer = mh_xmalloc(bufsize);
1219
1220 va_start(ap, fmt);
1221 result = vsnprintf (buffer, bufsize, fmt, ap);
1222 va_end(ap);
1223
1224 if (result > (int) bufsize) {
1225 buffer = mh_xrealloc(buffer, bufsize = result + 1);
1226 va_start(ap, fmt);
1227 vsnprintf (buffer, bufsize, fmt, ap);
1228 va_end(ap);
1229 }
1230
1231 if (sm_debug) {
1232 char *decoded_buffer =
1233 prepare_for_display (buffer, &next_line_encoded);
1234
1235 if (sasl_ssf)
1236 printf("(sasl-encrypted) ");
1237 if (tls_active)
1238 printf("(tls-encrypted) ");
1239 printf ("=> %s\n", decoded_buffer);
1240 free (decoded_buffer);
1241 fflush (stdout);
1242 }
1243
1244 sm_alarmed = 0;
1245 alarm ((unsigned) time);
1246 if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK)
1247 result = smhear ();
1248 alarm (0);
1249
1250 free(buffer);
1251
1252 return result;
1253 }
1254
1255
1256 /*
1257 * write the buffer to the open SMTP channel
1258 */
1259
1260 static int
1261 sm_wrecord (char *buffer, int len)
1262 {
1263 if (sm_wfp == NULL)
1264 return sm_werror ();
1265
1266 sm_fwrite (buffer, len);
1267 sm_fputs ("\r\n");
1268 sm_fflush ();
1269
1270 return (ferror (sm_wfp) ? sm_werror () : OK);
1271 }
1272
1273
1274 static int
1275 sm_wstream (char *buffer, int len)
1276 {
1277 char *bp;
1278 static char lc = '\0';
1279
1280 if (sm_wfp == NULL)
1281 return sm_werror ();
1282
1283 if (buffer == NULL && len == 0) {
1284 if (lc != '\n')
1285 sm_fputs ("\r\n");
1286 lc = '\0';
1287 return (ferror (sm_wfp) ? sm_werror () : OK);
1288 }
1289
1290 for (bp = buffer; bp && len > 0; bp++, len--) {
1291 switch (*bp) {
1292 case '\n':
1293 sm_nl = TRUE;
1294 sm_fputc ('\r');
1295 break;
1296
1297 case '.':
1298 if (sm_nl)
1299 sm_fputc ('.');/* FALL THROUGH */
1300 default:
1301 sm_nl = FALSE;
1302 }
1303 sm_fputc (*bp);
1304 if (ferror (sm_wfp))
1305 return sm_werror ();
1306 }
1307
1308 if (bp > buffer)
1309 lc = *--bp;
1310 return (ferror (sm_wfp) ? sm_werror () : OK);
1311 }
1312
1313 /*
1314 * Write out to the network, but do buffering for SASL (if enabled)
1315 */
1316
1317 static int
1318 sm_fwrite(char *buffer, int len)
1319 {
1320 #ifdef CYRUS_SASL
1321 const char *output;
1322 unsigned int outputlen;
1323
1324 if (sasl_complete == 0 || sasl_ssf == 0) {
1325 #endif /* CYRUS_SASL */
1326 #ifdef TLS_SUPPORT
1327 if (tls_active) {
1328 int ret;
1329
1330 ret = BIO_write(io, buffer, len);
1331
1332 if (ret <= 0) {
1333 sm_ierror("TLS error during write: %s",
1334 ERR_error_string(ERR_get_error(), NULL));
1335 return NOTOK;
1336 }
1337 } else
1338 #endif /* TLS_SUPPORT */
1339 if ((int) fwrite(buffer, sizeof(*buffer), len, sm_wfp) < len) {
1340 advise ("sm_fwrite", "fwrite");
1341 }
1342 #ifdef CYRUS_SASL
1343 } else {
1344 while (len >= maxoutbuf - sasl_outbuflen) {
1345 memcpy(sasl_outbuffer + sasl_outbuflen, buffer,
1346 maxoutbuf - sasl_outbuflen);
1347 len -= maxoutbuf - sasl_outbuflen;
1348 sasl_outbuflen = 0;
1349
1350 if (sasl_encode(conn, sasl_outbuffer, maxoutbuf,
1351 &output, &outputlen) != SASL_OK) {
1352 sm_ierror("Unable to SASL encode connection data: %s",
1353 sasl_errdetail(conn));
1354 return NOTOK;
1355 }
1356
1357 if (fwrite(output, sizeof(*output), outputlen, sm_wfp) <
1358 outputlen) {
1359 advise ("sm_fwrite", "fwrite");
1360 }
1361 }
1362
1363 if (len > 0) {
1364 memcpy(sasl_outbuffer + sasl_outbuflen, buffer, len);
1365 sasl_outbuflen += len;
1366 }
1367 }
1368 #endif /* CYRUS_SASL */
1369 return ferror(sm_wfp) ? NOTOK : RP_OK;
1370 }
1371
1372 #ifdef TLS_SUPPORT
1373 /*
1374 * Negotiate Transport Layer Security
1375 */
1376
1377 static int
1378 tls_negotiate(void)
1379 {
1380 BIO *ssl_bio;
1381
1382 if (! sslctx) {
1383 const SSL_METHOD *method;
1384
1385 SSL_library_init();
1386 SSL_load_error_strings();
1387
1388 method = TLSv1_client_method(); /* Not sure about this */
1389
1390 /* Older ssl takes a non-const arg. */
1391 sslctx = SSL_CTX_new((SSL_METHOD *) method);
1392
1393 if (! sslctx) {
1394 sm_end(NOTOK);
1395 return sm_ierror("Unable to initialize OpenSSL context: %s",
1396 ERR_error_string(ERR_get_error(), NULL));
1397 }
1398 }
1399
1400 ssl = SSL_new(sslctx);
1401
1402 if (! ssl) {
1403 sm_end(NOTOK);
1404 return sm_ierror("Unable to create SSL connection: %s",
1405 ERR_error_string(ERR_get_error(), NULL));
1406 }
1407
1408 sbior = BIO_new_socket(fileno(sm_rfp), BIO_NOCLOSE);
1409 sbiow = BIO_new_socket(fileno(sm_wfp), BIO_NOCLOSE);
1410
1411 if (sbior == NULL || sbiow == NULL) {
1412 sm_end(NOTOK);
1413 return sm_ierror("Unable to create BIO endpoints: %s",
1414 ERR_error_string(ERR_get_error(), NULL));
1415 }
1416
1417 SSL_set_bio(ssl, sbior, sbiow);
1418 SSL_set_connect_state(ssl);
1419
1420 /*
1421 * Set up a BIO to handle buffering for us
1422 */
1423
1424 io = BIO_new(BIO_f_buffer());
1425
1426 if (! io) {
1427 sm_end(NOTOK);
1428 return sm_ierror("Unable to create a buffer BIO: %s",
1429 ERR_error_string(ERR_get_error(), NULL));
1430 }
1431
1432 ssl_bio = BIO_new(BIO_f_ssl());
1433
1434 if (! ssl_bio) {
1435 sm_end(NOTOK);
1436 return sm_ierror("Unable to create a SSL BIO: %s",
1437 ERR_error_string(ERR_get_error(), NULL));
1438 }
1439
1440 BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
1441 BIO_push(io, ssl_bio);
1442
1443 /*
1444 * Try doing the handshake now
1445 */
1446
1447 if (BIO_do_handshake(io) < 1) {
1448 sm_end(NOTOK);
1449 return sm_ierror("Unable to negotiate SSL connection: %s",
1450 ERR_error_string(ERR_get_error(), NULL));
1451 }
1452
1453 if (sm_debug) {
1454 const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
1455 printf("SSL negotiation successful: %s(%d) %s\n",
1456 SSL_CIPHER_get_name(cipher),
1457 SSL_CIPHER_get_bits(cipher, NULL),
1458 SSL_CIPHER_get_version(cipher));
1459
1460 }
1461
1462 tls_active = 1;
1463
1464 return RP_OK;
1465 }
1466 #endif /* TLS_SUPPORT */
1467
1468 /*
1469 * Convenience functions to replace occurrences of fputs() and fputc()
1470 */
1471
1472 static int
1473 sm_fputs(char *buffer)
1474 {
1475 return sm_fwrite(buffer, strlen(buffer));
1476 }
1477
1478 static int
1479 sm_fputc(int c)
1480 {
1481 char h = c;
1482
1483 return sm_fwrite(&h, 1);
1484 }
1485
1486 /*
1487 * Flush out any pending data on the connection
1488 */
1489
1490 static void
1491 sm_fflush(void)
1492 {
1493 #ifdef CYRUS_SASL
1494 const char *output;
1495 unsigned int outputlen;
1496 int result;
1497
1498 if (sasl_complete == 1 && sasl_ssf > 0 && sasl_outbuflen > 0) {
1499 result = sasl_encode(conn, sasl_outbuffer, sasl_outbuflen,
1500 &output, &outputlen);
1501 if (result != SASL_OK) {
1502 sm_ierror("Unable to SASL encode connection data: %s",
1503 sasl_errdetail(conn));
1504 return;
1505 }
1506
1507 if (fwrite(output, sizeof(*output), outputlen, sm_wfp) < outputlen) {
1508 advise ("sm_fflush", "fwrite");
1509 }
1510 sasl_outbuflen = 0;
1511 }
1512 #endif /* CYRUS_SASL */
1513
1514 #ifdef TLS_SUPPORT
1515 if (tls_active) {
1516 (void) BIO_flush(io);
1517 }
1518 #endif /* TLS_SUPPORT */
1519
1520 fflush(sm_wfp);
1521 }
1522
1523 static int
1524 sm_werror (void)
1525 {
1526 sm_reply.length =
1527 strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened"
1528 : sm_alarmed ? "write to socket timed out"
1529 : "error writing to socket"));
1530
1531 return (sm_reply.code = NOTOK);
1532 }
1533
1534
1535 static int
1536 smhear (void)
1537 {
1538 int i, code, cont, bc = 0, rc, more;
1539 unsigned char *bp;
1540 char *rp;
1541 char **ehlo = EHLOkeys, buffer[BUFSIZ];
1542
1543 if (doingEHLO) {
1544 static int at_least_once = 0;
1545
1546 if (at_least_once) {
1547 char *ep;
1548
1549 for (ehlo = EHLOkeys; *ehlo; ehlo++) {
1550 ep = *ehlo;
1551 free (ep);
1552 }
1553 } else {
1554 at_least_once = 1;
1555 }
1556
1557 ehlo = EHLOkeys;
1558 *ehlo = NULL;
1559 }
1560
1561 again: ;
1562
1563 sm_reply.length = 0;
1564 sm_reply.text[0] = 0;
1565 rp = sm_reply.text;
1566 rc = sizeof(sm_reply.text) - 1;
1567
1568 for (more = FALSE; sm_rrecord ((char *) (bp = (unsigned char *) buffer),
1569 &bc) != NOTOK ; ) {
1570 if (sm_debug) {
1571 char *decoded_buffer =
1572 prepare_for_display (buffer, &next_line_encoded);
1573
1574 if (sasl_ssf > 0)
1575 printf("(sasl-decrypted) ");
1576 if (tls_active)
1577 printf("(tls-decrypted) ");
1578 printf ("<= %s\n", decoded_buffer);
1579 free (decoded_buffer);
1580 fflush (stdout);
1581 }
1582
1583 if (doingEHLO
1584 && strncmp (buffer, "250", sizeof("250") - 1) == 0
1585 && (buffer[3] == '-' || doingEHLO == 2)
1586 && buffer[4]) {
1587 if (doingEHLO == 2) {
1588 if ((*ehlo = malloc ((size_t) (strlen (buffer + 4) + 1)))) {
1589 strcpy (*ehlo++, buffer + 4);
1590 *ehlo = NULL;
1591 if (ehlo >= EHLOkeys + MAXEHLO)
1592 doingEHLO = 0;
1593 }
1594 else
1595 doingEHLO = 0;
1596 }
1597 else
1598 doingEHLO = 2;
1599 }
1600
1601 for (; bc > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, bc--)
1602 continue;
1603
1604 cont = FALSE;
1605 code = atoi ((char *) bp);
1606 bp += 3, bc -= 3;
1607 for (; bc > 0 && isspace (*bp); bp++, bc--)
1608 continue;
1609 if (bc > 0 && *bp == '-') {
1610 cont = TRUE;
1611 bp++, bc--;
1612 for (; bc > 0 && isspace (*bp); bp++, bc--)
1613 continue;
1614 }
1615
1616 if (more) {
1617 if (code != sm_reply.code || cont)
1618 continue;
1619 more = FALSE;
1620 } else {
1621 sm_reply.code = code;
1622 more = cont;
1623 if (bc <= 0) {
1624 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1625 strncpy (buffer, sm_noreply, sizeof(buffer));
1626 bp = (unsigned char *) buffer;
1627 bc = strlen (sm_noreply);
1628 }
1629 }
1630
1631 if ((i = min (bc, rc)) > 0) {
1632 memcpy (rp, bp, i);
1633 rp += i;
1634 rc -= i;
1635 i = strlen(sm_moreply);
1636 if (more && rc > i + 1) {
1637 memcpy (rp, sm_moreply, i); /* safe because of check in if() */
1638 rp += i;
1639 rc -= i;
1640 }
1641 }
1642 if (more)
1643 continue;
1644 if (sm_reply.code < 100) {
1645 if (sm_verbose) {
1646 printf ("%s\n", sm_reply.text);
1647 fflush (stdout);
1648 }
1649 goto again;
1650 }
1651
1652 sm_reply.length = rp - sm_reply.text;
1653 sm_reply.text[sm_reply.length] = 0;
1654 return sm_reply.code;
1655 }
1656 return NOTOK;
1657 }
1658
1659
1660 static int
1661 sm_rrecord (char *buffer, int *len)
1662 {
1663 int retval;
1664
1665 if (sm_rfp == NULL)
1666 return sm_rerror(0);
1667
1668 buffer[*len = 0] = 0;
1669
1670 if ((retval = sm_fgets (buffer, BUFSIZ, sm_rfp)) != RP_OK)
1671 return sm_rerror (retval);
1672 *len = strlen (buffer);
1673 /* *len should be >0 except on EOF, but check for safety's sake */
1674 if (*len == 0)
1675 return sm_rerror (RP_EOF);
1676 if (buffer[*len - 1] != '\n')
1677 while ((retval = sm_fgetc (sm_rfp)) != '\n' && retval != EOF &&
1678 retval != -2)
1679 continue;
1680 else
1681 if ((*len > 1) && (buffer[*len - 2] == '\r'))
1682 *len -= 1;
1683 *len -= 1;
1684 buffer[*len] = 0;
1685
1686 return OK;
1687 }
1688
1689 /*
1690 * Our version of fgets, which calls our private fgetc function
1691 */
1692
1693 static int
1694 sm_fgets(char *buffer, int size, FILE *f)
1695 {
1696 int c;
1697
1698 do {
1699 c = sm_fgetc(f);
1700
1701 if (c == EOF)
1702 return RP_EOF;
1703
1704 if (c == -2)
1705 return NOTOK;
1706
1707 *buffer++ = c;
1708 } while (size > 1 && c != '\n');
1709
1710 *buffer = '\0';
1711
1712 return RP_OK;
1713 }
1714
1715
1716 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1717 /*
1718 * Read from the network, but do SASL or TLS encryption
1719 */
1720
1721 static int
1722 sm_fgetc(FILE *f)
1723 {
1724 char tmpbuf[BUFSIZ], *retbuf;
1725 unsigned int retbufsize = 0;
1726 int cc, result;
1727
1728 /*
1729 * If we have leftover data, return it
1730 */
1731
1732 if (sasl_inbuflen) {
1733 sasl_inbuflen--;
1734 return (int) *sasl_inptr++;
1735 }
1736
1737 /*
1738 * If not, read from the network until we have some data to return
1739 */
1740
1741 while (retbufsize == 0) {
1742
1743 #ifdef TLS_SUPPORT
1744 if (tls_active) {
1745 cc = SSL_read(ssl, tmpbuf, sizeof(tmpbuf));
1746
1747 if (cc == 0) {
1748 result = SSL_get_error(ssl, cc);
1749
1750 if (result != SSL_ERROR_ZERO_RETURN) {
1751 sm_ierror("TLS peer aborted connection");
1752 }
1753
1754 return EOF;
1755 }
1756
1757 if (cc < 0) {
1758 sm_ierror("SSL_read failed: %s",
1759 ERR_error_string(ERR_get_error(), NULL));
1760 return -2;
1761 }
1762 } else
1763 #endif /* TLS_SUPPORT */
1764
1765 cc = read(fileno(f), tmpbuf, sizeof(tmpbuf));
1766
1767 if (cc == 0)
1768 return EOF;
1769
1770 if (cc < 0) {
1771 sm_ierror("Unable to read from network: %s", strerror(errno));
1772 return -2;
1773 }
1774
1775 /*
1776 * Don't call sasl_decode unless sasl is complete and we have
1777 * encryption working
1778 */
1779
1780 #ifdef CYRUS_SASL
1781 if (sasl_complete == 0 || sasl_ssf == 0) {
1782 retbuf = tmpbuf;
1783 retbufsize = cc;
1784 } else {
1785 result = sasl_decode(conn, tmpbuf, cc, (const char **) &retbuf,
1786 &retbufsize);
1787
1788 if (result != SASL_OK) {
1789 sm_ierror("Unable to decode SASL network data: %s",
1790 sasl_errdetail(conn));
1791 return -2;
1792 }
1793 }
1794 #else /* ! CYRUS_SASL */
1795 retbuf = tmpbuf;
1796 retbufsize = cc;
1797 #endif /* CYRUS_SASL */
1798 }
1799
1800 if (retbufsize > SASL_MAXRECVBUF) {
1801 sm_ierror("Received data (%d bytes) is larger than the buffer "
1802 "size (%d bytes)", retbufsize, SASL_MAXRECVBUF);
1803 return -2;
1804 }
1805
1806 memcpy(sasl_inbuffer, retbuf, retbufsize);
1807 sasl_inptr = sasl_inbuffer + 1;
1808 sasl_inbuflen = retbufsize - 1;
1809
1810 return (int) sasl_inbuffer[0];
1811 }
1812 #endif /* CYRUS_SASL || TLS_SUPPORT */
1813
1814 static int
1815 sm_rerror (int rc)
1816 {
1817 if (sm_mts == MTS_SMTP)
1818 sm_reply.length =
1819 strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no socket opened"
1820 : sm_alarmed ? "read from socket timed out"
1821 : rc == RP_EOF ? "premature end-of-file on socket"
1822 : "error reading from socket"));
1823 else
1824 sm_reply.length =
1825 strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no pipe opened"
1826 : sm_alarmed ? "read from pipe timed out"
1827 : rc == RP_EOF ? "premature end-of-file on pipe"
1828 : "error reading from pipe"));
1829
1830 return (sm_reply.code = NOTOK);
1831 }
1832
1833
1834 static void
1835 alrmser (int i)
1836 {
1837 NMH_UNUSED (i);
1838
1839 #ifndef RELIABLE_SIGNALS
1840 SIGNAL (SIGALRM, alrmser);
1841 #endif
1842
1843 sm_alarmed++;
1844 if (sm_debug) {
1845 printf ("timed out...\n");
1846 fflush (stdout);
1847 }
1848 }
1849
1850
1851 char *
1852 rp_string (int code)
1853 {
1854 char *text;
1855 static char buffer[BUFSIZ];
1856
1857 switch (sm_reply.code != NOTOK ? code : NOTOK) {
1858 case RP_AOK:
1859 text = "AOK";
1860 break;
1861
1862 case RP_MOK:
1863 text = "MOK";
1864 break;
1865
1866 case RP_OK:
1867 text = "OK";
1868 break;
1869
1870 case RP_RPLY:
1871 text = "RPLY";
1872 break;
1873
1874 case RP_BHST:
1875 default:
1876 text = "BHST";
1877 snprintf (buffer, sizeof(buffer), "[%s] %s", text, sm_reply.text);
1878 return buffer;
1879
1880 case RP_PARM:
1881 text = "PARM";
1882 break;
1883
1884 case RP_NO:
1885 text = "NO";
1886 break;
1887
1888 case RP_USER:
1889 text = "USER";
1890 break;
1891
1892 case RP_NDEL:
1893 text = "NDEL";
1894 break;
1895 }
1896
1897 snprintf (buffer, sizeof(buffer), "[%s] %3d %s",
1898 text, sm_reply.code, sm_reply.text);
1899 return buffer;
1900 }
1901
1902 static char *
1903 EHLOset (char *s)
1904 {
1905 size_t len;
1906 char *ep, **ehlo;
1907
1908 len = strlen (s);
1909
1910 for (ehlo = EHLOkeys; *ehlo; ehlo++) {
1911 ep = *ehlo;
1912 if (strncmp (ep, s, len) == 0) {
1913 for (ep += len; *ep == ' '; ep++)
1914 continue;
1915 return ep;
1916 }
1917 }
1918
1919 return 0;
1920 }
1921
1922
1923 /*
1924 * Detects, using heuristics, if an SMTP server or client response string
1925 * contains a base64-encoded portion. If it does, decodes it and replaces
1926 * any non-printable characters with a hex representation. Caller is
1927 * responsible for free'ing return value. If the decode fails, a copy of
1928 * the input string is returned.
1929 */
1930 static
1931 char *
1932 prepare_for_display (const char *string, int *next_line_encoded) {
1933 const char *start = NULL;
1934 const char *decoded;
1935 size_t decoded_len;
1936 int prefix_len = -1;
1937
1938 if (strncmp (string, "AUTH ", 5) == 0) {
1939 /* AUTH line: the mechanism isn't encoded. If there's an initial
1940 response, it must be base64 encoded.. */
1941 char *mechanism = strchr (string + 5, ' ');
1942
1943 if (mechanism != NULL) {
1944 prefix_len = (int) (mechanism - string + 1);
1945 } /* else no space following the mechanism, so no initial response */
1946 *next_line_encoded = 0;
1947 } else if (strncmp (string, "334 ", 4) == 0) {
1948 /* 334 is the server's request for user or password. */
1949 prefix_len = 4;
1950 /* The next (client response) line must be base64 encoded. */
1951 *next_line_encoded = 1;
1952 } else if (*next_line_encoded) {
1953 /* "next" line now refers to this line, which is a base64-encoded
1954 client response. */
1955 prefix_len = 0;
1956 *next_line_encoded = 0;
1957 } else {
1958 *next_line_encoded = 0;
1959 }
1960
1961 /* Don't attempt to decoded unencoded initial response ('=') or cancel
1962 response ('*'). */
1963 if (prefix_len > -1 &&
1964 string[prefix_len] != '=' && string[prefix_len] != '*') {
1965 start = string + prefix_len;
1966 }
1967
1968 if (start && decodeBase64 (start, &decoded, &decoded_len, 1, NULL) == OK) {
1969 char *hexified;
1970 char *prefix = mh_xmalloc(prefix_len + 1);
1971 char *display_string;
1972
1973 /* prefix is the beginning portion, which isn't base64 encoded. */
1974 snprintf (prefix, prefix_len + 1, "%*s", prefix_len, string);
1975 hexify ((const unsigned char *) decoded, decoded_len, &hexified);
1976 /* Wrap the decoded portion in "b64<>". */
1977 display_string = concat (prefix, "b64<", hexified, ">", NULL);
1978 free (hexified);
1979 free (prefix);
1980 free ((char *) decoded);
1981
1982 return display_string;
1983 } else {
1984 return getcpy (string);
1985 }
1986 }