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