xref: /freebsd/contrib/sendmail/src/sfsasl.c (revision b6bacd3150f411c3de886f7615bc22129b6974ad)
106f25ae9SGregory Neil Shapiro /*
2e92d3f3fSGregory Neil Shapiro  * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
406f25ae9SGregory Neil Shapiro  *
506f25ae9SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
606f25ae9SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
706f25ae9SGregory Neil Shapiro  * the sendmail distribution.
806f25ae9SGregory Neil Shapiro  *
906f25ae9SGregory Neil Shapiro  */
1006f25ae9SGregory Neil Shapiro 
1140266059SGregory Neil Shapiro #include <sm/gen.h>
12b6bacd31SGregory Neil Shapiro SM_RCSID("@(#)$Id: sfsasl.c,v 8.101 2004/12/15 22:45:55 ca Exp $")
1306f25ae9SGregory Neil Shapiro #include <stdlib.h>
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
1540266059SGregory Neil Shapiro #include <errno.h>
16b6bacd31SGregory Neil Shapiro 
17b6bacd31SGregory Neil Shapiro /* allow to disable error handling code just in case... */
18b6bacd31SGregory Neil Shapiro #ifndef DEAL_WITH_ERROR_SSL
19b6bacd31SGregory Neil Shapiro # define DEAL_WITH_ERROR_SSL	1
20b6bacd31SGregory Neil Shapiro #endif /* ! DEAL_WITH_ERROR_SSL */
21b6bacd31SGregory Neil Shapiro 
2240266059SGregory Neil Shapiro #if SASL
2306f25ae9SGregory Neil Shapiro # include "sfsasl.h"
2406f25ae9SGregory Neil Shapiro 
2540266059SGregory Neil Shapiro /* Structure used by the "sasl" file type */
2640266059SGregory Neil Shapiro struct sasl_obj
2740266059SGregory Neil Shapiro {
2840266059SGregory Neil Shapiro 	SM_FILE_T *fp;
2940266059SGregory Neil Shapiro 	sasl_conn_t *conn;
3040266059SGregory Neil Shapiro };
3140266059SGregory Neil Shapiro 
3240266059SGregory Neil Shapiro struct sasl_info
3340266059SGregory Neil Shapiro {
3440266059SGregory Neil Shapiro 	SM_FILE_T *fp;
3540266059SGregory Neil Shapiro 	sasl_conn_t *conn;
3640266059SGregory Neil Shapiro };
3740266059SGregory Neil Shapiro 
3840266059SGregory Neil Shapiro /*
3940266059SGregory Neil Shapiro **  SASL_GETINFO - returns requested information about a "sasl" file
4040266059SGregory Neil Shapiro **		  descriptor.
4140266059SGregory Neil Shapiro **
4240266059SGregory Neil Shapiro **	Parameters:
4340266059SGregory Neil Shapiro **		fp -- the file descriptor
4440266059SGregory Neil Shapiro **		what -- the type of information requested
4540266059SGregory Neil Shapiro **		valp -- the thang to return the information in
4640266059SGregory Neil Shapiro **
4740266059SGregory Neil Shapiro **	Returns:
4840266059SGregory Neil Shapiro **		-1 for unknown requests
4940266059SGregory Neil Shapiro **		>=0 on success with valp filled in (if possible).
5040266059SGregory Neil Shapiro */
5140266059SGregory Neil Shapiro 
5240266059SGregory Neil Shapiro static int sasl_getinfo __P((SM_FILE_T *, int, void *));
5340266059SGregory Neil Shapiro 
5440266059SGregory Neil Shapiro static int
5540266059SGregory Neil Shapiro sasl_getinfo(fp, what, valp)
5640266059SGregory Neil Shapiro 	SM_FILE_T *fp;
5740266059SGregory Neil Shapiro 	int what;
5840266059SGregory Neil Shapiro 	void *valp;
5940266059SGregory Neil Shapiro {
6040266059SGregory Neil Shapiro 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
6140266059SGregory Neil Shapiro 
6240266059SGregory Neil Shapiro 	switch (what)
6340266059SGregory Neil Shapiro 	{
6440266059SGregory Neil Shapiro 	  case SM_IO_WHAT_FD:
6540266059SGregory Neil Shapiro 		if (so->fp == NULL)
6640266059SGregory Neil Shapiro 			return -1;
6740266059SGregory Neil Shapiro 		return so->fp->f_file; /* for stdio fileno() compatability */
6840266059SGregory Neil Shapiro 
6940266059SGregory Neil Shapiro 	  case SM_IO_IS_READABLE:
7040266059SGregory Neil Shapiro 		if (so->fp == NULL)
7140266059SGregory Neil Shapiro 			return 0;
7240266059SGregory Neil Shapiro 
7340266059SGregory Neil Shapiro 		/* get info from underlying file */
7440266059SGregory Neil Shapiro 		return sm_io_getinfo(so->fp, what, valp);
7540266059SGregory Neil Shapiro 
7640266059SGregory Neil Shapiro 	  default:
7740266059SGregory Neil Shapiro 		return -1;
7840266059SGregory Neil Shapiro 	}
7940266059SGregory Neil Shapiro }
8040266059SGregory Neil Shapiro 
8140266059SGregory Neil Shapiro /*
8240266059SGregory Neil Shapiro **  SASL_OPEN -- creates the sasl specific information for opening a
8340266059SGregory Neil Shapiro **		file of the sasl type.
8440266059SGregory Neil Shapiro **
8540266059SGregory Neil Shapiro **	Parameters:
8640266059SGregory Neil Shapiro **		fp -- the file pointer associated with the new open
8740266059SGregory Neil Shapiro **		info -- contains the sasl connection information pointer and
8840266059SGregory Neil Shapiro **			the original SM_FILE_T that holds the open
8940266059SGregory Neil Shapiro **		flags -- ignored
9040266059SGregory Neil Shapiro **		rpool -- ignored
9140266059SGregory Neil Shapiro **
9240266059SGregory Neil Shapiro **	Returns:
9340266059SGregory Neil Shapiro **		0 on success
9440266059SGregory Neil Shapiro */
9540266059SGregory Neil Shapiro 
9640266059SGregory Neil Shapiro static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
9740266059SGregory Neil Shapiro 
9840266059SGregory Neil Shapiro /* ARGSUSED2 */
9940266059SGregory Neil Shapiro static int
10040266059SGregory Neil Shapiro sasl_open(fp, info, flags, rpool)
10140266059SGregory Neil Shapiro 	SM_FILE_T *fp;
10240266059SGregory Neil Shapiro 	const void *info;
10340266059SGregory Neil Shapiro 	int flags;
10440266059SGregory Neil Shapiro 	const void *rpool;
10540266059SGregory Neil Shapiro {
10640266059SGregory Neil Shapiro 	struct sasl_obj *so;
10740266059SGregory Neil Shapiro 	struct sasl_info *si = (struct sasl_info *) info;
10840266059SGregory Neil Shapiro 
10940266059SGregory Neil Shapiro 	so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
110a7ec597cSGregory Neil Shapiro 	if (so == NULL)
111a7ec597cSGregory Neil Shapiro 	{
112a7ec597cSGregory Neil Shapiro 		errno = ENOMEM;
113a7ec597cSGregory Neil Shapiro 		return -1;
114a7ec597cSGregory Neil Shapiro 	}
11540266059SGregory Neil Shapiro 	so->fp = si->fp;
11640266059SGregory Neil Shapiro 	so->conn = si->conn;
11740266059SGregory Neil Shapiro 
11840266059SGregory Neil Shapiro 	/*
11940266059SGregory Neil Shapiro 	**  The underlying 'fp' is set to SM_IO_NOW so that the entire
12040266059SGregory Neil Shapiro 	**  encoded string is written in one chunk. Otherwise there is
12140266059SGregory Neil Shapiro 	**  the possibility that it may appear illegal, bogus or
12240266059SGregory Neil Shapiro 	**  mangled to the other side of the connection.
12340266059SGregory Neil Shapiro 	**  We will read or write through 'fp' since it is the opaque
12440266059SGregory Neil Shapiro 	**  connection for the communications. We need to treat it this
12540266059SGregory Neil Shapiro 	**  way in case the encoded string is to be sent down a TLS
12640266059SGregory Neil Shapiro 	**  connection rather than, say, sm_io's stdio.
12740266059SGregory Neil Shapiro 	*/
12840266059SGregory Neil Shapiro 
12940266059SGregory Neil Shapiro 	(void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
13040266059SGregory Neil Shapiro 	fp->f_cookie = so;
13140266059SGregory Neil Shapiro 	return 0;
13240266059SGregory Neil Shapiro }
13340266059SGregory Neil Shapiro 
13440266059SGregory Neil Shapiro /*
13540266059SGregory Neil Shapiro **  SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
13640266059SGregory Neil Shapiro **
13740266059SGregory Neil Shapiro **	Parameters:
13840266059SGregory Neil Shapiro **		fp -- the file pointer to close
13940266059SGregory Neil Shapiro **
14040266059SGregory Neil Shapiro **	Returns:
14140266059SGregory Neil Shapiro **		0 on success
14240266059SGregory Neil Shapiro */
14340266059SGregory Neil Shapiro 
14440266059SGregory Neil Shapiro static int sasl_close __P((SM_FILE_T *));
14540266059SGregory Neil Shapiro 
14640266059SGregory Neil Shapiro static int
14740266059SGregory Neil Shapiro sasl_close(fp)
14840266059SGregory Neil Shapiro 	SM_FILE_T *fp;
14940266059SGregory Neil Shapiro {
15040266059SGregory Neil Shapiro 	struct sasl_obj *so;
15140266059SGregory Neil Shapiro 
15240266059SGregory Neil Shapiro 	so = (struct sasl_obj *) fp->f_cookie;
153a7ec597cSGregory Neil Shapiro 	if (so == NULL)
154a7ec597cSGregory Neil Shapiro 		return 0;
15540266059SGregory Neil Shapiro 	if (so->fp != NULL)
15640266059SGregory Neil Shapiro 	{
15740266059SGregory Neil Shapiro 		sm_io_close(so->fp, SM_TIME_DEFAULT);
15840266059SGregory Neil Shapiro 		so->fp = NULL;
15940266059SGregory Neil Shapiro 	}
16040266059SGregory Neil Shapiro 	sm_free(so);
16140266059SGregory Neil Shapiro 	so = NULL;
16240266059SGregory Neil Shapiro 	return 0;
16340266059SGregory Neil Shapiro }
16440266059SGregory Neil Shapiro 
165193538b7SGregory Neil Shapiro /* how to deallocate a buffer allocated by SASL */
16640266059SGregory Neil Shapiro extern void	sm_sasl_free __P((void *));
16740266059SGregory Neil Shapiro #  define SASL_DEALLOC(b)	sm_sasl_free(b)
16840266059SGregory Neil Shapiro 
16940266059SGregory Neil Shapiro /*
17040266059SGregory Neil Shapiro **  SASL_READ -- read encrypted information and decrypt it for the caller
17140266059SGregory Neil Shapiro **
17240266059SGregory Neil Shapiro **	Parameters:
17340266059SGregory Neil Shapiro **		fp -- the file pointer
17440266059SGregory Neil Shapiro **		buf -- the location to place the decrypted information
17540266059SGregory Neil Shapiro **		size -- the number of bytes to read after decryption
17640266059SGregory Neil Shapiro **
17740266059SGregory Neil Shapiro **	Results:
17840266059SGregory Neil Shapiro **		-1 on error
17940266059SGregory Neil Shapiro **		otherwise the number of bytes read
18040266059SGregory Neil Shapiro */
18140266059SGregory Neil Shapiro 
18240266059SGregory Neil Shapiro static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
183193538b7SGregory Neil Shapiro 
18406f25ae9SGregory Neil Shapiro static ssize_t
18540266059SGregory Neil Shapiro sasl_read(fp, buf, size)
18640266059SGregory Neil Shapiro 	SM_FILE_T *fp;
18740266059SGregory Neil Shapiro 	char *buf;
18806f25ae9SGregory Neil Shapiro 	size_t size;
18906f25ae9SGregory Neil Shapiro {
19040266059SGregory Neil Shapiro 	int result;
19140266059SGregory Neil Shapiro 	ssize_t len;
19294c01205SGregory Neil Shapiro # if SASL >= 20000
19313bd1963SGregory Neil Shapiro 	static const char *outbuf = NULL;
19494c01205SGregory Neil Shapiro # else /* SASL >= 20000 */
195193538b7SGregory Neil Shapiro 	static char *outbuf = NULL;
19694c01205SGregory Neil Shapiro # endif /* SASL >= 20000 */
197193538b7SGregory Neil Shapiro 	static unsigned int outlen = 0;
198193538b7SGregory Neil Shapiro 	static unsigned int offset = 0;
19940266059SGregory Neil Shapiro 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
20006f25ae9SGregory Neil Shapiro 
201193538b7SGregory Neil Shapiro 	/*
202193538b7SGregory Neil Shapiro 	**  sasl_decode() may require more data than a single read() returns.
203193538b7SGregory Neil Shapiro 	**  Hence we have to put a loop around the decoding.
204193538b7SGregory Neil Shapiro 	**  This also requires that we may have to split up the returned
205193538b7SGregory Neil Shapiro 	**  data since it might be larger than the allowed size.
206193538b7SGregory Neil Shapiro 	**  Therefore we use a static pointer and return portions of it
207193538b7SGregory Neil Shapiro 	**  if necessary.
208a7ec597cSGregory Neil Shapiro 	**  XXX Note: This function is not thread-safe nor can it be used
209a7ec597cSGregory Neil Shapiro 	**  on more than one file. A correct implementation would store
210a7ec597cSGregory Neil Shapiro 	**  this data in fp->f_cookie.
211193538b7SGregory Neil Shapiro 	*/
21206f25ae9SGregory Neil Shapiro 
21313bd1963SGregory Neil Shapiro # if SASL >= 20000
21413bd1963SGregory Neil Shapiro 	while (outlen == 0)
21513bd1963SGregory Neil Shapiro # else /* SASL >= 20000 */
216193538b7SGregory Neil Shapiro 	while (outbuf == NULL && outlen == 0)
21713bd1963SGregory Neil Shapiro # endif /* SASL >= 20000 */
218193538b7SGregory Neil Shapiro 	{
21940266059SGregory Neil Shapiro 		len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
22006f25ae9SGregory Neil Shapiro 		if (len <= 0)
22106f25ae9SGregory Neil Shapiro 			return len;
22240266059SGregory Neil Shapiro 		result = sasl_decode(so->conn, buf,
22340266059SGregory Neil Shapiro 				     (unsigned int) len, &outbuf, &outlen);
22406f25ae9SGregory Neil Shapiro 		if (result != SASL_OK)
22506f25ae9SGregory Neil Shapiro 		{
226193538b7SGregory Neil Shapiro 			outbuf = NULL;
227193538b7SGregory Neil Shapiro 			offset = 0;
228193538b7SGregory Neil Shapiro 			outlen = 0;
22906f25ae9SGregory Neil Shapiro 			return -1;
23006f25ae9SGregory Neil Shapiro 		}
231193538b7SGregory Neil Shapiro 	}
23206f25ae9SGregory Neil Shapiro 
23340266059SGregory Neil Shapiro 	if (outbuf == NULL)
23406f25ae9SGregory Neil Shapiro 	{
23540266059SGregory Neil Shapiro 		/* be paranoid: outbuf == NULL but outlen != 0 */
23640266059SGregory Neil Shapiro 		syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
23740266059SGregory Neil Shapiro 		/* NOTREACHED */
23840266059SGregory Neil Shapiro 	}
239193538b7SGregory Neil Shapiro 	if (outlen - offset > size)
240193538b7SGregory Neil Shapiro 	{
241193538b7SGregory Neil Shapiro 		/* return another part of the buffer */
24240266059SGregory Neil Shapiro 		(void) memcpy(buf, outbuf + offset, size);
243193538b7SGregory Neil Shapiro 		offset += size;
24440266059SGregory Neil Shapiro 		len = size;
24506f25ae9SGregory Neil Shapiro 	}
246193538b7SGregory Neil Shapiro 	else
247193538b7SGregory Neil Shapiro 	{
248193538b7SGregory Neil Shapiro 		/* return the rest of the buffer */
24940266059SGregory Neil Shapiro 		len = outlen - offset;
25040266059SGregory Neil Shapiro 		(void) memcpy(buf, outbuf + offset, (size_t) len);
25194c01205SGregory Neil Shapiro # if SASL < 20000
252193538b7SGregory Neil Shapiro 		SASL_DEALLOC(outbuf);
25394c01205SGregory Neil Shapiro # endif /* SASL < 20000 */
254193538b7SGregory Neil Shapiro 		outbuf = NULL;
255193538b7SGregory Neil Shapiro 		offset = 0;
256193538b7SGregory Neil Shapiro 		outlen = 0;
257193538b7SGregory Neil Shapiro 	}
25840266059SGregory Neil Shapiro 	return len;
25906f25ae9SGregory Neil Shapiro }
26006f25ae9SGregory Neil Shapiro 
26140266059SGregory Neil Shapiro /*
26240266059SGregory Neil Shapiro **  SASL_WRITE -- write information out after encrypting it
26340266059SGregory Neil Shapiro **
26440266059SGregory Neil Shapiro **	Parameters:
26540266059SGregory Neil Shapiro **		fp -- the file pointer
26640266059SGregory Neil Shapiro **		buf -- holds the data to be encrypted and written
26740266059SGregory Neil Shapiro **		size -- the number of bytes to have encrypted and written
26840266059SGregory Neil Shapiro **
26940266059SGregory Neil Shapiro **	Returns:
27040266059SGregory Neil Shapiro **		-1 on error
27140266059SGregory Neil Shapiro **		otherwise number of bytes written
27240266059SGregory Neil Shapiro */
27340266059SGregory Neil Shapiro 
27440266059SGregory Neil Shapiro static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
27540266059SGregory Neil Shapiro 
27606f25ae9SGregory Neil Shapiro static ssize_t
27740266059SGregory Neil Shapiro sasl_write(fp, buf, size)
27840266059SGregory Neil Shapiro 	SM_FILE_T *fp;
27940266059SGregory Neil Shapiro 	const char *buf;
28006f25ae9SGregory Neil Shapiro 	size_t size;
28106f25ae9SGregory Neil Shapiro {
28206f25ae9SGregory Neil Shapiro 	int result;
28394c01205SGregory Neil Shapiro # if SASL >= 20000
28494c01205SGregory Neil Shapiro 	const char *outbuf;
28594c01205SGregory Neil Shapiro # else /* SASL >= 20000 */
28606f25ae9SGregory Neil Shapiro 	char *outbuf;
28794c01205SGregory Neil Shapiro # endif /* SASL >= 20000 */
288b6bacd31SGregory Neil Shapiro 	unsigned int outlen, *maxencode;
28940266059SGregory Neil Shapiro 	size_t ret = 0, total = 0;
29040266059SGregory Neil Shapiro 	struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
29106f25ae9SGregory Neil Shapiro 
292b6bacd31SGregory Neil Shapiro 	/*
293b6bacd31SGregory Neil Shapiro 	**  Fetch the maximum input buffer size for sasl_encode().
294b6bacd31SGregory Neil Shapiro 	**  This can be less than the size set in attemptauth()
295b6bacd31SGregory Neil Shapiro 	**  due to a negotation with the other side, e.g.,
296b6bacd31SGregory Neil Shapiro 	**  Cyrus IMAP lmtp program sets maxbuf=4096,
297b6bacd31SGregory Neil Shapiro 	**  digestmd5 substracts 25 and hence we'll get 4071
298b6bacd31SGregory Neil Shapiro 	**  instead of 8192 (MAXOUTLEN).
299b6bacd31SGregory Neil Shapiro 	**  Hack (for now): simply reduce the size, callers are (must be)
300b6bacd31SGregory Neil Shapiro 	**  able to deal with that and invoke sasl_write() again with
301b6bacd31SGregory Neil Shapiro 	**  the rest of the data.
302b6bacd31SGregory Neil Shapiro 	**  Note: it would be better to store this value in the context
303b6bacd31SGregory Neil Shapiro 	**  after the negotiation.
304b6bacd31SGregory Neil Shapiro 	*/
305b6bacd31SGregory Neil Shapiro 
306b6bacd31SGregory Neil Shapiro 	result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
307b6bacd31SGregory Neil Shapiro                              (const void **) &maxencode);
308b6bacd31SGregory Neil Shapiro 	if (result == SASL_OK && size > *maxencode && *maxencode > 0)
309b6bacd31SGregory Neil Shapiro 		size = *maxencode;
310b6bacd31SGregory Neil Shapiro 
31140266059SGregory Neil Shapiro 	result = sasl_encode(so->conn, buf,
31240266059SGregory Neil Shapiro 			     (unsigned int) size, &outbuf, &outlen);
31306f25ae9SGregory Neil Shapiro 
31406f25ae9SGregory Neil Shapiro 	if (result != SASL_OK)
31506f25ae9SGregory Neil Shapiro 		return -1;
31606f25ae9SGregory Neil Shapiro 
31706f25ae9SGregory Neil Shapiro 	if (outbuf != NULL)
31806f25ae9SGregory Neil Shapiro 	{
31940266059SGregory Neil Shapiro 		while (outlen > 0)
32040266059SGregory Neil Shapiro 		{
321605302a5SGregory Neil Shapiro 			/* XXX result == 0? */
32240266059SGregory Neil Shapiro 			ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
32340266059SGregory Neil Shapiro 					  &outbuf[total], outlen);
324a7ec597cSGregory Neil Shapiro 			if (ret <= 0)
325a7ec597cSGregory Neil Shapiro 				return ret;
32640266059SGregory Neil Shapiro 			outlen -= ret;
32740266059SGregory Neil Shapiro 			total += ret;
32840266059SGregory Neil Shapiro 		}
32994c01205SGregory Neil Shapiro # if SASL < 20000
330193538b7SGregory Neil Shapiro 		SASL_DEALLOC(outbuf);
33194c01205SGregory Neil Shapiro # endif /* SASL < 20000 */
33206f25ae9SGregory Neil Shapiro 	}
33306f25ae9SGregory Neil Shapiro 	return size;
33406f25ae9SGregory Neil Shapiro }
33506f25ae9SGregory Neil Shapiro 
33640266059SGregory Neil Shapiro /*
33740266059SGregory Neil Shapiro **  SFDCSASL -- create sasl file type and open in and out file pointers
33840266059SGregory Neil Shapiro **	       for sendmail to read from and write to.
33940266059SGregory Neil Shapiro **
34040266059SGregory Neil Shapiro **	Parameters:
34140266059SGregory Neil Shapiro **		fin -- the sm_io file encrypted data to be read from
34240266059SGregory Neil Shapiro **		fout -- the sm_io file encrypted data to be writen to
34340266059SGregory Neil Shapiro **		conn -- the sasl connection pointer
34440266059SGregory Neil Shapiro **
34540266059SGregory Neil Shapiro **	Returns:
34640266059SGregory Neil Shapiro **		-1 on error
34740266059SGregory Neil Shapiro **		0 on success
34840266059SGregory Neil Shapiro **
34940266059SGregory Neil Shapiro **	Side effects:
35040266059SGregory Neil Shapiro **		The arguments "fin" and "fout" are replaced with the new
35140266059SGregory Neil Shapiro **		SM_FILE_T pointers.
35240266059SGregory Neil Shapiro */
35340266059SGregory Neil Shapiro 
35406f25ae9SGregory Neil Shapiro int
35506f25ae9SGregory Neil Shapiro sfdcsasl(fin, fout, conn)
35640266059SGregory Neil Shapiro 	SM_FILE_T **fin;
35740266059SGregory Neil Shapiro 	SM_FILE_T **fout;
35806f25ae9SGregory Neil Shapiro 	sasl_conn_t *conn;
35906f25ae9SGregory Neil Shapiro {
36040266059SGregory Neil Shapiro 	SM_FILE_T *newin, *newout;
36140266059SGregory Neil Shapiro 	SM_FILE_T  SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
36240266059SGregory Neil Shapiro 		sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
36340266059SGregory Neil Shapiro 		SM_TIME_FOREVER);
36440266059SGregory Neil Shapiro 	struct sasl_info info;
36506f25ae9SGregory Neil Shapiro 
36606f25ae9SGregory Neil Shapiro 	if (conn == NULL)
36706f25ae9SGregory Neil Shapiro 	{
36806f25ae9SGregory Neil Shapiro 		/* no need to do anything */
36906f25ae9SGregory Neil Shapiro 		return 0;
37006f25ae9SGregory Neil Shapiro 	}
37106f25ae9SGregory Neil Shapiro 
37240266059SGregory Neil Shapiro 	SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
37340266059SGregory Neil Shapiro 		sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
37440266059SGregory Neil Shapiro 		SM_TIME_FOREVER);
37540266059SGregory Neil Shapiro 	info.fp = *fin;
37640266059SGregory Neil Shapiro 	info.conn = conn;
377e92d3f3fSGregory Neil Shapiro 	newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
378e92d3f3fSGregory Neil Shapiro 			SM_IO_RDONLY_B, NULL);
37906f25ae9SGregory Neil Shapiro 
38040266059SGregory Neil Shapiro 	if (newin == NULL)
38140266059SGregory Neil Shapiro 		return -1;
38206f25ae9SGregory Neil Shapiro 
38340266059SGregory Neil Shapiro 	info.fp = *fout;
38440266059SGregory Neil Shapiro 	info.conn = conn;
385e92d3f3fSGregory Neil Shapiro 	newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
386e92d3f3fSGregory Neil Shapiro 			SM_IO_WRONLY_B, NULL);
38706f25ae9SGregory Neil Shapiro 
38840266059SGregory Neil Shapiro 	if (newout == NULL)
38906f25ae9SGregory Neil Shapiro 	{
39040266059SGregory Neil Shapiro 		(void) sm_io_close(newin, SM_TIME_DEFAULT);
39106f25ae9SGregory Neil Shapiro 		return -1;
39206f25ae9SGregory Neil Shapiro 	}
39340266059SGregory Neil Shapiro 	sm_io_automode(newin, newout);
39440266059SGregory Neil Shapiro 
39540266059SGregory Neil Shapiro 	*fin = newin;
39640266059SGregory Neil Shapiro 	*fout = newout;
39706f25ae9SGregory Neil Shapiro 	return 0;
39806f25ae9SGregory Neil Shapiro }
39940266059SGregory Neil Shapiro #endif /* SASL */
40006f25ae9SGregory Neil Shapiro 
40140266059SGregory Neil Shapiro #if STARTTLS
40206f25ae9SGregory Neil Shapiro # include "sfsasl.h"
40306f25ae9SGregory Neil Shapiro #  include <openssl/err.h>
40406f25ae9SGregory Neil Shapiro 
40540266059SGregory Neil Shapiro /* Structure used by the "tls" file type */
40640266059SGregory Neil Shapiro struct tls_obj
40740266059SGregory Neil Shapiro {
40840266059SGregory Neil Shapiro 	SM_FILE_T *fp;
40940266059SGregory Neil Shapiro 	SSL *con;
41040266059SGregory Neil Shapiro };
41140266059SGregory Neil Shapiro 
41240266059SGregory Neil Shapiro struct tls_info
41340266059SGregory Neil Shapiro {
41440266059SGregory Neil Shapiro 	SM_FILE_T *fp;
41540266059SGregory Neil Shapiro 	SSL *con;
41640266059SGregory Neil Shapiro };
41740266059SGregory Neil Shapiro 
41840266059SGregory Neil Shapiro /*
41940266059SGregory Neil Shapiro **  TLS_GETINFO - returns requested information about a "tls" file
42040266059SGregory Neil Shapiro **		 descriptor.
42140266059SGregory Neil Shapiro **
42240266059SGregory Neil Shapiro **	Parameters:
42340266059SGregory Neil Shapiro **		fp -- the file descriptor
42440266059SGregory Neil Shapiro **		what -- the type of information requested
42540266059SGregory Neil Shapiro **		valp -- the thang to return the information in (unused)
42640266059SGregory Neil Shapiro **
42740266059SGregory Neil Shapiro **	Returns:
42840266059SGregory Neil Shapiro **		-1 for unknown requests
42940266059SGregory Neil Shapiro **		>=0 on success with valp filled in (if possible).
43040266059SGregory Neil Shapiro */
43140266059SGregory Neil Shapiro 
43240266059SGregory Neil Shapiro static int tls_getinfo __P((SM_FILE_T *, int, void *));
43340266059SGregory Neil Shapiro 
43440266059SGregory Neil Shapiro /* ARGSUSED2 */
43513058a91SGregory Neil Shapiro static int
43640266059SGregory Neil Shapiro tls_getinfo(fp, what, valp)
43740266059SGregory Neil Shapiro 	SM_FILE_T *fp;
43840266059SGregory Neil Shapiro 	int what;
43940266059SGregory Neil Shapiro 	void *valp;
44040266059SGregory Neil Shapiro {
44140266059SGregory Neil Shapiro 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
44240266059SGregory Neil Shapiro 
44340266059SGregory Neil Shapiro 	switch (what)
44440266059SGregory Neil Shapiro 	{
44540266059SGregory Neil Shapiro 	  case SM_IO_WHAT_FD:
44640266059SGregory Neil Shapiro 		if (so->fp == NULL)
44740266059SGregory Neil Shapiro 			return -1;
44840266059SGregory Neil Shapiro 		return so->fp->f_file; /* for stdio fileno() compatability */
44940266059SGregory Neil Shapiro 
45040266059SGregory Neil Shapiro 	  case SM_IO_IS_READABLE:
45140266059SGregory Neil Shapiro 		return SSL_pending(so->con) > 0;
45240266059SGregory Neil Shapiro 
45340266059SGregory Neil Shapiro 	  default:
45440266059SGregory Neil Shapiro 		return -1;
45540266059SGregory Neil Shapiro 	}
45640266059SGregory Neil Shapiro }
45740266059SGregory Neil Shapiro 
45840266059SGregory Neil Shapiro /*
45940266059SGregory Neil Shapiro **  TLS_OPEN -- creates the tls specific information for opening a
46040266059SGregory Neil Shapiro **	       file of the tls type.
46140266059SGregory Neil Shapiro **
46240266059SGregory Neil Shapiro **	Parameters:
46340266059SGregory Neil Shapiro **		fp -- the file pointer associated with the new open
46440266059SGregory Neil Shapiro **		info -- the sm_io file pointer holding the open and the
46540266059SGregory Neil Shapiro **			TLS encryption connection to be read from or written to
46640266059SGregory Neil Shapiro **		flags -- ignored
46740266059SGregory Neil Shapiro **		rpool -- ignored
46840266059SGregory Neil Shapiro **
46940266059SGregory Neil Shapiro **	Returns:
47040266059SGregory Neil Shapiro **		0 on success
47140266059SGregory Neil Shapiro */
47240266059SGregory Neil Shapiro 
47340266059SGregory Neil Shapiro static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
47440266059SGregory Neil Shapiro 
47540266059SGregory Neil Shapiro /* ARGSUSED2 */
47640266059SGregory Neil Shapiro static int
47740266059SGregory Neil Shapiro tls_open(fp, info, flags, rpool)
47840266059SGregory Neil Shapiro 	SM_FILE_T *fp;
47940266059SGregory Neil Shapiro 	const void *info;
48040266059SGregory Neil Shapiro 	int flags;
48140266059SGregory Neil Shapiro 	const void *rpool;
48240266059SGregory Neil Shapiro {
48340266059SGregory Neil Shapiro 	struct tls_obj *so;
48440266059SGregory Neil Shapiro 	struct tls_info *ti = (struct tls_info *) info;
48540266059SGregory Neil Shapiro 
48640266059SGregory Neil Shapiro 	so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
487a7ec597cSGregory Neil Shapiro 	if (so == NULL)
488a7ec597cSGregory Neil Shapiro 	{
489a7ec597cSGregory Neil Shapiro 		errno = ENOMEM;
490a7ec597cSGregory Neil Shapiro 		return -1;
491a7ec597cSGregory Neil Shapiro 	}
49240266059SGregory Neil Shapiro 	so->fp = ti->fp;
49340266059SGregory Neil Shapiro 	so->con = ti->con;
49440266059SGregory Neil Shapiro 
49540266059SGregory Neil Shapiro 	/*
49640266059SGregory Neil Shapiro 	**  We try to get the "raw" file descriptor that TLS uses to
49740266059SGregory Neil Shapiro 	**  do the actual read/write with. This is to allow us control
49840266059SGregory Neil Shapiro 	**  over the file descriptor being a blocking or non-blocking type.
49940266059SGregory Neil Shapiro 	**  Under the covers TLS handles the change and this allows us
50040266059SGregory Neil Shapiro 	**  to do timeouts with sm_io.
50140266059SGregory Neil Shapiro 	*/
50240266059SGregory Neil Shapiro 
50340266059SGregory Neil Shapiro 	fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL);
50440266059SGregory Neil Shapiro 	(void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
50540266059SGregory Neil Shapiro 	fp->f_cookie = so;
50640266059SGregory Neil Shapiro 	return 0;
50740266059SGregory Neil Shapiro }
50840266059SGregory Neil Shapiro 
50940266059SGregory Neil Shapiro /*
51040266059SGregory Neil Shapiro **  TLS_CLOSE -- close the tls specific parts of the tls file pointer
51140266059SGregory Neil Shapiro **
51240266059SGregory Neil Shapiro **	Parameters:
51340266059SGregory Neil Shapiro **		fp -- the file pointer to close
51440266059SGregory Neil Shapiro **
51540266059SGregory Neil Shapiro **	Returns:
51640266059SGregory Neil Shapiro **		0 on success
51740266059SGregory Neil Shapiro */
51840266059SGregory Neil Shapiro 
51940266059SGregory Neil Shapiro static int tls_close __P((SM_FILE_T *));
52040266059SGregory Neil Shapiro 
52140266059SGregory Neil Shapiro static int
52240266059SGregory Neil Shapiro tls_close(fp)
52340266059SGregory Neil Shapiro 	SM_FILE_T *fp;
52440266059SGregory Neil Shapiro {
52540266059SGregory Neil Shapiro 	struct tls_obj *so;
52640266059SGregory Neil Shapiro 
52740266059SGregory Neil Shapiro 	so = (struct tls_obj *) fp->f_cookie;
528a7ec597cSGregory Neil Shapiro 	if (so == NULL)
529a7ec597cSGregory Neil Shapiro 		return 0;
53040266059SGregory Neil Shapiro 	if (so->fp != NULL)
53140266059SGregory Neil Shapiro 	{
53240266059SGregory Neil Shapiro 		sm_io_close(so->fp, SM_TIME_DEFAULT);
53340266059SGregory Neil Shapiro 		so->fp = NULL;
53440266059SGregory Neil Shapiro 	}
53540266059SGregory Neil Shapiro 	sm_free(so);
53640266059SGregory Neil Shapiro 	so = NULL;
53740266059SGregory Neil Shapiro 	return 0;
53840266059SGregory Neil Shapiro }
53940266059SGregory Neil Shapiro 
54040266059SGregory Neil Shapiro /* maximum number of retries for TLS related I/O due to handshakes */
54140266059SGregory Neil Shapiro # define MAX_TLS_IOS	4
54240266059SGregory Neil Shapiro 
54340266059SGregory Neil Shapiro /*
54440266059SGregory Neil Shapiro **  TLS_READ -- read secured information for the caller
54540266059SGregory Neil Shapiro **
54640266059SGregory Neil Shapiro **	Parameters:
54740266059SGregory Neil Shapiro **		fp -- the file pointer
54840266059SGregory Neil Shapiro **		buf -- the location to place the data
54940266059SGregory Neil Shapiro **		size -- the number of bytes to read from connection
55040266059SGregory Neil Shapiro **
55140266059SGregory Neil Shapiro **	Results:
55240266059SGregory Neil Shapiro **		-1 on error
55340266059SGregory Neil Shapiro **		otherwise the number of bytes read
55440266059SGregory Neil Shapiro */
55540266059SGregory Neil Shapiro 
55640266059SGregory Neil Shapiro static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
55740266059SGregory Neil Shapiro 
55840266059SGregory Neil Shapiro static ssize_t
55940266059SGregory Neil Shapiro tls_read(fp, buf, size)
56040266059SGregory Neil Shapiro 	SM_FILE_T *fp;
56113058a91SGregory Neil Shapiro 	char *buf;
56240266059SGregory Neil Shapiro 	size_t size;
56306f25ae9SGregory Neil Shapiro {
56406f25ae9SGregory Neil Shapiro 	int r;
56540266059SGregory Neil Shapiro 	static int again = MAX_TLS_IOS;
56640266059SGregory Neil Shapiro 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
56706f25ae9SGregory Neil Shapiro 	char *err;
56806f25ae9SGregory Neil Shapiro 
56940266059SGregory Neil Shapiro 	r = SSL_read(so->con, (char *) buf, size);
57040266059SGregory Neil Shapiro 
57140266059SGregory Neil Shapiro 	if (r > 0)
57240266059SGregory Neil Shapiro 	{
57340266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
57440266059SGregory Neil Shapiro 		return r;
57540266059SGregory Neil Shapiro 	}
57640266059SGregory Neil Shapiro 
57706f25ae9SGregory Neil Shapiro 	err = NULL;
57840266059SGregory Neil Shapiro 	switch (SSL_get_error(so->con, r))
57906f25ae9SGregory Neil Shapiro 	{
58006f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_NONE:
58140266059SGregory Neil Shapiro 	  case SSL_ERROR_ZERO_RETURN:
58240266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
58306f25ae9SGregory Neil Shapiro 		break;
58406f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_WRITE:
58540266059SGregory Neil Shapiro 		if (--again <= 0)
58640266059SGregory Neil Shapiro 			err = "read W BLOCK";
58740266059SGregory Neil Shapiro 		else
58840266059SGregory Neil Shapiro 			errno = EAGAIN;
58906f25ae9SGregory Neil Shapiro 		break;
59006f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_READ:
59140266059SGregory Neil Shapiro 		if (--again <= 0)
59240266059SGregory Neil Shapiro 			err = "read R BLOCK";
59340266059SGregory Neil Shapiro 		else
59440266059SGregory Neil Shapiro 			errno = EAGAIN;
59506f25ae9SGregory Neil Shapiro 		break;
59606f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_X509_LOOKUP:
59706f25ae9SGregory Neil Shapiro 		err = "write X BLOCK";
59806f25ae9SGregory Neil Shapiro 		break;
59906f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_SYSCALL:
60040266059SGregory Neil Shapiro 		if (r == 0 && errno == 0) /* out of protocol EOF found */
60140266059SGregory Neil Shapiro 			break;
60206f25ae9SGregory Neil Shapiro 		err = "syscall error";
60306f25ae9SGregory Neil Shapiro /*
60406f25ae9SGregory Neil Shapiro 		get_last_socket_error());
60506f25ae9SGregory Neil Shapiro */
60606f25ae9SGregory Neil Shapiro 		break;
60706f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_SSL:
608b6bacd31SGregory Neil Shapiro #if DEAL_WITH_ERROR_SSL
609959366dcSGregory Neil Shapiro 		if (r == 0 && errno == 0) /* out of protocol EOF found */
610959366dcSGregory Neil Shapiro 			break;
611b6bacd31SGregory Neil Shapiro #endif /* DEAL_WITH_ERROR_SSL */
61206f25ae9SGregory Neil Shapiro 		err = "generic SSL error";
61340266059SGregory Neil Shapiro 		if (LogLevel > 9)
61440266059SGregory Neil Shapiro 			tlslogerr("read");
615959366dcSGregory Neil Shapiro 
616b6bacd31SGregory Neil Shapiro #if DEAL_WITH_ERROR_SSL
617959366dcSGregory Neil Shapiro 		/* avoid repeated calls? */
618959366dcSGregory Neil Shapiro 		if (r == 0)
619959366dcSGregory Neil Shapiro 			r = -1;
620b6bacd31SGregory Neil Shapiro #endif /* DEAL_WITH_ERROR_SSL */
62106f25ae9SGregory Neil Shapiro 		break;
62206f25ae9SGregory Neil Shapiro 	}
62306f25ae9SGregory Neil Shapiro 	if (err != NULL)
62440266059SGregory Neil Shapiro 	{
625605302a5SGregory Neil Shapiro 		int save_errno;
626605302a5SGregory Neil Shapiro 
627605302a5SGregory Neil Shapiro 		save_errno = (errno == 0) ? EIO : errno;
62840266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
629a7ec597cSGregory Neil Shapiro 		if (LogLevel > 9)
630a7ec597cSGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
631a7ec597cSGregory Neil Shapiro 				  "STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
632a7ec597cSGregory Neil Shapiro 				  err, r, errno,
633a7ec597cSGregory Neil Shapiro 				  ERR_error_string(ERR_get_error(), NULL));
634a7ec597cSGregory Neil Shapiro 		else if (LogLevel > 7)
63540266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
63640266059SGregory Neil Shapiro 				  "STARTTLS: read error=%s (%d)", err, r);
637605302a5SGregory Neil Shapiro 		errno = save_errno;
63806f25ae9SGregory Neil Shapiro 	}
63906f25ae9SGregory Neil Shapiro 	return r;
64006f25ae9SGregory Neil Shapiro }
64106f25ae9SGregory Neil Shapiro 
64240266059SGregory Neil Shapiro /*
64340266059SGregory Neil Shapiro **  TLS_WRITE -- write information out through secure connection
64440266059SGregory Neil Shapiro **
64540266059SGregory Neil Shapiro **	Parameters:
64640266059SGregory Neil Shapiro **		fp -- the file pointer
64740266059SGregory Neil Shapiro **		buf -- holds the data to be securely written
64840266059SGregory Neil Shapiro **		size -- the number of bytes to write
64940266059SGregory Neil Shapiro **
65040266059SGregory Neil Shapiro **	Returns:
65140266059SGregory Neil Shapiro **		-1 on error
65240266059SGregory Neil Shapiro **		otherwise number of bytes written
65340266059SGregory Neil Shapiro */
65440266059SGregory Neil Shapiro 
65540266059SGregory Neil Shapiro static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
65640266059SGregory Neil Shapiro 
65713058a91SGregory Neil Shapiro static ssize_t
65840266059SGregory Neil Shapiro tls_write(fp, buf, size)
65940266059SGregory Neil Shapiro 	SM_FILE_T *fp;
66013058a91SGregory Neil Shapiro 	const char *buf;
66140266059SGregory Neil Shapiro 	size_t size;
66206f25ae9SGregory Neil Shapiro {
66306f25ae9SGregory Neil Shapiro 	int r;
66440266059SGregory Neil Shapiro 	static int again = MAX_TLS_IOS;
66540266059SGregory Neil Shapiro 	struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
66606f25ae9SGregory Neil Shapiro 	char *err;
66706f25ae9SGregory Neil Shapiro 
66840266059SGregory Neil Shapiro 	r = SSL_write(so->con, (char *) buf, size);
66940266059SGregory Neil Shapiro 
67040266059SGregory Neil Shapiro 	if (r > 0)
67140266059SGregory Neil Shapiro 	{
67240266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
67340266059SGregory Neil Shapiro 		return r;
67440266059SGregory Neil Shapiro 	}
67506f25ae9SGregory Neil Shapiro 	err = NULL;
67640266059SGregory Neil Shapiro 	switch (SSL_get_error(so->con, r))
67706f25ae9SGregory Neil Shapiro 	{
67806f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_NONE:
67940266059SGregory Neil Shapiro 	  case SSL_ERROR_ZERO_RETURN:
68040266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
68106f25ae9SGregory Neil Shapiro 		break;
68206f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_WRITE:
68340266059SGregory Neil Shapiro 		if (--again <= 0)
68406f25ae9SGregory Neil Shapiro 			err = "write W BLOCK";
68540266059SGregory Neil Shapiro 		else
68640266059SGregory Neil Shapiro 			errno = EAGAIN;
68706f25ae9SGregory Neil Shapiro 		break;
68806f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_READ:
68940266059SGregory Neil Shapiro 		if (--again <= 0)
69006f25ae9SGregory Neil Shapiro 			err = "write R BLOCK";
69140266059SGregory Neil Shapiro 		else
69240266059SGregory Neil Shapiro 			errno = EAGAIN;
69306f25ae9SGregory Neil Shapiro 		break;
69406f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_WANT_X509_LOOKUP:
69506f25ae9SGregory Neil Shapiro 		err = "write X BLOCK";
69606f25ae9SGregory Neil Shapiro 		break;
69706f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_SYSCALL:
69840266059SGregory Neil Shapiro 		if (r == 0 && errno == 0) /* out of protocol EOF found */
69940266059SGregory Neil Shapiro 			break;
70006f25ae9SGregory Neil Shapiro 		err = "syscall error";
70106f25ae9SGregory Neil Shapiro /*
70206f25ae9SGregory Neil Shapiro 		get_last_socket_error());
70306f25ae9SGregory Neil Shapiro */
70406f25ae9SGregory Neil Shapiro 		break;
70506f25ae9SGregory Neil Shapiro 	  case SSL_ERROR_SSL:
70606f25ae9SGregory Neil Shapiro 		err = "generic SSL error";
70706f25ae9SGregory Neil Shapiro /*
70806f25ae9SGregory Neil Shapiro 		ERR_GET_REASON(ERR_peek_error()));
70906f25ae9SGregory Neil Shapiro */
71040266059SGregory Neil Shapiro 		if (LogLevel > 9)
71140266059SGregory Neil Shapiro 			tlslogerr("write");
712959366dcSGregory Neil Shapiro 
713b6bacd31SGregory Neil Shapiro #if DEAL_WITH_ERROR_SSL
714959366dcSGregory Neil Shapiro 		/* avoid repeated calls? */
715959366dcSGregory Neil Shapiro 		if (r == 0)
716959366dcSGregory Neil Shapiro 			r = -1;
717b6bacd31SGregory Neil Shapiro #endif /* DEAL_WITH_ERROR_SSL */
71806f25ae9SGregory Neil Shapiro 		break;
71906f25ae9SGregory Neil Shapiro 	}
72006f25ae9SGregory Neil Shapiro 	if (err != NULL)
72140266059SGregory Neil Shapiro 	{
722605302a5SGregory Neil Shapiro 		int save_errno;
723605302a5SGregory Neil Shapiro 
724605302a5SGregory Neil Shapiro 		save_errno = (errno == 0) ? EIO : errno;
72540266059SGregory Neil Shapiro 		again = MAX_TLS_IOS;
726a7ec597cSGregory Neil Shapiro 		if (LogLevel > 9)
727a7ec597cSGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
728a7ec597cSGregory Neil Shapiro 				  "STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
729a7ec597cSGregory Neil Shapiro 				  err, r, errno,
730a7ec597cSGregory Neil Shapiro 				  ERR_error_string(ERR_get_error(), NULL));
731a7ec597cSGregory Neil Shapiro 		else if (LogLevel > 7)
73240266059SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
73340266059SGregory Neil Shapiro 				  "STARTTLS: write error=%s (%d)", err, r);
734605302a5SGregory Neil Shapiro 		errno = save_errno;
73506f25ae9SGregory Neil Shapiro 	}
73606f25ae9SGregory Neil Shapiro 	return r;
73706f25ae9SGregory Neil Shapiro }
73806f25ae9SGregory Neil Shapiro 
73940266059SGregory Neil Shapiro /*
74040266059SGregory Neil Shapiro **  SFDCTLS -- create tls file type and open in and out file pointers
74140266059SGregory Neil Shapiro **	      for sendmail to read from and write to.
74240266059SGregory Neil Shapiro **
74340266059SGregory Neil Shapiro **	Parameters:
74440266059SGregory Neil Shapiro **		fin -- data input source being replaced
74540266059SGregory Neil Shapiro **		fout -- data output source being replaced
746a7ec597cSGregory Neil Shapiro **		con -- the tls connection pointer
74740266059SGregory Neil Shapiro **
74840266059SGregory Neil Shapiro **	Returns:
74940266059SGregory Neil Shapiro **		-1 on error
75040266059SGregory Neil Shapiro **		0 on success
75140266059SGregory Neil Shapiro **
75240266059SGregory Neil Shapiro **	Side effects:
75340266059SGregory Neil Shapiro **		The arguments "fin" and "fout" are replaced with the new
75440266059SGregory Neil Shapiro **		SM_FILE_T pointers.
75540266059SGregory Neil Shapiro **		The original "fin" and "fout" are preserved in the tls file
75640266059SGregory Neil Shapiro **		type but are not actually used because of the design of TLS.
75740266059SGregory Neil Shapiro */
75806f25ae9SGregory Neil Shapiro 
75906f25ae9SGregory Neil Shapiro int
76006f25ae9SGregory Neil Shapiro sfdctls(fin, fout, con)
76140266059SGregory Neil Shapiro 	SM_FILE_T **fin;
76240266059SGregory Neil Shapiro 	SM_FILE_T **fout;
76306f25ae9SGregory Neil Shapiro 	SSL *con;
76406f25ae9SGregory Neil Shapiro {
76540266059SGregory Neil Shapiro 	SM_FILE_T *tlsin, *tlsout;
76640266059SGregory Neil Shapiro 	SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
76740266059SGregory Neil Shapiro 		tls_read, tls_write, NULL, tls_getinfo, NULL,
76840266059SGregory Neil Shapiro 		SM_TIME_FOREVER);
76940266059SGregory Neil Shapiro 	struct tls_info info;
77006f25ae9SGregory Neil Shapiro 
77140266059SGregory Neil Shapiro 	SM_ASSERT(con != NULL);
77206f25ae9SGregory Neil Shapiro 
77340266059SGregory Neil Shapiro 	SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
77440266059SGregory Neil Shapiro 		tls_read, tls_write, NULL, tls_getinfo, NULL,
77540266059SGregory Neil Shapiro 		SM_TIME_FOREVER);
77640266059SGregory Neil Shapiro 	info.fp = *fin;
77740266059SGregory Neil Shapiro 	info.con = con;
778e92d3f3fSGregory Neil Shapiro 	tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
77940266059SGregory Neil Shapiro 			   NULL);
78040266059SGregory Neil Shapiro 	if (tlsin == NULL)
78140266059SGregory Neil Shapiro 		return -1;
78206f25ae9SGregory Neil Shapiro 
78340266059SGregory Neil Shapiro 	info.fp = *fout;
784e92d3f3fSGregory Neil Shapiro 	tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
78540266059SGregory Neil Shapiro 			    NULL);
78640266059SGregory Neil Shapiro 	if (tlsout == NULL)
78742e5d165SGregory Neil Shapiro 	{
78840266059SGregory Neil Shapiro 		(void) sm_io_close(tlsin, SM_TIME_DEFAULT);
78942e5d165SGregory Neil Shapiro 		return -1;
79042e5d165SGregory Neil Shapiro 	}
79140266059SGregory Neil Shapiro 	sm_io_automode(tlsin, tlsout);
79206f25ae9SGregory Neil Shapiro 
79340266059SGregory Neil Shapiro 	*fin = tlsin;
79440266059SGregory Neil Shapiro 	*fout = tlsout;
79506f25ae9SGregory Neil Shapiro 	return 0;
79606f25ae9SGregory Neil Shapiro }
79740266059SGregory Neil Shapiro #endif /* STARTTLS */
798