xref: /illumos-gate/usr/src/cmd/sendmail/src/sfsasl.c (revision e9af4bc0)
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 #include <sm/gen.h>
12 SM_RCSID("@(#)$Id: sfsasl.c,v 8.118 2008/07/22 15:12:48 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
sasl_getinfo(fp,what,valp)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
sasl_open(fp,info,flags,rpool)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
sasl_close(fp)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
sasl_read(fp,buf,size)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
sasl_write(fp,buf,size)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 negotiation 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
sfdcsasl(fin,fout,conn,tmo)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
tls_getinfo(fp,what,valp)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
tls_open(fp,info,flags,rpool)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
tls_close(fp)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
tls_retry(ssl,rfd,wfd,tlsstart,timeout,err,where)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 **  SET_TLS_RD_TMO -- read secured information for the caller
679 **
680 **	Parameters:
681 **		rd_tmo -- read timeout
682 **
683 **	Results:
684 **		none
685 **	This is a hack: there is no way to pass it in
686 */
687 
688 static int tls_rd_tmo = -1;
689 
690 void
set_tls_rd_tmo(rd_tmo)691 set_tls_rd_tmo(rd_tmo)
692 	int rd_tmo;
693 {
694 	tls_rd_tmo = rd_tmo;
695 }
696 
697 /*
698 **  TLS_READ -- read secured information for the caller
699 **
700 **	Parameters:
701 **		fp -- the file pointer
702 **		buf -- the location to place the data
703 **		size -- the number of bytes to read from connection
704 **
705 **	Results:
706 **		-1 on error
707 **		otherwise the number of bytes read
708 */
709 
710 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
711 
712 static ssize_t
tls_read(fp,buf,size)713 tls_read(fp, buf, size)
714 	SM_FILE_T *fp;
715 	char *buf;
716 	size_t size;
717 {
718 	int r, rfd, wfd, try, ssl_err;
719 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
720 	time_t tlsstart;
721 	char *err;
722 
723 	try = 99;
724 	err = NULL;
725 	tlsstart = curtime();
726 
727   retry:
728 	r = SSL_read(so->con, (char *) buf, size);
729 
730 	if (r > 0)
731 		return r;
732 
733 	err = NULL;
734 	switch (ssl_err = SSL_get_error(so->con, r))
735 	{
736 	  case SSL_ERROR_NONE:
737 	  case SSL_ERROR_ZERO_RETURN:
738 		break;
739 	  case SSL_ERROR_WANT_WRITE:
740 		err = "read W BLOCK";
741 		/* FALLTHROUGH */
742 	  case SSL_ERROR_WANT_READ:
743 		if (err == NULL)
744 			err = "read R BLOCK";
745 		rfd = SSL_get_rfd(so->con);
746 		wfd = SSL_get_wfd(so->con);
747 		try = tls_retry(so->con, rfd, wfd, tlsstart,
748 				(tls_rd_tmo < 0) ? TimeOuts.to_datablock
749 						 : tls_rd_tmo,
750 				ssl_err, "read");
751 		if (try > 0)
752 			goto retry;
753 		errno = SM_ERR_TIMEOUT;
754 		break;
755 
756 	  case SSL_ERROR_WANT_X509_LOOKUP:
757 		err = "write X BLOCK";
758 		break;
759 	  case SSL_ERROR_SYSCALL:
760 		if (r == 0 && errno == 0) /* out of protocol EOF found */
761 			break;
762 		err = "syscall error";
763 /*
764 		get_last_socket_error());
765 */
766 		break;
767 	  case SSL_ERROR_SSL:
768 #if DEAL_WITH_ERROR_SSL
769 		if (r == 0 && errno == 0) /* out of protocol EOF found */
770 			break;
771 #endif /* DEAL_WITH_ERROR_SSL */
772 		err = "generic SSL error";
773 		if (LogLevel > 9)
774 			tlslogerr("read");
775 
776 #if DEAL_WITH_ERROR_SSL
777 		/* avoid repeated calls? */
778 		if (r == 0)
779 			r = -1;
780 #endif /* DEAL_WITH_ERROR_SSL */
781 		break;
782 	}
783 	if (err != NULL)
784 	{
785 		int save_errno;
786 
787 		save_errno = (errno == 0) ? EIO : errno;
788 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
789 		{
790 			if (LogLevel > 7)
791 				sm_syslog(LOG_WARNING, NOQID,
792 					  "STARTTLS: read error=timeout");
793 		}
794 		else if (LogLevel > 8)
795 			sm_syslog(LOG_WARNING, NOQID,
796 				  "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
797 				  err, r, errno,
798 				  ERR_error_string(ERR_get_error(), NULL), try,
799 				  ssl_err);
800 		else if (LogLevel > 7)
801 			sm_syslog(LOG_WARNING, NOQID,
802 				  "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
803 				  err, r, errno, try, ssl_err);
804 		errno = save_errno;
805 	}
806 	return r;
807 }
808 
809 /*
810 **  TLS_WRITE -- write information out through secure connection
811 **
812 **	Parameters:
813 **		fp -- the file pointer
814 **		buf -- holds the data to be securely written
815 **		size -- the number of bytes to write
816 **
817 **	Returns:
818 **		-1 on error
819 **		otherwise number of bytes written
820 */
821 
822 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
823 
824 static ssize_t
tls_write(fp,buf,size)825 tls_write(fp, buf, size)
826 	SM_FILE_T *fp;
827 	const char *buf;
828 	size_t size;
829 {
830 	int r, rfd, wfd, try, ssl_err;
831 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
832 	time_t tlsstart;
833 	char *err;
834 
835 	try = 99;
836 	err = NULL;
837 	tlsstart = curtime();
838 
839   retry:
840 	r = SSL_write(so->con, (char *) buf, size);
841 
842 	if (r > 0)
843 		return r;
844 	err = NULL;
845 	switch (ssl_err = SSL_get_error(so->con, r))
846 	{
847 	  case SSL_ERROR_NONE:
848 	  case SSL_ERROR_ZERO_RETURN:
849 		break;
850 	  case SSL_ERROR_WANT_WRITE:
851 		err = "read W BLOCK";
852 		/* FALLTHROUGH */
853 	  case SSL_ERROR_WANT_READ:
854 		if (err == NULL)
855 			err = "read R BLOCK";
856 		rfd = SSL_get_rfd(so->con);
857 		wfd = SSL_get_wfd(so->con);
858 		try = tls_retry(so->con, rfd, wfd, tlsstart,
859 				DATA_PROGRESS_TIMEOUT, ssl_err, "write");
860 		if (try > 0)
861 			goto retry;
862 		errno = SM_ERR_TIMEOUT;
863 		break;
864 	  case SSL_ERROR_WANT_X509_LOOKUP:
865 		err = "write X BLOCK";
866 		break;
867 	  case SSL_ERROR_SYSCALL:
868 		if (r == 0 && errno == 0) /* out of protocol EOF found */
869 			break;
870 		err = "syscall error";
871 /*
872 		get_last_socket_error());
873 */
874 		break;
875 	  case SSL_ERROR_SSL:
876 		err = "generic SSL error";
877 /*
878 		ERR_GET_REASON(ERR_peek_error()));
879 */
880 		if (LogLevel > 9)
881 			tlslogerr("write");
882 
883 #if DEAL_WITH_ERROR_SSL
884 		/* avoid repeated calls? */
885 		if (r == 0)
886 			r = -1;
887 #endif /* DEAL_WITH_ERROR_SSL */
888 		break;
889 	}
890 	if (err != NULL)
891 	{
892 		int save_errno;
893 
894 		save_errno = (errno == 0) ? EIO : errno;
895 		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
896 		{
897 			if (LogLevel > 7)
898 				sm_syslog(LOG_WARNING, NOQID,
899 					  "STARTTLS: write error=timeout");
900 		}
901 		else if (LogLevel > 8)
902 			sm_syslog(LOG_WARNING, NOQID,
903 				  "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
904 				  err, r, errno,
905 				  ERR_error_string(ERR_get_error(), NULL), try,
906 				  ssl_err);
907 		else if (LogLevel > 7)
908 			sm_syslog(LOG_WARNING, NOQID,
909 				  "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
910 				  err, r, errno, try, ssl_err);
911 		errno = save_errno;
912 	}
913 	return r;
914 }
915 
916 /*
917 **  SFDCTLS -- create tls file type and open in and out file pointers
918 **	      for sendmail to read from and write to.
919 **
920 **	Parameters:
921 **		fin -- data input source being replaced
922 **		fout -- data output source being replaced
923 **		con -- the tls connection pointer
924 **
925 **	Returns:
926 **		-1 on error
927 **		0 on success
928 **
929 **	Side effects:
930 **		The arguments "fin" and "fout" are replaced with the new
931 **		SM_FILE_T pointers.
932 **		The original "fin" and "fout" are preserved in the tls file
933 **		type but are not actually used because of the design of TLS.
934 */
935 
936 int
sfdctls(fin,fout,con)937 sfdctls(fin, fout, con)
938 	SM_FILE_T **fin;
939 	SM_FILE_T **fout;
940 	SSL *con;
941 {
942 	SM_FILE_T *tlsin, *tlsout;
943 	SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
944 		tls_read, tls_write, NULL, tls_getinfo, NULL,
945 		SM_TIME_FOREVER);
946 	struct tls_info info;
947 
948 	SM_ASSERT(con != NULL);
949 
950 	SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
951 		tls_read, tls_write, NULL, tls_getinfo, NULL,
952 		SM_TIME_FOREVER);
953 	info.fp = *fin;
954 	info.con = con;
955 	tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
956 			   NULL);
957 	if (tlsin == NULL)
958 		return -1;
959 
960 	info.fp = *fout;
961 	tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
962 			    NULL);
963 	if (tlsout == NULL)
964 	{
965 		(void) sm_io_close(tlsin, SM_TIME_DEFAULT);
966 		return -1;
967 	}
968 	sm_io_automode(tlsin, tlsout);
969 
970 	*fin = tlsin;
971 	*fout = tlsout;
972 	return 0;
973 }
974 #endif /* STARTTLS */
975