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>
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>
29 #endif /* CYRUS_SASL */
32 #include <openssl/ssl.h>
33 #include <openssl/err.h>
34 #endif /* TLS_SUPPORT */
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
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.
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!
64 #define NBITS ((sizeof (int)) * 8)
67 * these codes must all be different!
69 #define SM_OPEN 300 /* Changed to 5 minutes to comply with a SHOULD in RFC 1123 */
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 */
81 static int sm_addrs
= 0;
82 static int sm_alarmed
= 0;
83 static int sm_child
= NOTOK
;
84 static int sm_debug
= 0;
85 static int sm_nl
= TRUE
;
86 static int sm_verbose
= 0;
88 static FILE *sm_rfp
= NULL
;
89 static FILE *sm_wfp
= NULL
;
93 * Some globals needed by SASL
96 static sasl_conn_t
*conn
= NULL
; /* SASL connection state */
97 static int sasl_complete
= 0; /* Has authentication succeeded? */
98 static sasl_ssf_t sasl_ssf
; /* Our security strength factor */
99 static int maxoutbuf
; /* Maximum crypto output buffer */
100 static char *sasl_outbuffer
; /* SASL output buffer for encryption */
101 static int sasl_outbuflen
; /* Current length of data in outbuf */
102 static int sm_get_user(void *, int, const char **, unsigned *);
103 static int sm_get_pass(sasl_conn_t
*, void *, int, sasl_secret_t
**);
105 static sasl_callback_t callbacks
[] = {
106 { SASL_CB_USER
, (sasl_callback_ft
) sm_get_user
, NULL
},
107 #define SM_SASL_N_CB_USER 0
108 { SASL_CB_AUTHNAME
, (sasl_callback_ft
) sm_get_user
, NULL
},
109 #define SM_SASL_N_CB_AUTHNAME 1
110 { SASL_CB_PASS
, (sasl_callback_ft
) sm_get_pass
, NULL
},
111 #define SM_SASL_N_CB_PASS 2
112 { SASL_CB_LIST_END
, NULL
, NULL
},
115 #else /* CYRUS_SASL */
117 #endif /* CYRUS_SASL */
120 static SSL_CTX
*sslctx
= NULL
;
121 static SSL
*ssl
= NULL
;
122 static BIO
*sbior
= NULL
;
123 static BIO
*sbiow
= NULL
;
124 static BIO
*io
= NULL
;
126 static int tls_negotiate(void);
127 #endif /* TLS_SUPPORT */
129 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
130 #define SASL_MAXRECVBUF 65536
131 static int sm_fgetc(FILE *);
132 static char *sasl_inbuffer
; /* SASL input buffer for encryption */
133 static char *sasl_inptr
; /* Pointer to current inbuf position */
134 static int sasl_inbuflen
; /* Current length of data in inbuf */
136 #define sm_fgetc fgetc
139 static int tls_active
= 0;
141 static char *sm_noreply
= "No reply text given";
142 static char *sm_moreply
= "; ";
143 static struct smtp sm_reply
;
147 static int doingEHLO
;
148 static char *EHLOkeys
[MAXEHLO
+ 1];
153 static int smtp_init (char *, char *, char *, int, int, int, int, int,
154 char *, char *, const char *, int);
155 static int sendmail_init (char *, char *, int, int, int, int, int,
158 static int rclient (char *, char *);
159 static int sm_ierror (char *fmt
, ...);
160 static int smtalk (int time
, char *fmt
, ...);
161 static int sm_wrecord (char *, int);
162 static int sm_wstream (char *, int);
163 static int sm_werror (void);
164 static int smhear (void);
165 static int sm_rrecord (char *, int *);
166 static int sm_rerror (int);
167 static void alrmser (int);
168 static char *EHLOset (char *);
169 static int sm_fwrite(char *, int);
170 static int sm_fputs(char *);
171 static int sm_fputc(int);
172 static void sm_fflush(void);
173 static int sm_fgets(char *, int, FILE *);
174 static int sm_auth_xoauth2(const char *);
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
,
187 const char *xoauth_client_res
, int tls
)
189 if (sm_mts
== MTS_SMTP
)
190 return smtp_init (client
, server
, port
, watch
, verbose
,
191 debug
, sasl
, saslssf
, saslmech
, user
,
192 xoauth_client_res
, tls
);
194 return sendmail_init (client
, server
, watch
, verbose
,
195 debug
, sasl
, saslssf
, saslmech
, user
);
199 smtp_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
201 int sasl
, int saslssf
, char *saslmech
, char *user
,
202 const char *xoauth_client_res
, int tls
)
204 int result
, sd1
, sd2
;
207 NMH_UNUSED (saslssf
);
208 NMH_UNUSED (saslmech
);
210 #endif /* CYRUS_SASL */
215 sm_verbose
= verbose
;
218 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
221 if (client
== NULL
|| *client
== '\0') {
225 client
= LocalName(1); /* no clientname -> LocalName */
230 * Last-ditch check just in case client still isn't set to anything
233 if (client
== NULL
|| *client
== '\0')
234 client
= "localhost";
236 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
237 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
239 return sm_ierror("Unable to allocate %d bytes for read buffer",
241 #endif /* CYRUS_SASL || TLS_SUPPORT */
243 if ((sd1
= rclient (server
, port
)) == NOTOK
)
246 if ((sd2
= dup (sd1
)) == NOTOK
) {
248 return sm_ierror ("unable to dup");
251 SIGNAL (SIGALRM
, alrmser
);
252 SIGNAL (SIGPIPE
, SIG_IGN
);
254 if ((sm_rfp
= fdopen (sd1
, "r")) == NULL
255 || (sm_wfp
= fdopen (sd2
, "w")) == NULL
) {
258 sm_rfp
= sm_wfp
= NULL
;
259 return sm_ierror ("unable to fdopen");
266 * If tls == 2, that means that the user requested "initial" TLS,
267 * which happens right after the connection has opened. Do that
272 result
= tls_negotiate();
275 * Note: if tls_negotiate() fails it will call sm_end() for us,
276 * which closes the connection.
281 #endif /* TLS_SUPPORT */
298 * Give EHLO or HELO command
302 result
= smtalk (SM_HELO
, "EHLO %s", client
);
305 if (result
>= 500 && result
<= 599)
306 result
= smtalk (SM_HELO
, "HELO %s", client
);
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.
321 if (! EHLOset("STARTTLS")) {
323 return sm_ierror("SMTP server does not support TLS");
326 result
= smtalk(SM_HELO
, "STARTTLS");
334 * Okay, the other side should be waiting for us to start TLS
335 * negotiation. Oblige them.
338 result
= tls_negotiate();
344 result
= smtalk (SM_HELO
, "EHLO %s", client
);
352 #else /* TLS_SUPPORT */
354 #endif /* TLS_SUPPORT */
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
366 if (! (server_mechs
= EHLOset("AUTH"))) {
368 return sm_ierror("SMTP server does not support SASL");
371 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
373 return sm_ierror("Requested SASL mech \"%s\" is not in the "
374 "list of supported mechanisms:\n%s",
375 saslmech
, server_mechs
);
378 /* Don't call sm_auth_sasl() for XAUTH2 with -sasl. Instead, call
379 sm_auth_xoauth2() below. */
380 if (xoauth_client_res
== NULL
&&
381 sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
387 #endif /* CYRUS_SASL */
389 if (xoauth_client_res
!= NULL
) {
391 if ((server_mechs
= EHLOset("AUTH")) == NULL
392 || stringdex("XOAUTH2", server_mechs
) == -1) {
394 return sm_ierror("SMTP server does not support SASL XOAUTH2");
396 if (sm_auth_xoauth2(xoauth_client_res
) != RP_OK
) {
403 if (watch
&& EHLOset ("XVRB"))
404 smtalk (SM_HELO
, "VERB on");
410 sendmail_init (char *client
, char *server
, int watch
, int verbose
,
411 int debug
, int sasl
, int saslssf
, char *saslmech
, char *user
)
413 unsigned int i
, result
, vecp
;
418 #else /* CYRUS_SASL */
421 NMH_UNUSED (saslssf
);
422 NMH_UNUSED (saslmech
);
424 #endif /* CYRUS_SASL */
429 sm_verbose
= verbose
;
431 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
434 if (client
== NULL
|| *client
== '\0') {
438 client
= LocalName(1); /* no clientname -> LocalName */
442 * Last-ditch check just in case client still isn't set to anything
445 if (client
== NULL
|| *client
== '\0')
446 client
= "localhost";
448 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
449 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
451 return sm_ierror("Unable to allocate %d bytes for read buffer",
453 #endif /* CYRUS_SASL || TLS_SUPPORT */
455 if (pipe (pdi
) == NOTOK
)
456 return sm_ierror ("no pipes");
457 if (pipe (pdo
) == NOTOK
) {
460 return sm_ierror ("no pipes");
463 for (i
= 0; (sm_child
= fork ()) == NOTOK
&& i
< 5; i
++)
472 return sm_ierror ("unable to fork");
475 if (pdo
[0] != fileno (stdin
))
476 dup2 (pdo
[0], fileno (stdin
));
477 if (pdi
[1] != fileno (stdout
))
478 dup2 (pdi
[1], fileno (stdout
));
479 if (pdi
[1] != fileno (stderr
))
480 dup2 (pdi
[1], fileno (stderr
));
481 for (i
= fileno (stderr
) + 1; i
< NBITS
; i
++)
485 vec
[vecp
++] = r1bindex (sendmail
, '/');
487 vec
[vecp
++] = watch
? "-odi" : "-odb";
488 vec
[vecp
++] = "-oem";
494 execvp (sendmail
, vec
);
495 fprintf (stderr
, "unable to exec ");
497 _exit (-1); /* NOTREACHED */
500 SIGNAL (SIGALRM
, alrmser
);
501 SIGNAL (SIGPIPE
, SIG_IGN
);
505 if ((sm_rfp
= fdopen (pdi
[0], "r")) == NULL
506 || (sm_wfp
= fdopen (pdo
[1], "w")) == NULL
) {
509 sm_rfp
= sm_wfp
= NULL
;
510 return sm_ierror ("unable to fdopen");
526 result
= smtalk (SM_HELO
, "EHLO %s", client
);
529 if (500 <= result
&& result
<= 599)
530 result
= smtalk (SM_HELO
, "HELO %s", client
);
543 * If the user asked for SASL, then check to see if the SMTP server
544 * supports it. Otherwise, error out (because the SMTP server
545 * might have been spoofed; we don't want to just silently not
550 if (! (server_mechs
= EHLOset("AUTH"))) {
552 return sm_ierror("SMTP server does not support SASL");
555 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
557 return sm_ierror("Requested SASL mech \"%s\" is not in the "
558 "list of supported mechanisms:\n%s",
559 saslmech
, server_mechs
);
562 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
568 #endif /* CYRUS_SASL */
571 smtalk (SM_HELO
, "VERB on");
578 rclient (char *server
, char *service
)
581 char response
[BUFSIZ
];
583 if ((sd
= client (server
, service
, response
, sizeof(response
),
587 sm_ierror ("%s", response
);
592 sm_winit (char *from
)
594 switch (smtalk (SM_MAIL
, "MAIL FROM:<%s>", from
)) {
611 sm_wadr (char *mbox
, char *host
, char *path
)
613 switch (smtalk (SM_RCPT
, host
&& *host
? "RCPT TO:<%s%s@%s>"
615 path
? path
: "", mbox
, host
)) {
625 #endif /* SENDMAILBUG */
650 switch (smtalk (SM_DATA
, "DATA")) {
659 #endif /* SENDMAILBUG */
676 sm_wtxt (char *buffer
, int len
)
682 result
= sm_wstream (buffer
, len
);
685 return (result
== NOTOK
? RP_BHST
: RP_OK
);
692 if (sm_wstream ((char *) NULL
, 0) == NOTOK
)
695 switch (smtalk (SM_DOT
+ 3 * sm_addrs
, ".")) {
703 #endif /* SENDMAILBUG */
721 if (sm_mts
== MTS_SENDMAIL_SMTP
) {
732 if (sm_rfp
== NULL
&& sm_wfp
== NULL
)
737 smtalk (SM_QUIT
, "QUIT");
741 sm_note
.code
= sm_reply
.code
;
742 sm_note
.length
= sm_reply
.length
;
743 memcpy (sm_note
.text
, sm_reply
.text
, sm_reply
.length
+ 1);/* fall */
745 if (smtalk (SM_RSET
, "RSET") == 250 && type
== DONE
)
747 if (sm_mts
== MTS_SMTP
)
748 smtalk (SM_QUIT
, "QUIT");
750 /* The SIGPIPE block replaces old calls to discard ().
751 We're not sure what the discard () calls were for,
752 maybe to prevent deadlock on old systems. In any
753 case, blocking SIGPIPE should be harmless.
754 Because the file handles are closed below, leave it
758 sigaddset (&set
, SIGPIPE
);
759 sigprocmask (SIG_BLOCK
, &set
, &oset
);
761 kill (sm_child
, SIGKILL
);
765 sm_reply
.code
= sm_note
.code
;
766 sm_reply
.length
= sm_note
.length
;
767 memcpy (sm_reply
.text
, sm_note
.text
, sm_note
.length
+ 1);
774 BIO_ssl_shutdown(io
);
777 #endif /* TLS_SUPPORT */
779 if (sm_rfp
!= NULL
) {
784 if (sm_wfp
!= NULL
) {
790 if (sm_mts
== MTS_SMTP
) {
795 if (sasl_outbuffer
) {
796 free(sasl_outbuffer
);
801 #endif /* CYRUS_SASL */
802 } else if (sm_child
!= NOTOK
) {
803 status
= pidwait (sm_child
, OK
);
809 sm_rfp
= sm_wfp
= NULL
;
810 return (status
? RP_BHST
: RP_OK
);
815 * This function implements SASL authentication for SMTP. If this function
816 * completes successfully, then authentication is successful and we've
817 * (optionally) negotiated a security layer.
820 #define CHECKB64SIZE(insize, outbuf, outsize) \
821 { size_t wantout = (((insize + 2) / 3) * 4) + 32; \
822 if (wantout > outsize) { \
823 outbuf = mh_xrealloc(outbuf, outsize = wantout); \
828 sm_auth_sasl(char *user
, int saslssf
, char *mechlist
, char *inhost
)
831 unsigned int buflen
, outlen
;
832 char *buf
, *outbuf
= NULL
, host
[NI_MAXHOST
];
833 const char *chosen_mech
;
834 sasl_security_properties_t secprops
;
837 struct nmh_creds creds
= { 0, 0, 0 };
838 size_t outbufsize
= 0;
841 * Initialize the callback contexts
845 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
846 * to us on the command line, then call getpeername and do a
847 * reverse-address lookup on the IP address to get the name.
850 memset(host
, 0, sizeof(host
));
853 struct sockaddr_storage sin
;
854 socklen_t len
= sizeof(sin
);
857 if (getpeername(fileno(sm_wfp
), (struct sockaddr
*) &sin
, &len
) < 0) {
858 sm_ierror("getpeername on SMTP socket failed: %s",
863 result
= getnameinfo((struct sockaddr
*) &sin
, len
, host
, sizeof(host
),
864 NULL
, 0, NI_NAMEREQD
);
866 sm_ierror("Unable to look up name of connected host: %s",
867 gai_strerror(result
));
871 strncpy(host
, inhost
, sizeof(host
) - 1);
874 /* It's OK to copy the addresses here. The callbacks that use
875 them will only be called before this function returns. */
878 callbacks
[SM_SASL_N_CB_USER
].context
= &creds
;
879 callbacks
[SM_SASL_N_CB_AUTHNAME
].context
= &creds
;
880 callbacks
[SM_SASL_N_CB_PASS
].context
= &creds
;
882 result
= sasl_client_init(callbacks
);
884 if (result
!= SASL_OK
) {
885 sm_ierror("SASL library initialization failed: %s",
886 sasl_errstring(result
, NULL
, NULL
));
890 result
= sasl_client_new("smtp", host
, NULL
, NULL
, NULL
, 0, &conn
);
892 if (result
!= SASL_OK
) {
893 sm_ierror("SASL client initialization failed: %s",
894 sasl_errstring(result
, NULL
, NULL
));
899 * Initialize the security properties. But if TLS is active, then
900 * don't negotiate encryption here.
903 memset(&secprops
, 0, sizeof(secprops
));
904 secprops
.maxbufsize
= SASL_MAXRECVBUF
;
906 tls_active
? 0 : (saslssf
!= -1 ? (unsigned int) saslssf
: UINT_MAX
);
908 result
= sasl_setprop(conn
, SASL_SEC_PROPS
, &secprops
);
910 if (result
!= SASL_OK
) {
911 sm_ierror("SASL security property initialization failed: %s",
912 sasl_errstring(result
, NULL
, NULL
));
917 * Start the actual protocol. Feed the mech list into the library
918 * and get out a possible initial challenge
921 result
= sasl_client_start(conn
, mechlist
, NULL
, (const char **) &buf
,
922 &buflen
, (const char **) &chosen_mech
);
924 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
925 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn
));
930 * If we got an initial challenge, send it as part of the AUTH
931 * command; otherwise, just send a plain AUTH command.
935 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
936 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
937 if (status
!= SASL_OK
) {
938 sm_ierror("SASL base64 encode failed: %s",
939 sasl_errstring(status
, NULL
, NULL
));
945 status
= smtalk(SM_AUTH
, "AUTH %s %s", chosen_mech
, outbuf
);
947 status
= smtalk(SM_AUTH
, "AUTH %s", chosen_mech
);
950 * Now we loop until we either fail, get a SASL_OK, or a 235
951 * response code. Receive the challenges and process them until
955 while (result
== SASL_CONTINUE
) {
958 * If we get a 235 response, that means authentication has
959 * succeeded and we need to break out of the loop (yes, even if
960 * we still get SASL_CONTINUE from sasl_client_step()).
962 * Otherwise, if we get a message that doesn't seem to be a
963 * valid response, then abort
968 else if (status
< 300 || status
> 399) {
975 * Special case; a zero-length response from the SMTP server
976 * is returned as a single =. If we get that, then set buflen
977 * to be zero. Otherwise, just decode the response.
980 if (strcmp("=", sm_reply
.text
) == 0) {
983 if (sm_reply
.length
> (int) outbufsize
) {
984 outbuf
= mh_xrealloc(outbuf
, outbufsize
= sm_reply
.length
);
987 result
= sasl_decode64(sm_reply
.text
, sm_reply
.length
,
988 outbuf
, outbufsize
, &outlen
);
989 if (result
!= SASL_OK
) {
990 smtalk(SM_AUTH
, "*");
991 sm_ierror("SASL base64 decode failed: %s",
992 sasl_errstring(result
, NULL
, NULL
));
999 result
= sasl_client_step(conn
, outbuf
, outlen
, NULL
,
1000 (const char **) &buf
, &buflen
);
1002 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
1003 smtalk(SM_AUTH
, "*");
1004 sm_ierror("SASL client negotiation failed: %s",
1005 sasl_errstring(result
, NULL
, NULL
));
1011 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
1012 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
1014 if (status
!= SASL_OK
) {
1015 smtalk(SM_AUTH
, "*");
1016 sm_ierror("SASL base64 encode failed: %s",
1017 sasl_errstring(status
, NULL
, NULL
));
1023 status
= smtalk(SM_AUTH
, outbuf
);
1030 * Make sure that we got the correct response
1033 if (status
< 200 || status
> 299)
1037 * We _should_ have completed the authentication successfully.
1038 * Get a few properties from the authentication exchange.
1041 result
= sasl_getprop(conn
, SASL_MAXOUTBUF
, (const void **) &outbufmax
);
1043 if (result
!= SASL_OK
) {
1044 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
1045 sasl_errstring(result
, NULL
, NULL
));
1049 maxoutbuf
= *outbufmax
;
1051 result
= sasl_getprop(conn
, SASL_SSF
, (const void **) &ssf
);
1055 if (result
!= SASL_OK
) {
1056 sm_ierror("Cannot retrieve SASL negotiated security strength "
1057 "factor: %s", sasl_errstring(result
, NULL
, NULL
));
1062 sasl_outbuffer
= malloc(maxoutbuf
);
1064 if (sasl_outbuffer
== NULL
) {
1065 sm_ierror("Unable to allocate %d bytes for SASL output "
1066 "buffer", maxoutbuf
);
1071 sasl_inptr
= sasl_inbuffer
;
1073 sasl_outbuffer
= NULL
;
1074 /* Don't NULL out sasl_inbuffer because it could be used in
1084 * Our callback functions to feed data to the SASL library
1088 sm_get_user(void *context
, int id
, const char **result
, unsigned *len
)
1090 nmh_creds_t creds
= (nmh_creds_t
) context
;
1092 if (! result
|| ((id
!= SASL_CB_USER
) && (id
!= SASL_CB_AUTHNAME
)))
1093 return SASL_BADPARAM
;
1095 if (creds
->user
== NULL
) {
1097 * Pass the 1 third argument to nmh_get_credentials() so
1098 * that a default user if the -user switch to send(1)/post(8)
1099 * wasn't used, and so that a default password will be supplied.
1100 * That's used when those values really don't matter, and only
1101 * with legacy/.netrc, i.e., with a credentials profile entry.
1103 if (nmh_get_credentials (creds
->host
, creds
->user
, 1, creds
) != OK
) {
1104 return SASL_BADPARAM
;
1108 *result
= creds
->user
;
1110 *len
= strlen(creds
->user
);
1116 sm_get_pass(sasl_conn_t
*conn
, void *context
, int id
,
1117 sasl_secret_t
**psecret
)
1119 nmh_creds_t creds
= (nmh_creds_t
) context
;
1124 if (! psecret
|| id
!= SASL_CB_PASS
)
1125 return SASL_BADPARAM
;
1127 if (creds
->password
== NULL
) {
1129 * Pass the 0 third argument to nmh_get_credentials() so
1130 * that the default password isn't used. With legacy/.netrc
1131 * credentials support, we'll only get here if the -user
1132 * switch to send(1)/post(8) wasn't used.
1134 if (nmh_get_credentials (creds
->host
, creds
->user
, 0, creds
) != OK
) {
1135 return SASL_BADPARAM
;
1139 len
= strlen (creds
->password
);
1141 if (! (*psecret
= (sasl_secret_t
*) malloc(sizeof(sasl_secret_t
) + len
))) {
1145 (*psecret
)->len
= len
;
1146 strcpy((char *) (*psecret
)->data
, creds
->password
);
1150 #endif /* CYRUS_SASL */
1152 /* https://developers.google.com/gmail/xoauth2_protocol */
1154 sm_auth_xoauth2(const char *client_res
)
1156 int status
= smtalk(SM_AUTH
, "AUTH XOAUTH2 %s", client_res
);
1157 if (status
== 235) {
1163 * Status is 334 and sm_reply.text contains base64-encoded JSON. As far as
1164 * epg can tell, no matter the error, the JSON is always the same:
1165 * {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
1166 * I tried these errors:
1172 /* Then we're supposed to send an empty response ("\r\n"). */
1173 smtalk(SM_AUTH
, "");
1175 * And now we always get this, again, no matter the error:
1176 * 535-5.7.8 Username and Password not accepted. Learn more at
1177 * 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257
1183 sm_ierror (char *fmt
, ...)
1188 vsnprintf (sm_reply
.text
, sizeof(sm_reply
.text
), fmt
, ap
);
1191 sm_reply
.length
= strlen (sm_reply
.text
);
1192 sm_reply
.code
= NOTOK
;
1198 smtalk (int time
, char *fmt
, ...)
1203 size_t bufsize
= BUFSIZ
;
1205 buffer
= mh_xmalloc(bufsize
);
1208 result
= vsnprintf (buffer
, bufsize
, fmt
, ap
);
1211 if (result
> (int) bufsize
) {
1212 buffer
= mh_xrealloc(buffer
, bufsize
= result
+ 1);
1214 vsnprintf (buffer
, bufsize
, fmt
, ap
);
1220 printf("(sasl-encrypted) ");
1222 printf("(tls-encrypted) ");
1223 printf ("=> %s\n", buffer
);
1228 alarm ((unsigned) time
);
1229 if ((result
= sm_wrecord (buffer
, strlen (buffer
))) != NOTOK
)
1240 * write the buffer to the open SMTP channel
1244 sm_wrecord (char *buffer
, int len
)
1247 return sm_werror ();
1249 sm_fwrite (buffer
, len
);
1253 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1258 sm_wstream (char *buffer
, int len
)
1261 static char lc
= '\0';
1264 return sm_werror ();
1266 if (buffer
== NULL
&& len
== 0) {
1270 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1273 for (bp
= buffer
; bp
&& len
> 0; bp
++, len
--) {
1282 sm_fputc ('.');/* FALL THROUGH */
1287 if (ferror (sm_wfp
))
1288 return sm_werror ();
1293 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1297 * Write out to the network, but do buffering for SASL (if enabled)
1301 sm_fwrite(char *buffer
, int len
)
1305 unsigned int outputlen
;
1307 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1308 #endif /* CYRUS_SASL */
1313 ret
= BIO_write(io
, buffer
, len
);
1316 sm_ierror("TLS error during write: %s",
1317 ERR_error_string(ERR_get_error(), NULL
));
1321 #endif /* TLS_SUPPORT */
1322 if ((int) fwrite(buffer
, sizeof(*buffer
), len
, sm_wfp
) < len
) {
1323 advise ("sm_fwrite", "fwrite");
1327 while (len
>= maxoutbuf
- sasl_outbuflen
) {
1328 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
,
1329 maxoutbuf
- sasl_outbuflen
);
1330 len
-= maxoutbuf
- sasl_outbuflen
;
1333 if (sasl_encode(conn
, sasl_outbuffer
, maxoutbuf
,
1334 &output
, &outputlen
) != SASL_OK
) {
1335 sm_ierror("Unable to SASL encode connection data: %s",
1336 sasl_errdetail(conn
));
1340 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) <
1342 advise ("sm_fwrite", "fwrite");
1347 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
, len
);
1348 sasl_outbuflen
+= len
;
1351 #endif /* CYRUS_SASL */
1352 return ferror(sm_wfp
) ? NOTOK
: RP_OK
;
1357 * Negotiate Transport Layer Security
1366 const SSL_METHOD
*method
;
1369 SSL_load_error_strings();
1371 method
= TLSv1_client_method(); /* Not sure about this */
1373 /* Older ssl takes a non-const arg. */
1374 sslctx
= SSL_CTX_new((SSL_METHOD
*) method
);
1378 return sm_ierror("Unable to initialize OpenSSL context: %s",
1379 ERR_error_string(ERR_get_error(), NULL
));
1383 ssl
= SSL_new(sslctx
);
1387 return sm_ierror("Unable to create SSL connection: %s",
1388 ERR_error_string(ERR_get_error(), NULL
));
1391 sbior
= BIO_new_socket(fileno(sm_rfp
), BIO_NOCLOSE
);
1392 sbiow
= BIO_new_socket(fileno(sm_wfp
), BIO_NOCLOSE
);
1394 if (sbior
== NULL
|| sbiow
== NULL
) {
1396 return sm_ierror("Unable to create BIO endpoints: %s",
1397 ERR_error_string(ERR_get_error(), NULL
));
1400 SSL_set_bio(ssl
, sbior
, sbiow
);
1401 SSL_set_connect_state(ssl
);
1404 * Set up a BIO to handle buffering for us
1407 io
= BIO_new(BIO_f_buffer());
1411 return sm_ierror("Unable to create a buffer BIO: %s",
1412 ERR_error_string(ERR_get_error(), NULL
));
1415 ssl_bio
= BIO_new(BIO_f_ssl());
1419 return sm_ierror("Unable to create a SSL BIO: %s",
1420 ERR_error_string(ERR_get_error(), NULL
));
1423 BIO_set_ssl(ssl_bio
, ssl
, BIO_CLOSE
);
1424 BIO_push(io
, ssl_bio
);
1427 * Try doing the handshake now
1430 if (BIO_do_handshake(io
) < 1) {
1432 return sm_ierror("Unable to negotiate SSL connection: %s",
1433 ERR_error_string(ERR_get_error(), NULL
));
1437 const SSL_CIPHER
*cipher
= SSL_get_current_cipher(ssl
);
1438 printf("SSL negotiation successful: %s(%d) %s\n",
1439 SSL_CIPHER_get_name(cipher
),
1440 SSL_CIPHER_get_bits(cipher
, NULL
),
1441 SSL_CIPHER_get_version(cipher
));
1449 #endif /* TLS_SUPPORT */
1452 * Convenience functions to replace occurrences of fputs() and fputc()
1456 sm_fputs(char *buffer
)
1458 return sm_fwrite(buffer
, strlen(buffer
));
1466 return sm_fwrite(&h
, 1);
1470 * Flush out any pending data on the connection
1478 unsigned int outputlen
;
1481 if (sasl_complete
== 1 && sasl_ssf
> 0 && sasl_outbuflen
> 0) {
1482 result
= sasl_encode(conn
, sasl_outbuffer
, sasl_outbuflen
,
1483 &output
, &outputlen
);
1484 if (result
!= SASL_OK
) {
1485 sm_ierror("Unable to SASL encode connection data: %s",
1486 sasl_errdetail(conn
));
1490 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) < outputlen
) {
1491 advise ("sm_fflush", "fwrite");
1495 #endif /* CYRUS_SASL */
1499 (void) BIO_flush(io
);
1501 #endif /* TLS_SUPPORT */
1510 strlen (strcpy (sm_reply
.text
, sm_wfp
== NULL
? "no socket opened"
1511 : sm_alarmed
? "write to socket timed out"
1512 : "error writing to socket"));
1514 return (sm_reply
.code
= NOTOK
);
1521 int i
, code
, cont
, bc
= 0, rc
, more
;
1524 char **ehlo
= EHLOkeys
, buffer
[BUFSIZ
];
1527 static int at_least_once
= 0;
1529 if (at_least_once
) {
1532 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1546 sm_reply
.length
= 0;
1547 sm_reply
.text
[0] = 0;
1549 rc
= sizeof(sm_reply
.text
) - 1;
1551 for (more
= FALSE
; sm_rrecord ((char *) (bp
= (unsigned char *) buffer
),
1555 printf("(sasl-decrypted) ");
1557 printf("(tls-decrypted) ");
1558 printf ("<= %s\n", buffer
);
1563 && strncmp (buffer
, "250", sizeof("250") - 1) == 0
1564 && (buffer
[3] == '-' || doingEHLO
== 2)
1566 if (doingEHLO
== 2) {
1567 if ((*ehlo
= malloc ((size_t) (strlen (buffer
+ 4) + 1)))) {
1568 strcpy (*ehlo
++, buffer
+ 4);
1570 if (ehlo
>= EHLOkeys
+ MAXEHLO
)
1580 for (; bc
> 0 && (!isascii (*bp
) || !isdigit (*bp
)); bp
++, bc
--)
1584 code
= atoi ((char *) bp
);
1586 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1588 if (bc
> 0 && *bp
== '-') {
1591 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1596 if (code
!= sm_reply
.code
|| cont
)
1600 sm_reply
.code
= code
;
1603 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1604 strncpy (buffer
, sm_noreply
, sizeof(buffer
));
1605 bp
= (unsigned char *) buffer
;
1606 bc
= strlen (sm_noreply
);
1610 if ((i
= min (bc
, rc
)) > 0) {
1614 i
= strlen(sm_moreply
);
1615 if (more
&& rc
> i
+ 1) {
1616 memcpy (rp
, sm_moreply
, i
); /* safe because of check in if() */
1623 if (sm_reply
.code
< 100) {
1625 printf ("%s\n", sm_reply
.text
);
1631 sm_reply
.length
= rp
- sm_reply
.text
;
1632 sm_reply
.text
[sm_reply
.length
] = 0;
1633 return sm_reply
.code
;
1640 sm_rrecord (char *buffer
, int *len
)
1645 return sm_rerror(0);
1647 buffer
[*len
= 0] = 0;
1649 if ((retval
= sm_fgets (buffer
, BUFSIZ
, sm_rfp
)) != RP_OK
)
1650 return sm_rerror (retval
);
1651 *len
= strlen (buffer
);
1652 /* *len should be >0 except on EOF, but check for safety's sake */
1654 return sm_rerror (RP_EOF
);
1655 if (buffer
[*len
- 1] != '\n')
1656 while ((retval
= sm_fgetc (sm_rfp
)) != '\n' && retval
!= EOF
&&
1660 if ((*len
> 1) && (buffer
[*len
- 2] == '\r'))
1669 * Our version of fgets, which calls our private fgetc function
1673 sm_fgets(char *buffer
, int size
, FILE *f
)
1687 } while (size
> 1 && c
!= '\n');
1695 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1697 * Read from the network, but do SASL or TLS encryption
1703 char tmpbuf
[BUFSIZ
], *retbuf
;
1704 unsigned int retbufsize
= 0;
1708 * If we have leftover data, return it
1711 if (sasl_inbuflen
) {
1713 return (int) *sasl_inptr
++;
1717 * If not, read from the network until we have some data to return
1720 while (retbufsize
== 0) {
1724 cc
= SSL_read(ssl
, tmpbuf
, sizeof(tmpbuf
));
1727 result
= SSL_get_error(ssl
, cc
);
1729 if (result
!= SSL_ERROR_ZERO_RETURN
) {
1730 sm_ierror("TLS peer aborted connection");
1737 sm_ierror("SSL_read failed: %s",
1738 ERR_error_string(ERR_get_error(), NULL
));
1742 #endif /* TLS_SUPPORT */
1744 cc
= read(fileno(f
), tmpbuf
, sizeof(tmpbuf
));
1750 sm_ierror("Unable to read from network: %s", strerror(errno
));
1755 * Don't call sasl_decode unless sasl is complete and we have
1756 * encryption working
1760 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1764 result
= sasl_decode(conn
, tmpbuf
, cc
, (const char **) &retbuf
,
1767 if (result
!= SASL_OK
) {
1768 sm_ierror("Unable to decode SASL network data: %s",
1769 sasl_errdetail(conn
));
1773 #else /* ! CYRUS_SASL */
1776 #endif /* CYRUS_SASL */
1779 if (retbufsize
> SASL_MAXRECVBUF
) {
1780 sm_ierror("Received data (%d bytes) is larger than the buffer "
1781 "size (%d bytes)", retbufsize
, SASL_MAXRECVBUF
);
1785 memcpy(sasl_inbuffer
, retbuf
, retbufsize
);
1786 sasl_inptr
= sasl_inbuffer
+ 1;
1787 sasl_inbuflen
= retbufsize
- 1;
1789 return (int) sasl_inbuffer
[0];
1791 #endif /* CYRUS_SASL || TLS_SUPPORT */
1796 if (sm_mts
== MTS_SMTP
)
1798 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no socket opened"
1799 : sm_alarmed
? "read from socket timed out"
1800 : rc
== RP_EOF
? "premature end-of-file on socket"
1801 : "error reading from socket"));
1804 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no pipe opened"
1805 : sm_alarmed
? "read from pipe timed out"
1806 : rc
== RP_EOF
? "premature end-of-file on pipe"
1807 : "error reading from pipe"));
1809 return (sm_reply
.code
= NOTOK
);
1818 #ifndef RELIABLE_SIGNALS
1819 SIGNAL (SIGALRM
, alrmser
);
1824 printf ("timed out...\n");
1831 rp_string (int code
)
1834 static char buffer
[BUFSIZ
];
1836 switch (sm_reply
.code
!= NOTOK
? code
: NOTOK
) {
1856 snprintf (buffer
, sizeof(buffer
), "[%s] %s", text
, sm_reply
.text
);
1876 snprintf (buffer
, sizeof(buffer
), "[%s] %3d %s",
1877 text
, sm_reply
.code
, sm_reply
.text
);
1889 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1891 if (strncmp (ep
, s
, len
) == 0) {
1892 for (ep
+= len
; *ep
== ' '; ep
++)