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>
17 #include <sasl/sasl.h>
18 #include <sasl/saslutil.h>
19 # if SASL_VERSION_FULL < 0x020125
20 /* Cyrus SASL 2.1.25 introduced the sasl_callback_ft prototype,
21 which has an explicit void parameter list, according to best
22 practice. So we need to cast to avoid compile warnings.
23 Provide this prototype for earlier versions. */
24 typedef int (*sasl_callback_ft
)();
25 # endif /* SASL_VERSION_FULL < 0x020125 */
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
30 #endif /* CYRUS_SASL */
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #endif /* TLS_SUPPORT */
38 * This module implements an interface to SendMail very similar
39 * to the MMDF mm_(3) routines. The sm_() routines herein talk
40 * SMTP to a sendmail process, mapping SMTP reply codes into
45 * On older 4.2BSD machines without the POSIX function `sigaction',
46 * the alarm handing stuff for time-outs will NOT work due to the way
47 * syscalls get restarted. This is not really crucial, since SendMail
48 * is generally well-behaved in this area.
53 * It appears that some versions of Sendmail will return Code 451
54 * when they don't really want to indicate a failure.
55 * "Code 451 almost always means sendmail has deferred; we don't
56 * really want bomb out at this point since sendmail will rectify
57 * things later." So, if you define SENDMAILBUG, Code 451 is
58 * considered the same as Code 250. Yuck!
65 #define NBITS ((sizeof (int)) * 8)
68 * these codes must all be different!
70 #define SM_OPEN 300 /* Changed to 5 minutes to comply with a SHOULD in RFC 1123 */
73 #define SM_MAIL 301 /* changed to 5 minutes and a second (for uniqueness), see above */
74 #define SM_RCPT 302 /* see above */
75 #define SM_DATA 120 /* see above */
76 #define SM_TEXT 180 /* see above */
77 #define SM_DOT 600 /* see above */
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
;
92 static int next_line_encoded
= 0;
96 * Some globals needed by SASL
99 static sasl_conn_t
*conn
= NULL
; /* SASL connection state */
100 static int sasl_complete
= 0; /* Has authentication succeeded? */
101 static sasl_ssf_t sasl_ssf
; /* Our security strength factor */
102 static int maxoutbuf
; /* Maximum crypto output buffer */
103 static char *sasl_outbuffer
; /* SASL output buffer for encryption */
104 static int sasl_outbuflen
; /* Current length of data in outbuf */
105 static int sm_get_user(void *, int, const char **, unsigned *);
106 static int sm_get_pass(sasl_conn_t
*, void *, int, sasl_secret_t
**);
108 static sasl_callback_t callbacks
[] = {
109 { SASL_CB_USER
, (sasl_callback_ft
) sm_get_user
, NULL
},
110 #define SM_SASL_N_CB_USER 0
111 { SASL_CB_AUTHNAME
, (sasl_callback_ft
) sm_get_user
, NULL
},
112 #define SM_SASL_N_CB_AUTHNAME 1
113 { SASL_CB_PASS
, (sasl_callback_ft
) sm_get_pass
, NULL
},
114 #define SM_SASL_N_CB_PASS 2
115 { SASL_CB_LIST_END
, NULL
, NULL
},
118 #else /* CYRUS_SASL */
120 #endif /* CYRUS_SASL */
123 static SSL_CTX
*sslctx
= NULL
;
124 static SSL
*ssl
= NULL
;
125 static BIO
*sbior
= NULL
;
126 static BIO
*sbiow
= NULL
;
127 static BIO
*io
= NULL
;
129 static int tls_negotiate(void);
130 #endif /* TLS_SUPPORT */
132 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
133 #define SASL_MAXRECVBUF 65536
134 static int sm_fgetc(FILE *);
135 static char *sasl_inbuffer
; /* SASL input buffer for encryption */
136 static char *sasl_inptr
; /* Pointer to current inbuf position */
137 static int sasl_inbuflen
; /* Current length of data in inbuf */
139 #define sm_fgetc fgetc
142 static int tls_active
= 0;
144 static char *sm_noreply
= "No reply text given";
145 static char *sm_moreply
= "; ";
146 static struct smtp sm_reply
;
150 static int doingEHLO
;
151 static char *EHLOkeys
[MAXEHLO
+ 1];
156 static int smtp_init (char *, char *, char *, int, int, int, int, int,
157 char *, char *, const char *, int);
158 static int sendmail_init (char *, char *, int, int, int, int, int,
161 static int rclient (char *, char *);
162 static int sm_ierror (char *fmt
, ...);
163 static int smtalk (int time
, char *fmt
, ...);
164 static int sm_wrecord (char *, int);
165 static int sm_wstream (char *, int);
166 static int sm_werror (void);
167 static int smhear (void);
168 static int sm_rrecord (char *, int *);
169 static int sm_rerror (int);
170 static void alrmser (int);
171 static char *EHLOset (char *);
172 static char *prepare_for_display (const char *, int *);
173 static int sm_fwrite(char *, int);
174 static int sm_fputs(char *);
175 static int sm_fputc(int);
176 static void sm_fflush(void);
177 static int sm_fgets(char *, int, FILE *);
178 static int sm_auth_xoauth2(const char *, const char *, int);
182 * Function prototypes needed for SASL
185 static int sm_auth_sasl(char *, int, char *, char *);
186 #endif /* CYRUS_SASL */
189 sm_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
190 int debug
, int sasl
, int saslssf
, char *saslmech
, char *user
,
191 const char *oauth_svc
, int tls
)
193 if (sm_mts
== MTS_SMTP
)
194 return smtp_init (client
, server
, port
, watch
, verbose
,
195 debug
, sasl
, saslssf
, saslmech
, user
,
198 return sendmail_init (client
, server
, watch
, verbose
,
199 debug
, sasl
, saslssf
, saslmech
, user
);
203 smtp_init (char *client
, char *server
, char *port
, int watch
, int verbose
,
205 int sasl
, int saslssf
, char *saslmech
, char *user
,
206 const char *oauth_svc
, int tls
)
208 int result
, sd1
, sd2
;
211 NMH_UNUSED (saslssf
);
212 NMH_UNUSED (saslmech
);
214 #endif /* CYRUS_SASL */
219 sm_verbose
= verbose
;
222 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
225 if (client
== NULL
|| *client
== '\0') {
229 client
= LocalName(1); /* no clientname -> LocalName */
234 * Last-ditch check just in case client still isn't set to anything
237 if (client
== NULL
|| *client
== '\0')
238 client
= "localhost";
240 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
241 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
243 return sm_ierror("Unable to allocate %d bytes for read buffer",
245 #endif /* CYRUS_SASL || TLS_SUPPORT */
247 if ((sd1
= rclient (server
, port
)) == NOTOK
)
250 if ((sd2
= dup (sd1
)) == NOTOK
) {
252 return sm_ierror ("unable to dup");
255 SIGNAL (SIGALRM
, alrmser
);
256 SIGNAL (SIGPIPE
, SIG_IGN
);
258 if ((sm_rfp
= fdopen (sd1
, "r")) == NULL
259 || (sm_wfp
= fdopen (sd2
, "w")) == NULL
) {
262 sm_rfp
= sm_wfp
= NULL
;
263 return sm_ierror ("unable to fdopen");
270 * If tls == 2, that means that the user requested "initial" TLS,
271 * which happens right after the connection has opened. Do that
276 result
= tls_negotiate();
279 * Note: if tls_negotiate() fails it will call sm_end() for us,
280 * which closes the connection.
285 #endif /* TLS_SUPPORT */
302 * Give EHLO or HELO command
306 result
= smtalk (SM_HELO
, "EHLO %s", client
);
309 if (result
>= 500 && result
<= 599)
310 result
= smtalk (SM_HELO
, "HELO %s", client
);
319 * If the user requested TLS support, then try to do the STARTTLS command
320 * as part of the initial dialog. Assuming this works, we then need to
321 * restart the EHLO dialog after TLS negotiation is complete.
325 if (! EHLOset("STARTTLS")) {
327 return sm_ierror("SMTP server does not support TLS");
330 result
= smtalk(SM_HELO
, "STARTTLS");
338 * Okay, the other side should be waiting for us to start TLS
339 * negotiation. Oblige them.
342 result
= tls_negotiate();
348 result
= smtalk (SM_HELO
, "EHLO %s", client
);
356 #else /* TLS_SUPPORT */
358 #endif /* TLS_SUPPORT */
362 * If the user asked for SASL, then check to see if the SMTP server
363 * supports it. Otherwise, error out (because the SMTP server
364 * might have been spoofed; we don't want to just silently not
370 if (! (server_mechs
= EHLOset("AUTH"))) {
372 return sm_ierror("SMTP server does not support SASL");
375 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
377 return sm_ierror("Requested SASL mech \"%s\" is not in the "
378 "list of supported mechanisms:\n%s",
379 saslmech
, server_mechs
);
382 /* Don't call sm_auth_sasl() for XAUTH2 with -sasl. Instead, call
383 sm_auth_xoauth2() below. */
384 if (oauth_svc
== NULL
&&
385 sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
391 #endif /* CYRUS_SASL */
393 if (oauth_svc
!= NULL
) {
395 if ((server_mechs
= EHLOset("AUTH")) == NULL
396 || stringdex("XOAUTH2", server_mechs
) == -1) {
398 return sm_ierror("SMTP server does not support SASL XOAUTH2");
400 if (sm_auth_xoauth2(user
, oauth_svc
, debug
) != RP_OK
) {
407 if (watch
&& EHLOset ("XVRB"))
408 smtalk (SM_HELO
, "VERB on");
414 sendmail_init (char *client
, char *server
, int watch
, int verbose
,
415 int debug
, int sasl
, int saslssf
, char *saslmech
, char *user
)
417 unsigned int i
, result
, vecp
;
422 #else /* CYRUS_SASL */
425 NMH_UNUSED (saslssf
);
426 NMH_UNUSED (saslmech
);
428 #endif /* CYRUS_SASL */
433 sm_verbose
= verbose
;
435 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
438 if (client
== NULL
|| *client
== '\0') {
442 client
= LocalName(1); /* no clientname -> LocalName */
446 * Last-ditch check just in case client still isn't set to anything
449 if (client
== NULL
|| *client
== '\0')
450 client
= "localhost";
452 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
453 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
455 return sm_ierror("Unable to allocate %d bytes for read buffer",
457 #endif /* CYRUS_SASL || TLS_SUPPORT */
459 if (pipe (pdi
) == NOTOK
)
460 return sm_ierror ("no pipes");
461 if (pipe (pdo
) == NOTOK
) {
464 return sm_ierror ("no pipes");
467 for (i
= 0; (sm_child
= fork ()) == NOTOK
&& i
< 5; i
++)
476 return sm_ierror ("unable to fork");
479 if (pdo
[0] != fileno (stdin
))
480 dup2 (pdo
[0], fileno (stdin
));
481 if (pdi
[1] != fileno (stdout
))
482 dup2 (pdi
[1], fileno (stdout
));
483 if (pdi
[1] != fileno (stderr
))
484 dup2 (pdi
[1], fileno (stderr
));
485 for (i
= fileno (stderr
) + 1; i
< NBITS
; i
++)
489 vec
[vecp
++] = r1bindex (sendmail
, '/');
491 vec
[vecp
++] = watch
? "-odi" : "-odb";
492 vec
[vecp
++] = "-oem";
498 execvp (sendmail
, vec
);
499 fprintf (stderr
, "unable to exec ");
501 _exit (-1); /* NOTREACHED */
504 SIGNAL (SIGALRM
, alrmser
);
505 SIGNAL (SIGPIPE
, SIG_IGN
);
509 if ((sm_rfp
= fdopen (pdi
[0], "r")) == NULL
510 || (sm_wfp
= fdopen (pdo
[1], "w")) == NULL
) {
513 sm_rfp
= sm_wfp
= NULL
;
514 return sm_ierror ("unable to fdopen");
530 result
= smtalk (SM_HELO
, "EHLO %s", client
);
533 if (500 <= result
&& result
<= 599)
534 result
= smtalk (SM_HELO
, "HELO %s", client
);
547 * If the user asked for SASL, then check to see if the SMTP server
548 * supports it. Otherwise, error out (because the SMTP server
549 * might have been spoofed; we don't want to just silently not
554 if (! (server_mechs
= EHLOset("AUTH"))) {
556 return sm_ierror("SMTP server does not support SASL");
559 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
561 return sm_ierror("Requested SASL mech \"%s\" is not in the "
562 "list of supported mechanisms:\n%s",
563 saslmech
, server_mechs
);
566 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
572 #endif /* CYRUS_SASL */
575 smtalk (SM_HELO
, "VERB on");
582 rclient (char *server
, char *service
)
585 char response
[BUFSIZ
];
587 if ((sd
= client (server
, service
, response
, sizeof(response
),
591 sm_ierror ("%s", response
);
596 sm_winit (char *from
)
598 switch (smtalk (SM_MAIL
, "MAIL FROM:<%s>", from
)) {
615 sm_wadr (char *mbox
, char *host
, char *path
)
617 switch (smtalk (SM_RCPT
, host
&& *host
? "RCPT TO:<%s%s@%s>"
619 path
? path
: "", mbox
, host
)) {
629 #endif /* SENDMAILBUG */
654 switch (smtalk (SM_DATA
, "DATA")) {
663 #endif /* SENDMAILBUG */
680 sm_wtxt (char *buffer
, int len
)
686 result
= sm_wstream (buffer
, len
);
689 return (result
== NOTOK
? RP_BHST
: RP_OK
);
696 if (sm_wstream ((char *) NULL
, 0) == NOTOK
)
699 switch (smtalk (SM_DOT
+ 3 * sm_addrs
, ".")) {
707 #endif /* SENDMAILBUG */
725 if (sm_mts
== MTS_SENDMAIL_SMTP
) {
736 if (sm_rfp
== NULL
&& sm_wfp
== NULL
)
741 smtalk (SM_QUIT
, "QUIT");
745 sm_note
.code
= sm_reply
.code
;
746 sm_note
.length
= sm_reply
.length
;
747 memcpy (sm_note
.text
, sm_reply
.text
, sm_reply
.length
+ 1);/* fall */
749 if (smtalk (SM_RSET
, "RSET") == 250 && type
== DONE
)
751 if (sm_mts
== MTS_SMTP
)
752 smtalk (SM_QUIT
, "QUIT");
754 /* The SIGPIPE block replaces old calls to discard ().
755 We're not sure what the discard () calls were for,
756 maybe to prevent deadlock on old systems. In any
757 case, blocking SIGPIPE should be harmless.
758 Because the file handles are closed below, leave it
762 sigaddset (&set
, SIGPIPE
);
763 sigprocmask (SIG_BLOCK
, &set
, &oset
);
765 kill (sm_child
, SIGKILL
);
769 sm_reply
.code
= sm_note
.code
;
770 sm_reply
.length
= sm_note
.length
;
771 memcpy (sm_reply
.text
, sm_note
.text
, sm_note
.length
+ 1);
778 BIO_ssl_shutdown(io
);
781 #endif /* TLS_SUPPORT */
783 if (sm_rfp
!= NULL
) {
788 if (sm_wfp
!= NULL
) {
794 if (sm_mts
== MTS_SMTP
) {
799 if (sasl_outbuffer
) {
800 free(sasl_outbuffer
);
805 #endif /* CYRUS_SASL */
806 } else if (sm_child
!= NOTOK
) {
807 status
= pidwait (sm_child
, OK
);
813 sm_rfp
= sm_wfp
= NULL
;
814 return (status
? RP_BHST
: RP_OK
);
819 * This function implements SASL authentication for SMTP. If this function
820 * completes successfully, then authentication is successful and we've
821 * (optionally) negotiated a security layer.
824 #define CHECKB64SIZE(insize, outbuf, outsize) \
825 { size_t wantout = (((insize + 2) / 3) * 4) + 32; \
826 if (wantout > outsize) { \
827 outbuf = mh_xrealloc(outbuf, outsize = wantout); \
832 sm_auth_sasl(char *user
, int saslssf
, char *mechlist
, char *inhost
)
835 unsigned int buflen
, outlen
;
836 char *buf
, *outbuf
= NULL
, host
[NI_MAXHOST
];
837 const char *chosen_mech
;
838 sasl_security_properties_t secprops
;
841 struct nmh_creds creds
= { 0, 0, 0 };
842 size_t outbufsize
= 0;
845 * Initialize the callback contexts
849 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
850 * to us on the command line, then call getpeername and do a
851 * reverse-address lookup on the IP address to get the name.
854 memset(host
, 0, sizeof(host
));
857 struct sockaddr_storage sin
;
858 socklen_t len
= sizeof(sin
);
861 if (getpeername(fileno(sm_wfp
), (struct sockaddr
*) &sin
, &len
) < 0) {
862 sm_ierror("getpeername on SMTP socket failed: %s",
867 result
= getnameinfo((struct sockaddr
*) &sin
, len
, host
, sizeof(host
),
868 NULL
, 0, NI_NAMEREQD
);
870 sm_ierror("Unable to look up name of connected host: %s",
871 gai_strerror(result
));
875 strncpy(host
, inhost
, sizeof(host
) - 1);
878 /* It's OK to copy the addresses here. The callbacks that use
879 them will only be called before this function returns. */
882 callbacks
[SM_SASL_N_CB_USER
].context
= &creds
;
883 callbacks
[SM_SASL_N_CB_AUTHNAME
].context
= &creds
;
884 callbacks
[SM_SASL_N_CB_PASS
].context
= &creds
;
886 result
= sasl_client_init(callbacks
);
888 if (result
!= SASL_OK
) {
889 sm_ierror("SASL library initialization failed: %s",
890 sasl_errstring(result
, NULL
, NULL
));
894 result
= sasl_client_new("smtp", host
, NULL
, NULL
, NULL
, 0, &conn
);
896 if (result
!= SASL_OK
) {
897 sm_ierror("SASL client initialization failed: %s",
898 sasl_errstring(result
, NULL
, NULL
));
903 * Initialize the security properties. But if TLS is active, then
904 * don't negotiate encryption here.
907 memset(&secprops
, 0, sizeof(secprops
));
908 secprops
.maxbufsize
= SASL_MAXRECVBUF
;
910 tls_active
? 0 : (saslssf
!= -1 ? (unsigned int) saslssf
: UINT_MAX
);
912 result
= sasl_setprop(conn
, SASL_SEC_PROPS
, &secprops
);
914 if (result
!= SASL_OK
) {
915 sm_ierror("SASL security property initialization failed: %s",
916 sasl_errstring(result
, NULL
, NULL
));
921 * Start the actual protocol. Feed the mech list into the library
922 * and get out a possible initial challenge
925 result
= sasl_client_start(conn
, mechlist
, NULL
, (const char **) &buf
,
926 &buflen
, (const char **) &chosen_mech
);
928 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
929 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn
));
934 * If we got an initial challenge, send it as part of the AUTH
935 * command; otherwise, just send a plain AUTH command.
939 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
940 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
941 if (status
!= SASL_OK
) {
942 sm_ierror("SASL base64 encode failed: %s",
943 sasl_errstring(status
, NULL
, NULL
));
949 status
= smtalk(SM_AUTH
, "AUTH %s %s", chosen_mech
, outbuf
);
951 status
= smtalk(SM_AUTH
, "AUTH %s", chosen_mech
);
954 * Now we loop until we either fail, get a SASL_OK, or a 235
955 * response code. Receive the challenges and process them until
959 while (result
== SASL_CONTINUE
) {
962 * If we get a 235 response, that means authentication has
963 * succeeded and we need to break out of the loop (yes, even if
964 * we still get SASL_CONTINUE from sasl_client_step()).
966 * Otherwise, if we get a message that doesn't seem to be a
967 * valid response, then abort
972 else if (status
< 300 || status
> 399) {
979 * Special case; a zero-length response from the SMTP server
980 * is returned as a single =. If we get that, then set buflen
981 * to be zero. Otherwise, just decode the response.
984 if (strcmp("=", sm_reply
.text
) == 0) {
987 if (sm_reply
.length
> (int) outbufsize
) {
988 outbuf
= mh_xrealloc(outbuf
, outbufsize
= sm_reply
.length
);
991 result
= sasl_decode64(sm_reply
.text
, sm_reply
.length
,
992 outbuf
, outbufsize
, &outlen
);
993 if (result
!= SASL_OK
) {
994 smtalk(SM_AUTH
, "*");
995 sm_ierror("SASL base64 decode failed: %s",
996 sasl_errstring(result
, NULL
, NULL
));
1003 result
= sasl_client_step(conn
, outbuf
, outlen
, NULL
,
1004 (const char **) &buf
, &buflen
);
1006 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
1007 smtalk(SM_AUTH
, "*");
1008 sm_ierror("SASL client negotiation failed: %s",
1009 sasl_errstring(result
, NULL
, NULL
));
1015 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
1016 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
1018 if (status
!= SASL_OK
) {
1019 smtalk(SM_AUTH
, "*");
1020 sm_ierror("SASL base64 encode failed: %s",
1021 sasl_errstring(status
, NULL
, NULL
));
1027 status
= smtalk(SM_AUTH
, outbuf
);
1034 * Make sure that we got the correct response
1037 if (status
< 200 || status
> 299)
1041 * We _should_ have completed the authentication successfully.
1042 * Get a few properties from the authentication exchange.
1045 result
= sasl_getprop(conn
, SASL_MAXOUTBUF
, (const void **) &outbufmax
);
1047 if (result
!= SASL_OK
) {
1048 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
1049 sasl_errstring(result
, NULL
, NULL
));
1053 maxoutbuf
= *outbufmax
;
1055 result
= sasl_getprop(conn
, SASL_SSF
, (const void **) &ssf
);
1059 if (result
!= SASL_OK
) {
1060 sm_ierror("Cannot retrieve SASL negotiated security strength "
1061 "factor: %s", sasl_errstring(result
, NULL
, NULL
));
1066 sasl_outbuffer
= malloc(maxoutbuf
);
1068 if (sasl_outbuffer
== NULL
) {
1069 sm_ierror("Unable to allocate %d bytes for SASL output "
1070 "buffer", maxoutbuf
);
1075 sasl_inptr
= sasl_inbuffer
;
1077 sasl_outbuffer
= NULL
;
1078 /* Don't NULL out sasl_inbuffer because it could be used in
1088 * Our callback functions to feed data to the SASL library
1092 sm_get_user(void *context
, int id
, const char **result
, unsigned *len
)
1094 nmh_creds_t creds
= (nmh_creds_t
) context
;
1096 if (! result
|| ((id
!= SASL_CB_USER
) && (id
!= SASL_CB_AUTHNAME
)))
1097 return SASL_BADPARAM
;
1099 if (creds
->user
== NULL
) {
1101 * Pass the 1 third argument to nmh_get_credentials() so
1102 * that a default user if the -user switch to send(1)/post(8)
1103 * wasn't used, and so that a default password will be supplied.
1104 * That's used when those values really don't matter, and only
1105 * with legacy/.netrc, i.e., with a credentials profile entry.
1107 if (nmh_get_credentials (creds
->host
, creds
->user
, 1, creds
) != OK
) {
1108 return SASL_BADPARAM
;
1112 *result
= creds
->user
;
1114 *len
= strlen(creds
->user
);
1120 sm_get_pass(sasl_conn_t
*conn
, void *context
, int id
,
1121 sasl_secret_t
**psecret
)
1123 nmh_creds_t creds
= (nmh_creds_t
) context
;
1128 if (! psecret
|| id
!= SASL_CB_PASS
)
1129 return SASL_BADPARAM
;
1131 if (creds
->password
== NULL
) {
1133 * Pass the 0 third argument to nmh_get_credentials() so
1134 * that the default password isn't used. With legacy/.netrc
1135 * credentials support, we'll only get here if the -user
1136 * switch to send(1)/post(8) wasn't used.
1138 if (nmh_get_credentials (creds
->host
, creds
->user
, 0, creds
) != OK
) {
1139 return SASL_BADPARAM
;
1143 len
= strlen (creds
->password
);
1145 if (! (*psecret
= (sasl_secret_t
*) malloc(sizeof(sasl_secret_t
) + len
))) {
1149 (*psecret
)->len
= len
;
1150 strcpy((char *) (*psecret
)->data
, creds
->password
);
1154 #endif /* CYRUS_SASL */
1156 /* https://developers.google.com/gmail/xoauth2_protocol */
1158 sm_auth_xoauth2(const char *user
, const char *oauth_svc
, int snoop
)
1160 const char *xoauth_client_res
;
1163 xoauth_client_res
= mh_oauth_do_xoauth(user
, oauth_svc
,
1164 snoop
? stderr
: NULL
);
1166 if (xoauth_client_res
== NULL
)
1167 return sm_ierror("Internal error: oauth_do_xoauth() returned NULL");
1169 status
= smtalk(SM_AUTH
, "AUTH XOAUTH2 %s", xoauth_client_res
);
1170 if (status
== 235) {
1176 * Status is 334 and sm_reply.text contains base64-encoded JSON. As far as
1177 * epg can tell, no matter the error, the JSON is always the same:
1178 * {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
1179 * I tried these errors:
1185 /* Then we're supposed to send an empty response ("\r\n"). */
1186 smtalk(SM_AUTH
, "");
1188 * And now we always get this, again, no matter the error:
1189 * 535-5.7.8 Username and Password not accepted. Learn more at
1190 * 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257
1196 sm_ierror (char *fmt
, ...)
1201 vsnprintf (sm_reply
.text
, sizeof(sm_reply
.text
), fmt
, ap
);
1204 sm_reply
.length
= strlen (sm_reply
.text
);
1205 sm_reply
.code
= NOTOK
;
1211 smtalk (int time
, char *fmt
, ...)
1216 size_t bufsize
= BUFSIZ
;
1218 buffer
= mh_xmalloc(bufsize
);
1221 result
= vsnprintf (buffer
, bufsize
, fmt
, ap
);
1224 if (result
> (int) bufsize
) {
1225 buffer
= mh_xrealloc(buffer
, bufsize
= result
+ 1);
1227 vsnprintf (buffer
, bufsize
, fmt
, ap
);
1232 char *decoded_buffer
=
1233 prepare_for_display (buffer
, &next_line_encoded
);
1236 printf("(sasl-encrypted) ");
1238 printf("(tls-encrypted) ");
1239 printf ("=> %s\n", decoded_buffer
);
1240 free (decoded_buffer
);
1245 alarm ((unsigned) time
);
1246 if ((result
= sm_wrecord (buffer
, strlen (buffer
))) != NOTOK
)
1257 * write the buffer to the open SMTP channel
1261 sm_wrecord (char *buffer
, int len
)
1264 return sm_werror ();
1266 sm_fwrite (buffer
, len
);
1270 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1275 sm_wstream (char *buffer
, int len
)
1278 static char lc
= '\0';
1281 return sm_werror ();
1283 if (buffer
== NULL
&& len
== 0) {
1287 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1290 for (bp
= buffer
; bp
&& len
> 0; bp
++, len
--) {
1299 sm_fputc ('.');/* FALL THROUGH */
1304 if (ferror (sm_wfp
))
1305 return sm_werror ();
1310 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1314 * Write out to the network, but do buffering for SASL (if enabled)
1318 sm_fwrite(char *buffer
, int len
)
1322 unsigned int outputlen
;
1324 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1325 #endif /* CYRUS_SASL */
1330 ret
= BIO_write(io
, buffer
, len
);
1333 sm_ierror("TLS error during write: %s",
1334 ERR_error_string(ERR_get_error(), NULL
));
1338 #endif /* TLS_SUPPORT */
1339 if ((int) fwrite(buffer
, sizeof(*buffer
), len
, sm_wfp
) < len
) {
1340 advise ("sm_fwrite", "fwrite");
1344 while (len
>= maxoutbuf
- sasl_outbuflen
) {
1345 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
,
1346 maxoutbuf
- sasl_outbuflen
);
1347 len
-= maxoutbuf
- sasl_outbuflen
;
1350 if (sasl_encode(conn
, sasl_outbuffer
, maxoutbuf
,
1351 &output
, &outputlen
) != SASL_OK
) {
1352 sm_ierror("Unable to SASL encode connection data: %s",
1353 sasl_errdetail(conn
));
1357 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) <
1359 advise ("sm_fwrite", "fwrite");
1364 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
, len
);
1365 sasl_outbuflen
+= len
;
1368 #endif /* CYRUS_SASL */
1369 return ferror(sm_wfp
) ? NOTOK
: RP_OK
;
1374 * Negotiate Transport Layer Security
1383 const SSL_METHOD
*method
;
1386 SSL_load_error_strings();
1388 method
= TLSv1_client_method(); /* Not sure about this */
1390 /* Older ssl takes a non-const arg. */
1391 sslctx
= SSL_CTX_new((SSL_METHOD
*) method
);
1395 return sm_ierror("Unable to initialize OpenSSL context: %s",
1396 ERR_error_string(ERR_get_error(), NULL
));
1400 ssl
= SSL_new(sslctx
);
1404 return sm_ierror("Unable to create SSL connection: %s",
1405 ERR_error_string(ERR_get_error(), NULL
));
1408 sbior
= BIO_new_socket(fileno(sm_rfp
), BIO_NOCLOSE
);
1409 sbiow
= BIO_new_socket(fileno(sm_wfp
), BIO_NOCLOSE
);
1411 if (sbior
== NULL
|| sbiow
== NULL
) {
1413 return sm_ierror("Unable to create BIO endpoints: %s",
1414 ERR_error_string(ERR_get_error(), NULL
));
1417 SSL_set_bio(ssl
, sbior
, sbiow
);
1418 SSL_set_connect_state(ssl
);
1421 * Set up a BIO to handle buffering for us
1424 io
= BIO_new(BIO_f_buffer());
1428 return sm_ierror("Unable to create a buffer BIO: %s",
1429 ERR_error_string(ERR_get_error(), NULL
));
1432 ssl_bio
= BIO_new(BIO_f_ssl());
1436 return sm_ierror("Unable to create a SSL BIO: %s",
1437 ERR_error_string(ERR_get_error(), NULL
));
1440 BIO_set_ssl(ssl_bio
, ssl
, BIO_CLOSE
);
1441 BIO_push(io
, ssl_bio
);
1444 * Try doing the handshake now
1447 if (BIO_do_handshake(io
) < 1) {
1449 return sm_ierror("Unable to negotiate SSL connection: %s",
1450 ERR_error_string(ERR_get_error(), NULL
));
1454 const SSL_CIPHER
*cipher
= SSL_get_current_cipher(ssl
);
1455 printf("SSL negotiation successful: %s(%d) %s\n",
1456 SSL_CIPHER_get_name(cipher
),
1457 SSL_CIPHER_get_bits(cipher
, NULL
),
1458 SSL_CIPHER_get_version(cipher
));
1466 #endif /* TLS_SUPPORT */
1469 * Convenience functions to replace occurrences of fputs() and fputc()
1473 sm_fputs(char *buffer
)
1475 return sm_fwrite(buffer
, strlen(buffer
));
1483 return sm_fwrite(&h
, 1);
1487 * Flush out any pending data on the connection
1495 unsigned int outputlen
;
1498 if (sasl_complete
== 1 && sasl_ssf
> 0 && sasl_outbuflen
> 0) {
1499 result
= sasl_encode(conn
, sasl_outbuffer
, sasl_outbuflen
,
1500 &output
, &outputlen
);
1501 if (result
!= SASL_OK
) {
1502 sm_ierror("Unable to SASL encode connection data: %s",
1503 sasl_errdetail(conn
));
1507 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) < outputlen
) {
1508 advise ("sm_fflush", "fwrite");
1512 #endif /* CYRUS_SASL */
1516 (void) BIO_flush(io
);
1518 #endif /* TLS_SUPPORT */
1527 strlen (strcpy (sm_reply
.text
, sm_wfp
== NULL
? "no socket opened"
1528 : sm_alarmed
? "write to socket timed out"
1529 : "error writing to socket"));
1531 return (sm_reply
.code
= NOTOK
);
1538 int i
, code
, cont
, bc
= 0, rc
, more
;
1541 char **ehlo
= EHLOkeys
, buffer
[BUFSIZ
];
1544 static int at_least_once
= 0;
1546 if (at_least_once
) {
1549 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1563 sm_reply
.length
= 0;
1564 sm_reply
.text
[0] = 0;
1566 rc
= sizeof(sm_reply
.text
) - 1;
1568 for (more
= FALSE
; sm_rrecord ((char *) (bp
= (unsigned char *) buffer
),
1571 char *decoded_buffer
=
1572 prepare_for_display (buffer
, &next_line_encoded
);
1575 printf("(sasl-decrypted) ");
1577 printf("(tls-decrypted) ");
1578 printf ("<= %s\n", decoded_buffer
);
1579 free (decoded_buffer
);
1584 && strncmp (buffer
, "250", sizeof("250") - 1) == 0
1585 && (buffer
[3] == '-' || doingEHLO
== 2)
1587 if (doingEHLO
== 2) {
1588 if ((*ehlo
= malloc ((size_t) (strlen (buffer
+ 4) + 1)))) {
1589 strcpy (*ehlo
++, buffer
+ 4);
1591 if (ehlo
>= EHLOkeys
+ MAXEHLO
)
1601 for (; bc
> 0 && (!isascii (*bp
) || !isdigit (*bp
)); bp
++, bc
--)
1605 code
= atoi ((char *) bp
);
1607 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1609 if (bc
> 0 && *bp
== '-') {
1612 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1617 if (code
!= sm_reply
.code
|| cont
)
1621 sm_reply
.code
= code
;
1624 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1625 strncpy (buffer
, sm_noreply
, sizeof(buffer
));
1626 bp
= (unsigned char *) buffer
;
1627 bc
= strlen (sm_noreply
);
1631 if ((i
= min (bc
, rc
)) > 0) {
1635 i
= strlen(sm_moreply
);
1636 if (more
&& rc
> i
+ 1) {
1637 memcpy (rp
, sm_moreply
, i
); /* safe because of check in if() */
1644 if (sm_reply
.code
< 100) {
1646 printf ("%s\n", sm_reply
.text
);
1652 sm_reply
.length
= rp
- sm_reply
.text
;
1653 sm_reply
.text
[sm_reply
.length
] = 0;
1654 return sm_reply
.code
;
1661 sm_rrecord (char *buffer
, int *len
)
1666 return sm_rerror(0);
1668 buffer
[*len
= 0] = 0;
1670 if ((retval
= sm_fgets (buffer
, BUFSIZ
, sm_rfp
)) != RP_OK
)
1671 return sm_rerror (retval
);
1672 *len
= strlen (buffer
);
1673 /* *len should be >0 except on EOF, but check for safety's sake */
1675 return sm_rerror (RP_EOF
);
1676 if (buffer
[*len
- 1] != '\n')
1677 while ((retval
= sm_fgetc (sm_rfp
)) != '\n' && retval
!= EOF
&&
1681 if ((*len
> 1) && (buffer
[*len
- 2] == '\r'))
1690 * Our version of fgets, which calls our private fgetc function
1694 sm_fgets(char *buffer
, int size
, FILE *f
)
1708 } while (size
> 1 && c
!= '\n');
1716 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1718 * Read from the network, but do SASL or TLS encryption
1724 char tmpbuf
[BUFSIZ
], *retbuf
;
1725 unsigned int retbufsize
= 0;
1729 * If we have leftover data, return it
1732 if (sasl_inbuflen
) {
1734 return (int) *sasl_inptr
++;
1738 * If not, read from the network until we have some data to return
1741 while (retbufsize
== 0) {
1745 cc
= SSL_read(ssl
, tmpbuf
, sizeof(tmpbuf
));
1748 result
= SSL_get_error(ssl
, cc
);
1750 if (result
!= SSL_ERROR_ZERO_RETURN
) {
1751 sm_ierror("TLS peer aborted connection");
1758 sm_ierror("SSL_read failed: %s",
1759 ERR_error_string(ERR_get_error(), NULL
));
1763 #endif /* TLS_SUPPORT */
1765 cc
= read(fileno(f
), tmpbuf
, sizeof(tmpbuf
));
1771 sm_ierror("Unable to read from network: %s", strerror(errno
));
1776 * Don't call sasl_decode unless sasl is complete and we have
1777 * encryption working
1781 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1785 result
= sasl_decode(conn
, tmpbuf
, cc
, (const char **) &retbuf
,
1788 if (result
!= SASL_OK
) {
1789 sm_ierror("Unable to decode SASL network data: %s",
1790 sasl_errdetail(conn
));
1794 #else /* ! CYRUS_SASL */
1797 #endif /* CYRUS_SASL */
1800 if (retbufsize
> SASL_MAXRECVBUF
) {
1801 sm_ierror("Received data (%d bytes) is larger than the buffer "
1802 "size (%d bytes)", retbufsize
, SASL_MAXRECVBUF
);
1806 memcpy(sasl_inbuffer
, retbuf
, retbufsize
);
1807 sasl_inptr
= sasl_inbuffer
+ 1;
1808 sasl_inbuflen
= retbufsize
- 1;
1810 return (int) sasl_inbuffer
[0];
1812 #endif /* CYRUS_SASL || TLS_SUPPORT */
1817 if (sm_mts
== MTS_SMTP
)
1819 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no socket opened"
1820 : sm_alarmed
? "read from socket timed out"
1821 : rc
== RP_EOF
? "premature end-of-file on socket"
1822 : "error reading from socket"));
1825 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no pipe opened"
1826 : sm_alarmed
? "read from pipe timed out"
1827 : rc
== RP_EOF
? "premature end-of-file on pipe"
1828 : "error reading from pipe"));
1830 return (sm_reply
.code
= NOTOK
);
1839 #ifndef RELIABLE_SIGNALS
1840 SIGNAL (SIGALRM
, alrmser
);
1845 printf ("timed out...\n");
1852 rp_string (int code
)
1855 static char buffer
[BUFSIZ
];
1857 switch (sm_reply
.code
!= NOTOK
? code
: NOTOK
) {
1877 snprintf (buffer
, sizeof(buffer
), "[%s] %s", text
, sm_reply
.text
);
1897 snprintf (buffer
, sizeof(buffer
), "[%s] %3d %s",
1898 text
, sm_reply
.code
, sm_reply
.text
);
1910 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1912 if (strncmp (ep
, s
, len
) == 0) {
1913 for (ep
+= len
; *ep
== ' '; ep
++)
1924 * Detects, using heuristics, if an SMTP server or client response string
1925 * contains a base64-encoded portion. If it does, decodes it and replaces
1926 * any non-printable characters with a hex representation. Caller is
1927 * responsible for free'ing return value. If the decode fails, a copy of
1928 * the input string is returned.
1932 prepare_for_display (const char *string
, int *next_line_encoded
) {
1933 const char *start
= NULL
;
1934 const char *decoded
;
1936 int prefix_len
= -1;
1938 if (strncmp (string
, "AUTH ", 5) == 0) {
1939 /* AUTH line: the mechanism isn't encoded. If there's an initial
1940 response, it must be base64 encoded.. */
1941 char *mechanism
= strchr (string
+ 5, ' ');
1943 if (mechanism
!= NULL
) {
1944 prefix_len
= (int) (mechanism
- string
+ 1);
1945 } /* else no space following the mechanism, so no initial response */
1946 *next_line_encoded
= 0;
1947 } else if (strncmp (string
, "334 ", 4) == 0) {
1948 /* 334 is the server's request for user or password. */
1950 /* The next (client response) line must be base64 encoded. */
1951 *next_line_encoded
= 1;
1952 } else if (*next_line_encoded
) {
1953 /* "next" line now refers to this line, which is a base64-encoded
1956 *next_line_encoded
= 0;
1958 *next_line_encoded
= 0;
1961 /* Don't attempt to decoded unencoded initial response ('=') or cancel
1963 if (prefix_len
> -1 &&
1964 string
[prefix_len
] != '=' && string
[prefix_len
] != '*') {
1965 start
= string
+ prefix_len
;
1968 if (start
&& decodeBase64 (start
, &decoded
, &decoded_len
, 1, NULL
) == OK
) {
1970 char *prefix
= mh_xmalloc(prefix_len
+ 1);
1971 char *display_string
;
1973 /* prefix is the beginning portion, which isn't base64 encoded. */
1974 snprintf (prefix
, prefix_len
+ 1, "%*s", prefix_len
, string
);
1975 hexify ((const unsigned char *) decoded
, decoded_len
, &hexified
);
1976 /* Wrap the decoded portion in "b64<>". */
1977 display_string
= concat (prefix
, "b64<", hexified
, ">", NULL
);
1980 free ((char *) decoded
);
1982 return display_string
;
1984 return getcpy (string
);