2 * smtp.c -- nmh SMTP interface
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.
12 #include <h/signals.h>
15 #include <sasl/sasl.h>
16 #include <sasl/saslutil.h>
17 # if SASL_VERSION_FULL < 0x020125
18 /* Cyrus SASL 2.1.25 introduced the sasl_callback_ft prototype,
19 which has an explicit void parameter list, according to best
20 practice. So we need to cast to avoid compile warnings.
21 Provide this prototype for earlier versions. */
22 typedef int (*sasl_callback_ft
)();
23 # endif /* SASL_VERSION_FULL < 0x020125 */
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
28 #endif /* CYRUS_SASL */
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
33 #endif /* TLS_SUPPORT */
36 * This module implements an interface to SendMail very similar
37 * to the MMDF mm_(3) routines. The sm_() routines herein talk
38 * SMTP to a sendmail process, mapping SMTP reply codes into
43 * On older 4.2BSD machines without the POSIX function `sigaction',
44 * the alarm handing stuff for time-outs will NOT work due to the way
45 * syscalls get restarted. This is not really crucial, since SendMail
46 * is generally well-behaved in this area.
51 * It appears that some versions of Sendmail will return Code 451
52 * when they don't really want to indicate a failure.
53 * "Code 451 almost always means sendmail has deferred; we don't
54 * really want bomb out at this point since sendmail will rectify
55 * things later." So, if you define SENDMAILBUG, Code 451 is
56 * considered the same as Code 250. Yuck!
63 #define NBITS ((sizeof (int)) * 8)
66 * these codes must all be different!
68 #define SM_OPEN 300 /* Changed to 5 minutes to comply with a SHOULD in RFC 1123 */
71 #define SM_MAIL 301 /* changed to 5 minutes and a second (for uniqueness), see above */
72 #define SM_RCPT 302 /* see above */
73 #define SM_DATA 120 /* see above */
74 #define SM_TEXT 180 /* see above */
75 #define SM_DOT 600 /* see above */
80 #endif /* CYRUS_SASL */
82 static int sm_addrs
= 0;
83 static int sm_alarmed
= 0;
84 static int sm_child
= NOTOK
;
85 static int sm_debug
= 0;
86 static int sm_nl
= TRUE
;
87 static int sm_verbose
= 0;
89 static FILE *sm_rfp
= NULL
;
90 static FILE *sm_wfp
= NULL
;
94 * Some globals needed by SASL
97 static sasl_conn_t
*conn
= NULL
; /* SASL connection state */
98 static int sasl_complete
= 0; /* Has authentication succeded? */
99 static sasl_ssf_t sasl_ssf
; /* Our security strength factor */
100 static int maxoutbuf
; /* Maximum crypto output buffer */
101 static char *sasl_outbuffer
; /* SASL output buffer for encryption */
102 static int sasl_outbuflen
; /* Current length of data in outbuf */
103 static int sm_get_user(void *, int, const char **, unsigned *);
104 static int sm_get_pass(sasl_conn_t
*, void *, int, sasl_secret_t
**);
106 static sasl_callback_t callbacks
[] = {
107 { SASL_CB_USER
, (sasl_callback_ft
) sm_get_user
, NULL
},
108 #define SM_SASL_N_CB_USER 0
109 { SASL_CB_AUTHNAME
, (sasl_callback_ft
) sm_get_user
, NULL
},
110 #define SM_SASL_N_CB_AUTHNAME 1
111 { SASL_CB_PASS
, (sasl_callback_ft
) sm_get_pass
, NULL
},
112 #define SM_SASL_N_CB_PASS 2
113 { SASL_CB_LIST_END
, NULL
, NULL
},
116 #else /* CYRUS_SASL */
118 #endif /* CYRUS_SASL */
121 static SSL_CTX
*sslctx
= NULL
;
122 static SSL
*ssl
= NULL
;
123 static BIO
*sbior
= NULL
;
124 static BIO
*sbiow
= NULL
;
125 static BIO
*io
= NULL
;
127 static int tls_negotiate(void);
128 #endif /* TLS_SUPPORT */
130 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
131 #define SASL_MAXRECVBUF 65536
132 static int sm_fgetc(FILE *);
133 static char *sasl_inbuffer
; /* SASL input buffer for encryption */
134 static char *sasl_inptr
; /* Pointer to current inbuf position */
135 static int sasl_inbuflen
; /* Current length of data in inbuf */
137 #define sm_fgetc fgetc
140 static int tls_active
= 0;
142 static char *sm_noreply
= "No reply text given";
143 static char *sm_moreply
= "; ";
144 static struct smtp sm_reply
;
148 static int doingEHLO
;
149 static char *EHLOkeys
[MAXEHLO
+ 1];
154 static int smtp_init (char *, char *, char *, int, int, int, int, int, int,
155 char *, char *, int);
156 static int sendmail_init (char *, char *, int, int, int, int, int, int,
159 static int rclient (char *, char *);
160 static int sm_ierror (char *fmt
, ...);
161 static int smtalk (int time
, char *fmt
, ...);
162 static int sm_wrecord (char *, int);
163 static int sm_wstream (char *, int);
164 static int sm_werror (void);
165 static int smhear (void);
166 static int sm_rrecord (char *, int *);
167 static int sm_rerror (int);
168 static void alrmser (int);
169 static char *EHLOset (char *);
170 static int sm_fwrite(char *, int);
171 static int sm_fputs(char *);
172 static int sm_fputc(int);
173 static void sm_fflush(void);
174 static int sm_fgets(char *, int, FILE *);
178 * Function prototypes needed for SASL
181 static int sm_auth_sasl(char *, int, char *, char *);
182 #endif /* CYRUS_SASL */
185 sm_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
186 int debug
, int queued
, int sasl
, int saslssf
,
187 char *saslmech
, char *user
, int tls
)
189 if (sm_mts
== MTS_SMTP
)
190 return smtp_init (client
, server
, port
, watch
, verbose
,
191 debug
, queued
, sasl
, saslssf
, saslmech
,
194 return sendmail_init (client
, server
, watch
, verbose
,
195 debug
, queued
, sasl
, saslssf
, saslmech
,
200 smtp_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
201 int debug
, int queued
,
202 int sasl
, int saslssf
, char *saslmech
, char *user
, int tls
)
204 int result
, sd1
, sd2
;
207 #else /* CYRUS_SASL */
209 NMH_UNUSED (saslssf
);
210 NMH_UNUSED (saslmech
);
212 #endif /* CYRUS_SASL */
217 sm_verbose
= verbose
;
220 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
223 if (client
== NULL
|| *client
== '\0') {
227 client
= LocalName(1); /* no clientname -> LocalName */
232 * Last-ditch check just in case client still isn't set to anything
235 if (client
== NULL
|| *client
== '\0')
236 client
= "localhost";
238 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
239 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
241 return sm_ierror("Unable to allocate %d bytes for read buffer",
243 #endif /* CYRUS_SASL || TLS_SUPPORT */
245 if ((sd1
= rclient (server
, port
)) == NOTOK
)
248 if ((sd2
= dup (sd1
)) == NOTOK
) {
250 return sm_ierror ("unable to dup");
253 SIGNAL (SIGALRM
, alrmser
);
254 SIGNAL (SIGPIPE
, SIG_IGN
);
256 if ((sm_rfp
= fdopen (sd1
, "r")) == NULL
257 || (sm_wfp
= fdopen (sd2
, "w")) == NULL
) {
260 sm_rfp
= sm_wfp
= NULL
;
261 return sm_ierror ("unable to fdopen");
268 * If tls == 2, that means that the user requested "initial" TLS,
269 * which happens right after the connection has opened. Do that
274 result
= tls_negotiate();
277 * Note: if tls_negotiate() fails it will call sm_end() for us,
278 * which closes the connection.
283 #endif /* TLS_SUPPORT */
300 * Give EHLO or HELO command
304 result
= smtalk (SM_HELO
, "EHLO %s", client
);
307 if (result
>= 500 && result
<= 599)
308 result
= smtalk (SM_HELO
, "HELO %s", client
);
317 * If the user requested TLS support, then try to do the STARTTLS command
318 * as part of the initial dialog. Assuming this works, we then need to
319 * restart the EHLO dialog after TLS negotiation is complete.
323 if (! EHLOset("STARTTLS")) {
325 return sm_ierror("SMTP server does not support TLS");
328 result
= smtalk(SM_HELO
, "STARTTLS");
336 * Okay, the other side should be waiting for us to start TLS
337 * negotiation. Oblige them.
340 result
= tls_negotiate();
346 result
= smtalk (SM_HELO
, "EHLO %s", client
);
354 #else /* TLS_SUPPORT */
356 #endif /* TLS_SUPPORT */
360 * If the user asked for SASL, then check to see if the SMTP server
361 * supports it. Otherwise, error out (because the SMTP server
362 * might have been spoofed; we don't want to just silently not
367 if (! (server_mechs
= EHLOset("AUTH"))) {
369 return sm_ierror("SMTP server does not support SASL");
372 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
374 return sm_ierror("Requested SASL mech \"%s\" is not in the "
375 "list of supported mechanisms:\n%s",
376 saslmech
, server_mechs
);
379 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
385 #endif /* CYRUS_SASL */
388 if (watch
&& EHLOset ("XVRB"))
389 smtalk (SM_HELO
, "VERB on");
390 if (queued
&& EHLOset ("XQUE"))
391 smtalk (SM_HELO
, "QUED");
397 sendmail_init (char *client
, char *server
, int watch
, int verbose
,
398 int debug
, int queued
,
399 int sasl
, int saslssf
, char *saslmech
, char *user
)
401 unsigned int i
, result
, vecp
;
406 #else /* CYRUS_SASL */
409 NMH_UNUSED (saslssf
);
410 NMH_UNUSED (saslmech
);
412 #endif /* CYRUS_SASL */
417 sm_verbose
= verbose
;
419 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
422 if (client
== NULL
|| *client
== '\0') {
426 client
= LocalName(1); /* no clientname -> LocalName */
430 * Last-ditch check just in case client still isn't set to anything
433 if (client
== NULL
|| *client
== '\0')
434 client
= "localhost";
436 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
437 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
439 return sm_ierror("Unable to allocate %d bytes for read buffer",
441 #endif /* CYRUS_SASL || TLS_SUPPORT */
443 if (pipe (pdi
) == NOTOK
)
444 return sm_ierror ("no pipes");
445 if (pipe (pdo
) == NOTOK
) {
448 return sm_ierror ("no pipes");
451 for (i
= 0; (sm_child
= fork ()) == NOTOK
&& i
< 5; i
++)
460 return sm_ierror ("unable to fork");
463 if (pdo
[0] != fileno (stdin
))
464 dup2 (pdo
[0], fileno (stdin
));
465 if (pdi
[1] != fileno (stdout
))
466 dup2 (pdi
[1], fileno (stdout
));
467 if (pdi
[1] != fileno (stderr
))
468 dup2 (pdi
[1], fileno (stderr
));
469 for (i
= fileno (stderr
) + 1; i
< NBITS
; i
++)
473 vec
[vecp
++] = r1bindex (sendmail
, '/');
475 vec
[vecp
++] = watch
? "-odi" : queued
? "-odq" : "-odb";
476 vec
[vecp
++] = "-oem";
482 execvp (sendmail
, vec
);
483 fprintf (stderr
, "unable to exec ");
485 _exit (-1); /* NOTREACHED */
488 SIGNAL (SIGALRM
, alrmser
);
489 SIGNAL (SIGPIPE
, SIG_IGN
);
493 if ((sm_rfp
= fdopen (pdi
[0], "r")) == NULL
494 || (sm_wfp
= fdopen (pdo
[1], "w")) == NULL
) {
497 sm_rfp
= sm_wfp
= NULL
;
498 return sm_ierror ("unable to fdopen");
514 result
= smtalk (SM_HELO
, "EHLO %s", client
);
517 if (500 <= result
&& result
<= 599)
518 result
= smtalk (SM_HELO
, "HELO %s", client
);
531 * If the user asked for SASL, then check to see if the SMTP server
532 * supports it. Otherwise, error out (because the SMTP server
533 * might have been spoofed; we don't want to just silently not
538 if (! (server_mechs
= EHLOset("AUTH"))) {
540 return sm_ierror("SMTP server does not support SASL");
543 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
545 return sm_ierror("Requested SASL mech \"%s\" is not in the "
546 "list of supported mechanisms:\n%s",
547 saslmech
, server_mechs
);
550 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
556 #endif /* CYRUS_SASL */
559 smtalk (SM_HELO
, "VERB on");
566 rclient (char *server
, char *service
)
569 char response
[BUFSIZ
];
571 if ((sd
= client (server
, service
, response
, sizeof(response
),
575 sm_ierror ("%s", response
);
580 sm_winit (char *from
)
582 switch (smtalk (SM_MAIL
, "MAIL FROM:<%s>", from
)) {
599 sm_wadr (char *mbox
, char *host
, char *path
)
601 switch (smtalk (SM_RCPT
, host
&& *host
? "RCPT TO:<%s%s@%s>"
603 path
? path
: "", mbox
, host
)) {
613 #endif /* SENDMAILBUG */
638 switch (smtalk (SM_DATA
, "DATA")) {
647 #endif /* SENDMAILBUG */
664 sm_wtxt (char *buffer
, int len
)
670 result
= sm_wstream (buffer
, len
);
673 return (result
== NOTOK
? RP_BHST
: RP_OK
);
680 if (sm_wstream ((char *) NULL
, 0) == NOTOK
)
683 switch (smtalk (SM_DOT
+ 3 * sm_addrs
, ".")) {
691 #endif /* SENDMAILBUG */
709 if (sm_mts
== MTS_SENDMAIL_SMTP
) {
720 if (sm_rfp
== NULL
&& sm_wfp
== NULL
)
725 smtalk (SM_QUIT
, "QUIT");
729 sm_note
.code
= sm_reply
.code
;
730 sm_note
.length
= sm_reply
.length
;
731 memcpy (sm_note
.text
, sm_reply
.text
, sm_reply
.length
+ 1);/* fall */
733 if (smtalk (SM_RSET
, "RSET") == 250 && type
== DONE
)
735 if (sm_mts
== MTS_SMTP
)
736 smtalk (SM_QUIT
, "QUIT");
738 /* The SIGPIPE block replaces old calls to discard ().
739 We're not sure what the discard () calls were for,
740 maybe to prevent deadlock on old systems. In any
741 case, blocking SIGPIPE should be harmless.
742 Because the file handles are closed below, leave it
746 sigaddset (&set
, SIGPIPE
);
747 sigprocmask (SIG_BLOCK
, &set
, &oset
);
749 kill (sm_child
, SIGKILL
);
753 sm_reply
.code
= sm_note
.code
;
754 sm_reply
.length
= sm_note
.length
;
755 memcpy (sm_reply
.text
, sm_note
.text
, sm_note
.length
+ 1);
762 BIO_ssl_shutdown(io
);
765 #endif /* TLS_SUPPORT */
767 if (sm_rfp
!= NULL
) {
772 if (sm_wfp
!= NULL
) {
778 if (sm_mts
== MTS_SMTP
) {
783 if (sasl_outbuffer
) {
784 free(sasl_outbuffer
);
789 #endif /* CYRUS_SASL */
790 } else if (sm_child
!= NOTOK
) {
791 status
= pidwait (sm_child
, OK
);
797 sm_rfp
= sm_wfp
= NULL
;
798 return (status
? RP_BHST
: RP_OK
);
803 * This function implements SASL authentication for SMTP. If this function
804 * completes successfully, then authentication is successful and we've
805 * (optionally) negotiated a security layer.
808 sm_auth_sasl(char *user
, int saslssf
, char *mechlist
, char *inhost
)
811 unsigned int buflen
, outlen
;
812 char *buf
, outbuf
[BUFSIZ
], host
[NI_MAXHOST
];
813 const char *chosen_mech
;
814 sasl_security_properties_t secprops
;
817 struct nmh_creds creds
= { 0, 0, 0 };
820 * Initialize the callback contexts
824 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
825 * to us on the command line, then call getpeername and do a
826 * reverse-address lookup on the IP address to get the name.
829 memset(host
, 0, sizeof(host
));
832 struct sockaddr_storage sin
;
833 socklen_t len
= sizeof(sin
);
836 if (getpeername(fileno(sm_wfp
), (struct sockaddr
*) &sin
, &len
) < 0) {
837 sm_ierror("getpeername on SMTP socket failed: %s",
842 result
= getnameinfo((struct sockaddr
*) &sin
, len
, host
, sizeof(host
),
843 NULL
, 0, NI_NAMEREQD
);
845 sm_ierror("Unable to look up name of connected host: %s",
846 gai_strerror(result
));
850 strncpy(host
, inhost
, sizeof(host
) - 1);
853 /* It's OK to copy the addresses here. The callbacks that use
854 them will only be called before this function returns. */
857 callbacks
[SM_SASL_N_CB_USER
].context
= &creds
;
858 callbacks
[SM_SASL_N_CB_AUTHNAME
].context
= &creds
;
859 callbacks
[SM_SASL_N_CB_PASS
].context
= &creds
;
861 result
= sasl_client_init(callbacks
);
863 if (result
!= SASL_OK
) {
864 sm_ierror("SASL library initialization failed: %s",
865 sasl_errstring(result
, NULL
, NULL
));
869 result
= sasl_client_new("smtp", host
, NULL
, NULL
, NULL
, 0, &conn
);
871 if (result
!= SASL_OK
) {
872 sm_ierror("SASL client initialization failed: %s",
873 sasl_errstring(result
, NULL
, NULL
));
878 * Initialize the security properties. But if TLS is active, then
879 * don't negotiate encryption here.
882 memset(&secprops
, 0, sizeof(secprops
));
883 secprops
.maxbufsize
= SASL_MAXRECVBUF
;
885 tls_active
? 0 : (saslssf
!= -1 ? (unsigned int) saslssf
: UINT_MAX
);
887 result
= sasl_setprop(conn
, SASL_SEC_PROPS
, &secprops
);
889 if (result
!= SASL_OK
) {
890 sm_ierror("SASL security property initialization failed: %s",
891 sasl_errstring(result
, NULL
, NULL
));
896 * Start the actual protocol. Feed the mech list into the library
897 * and get out a possible initial challenge
900 result
= sasl_client_start(conn
, mechlist
, NULL
, (const char **) &buf
,
901 &buflen
, (const char **) &chosen_mech
);
903 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
904 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn
));
909 * If we got an initial challenge, send it as part of the AUTH
910 * command; otherwise, just send a plain AUTH command.
914 status
= sasl_encode64(buf
, buflen
, outbuf
, sizeof(outbuf
), NULL
);
915 if (status
!= SASL_OK
) {
916 sm_ierror("SASL base64 encode failed: %s",
917 sasl_errstring(status
, NULL
, NULL
));
921 status
= smtalk(SM_AUTH
, "AUTH %s %s", chosen_mech
, outbuf
);
923 status
= smtalk(SM_AUTH
, "AUTH %s", chosen_mech
);
926 * Now we loop until we either fail, get a SASL_OK, or a 235
927 * response code. Receive the challenges and process them until
931 while (result
== SASL_CONTINUE
) {
934 * If we get a 235 response, that means authentication has
935 * succeeded and we need to break out of the loop (yes, even if
936 * we still get SASL_CONTINUE from sasl_client_step()).
938 * Otherwise, if we get a message that doesn't seem to be a
939 * valid response, then abort
944 else if (status
< 300 || status
> 399)
948 * Special case; a zero-length response from the SMTP server
949 * is returned as a single =. If we get that, then set buflen
950 * to be zero. Otherwise, just decode the response.
953 if (strcmp("=", sm_reply
.text
) == 0) {
956 result
= sasl_decode64(sm_reply
.text
, sm_reply
.length
,
957 outbuf
, sizeof(outbuf
), &outlen
);
958 if (result
!= SASL_OK
) {
959 smtalk(SM_AUTH
, "*");
960 sm_ierror("SASL base64 decode failed: %s",
961 sasl_errstring(result
, NULL
, NULL
));
966 result
= sasl_client_step(conn
, outbuf
, outlen
, NULL
,
967 (const char **) &buf
, &buflen
);
969 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
970 smtalk(SM_AUTH
, "*");
971 sm_ierror("SASL client negotiation failed: %s",
972 sasl_errstring(result
, NULL
, NULL
));
976 status
= sasl_encode64(buf
, buflen
, outbuf
, sizeof(outbuf
), NULL
);
978 if (status
!= SASL_OK
) {
979 smtalk(SM_AUTH
, "*");
980 sm_ierror("SASL base64 encode failed: %s",
981 sasl_errstring(status
, NULL
, NULL
));
985 status
= smtalk(SM_AUTH
, outbuf
);
989 * Make sure that we got the correct response
992 if (status
< 200 || status
> 299)
996 * We _should_ have completed the authentication successfully.
997 * Get a few properties from the authentication exchange.
1000 result
= sasl_getprop(conn
, SASL_MAXOUTBUF
, (const void **) &outbufmax
);
1002 if (result
!= SASL_OK
) {
1003 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
1004 sasl_errstring(result
, NULL
, NULL
));
1008 maxoutbuf
= *outbufmax
;
1010 result
= sasl_getprop(conn
, SASL_SSF
, (const void **) &ssf
);
1014 if (result
!= SASL_OK
) {
1015 sm_ierror("Cannot retrieve SASL negotiated security strength "
1016 "factor: %s", sasl_errstring(result
, NULL
, NULL
));
1021 sasl_outbuffer
= malloc(maxoutbuf
);
1023 if (sasl_outbuffer
== NULL
) {
1024 sm_ierror("Unable to allocate %d bytes for SASL output "
1025 "buffer", maxoutbuf
);
1030 sasl_inptr
= sasl_inbuffer
;
1032 sasl_outbuffer
= NULL
;
1033 /* Don't NULL out sasl_inbuffer because it could be used in
1043 * Our callback functions to feed data to the SASL library
1047 sm_get_user(void *context
, int id
, const char **result
, unsigned *len
)
1049 nmh_creds_t creds
= (nmh_creds_t
) context
;
1051 if (! result
|| ((id
!= SASL_CB_USER
) && (id
!= SASL_CB_AUTHNAME
)))
1052 return SASL_BADPARAM
;
1054 if (creds
->user
== NULL
) {
1056 * Pass the 1 third argument to nmh_get_credentials() so
1057 * that a default user if the -user switch to send(1)/post(8)
1058 * wasn't used, and so that a default password will be supplied.
1059 * That's used when those values really don't matter, and only
1060 * with legacy/.netrc, i.e., with a credentials profile entry.
1062 nmh_get_credentials (creds
->host
, creds
->user
, 1, creds
);
1065 *result
= creds
->user
;
1067 *len
= strlen(creds
->user
);
1073 sm_get_pass(sasl_conn_t
*conn
, void *context
, int id
,
1074 sasl_secret_t
**psecret
)
1076 nmh_creds_t creds
= (nmh_creds_t
) context
;
1081 if (! psecret
|| id
!= SASL_CB_PASS
)
1082 return SASL_BADPARAM
;
1084 if (creds
->password
== NULL
) {
1086 * Pass the 0 third argument to nmh_get_credentials() so
1087 * that the default password isn't used. With legacy/.netrc
1088 * credentials support, we'll only get here if the -user
1089 * switch to send(1)/post(8) wasn used.
1091 nmh_get_credentials (creds
->host
, creds
->user
, 0, creds
);
1094 len
= strlen (creds
->password
);
1096 if (! (*psecret
= (sasl_secret_t
*) malloc(sizeof(sasl_secret_t
) + len
))) {
1100 (*psecret
)->len
= len
;
1101 strcpy((char *) (*psecret
)->data
, creds
->password
);
1105 #endif /* CYRUS_SASL */
1108 sm_ierror (char *fmt
, ...)
1113 vsnprintf (sm_reply
.text
, sizeof(sm_reply
.text
), fmt
, ap
);
1116 sm_reply
.length
= strlen (sm_reply
.text
);
1117 sm_reply
.code
= NOTOK
;
1123 smtalk (int time
, char *fmt
, ...)
1127 char buffer
[BUFSIZ
];
1130 vsnprintf (buffer
, sizeof(buffer
), fmt
, ap
);
1135 printf("(sasl-encrypted) ");
1137 printf("(tls-encrypted) ");
1138 printf ("=> %s\n", buffer
);
1143 alarm ((unsigned) time
);
1144 if ((result
= sm_wrecord (buffer
, strlen (buffer
))) != NOTOK
)
1153 * write the buffer to the open SMTP channel
1157 sm_wrecord (char *buffer
, int len
)
1160 return sm_werror ();
1162 sm_fwrite (buffer
, len
);
1166 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1171 sm_wstream (char *buffer
, int len
)
1174 static char lc
= '\0';
1177 return sm_werror ();
1179 if (buffer
== NULL
&& len
== 0) {
1183 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1186 for (bp
= buffer
; len
> 0; bp
++, len
--) {
1195 sm_fputc ('.');/* FALL THROUGH */
1200 if (ferror (sm_wfp
))
1201 return sm_werror ();
1206 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1210 * Write out to the network, but do buffering for SASL (if enabled)
1214 sm_fwrite(char *buffer
, int len
)
1218 unsigned int outputlen
;
1220 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1221 #endif /* CYRUS_SASL */
1226 ret
= BIO_write(io
, buffer
, len
);
1229 sm_ierror("TLS error during write: %s",
1230 ERR_error_string(ERR_get_error(), NULL
));
1234 #endif /* TLS_SUPPORT */
1235 fwrite(buffer
, sizeof(*buffer
), len
, sm_wfp
);
1238 while (len
>= maxoutbuf
- sasl_outbuflen
) {
1239 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
,
1240 maxoutbuf
- sasl_outbuflen
);
1241 len
-= maxoutbuf
- sasl_outbuflen
;
1244 if (sasl_encode(conn
, sasl_outbuffer
, maxoutbuf
,
1245 &output
, &outputlen
) != SASL_OK
) {
1246 sm_ierror("Unable to SASL encode connection data: %s",
1247 sasl_errdetail(conn
));
1251 fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
);
1255 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
, len
);
1256 sasl_outbuflen
+= len
;
1259 #endif /* CYRUS_SASL */
1260 return ferror(sm_wfp
) ? NOTOK
: RP_OK
;
1265 * Negotiate Transport Layer Security
1274 const SSL_METHOD
*method
;
1277 SSL_load_error_strings();
1279 method
= TLSv1_client_method(); /* Not sure about this */
1281 /* Older ssl takes a non-const arg. */
1282 sslctx
= SSL_CTX_new((SSL_METHOD
*) method
);
1286 return sm_ierror("Unable to initialize OpenSSL context: %s",
1287 ERR_error_string(ERR_get_error(), NULL
));
1291 ssl
= SSL_new(sslctx
);
1295 return sm_ierror("Unable to create SSL connection: %s",
1296 ERR_error_string(ERR_get_error(), NULL
));
1299 sbior
= BIO_new_socket(fileno(sm_rfp
), BIO_NOCLOSE
);
1300 sbiow
= BIO_new_socket(fileno(sm_wfp
), BIO_NOCLOSE
);
1302 if (sbior
== NULL
|| sbiow
== NULL
) {
1304 return sm_ierror("Unable to create BIO endpoints: %s",
1305 ERR_error_string(ERR_get_error(), NULL
));
1308 SSL_set_bio(ssl
, sbior
, sbiow
);
1309 SSL_set_connect_state(ssl
);
1312 * Set up a BIO to handle buffering for us
1315 io
= BIO_new(BIO_f_buffer());
1319 return sm_ierror("Unable to create a buffer BIO: %s",
1320 ERR_error_string(ERR_get_error(), NULL
));
1323 ssl_bio
= BIO_new(BIO_f_ssl());
1327 return sm_ierror("Unable to create a SSL BIO: %s",
1328 ERR_error_string(ERR_get_error(), NULL
));
1331 BIO_set_ssl(ssl_bio
, ssl
, BIO_CLOSE
);
1332 BIO_push(io
, ssl_bio
);
1335 * Try doing the handshake now
1338 if (BIO_do_handshake(io
) < 1) {
1340 return sm_ierror("Unable to negotiate SSL connection: %s",
1341 ERR_error_string(ERR_get_error(), NULL
));
1345 const SSL_CIPHER
*cipher
= SSL_get_current_cipher(ssl
);
1346 printf("SSL negotiation successful: %s(%d) %s\n",
1347 SSL_CIPHER_get_name(cipher
),
1348 SSL_CIPHER_get_bits(cipher
, NULL
),
1349 SSL_CIPHER_get_version(cipher
));
1357 #endif /* TLS_SUPPORT */
1360 * Convenience functions to replace occurences of fputs() and fputc()
1364 sm_fputs(char *buffer
)
1366 return sm_fwrite(buffer
, strlen(buffer
));
1374 return sm_fwrite(&h
, 1);
1378 * Flush out any pending data on the connection
1386 unsigned int outputlen
;
1389 if (sasl_complete
== 1 && sasl_ssf
> 0 && sasl_outbuflen
> 0) {
1390 result
= sasl_encode(conn
, sasl_outbuffer
, sasl_outbuflen
,
1391 &output
, &outputlen
);
1392 if (result
!= SASL_OK
) {
1393 sm_ierror("Unable to SASL encode connection data: %s",
1394 sasl_errdetail(conn
));
1398 fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
);
1401 #endif /* CYRUS_SASL */
1405 (void) BIO_flush(io
);
1407 #endif /* TLS_SUPPORT */
1416 strlen (strcpy (sm_reply
.text
, sm_wfp
== NULL
? "no socket opened"
1417 : sm_alarmed
? "write to socket timed out"
1418 : "error writing to socket"));
1420 return (sm_reply
.code
= NOTOK
);
1427 int i
, code
, cont
, bc
= 0, rc
, more
;
1430 char **ehlo
= NULL
, buffer
[BUFSIZ
];
1433 static int at_least_once
= 0;
1435 if (at_least_once
) {
1438 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1452 sm_reply
.length
= 0;
1453 sm_reply
.text
[0] = 0;
1455 rc
= sizeof(sm_reply
.text
) - 1;
1457 for (more
= FALSE
; sm_rrecord ((char *) (bp
= (unsigned char *) buffer
),
1461 printf("(sasl-decrypted) ");
1463 printf("(tls-decrypted) ");
1464 printf ("<= %s\n", buffer
);
1469 && strncmp (buffer
, "250", sizeof("250") - 1) == 0
1470 && (buffer
[3] == '-' || doingEHLO
== 2)
1472 if (doingEHLO
== 2) {
1473 if ((*ehlo
= malloc ((size_t) (strlen (buffer
+ 4) + 1)))) {
1474 strcpy (*ehlo
++, buffer
+ 4);
1476 if (ehlo
>= EHLOkeys
+ MAXEHLO
)
1486 for (; bc
> 0 && (!isascii (*bp
) || !isdigit (*bp
)); bp
++, bc
--)
1490 code
= atoi ((char *) bp
);
1492 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1494 if (bc
> 0 && *bp
== '-') {
1497 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1502 if (code
!= sm_reply
.code
|| cont
)
1506 sm_reply
.code
= code
;
1509 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1510 strncpy (buffer
, sm_noreply
, sizeof(buffer
));
1511 bp
= (unsigned char *) buffer
;
1512 bc
= strlen (sm_noreply
);
1516 if ((i
= min (bc
, rc
)) > 0) {
1520 i
= strlen(sm_moreply
);
1521 if (more
&& rc
> i
+ 1) {
1522 memcpy (rp
, sm_moreply
, i
); /* safe because of check in if() */
1529 if (sm_reply
.code
< 100) {
1531 printf ("%s\n", sm_reply
.text
);
1537 sm_reply
.length
= rp
- sm_reply
.text
;
1538 sm_reply
.text
[sm_reply
.length
] = 0;
1539 return sm_reply
.code
;
1546 sm_rrecord (char *buffer
, int *len
)
1551 return sm_rerror(0);
1553 buffer
[*len
= 0] = 0;
1555 if ((retval
= sm_fgets (buffer
, BUFSIZ
, sm_rfp
)) != RP_OK
)
1556 return sm_rerror (retval
);
1557 *len
= strlen (buffer
);
1558 /* *len should be >0 except on EOF, but check for safety's sake */
1560 return sm_rerror (RP_EOF
);
1561 if (buffer
[*len
- 1] != '\n')
1562 while ((retval
= sm_fgetc (sm_rfp
)) != '\n' && retval
!= EOF
&&
1566 if ((*len
> 1) && (buffer
[*len
- 2] == '\r'))
1575 * Our version of fgets, which calls our private fgetc function
1579 sm_fgets(char *buffer
, int size
, FILE *f
)
1593 } while (size
> 1 && c
!= '\n');
1601 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1603 * Read from the network, but do SASL or TLS encryption
1609 char tmpbuf
[BUFSIZ
], *retbuf
;
1610 unsigned int retbufsize
= 0;
1614 * If we have leftover data, return it
1617 if (sasl_inbuflen
) {
1619 return (int) *sasl_inptr
++;
1623 * If not, read from the network until we have some data to return
1626 while (retbufsize
== 0) {
1630 cc
= SSL_read(ssl
, tmpbuf
, sizeof(tmpbuf
));
1633 result
= SSL_get_error(ssl
, cc
);
1635 if (result
!= SSL_ERROR_ZERO_RETURN
) {
1636 sm_ierror("TLS peer aborted connection");
1643 sm_ierror("SSL_read failed: %s",
1644 ERR_error_string(ERR_get_error(), NULL
));
1648 #endif /* TLS_SUPPORT */
1650 cc
= read(fileno(f
), tmpbuf
, sizeof(tmpbuf
));
1656 sm_ierror("Unable to read from network: %s", strerror(errno
));
1661 * Don't call sasl_decode unless sasl is complete and we have
1662 * encryption working
1666 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1670 result
= sasl_decode(conn
, tmpbuf
, cc
, (const char **) &retbuf
,
1673 if (result
!= SASL_OK
) {
1674 sm_ierror("Unable to decode SASL network data: %s",
1675 sasl_errdetail(conn
));
1679 #else /* ! CYRUS_SASL */
1682 #endif /* CYRUS_SASL */
1685 if (retbufsize
> SASL_MAXRECVBUF
) {
1686 sm_ierror("Received data (%d bytes) is larger than the buffer "
1687 "size (%d bytes)", retbufsize
, SASL_MAXRECVBUF
);
1691 memcpy(sasl_inbuffer
, retbuf
, retbufsize
);
1692 sasl_inptr
= sasl_inbuffer
+ 1;
1693 sasl_inbuflen
= retbufsize
- 1;
1695 return (int) sasl_inbuffer
[0];
1697 #endif /* CYRUS_SASL || TLS_SUPPORT */
1702 if (sm_mts
== MTS_SMTP
)
1704 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no socket opened"
1705 : sm_alarmed
? "read from socket timed out"
1706 : rc
== RP_EOF
? "premature end-of-file on socket"
1707 : "error reading from socket"));
1710 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no pipe opened"
1711 : sm_alarmed
? "read from pipe timed out"
1712 : rc
== RP_EOF
? "premature end-of-file on pipe"
1713 : "error reading from pipe"));
1715 return (sm_reply
.code
= NOTOK
);
1724 #ifndef RELIABLE_SIGNALS
1725 SIGNAL (SIGALRM
, alrmser
);
1730 printf ("timed out...\n");
1737 rp_string (int code
)
1740 static char buffer
[BUFSIZ
];
1742 switch (sm_reply
.code
!= NOTOK
? code
: NOTOK
) {
1762 snprintf (buffer
, sizeof(buffer
), "[%s] %s", text
, sm_reply
.text
);
1782 snprintf (buffer
, sizeof(buffer
), "[%s] %3d %s",
1783 text
, sm_reply
.code
, sm_reply
.text
);
1795 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1797 if (strncmp (ep
, s
, len
) == 0) {
1798 for (ep
+= len
; *ep
== ' '; ep
++)