xref: /freebsd/contrib/sendmail/src/sfsasl.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * Copyright (c) 1999-2006 Sendmail, Inc. and its suppliers.
3  *	All rights reserved.
4  *
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.
8  *
9  */
10 
11 #include <sm/gen.h>
12 SM_RCSID("@(#)$Id: sfsasl.c,v 8.115 2006/04/18 21:34:07 ca Exp $")
13 #include <stdlib.h>
14 #include <sendmail.h>
15 #include <sm/time.h>
16 #include <errno.h>
17 
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 */
22 
23 #if SASL
24 # include "sfsasl.h"
25 
26 /* Structure used by the "sasl" file type */
27 struct sasl_obj
28 {
29 	SM_FILE_T *fp;
30 	sasl_conn_t *conn;
31 };
32 
33 struct sasl_info
34 {
35 	SM_FILE_T *fp;
36 	sasl_conn_t *conn;
37 };
38 
39 /*
40 **  SASL_GETINFO - returns requested information about a "sasl" file
41 **		  descriptor.
42 **
43 **	Parameters:
44 **		fp -- the file descriptor
45 **		what -- the type of information requested
46 **		valp -- the thang to return the information in
47 **
48 **	Returns:
49 **		-1 for unknown requests
50 **		>=0 on success with valp filled in (if possible).
51 */
52 
53 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
54 
55 static int
56 sasl_getinfo(fp, what, valp)
57 	SM_FILE_T *fp;
58 	int what;
59 	void *valp;
60 {
61 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
62 
63 	switch (what)
64 	{
65 	  case SM_IO_WHAT_FD:
66 		if (so->fp == NULL)
67 			return -1;
68 		return so->fp->f_file; /* for stdio fileno() compatability */
69 
70 	  case SM_IO_IS_READABLE:
71 		if (so->fp == NULL)
72 			return 0;
73 
74 		/* get info from underlying file */
75 		return sm_io_getinfo(so->fp, what, valp);
76 
77 	  default:
78 		return -1;
79 	}
80 }
81 
82 /*
83 **  SASL_OPEN -- creates the sasl specific information for opening a
84 **		file of the sasl type.
85 **
86 **	Parameters:
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
90 **		flags -- ignored
91 **		rpool -- ignored
92 **
93 **	Returns:
94 **		0 on success
95 */
96 
97 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
98 
99 /* ARGSUSED2 */
100 static int
101 sasl_open(fp, info, flags, rpool)
102 	SM_FILE_T *fp;
103 	const void *info;
104 	int flags;
105 	const void *rpool;
106 {
107 	struct sasl_obj *so;
108 	struct sasl_info *si = (struct sasl_info *) info;
109 
110 	so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
111 	if (so == NULL)
112 	{
113 		errno = ENOMEM;
114 		return -1;
115 	}
116 	so->fp = si->fp;
117 	so->conn = si->conn;
118 
119 	/*
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.
128 	*/
129 
130 	(void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
131 	fp->f_cookie = so;
132 	return 0;
133 }
134 
135 /*
136 **  SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
137 **
138 **	Parameters:
139 **		fp -- the file pointer to close
140 **
141 **	Returns:
142 **		0 on success
143 */
144 
145 static int sasl_close __P((SM_FILE_T *));
146 
147 static int
148 sasl_close(fp)
149 	SM_FILE_T *fp;
150 {
151 	struct sasl_obj *so;
152 
153 	so = (struct sasl_obj *) fp->f_cookie;
154 	if (so == NULL)
155 		return 0;
156 	if (so->fp != NULL)
157 	{
158 		sm_io_close(so->fp, SM_TIME_DEFAULT);
159 		so->fp = NULL;
160 	}
161 	sm_free(so);
162 	so = NULL;
163 	return 0;
164 }
165 
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)
169 
170 /*
171 **  SASL_READ -- read encrypted information and decrypt it for the caller
172 **
173 **	Parameters:
174 **		fp -- the file pointer
175 **		buf -- the location to place the decrypted information
176 **		size -- the number of bytes to read after decryption
177 **
178 **	Results:
179 **		-1 on error
180 **		otherwise the number of bytes read
181 */
182 
183 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
184 
185 static ssize_t
186 sasl_read(fp, buf, size)
187 	SM_FILE_T *fp;
188 	char *buf;
189 	size_t size;
190 {
191 	int result;
192 	ssize_t len;
193 # if SASL >= 20000
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;
201 
202 	/*
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
208 	**  if necessary.
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.
212 	*/
213 
214 # if SASL >= 20000
215 	while (outlen == 0)
216 # else /* SASL >= 20000 */
217 	while (outbuf == NULL && outlen == 0)
218 # endif /* SASL >= 20000 */
219 	{
220 		len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
221 		if (len <= 0)
222 			return len;
223 		result = sasl_decode(so->conn, buf,
224 				     (unsigned int) len, &outbuf, &outlen);
225 		if (result != SASL_OK)
226 		{
227 			if (LogLevel > 7)
228 				sm_syslog(LOG_WARNING, NOQID,
229 					"AUTH: sasl_decode error=%d", result);
230 			outbuf = NULL;
231 			offset = 0;
232 			outlen = 0;
233 			return -1;
234 		}
235 	}
236 
237 	if (outbuf == NULL)
238 	{
239 		/* be paranoid: outbuf == NULL but outlen != 0 */
240 		syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
241 		/* NOTREACHED */
242 	}
243 	if (outlen - offset > size)
244 	{
245 		/* return another part of the buffer */
246 		(void) memcpy(buf, outbuf + offset, size);
247 		offset += size;
248 		len = size;
249 	}
250 	else
251 	{
252 		/* return the rest of the buffer */
253 		len = outlen - offset;
254 		(void) memcpy(buf, outbuf + offset, (size_t) len);
255 # if SASL < 20000
256 		SASL_DEALLOC(outbuf);
257 # endif /* SASL < 20000 */
258 		outbuf = NULL;
259 		offset = 0;
260 		outlen = 0;
261 	}
262 	return len;
263 }
264 
265 /*
266 **  SASL_WRITE -- write information out after encrypting it
267 **
268 **	Parameters:
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
272 **
273 **	Returns:
274 **		-1 on error
275 **		otherwise number of bytes written
276 */
277 
278 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
279 
280 static ssize_t
281 sasl_write(fp, buf, size)
282 	SM_FILE_T *fp;
283 	const char *buf;
284 	size_t size;
285 {
286 	int result;
287 # if SASL >= 20000
288 	const char *outbuf;
289 # else /* SASL >= 20000 */
290 	char *outbuf;
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;
295 
296 	/*
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.
308 	*/
309 
310 	result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
311 				(const void **) &maxencode);
312 	if (result == SASL_OK && size > *maxencode && *maxencode > 0)
313 		size = *maxencode;
314 
315 	result = sasl_encode(so->conn, buf,
316 			     (unsigned int) size, &outbuf, &outlen);
317 
318 	if (result != SASL_OK)
319 	{
320 		if (LogLevel > 7)
321 			sm_syslog(LOG_WARNING, NOQID,
322 				"AUTH: sasl_encode error=%d", result);
323 		return -1;
324 	}
325 
326 	if (outbuf != NULL)
327 	{
328 		while (outlen > 0)
329 		{
330 			errno = 0;
331 			/* XXX result == 0? */
332 			ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
333 					  &outbuf[total], outlen);
334 			if (ret <= 0)
335 				return ret;
336 			outlen -= ret;
337 			total += ret;
338 		}
339 # if SASL < 20000
340 		SASL_DEALLOC(outbuf);
341 # endif /* SASL < 20000 */
342 	}
343 	return size;
344 }
345 
346 /*
347 **  SFDCSASL -- create sasl file type and open in and out file pointers
348 **	       for sendmail to read from and write to.
349 **
350 **	Parameters:
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
354 **		tmo -- timeout
355 **
356 **	Returns:
357 **		-1 on error
358 **		0 on success
359 **
360 **	Side effects:
361 **		The arguments "fin" and "fout" are replaced with the new
362 **		SM_FILE_T pointers.
363 */
364 
365 int
366 sfdcsasl(fin, fout, conn, tmo)
367 	SM_FILE_T **fin;
368 	SM_FILE_T **fout;
369 	sasl_conn_t *conn;
370 	int tmo;
371 {
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,
375 		SM_TIME_DEFAULT);
376 	struct sasl_info info;
377 
378 	if (conn == NULL)
379 	{
380 		/* no need to do anything */
381 		return 0;
382 	}
383 
384 	SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
385 		sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
386 		SM_TIME_DEFAULT);
387 	info.fp = *fin;
388 	info.conn = conn;
389 	newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
390 			SM_IO_RDONLY_B, NULL);
391 
392 	if (newin == NULL)
393 		return -1;
394 
395 	info.fp = *fout;
396 	info.conn = conn;
397 	newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
398 			SM_IO_WRONLY_B, NULL);
399 
400 	if (newout == NULL)
401 	{
402 		(void) sm_io_close(newin, SM_TIME_DEFAULT);
403 		return -1;
404 	}
405 	sm_io_automode(newin, newout);
406 
407 	sm_io_setinfo(*fin, SM_IO_WHAT_TIMEOUT, &tmo);
408 	sm_io_setinfo(*fout, SM_IO_WHAT_TIMEOUT, &tmo);
409 
410 	*fin = newin;
411 	*fout = newout;
412 	return 0;
413 }
414 #endif /* SASL */
415 
416 #if STARTTLS
417 # include "sfsasl.h"
418 #  include <openssl/err.h>
419 
420 /* Structure used by the "tls" file type */
421 struct tls_obj
422 {
423 	SM_FILE_T *fp;
424 	SSL *con;
425 };
426 
427 struct tls_info
428 {
429 	SM_FILE_T *fp;
430 	SSL *con;
431 };
432 
433 /*
434 **  TLS_GETINFO - returns requested information about a "tls" file
435 **		 descriptor.
436 **
437 **	Parameters:
438 **		fp -- the file descriptor
439 **		what -- the type of information requested
440 **		valp -- the thang to return the information in (unused)
441 **
442 **	Returns:
443 **		-1 for unknown requests
444 **		>=0 on success with valp filled in (if possible).
445 */
446 
447 static int tls_getinfo __P((SM_FILE_T *, int, void *));
448 
449 /* ARGSUSED2 */
450 static int
451 tls_getinfo(fp, what, valp)
452 	SM_FILE_T *fp;
453 	int what;
454 	void *valp;
455 {
456 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
457 
458 	switch (what)
459 	{
460 	  case SM_IO_WHAT_FD:
461 		if (so->fp == NULL)
462 			return -1;
463 		return so->fp->f_file; /* for stdio fileno() compatability */
464 
465 	  case SM_IO_IS_READABLE:
466 		return SSL_pending(so->con) > 0;
467 
468 	  default:
469 		return -1;
470 	}
471 }
472 
473 /*
474 **  TLS_OPEN -- creates the tls specific information for opening a
475 **	       file of the tls type.
476 **
477 **	Parameters:
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
481 **		flags -- ignored
482 **		rpool -- ignored
483 **
484 **	Returns:
485 **		0 on success
486 */
487 
488 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
489 
490 /* ARGSUSED2 */
491 static int
492 tls_open(fp, info, flags, rpool)
493 	SM_FILE_T *fp;
494 	const void *info;
495 	int flags;
496 	const void *rpool;
497 {
498 	struct tls_obj *so;
499 	struct tls_info *ti = (struct tls_info *) info;
500 
501 	so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
502 	if (so == NULL)
503 	{
504 		errno = ENOMEM;
505 		return -1;
506 	}
507 	so->fp = ti->fp;
508 	so->con = ti->con;
509 
510 	/*
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.
516 	*/
517 
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);
520 	fp->f_cookie = so;
521 	return 0;
522 }
523 
524 /*
525 **  TLS_CLOSE -- close the tls specific parts of the tls file pointer
526 **
527 **	Parameters:
528 **		fp -- the file pointer to close
529 **
530 **	Returns:
531 **		0 on success
532 */
533 
534 static int tls_close __P((SM_FILE_T *));
535 
536 static int
537 tls_close(fp)
538 	SM_FILE_T *fp;
539 {
540 	struct tls_obj *so;
541 
542 	so = (struct tls_obj *) fp->f_cookie;
543 	if (so == NULL)
544 		return 0;
545 	if (so->fp != NULL)
546 	{
547 		sm_io_close(so->fp, SM_TIME_DEFAULT);
548 		so->fp = NULL;
549 	}
550 	sm_free(so);
551 	so = NULL;
552 	return 0;
553 }
554 
555 /* maximum number of retries for TLS related I/O due to handshakes */
556 # define MAX_TLS_IOS	4
557 
558 /*
559 **  TLS_RETRY -- check whether a failed SSL operation can be retried
560 **
561 **	Parameters:
562 **		ssl -- TLS structure
563 **		rfd -- read fd
564 **		wfd -- write fd
565 **		tlsstart -- start time of TLS operation
566 **		timeout -- timeout for TLS operation
567 **		err -- SSL error
568 **		where -- description of operation
569 **
570 **	Results:
571 **		>0 on success
572 **		0 on timeout
573 **		<0 on error
574 */
575 
576 int
577 tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
578 	SSL *ssl;
579 	int rfd;
580 	int wfd;
581 	time_t tlsstart;
582 	int timeout;
583 	int err;
584 	const char *where;
585 {
586 	int ret;
587 	time_t left;
588 	time_t now = curtime();
589 	struct timeval tv;
590 
591 	ret = -1;
592 
593 	/*
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.
606 	*/
607 
608 	left = timeout - (now - tlsstart);
609 	if (left <= 0)
610 		return 0;	/* timeout */
611 	tv.tv_sec = left;
612 	tv.tv_usec = 0;
613 
614 	if (LogLevel > 14)
615 	{
616 		sm_syslog(LOG_INFO, NOQID,
617 			  "STARTTLS=%s, info: fds=%d/%d, err=%d",
618 			  where, rfd, wfd, err);
619 	}
620 
621 	if (FD_SETSIZE > 0 &&
622 	    ((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) ||
623 	     (err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
624 	{
625 		if (LogLevel > 5)
626 		{
627 			sm_syslog(LOG_ERR, NOQID,
628 				  "STARTTLS=%s, error: fd %d/%d too large",
629 				  where, rfd, wfd);
630 		if (LogLevel > 8)
631 			tlslogerr(where);
632 		}
633 		errno = EINVAL;
634 	}
635 	else if (err == SSL_ERROR_WANT_READ)
636 	{
637 		fd_set ssl_maskr, ssl_maskx;
638 
639 		FD_ZERO(&ssl_maskr);
640 		FD_SET(rfd, &ssl_maskr);
641 		FD_ZERO(&ssl_maskx);
642 		FD_SET(rfd, &ssl_maskx);
643 		do
644 		{
645 			ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
646 					&tv);
647 		} while (ret < 0 && errno == EINTR);
648 		if (ret < 0 && errno > 0)
649 			ret = -errno;
650 	}
651 	else if (err == SSL_ERROR_WANT_WRITE)
652 	{
653 		fd_set ssl_maskw, ssl_maskx;
654 
655 		FD_ZERO(&ssl_maskw);
656 		FD_SET(wfd, &ssl_maskw);
657 		FD_ZERO(&ssl_maskx);
658 		FD_SET(rfd, &ssl_maskx);
659 		do
660 		{
661 			ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
662 					&tv);
663 		} while (ret < 0 && errno == EINTR);
664 		if (ret < 0 && errno > 0)
665 			ret = -errno;
666 	}
667 	return ret;
668 }
669 
670 /* errno to force refill() etc to stop (see IS_IO_ERROR()) */
671 #ifdef ETIMEDOUT
672 # define SM_ERR_TIMEOUT	ETIMEDOUT
673 #else /* ETIMEDOUT */
674 # define SM_ERR_TIMEOUT	EIO
675 #endif /* ETIMEDOUT */
676 
677 /*
678 **  TLS_READ -- read secured information for the caller
679 **
680 **	Parameters:
681 **		fp -- the file pointer
682 **		buf -- the location to place the data
683 **		size -- the number of bytes to read from connection
684 **
685 **	Results:
686 **		-1 on error
687 **		otherwise the number of bytes read
688 */
689 
690 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
691 
692 static ssize_t
693 tls_read(fp, buf, size)
694 	SM_FILE_T *fp;
695 	char *buf;
696 	size_t size;
697 {
698 	int r, rfd, wfd, try, ssl_err;
699 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
700 	time_t tlsstart;
701 	char *err;
702 
703 	try = 99;
704 	err = NULL;
705 	tlsstart = curtime();
706 
707   retry:
708 	r = SSL_read(so->con, (char *) buf, size);
709 
710 	if (r > 0)
711 		return r;
712 
713 	err = NULL;
714 	switch (ssl_err = SSL_get_error(so->con, r))
715 	{
716 	  case SSL_ERROR_NONE:
717 	  case SSL_ERROR_ZERO_RETURN:
718 		break;
719 	  case SSL_ERROR_WANT_WRITE:
720 		err = "read W BLOCK";
721 		/* FALLTHROUGH */
722 	  case SSL_ERROR_WANT_READ:
723 		if (err == NULL)
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");
729 		if (try > 0)
730 			goto retry;
731 		errno = SM_ERR_TIMEOUT;
732 		break;
733 
734 	  case SSL_ERROR_WANT_X509_LOOKUP:
735 		err = "write X BLOCK";
736 		break;
737 	  case SSL_ERROR_SYSCALL:
738 		if (r == 0 && errno == 0) /* out of protocol EOF found */
739 			break;
740 		err = "syscall error";
741 /*
742 		get_last_socket_error());
743 */
744 		break;
745 	  case SSL_ERROR_SSL:
746 #if DEAL_WITH_ERROR_SSL
747 		if (r == 0 && errno == 0) /* out of protocol EOF found */
748 			break;
749 #endif /* DEAL_WITH_ERROR_SSL */
750 		err = "generic SSL error";
751 		if (LogLevel > 9)
752 			tlslogerr("read");
753 
754 #if DEAL_WITH_ERROR_SSL
755 		/* avoid repeated calls? */
756 		if (r == 0)
757 			r = -1;
758 #endif /* DEAL_WITH_ERROR_SSL */
759 		break;
760 	}
761 	if (err != NULL)
762 	{
763 		int save_errno;
764 
765 		save_errno = (errno == 0) ? EIO : errno;
766 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
767 		{
768 			if (LogLevel > 7)
769 				sm_syslog(LOG_WARNING, NOQID,
770 					  "STARTTLS: read error=timeout");
771 		}
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",
775 				  err, r, errno,
776 				  ERR_error_string(ERR_get_error(), NULL), try,
777 				  ssl_err);
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);
782 		errno = save_errno;
783 	}
784 	return r;
785 }
786 
787 /*
788 **  TLS_WRITE -- write information out through secure connection
789 **
790 **	Parameters:
791 **		fp -- the file pointer
792 **		buf -- holds the data to be securely written
793 **		size -- the number of bytes to write
794 **
795 **	Returns:
796 **		-1 on error
797 **		otherwise number of bytes written
798 */
799 
800 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
801 
802 static ssize_t
803 tls_write(fp, buf, size)
804 	SM_FILE_T *fp;
805 	const char *buf;
806 	size_t size;
807 {
808 	int r, rfd, wfd, try, ssl_err;
809 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
810 	time_t tlsstart;
811 	char *err;
812 
813 	try = 99;
814 	err = NULL;
815 	tlsstart = curtime();
816 
817   retry:
818 	r = SSL_write(so->con, (char *) buf, size);
819 
820 	if (r > 0)
821 		return r;
822 	err = NULL;
823 	switch (ssl_err = SSL_get_error(so->con, r))
824 	{
825 	  case SSL_ERROR_NONE:
826 	  case SSL_ERROR_ZERO_RETURN:
827 		break;
828 	  case SSL_ERROR_WANT_WRITE:
829 		err = "read W BLOCK";
830 		/* FALLTHROUGH */
831 	  case SSL_ERROR_WANT_READ:
832 		if (err == NULL)
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");
838 		if (try > 0)
839 			goto retry;
840 		errno = SM_ERR_TIMEOUT;
841 		break;
842 	  case SSL_ERROR_WANT_X509_LOOKUP:
843 		err = "write X BLOCK";
844 		break;
845 	  case SSL_ERROR_SYSCALL:
846 		if (r == 0 && errno == 0) /* out of protocol EOF found */
847 			break;
848 		err = "syscall error";
849 /*
850 		get_last_socket_error());
851 */
852 		break;
853 	  case SSL_ERROR_SSL:
854 		err = "generic SSL error";
855 /*
856 		ERR_GET_REASON(ERR_peek_error()));
857 */
858 		if (LogLevel > 9)
859 			tlslogerr("write");
860 
861 #if DEAL_WITH_ERROR_SSL
862 		/* avoid repeated calls? */
863 		if (r == 0)
864 			r = -1;
865 #endif /* DEAL_WITH_ERROR_SSL */
866 		break;
867 	}
868 	if (err != NULL)
869 	{
870 		int save_errno;
871 
872 		save_errno = (errno == 0) ? EIO : errno;
873 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
874 		{
875 			if (LogLevel > 7)
876 				sm_syslog(LOG_WARNING, NOQID,
877 					  "STARTTLS: write error=timeout");
878 		}
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",
882 				  err, r, errno,
883 				  ERR_error_string(ERR_get_error(), NULL), try,
884 				  ssl_err);
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);
889 		errno = save_errno;
890 	}
891 	return r;
892 }
893 
894 /*
895 **  SFDCTLS -- create tls file type and open in and out file pointers
896 **	      for sendmail to read from and write to.
897 **
898 **	Parameters:
899 **		fin -- data input source being replaced
900 **		fout -- data output source being replaced
901 **		con -- the tls connection pointer
902 **
903 **	Returns:
904 **		-1 on error
905 **		0 on success
906 **
907 **	Side effects:
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.
912 */
913 
914 int
915 sfdctls(fin, fout, con)
916 	SM_FILE_T **fin;
917 	SM_FILE_T **fout;
918 	SSL *con;
919 {
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,
923 		SM_TIME_FOREVER);
924 	struct tls_info info;
925 
926 	SM_ASSERT(con != NULL);
927 
928 	SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
929 		tls_read, tls_write, NULL, tls_getinfo, NULL,
930 		SM_TIME_FOREVER);
931 	info.fp = *fin;
932 	info.con = con;
933 	tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
934 			   NULL);
935 	if (tlsin == NULL)
936 		return -1;
937 
938 	info.fp = *fout;
939 	tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
940 			    NULL);
941 	if (tlsout == NULL)
942 	{
943 		(void) sm_io_close(tlsin, SM_TIME_DEFAULT);
944 		return -1;
945 	}
946 	sm_io_automode(tlsin, tlsout);
947 
948 	*fin = tlsin;
949 	*fout = tlsout;
950 	return 0;
951 }
952 #endif /* STARTTLS */
953