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,
155 char *, char *, int);
156 static int sendmail_init (char *, char *, 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 sasl
, int saslssf
, char *saslmech
, char *user
, int tls
)
188 if (sm_mts
== MTS_SMTP
)
189 return smtp_init (client
, server
, port
, watch
, verbose
,
190 debug
, sasl
, saslssf
, saslmech
, user
, tls
);
192 return sendmail_init (client
, server
, watch
, verbose
,
193 debug
, sasl
, saslssf
, saslmech
, user
);
197 smtp_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
199 int sasl
, int saslssf
, char *saslmech
, char *user
, int tls
)
201 int result
, sd1
, sd2
;
204 #else /* CYRUS_SASL */
206 NMH_UNUSED (saslssf
);
207 NMH_UNUSED (saslmech
);
209 #endif /* CYRUS_SASL */
214 sm_verbose
= verbose
;
217 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
220 if (client
== NULL
|| *client
== '\0') {
224 client
= LocalName(1); /* no clientname -> LocalName */
229 * Last-ditch check just in case client still isn't set to anything
232 if (client
== NULL
|| *client
== '\0')
233 client
= "localhost";
235 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
236 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
238 return sm_ierror("Unable to allocate %d bytes for read buffer",
240 #endif /* CYRUS_SASL || TLS_SUPPORT */
242 if ((sd1
= rclient (server
, port
)) == NOTOK
)
245 if ((sd2
= dup (sd1
)) == NOTOK
) {
247 return sm_ierror ("unable to dup");
250 SIGNAL (SIGALRM
, alrmser
);
251 SIGNAL (SIGPIPE
, SIG_IGN
);
253 if ((sm_rfp
= fdopen (sd1
, "r")) == NULL
254 || (sm_wfp
= fdopen (sd2
, "w")) == NULL
) {
257 sm_rfp
= sm_wfp
= NULL
;
258 return sm_ierror ("unable to fdopen");
265 * If tls == 2, that means that the user requested "initial" TLS,
266 * which happens right after the connection has opened. Do that
271 result
= tls_negotiate();
274 * Note: if tls_negotiate() fails it will call sm_end() for us,
275 * which closes the connection.
280 #endif /* TLS_SUPPORT */
297 * Give EHLO or HELO command
301 result
= smtalk (SM_HELO
, "EHLO %s", client
);
304 if (result
>= 500 && result
<= 599)
305 result
= smtalk (SM_HELO
, "HELO %s", client
);
314 * If the user requested TLS support, then try to do the STARTTLS command
315 * as part of the initial dialog. Assuming this works, we then need to
316 * restart the EHLO dialog after TLS negotiation is complete.
320 if (! EHLOset("STARTTLS")) {
322 return sm_ierror("SMTP server does not support TLS");
325 result
= smtalk(SM_HELO
, "STARTTLS");
333 * Okay, the other side should be waiting for us to start TLS
334 * negotiation. Oblige them.
337 result
= tls_negotiate();
343 result
= smtalk (SM_HELO
, "EHLO %s", client
);
351 #else /* TLS_SUPPORT */
353 #endif /* TLS_SUPPORT */
357 * If the user asked for SASL, then check to see if the SMTP server
358 * supports it. Otherwise, error out (because the SMTP server
359 * might have been spoofed; we don't want to just silently not
364 if (! (server_mechs
= EHLOset("AUTH"))) {
366 return sm_ierror("SMTP server does not support SASL");
369 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
371 return sm_ierror("Requested SASL mech \"%s\" is not in the "
372 "list of supported mechanisms:\n%s",
373 saslmech
, server_mechs
);
376 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
382 #endif /* CYRUS_SASL */
385 if (watch
&& EHLOset ("XVRB"))
386 smtalk (SM_HELO
, "VERB on");
392 sendmail_init (char *client
, char *server
, int watch
, int verbose
,
393 int debug
, int sasl
, int saslssf
, char *saslmech
, char *user
)
395 unsigned int i
, result
, vecp
;
400 #else /* CYRUS_SASL */
403 NMH_UNUSED (saslssf
);
404 NMH_UNUSED (saslmech
);
406 #endif /* CYRUS_SASL */
411 sm_verbose
= verbose
;
413 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
416 if (client
== NULL
|| *client
== '\0') {
420 client
= LocalName(1); /* no clientname -> LocalName */
424 * Last-ditch check just in case client still isn't set to anything
427 if (client
== NULL
|| *client
== '\0')
428 client
= "localhost";
430 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
431 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
433 return sm_ierror("Unable to allocate %d bytes for read buffer",
435 #endif /* CYRUS_SASL || TLS_SUPPORT */
437 if (pipe (pdi
) == NOTOK
)
438 return sm_ierror ("no pipes");
439 if (pipe (pdo
) == NOTOK
) {
442 return sm_ierror ("no pipes");
445 for (i
= 0; (sm_child
= fork ()) == NOTOK
&& i
< 5; i
++)
454 return sm_ierror ("unable to fork");
457 if (pdo
[0] != fileno (stdin
))
458 dup2 (pdo
[0], fileno (stdin
));
459 if (pdi
[1] != fileno (stdout
))
460 dup2 (pdi
[1], fileno (stdout
));
461 if (pdi
[1] != fileno (stderr
))
462 dup2 (pdi
[1], fileno (stderr
));
463 for (i
= fileno (stderr
) + 1; i
< NBITS
; i
++)
467 vec
[vecp
++] = r1bindex (sendmail
, '/');
469 vec
[vecp
++] = watch
? "-odi" : "-odb";
470 vec
[vecp
++] = "-oem";
476 execvp (sendmail
, vec
);
477 fprintf (stderr
, "unable to exec ");
479 _exit (-1); /* NOTREACHED */
482 SIGNAL (SIGALRM
, alrmser
);
483 SIGNAL (SIGPIPE
, SIG_IGN
);
487 if ((sm_rfp
= fdopen (pdi
[0], "r")) == NULL
488 || (sm_wfp
= fdopen (pdo
[1], "w")) == NULL
) {
491 sm_rfp
= sm_wfp
= NULL
;
492 return sm_ierror ("unable to fdopen");
508 result
= smtalk (SM_HELO
, "EHLO %s", client
);
511 if (500 <= result
&& result
<= 599)
512 result
= smtalk (SM_HELO
, "HELO %s", client
);
525 * If the user asked for SASL, then check to see if the SMTP server
526 * supports it. Otherwise, error out (because the SMTP server
527 * might have been spoofed; we don't want to just silently not
532 if (! (server_mechs
= EHLOset("AUTH"))) {
534 return sm_ierror("SMTP server does not support SASL");
537 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
539 return sm_ierror("Requested SASL mech \"%s\" is not in the "
540 "list of supported mechanisms:\n%s",
541 saslmech
, server_mechs
);
544 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
550 #endif /* CYRUS_SASL */
553 smtalk (SM_HELO
, "VERB on");
560 rclient (char *server
, char *service
)
563 char response
[BUFSIZ
];
565 if ((sd
= client (server
, service
, response
, sizeof(response
),
569 sm_ierror ("%s", response
);
574 sm_winit (char *from
)
576 switch (smtalk (SM_MAIL
, "MAIL FROM:<%s>", from
)) {
593 sm_wadr (char *mbox
, char *host
, char *path
)
595 switch (smtalk (SM_RCPT
, host
&& *host
? "RCPT TO:<%s%s@%s>"
597 path
? path
: "", mbox
, host
)) {
607 #endif /* SENDMAILBUG */
632 switch (smtalk (SM_DATA
, "DATA")) {
641 #endif /* SENDMAILBUG */
658 sm_wtxt (char *buffer
, int len
)
664 result
= sm_wstream (buffer
, len
);
667 return (result
== NOTOK
? RP_BHST
: RP_OK
);
674 if (sm_wstream ((char *) NULL
, 0) == NOTOK
)
677 switch (smtalk (SM_DOT
+ 3 * sm_addrs
, ".")) {
685 #endif /* SENDMAILBUG */
703 if (sm_mts
== MTS_SENDMAIL_SMTP
) {
714 if (sm_rfp
== NULL
&& sm_wfp
== NULL
)
719 smtalk (SM_QUIT
, "QUIT");
723 sm_note
.code
= sm_reply
.code
;
724 sm_note
.length
= sm_reply
.length
;
725 memcpy (sm_note
.text
, sm_reply
.text
, sm_reply
.length
+ 1);/* fall */
727 if (smtalk (SM_RSET
, "RSET") == 250 && type
== DONE
)
729 if (sm_mts
== MTS_SMTP
)
730 smtalk (SM_QUIT
, "QUIT");
732 /* The SIGPIPE block replaces old calls to discard ().
733 We're not sure what the discard () calls were for,
734 maybe to prevent deadlock on old systems. In any
735 case, blocking SIGPIPE should be harmless.
736 Because the file handles are closed below, leave it
740 sigaddset (&set
, SIGPIPE
);
741 sigprocmask (SIG_BLOCK
, &set
, &oset
);
743 kill (sm_child
, SIGKILL
);
747 sm_reply
.code
= sm_note
.code
;
748 sm_reply
.length
= sm_note
.length
;
749 memcpy (sm_reply
.text
, sm_note
.text
, sm_note
.length
+ 1);
756 BIO_ssl_shutdown(io
);
759 #endif /* TLS_SUPPORT */
761 if (sm_rfp
!= NULL
) {
766 if (sm_wfp
!= NULL
) {
772 if (sm_mts
== MTS_SMTP
) {
777 if (sasl_outbuffer
) {
778 free(sasl_outbuffer
);
783 #endif /* CYRUS_SASL */
784 } else if (sm_child
!= NOTOK
) {
785 status
= pidwait (sm_child
, OK
);
791 sm_rfp
= sm_wfp
= NULL
;
792 return (status
? RP_BHST
: RP_OK
);
797 * This function implements SASL authentication for SMTP. If this function
798 * completes successfully, then authentication is successful and we've
799 * (optionally) negotiated a security layer.
802 sm_auth_sasl(char *user
, int saslssf
, char *mechlist
, char *inhost
)
805 unsigned int buflen
, outlen
;
806 char *buf
, outbuf
[BUFSIZ
], host
[NI_MAXHOST
];
807 const char *chosen_mech
;
808 sasl_security_properties_t secprops
;
811 struct nmh_creds creds
= { 0, 0, 0 };
814 * Initialize the callback contexts
818 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
819 * to us on the command line, then call getpeername and do a
820 * reverse-address lookup on the IP address to get the name.
823 memset(host
, 0, sizeof(host
));
826 struct sockaddr_storage sin
;
827 socklen_t len
= sizeof(sin
);
830 if (getpeername(fileno(sm_wfp
), (struct sockaddr
*) &sin
, &len
) < 0) {
831 sm_ierror("getpeername on SMTP socket failed: %s",
836 result
= getnameinfo((struct sockaddr
*) &sin
, len
, host
, sizeof(host
),
837 NULL
, 0, NI_NAMEREQD
);
839 sm_ierror("Unable to look up name of connected host: %s",
840 gai_strerror(result
));
844 strncpy(host
, inhost
, sizeof(host
) - 1);
847 /* It's OK to copy the addresses here. The callbacks that use
848 them will only be called before this function returns. */
851 callbacks
[SM_SASL_N_CB_USER
].context
= &creds
;
852 callbacks
[SM_SASL_N_CB_AUTHNAME
].context
= &creds
;
853 callbacks
[SM_SASL_N_CB_PASS
].context
= &creds
;
855 result
= sasl_client_init(callbacks
);
857 if (result
!= SASL_OK
) {
858 sm_ierror("SASL library initialization failed: %s",
859 sasl_errstring(result
, NULL
, NULL
));
863 result
= sasl_client_new("smtp", host
, NULL
, NULL
, NULL
, 0, &conn
);
865 if (result
!= SASL_OK
) {
866 sm_ierror("SASL client initialization failed: %s",
867 sasl_errstring(result
, NULL
, NULL
));
872 * Initialize the security properties. But if TLS is active, then
873 * don't negotiate encryption here.
876 memset(&secprops
, 0, sizeof(secprops
));
877 secprops
.maxbufsize
= SASL_MAXRECVBUF
;
879 tls_active
? 0 : (saslssf
!= -1 ? (unsigned int) saslssf
: UINT_MAX
);
881 result
= sasl_setprop(conn
, SASL_SEC_PROPS
, &secprops
);
883 if (result
!= SASL_OK
) {
884 sm_ierror("SASL security property initialization failed: %s",
885 sasl_errstring(result
, NULL
, NULL
));
890 * Start the actual protocol. Feed the mech list into the library
891 * and get out a possible initial challenge
894 result
= sasl_client_start(conn
, mechlist
, NULL
, (const char **) &buf
,
895 &buflen
, (const char **) &chosen_mech
);
897 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
898 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn
));
903 * If we got an initial challenge, send it as part of the AUTH
904 * command; otherwise, just send a plain AUTH command.
908 status
= sasl_encode64(buf
, buflen
, outbuf
, sizeof(outbuf
), NULL
);
909 if (status
!= SASL_OK
) {
910 sm_ierror("SASL base64 encode failed: %s",
911 sasl_errstring(status
, NULL
, NULL
));
915 status
= smtalk(SM_AUTH
, "AUTH %s %s", chosen_mech
, outbuf
);
917 status
= smtalk(SM_AUTH
, "AUTH %s", chosen_mech
);
920 * Now we loop until we either fail, get a SASL_OK, or a 235
921 * response code. Receive the challenges and process them until
925 while (result
== SASL_CONTINUE
) {
928 * If we get a 235 response, that means authentication has
929 * succeeded and we need to break out of the loop (yes, even if
930 * we still get SASL_CONTINUE from sasl_client_step()).
932 * Otherwise, if we get a message that doesn't seem to be a
933 * valid response, then abort
938 else if (status
< 300 || status
> 399)
942 * Special case; a zero-length response from the SMTP server
943 * is returned as a single =. If we get that, then set buflen
944 * to be zero. Otherwise, just decode the response.
947 if (strcmp("=", sm_reply
.text
) == 0) {
950 result
= sasl_decode64(sm_reply
.text
, sm_reply
.length
,
951 outbuf
, sizeof(outbuf
), &outlen
);
952 if (result
!= SASL_OK
) {
953 smtalk(SM_AUTH
, "*");
954 sm_ierror("SASL base64 decode failed: %s",
955 sasl_errstring(result
, NULL
, NULL
));
960 result
= sasl_client_step(conn
, outbuf
, outlen
, NULL
,
961 (const char **) &buf
, &buflen
);
963 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
964 smtalk(SM_AUTH
, "*");
965 sm_ierror("SASL client negotiation failed: %s",
966 sasl_errstring(result
, NULL
, NULL
));
970 status
= sasl_encode64(buf
, buflen
, outbuf
, sizeof(outbuf
), NULL
);
972 if (status
!= SASL_OK
) {
973 smtalk(SM_AUTH
, "*");
974 sm_ierror("SASL base64 encode failed: %s",
975 sasl_errstring(status
, NULL
, NULL
));
979 status
= smtalk(SM_AUTH
, outbuf
);
983 * Make sure that we got the correct response
986 if (status
< 200 || status
> 299)
990 * We _should_ have completed the authentication successfully.
991 * Get a few properties from the authentication exchange.
994 result
= sasl_getprop(conn
, SASL_MAXOUTBUF
, (const void **) &outbufmax
);
996 if (result
!= SASL_OK
) {
997 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
998 sasl_errstring(result
, NULL
, NULL
));
1002 maxoutbuf
= *outbufmax
;
1004 result
= sasl_getprop(conn
, SASL_SSF
, (const void **) &ssf
);
1008 if (result
!= SASL_OK
) {
1009 sm_ierror("Cannot retrieve SASL negotiated security strength "
1010 "factor: %s", sasl_errstring(result
, NULL
, NULL
));
1015 sasl_outbuffer
= malloc(maxoutbuf
);
1017 if (sasl_outbuffer
== NULL
) {
1018 sm_ierror("Unable to allocate %d bytes for SASL output "
1019 "buffer", maxoutbuf
);
1024 sasl_inptr
= sasl_inbuffer
;
1026 sasl_outbuffer
= NULL
;
1027 /* Don't NULL out sasl_inbuffer because it could be used in
1037 * Our callback functions to feed data to the SASL library
1041 sm_get_user(void *context
, int id
, const char **result
, unsigned *len
)
1043 nmh_creds_t creds
= (nmh_creds_t
) context
;
1045 if (! result
|| ((id
!= SASL_CB_USER
) && (id
!= SASL_CB_AUTHNAME
)))
1046 return SASL_BADPARAM
;
1048 if (creds
->user
== NULL
) {
1050 * Pass the 1 third argument to nmh_get_credentials() so
1051 * that a default user if the -user switch to send(1)/post(8)
1052 * wasn't used, and so that a default password will be supplied.
1053 * That's used when those values really don't matter, and only
1054 * with legacy/.netrc, i.e., with a credentials profile entry.
1056 if (nmh_get_credentials (creds
->host
, creds
->user
, 1, creds
) != OK
) {
1057 return SASL_BADPARAM
;
1061 *result
= creds
->user
;
1063 *len
= strlen(creds
->user
);
1069 sm_get_pass(sasl_conn_t
*conn
, void *context
, int id
,
1070 sasl_secret_t
**psecret
)
1072 nmh_creds_t creds
= (nmh_creds_t
) context
;
1077 if (! psecret
|| id
!= SASL_CB_PASS
)
1078 return SASL_BADPARAM
;
1080 if (creds
->password
== NULL
) {
1082 * Pass the 0 third argument to nmh_get_credentials() so
1083 * that the default password isn't used. With legacy/.netrc
1084 * credentials support, we'll only get here if the -user
1085 * switch to send(1)/post(8) wasn't used.
1087 if (nmh_get_credentials (creds
->host
, creds
->user
, 0, creds
) != OK
) {
1088 return SASL_BADPARAM
;
1092 len
= strlen (creds
->password
);
1094 if (! (*psecret
= (sasl_secret_t
*) malloc(sizeof(sasl_secret_t
) + len
))) {
1098 (*psecret
)->len
= len
;
1099 strcpy((char *) (*psecret
)->data
, creds
->password
);
1103 #endif /* CYRUS_SASL */
1106 sm_ierror (char *fmt
, ...)
1111 vsnprintf (sm_reply
.text
, sizeof(sm_reply
.text
), fmt
, ap
);
1114 sm_reply
.length
= strlen (sm_reply
.text
);
1115 sm_reply
.code
= NOTOK
;
1121 smtalk (int time
, char *fmt
, ...)
1125 char buffer
[BUFSIZ
];
1128 vsnprintf (buffer
, sizeof(buffer
), fmt
, ap
);
1133 printf("(sasl-encrypted) ");
1135 printf("(tls-encrypted) ");
1136 printf ("=> %s\n", buffer
);
1141 alarm ((unsigned) time
);
1142 if ((result
= sm_wrecord (buffer
, strlen (buffer
))) != NOTOK
)
1151 * write the buffer to the open SMTP channel
1155 sm_wrecord (char *buffer
, int len
)
1158 return sm_werror ();
1160 sm_fwrite (buffer
, len
);
1164 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1169 sm_wstream (char *buffer
, int len
)
1172 static char lc
= '\0';
1175 return sm_werror ();
1177 if (buffer
== NULL
&& len
== 0) {
1181 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1184 for (bp
= buffer
; len
> 0; bp
++, len
--) {
1193 sm_fputc ('.');/* FALL THROUGH */
1198 if (ferror (sm_wfp
))
1199 return sm_werror ();
1204 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1208 * Write out to the network, but do buffering for SASL (if enabled)
1212 sm_fwrite(char *buffer
, int len
)
1216 unsigned int outputlen
;
1218 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1219 #endif /* CYRUS_SASL */
1224 ret
= BIO_write(io
, buffer
, len
);
1227 sm_ierror("TLS error during write: %s",
1228 ERR_error_string(ERR_get_error(), NULL
));
1232 #endif /* TLS_SUPPORT */
1233 fwrite(buffer
, sizeof(*buffer
), len
, sm_wfp
);
1236 while (len
>= maxoutbuf
- sasl_outbuflen
) {
1237 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
,
1238 maxoutbuf
- sasl_outbuflen
);
1239 len
-= maxoutbuf
- sasl_outbuflen
;
1242 if (sasl_encode(conn
, sasl_outbuffer
, maxoutbuf
,
1243 &output
, &outputlen
) != SASL_OK
) {
1244 sm_ierror("Unable to SASL encode connection data: %s",
1245 sasl_errdetail(conn
));
1249 fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
);
1253 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
, len
);
1254 sasl_outbuflen
+= len
;
1257 #endif /* CYRUS_SASL */
1258 return ferror(sm_wfp
) ? NOTOK
: RP_OK
;
1263 * Negotiate Transport Layer Security
1272 const SSL_METHOD
*method
;
1275 SSL_load_error_strings();
1277 method
= TLSv1_client_method(); /* Not sure about this */
1279 /* Older ssl takes a non-const arg. */
1280 sslctx
= SSL_CTX_new((SSL_METHOD
*) method
);
1284 return sm_ierror("Unable to initialize OpenSSL context: %s",
1285 ERR_error_string(ERR_get_error(), NULL
));
1289 ssl
= SSL_new(sslctx
);
1293 return sm_ierror("Unable to create SSL connection: %s",
1294 ERR_error_string(ERR_get_error(), NULL
));
1297 sbior
= BIO_new_socket(fileno(sm_rfp
), BIO_NOCLOSE
);
1298 sbiow
= BIO_new_socket(fileno(sm_wfp
), BIO_NOCLOSE
);
1300 if (sbior
== NULL
|| sbiow
== NULL
) {
1302 return sm_ierror("Unable to create BIO endpoints: %s",
1303 ERR_error_string(ERR_get_error(), NULL
));
1306 SSL_set_bio(ssl
, sbior
, sbiow
);
1307 SSL_set_connect_state(ssl
);
1310 * Set up a BIO to handle buffering for us
1313 io
= BIO_new(BIO_f_buffer());
1317 return sm_ierror("Unable to create a buffer BIO: %s",
1318 ERR_error_string(ERR_get_error(), NULL
));
1321 ssl_bio
= BIO_new(BIO_f_ssl());
1325 return sm_ierror("Unable to create a SSL BIO: %s",
1326 ERR_error_string(ERR_get_error(), NULL
));
1329 BIO_set_ssl(ssl_bio
, ssl
, BIO_CLOSE
);
1330 BIO_push(io
, ssl_bio
);
1333 * Try doing the handshake now
1336 if (BIO_do_handshake(io
) < 1) {
1338 return sm_ierror("Unable to negotiate SSL connection: %s",
1339 ERR_error_string(ERR_get_error(), NULL
));
1343 const SSL_CIPHER
*cipher
= SSL_get_current_cipher(ssl
);
1344 printf("SSL negotiation successful: %s(%d) %s\n",
1345 SSL_CIPHER_get_name(cipher
),
1346 SSL_CIPHER_get_bits(cipher
, NULL
),
1347 SSL_CIPHER_get_version(cipher
));
1355 #endif /* TLS_SUPPORT */
1358 * Convenience functions to replace occurences of fputs() and fputc()
1362 sm_fputs(char *buffer
)
1364 return sm_fwrite(buffer
, strlen(buffer
));
1372 return sm_fwrite(&h
, 1);
1376 * Flush out any pending data on the connection
1384 unsigned int outputlen
;
1387 if (sasl_complete
== 1 && sasl_ssf
> 0 && sasl_outbuflen
> 0) {
1388 result
= sasl_encode(conn
, sasl_outbuffer
, sasl_outbuflen
,
1389 &output
, &outputlen
);
1390 if (result
!= SASL_OK
) {
1391 sm_ierror("Unable to SASL encode connection data: %s",
1392 sasl_errdetail(conn
));
1396 fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
);
1399 #endif /* CYRUS_SASL */
1403 (void) BIO_flush(io
);
1405 #endif /* TLS_SUPPORT */
1414 strlen (strcpy (sm_reply
.text
, sm_wfp
== NULL
? "no socket opened"
1415 : sm_alarmed
? "write to socket timed out"
1416 : "error writing to socket"));
1418 return (sm_reply
.code
= NOTOK
);
1425 int i
, code
, cont
, bc
= 0, rc
, more
;
1428 char **ehlo
= NULL
, buffer
[BUFSIZ
];
1431 static int at_least_once
= 0;
1433 if (at_least_once
) {
1436 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1450 sm_reply
.length
= 0;
1451 sm_reply
.text
[0] = 0;
1453 rc
= sizeof(sm_reply
.text
) - 1;
1455 for (more
= FALSE
; sm_rrecord ((char *) (bp
= (unsigned char *) buffer
),
1459 printf("(sasl-decrypted) ");
1461 printf("(tls-decrypted) ");
1462 printf ("<= %s\n", buffer
);
1467 && strncmp (buffer
, "250", sizeof("250") - 1) == 0
1468 && (buffer
[3] == '-' || doingEHLO
== 2)
1470 if (doingEHLO
== 2) {
1471 if ((*ehlo
= malloc ((size_t) (strlen (buffer
+ 4) + 1)))) {
1472 strcpy (*ehlo
++, buffer
+ 4);
1474 if (ehlo
>= EHLOkeys
+ MAXEHLO
)
1484 for (; bc
> 0 && (!isascii (*bp
) || !isdigit (*bp
)); bp
++, bc
--)
1488 code
= atoi ((char *) bp
);
1490 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1492 if (bc
> 0 && *bp
== '-') {
1495 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1500 if (code
!= sm_reply
.code
|| cont
)
1504 sm_reply
.code
= code
;
1507 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1508 strncpy (buffer
, sm_noreply
, sizeof(buffer
));
1509 bp
= (unsigned char *) buffer
;
1510 bc
= strlen (sm_noreply
);
1514 if ((i
= min (bc
, rc
)) > 0) {
1518 i
= strlen(sm_moreply
);
1519 if (more
&& rc
> i
+ 1) {
1520 memcpy (rp
, sm_moreply
, i
); /* safe because of check in if() */
1527 if (sm_reply
.code
< 100) {
1529 printf ("%s\n", sm_reply
.text
);
1535 sm_reply
.length
= rp
- sm_reply
.text
;
1536 sm_reply
.text
[sm_reply
.length
] = 0;
1537 return sm_reply
.code
;
1544 sm_rrecord (char *buffer
, int *len
)
1549 return sm_rerror(0);
1551 buffer
[*len
= 0] = 0;
1553 if ((retval
= sm_fgets (buffer
, BUFSIZ
, sm_rfp
)) != RP_OK
)
1554 return sm_rerror (retval
);
1555 *len
= strlen (buffer
);
1556 /* *len should be >0 except on EOF, but check for safety's sake */
1558 return sm_rerror (RP_EOF
);
1559 if (buffer
[*len
- 1] != '\n')
1560 while ((retval
= sm_fgetc (sm_rfp
)) != '\n' && retval
!= EOF
&&
1564 if ((*len
> 1) && (buffer
[*len
- 2] == '\r'))
1573 * Our version of fgets, which calls our private fgetc function
1577 sm_fgets(char *buffer
, int size
, FILE *f
)
1591 } while (size
> 1 && c
!= '\n');
1599 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1601 * Read from the network, but do SASL or TLS encryption
1607 char tmpbuf
[BUFSIZ
], *retbuf
;
1608 unsigned int retbufsize
= 0;
1612 * If we have leftover data, return it
1615 if (sasl_inbuflen
) {
1617 return (int) *sasl_inptr
++;
1621 * If not, read from the network until we have some data to return
1624 while (retbufsize
== 0) {
1628 cc
= SSL_read(ssl
, tmpbuf
, sizeof(tmpbuf
));
1631 result
= SSL_get_error(ssl
, cc
);
1633 if (result
!= SSL_ERROR_ZERO_RETURN
) {
1634 sm_ierror("TLS peer aborted connection");
1641 sm_ierror("SSL_read failed: %s",
1642 ERR_error_string(ERR_get_error(), NULL
));
1646 #endif /* TLS_SUPPORT */
1648 cc
= read(fileno(f
), tmpbuf
, sizeof(tmpbuf
));
1654 sm_ierror("Unable to read from network: %s", strerror(errno
));
1659 * Don't call sasl_decode unless sasl is complete and we have
1660 * encryption working
1664 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1668 result
= sasl_decode(conn
, tmpbuf
, cc
, (const char **) &retbuf
,
1671 if (result
!= SASL_OK
) {
1672 sm_ierror("Unable to decode SASL network data: %s",
1673 sasl_errdetail(conn
));
1677 #else /* ! CYRUS_SASL */
1680 #endif /* CYRUS_SASL */
1683 if (retbufsize
> SASL_MAXRECVBUF
) {
1684 sm_ierror("Received data (%d bytes) is larger than the buffer "
1685 "size (%d bytes)", retbufsize
, SASL_MAXRECVBUF
);
1689 memcpy(sasl_inbuffer
, retbuf
, retbufsize
);
1690 sasl_inptr
= sasl_inbuffer
+ 1;
1691 sasl_inbuflen
= retbufsize
- 1;
1693 return (int) sasl_inbuffer
[0];
1695 #endif /* CYRUS_SASL || TLS_SUPPORT */
1700 if (sm_mts
== MTS_SMTP
)
1702 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no socket opened"
1703 : sm_alarmed
? "read from socket timed out"
1704 : rc
== RP_EOF
? "premature end-of-file on socket"
1705 : "error reading from socket"));
1708 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no pipe opened"
1709 : sm_alarmed
? "read from pipe timed out"
1710 : rc
== RP_EOF
? "premature end-of-file on pipe"
1711 : "error reading from pipe"));
1713 return (sm_reply
.code
= NOTOK
);
1722 #ifndef RELIABLE_SIGNALS
1723 SIGNAL (SIGALRM
, alrmser
);
1728 printf ("timed out...\n");
1735 rp_string (int code
)
1738 static char buffer
[BUFSIZ
];
1740 switch (sm_reply
.code
!= NOTOK
? code
: NOTOK
) {
1760 snprintf (buffer
, sizeof(buffer
), "[%s] %s", text
, sm_reply
.text
);
1780 snprintf (buffer
, sizeof(buffer
), "[%s] %3d %s",
1781 text
, sm_reply
.code
, sm_reply
.text
);
1793 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1795 if (strncmp (ep
, s
, len
) == 0) {
1796 for (ep
+= len
; *ep
== ' '; ep
++)