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