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 succeded? */
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 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
384 #endif /* CYRUS_SASL */
386 if (xoauth_client_res
!= NULL
) {
388 if ((server_mechs
= EHLOset("AUTH")) == NULL
389 || stringdex("XOAUTH2", server_mechs
) == -1) {
391 return sm_ierror("SMTP server does not support SASL XOAUTH2");
393 if (sm_auth_xoauth2(xoauth_client_res
) != RP_OK
) {
400 if (watch
&& EHLOset ("XVRB"))
401 smtalk (SM_HELO
, "VERB on");
407 sendmail_init (char *client
, char *server
, int watch
, int verbose
,
408 int debug
, int sasl
, int saslssf
, char *saslmech
, char *user
)
410 unsigned int i
, result
, vecp
;
415 #else /* CYRUS_SASL */
418 NMH_UNUSED (saslssf
);
419 NMH_UNUSED (saslmech
);
421 #endif /* CYRUS_SASL */
426 sm_verbose
= verbose
;
428 if (sm_rfp
!= NULL
&& sm_wfp
!= NULL
)
431 if (client
== NULL
|| *client
== '\0') {
435 client
= LocalName(1); /* no clientname -> LocalName */
439 * Last-ditch check just in case client still isn't set to anything
442 if (client
== NULL
|| *client
== '\0')
443 client
= "localhost";
445 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
446 sasl_inbuffer
= malloc(SASL_MAXRECVBUF
);
448 return sm_ierror("Unable to allocate %d bytes for read buffer",
450 #endif /* CYRUS_SASL || TLS_SUPPORT */
452 if (pipe (pdi
) == NOTOK
)
453 return sm_ierror ("no pipes");
454 if (pipe (pdo
) == NOTOK
) {
457 return sm_ierror ("no pipes");
460 for (i
= 0; (sm_child
= fork ()) == NOTOK
&& i
< 5; i
++)
469 return sm_ierror ("unable to fork");
472 if (pdo
[0] != fileno (stdin
))
473 dup2 (pdo
[0], fileno (stdin
));
474 if (pdi
[1] != fileno (stdout
))
475 dup2 (pdi
[1], fileno (stdout
));
476 if (pdi
[1] != fileno (stderr
))
477 dup2 (pdi
[1], fileno (stderr
));
478 for (i
= fileno (stderr
) + 1; i
< NBITS
; i
++)
482 vec
[vecp
++] = r1bindex (sendmail
, '/');
484 vec
[vecp
++] = watch
? "-odi" : "-odb";
485 vec
[vecp
++] = "-oem";
491 execvp (sendmail
, vec
);
492 fprintf (stderr
, "unable to exec ");
494 _exit (-1); /* NOTREACHED */
497 SIGNAL (SIGALRM
, alrmser
);
498 SIGNAL (SIGPIPE
, SIG_IGN
);
502 if ((sm_rfp
= fdopen (pdi
[0], "r")) == NULL
503 || (sm_wfp
= fdopen (pdo
[1], "w")) == NULL
) {
506 sm_rfp
= sm_wfp
= NULL
;
507 return sm_ierror ("unable to fdopen");
523 result
= smtalk (SM_HELO
, "EHLO %s", client
);
526 if (500 <= result
&& result
<= 599)
527 result
= smtalk (SM_HELO
, "HELO %s", client
);
540 * If the user asked for SASL, then check to see if the SMTP server
541 * supports it. Otherwise, error out (because the SMTP server
542 * might have been spoofed; we don't want to just silently not
547 if (! (server_mechs
= EHLOset("AUTH"))) {
549 return sm_ierror("SMTP server does not support SASL");
552 if (saslmech
&& stringdex(saslmech
, server_mechs
) == -1) {
554 return sm_ierror("Requested SASL mech \"%s\" is not in the "
555 "list of supported mechanisms:\n%s",
556 saslmech
, server_mechs
);
559 if (sm_auth_sasl(user
, saslssf
, saslmech
? saslmech
: server_mechs
,
565 #endif /* CYRUS_SASL */
568 smtalk (SM_HELO
, "VERB on");
575 rclient (char *server
, char *service
)
578 char response
[BUFSIZ
];
580 if ((sd
= client (server
, service
, response
, sizeof(response
),
584 sm_ierror ("%s", response
);
589 sm_winit (char *from
)
591 switch (smtalk (SM_MAIL
, "MAIL FROM:<%s>", from
)) {
608 sm_wadr (char *mbox
, char *host
, char *path
)
610 switch (smtalk (SM_RCPT
, host
&& *host
? "RCPT TO:<%s%s@%s>"
612 path
? path
: "", mbox
, host
)) {
622 #endif /* SENDMAILBUG */
647 switch (smtalk (SM_DATA
, "DATA")) {
656 #endif /* SENDMAILBUG */
673 sm_wtxt (char *buffer
, int len
)
679 result
= sm_wstream (buffer
, len
);
682 return (result
== NOTOK
? RP_BHST
: RP_OK
);
689 if (sm_wstream ((char *) NULL
, 0) == NOTOK
)
692 switch (smtalk (SM_DOT
+ 3 * sm_addrs
, ".")) {
700 #endif /* SENDMAILBUG */
718 if (sm_mts
== MTS_SENDMAIL_SMTP
) {
729 if (sm_rfp
== NULL
&& sm_wfp
== NULL
)
734 smtalk (SM_QUIT
, "QUIT");
738 sm_note
.code
= sm_reply
.code
;
739 sm_note
.length
= sm_reply
.length
;
740 memcpy (sm_note
.text
, sm_reply
.text
, sm_reply
.length
+ 1);/* fall */
742 if (smtalk (SM_RSET
, "RSET") == 250 && type
== DONE
)
744 if (sm_mts
== MTS_SMTP
)
745 smtalk (SM_QUIT
, "QUIT");
747 /* The SIGPIPE block replaces old calls to discard ().
748 We're not sure what the discard () calls were for,
749 maybe to prevent deadlock on old systems. In any
750 case, blocking SIGPIPE should be harmless.
751 Because the file handles are closed below, leave it
755 sigaddset (&set
, SIGPIPE
);
756 sigprocmask (SIG_BLOCK
, &set
, &oset
);
758 kill (sm_child
, SIGKILL
);
762 sm_reply
.code
= sm_note
.code
;
763 sm_reply
.length
= sm_note
.length
;
764 memcpy (sm_reply
.text
, sm_note
.text
, sm_note
.length
+ 1);
771 BIO_ssl_shutdown(io
);
774 #endif /* TLS_SUPPORT */
776 if (sm_rfp
!= NULL
) {
781 if (sm_wfp
!= NULL
) {
787 if (sm_mts
== MTS_SMTP
) {
792 if (sasl_outbuffer
) {
793 free(sasl_outbuffer
);
798 #endif /* CYRUS_SASL */
799 } else if (sm_child
!= NOTOK
) {
800 status
= pidwait (sm_child
, OK
);
806 sm_rfp
= sm_wfp
= NULL
;
807 return (status
? RP_BHST
: RP_OK
);
812 * This function implements SASL authentication for SMTP. If this function
813 * completes successfully, then authentication is successful and we've
814 * (optionally) negotiated a security layer.
817 #define CHECKB64SIZE(insize, outbuf, outsize) \
818 { size_t wantout = (((insize + 2) / 3) * 4) + 32; \
819 if (wantout > outsize) { \
820 outbuf = mh_xrealloc(outbuf, outsize = wantout); \
825 sm_auth_sasl(char *user
, int saslssf
, char *mechlist
, char *inhost
)
828 unsigned int buflen
, outlen
;
829 char *buf
, *outbuf
= NULL
, host
[NI_MAXHOST
];
830 const char *chosen_mech
;
831 sasl_security_properties_t secprops
;
834 struct nmh_creds creds
= { 0, 0, 0 };
835 size_t outbufsize
= 0;
838 * Initialize the callback contexts
842 * This is a _bit_ of a hack ... but if the hostname wasn't supplied
843 * to us on the command line, then call getpeername and do a
844 * reverse-address lookup on the IP address to get the name.
847 memset(host
, 0, sizeof(host
));
850 struct sockaddr_storage sin
;
851 socklen_t len
= sizeof(sin
);
854 if (getpeername(fileno(sm_wfp
), (struct sockaddr
*) &sin
, &len
) < 0) {
855 sm_ierror("getpeername on SMTP socket failed: %s",
860 result
= getnameinfo((struct sockaddr
*) &sin
, len
, host
, sizeof(host
),
861 NULL
, 0, NI_NAMEREQD
);
863 sm_ierror("Unable to look up name of connected host: %s",
864 gai_strerror(result
));
868 strncpy(host
, inhost
, sizeof(host
) - 1);
871 /* It's OK to copy the addresses here. The callbacks that use
872 them will only be called before this function returns. */
875 callbacks
[SM_SASL_N_CB_USER
].context
= &creds
;
876 callbacks
[SM_SASL_N_CB_AUTHNAME
].context
= &creds
;
877 callbacks
[SM_SASL_N_CB_PASS
].context
= &creds
;
879 result
= sasl_client_init(callbacks
);
881 if (result
!= SASL_OK
) {
882 sm_ierror("SASL library initialization failed: %s",
883 sasl_errstring(result
, NULL
, NULL
));
887 result
= sasl_client_new("smtp", host
, NULL
, NULL
, NULL
, 0, &conn
);
889 if (result
!= SASL_OK
) {
890 sm_ierror("SASL client initialization failed: %s",
891 sasl_errstring(result
, NULL
, NULL
));
896 * Initialize the security properties. But if TLS is active, then
897 * don't negotiate encryption here.
900 memset(&secprops
, 0, sizeof(secprops
));
901 secprops
.maxbufsize
= SASL_MAXRECVBUF
;
903 tls_active
? 0 : (saslssf
!= -1 ? (unsigned int) saslssf
: UINT_MAX
);
905 result
= sasl_setprop(conn
, SASL_SEC_PROPS
, &secprops
);
907 if (result
!= SASL_OK
) {
908 sm_ierror("SASL security property initialization failed: %s",
909 sasl_errstring(result
, NULL
, NULL
));
914 * Start the actual protocol. Feed the mech list into the library
915 * and get out a possible initial challenge
918 result
= sasl_client_start(conn
, mechlist
, NULL
, (const char **) &buf
,
919 &buflen
, (const char **) &chosen_mech
);
921 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
922 sm_ierror("SASL client start failed: %s", sasl_errdetail(conn
));
927 * If we got an initial challenge, send it as part of the AUTH
928 * command; otherwise, just send a plain AUTH command.
932 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
933 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
934 if (status
!= SASL_OK
) {
935 sm_ierror("SASL base64 encode failed: %s",
936 sasl_errstring(status
, NULL
, NULL
));
942 status
= smtalk(SM_AUTH
, "AUTH %s %s", chosen_mech
, outbuf
);
944 status
= smtalk(SM_AUTH
, "AUTH %s", chosen_mech
);
947 * Now we loop until we either fail, get a SASL_OK, or a 235
948 * response code. Receive the challenges and process them until
952 while (result
== SASL_CONTINUE
) {
955 * If we get a 235 response, that means authentication has
956 * succeeded and we need to break out of the loop (yes, even if
957 * we still get SASL_CONTINUE from sasl_client_step()).
959 * Otherwise, if we get a message that doesn't seem to be a
960 * valid response, then abort
965 else if (status
< 300 || status
> 399) {
972 * Special case; a zero-length response from the SMTP server
973 * is returned as a single =. If we get that, then set buflen
974 * to be zero. Otherwise, just decode the response.
977 if (strcmp("=", sm_reply
.text
) == 0) {
980 if (sm_reply
.length
> (int) outbufsize
) {
981 outbuf
= mh_xrealloc(outbuf
, outbufsize
= sm_reply
.length
);
984 result
= sasl_decode64(sm_reply
.text
, sm_reply
.length
,
985 outbuf
, outbufsize
, &outlen
);
986 if (result
!= SASL_OK
) {
987 smtalk(SM_AUTH
, "*");
988 sm_ierror("SASL base64 decode failed: %s",
989 sasl_errstring(result
, NULL
, NULL
));
996 result
= sasl_client_step(conn
, outbuf
, outlen
, NULL
,
997 (const char **) &buf
, &buflen
);
999 if (result
!= SASL_OK
&& result
!= SASL_CONTINUE
) {
1000 smtalk(SM_AUTH
, "*");
1001 sm_ierror("SASL client negotiation failed: %s",
1002 sasl_errstring(result
, NULL
, NULL
));
1008 CHECKB64SIZE(buflen
, outbuf
, outbufsize
);
1009 status
= sasl_encode64(buf
, buflen
, outbuf
, outbufsize
, NULL
);
1011 if (status
!= SASL_OK
) {
1012 smtalk(SM_AUTH
, "*");
1013 sm_ierror("SASL base64 encode failed: %s",
1014 sasl_errstring(status
, NULL
, NULL
));
1020 status
= smtalk(SM_AUTH
, outbuf
);
1027 * Make sure that we got the correct response
1030 if (status
< 200 || status
> 299)
1034 * We _should_ have completed the authentication successfully.
1035 * Get a few properties from the authentication exchange.
1038 result
= sasl_getprop(conn
, SASL_MAXOUTBUF
, (const void **) &outbufmax
);
1040 if (result
!= SASL_OK
) {
1041 sm_ierror("Cannot retrieve SASL negotiated output buffer size: %s",
1042 sasl_errstring(result
, NULL
, NULL
));
1046 maxoutbuf
= *outbufmax
;
1048 result
= sasl_getprop(conn
, SASL_SSF
, (const void **) &ssf
);
1052 if (result
!= SASL_OK
) {
1053 sm_ierror("Cannot retrieve SASL negotiated security strength "
1054 "factor: %s", sasl_errstring(result
, NULL
, NULL
));
1059 sasl_outbuffer
= malloc(maxoutbuf
);
1061 if (sasl_outbuffer
== NULL
) {
1062 sm_ierror("Unable to allocate %d bytes for SASL output "
1063 "buffer", maxoutbuf
);
1068 sasl_inptr
= sasl_inbuffer
;
1070 sasl_outbuffer
= NULL
;
1071 /* Don't NULL out sasl_inbuffer because it could be used in
1081 * Our callback functions to feed data to the SASL library
1085 sm_get_user(void *context
, int id
, const char **result
, unsigned *len
)
1087 nmh_creds_t creds
= (nmh_creds_t
) context
;
1089 if (! result
|| ((id
!= SASL_CB_USER
) && (id
!= SASL_CB_AUTHNAME
)))
1090 return SASL_BADPARAM
;
1092 if (creds
->user
== NULL
) {
1094 * Pass the 1 third argument to nmh_get_credentials() so
1095 * that a default user if the -user switch to send(1)/post(8)
1096 * wasn't used, and so that a default password will be supplied.
1097 * That's used when those values really don't matter, and only
1098 * with legacy/.netrc, i.e., with a credentials profile entry.
1100 if (nmh_get_credentials (creds
->host
, creds
->user
, 1, creds
) != OK
) {
1101 return SASL_BADPARAM
;
1105 *result
= creds
->user
;
1107 *len
= strlen(creds
->user
);
1113 sm_get_pass(sasl_conn_t
*conn
, void *context
, int id
,
1114 sasl_secret_t
**psecret
)
1116 nmh_creds_t creds
= (nmh_creds_t
) context
;
1121 if (! psecret
|| id
!= SASL_CB_PASS
)
1122 return SASL_BADPARAM
;
1124 if (creds
->password
== NULL
) {
1126 * Pass the 0 third argument to nmh_get_credentials() so
1127 * that the default password isn't used. With legacy/.netrc
1128 * credentials support, we'll only get here if the -user
1129 * switch to send(1)/post(8) wasn't used.
1131 if (nmh_get_credentials (creds
->host
, creds
->user
, 0, creds
) != OK
) {
1132 return SASL_BADPARAM
;
1136 len
= strlen (creds
->password
);
1138 if (! (*psecret
= (sasl_secret_t
*) malloc(sizeof(sasl_secret_t
) + len
))) {
1142 (*psecret
)->len
= len
;
1143 strcpy((char *) (*psecret
)->data
, creds
->password
);
1147 #endif /* CYRUS_SASL */
1149 /* https://developers.google.com/gmail/xoauth2_protocol */
1151 sm_auth_xoauth2(const char *client_res
)
1153 int status
= smtalk(SM_AUTH
, "AUTH XOAUTH2 %s", client_res
);
1154 if (status
== 235) {
1160 * Status is 334 and sm_reply.text contains base64-encoded JSON. As far as
1161 * epg can tell, no matter the error, the JSON is always the same:
1162 * {"status":"400","schemes":"Bearer","scope":"https://mail.google.com/"}
1163 * I tried these errors:
1169 /* Then we're supposed to send an empty response ("\r\n"). */
1170 smtalk(SM_AUTH
, "");
1172 * And now we always get this, again, no matter the error:
1173 * 535-5.7.8 Username and Password not accepted. Learn more at
1174 * 535 5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257
1180 sm_ierror (char *fmt
, ...)
1185 vsnprintf (sm_reply
.text
, sizeof(sm_reply
.text
), fmt
, ap
);
1188 sm_reply
.length
= strlen (sm_reply
.text
);
1189 sm_reply
.code
= NOTOK
;
1195 smtalk (int time
, char *fmt
, ...)
1200 size_t bufsize
= BUFSIZ
;
1202 buffer
= mh_xmalloc(bufsize
);
1205 result
= vsnprintf (buffer
, bufsize
, fmt
, ap
);
1208 if (result
> (int) bufsize
) {
1209 buffer
= mh_xrealloc(buffer
, bufsize
= result
+ 1);
1211 vsnprintf (buffer
, bufsize
, fmt
, ap
);
1217 printf("(sasl-encrypted) ");
1219 printf("(tls-encrypted) ");
1220 printf ("=> %s\n", buffer
);
1225 alarm ((unsigned) time
);
1226 if ((result
= sm_wrecord (buffer
, strlen (buffer
))) != NOTOK
)
1237 * write the buffer to the open SMTP channel
1241 sm_wrecord (char *buffer
, int len
)
1244 return sm_werror ();
1246 sm_fwrite (buffer
, len
);
1250 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1255 sm_wstream (char *buffer
, int len
)
1258 static char lc
= '\0';
1261 return sm_werror ();
1263 if (buffer
== NULL
&& len
== 0) {
1267 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1270 for (bp
= buffer
; bp
&& len
> 0; bp
++, len
--) {
1279 sm_fputc ('.');/* FALL THROUGH */
1284 if (ferror (sm_wfp
))
1285 return sm_werror ();
1290 return (ferror (sm_wfp
) ? sm_werror () : OK
);
1294 * Write out to the network, but do buffering for SASL (if enabled)
1298 sm_fwrite(char *buffer
, int len
)
1302 unsigned int outputlen
;
1304 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1305 #endif /* CYRUS_SASL */
1310 ret
= BIO_write(io
, buffer
, len
);
1313 sm_ierror("TLS error during write: %s",
1314 ERR_error_string(ERR_get_error(), NULL
));
1318 #endif /* TLS_SUPPORT */
1319 if ((int) fwrite(buffer
, sizeof(*buffer
), len
, sm_wfp
) < len
) {
1320 advise ("sm_fwrite", "fwrite");
1324 while (len
>= maxoutbuf
- sasl_outbuflen
) {
1325 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
,
1326 maxoutbuf
- sasl_outbuflen
);
1327 len
-= maxoutbuf
- sasl_outbuflen
;
1330 if (sasl_encode(conn
, sasl_outbuffer
, maxoutbuf
,
1331 &output
, &outputlen
) != SASL_OK
) {
1332 sm_ierror("Unable to SASL encode connection data: %s",
1333 sasl_errdetail(conn
));
1337 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) <
1339 advise ("sm_fwrite", "fwrite");
1344 memcpy(sasl_outbuffer
+ sasl_outbuflen
, buffer
, len
);
1345 sasl_outbuflen
+= len
;
1348 #endif /* CYRUS_SASL */
1349 return ferror(sm_wfp
) ? NOTOK
: RP_OK
;
1354 * Negotiate Transport Layer Security
1363 const SSL_METHOD
*method
;
1366 SSL_load_error_strings();
1368 method
= TLSv1_client_method(); /* Not sure about this */
1370 /* Older ssl takes a non-const arg. */
1371 sslctx
= SSL_CTX_new((SSL_METHOD
*) method
);
1375 return sm_ierror("Unable to initialize OpenSSL context: %s",
1376 ERR_error_string(ERR_get_error(), NULL
));
1380 ssl
= SSL_new(sslctx
);
1384 return sm_ierror("Unable to create SSL connection: %s",
1385 ERR_error_string(ERR_get_error(), NULL
));
1388 sbior
= BIO_new_socket(fileno(sm_rfp
), BIO_NOCLOSE
);
1389 sbiow
= BIO_new_socket(fileno(sm_wfp
), BIO_NOCLOSE
);
1391 if (sbior
== NULL
|| sbiow
== NULL
) {
1393 return sm_ierror("Unable to create BIO endpoints: %s",
1394 ERR_error_string(ERR_get_error(), NULL
));
1397 SSL_set_bio(ssl
, sbior
, sbiow
);
1398 SSL_set_connect_state(ssl
);
1401 * Set up a BIO to handle buffering for us
1404 io
= BIO_new(BIO_f_buffer());
1408 return sm_ierror("Unable to create a buffer BIO: %s",
1409 ERR_error_string(ERR_get_error(), NULL
));
1412 ssl_bio
= BIO_new(BIO_f_ssl());
1416 return sm_ierror("Unable to create a SSL BIO: %s",
1417 ERR_error_string(ERR_get_error(), NULL
));
1420 BIO_set_ssl(ssl_bio
, ssl
, BIO_CLOSE
);
1421 BIO_push(io
, ssl_bio
);
1424 * Try doing the handshake now
1427 if (BIO_do_handshake(io
) < 1) {
1429 return sm_ierror("Unable to negotiate SSL connection: %s",
1430 ERR_error_string(ERR_get_error(), NULL
));
1434 const SSL_CIPHER
*cipher
= SSL_get_current_cipher(ssl
);
1435 printf("SSL negotiation successful: %s(%d) %s\n",
1436 SSL_CIPHER_get_name(cipher
),
1437 SSL_CIPHER_get_bits(cipher
, NULL
),
1438 SSL_CIPHER_get_version(cipher
));
1446 #endif /* TLS_SUPPORT */
1449 * Convenience functions to replace occurences of fputs() and fputc()
1453 sm_fputs(char *buffer
)
1455 return sm_fwrite(buffer
, strlen(buffer
));
1463 return sm_fwrite(&h
, 1);
1467 * Flush out any pending data on the connection
1475 unsigned int outputlen
;
1478 if (sasl_complete
== 1 && sasl_ssf
> 0 && sasl_outbuflen
> 0) {
1479 result
= sasl_encode(conn
, sasl_outbuffer
, sasl_outbuflen
,
1480 &output
, &outputlen
);
1481 if (result
!= SASL_OK
) {
1482 sm_ierror("Unable to SASL encode connection data: %s",
1483 sasl_errdetail(conn
));
1487 if (fwrite(output
, sizeof(*output
), outputlen
, sm_wfp
) < outputlen
) {
1488 advise ("sm_fflush", "fwrite");
1492 #endif /* CYRUS_SASL */
1496 (void) BIO_flush(io
);
1498 #endif /* TLS_SUPPORT */
1507 strlen (strcpy (sm_reply
.text
, sm_wfp
== NULL
? "no socket opened"
1508 : sm_alarmed
? "write to socket timed out"
1509 : "error writing to socket"));
1511 return (sm_reply
.code
= NOTOK
);
1518 int i
, code
, cont
, bc
= 0, rc
, more
;
1521 char **ehlo
= EHLOkeys
, buffer
[BUFSIZ
];
1524 static int at_least_once
= 0;
1526 if (at_least_once
) {
1529 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1543 sm_reply
.length
= 0;
1544 sm_reply
.text
[0] = 0;
1546 rc
= sizeof(sm_reply
.text
) - 1;
1548 for (more
= FALSE
; sm_rrecord ((char *) (bp
= (unsigned char *) buffer
),
1552 printf("(sasl-decrypted) ");
1554 printf("(tls-decrypted) ");
1555 printf ("<= %s\n", buffer
);
1560 && strncmp (buffer
, "250", sizeof("250") - 1) == 0
1561 && (buffer
[3] == '-' || doingEHLO
== 2)
1563 if (doingEHLO
== 2) {
1564 if ((*ehlo
= malloc ((size_t) (strlen (buffer
+ 4) + 1)))) {
1565 strcpy (*ehlo
++, buffer
+ 4);
1567 if (ehlo
>= EHLOkeys
+ MAXEHLO
)
1577 for (; bc
> 0 && (!isascii (*bp
) || !isdigit (*bp
)); bp
++, bc
--)
1581 code
= atoi ((char *) bp
);
1583 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1585 if (bc
> 0 && *bp
== '-') {
1588 for (; bc
> 0 && isspace (*bp
); bp
++, bc
--)
1593 if (code
!= sm_reply
.code
|| cont
)
1597 sm_reply
.code
= code
;
1600 /* can never fail to 0-terminate because of size of buffer vs fixed string */
1601 strncpy (buffer
, sm_noreply
, sizeof(buffer
));
1602 bp
= (unsigned char *) buffer
;
1603 bc
= strlen (sm_noreply
);
1607 if ((i
= min (bc
, rc
)) > 0) {
1611 i
= strlen(sm_moreply
);
1612 if (more
&& rc
> i
+ 1) {
1613 memcpy (rp
, sm_moreply
, i
); /* safe because of check in if() */
1620 if (sm_reply
.code
< 100) {
1622 printf ("%s\n", sm_reply
.text
);
1628 sm_reply
.length
= rp
- sm_reply
.text
;
1629 sm_reply
.text
[sm_reply
.length
] = 0;
1630 return sm_reply
.code
;
1637 sm_rrecord (char *buffer
, int *len
)
1642 return sm_rerror(0);
1644 buffer
[*len
= 0] = 0;
1646 if ((retval
= sm_fgets (buffer
, BUFSIZ
, sm_rfp
)) != RP_OK
)
1647 return sm_rerror (retval
);
1648 *len
= strlen (buffer
);
1649 /* *len should be >0 except on EOF, but check for safety's sake */
1651 return sm_rerror (RP_EOF
);
1652 if (buffer
[*len
- 1] != '\n')
1653 while ((retval
= sm_fgetc (sm_rfp
)) != '\n' && retval
!= EOF
&&
1657 if ((*len
> 1) && (buffer
[*len
- 2] == '\r'))
1666 * Our version of fgets, which calls our private fgetc function
1670 sm_fgets(char *buffer
, int size
, FILE *f
)
1684 } while (size
> 1 && c
!= '\n');
1692 #if defined(CYRUS_SASL) || defined(TLS_SUPPORT)
1694 * Read from the network, but do SASL or TLS encryption
1700 char tmpbuf
[BUFSIZ
], *retbuf
;
1701 unsigned int retbufsize
= 0;
1705 * If we have leftover data, return it
1708 if (sasl_inbuflen
) {
1710 return (int) *sasl_inptr
++;
1714 * If not, read from the network until we have some data to return
1717 while (retbufsize
== 0) {
1721 cc
= SSL_read(ssl
, tmpbuf
, sizeof(tmpbuf
));
1724 result
= SSL_get_error(ssl
, cc
);
1726 if (result
!= SSL_ERROR_ZERO_RETURN
) {
1727 sm_ierror("TLS peer aborted connection");
1734 sm_ierror("SSL_read failed: %s",
1735 ERR_error_string(ERR_get_error(), NULL
));
1739 #endif /* TLS_SUPPORT */
1741 cc
= read(fileno(f
), tmpbuf
, sizeof(tmpbuf
));
1747 sm_ierror("Unable to read from network: %s", strerror(errno
));
1752 * Don't call sasl_decode unless sasl is complete and we have
1753 * encryption working
1757 if (sasl_complete
== 0 || sasl_ssf
== 0) {
1761 result
= sasl_decode(conn
, tmpbuf
, cc
, (const char **) &retbuf
,
1764 if (result
!= SASL_OK
) {
1765 sm_ierror("Unable to decode SASL network data: %s",
1766 sasl_errdetail(conn
));
1770 #else /* ! CYRUS_SASL */
1773 #endif /* CYRUS_SASL */
1776 if (retbufsize
> SASL_MAXRECVBUF
) {
1777 sm_ierror("Received data (%d bytes) is larger than the buffer "
1778 "size (%d bytes)", retbufsize
, SASL_MAXRECVBUF
);
1782 memcpy(sasl_inbuffer
, retbuf
, retbufsize
);
1783 sasl_inptr
= sasl_inbuffer
+ 1;
1784 sasl_inbuflen
= retbufsize
- 1;
1786 return (int) sasl_inbuffer
[0];
1788 #endif /* CYRUS_SASL || TLS_SUPPORT */
1793 if (sm_mts
== MTS_SMTP
)
1795 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no socket opened"
1796 : sm_alarmed
? "read from socket timed out"
1797 : rc
== RP_EOF
? "premature end-of-file on socket"
1798 : "error reading from socket"));
1801 strlen (strcpy (sm_reply
.text
, sm_rfp
== NULL
? "no pipe opened"
1802 : sm_alarmed
? "read from pipe timed out"
1803 : rc
== RP_EOF
? "premature end-of-file on pipe"
1804 : "error reading from pipe"));
1806 return (sm_reply
.code
= NOTOK
);
1815 #ifndef RELIABLE_SIGNALS
1816 SIGNAL (SIGALRM
, alrmser
);
1821 printf ("timed out...\n");
1828 rp_string (int code
)
1831 static char buffer
[BUFSIZ
];
1833 switch (sm_reply
.code
!= NOTOK
? code
: NOTOK
) {
1853 snprintf (buffer
, sizeof(buffer
), "[%s] %s", text
, sm_reply
.text
);
1873 snprintf (buffer
, sizeof(buffer
), "[%s] %3d %s",
1874 text
, sm_reply
.code
, sm_reply
.text
);
1886 for (ehlo
= EHLOkeys
; *ehlo
; ehlo
++) {
1888 if (strncmp (ep
, s
, len
) == 0) {
1889 for (ep
+= len
; *ep
== ' '; ep
++)