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