xref: /illumos-gate/usr/src/cmd/sendmail/src/sfsasl.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * Copyright (c) 1999-2006, 2008 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
12 
13 #include <sm/gen.h>
14 SM_RCSID("@(#)$Id: sfsasl.c,v 8.117 2008/01/31 18:48:29 ca Exp $")
15 #include <stdlib.h>
16 #include <sendmail.h>
17 #include <sm/time.h>
18 #include <errno.h>
19 
20 /* allow to disable error handling code just in case... */
21 #ifndef DEAL_WITH_ERROR_SSL
22 # define DEAL_WITH_ERROR_SSL	1
23 #endif /* ! DEAL_WITH_ERROR_SSL */
24 
25 #if SASL
26 # include "sfsasl.h"
27 
28 /* Structure used by the "sasl" file type */
29 struct sasl_obj
30 {
31 	SM_FILE_T *fp;
32 	sasl_conn_t *conn;
33 };
34 
35 struct sasl_info
36 {
37 	SM_FILE_T *fp;
38 	sasl_conn_t *conn;
39 };
40 
41 /*
42 **  SASL_GETINFO - returns requested information about a "sasl" file
43 **		  descriptor.
44 **
45 **	Parameters:
46 **		fp -- the file descriptor
47 **		what -- the type of information requested
48 **		valp -- the thang to return the information in
49 **
50 **	Returns:
51 **		-1 for unknown requests
52 **		>=0 on success with valp filled in (if possible).
53 */
54 
55 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
56 
57 static int
58 sasl_getinfo(fp, what, valp)
59 	SM_FILE_T *fp;
60 	int what;
61 	void *valp;
62 {
63 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
64 
65 	switch (what)
66 	{
67 	  case SM_IO_WHAT_FD:
68 		if (so->fp == NULL)
69 			return -1;
70 		return so->fp->f_file; /* for stdio fileno() compatability */
71 
72 	  case SM_IO_IS_READABLE:
73 		if (so->fp == NULL)
74 			return 0;
75 
76 		/* get info from underlying file */
77 		return sm_io_getinfo(so->fp, what, valp);
78 
79 	  default:
80 		return -1;
81 	}
82 }
83 
84 /*
85 **  SASL_OPEN -- creates the sasl specific information for opening a
86 **		file of the sasl type.
87 **
88 **	Parameters:
89 **		fp -- the file pointer associated with the new open
90 **		info -- contains the sasl connection information pointer and
91 **			the original SM_FILE_T that holds the open
92 **		flags -- ignored
93 **		rpool -- ignored
94 **
95 **	Returns:
96 **		0 on success
97 */
98 
99 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
100 
101 /* ARGSUSED2 */
102 static int
103 sasl_open(fp, info, flags, rpool)
104 	SM_FILE_T *fp;
105 	const void *info;
106 	int flags;
107 	const void *rpool;
108 {
109 	struct sasl_obj *so;
110 	struct sasl_info *si = (struct sasl_info *) info;
111 
112 	so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
113 	if (so == NULL)
114 	{
115 		errno = ENOMEM;
116 		return -1;
117 	}
118 	so->fp = si->fp;
119 	so->conn = si->conn;
120 
121 	/*
122 	**  The underlying 'fp' is set to SM_IO_NOW so that the entire
123 	**  encoded string is written in one chunk. Otherwise there is
124 	**  the possibility that it may appear illegal, bogus or
125 	**  mangled to the other side of the connection.
126 	**  We will read or write through 'fp' since it is the opaque
127 	**  connection for the communications. We need to treat it this
128 	**  way in case the encoded string is to be sent down a TLS
129 	**  connection rather than, say, sm_io's stdio.
130 	*/
131 
132 	(void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
133 	fp->f_cookie = so;
134 	return 0;
135 }
136 
137 /*
138 **  SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
139 **
140 **	Parameters:
141 **		fp -- the file pointer to close
142 **
143 **	Returns:
144 **		0 on success
145 */
146 
147 static int sasl_close __P((SM_FILE_T *));
148 
149 static int
150 sasl_close(fp)
151 	SM_FILE_T *fp;
152 {
153 	struct sasl_obj *so;
154 
155 	so = (struct sasl_obj *) fp->f_cookie;
156 	if (so == NULL)
157 		return 0;
158 	if (so->fp != NULL)
159 	{
160 		sm_io_close(so->fp, SM_TIME_DEFAULT);
161 		so->fp = NULL;
162 	}
163 	sm_free(so);
164 	so = NULL;
165 	return 0;
166 }
167 
168 /* how to deallocate a buffer allocated by SASL */
169 extern void	sm_sasl_free __P((void *));
170 #  define SASL_DEALLOC(b)	sm_sasl_free(b)
171 
172 /*
173 **  SASL_READ -- read encrypted information and decrypt it for the caller
174 **
175 **	Parameters:
176 **		fp -- the file pointer
177 **		buf -- the location to place the decrypted information
178 **		size -- the number of bytes to read after decryption
179 **
180 **	Results:
181 **		-1 on error
182 **		otherwise the number of bytes read
183 */
184 
185 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
186 
187 static ssize_t
188 sasl_read(fp, buf, size)
189 	SM_FILE_T *fp;
190 	char *buf;
191 	size_t size;
192 {
193 	int result;
194 	ssize_t len;
195 # if SASL >= 20000
196 	static const char *outbuf = NULL;
197 # else /* SASL >= 20000 */
198 	static char *outbuf = NULL;
199 # endif /* SASL >= 20000 */
200 	static unsigned int outlen = 0;
201 	static unsigned int offset = 0;
202 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
203 
204 	/*
205 	**  sasl_decode() may require more data than a single read() returns.
206 	**  Hence we have to put a loop around the decoding.
207 	**  This also requires that we may have to split up the returned
208 	**  data since it might be larger than the allowed size.
209 	**  Therefore we use a static pointer and return portions of it
210 	**  if necessary.
211 	**  XXX Note: This function is not thread-safe nor can it be used
212 	**  on more than one file. A correct implementation would store
213 	**  this data in fp->f_cookie.
214 	*/
215 
216 # if SASL >= 20000
217 	while (outlen == 0)
218 # else /* SASL >= 20000 */
219 	while (outbuf == NULL && outlen == 0)
220 # endif /* SASL >= 20000 */
221 	{
222 		len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
223 		if (len <= 0)
224 			return len;
225 		result = sasl_decode(so->conn, buf,
226 				     (unsigned int) len, &outbuf, &outlen);
227 		if (result != SASL_OK)
228 		{
229 			if (LogLevel > 7)
230 				sm_syslog(LOG_WARNING, NOQID,
231 					"AUTH: sasl_decode error=%d", result);
232 			outbuf = NULL;
233 			offset = 0;
234 			outlen = 0;
235 			return -1;
236 		}
237 	}
238 
239 	if (outbuf == NULL)
240 	{
241 		/* be paranoid: outbuf == NULL but outlen != 0 */
242 		syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
243 		/* NOTREACHED */
244 	}
245 	if (outlen - offset > size)
246 	{
247 		/* return another part of the buffer */
248 		(void) memcpy(buf, outbuf + offset, size);
249 		offset += size;
250 		len = size;
251 	}
252 	else
253 	{
254 		/* return the rest of the buffer */
255 		len = outlen - offset;
256 		(void) memcpy(buf, outbuf + offset, (size_t) len);
257 # if SASL < 20000
258 		SASL_DEALLOC(outbuf);
259 # endif /* SASL < 20000 */
260 		outbuf = NULL;
261 		offset = 0;
262 		outlen = 0;
263 	}
264 	return len;
265 }
266 
267 /*
268 **  SASL_WRITE -- write information out after encrypting it
269 **
270 **	Parameters:
271 **		fp -- the file pointer
272 **		buf -- holds the data to be encrypted and written
273 **		size -- the number of bytes to have encrypted and written
274 **
275 **	Returns:
276 **		-1 on error
277 **		otherwise number of bytes written
278 */
279 
280 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
281 
282 static ssize_t
283 sasl_write(fp, buf, size)
284 	SM_FILE_T *fp;
285 	const char *buf;
286 	size_t size;
287 {
288 	int result;
289 # if SASL >= 20000
290 	const char *outbuf;
291 # else /* SASL >= 20000 */
292 	char *outbuf;
293 # endif /* SASL >= 20000 */
294 	unsigned int outlen, *maxencode;
295 	size_t ret = 0, total = 0;
296 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
297 
298 	/*
299 	**  Fetch the maximum input buffer size for sasl_encode().
300 	**  This can be less than the size set in attemptauth()
301 	**  due to a negotation with the other side, e.g.,
302 	**  Cyrus IMAP lmtp program sets maxbuf=4096,
303 	**  digestmd5 substracts 25 and hence we'll get 4071
304 	**  instead of 8192 (MAXOUTLEN).
305 	**  Hack (for now): simply reduce the size, callers are (must be)
306 	**  able to deal with that and invoke sasl_write() again with
307 	**  the rest of the data.
308 	**  Note: it would be better to store this value in the context
309 	**  after the negotiation.
310 	*/
311 
312 	result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
313 				(const void **) &maxencode);
314 	if (result == SASL_OK && size > *maxencode && *maxencode > 0)
315 		size = *maxencode;
316 
317 	result = sasl_encode(so->conn, buf,
318 			     (unsigned int) size, &outbuf, &outlen);
319 
320 	if (result != SASL_OK)
321 	{
322 		if (LogLevel > 7)
323 			sm_syslog(LOG_WARNING, NOQID,
324 				"AUTH: sasl_encode error=%d", result);
325 		return -1;
326 	}
327 
328 	if (outbuf != NULL)
329 	{
330 		while (outlen > 0)
331 		{
332 			errno = 0;
333 			/* XXX result == 0? */
334 			ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
335 					  &outbuf[total], outlen);
336 			if (ret <= 0)
337 				return ret;
338 			outlen -= ret;
339 			total += ret;
340 		}
341 # if SASL < 20000
342 		SASL_DEALLOC(outbuf);
343 # endif /* SASL < 20000 */
344 	}
345 	return size;
346 }
347 
348 /*
349 **  SFDCSASL -- create sasl file type and open in and out file pointers
350 **	       for sendmail to read from and write to.
351 **
352 **	Parameters:
353 **		fin -- the sm_io file encrypted data to be read from
354 **		fout -- the sm_io file encrypted data to be written to
355 **		conn -- the sasl connection pointer
356 **		tmo -- timeout
357 **
358 **	Returns:
359 **		-1 on error
360 **		0 on success
361 **
362 **	Side effects:
363 **		The arguments "fin" and "fout" are replaced with the new
364 **		SM_FILE_T pointers.
365 */
366 
367 int
368 sfdcsasl(fin, fout, conn, tmo)
369 	SM_FILE_T **fin;
370 	SM_FILE_T **fout;
371 	sasl_conn_t *conn;
372 	int tmo;
373 {
374 	SM_FILE_T *newin, *newout;
375 	SM_FILE_T  SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
376 		sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
377 		SM_TIME_DEFAULT);
378 	struct sasl_info info;
379 
380 	if (conn == NULL)
381 	{
382 		/* no need to do anything */
383 		return 0;
384 	}
385 
386 	SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
387 		sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
388 		SM_TIME_DEFAULT);
389 	info.fp = *fin;
390 	info.conn = conn;
391 	newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
392 			SM_IO_RDONLY_B, NULL);
393 
394 	if (newin == NULL)
395 		return -1;
396 
397 	info.fp = *fout;
398 	info.conn = conn;
399 	newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
400 			SM_IO_WRONLY_B, NULL);
401 
402 	if (newout == NULL)
403 	{
404 		(void) sm_io_close(newin, SM_TIME_DEFAULT);
405 		return -1;
406 	}
407 	sm_io_automode(newin, newout);
408 
409 	sm_io_setinfo(*fin, SM_IO_WHAT_TIMEOUT, &tmo);
410 	sm_io_setinfo(*fout, SM_IO_WHAT_TIMEOUT, &tmo);
411 
412 	*fin = newin;
413 	*fout = newout;
414 	return 0;
415 }
416 #endif /* SASL */
417 
418 #if STARTTLS
419 # include "sfsasl.h"
420 #  include <openssl/err.h>
421 
422 /* Structure used by the "tls" file type */
423 struct tls_obj
424 {
425 	SM_FILE_T *fp;
426 	SSL *con;
427 };
428 
429 struct tls_info
430 {
431 	SM_FILE_T *fp;
432 	SSL *con;
433 };
434 
435 /*
436 **  TLS_GETINFO - returns requested information about a "tls" file
437 **		 descriptor.
438 **
439 **	Parameters:
440 **		fp -- the file descriptor
441 **		what -- the type of information requested
442 **		valp -- the thang to return the information in (unused)
443 **
444 **	Returns:
445 **		-1 for unknown requests
446 **		>=0 on success with valp filled in (if possible).
447 */
448 
449 static int tls_getinfo __P((SM_FILE_T *, int, void *));
450 
451 /* ARGSUSED2 */
452 static int
453 tls_getinfo(fp, what, valp)
454 	SM_FILE_T *fp;
455 	int what;
456 	void *valp;
457 {
458 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
459 
460 	switch (what)
461 	{
462 	  case SM_IO_WHAT_FD:
463 		if (so->fp == NULL)
464 			return -1;
465 		return so->fp->f_file; /* for stdio fileno() compatability */
466 
467 	  case SM_IO_IS_READABLE:
468 		return SSL_pending(so->con) > 0;
469 
470 	  default:
471 		return -1;
472 	}
473 }
474 
475 /*
476 **  TLS_OPEN -- creates the tls specific information for opening a
477 **	       file of the tls type.
478 **
479 **	Parameters:
480 **		fp -- the file pointer associated with the new open
481 **		info -- the sm_io file pointer holding the open and the
482 **			TLS encryption connection to be read from or written to
483 **		flags -- ignored
484 **		rpool -- ignored
485 **
486 **	Returns:
487 **		0 on success
488 */
489 
490 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
491 
492 /* ARGSUSED2 */
493 static int
494 tls_open(fp, info, flags, rpool)
495 	SM_FILE_T *fp;
496 	const void *info;
497 	int flags;
498 	const void *rpool;
499 {
500 	struct tls_obj *so;
501 	struct tls_info *ti = (struct tls_info *) info;
502 
503 	so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
504 	if (so == NULL)
505 	{
506 		errno = ENOMEM;
507 		return -1;
508 	}
509 	so->fp = ti->fp;
510 	so->con = ti->con;
511 
512 	/*
513 	**  We try to get the "raw" file descriptor that TLS uses to
514 	**  do the actual read/write with. This is to allow us control
515 	**  over the file descriptor being a blocking or non-blocking type.
516 	**  Under the covers TLS handles the change and this allows us
517 	**  to do timeouts with sm_io.
518 	*/
519 
520 	fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL);
521 	(void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
522 	fp->f_cookie = so;
523 	return 0;
524 }
525 
526 /*
527 **  TLS_CLOSE -- close the tls specific parts of the tls file pointer
528 **
529 **	Parameters:
530 **		fp -- the file pointer to close
531 **
532 **	Returns:
533 **		0 on success
534 */
535 
536 static int tls_close __P((SM_FILE_T *));
537 
538 static int
539 tls_close(fp)
540 	SM_FILE_T *fp;
541 {
542 	struct tls_obj *so;
543 
544 	so = (struct tls_obj *) fp->f_cookie;
545 	if (so == NULL)
546 		return 0;
547 	if (so->fp != NULL)
548 	{
549 		sm_io_close(so->fp, SM_TIME_DEFAULT);
550 		so->fp = NULL;
551 	}
552 	sm_free(so);
553 	so = NULL;
554 	return 0;
555 }
556 
557 /* maximum number of retries for TLS related I/O due to handshakes */
558 # define MAX_TLS_IOS	4
559 
560 /*
561 **  TLS_RETRY -- check whether a failed SSL operation can be retried
562 **
563 **	Parameters:
564 **		ssl -- TLS structure
565 **		rfd -- read fd
566 **		wfd -- write fd
567 **		tlsstart -- start time of TLS operation
568 **		timeout -- timeout for TLS operation
569 **		err -- SSL error
570 **		where -- description of operation
571 **
572 **	Results:
573 **		>0 on success
574 **		0 on timeout
575 **		<0 on error
576 */
577 
578 int
579 tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
580 	SSL *ssl;
581 	int rfd;
582 	int wfd;
583 	time_t tlsstart;
584 	int timeout;
585 	int err;
586 	const char *where;
587 {
588 	int ret;
589 	time_t left;
590 	time_t now = curtime();
591 	struct timeval tv;
592 
593 	ret = -1;
594 
595 	/*
596 	**  For SSL_ERROR_WANT_{READ,WRITE}:
597 	**  There is not a complete SSL record available yet
598 	**  or there is only a partial SSL record removed from
599 	**  the network (socket) buffer into the SSL buffer.
600 	**  The SSL_connect will only succeed when a full
601 	**  SSL record is available (assuming a "real" error
602 	**  doesn't happen). To handle when a "real" error
603 	**  does happen the select is set for exceptions too.
604 	**  The connection may be re-negotiated during this time
605 	**  so both read and write "want errors" need to be handled.
606 	**  A select() exception loops back so that a proper SSL
607 	**  error message can be gotten.
608 	*/
609 
610 	left = timeout - (now - tlsstart);
611 	if (left <= 0)
612 		return 0;	/* timeout */
613 	tv.tv_sec = left;
614 	tv.tv_usec = 0;
615 
616 	if (LogLevel > 14)
617 	{
618 		sm_syslog(LOG_INFO, NOQID,
619 			  "STARTTLS=%s, info: fds=%d/%d, err=%d",
620 			  where, rfd, wfd, err);
621 	}
622 
623 	if (FD_SETSIZE > 0 &&
624 	    ((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) ||
625 	     (err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
626 	{
627 		if (LogLevel > 5)
628 		{
629 			sm_syslog(LOG_ERR, NOQID,
630 				  "STARTTLS=%s, error: fd %d/%d too large",
631 				  where, rfd, wfd);
632 		if (LogLevel > 8)
633 			tlslogerr(where);
634 		}
635 		errno = EINVAL;
636 	}
637 	else if (err == SSL_ERROR_WANT_READ)
638 	{
639 		fd_set ssl_maskr, ssl_maskx;
640 
641 		FD_ZERO(&ssl_maskr);
642 		FD_SET(rfd, &ssl_maskr);
643 		FD_ZERO(&ssl_maskx);
644 		FD_SET(rfd, &ssl_maskx);
645 		do
646 		{
647 			ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
648 					&tv);
649 		} while (ret < 0 && errno == EINTR);
650 		if (ret < 0 && errno > 0)
651 			ret = -errno;
652 	}
653 	else if (err == SSL_ERROR_WANT_WRITE)
654 	{
655 		fd_set ssl_maskw, ssl_maskx;
656 
657 		FD_ZERO(&ssl_maskw);
658 		FD_SET(wfd, &ssl_maskw);
659 		FD_ZERO(&ssl_maskx);
660 		FD_SET(rfd, &ssl_maskx);
661 		do
662 		{
663 			ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
664 					&tv);
665 		} while (ret < 0 && errno == EINTR);
666 		if (ret < 0 && errno > 0)
667 			ret = -errno;
668 	}
669 	return ret;
670 }
671 
672 /* errno to force refill() etc to stop (see IS_IO_ERROR()) */
673 #ifdef ETIMEDOUT
674 # define SM_ERR_TIMEOUT	ETIMEDOUT
675 #else /* ETIMEDOUT */
676 # define SM_ERR_TIMEOUT	EIO
677 #endif /* ETIMEDOUT */
678 
679 /*
680 **  SET_TLS_RD_TMO -- read secured information for the caller
681 **
682 **	Parameters:
683 **		rd_tmo -- read timeout
684 **
685 **	Results:
686 **		none
687 **	This is a hack: there is no way to pass it in
688 */
689 
690 static int tls_rd_tmo = -1;
691 
692 void
693 set_tls_rd_tmo(rd_tmo)
694 	int rd_tmo;
695 {
696 	tls_rd_tmo = rd_tmo;
697 }
698 
699 /*
700 **  TLS_READ -- read secured information for the caller
701 **
702 **	Parameters:
703 **		fp -- the file pointer
704 **		buf -- the location to place the data
705 **		size -- the number of bytes to read from connection
706 **
707 **	Results:
708 **		-1 on error
709 **		otherwise the number of bytes read
710 */
711 
712 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
713 
714 static ssize_t
715 tls_read(fp, buf, size)
716 	SM_FILE_T *fp;
717 	char *buf;
718 	size_t size;
719 {
720 	int r, rfd, wfd, try, ssl_err;
721 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
722 	time_t tlsstart;
723 	char *err;
724 
725 	try = 99;
726 	err = NULL;
727 	tlsstart = curtime();
728 
729   retry:
730 	r = SSL_read(so->con, (char *) buf, size);
731 
732 	if (r > 0)
733 		return r;
734 
735 	err = NULL;
736 	switch (ssl_err = SSL_get_error(so->con, r))
737 	{
738 	  case SSL_ERROR_NONE:
739 	  case SSL_ERROR_ZERO_RETURN:
740 		break;
741 	  case SSL_ERROR_WANT_WRITE:
742 		err = "read W BLOCK";
743 		/* FALLTHROUGH */
744 	  case SSL_ERROR_WANT_READ:
745 		if (err == NULL)
746 			err = "read R BLOCK";
747 		rfd = SSL_get_rfd(so->con);
748 		wfd = SSL_get_wfd(so->con);
749 		try = tls_retry(so->con, rfd, wfd, tlsstart,
750 				(tls_rd_tmo < 0) ? TimeOuts.to_datablock
751 						 : tls_rd_tmo,
752 				ssl_err, "read");
753 		if (try > 0)
754 			goto retry;
755 		errno = SM_ERR_TIMEOUT;
756 		break;
757 
758 	  case SSL_ERROR_WANT_X509_LOOKUP:
759 		err = "write X BLOCK";
760 		break;
761 	  case SSL_ERROR_SYSCALL:
762 		if (r == 0 && errno == 0) /* out of protocol EOF found */
763 			break;
764 		err = "syscall error";
765 /*
766 		get_last_socket_error());
767 */
768 		break;
769 	  case SSL_ERROR_SSL:
770 #if DEAL_WITH_ERROR_SSL
771 		if (r == 0 && errno == 0) /* out of protocol EOF found */
772 			break;
773 #endif /* DEAL_WITH_ERROR_SSL */
774 		err = "generic SSL error";
775 		if (LogLevel > 9)
776 			tlslogerr("read");
777 
778 #if DEAL_WITH_ERROR_SSL
779 		/* avoid repeated calls? */
780 		if (r == 0)
781 			r = -1;
782 #endif /* DEAL_WITH_ERROR_SSL */
783 		break;
784 	}
785 	if (err != NULL)
786 	{
787 		int save_errno;
788 
789 		save_errno = (errno == 0) ? EIO : errno;
790 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
791 		{
792 			if (LogLevel > 7)
793 				sm_syslog(LOG_WARNING, NOQID,
794 					  "STARTTLS: read error=timeout");
795 		}
796 		else if (LogLevel > 8)
797 			sm_syslog(LOG_WARNING, NOQID,
798 				  "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
799 				  err, r, errno,
800 				  ERR_error_string(ERR_get_error(), NULL), try,
801 				  ssl_err);
802 		else if (LogLevel > 7)
803 			sm_syslog(LOG_WARNING, NOQID,
804 				  "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
805 				  err, r, errno, try, ssl_err);
806 		errno = save_errno;
807 	}
808 	return r;
809 }
810 
811 /*
812 **  TLS_WRITE -- write information out through secure connection
813 **
814 **	Parameters:
815 **		fp -- the file pointer
816 **		buf -- holds the data to be securely written
817 **		size -- the number of bytes to write
818 **
819 **	Returns:
820 **		-1 on error
821 **		otherwise number of bytes written
822 */
823 
824 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
825 
826 static ssize_t
827 tls_write(fp, buf, size)
828 	SM_FILE_T *fp;
829 	const char *buf;
830 	size_t size;
831 {
832 	int r, rfd, wfd, try, ssl_err;
833 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
834 	time_t tlsstart;
835 	char *err;
836 
837 	try = 99;
838 	err = NULL;
839 	tlsstart = curtime();
840 
841   retry:
842 	r = SSL_write(so->con, (char *) buf, size);
843 
844 	if (r > 0)
845 		return r;
846 	err = NULL;
847 	switch (ssl_err = SSL_get_error(so->con, r))
848 	{
849 	  case SSL_ERROR_NONE:
850 	  case SSL_ERROR_ZERO_RETURN:
851 		break;
852 	  case SSL_ERROR_WANT_WRITE:
853 		err = "read W BLOCK";
854 		/* FALLTHROUGH */
855 	  case SSL_ERROR_WANT_READ:
856 		if (err == NULL)
857 			err = "read R BLOCK";
858 		rfd = SSL_get_rfd(so->con);
859 		wfd = SSL_get_wfd(so->con);
860 		try = tls_retry(so->con, rfd, wfd, tlsstart,
861 				DATA_PROGRESS_TIMEOUT, ssl_err, "write");
862 		if (try > 0)
863 			goto retry;
864 		errno = SM_ERR_TIMEOUT;
865 		break;
866 	  case SSL_ERROR_WANT_X509_LOOKUP:
867 		err = "write X BLOCK";
868 		break;
869 	  case SSL_ERROR_SYSCALL:
870 		if (r == 0 && errno == 0) /* out of protocol EOF found */
871 			break;
872 		err = "syscall error";
873 /*
874 		get_last_socket_error());
875 */
876 		break;
877 	  case SSL_ERROR_SSL:
878 		err = "generic SSL error";
879 /*
880 		ERR_GET_REASON(ERR_peek_error()));
881 */
882 		if (LogLevel > 9)
883 			tlslogerr("write");
884 
885 #if DEAL_WITH_ERROR_SSL
886 		/* avoid repeated calls? */
887 		if (r == 0)
888 			r = -1;
889 #endif /* DEAL_WITH_ERROR_SSL */
890 		break;
891 	}
892 	if (err != NULL)
893 	{
894 		int save_errno;
895 
896 		save_errno = (errno == 0) ? EIO : errno;
897 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
898 		{
899 			if (LogLevel > 7)
900 				sm_syslog(LOG_WARNING, NOQID,
901 					  "STARTTLS: write error=timeout");
902 		}
903 		else if (LogLevel > 8)
904 			sm_syslog(LOG_WARNING, NOQID,
905 				  "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
906 				  err, r, errno,
907 				  ERR_error_string(ERR_get_error(), NULL), try,
908 				  ssl_err);
909 		else if (LogLevel > 7)
910 			sm_syslog(LOG_WARNING, NOQID,
911 				  "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
912 				  err, r, errno, try, ssl_err);
913 		errno = save_errno;
914 	}
915 	return r;
916 }
917 
918 /*
919 **  SFDCTLS -- create tls file type and open in and out file pointers
920 **	      for sendmail to read from and write to.
921 **
922 **	Parameters:
923 **		fin -- data input source being replaced
924 **		fout -- data output source being replaced
925 **		con -- the tls connection pointer
926 **
927 **	Returns:
928 **		-1 on error
929 **		0 on success
930 **
931 **	Side effects:
932 **		The arguments "fin" and "fout" are replaced with the new
933 **		SM_FILE_T pointers.
934 **		The original "fin" and "fout" are preserved in the tls file
935 **		type but are not actually used because of the design of TLS.
936 */
937 
938 int
939 sfdctls(fin, fout, con)
940 	SM_FILE_T **fin;
941 	SM_FILE_T **fout;
942 	SSL *con;
943 {
944 	SM_FILE_T *tlsin, *tlsout;
945 	SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
946 		tls_read, tls_write, NULL, tls_getinfo, NULL,
947 		SM_TIME_FOREVER);
948 	struct tls_info info;
949 
950 	SM_ASSERT(con != NULL);
951 
952 	SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
953 		tls_read, tls_write, NULL, tls_getinfo, NULL,
954 		SM_TIME_FOREVER);
955 	info.fp = *fin;
956 	info.con = con;
957 	tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
958 			   NULL);
959 	if (tlsin == NULL)
960 		return -1;
961 
962 	info.fp = *fout;
963 	tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
964 			    NULL);
965 	if (tlsout == NULL)
966 	{
967 		(void) sm_io_close(tlsin, SM_TIME_DEFAULT);
968 		return -1;
969 	}
970 	sm_io_automode(tlsin, tlsout);
971 
972 	*fin = tlsin;
973 	*fout = tlsout;
974 	return 0;
975 }
976 #endif /* STARTTLS */
977