sfsasl.c revision 261363
1/*
2 * Copyright (c) 1999-2006, 2008 Proofpoint, 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.121 2013/11/22 20:51:56 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 */
27struct sasl_obj
28{
29	SM_FILE_T *fp;
30	sasl_conn_t *conn;
31};
32
33struct 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
53static int sasl_getinfo __P((SM_FILE_T *, int, void *));
54
55static int
56sasl_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
97static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
98
99/* ARGSUSED2 */
100static int
101sasl_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
145static int sasl_close __P((SM_FILE_T *));
146
147static int
148sasl_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 */
167extern 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
183static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
184
185static ssize_t
186sasl_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
278static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
279
280static ssize_t
281sasl_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
365int
366sfdcsasl(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 */
421struct tls_obj
422{
423	SM_FILE_T *fp;
424	SSL *con;
425};
426
427struct 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
447static int tls_getinfo __P((SM_FILE_T *, int, void *));
448
449/* ARGSUSED2 */
450static int
451tls_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
488static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
489
490/* ARGSUSED2 */
491static int
492tls_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
534static int tls_close __P((SM_FILE_T *));
535
536static int
537tls_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
576int
577tls_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(LOG_WARNING, where);
632		}
633		errno = EINVAL;
634	}
635	else if (err == SSL_ERROR_WANT_READ)
636	{
637		fd_set ssl_maskr, ssl_maskx;
638		int save_errno = errno;
639
640		FD_ZERO(&ssl_maskr);
641		FD_SET(rfd, &ssl_maskr);
642		FD_ZERO(&ssl_maskx);
643		FD_SET(rfd, &ssl_maskx);
644		do
645		{
646			ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
647					&tv);
648		} while (ret < 0 && errno == EINTR);
649		if (ret < 0 && errno > 0)
650			ret = -errno;
651		errno = save_errno;
652	}
653	else if (err == SSL_ERROR_WANT_WRITE)
654	{
655		fd_set ssl_maskw, ssl_maskx;
656		int save_errno = errno;
657
658		FD_ZERO(&ssl_maskw);
659		FD_SET(wfd, &ssl_maskw);
660		FD_ZERO(&ssl_maskx);
661		FD_SET(rfd, &ssl_maskx);
662		do
663		{
664			ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
665					&tv);
666		} while (ret < 0 && errno == EINTR);
667		if (ret < 0 && errno > 0)
668			ret = -errno;
669		errno = save_errno;
670	}
671	return ret;
672}
673
674/* errno to force refill() etc to stop (see IS_IO_ERROR()) */
675#ifdef ETIMEDOUT
676# define SM_ERR_TIMEOUT	ETIMEDOUT
677#else /* ETIMEDOUT */
678# define SM_ERR_TIMEOUT	EIO
679#endif /* ETIMEDOUT */
680
681/*
682**  SET_TLS_RD_TMO -- read secured information for the caller
683**
684**	Parameters:
685**		rd_tmo -- read timeout
686**
687**	Results:
688**		none
689**	This is a hack: there is no way to pass it in
690*/
691
692static int tls_rd_tmo = -1;
693
694void
695set_tls_rd_tmo(rd_tmo)
696	int rd_tmo;
697{
698	tls_rd_tmo = rd_tmo;
699}
700
701/*
702**  TLS_READ -- read secured information for the caller
703**
704**	Parameters:
705**		fp -- the file pointer
706**		buf -- the location to place the data
707**		size -- the number of bytes to read from connection
708**
709**	Results:
710**		-1 on error
711**		otherwise the number of bytes read
712*/
713
714static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
715
716static ssize_t
717tls_read(fp, buf, size)
718	SM_FILE_T *fp;
719	char *buf;
720	size_t size;
721{
722	int r, rfd, wfd, try, ssl_err;
723	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
724	time_t tlsstart;
725	char *err;
726
727	try = 99;
728	err = NULL;
729	tlsstart = curtime();
730
731  retry:
732	r = SSL_read(so->con, (char *) buf, size);
733
734	if (r > 0)
735		return r;
736
737	err = NULL;
738	switch (ssl_err = SSL_get_error(so->con, r))
739	{
740	  case SSL_ERROR_NONE:
741	  case SSL_ERROR_ZERO_RETURN:
742		break;
743	  case SSL_ERROR_WANT_WRITE:
744		err = "read W BLOCK";
745		/* FALLTHROUGH */
746	  case SSL_ERROR_WANT_READ:
747		if (err == NULL)
748			err = "read R BLOCK";
749		rfd = SSL_get_rfd(so->con);
750		wfd = SSL_get_wfd(so->con);
751		try = tls_retry(so->con, rfd, wfd, tlsstart,
752				(tls_rd_tmo < 0) ? TimeOuts.to_datablock
753						 : tls_rd_tmo,
754				ssl_err, "read");
755		if (try > 0)
756			goto retry;
757		errno = SM_ERR_TIMEOUT;
758		break;
759
760	  case SSL_ERROR_WANT_X509_LOOKUP:
761		err = "write X BLOCK";
762		break;
763	  case SSL_ERROR_SYSCALL:
764		if (r == 0 && errno == 0) /* out of protocol EOF found */
765			break;
766		err = "syscall error";
767/*
768		get_last_socket_error());
769*/
770		break;
771	  case SSL_ERROR_SSL:
772#if DEAL_WITH_ERROR_SSL
773		if (r == 0 && errno == 0) /* out of protocol EOF found */
774			break;
775#endif /* DEAL_WITH_ERROR_SSL */
776		err = "generic SSL error";
777
778		if (LogLevel > 9)
779		{
780			int pri;
781
782			if (errno == EAGAIN && try > 0)
783				pri = LOG_DEBUG;
784			else
785				pri = LOG_WARNING;
786			tlslogerr(pri, "read");
787		}
788
789#if DEAL_WITH_ERROR_SSL
790		/* avoid repeated calls? */
791		if (r == 0)
792			r = -1;
793#endif /* DEAL_WITH_ERROR_SSL */
794		break;
795	}
796	if (err != NULL)
797	{
798		int save_errno;
799
800		save_errno = (errno == 0) ? EIO : errno;
801		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
802		{
803			if (LogLevel > 7)
804				sm_syslog(LOG_WARNING, NOQID,
805					  "STARTTLS: read error=timeout");
806		}
807		else if (LogLevel > 8)
808		{
809			int pri;
810
811			if (save_errno == EAGAIN && try > 0)
812				pri = LOG_DEBUG;
813			else
814				pri = LOG_WARNING;
815			sm_syslog(pri, NOQID,
816				  "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
817				  err, r, errno,
818				  ERR_error_string(ERR_get_error(), NULL), try,
819				  ssl_err);
820		}
821		else if (LogLevel > 7)
822			sm_syslog(LOG_WARNING, NOQID,
823				  "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
824				  err, r, errno, try, ssl_err);
825		errno = save_errno;
826	}
827	return r;
828}
829
830/*
831**  TLS_WRITE -- write information out through secure connection
832**
833**	Parameters:
834**		fp -- the file pointer
835**		buf -- holds the data to be securely written
836**		size -- the number of bytes to write
837**
838**	Returns:
839**		-1 on error
840**		otherwise number of bytes written
841*/
842
843static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
844
845static ssize_t
846tls_write(fp, buf, size)
847	SM_FILE_T *fp;
848	const char *buf;
849	size_t size;
850{
851	int r, rfd, wfd, try, ssl_err;
852	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
853	time_t tlsstart;
854	char *err;
855
856	try = 99;
857	err = NULL;
858	tlsstart = curtime();
859
860  retry:
861	r = SSL_write(so->con, (char *) buf, size);
862
863	if (r > 0)
864		return r;
865	err = NULL;
866	switch (ssl_err = SSL_get_error(so->con, r))
867	{
868	  case SSL_ERROR_NONE:
869	  case SSL_ERROR_ZERO_RETURN:
870		break;
871	  case SSL_ERROR_WANT_WRITE:
872		err = "read W BLOCK";
873		/* FALLTHROUGH */
874	  case SSL_ERROR_WANT_READ:
875		if (err == NULL)
876			err = "read R BLOCK";
877		rfd = SSL_get_rfd(so->con);
878		wfd = SSL_get_wfd(so->con);
879		try = tls_retry(so->con, rfd, wfd, tlsstart,
880				DATA_PROGRESS_TIMEOUT, ssl_err, "write");
881		if (try > 0)
882			goto retry;
883		errno = SM_ERR_TIMEOUT;
884		break;
885	  case SSL_ERROR_WANT_X509_LOOKUP:
886		err = "write X BLOCK";
887		break;
888	  case SSL_ERROR_SYSCALL:
889		if (r == 0 && errno == 0) /* out of protocol EOF found */
890			break;
891		err = "syscall error";
892/*
893		get_last_socket_error());
894*/
895		break;
896	  case SSL_ERROR_SSL:
897		err = "generic SSL error";
898/*
899		ERR_GET_REASON(ERR_peek_error()));
900*/
901		if (LogLevel > 9)
902			tlslogerr(LOG_WARNING, "write");
903
904#if DEAL_WITH_ERROR_SSL
905		/* avoid repeated calls? */
906		if (r == 0)
907			r = -1;
908#endif /* DEAL_WITH_ERROR_SSL */
909		break;
910	}
911	if (err != NULL)
912	{
913		int save_errno;
914
915		save_errno = (errno == 0) ? EIO : errno;
916		if (try == 0 && save_errno == SM_ERR_TIMEOUT)
917		{
918			if (LogLevel > 7)
919				sm_syslog(LOG_WARNING, NOQID,
920					  "STARTTLS: write error=timeout");
921		}
922		else if (LogLevel > 8)
923			sm_syslog(LOG_WARNING, NOQID,
924				  "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
925				  err, r, errno,
926				  ERR_error_string(ERR_get_error(), NULL), try,
927				  ssl_err);
928		else if (LogLevel > 7)
929			sm_syslog(LOG_WARNING, NOQID,
930				  "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
931				  err, r, errno, try, ssl_err);
932		errno = save_errno;
933	}
934	return r;
935}
936
937/*
938**  SFDCTLS -- create tls file type and open in and out file pointers
939**	      for sendmail to read from and write to.
940**
941**	Parameters:
942**		fin -- data input source being replaced
943**		fout -- data output source being replaced
944**		con -- the tls connection pointer
945**
946**	Returns:
947**		-1 on error
948**		0 on success
949**
950**	Side effects:
951**		The arguments "fin" and "fout" are replaced with the new
952**		SM_FILE_T pointers.
953**		The original "fin" and "fout" are preserved in the tls file
954**		type but are not actually used because of the design of TLS.
955*/
956
957int
958sfdctls(fin, fout, con)
959	SM_FILE_T **fin;
960	SM_FILE_T **fout;
961	SSL *con;
962{
963	SM_FILE_T *tlsin, *tlsout;
964	SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
965		tls_read, tls_write, NULL, tls_getinfo, NULL,
966		SM_TIME_FOREVER);
967	struct tls_info info;
968
969	SM_ASSERT(con != NULL);
970
971	SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
972		tls_read, tls_write, NULL, tls_getinfo, NULL,
973		SM_TIME_FOREVER);
974	info.fp = *fin;
975	info.con = con;
976	tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
977			   NULL);
978	if (tlsin == NULL)
979		return -1;
980
981	info.fp = *fout;
982	tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
983			    NULL);
984	if (tlsout == NULL)
985	{
986		(void) sm_io_close(tlsin, SM_TIME_DEFAULT);
987		return -1;
988	}
989	sm_io_automode(tlsin, tlsout);
990
991	*fin = tlsin;
992	*fout = tlsout;
993	return 0;
994}
995#endif /* STARTTLS */
996