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