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