2 * Copyright (c) 1999-2006 Sendmail, 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.115 2006/04/18 21:34:07 ca Exp $")
18 /* allow to disable error handling code just in case... */
19 #ifndef DEAL_WITH_ERROR_SSL
20 # define DEAL_WITH_ERROR_SSL 1
21 #endif /* ! DEAL_WITH_ERROR_SSL */
26 /* Structure used by the "sasl" file type */
40 ** SASL_GETINFO - returns requested information about a "sasl" file
44 ** fp -- the file descriptor
45 ** what -- the type of information requested
46 ** valp -- the thang to return the information in
49 ** -1 for unknown requests
50 ** >=0 on success with valp filled in (if possible).
53 static int sasl_getinfo
__P((SM_FILE_T
*, int, void *));
56 sasl_getinfo(fp
, what
, valp
)
61 struct sasl_obj
*so
= (struct sasl_obj
*) fp
->f_cookie
;
68 return so
->fp
->f_file
; /* for stdio fileno() compatability */
70 case SM_IO_IS_READABLE
:
74 /* get info from underlying file */
75 return sm_io_getinfo(so
->fp
, what
, valp
);
83 ** SASL_OPEN -- creates the sasl specific information for opening a
84 ** file of the sasl type.
87 ** fp -- the file pointer associated with the new open
88 ** info -- contains the sasl connection information pointer and
89 ** the original SM_FILE_T that holds the open
97 static int sasl_open
__P((SM_FILE_T
*, const void *, int, const void *));
101 sasl_open(fp
, info
, flags
, rpool
)
108 struct sasl_info
*si
= (struct sasl_info
*) info
;
110 so
= (struct sasl_obj
*) sm_malloc(sizeof(struct sasl_obj
));
120 ** The underlying 'fp' is set to SM_IO_NOW so that the entire
121 ** encoded string is written in one chunk. Otherwise there is
122 ** the possibility that it may appear illegal, bogus or
123 ** mangled to the other side of the connection.
124 ** We will read or write through 'fp' since it is the opaque
125 ** connection for the communications. We need to treat it this
126 ** way in case the encoded string is to be sent down a TLS
127 ** connection rather than, say, sm_io's stdio.
130 (void) sm_io_setvbuf(so
->fp
, SM_TIME_DEFAULT
, NULL
, SM_IO_NOW
, 0);
136 ** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
139 ** fp -- the file pointer to close
145 static int sasl_close
__P((SM_FILE_T
*));
153 so
= (struct sasl_obj
*) fp
->f_cookie
;
158 sm_io_close(so
->fp
, SM_TIME_DEFAULT
);
166 /* how to deallocate a buffer allocated by SASL */
167 extern void sm_sasl_free
__P((void *));
168 # define SASL_DEALLOC(b) sm_sasl_free(b)
171 ** SASL_READ -- read encrypted information and decrypt it for the caller
174 ** fp -- the file pointer
175 ** buf -- the location to place the decrypted information
176 ** size -- the number of bytes to read after decryption
180 ** otherwise the number of bytes read
183 static ssize_t sasl_read
__P((SM_FILE_T
*, char *, size_t));
186 sasl_read(fp
, buf
, size
)
194 static const char *outbuf
= NULL
;
195 # else /* SASL >= 20000 */
196 static char *outbuf
= NULL
;
197 # endif /* SASL >= 20000 */
198 static unsigned int outlen
= 0;
199 static unsigned int offset
= 0;
200 struct sasl_obj
*so
= (struct sasl_obj
*) fp
->f_cookie
;
203 ** sasl_decode() may require more data than a single read() returns.
204 ** Hence we have to put a loop around the decoding.
205 ** This also requires that we may have to split up the returned
206 ** data since it might be larger than the allowed size.
207 ** Therefore we use a static pointer and return portions of it
209 ** XXX Note: This function is not thread-safe nor can it be used
210 ** on more than one file. A correct implementation would store
211 ** this data in fp->f_cookie.
216 # else /* SASL >= 20000 */
217 while (outbuf
== NULL
&& outlen
== 0)
218 # endif /* SASL >= 20000 */
220 len
= sm_io_read(so
->fp
, SM_TIME_DEFAULT
, buf
, size
);
223 result
= sasl_decode(so
->conn
, buf
,
224 (unsigned int) len
, &outbuf
, &outlen
);
225 if (result
!= SASL_OK
)
228 sm_syslog(LOG_WARNING
, NOQID
,
229 "AUTH: sasl_decode error=%d", result
);
239 /* be paranoid: outbuf == NULL but outlen != 0 */
240 syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
243 if (outlen
- offset
> size
)
245 /* return another part of the buffer */
246 (void) memcpy(buf
, outbuf
+ offset
, size
);
252 /* return the rest of the buffer */
253 len
= outlen
- offset
;
254 (void) memcpy(buf
, outbuf
+ offset
, (size_t) len
);
256 SASL_DEALLOC(outbuf
);
257 # endif /* SASL < 20000 */
266 ** SASL_WRITE -- write information out after encrypting it
269 ** fp -- the file pointer
270 ** buf -- holds the data to be encrypted and written
271 ** size -- the number of bytes to have encrypted and written
275 ** otherwise number of bytes written
278 static ssize_t sasl_write
__P((SM_FILE_T
*, const char *, size_t));
281 sasl_write(fp
, buf
, size
)
289 # else /* SASL >= 20000 */
291 # endif /* SASL >= 20000 */
292 unsigned int outlen
, *maxencode
;
293 size_t ret
= 0, total
= 0;
294 struct sasl_obj
*so
= (struct sasl_obj
*) fp
->f_cookie
;
297 ** Fetch the maximum input buffer size for sasl_encode().
298 ** This can be less than the size set in attemptauth()
299 ** due to a negotation with the other side, e.g.,
300 ** Cyrus IMAP lmtp program sets maxbuf=4096,
301 ** digestmd5 substracts 25 and hence we'll get 4071
302 ** instead of 8192 (MAXOUTLEN).
303 ** Hack (for now): simply reduce the size, callers are (must be)
304 ** able to deal with that and invoke sasl_write() again with
305 ** the rest of the data.
306 ** Note: it would be better to store this value in the context
307 ** after the negotiation.
310 result
= sasl_getprop(so
->conn
, SASL_MAXOUTBUF
,
311 (const void **) &maxencode
);
312 if (result
== SASL_OK
&& size
> *maxencode
&& *maxencode
> 0)
315 result
= sasl_encode(so
->conn
, buf
,
316 (unsigned int) size
, &outbuf
, &outlen
);
318 if (result
!= SASL_OK
)
321 sm_syslog(LOG_WARNING
, NOQID
,
322 "AUTH: sasl_encode error=%d", result
);
331 /* XXX result == 0? */
332 ret
= sm_io_write(so
->fp
, SM_TIME_DEFAULT
,
333 &outbuf
[total
], outlen
);
340 SASL_DEALLOC(outbuf
);
341 # endif /* SASL < 20000 */
347 ** SFDCSASL -- create sasl file type and open in and out file pointers
348 ** for sendmail to read from and write to.
351 ** fin -- the sm_io file encrypted data to be read from
352 ** fout -- the sm_io file encrypted data to be written to
353 ** conn -- the sasl connection pointer
361 ** The arguments "fin" and "fout" are replaced with the new
362 ** SM_FILE_T pointers.
366 sfdcsasl(fin
, fout
, conn
, tmo
)
372 SM_FILE_T
*newin
, *newout
;
373 SM_FILE_T
SM_IO_SET_TYPE(sasl_vector
, "sasl", sasl_open
, sasl_close
,
374 sasl_read
, sasl_write
, NULL
, sasl_getinfo
, NULL
,
376 struct sasl_info info
;
380 /* no need to do anything */
384 SM_IO_INIT_TYPE(sasl_vector
, "sasl", sasl_open
, sasl_close
,
385 sasl_read
, sasl_write
, NULL
, sasl_getinfo
, NULL
,
389 newin
= sm_io_open(&sasl_vector
, SM_TIME_DEFAULT
, &info
,
390 SM_IO_RDONLY_B
, NULL
);
397 newout
= sm_io_open(&sasl_vector
, SM_TIME_DEFAULT
, &info
,
398 SM_IO_WRONLY_B
, NULL
);
402 (void) sm_io_close(newin
, SM_TIME_DEFAULT
);
405 sm_io_automode(newin
, newout
);
407 sm_io_setinfo(*fin
, SM_IO_WHAT_TIMEOUT
, &tmo
);
408 sm_io_setinfo(*fout
, SM_IO_WHAT_TIMEOUT
, &tmo
);
418 # include <openssl/err.h>
420 /* Structure used by the "tls" file type */
434 ** TLS_GETINFO - returns requested information about a "tls" file
438 ** fp -- the file descriptor
439 ** what -- the type of information requested
440 ** valp -- the thang to return the information in (unused)
443 ** -1 for unknown requests
444 ** >=0 on success with valp filled in (if possible).
447 static int tls_getinfo
__P((SM_FILE_T
*, int, void *));
451 tls_getinfo(fp
, what
, valp
)
456 struct tls_obj
*so
= (struct tls_obj
*) fp
->f_cookie
;
463 return so
->fp
->f_file
; /* for stdio fileno() compatability */
465 case SM_IO_IS_READABLE
:
466 return SSL_pending(so
->con
) > 0;
474 ** TLS_OPEN -- creates the tls specific information for opening a
475 ** file of the tls type.
478 ** fp -- the file pointer associated with the new open
479 ** info -- the sm_io file pointer holding the open and the
480 ** TLS encryption connection to be read from or written to
488 static int tls_open
__P((SM_FILE_T
*, const void *, int, const void *));
492 tls_open(fp
, info
, flags
, rpool
)
499 struct tls_info
*ti
= (struct tls_info
*) info
;
501 so
= (struct tls_obj
*) sm_malloc(sizeof(struct tls_obj
));
511 ** We try to get the "raw" file descriptor that TLS uses to
512 ** do the actual read/write with. This is to allow us control
513 ** over the file descriptor being a blocking or non-blocking type.
514 ** Under the covers TLS handles the change and this allows us
515 ** to do timeouts with sm_io.
518 fp
->f_file
= sm_io_getinfo(so
->fp
, SM_IO_WHAT_FD
, NULL
);
519 (void) sm_io_setvbuf(so
->fp
, SM_TIME_DEFAULT
, NULL
, SM_IO_NOW
, 0);
525 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer
528 ** fp -- the file pointer to close
534 static int tls_close
__P((SM_FILE_T
*));
542 so
= (struct tls_obj
*) fp
->f_cookie
;
547 sm_io_close(so
->fp
, SM_TIME_DEFAULT
);
555 /* maximum number of retries for TLS related I/O due to handshakes */
556 # define MAX_TLS_IOS 4
559 ** TLS_RETRY -- check whether a failed SSL operation can be retried
562 ** ssl -- TLS structure
565 ** tlsstart -- start time of TLS operation
566 ** timeout -- timeout for TLS operation
568 ** where -- description of operation
577 tls_retry(ssl
, rfd
, wfd
, tlsstart
, timeout
, err
, where
)
588 time_t now
= curtime();
594 ** For SSL_ERROR_WANT_{READ,WRITE}:
595 ** There is not a complete SSL record available yet
596 ** or there is only a partial SSL record removed from
597 ** the network (socket) buffer into the SSL buffer.
598 ** The SSL_connect will only succeed when a full
599 ** SSL record is available (assuming a "real" error
600 ** doesn't happen). To handle when a "real" error
601 ** does happen the select is set for exceptions too.
602 ** The connection may be re-negotiated during this time
603 ** so both read and write "want errors" need to be handled.
604 ** A select() exception loops back so that a proper SSL
605 ** error message can be gotten.
608 left
= timeout
- (now
- tlsstart
);
610 return 0; /* timeout */
616 sm_syslog(LOG_INFO
, NOQID
,
617 "STARTTLS=%s, info: fds=%d/%d, err=%d",
618 where
, rfd
, wfd
, err
);
621 if (FD_SETSIZE
> 0 &&
622 ((err
== SSL_ERROR_WANT_READ
&& rfd
>= FD_SETSIZE
) ||
623 (err
== SSL_ERROR_WANT_WRITE
&& wfd
>= FD_SETSIZE
)))
627 sm_syslog(LOG_ERR
, NOQID
,
628 "STARTTLS=%s, error: fd %d/%d too large",
635 else if (err
== SSL_ERROR_WANT_READ
)
637 fd_set ssl_maskr
, ssl_maskx
;
640 FD_SET(rfd
, &ssl_maskr
);
642 FD_SET(rfd
, &ssl_maskx
);
645 ret
= select(rfd
+ 1, &ssl_maskr
, NULL
, &ssl_maskx
,
647 } while (ret
< 0 && errno
== EINTR
);
648 if (ret
< 0 && errno
> 0)
651 else if (err
== SSL_ERROR_WANT_WRITE
)
653 fd_set ssl_maskw
, ssl_maskx
;
656 FD_SET(wfd
, &ssl_maskw
);
658 FD_SET(rfd
, &ssl_maskx
);
661 ret
= select(wfd
+ 1, NULL
, &ssl_maskw
, &ssl_maskx
,
663 } while (ret
< 0 && errno
== EINTR
);
664 if (ret
< 0 && errno
> 0)
670 /* errno to force refill() etc to stop (see IS_IO_ERROR()) */
672 # define SM_ERR_TIMEOUT ETIMEDOUT
673 #else /* ETIMEDOUT */
674 # define SM_ERR_TIMEOUT EIO
675 #endif /* ETIMEDOUT */
678 ** TLS_READ -- read secured information for the caller
681 ** fp -- the file pointer
682 ** buf -- the location to place the data
683 ** size -- the number of bytes to read from connection
687 ** otherwise the number of bytes read
690 static ssize_t tls_read
__P((SM_FILE_T
*, char *, size_t));
693 tls_read(fp
, buf
, size
)
698 int r
, rfd
, wfd
, try, ssl_err
;
699 struct tls_obj
*so
= (struct tls_obj
*) fp
->f_cookie
;
705 tlsstart
= curtime();
708 r
= SSL_read(so
->con
, (char *) buf
, size
);
714 switch (ssl_err
= SSL_get_error(so
->con
, r
))
717 case SSL_ERROR_ZERO_RETURN
:
719 case SSL_ERROR_WANT_WRITE
:
720 err
= "read W BLOCK";
722 case SSL_ERROR_WANT_READ
:
724 err
= "read R BLOCK";
725 rfd
= SSL_get_rfd(so
->con
);
726 wfd
= SSL_get_wfd(so
->con
);
727 try = tls_retry(so
->con
, rfd
, wfd
, tlsstart
,
728 TimeOuts
.to_datablock
, ssl_err
, "read");
731 errno
= SM_ERR_TIMEOUT
;
734 case SSL_ERROR_WANT_X509_LOOKUP
:
735 err
= "write X BLOCK";
737 case SSL_ERROR_SYSCALL
:
738 if (r
== 0 && errno
== 0) /* out of protocol EOF found */
740 err
= "syscall error";
742 get_last_socket_error());
746 #if DEAL_WITH_ERROR_SSL
747 if (r
== 0 && errno
== 0) /* out of protocol EOF found */
749 #endif /* DEAL_WITH_ERROR_SSL */
750 err
= "generic SSL error";
754 #if DEAL_WITH_ERROR_SSL
755 /* avoid repeated calls? */
758 #endif /* DEAL_WITH_ERROR_SSL */
765 save_errno
= (errno
== 0) ? EIO
: errno
;
766 if (try == 0 && save_errno
== SM_ERR_TIMEOUT
)
769 sm_syslog(LOG_WARNING
, NOQID
,
770 "STARTTLS: read error=timeout");
772 else if (LogLevel
> 8)
773 sm_syslog(LOG_WARNING
, NOQID
,
774 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
776 ERR_error_string(ERR_get_error(), NULL
), try,
778 else if (LogLevel
> 7)
779 sm_syslog(LOG_WARNING
, NOQID
,
780 "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
781 err
, r
, errno
, try, ssl_err
);
788 ** TLS_WRITE -- write information out through secure connection
791 ** fp -- the file pointer
792 ** buf -- holds the data to be securely written
793 ** size -- the number of bytes to write
797 ** otherwise number of bytes written
800 static ssize_t tls_write
__P((SM_FILE_T
*, const char *, size_t));
803 tls_write(fp
, buf
, size
)
808 int r
, rfd
, wfd
, try, ssl_err
;
809 struct tls_obj
*so
= (struct tls_obj
*) fp
->f_cookie
;
815 tlsstart
= curtime();
818 r
= SSL_write(so
->con
, (char *) buf
, size
);
823 switch (ssl_err
= SSL_get_error(so
->con
, r
))
826 case SSL_ERROR_ZERO_RETURN
:
828 case SSL_ERROR_WANT_WRITE
:
829 err
= "read W BLOCK";
831 case SSL_ERROR_WANT_READ
:
833 err
= "read R BLOCK";
834 rfd
= SSL_get_rfd(so
->con
);
835 wfd
= SSL_get_wfd(so
->con
);
836 try = tls_retry(so
->con
, rfd
, wfd
, tlsstart
,
837 DATA_PROGRESS_TIMEOUT
, ssl_err
, "write");
840 errno
= SM_ERR_TIMEOUT
;
842 case SSL_ERROR_WANT_X509_LOOKUP
:
843 err
= "write X BLOCK";
845 case SSL_ERROR_SYSCALL
:
846 if (r
== 0 && errno
== 0) /* out of protocol EOF found */
848 err
= "syscall error";
850 get_last_socket_error());
854 err
= "generic SSL error";
856 ERR_GET_REASON(ERR_peek_error()));
861 #if DEAL_WITH_ERROR_SSL
862 /* avoid repeated calls? */
865 #endif /* DEAL_WITH_ERROR_SSL */
872 save_errno
= (errno
== 0) ? EIO
: errno
;
873 if (try == 0 && save_errno
== SM_ERR_TIMEOUT
)
876 sm_syslog(LOG_WARNING
, NOQID
,
877 "STARTTLS: write error=timeout");
879 else if (LogLevel
> 8)
880 sm_syslog(LOG_WARNING
, NOQID
,
881 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
883 ERR_error_string(ERR_get_error(), NULL
), try,
885 else if (LogLevel
> 7)
886 sm_syslog(LOG_WARNING
, NOQID
,
887 "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
888 err
, r
, errno
, try, ssl_err
);
895 ** SFDCTLS -- create tls file type and open in and out file pointers
896 ** for sendmail to read from and write to.
899 ** fin -- data input source being replaced
900 ** fout -- data output source being replaced
901 ** con -- the tls connection pointer
908 ** The arguments "fin" and "fout" are replaced with the new
909 ** SM_FILE_T pointers.
910 ** The original "fin" and "fout" are preserved in the tls file
911 ** type but are not actually used because of the design of TLS.
915 sfdctls(fin
, fout
, con
)
920 SM_FILE_T
*tlsin
, *tlsout
;
921 SM_FILE_T
SM_IO_SET_TYPE(tls_vector
, "tls", tls_open
, tls_close
,
922 tls_read
, tls_write
, NULL
, tls_getinfo
, NULL
,
924 struct tls_info info
;
926 SM_ASSERT(con
!= NULL
);
928 SM_IO_INIT_TYPE(tls_vector
, "tls", tls_open
, tls_close
,
929 tls_read
, tls_write
, NULL
, tls_getinfo
, NULL
,
933 tlsin
= sm_io_open(&tls_vector
, SM_TIME_DEFAULT
, &info
, SM_IO_RDONLY_B
,
939 tlsout
= sm_io_open(&tls_vector
, SM_TIME_DEFAULT
, &info
, SM_IO_WRONLY_B
,
943 (void) sm_io_close(tlsin
, SM_TIME_DEFAULT
);
946 sm_io_automode(tlsin
, tlsout
);
952 #endif /* STARTTLS */