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