xref: /freebsd/contrib/sendmail/src/sfsasl.c (revision 13058a916175518dfbac6ce66b9b8e22ecf43155)
106f25ae9SGregory Neil Shapiro /*
28774250cSGregory Neil Shapiro  * Copyright (c) 1999-2001 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 
1106f25ae9SGregory Neil Shapiro #ifndef lint
1213058a91SGregory Neil Shapiro static char id[] = "@(#)$Id: sfsasl.c,v 8.17.4.15 2001/07/11 17:37:07 gshapiro Exp $";
1306f25ae9SGregory Neil Shapiro #endif /* ! lint */
1406f25ae9SGregory Neil Shapiro 
1506f25ae9SGregory Neil Shapiro #if SFIO
1606f25ae9SGregory Neil Shapiro # include <sfio/stdio.h>
1706f25ae9SGregory Neil Shapiro #endif /* SFIO */
1806f25ae9SGregory Neil Shapiro 
1906f25ae9SGregory Neil Shapiro #include <stdlib.h>
2006f25ae9SGregory Neil Shapiro #include <sendmail.h>
2106f25ae9SGregory Neil Shapiro 
2206f25ae9SGregory Neil Shapiro #if SASL && SFIO
2306f25ae9SGregory Neil Shapiro /*
2406f25ae9SGregory Neil Shapiro **  SASL
2506f25ae9SGregory Neil Shapiro */
2606f25ae9SGregory Neil Shapiro 
2706f25ae9SGregory Neil Shapiro # include <sasl.h>
2806f25ae9SGregory Neil Shapiro # include "sfsasl.h"
2906f25ae9SGregory Neil Shapiro 
30193538b7SGregory Neil Shapiro /* how to deallocate a buffer allocated by SASL */
318774250cSGregory Neil Shapiro #  define SASL_DEALLOC(b)	sm_free(b)
32193538b7SGregory Neil Shapiro 
3306f25ae9SGregory Neil Shapiro static ssize_t
3406f25ae9SGregory Neil Shapiro sasl_read(f, buf, size, disc)
3506f25ae9SGregory Neil Shapiro 	Sfio_t *f;
3606f25ae9SGregory Neil Shapiro 	Void_t *buf;
3706f25ae9SGregory Neil Shapiro 	size_t size;
3806f25ae9SGregory Neil Shapiro 	Sfdisc_t *disc;
3906f25ae9SGregory Neil Shapiro {
4006f25ae9SGregory Neil Shapiro 	int len, result;
41193538b7SGregory Neil Shapiro 	static char *outbuf = NULL;
42193538b7SGregory Neil Shapiro 	static unsigned int outlen = 0;
43193538b7SGregory Neil Shapiro 	static unsigned int offset = 0;
4406f25ae9SGregory Neil Shapiro 	Sasldisc_t *sd = (Sasldisc_t *) disc;
4506f25ae9SGregory Neil Shapiro 
46193538b7SGregory Neil Shapiro 	/*
47193538b7SGregory Neil Shapiro 	**  sasl_decode() may require more data than a single read() returns.
48193538b7SGregory Neil Shapiro 	**  Hence we have to put a loop around the decoding.
49193538b7SGregory Neil Shapiro 	**  This also requires that we may have to split up the returned
50193538b7SGregory Neil Shapiro 	**  data since it might be larger than the allowed size.
51193538b7SGregory Neil Shapiro 	**  Therefore we use a static pointer and return portions of it
52193538b7SGregory Neil Shapiro 	**  if necessary.
53193538b7SGregory Neil Shapiro 	*/
5406f25ae9SGregory Neil Shapiro 
55193538b7SGregory Neil Shapiro 	while (outbuf == NULL && outlen == 0)
56193538b7SGregory Neil Shapiro 	{
57193538b7SGregory Neil Shapiro 		len = sfrd(f, buf, size, disc);
5806f25ae9SGregory Neil Shapiro 		if (len <= 0)
5906f25ae9SGregory Neil Shapiro 			return len;
6006f25ae9SGregory Neil Shapiro 		result = sasl_decode(sd->conn, buf, len, &outbuf, &outlen);
6106f25ae9SGregory Neil Shapiro 		if (result != SASL_OK)
6206f25ae9SGregory Neil Shapiro 		{
63193538b7SGregory Neil Shapiro 			outbuf = NULL;
64193538b7SGregory Neil Shapiro 			offset = 0;
65193538b7SGregory Neil Shapiro 			outlen = 0;
6606f25ae9SGregory Neil Shapiro 			return -1;
6706f25ae9SGregory Neil Shapiro 		}
68193538b7SGregory Neil Shapiro 	}
6906f25ae9SGregory Neil Shapiro 
7006f25ae9SGregory Neil Shapiro 	if (outbuf != NULL)
7106f25ae9SGregory Neil Shapiro 	{
72193538b7SGregory Neil Shapiro 		if (outlen - offset > size)
73193538b7SGregory Neil Shapiro 		{
74193538b7SGregory Neil Shapiro 			/* return another part of the buffer */
75193538b7SGregory Neil Shapiro 			(void) memcpy(buf, outbuf + offset, (size_t) size);
76193538b7SGregory Neil Shapiro 			offset += size;
77193538b7SGregory Neil Shapiro 			result = size;
7806f25ae9SGregory Neil Shapiro 		}
79193538b7SGregory Neil Shapiro 		else
80193538b7SGregory Neil Shapiro 		{
81193538b7SGregory Neil Shapiro 			/* return the rest of the buffer */
82193538b7SGregory Neil Shapiro 			result = outlen - offset;
83193538b7SGregory Neil Shapiro 			(void) memcpy(buf, outbuf + offset, (size_t) result);
84193538b7SGregory Neil Shapiro 			SASL_DEALLOC(outbuf);
85193538b7SGregory Neil Shapiro 			outbuf = NULL;
86193538b7SGregory Neil Shapiro 			offset = 0;
87193538b7SGregory Neil Shapiro 			outlen = 0;
88193538b7SGregory Neil Shapiro 		}
89193538b7SGregory Neil Shapiro 	}
90193538b7SGregory Neil Shapiro 	else
91193538b7SGregory Neil Shapiro 	{
92193538b7SGregory Neil Shapiro 		/* be paranoid: outbuf == NULL but outlen != 0 */
93193538b7SGregory Neil Shapiro 		syserr("!sasl_read failure: outbuf == NULL but outlen != 0");
94193538b7SGregory Neil Shapiro 	}
95193538b7SGregory Neil Shapiro 	return result;
9606f25ae9SGregory Neil Shapiro }
9706f25ae9SGregory Neil Shapiro 
9806f25ae9SGregory Neil Shapiro static ssize_t
9906f25ae9SGregory Neil Shapiro sasl_write(f, buf, size, disc)
10006f25ae9SGregory Neil Shapiro 	Sfio_t *f;
10106f25ae9SGregory Neil Shapiro 	const Void_t *buf;
10206f25ae9SGregory Neil Shapiro 	size_t size;
10306f25ae9SGregory Neil Shapiro 	Sfdisc_t *disc;
10406f25ae9SGregory Neil Shapiro {
10506f25ae9SGregory Neil Shapiro 	int result;
10606f25ae9SGregory Neil Shapiro 	char *outbuf;
10706f25ae9SGregory Neil Shapiro 	unsigned int outlen;
10806f25ae9SGregory Neil Shapiro 	Sasldisc_t *sd = (Sasldisc_t *) disc;
10906f25ae9SGregory Neil Shapiro 
11006f25ae9SGregory Neil Shapiro 	result = sasl_encode(sd->conn, buf, size, &outbuf, &outlen);
11106f25ae9SGregory Neil Shapiro 
11206f25ae9SGregory Neil Shapiro 	if (result != SASL_OK)
11306f25ae9SGregory Neil Shapiro 		return -1;
11406f25ae9SGregory Neil Shapiro 
11506f25ae9SGregory Neil Shapiro 	if (outbuf != NULL)
11606f25ae9SGregory Neil Shapiro 	{
11706f25ae9SGregory Neil Shapiro 		sfwr(f, outbuf, outlen, disc);
118193538b7SGregory Neil Shapiro 		SASL_DEALLOC(outbuf);
11906f25ae9SGregory Neil Shapiro 	}
12006f25ae9SGregory Neil Shapiro 	return size;
12106f25ae9SGregory Neil Shapiro }
12206f25ae9SGregory Neil Shapiro 
12306f25ae9SGregory Neil Shapiro int
12406f25ae9SGregory Neil Shapiro sfdcsasl(fin, fout, conn)
12506f25ae9SGregory Neil Shapiro 	Sfio_t *fin;
12606f25ae9SGregory Neil Shapiro 	Sfio_t *fout;
12706f25ae9SGregory Neil Shapiro 	sasl_conn_t *conn;
12806f25ae9SGregory Neil Shapiro {
12906f25ae9SGregory Neil Shapiro 	Sasldisc_t *saslin, *saslout;
13006f25ae9SGregory Neil Shapiro 
13106f25ae9SGregory Neil Shapiro 	if (conn == NULL)
13206f25ae9SGregory Neil Shapiro 	{
13306f25ae9SGregory Neil Shapiro 		/* no need to do anything */
13406f25ae9SGregory Neil Shapiro 		return 0;
13506f25ae9SGregory Neil Shapiro 	}
13606f25ae9SGregory Neil Shapiro 
1378774250cSGregory Neil Shapiro 	saslin = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t));
1388774250cSGregory Neil Shapiro 	saslout = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t));
13906f25ae9SGregory Neil Shapiro 	saslin->disc.readf = sasl_read;
14006f25ae9SGregory Neil Shapiro 	saslin->disc.writef = sasl_write;
14106f25ae9SGregory Neil Shapiro 	saslin->disc.seekf = NULL;
14206f25ae9SGregory Neil Shapiro 	saslin->disc.exceptf = NULL;
14306f25ae9SGregory Neil Shapiro 
14406f25ae9SGregory Neil Shapiro 	saslout->disc.readf = sasl_read;
14506f25ae9SGregory Neil Shapiro 	saslout->disc.writef = sasl_write;
14606f25ae9SGregory Neil Shapiro 	saslout->disc.seekf = NULL;
14706f25ae9SGregory Neil Shapiro 	saslout->disc.exceptf = NULL;
14806f25ae9SGregory Neil Shapiro 
14906f25ae9SGregory Neil Shapiro 	saslin->conn = conn;
15006f25ae9SGregory Neil Shapiro 	saslout->conn = conn;
15106f25ae9SGregory Neil Shapiro 
15206f25ae9SGregory Neil Shapiro 	if (sfdisc(fin, (Sfdisc_t *) saslin) != (Sfdisc_t *) saslin ||
15306f25ae9SGregory Neil Shapiro 	    sfdisc(fout, (Sfdisc_t *) saslout) != (Sfdisc_t *) saslout)
15406f25ae9SGregory Neil Shapiro 	{
1558774250cSGregory Neil Shapiro 		sm_free(saslin);
1568774250cSGregory Neil Shapiro 		sm_free(saslout);
15706f25ae9SGregory Neil Shapiro 		return -1;
15806f25ae9SGregory Neil Shapiro 	}
15906f25ae9SGregory Neil Shapiro 	return 0;
16006f25ae9SGregory Neil Shapiro }
16106f25ae9SGregory Neil Shapiro #endif /* SASL && SFIO */
16206f25ae9SGregory Neil Shapiro 
16306f25ae9SGregory Neil Shapiro #if STARTTLS && (SFIO || _FFR_TLS_TOREK)
16406f25ae9SGregory Neil Shapiro /*
16506f25ae9SGregory Neil Shapiro **  STARTTLS
16606f25ae9SGregory Neil Shapiro */
16706f25ae9SGregory Neil Shapiro 
16806f25ae9SGregory Neil Shapiro # include "sfsasl.h"
16906f25ae9SGregory Neil Shapiro #  include <openssl/err.h>
17006f25ae9SGregory Neil Shapiro 
17106f25ae9SGregory Neil Shapiro # if SFIO
17213058a91SGregory Neil Shapiro static ssize_t
17306f25ae9SGregory Neil Shapiro tls_read(f, buf, size, disc)
17406f25ae9SGregory Neil Shapiro 	Sfio_t *f;
17506f25ae9SGregory Neil Shapiro 	Void_t *buf;
17606f25ae9SGregory Neil Shapiro 	size_t size;
17706f25ae9SGregory Neil Shapiro 	Sfdisc_t *disc;
17806f25ae9SGregory Neil Shapiro # else /* SFIO */
17913058a91SGregory Neil Shapiro static int
18006f25ae9SGregory Neil Shapiro tls_read(disc, buf, size)
18106f25ae9SGregory Neil Shapiro 	void *disc;
18213058a91SGregory Neil Shapiro 	char *buf;
18313058a91SGregory Neil Shapiro 	int size;
18406f25ae9SGregory Neil Shapiro # endif /* SFIO */
18506f25ae9SGregory Neil Shapiro {
18606f25ae9SGregory Neil Shapiro 	int r;
18706f25ae9SGregory Neil Shapiro 	Tlsdisc_t *sd;
18806f25ae9SGregory Neil Shapiro 
18906f25ae9SGregory Neil Shapiro 	/* Cast back to correct type */
19006f25ae9SGregory Neil Shapiro 	sd = (Tlsdisc_t *) disc;
19106f25ae9SGregory Neil Shapiro 
19206f25ae9SGregory Neil Shapiro 	r = SSL_read(sd->con, (char *) buf, size);
19306f25ae9SGregory Neil Shapiro 	if (r < 0 && LogLevel > 7)
19406f25ae9SGregory Neil Shapiro 	{
19506f25ae9SGregory Neil Shapiro 		char *err;
19606f25ae9SGregory Neil Shapiro 
19706f25ae9SGregory Neil Shapiro 		err = NULL;
19806f25ae9SGregory Neil Shapiro 		switch (SSL_get_error(sd->con, r))
19906f25ae9SGregory Neil Shapiro 		{
20006f25ae9SGregory Neil Shapiro 			case SSL_ERROR_NONE:
20106f25ae9SGregory Neil Shapiro 				break;
20206f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_WRITE:
20306f25ae9SGregory Neil Shapiro 				err = "write W BLOCK";
20406f25ae9SGregory Neil Shapiro 				break;
20506f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_READ:
20606f25ae9SGregory Neil Shapiro 				err = "write R BLOCK";
20706f25ae9SGregory Neil Shapiro 				break;
20806f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_X509_LOOKUP:
20906f25ae9SGregory Neil Shapiro 				err = "write X BLOCK";
21006f25ae9SGregory Neil Shapiro 				break;
21106f25ae9SGregory Neil Shapiro 			case SSL_ERROR_ZERO_RETURN:
21206f25ae9SGregory Neil Shapiro 				break;
21306f25ae9SGregory Neil Shapiro 			case SSL_ERROR_SYSCALL:
21406f25ae9SGregory Neil Shapiro 				err = "syscall error";
21506f25ae9SGregory Neil Shapiro /*
21606f25ae9SGregory Neil Shapiro 				get_last_socket_error());
21706f25ae9SGregory Neil Shapiro */
21806f25ae9SGregory Neil Shapiro 				break;
21906f25ae9SGregory Neil Shapiro 			case SSL_ERROR_SSL:
22006f25ae9SGregory Neil Shapiro 				err = "generic SSL error";
22106f25ae9SGregory Neil Shapiro 				break;
22206f25ae9SGregory Neil Shapiro 		}
22306f25ae9SGregory Neil Shapiro 		if (err != NULL)
22406f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID, "TLS: read error:  %s",
22506f25ae9SGregory Neil Shapiro 				  err);
22606f25ae9SGregory Neil Shapiro 	}
22706f25ae9SGregory Neil Shapiro 	return r;
22806f25ae9SGregory Neil Shapiro }
22906f25ae9SGregory Neil Shapiro 
23006f25ae9SGregory Neil Shapiro # if SFIO
23113058a91SGregory Neil Shapiro static ssize_t
23206f25ae9SGregory Neil Shapiro tls_write(f, buf, size, disc)
23306f25ae9SGregory Neil Shapiro 	Sfio_t *f;
23406f25ae9SGregory Neil Shapiro 	const Void_t *buf;
23506f25ae9SGregory Neil Shapiro 	size_t size;
23606f25ae9SGregory Neil Shapiro 	Sfdisc_t *disc;
23706f25ae9SGregory Neil Shapiro # else /* SFIO */
23813058a91SGregory Neil Shapiro static int
23906f25ae9SGregory Neil Shapiro tls_write(disc, buf, size)
24006f25ae9SGregory Neil Shapiro 	void *disc;
24113058a91SGregory Neil Shapiro 	const char *buf;
24213058a91SGregory Neil Shapiro 	int size;
24306f25ae9SGregory Neil Shapiro # endif /* SFIO */
24406f25ae9SGregory Neil Shapiro {
24506f25ae9SGregory Neil Shapiro 	int r;
24606f25ae9SGregory Neil Shapiro 	Tlsdisc_t *sd;
24706f25ae9SGregory Neil Shapiro 
24806f25ae9SGregory Neil Shapiro 	/* Cast back to correct type */
24906f25ae9SGregory Neil Shapiro 	sd = (Tlsdisc_t *) disc;
25006f25ae9SGregory Neil Shapiro 
25106f25ae9SGregory Neil Shapiro 	r = SSL_write(sd->con, (char *)buf, size);
25206f25ae9SGregory Neil Shapiro 	if (r < 0 && LogLevel > 7)
25306f25ae9SGregory Neil Shapiro 	{
25406f25ae9SGregory Neil Shapiro 		char *err;
25506f25ae9SGregory Neil Shapiro 
25606f25ae9SGregory Neil Shapiro 		err = NULL;
25706f25ae9SGregory Neil Shapiro 		switch (SSL_get_error(sd->con, r))
25806f25ae9SGregory Neil Shapiro 		{
25906f25ae9SGregory Neil Shapiro 			case SSL_ERROR_NONE:
26006f25ae9SGregory Neil Shapiro 				break;
26106f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_WRITE:
26206f25ae9SGregory Neil Shapiro 				err = "write W BLOCK";
26306f25ae9SGregory Neil Shapiro 				break;
26406f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_READ:
26506f25ae9SGregory Neil Shapiro 				err = "write R BLOCK";
26606f25ae9SGregory Neil Shapiro 				break;
26706f25ae9SGregory Neil Shapiro 			case SSL_ERROR_WANT_X509_LOOKUP:
26806f25ae9SGregory Neil Shapiro 				err = "write X BLOCK";
26906f25ae9SGregory Neil Shapiro 				break;
27006f25ae9SGregory Neil Shapiro 			case SSL_ERROR_ZERO_RETURN:
27106f25ae9SGregory Neil Shapiro 				break;
27206f25ae9SGregory Neil Shapiro 			case SSL_ERROR_SYSCALL:
27306f25ae9SGregory Neil Shapiro 				err = "syscall error";
27406f25ae9SGregory Neil Shapiro /*
27506f25ae9SGregory Neil Shapiro 				get_last_socket_error());
27606f25ae9SGregory Neil Shapiro */
27706f25ae9SGregory Neil Shapiro 				break;
27806f25ae9SGregory Neil Shapiro 			case SSL_ERROR_SSL:
27906f25ae9SGregory Neil Shapiro 				err = "generic SSL error";
28006f25ae9SGregory Neil Shapiro /*
28106f25ae9SGregory Neil Shapiro 				ERR_GET_REASON(ERR_peek_error()));
28206f25ae9SGregory Neil Shapiro */
28306f25ae9SGregory Neil Shapiro 				break;
28406f25ae9SGregory Neil Shapiro 		}
28506f25ae9SGregory Neil Shapiro 		if (err != NULL)
28606f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID, "TLS: write error:  %s",
28706f25ae9SGregory Neil Shapiro 				  err);
28806f25ae9SGregory Neil Shapiro 	}
28906f25ae9SGregory Neil Shapiro 	return r;
29006f25ae9SGregory Neil Shapiro }
29106f25ae9SGregory Neil Shapiro 
29206f25ae9SGregory Neil Shapiro # if !SFIO
29306f25ae9SGregory Neil Shapiro static int
29406f25ae9SGregory Neil Shapiro tls_close(cookie)
29506f25ae9SGregory Neil Shapiro 	void *cookie;
29606f25ae9SGregory Neil Shapiro {
29706f25ae9SGregory Neil Shapiro 	int retval = 0;
29806f25ae9SGregory Neil Shapiro 	Tlsdisc_t *tc;
29906f25ae9SGregory Neil Shapiro 
30006f25ae9SGregory Neil Shapiro 	/* Cast back to correct type */
30106f25ae9SGregory Neil Shapiro 	tc = (Tlsdisc_t *)cookie;
30206f25ae9SGregory Neil Shapiro 
30306f25ae9SGregory Neil Shapiro 	if (tc->fp != NULL)
30406f25ae9SGregory Neil Shapiro 	{
30506f25ae9SGregory Neil Shapiro 		retval = fclose(tc->fp);
30606f25ae9SGregory Neil Shapiro 		tc->fp = NULL;
30706f25ae9SGregory Neil Shapiro 	}
30806f25ae9SGregory Neil Shapiro 
3098774250cSGregory Neil Shapiro 	sm_free(tc);
31006f25ae9SGregory Neil Shapiro 	return retval;
31106f25ae9SGregory Neil Shapiro }
31206f25ae9SGregory Neil Shapiro # endif /* !SFIO */
31306f25ae9SGregory Neil Shapiro 
31406f25ae9SGregory Neil Shapiro int
31506f25ae9SGregory Neil Shapiro sfdctls(fin, fout, con)
31606f25ae9SGregory Neil Shapiro # if SFIO
31706f25ae9SGregory Neil Shapiro 	Sfio_t *fin;
31806f25ae9SGregory Neil Shapiro 	Sfio_t *fout;
31906f25ae9SGregory Neil Shapiro # else /* SFIO */
32006f25ae9SGregory Neil Shapiro 	FILE **fin;
32106f25ae9SGregory Neil Shapiro 	FILE **fout;
32206f25ae9SGregory Neil Shapiro # endif /* SFIO */
32306f25ae9SGregory Neil Shapiro 	SSL *con;
32406f25ae9SGregory Neil Shapiro {
32506f25ae9SGregory Neil Shapiro 	Tlsdisc_t *tlsin, *tlsout;
32606f25ae9SGregory Neil Shapiro # if !SFIO
32706f25ae9SGregory Neil Shapiro 	FILE *fp;
32842e5d165SGregory Neil Shapiro # else /* !SFIO */
32942e5d165SGregory Neil Shapiro 	int rfd, wfd;
33006f25ae9SGregory Neil Shapiro # endif /* !SFIO */
33106f25ae9SGregory Neil Shapiro 
33206f25ae9SGregory Neil Shapiro 	if (con == NULL)
33306f25ae9SGregory Neil Shapiro 		return 0;
33406f25ae9SGregory Neil Shapiro 
3358774250cSGregory Neil Shapiro 	tlsin = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t));
3368774250cSGregory Neil Shapiro 	tlsout = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t));
33706f25ae9SGregory Neil Shapiro # if SFIO
33806f25ae9SGregory Neil Shapiro 	tlsin->disc.readf = tls_read;
33906f25ae9SGregory Neil Shapiro 	tlsin->disc.writef = tls_write;
34006f25ae9SGregory Neil Shapiro 	tlsin->disc.seekf = NULL;
34106f25ae9SGregory Neil Shapiro 	tlsin->disc.exceptf = NULL;
34206f25ae9SGregory Neil Shapiro 	tlsin->con = con;
34306f25ae9SGregory Neil Shapiro 
34406f25ae9SGregory Neil Shapiro 	tlsout->disc.readf = tls_read;
34506f25ae9SGregory Neil Shapiro 	tlsout->disc.writef = tls_write;
34606f25ae9SGregory Neil Shapiro 	tlsout->disc.seekf = NULL;
34706f25ae9SGregory Neil Shapiro 	tlsout->disc.exceptf = NULL;
34806f25ae9SGregory Neil Shapiro 	tlsout->con = con;
34906f25ae9SGregory Neil Shapiro 
35042e5d165SGregory Neil Shapiro 	rfd = fileno(fin);
35142e5d165SGregory Neil Shapiro 	wfd = fileno(fout);
35242e5d165SGregory Neil Shapiro 	if (rfd < 0 || wfd < 0 ||
35342e5d165SGregory Neil Shapiro 	    SSL_set_rfd(con, rfd) <= 0 || SSL_set_wfd(con, wfd) <= 0)
35442e5d165SGregory Neil Shapiro 	{
3558774250cSGregory Neil Shapiro 		sm_free(tlsin);
3568774250cSGregory Neil Shapiro 		sm_free(tlsout);
35742e5d165SGregory Neil Shapiro 		return -1;
35842e5d165SGregory Neil Shapiro 	}
35906f25ae9SGregory Neil Shapiro 	if (sfdisc(fin, (Sfdisc_t *) tlsin) != (Sfdisc_t *) tlsin ||
36006f25ae9SGregory Neil Shapiro 	    sfdisc(fout, (Sfdisc_t *) tlsout) != (Sfdisc_t *) tlsout)
36106f25ae9SGregory Neil Shapiro 	{
3628774250cSGregory Neil Shapiro 		sm_free(tlsin);
3638774250cSGregory Neil Shapiro 		sm_free(tlsout);
36406f25ae9SGregory Neil Shapiro 		return -1;
36506f25ae9SGregory Neil Shapiro 	}
36606f25ae9SGregory Neil Shapiro # else /* SFIO */
36706f25ae9SGregory Neil Shapiro 	tlsin->fp = *fin;
36806f25ae9SGregory Neil Shapiro 	tlsin->con = con;
36906f25ae9SGregory Neil Shapiro 	fp = funopen(tlsin, tls_read, tls_write, NULL, tls_close);
37006f25ae9SGregory Neil Shapiro 	if (fp == NULL)
37106f25ae9SGregory Neil Shapiro 	{
3728774250cSGregory Neil Shapiro 		sm_free(tlsin);
37306f25ae9SGregory Neil Shapiro 		return -1;
37406f25ae9SGregory Neil Shapiro 	}
37506f25ae9SGregory Neil Shapiro 	*fin = fp;
37606f25ae9SGregory Neil Shapiro 
37706f25ae9SGregory Neil Shapiro 	tlsout->fp = *fout;
37806f25ae9SGregory Neil Shapiro 	tlsout->con = con;
37906f25ae9SGregory Neil Shapiro 	fp = funopen(tlsout, tls_read, tls_write, NULL, tls_close);
38006f25ae9SGregory Neil Shapiro 	if (fp == NULL)
38106f25ae9SGregory Neil Shapiro 	{
38206f25ae9SGregory Neil Shapiro 		FILE *save;
38306f25ae9SGregory Neil Shapiro 
38406f25ae9SGregory Neil Shapiro 		/* Hack: Don't close underlying fp */
38506f25ae9SGregory Neil Shapiro 		save = tlsin->fp;
38606f25ae9SGregory Neil Shapiro 		tlsin->fp = NULL;
38706f25ae9SGregory Neil Shapiro 		fclose(*fin);
38806f25ae9SGregory Neil Shapiro 		*fin = save;
3898774250cSGregory Neil Shapiro 		sm_free(tlsout);
39006f25ae9SGregory Neil Shapiro 		return -1;
39106f25ae9SGregory Neil Shapiro 	}
39206f25ae9SGregory Neil Shapiro 	*fout = fp;
39306f25ae9SGregory Neil Shapiro 	SSL_set_rfd(con, fileno(tlsin->fp));
39406f25ae9SGregory Neil Shapiro 	SSL_set_wfd(con, fileno(tlsout->fp));
39506f25ae9SGregory Neil Shapiro # endif /* SFIO */
39606f25ae9SGregory Neil Shapiro 	return 0;
39706f25ae9SGregory Neil Shapiro }
39806f25ae9SGregory Neil Shapiro #endif /* STARTTLS && (SFIO || _FFR_TLS_TOREK) */
399