2 * Copyright (c) 1999-2006, 2008 Proofpoint, Inc. and its suppliers.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
12 SM_RCSID("@(#)$Id: sfsasl.c,v 8.121 2013-11-22 20:51:56 ca Exp $")
19 /* allow to disable error handling code just in case... */
20 #ifndef DEAL_WITH_ERROR_SSL
21 # define DEAL_WITH_ERROR_SSL 1
22 #endif /* ! DEAL_WITH_ERROR_SSL */
27 /* Structure used by the "sasl" file type */
41 ** SASL_GETINFO - returns requested information about a "sasl" file
45 ** fp -- the file descriptor
46 ** what -- the type of information requested
47 ** valp -- the thang to return the information in
50 ** -1 for unknown requests
51 ** >=0 on success with valp filled in (if possible).
54 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
57 sasl_getinfo(fp, what, valp)
62 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
69 return so->fp->f_file; /* for stdio fileno() compatability */
71 case SM_IO_IS_READABLE:
75 /* get info from underlying file */
76 return sm_io_getinfo(so->fp, what, valp);
84 ** SASL_OPEN -- creates the sasl specific information for opening a
85 ** file of the sasl type.
88 ** fp -- the file pointer associated with the new open
89 ** info -- contains the sasl connection information pointer and
90 ** the original SM_FILE_T that holds the open
98 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
102 sasl_open(fp, info, flags, rpool)
109 struct sasl_info *si = (struct sasl_info *) info;
111 so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
121 ** The underlying 'fp' is set to SM_IO_NOW so that the entire
122 ** encoded string is written in one chunk. Otherwise there is
123 ** the possibility that it may appear illegal, bogus or
124 ** mangled to the other side of the connection.
125 ** We will read or write through 'fp' since it is the opaque
126 ** connection for the communications. We need to treat it this
127 ** way in case the encoded string is to be sent down a TLS
128 ** connection rather than, say, sm_io's stdio.
131 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
137 ** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
140 ** fp -- the file pointer to close
146 static int sasl_close __P((SM_FILE_T *));
154 so = (struct sasl_obj *) fp->f_cookie;
159 sm_io_close(so->fp, SM_TIME_DEFAULT);
167 /* how to deallocate a buffer allocated by SASL */
168 extern void sm_sasl_free __P((void *));
169 # define SASL_DEALLOC(b) sm_sasl_free(b)
172 ** SASL_READ -- read encrypted information and decrypt it for the caller
175 ** fp -- the file pointer
176 ** buf -- the location to place the decrypted information
177 ** size -- the number of bytes to read after decryption
181 ** otherwise the number of bytes read
184 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
187 sasl_read(fp, buf, size)
195 static const char *outbuf = NULL;
196 # else /* SASL >= 20000 */
197 static char *outbuf = NULL;
198 # endif /* SASL >= 20000 */
199 static unsigned int outlen = 0;
200 static unsigned int offset = 0;
201 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
204 ** sasl_decode() may require more data than a single read() returns.
205 ** Hence we have to put a loop around the decoding.
206 ** This also requires that we may have to split up the returned
207 ** data since it might be larger than the allowed size.
208 ** Therefore we use a static pointer and return portions of it
210 ** XXX Note: This function is not thread-safe nor can it be used
211 ** on more than one file. A correct implementation would store
212 ** this data in fp->f_cookie.
217 # else /* SASL >= 20000 */
218 while (outbuf == NULL && outlen == 0)
219 # endif /* SASL >= 20000 */
221 len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
224 result = sasl_decode(so->conn, buf,
225 (unsigned int) len, &outbuf, &outlen);
226 if (result != SASL_OK)
229 sm_syslog(LOG_WARNING, NOQID,
230 "AUTH: sasl_decode error=%d", result);
240 /* be paranoid: outbuf == NULL but outlen != 0 */
241 syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
244 if (outlen - offset > size)
246 /* return another part of the buffer */
247 (void) memcpy(buf, outbuf + offset, size);
253 /* return the rest of the buffer */
254 len = outlen - offset;
255 (void) memcpy(buf, outbuf + offset, (size_t) len);
257 SASL_DEALLOC(outbuf);
258 # endif /* SASL < 20000 */
267 ** SASL_WRITE -- write information out after encrypting it
270 ** fp -- the file pointer
271 ** buf -- holds the data to be encrypted and written
272 ** size -- the number of bytes to have encrypted and written
276 ** otherwise number of bytes written
279 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
282 sasl_write(fp, buf, size)
290 # else /* SASL >= 20000 */
292 # endif /* SASL >= 20000 */
293 unsigned int outlen, *maxencode;
294 size_t ret = 0, total = 0;
295 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
298 ** Fetch the maximum input buffer size for sasl_encode().
299 ** This can be less than the size set in attemptauth()
300 ** due to a negotiation with the other side, e.g.,
301 ** Cyrus IMAP lmtp program sets maxbuf=4096,
302 ** digestmd5 substracts 25 and hence we'll get 4071
303 ** instead of 8192 (MAXOUTLEN).
304 ** Hack (for now): simply reduce the size, callers are (must be)
305 ** able to deal with that and invoke sasl_write() again with
306 ** the rest of the data.
307 ** Note: it would be better to store this value in the context
308 ** after the negotiation.
311 result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
312 (const void **) &maxencode);
313 if (result == SASL_OK && size > *maxencode && *maxencode > 0)
316 result = sasl_encode(so->conn, buf,
317 (unsigned int) size, &outbuf, &outlen);
319 if (result != SASL_OK)
322 sm_syslog(LOG_WARNING, NOQID,
323 "AUTH: sasl_encode error=%d", result);
332 /* XXX result == 0? */
333 ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
334 &outbuf[total], outlen);
341 SASL_DEALLOC(outbuf);
342 # endif /* SASL < 20000 */
348 ** SFDCSASL -- create sasl file type and open in and out file pointers
349 ** for sendmail to read from and write to.
352 ** fin -- the sm_io file encrypted data to be read from
353 ** fout -- the sm_io file encrypted data to be written to
354 ** conn -- the sasl connection pointer
362 ** The arguments "fin" and "fout" are replaced with the new
363 ** SM_FILE_T pointers.
367 sfdcsasl(fin, fout, conn, tmo)
373 SM_FILE_T *newin, *newout;
374 SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
375 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
377 struct sasl_info info;
381 /* no need to do anything */
385 SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
386 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
390 newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
391 SM_IO_RDONLY_B, NULL);
398 newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
399 SM_IO_WRONLY_B, NULL);
403 (void) sm_io_close(newin, SM_TIME_DEFAULT);
406 sm_io_automode(newin, newout);
408 sm_io_setinfo(*fin, SM_IO_WHAT_TIMEOUT, &tmo);
409 sm_io_setinfo(*fout, SM_IO_WHAT_TIMEOUT, &tmo);
419 # include <openssl/err.h>
421 /* Structure used by the "tls" file type */
435 ** TLS_GETINFO - returns requested information about a "tls" file
439 ** fp -- the file descriptor
440 ** what -- the type of information requested
441 ** valp -- the thang to return the information in (unused)
444 ** -1 for unknown requests
445 ** >=0 on success with valp filled in (if possible).
448 static int tls_getinfo __P((SM_FILE_T *, int, void *));
452 tls_getinfo(fp, what, valp)
457 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
464 return so->fp->f_file; /* for stdio fileno() compatability */
466 case SM_IO_IS_READABLE:
467 return SSL_pending(so->con) > 0;
475 ** TLS_OPEN -- creates the tls specific information for opening a
476 ** file of the tls type.
479 ** fp -- the file pointer associated with the new open
480 ** info -- the sm_io file pointer holding the open and the
481 ** TLS encryption connection to be read from or written to
489 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
493 tls_open(fp, info, flags, rpool)
500 struct tls_info *ti = (struct tls_info *) info;
502 so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
512 ** We try to get the "raw" file descriptor that TLS uses to
513 ** do the actual read/write with. This is to allow us control
514 ** over the file descriptor being a blocking or non-blocking type.
515 ** Under the covers TLS handles the change and this allows us
516 ** to do timeouts with sm_io.
519 fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL);
520 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
526 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer
529 ** fp -- the file pointer to close
535 static int tls_close __P((SM_FILE_T *));
543 so = (struct tls_obj *) fp->f_cookie;
548 sm_io_close(so->fp, SM_TIME_DEFAULT);
556 /* maximum number of retries for TLS related I/O due to handshakes */
557 # define MAX_TLS_IOS 4
560 ** TLS_RETRY -- check whether a failed SSL operation can be retried
563 ** ssl -- TLS structure
566 ** tlsstart -- start time of TLS operation
567 ** timeout -- timeout for TLS operation
569 ** where -- description of operation
578 tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
589 time_t now = curtime();
595 ** For SSL_ERROR_WANT_{READ,WRITE}:
596 ** There is not a complete SSL record available yet
597 ** or there is only a partial SSL record removed from
598 ** the network (socket) buffer into the SSL buffer.
599 ** The SSL_connect will only succeed when a full
600 ** SSL record is available (assuming a "real" error
601 ** doesn't happen). To handle when a "real" error
602 ** does happen the select is set for exceptions too.
603 ** The connection may be re-negotiated during this time
604 ** so both read and write "want errors" need to be handled.
605 ** A select() exception loops back so that a proper SSL
606 ** error message can be gotten.
609 left = timeout - (now - tlsstart);
611 return 0; /* timeout */
617 sm_syslog(LOG_INFO, NOQID,
618 "STARTTLS=%s, info: fds=%d/%d, err=%d",
619 where, rfd, wfd, err);
622 if ((err == SSL_ERROR_WANT_READ && !SM_FD_OK_SELECT(rfd)) ||
623 (err == SSL_ERROR_WANT_WRITE && !SM_FD_OK_SELECT(wfd)))
627 sm_syslog(LOG_ERR, NOQID,
628 "STARTTLS=%s, error: fd %d/%d too large",
631 tlslogerr(LOG_WARNING, where);
635 else if (err == SSL_ERROR_WANT_READ)
637 fd_set ssl_maskr, ssl_maskx;
638 int save_errno = errno;
641 FD_SET(rfd, &ssl_maskr);
643 FD_SET(rfd, &ssl_maskx);
646 ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
648 } while (ret < 0 && errno == EINTR);
649 if (ret < 0 && errno > 0)
653 else if (err == SSL_ERROR_WANT_WRITE)
655 fd_set ssl_maskw, ssl_maskx;
656 int save_errno = errno;
659 FD_SET(wfd, &ssl_maskw);
661 FD_SET(rfd, &ssl_maskx);
664 ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
666 } while (ret < 0 && errno == EINTR);
667 if (ret < 0 && errno > 0)
674 /* errno to force refill() etc to stop (see IS_IO_ERROR()) */
676 # define SM_ERR_TIMEOUT ETIMEDOUT
677 #else /* ETIMEDOUT */
678 # define SM_ERR_TIMEOUT EIO
679 #endif /* ETIMEDOUT */
682 ** SET_TLS_RD_TMO -- read secured information for the caller
685 ** rd_tmo -- read timeout
688 ** previous read timeout
689 ** This is a hack: there is no way to pass it in
692 static int tls_rd_tmo = -1;
695 set_tls_rd_tmo(rd_tmo)
700 old_rd_tmo = tls_rd_tmo;
706 ** TLS_READ -- read secured information for the caller
709 ** fp -- the file pointer
710 ** buf -- the location to place the data
711 ** size -- the number of bytes to read from connection
715 ** otherwise the number of bytes read
718 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
721 tls_read(fp, buf, size)
726 int r, rfd, wfd, try, ssl_err;
727 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
733 tlsstart = curtime();
736 r = SSL_read(so->con, (char *) buf, size);
742 switch (ssl_err = SSL_get_error(so->con, r))
745 case SSL_ERROR_ZERO_RETURN:
747 case SSL_ERROR_WANT_WRITE:
748 err = "read W BLOCK";
750 case SSL_ERROR_WANT_READ:
752 err = "read R BLOCK";
753 rfd = SSL_get_rfd(so->con);
754 wfd = SSL_get_wfd(so->con);
755 try = tls_retry(so->con, rfd, wfd, tlsstart,
756 (tls_rd_tmo < 0) ? TimeOuts.to_datablock
761 errno = SM_ERR_TIMEOUT;
764 case SSL_ERROR_WANT_X509_LOOKUP:
765 err = "write X BLOCK";
767 case SSL_ERROR_SYSCALL:
768 if (r == 0 && errno == 0) /* out of protocol EOF found */
770 err = "syscall error";
772 get_last_socket_error());
776 #if DEAL_WITH_ERROR_SSL
777 if (r == 0 && errno == 0) /* out of protocol EOF found */
779 #endif /* DEAL_WITH_ERROR_SSL */
780 err = "generic SSL error";
786 if (errno == EAGAIN && try > 0)
790 tlslogerr(pri, "read");
793 #if DEAL_WITH_ERROR_SSL
794 /* avoid repeated calls? */
797 #endif /* DEAL_WITH_ERROR_SSL */
804 save_errno = (errno == 0) ? EIO : errno;
805 if (try == 0 && save_errno == SM_ERR_TIMEOUT)
808 sm_syslog(LOG_WARNING, NOQID,
809 "STARTTLS: read error=timeout");
811 else if (LogLevel > 8)
815 if (save_errno == EAGAIN && try > 0)
819 sm_syslog(pri, NOQID,
820 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
822 ERR_error_string(ERR_get_error(), NULL), try,
825 else if (LogLevel > 7)
826 sm_syslog(LOG_WARNING, NOQID,
827 "STARTTLS: read error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
828 err, r, errno, try, ssl_err);
835 ** TLS_WRITE -- write information out through secure connection
838 ** fp -- the file pointer
839 ** buf -- holds the data to be securely written
840 ** size -- the number of bytes to write
844 ** otherwise number of bytes written
847 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
850 tls_write(fp, buf, size)
855 int r, rfd, wfd, try, ssl_err;
856 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
862 tlsstart = curtime();
865 r = SSL_write(so->con, (char *) buf, size);
870 switch (ssl_err = SSL_get_error(so->con, r))
873 case SSL_ERROR_ZERO_RETURN:
875 case SSL_ERROR_WANT_WRITE:
876 err = "read W BLOCK";
878 case SSL_ERROR_WANT_READ:
880 err = "read R BLOCK";
881 rfd = SSL_get_rfd(so->con);
882 wfd = SSL_get_wfd(so->con);
883 try = tls_retry(so->con, rfd, wfd, tlsstart,
884 DATA_PROGRESS_TIMEOUT, ssl_err, "write");
887 errno = SM_ERR_TIMEOUT;
889 case SSL_ERROR_WANT_X509_LOOKUP:
890 err = "write X BLOCK";
892 case SSL_ERROR_SYSCALL:
893 if (r == 0 && errno == 0) /* out of protocol EOF found */
895 err = "syscall error";
897 get_last_socket_error());
901 err = "generic SSL error";
903 ERR_GET_REASON(ERR_peek_error()));
906 tlslogerr(LOG_WARNING, "write");
908 #if DEAL_WITH_ERROR_SSL
909 /* avoid repeated calls? */
912 #endif /* DEAL_WITH_ERROR_SSL */
919 save_errno = (errno == 0) ? EIO : errno;
920 if (try == 0 && save_errno == SM_ERR_TIMEOUT)
923 sm_syslog(LOG_WARNING, NOQID,
924 "STARTTLS: write error=timeout");
926 else if (LogLevel > 8)
927 sm_syslog(LOG_WARNING, NOQID,
928 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
930 ERR_error_string(ERR_get_error(), NULL), try,
932 else if (LogLevel > 7)
933 sm_syslog(LOG_WARNING, NOQID,
934 "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
935 err, r, errno, try, ssl_err);
942 ** SFDCTLS -- create tls file type and open in and out file pointers
943 ** for sendmail to read from and write to.
946 ** fin -- data input source being replaced
947 ** fout -- data output source being replaced
948 ** con -- the tls connection pointer
955 ** The arguments "fin" and "fout" are replaced with the new
956 ** SM_FILE_T pointers.
957 ** The original "fin" and "fout" are preserved in the tls file
958 ** type but are not actually used because of the design of TLS.
962 sfdctls(fin, fout, con)
967 SM_FILE_T *tlsin, *tlsout;
968 SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
969 tls_read, tls_write, NULL, tls_getinfo, NULL,
971 struct tls_info info;
973 SM_ASSERT(con != NULL);
975 SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
976 tls_read, tls_write, NULL, tls_getinfo, NULL,
980 tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
986 tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
990 (void) sm_io_close(tlsin, SM_TIME_DEFAULT);
993 sm_io_automode(tlsin, tlsout);
999 #endif /* STARTTLS */