diff options
Diffstat (limited to 'contrib/sendmail/src/sfsasl.c')
-rw-r--r-- | contrib/sendmail/src/sfsasl.c | 827 |
1 files changed, 568 insertions, 259 deletions
diff --git a/contrib/sendmail/src/sfsasl.c b/contrib/sendmail/src/sfsasl.c index 8ac3428..c6f63fb 100644 --- a/contrib/sendmail/src/sfsasl.c +++ b/contrib/sendmail/src/sfsasl.c @@ -8,40 +8,179 @@ * */ -#ifndef lint -static char id[] = "@(#)$Id: sfsasl.c,v 8.17.4.15 2001/07/11 17:37:07 gshapiro Exp $"; -#endif /* ! lint */ - -#if SFIO -# include <sfio/stdio.h> -#endif /* SFIO */ - +#include <sm/gen.h> +SM_RCSID("@(#)$Id: sfsasl.c,v 8.86 2001/09/11 04:05:16 gshapiro Exp $") #include <stdlib.h> #include <sendmail.h> +#include <errno.h> +#if SASL +# include <sasl.h> +# include "sfsasl.h" + +/* Structure used by the "sasl" file type */ +struct sasl_obj +{ + SM_FILE_T *fp; + sasl_conn_t *conn; +}; + +struct sasl_info +{ + SM_FILE_T *fp; + sasl_conn_t *conn; +}; -#if SASL && SFIO /* -** SASL +** SASL_GETINFO - returns requested information about a "sasl" file +** descriptor. +** +** Parameters: +** fp -- the file descriptor +** what -- the type of information requested +** valp -- the thang to return the information in +** +** Returns: +** -1 for unknown requests +** >=0 on success with valp filled in (if possible). */ -# include <sasl.h> -# include "sfsasl.h" +static int sasl_getinfo __P((SM_FILE_T *, int, void *)); + +static int +sasl_getinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; + + switch (what) + { + case SM_IO_WHAT_FD: + if (so->fp == NULL) + return -1; + return so->fp->f_file; /* for stdio fileno() compatability */ + + case SM_IO_IS_READABLE: + if (so->fp == NULL) + return 0; + + /* get info from underlying file */ + return sm_io_getinfo(so->fp, what, valp); + + default: + return -1; + } +} + +/* +** SASL_OPEN -- creates the sasl specific information for opening a +** file of the sasl type. +** +** Parameters: +** fp -- the file pointer associated with the new open +** info -- contains the sasl connection information pointer and +** the original SM_FILE_T that holds the open +** flags -- ignored +** rpool -- ignored +** +** Returns: +** 0 on success +*/ + +static int sasl_open __P((SM_FILE_T *, const void *, int, const void *)); + +/* ARGSUSED2 */ +static int +sasl_open(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + struct sasl_obj *so; + struct sasl_info *si = (struct sasl_info *) info; + + so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj)); + so->fp = si->fp; + so->conn = si->conn; + + /* + ** The underlying 'fp' is set to SM_IO_NOW so that the entire + ** encoded string is written in one chunk. Otherwise there is + ** the possibility that it may appear illegal, bogus or + ** mangled to the other side of the connection. + ** We will read or write through 'fp' since it is the opaque + ** connection for the communications. We need to treat it this + ** way in case the encoded string is to be sent down a TLS + ** connection rather than, say, sm_io's stdio. + */ + + (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0); + fp->f_cookie = so; + return 0; +} + +/* +** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer +** +** Parameters: +** fp -- the file pointer to close +** +** Returns: +** 0 on success +*/ + +static int sasl_close __P((SM_FILE_T *)); + +static int +sasl_close(fp) + SM_FILE_T *fp; +{ + struct sasl_obj *so; + + so = (struct sasl_obj *) fp->f_cookie; + if (so->fp != NULL) + { + sm_io_close(so->fp, SM_TIME_DEFAULT); + so->fp = NULL; + } + sm_free(so); + so = NULL; + return 0; +} /* how to deallocate a buffer allocated by SASL */ -# define SASL_DEALLOC(b) sm_free(b) +extern void sm_sasl_free __P((void *)); +# define SASL_DEALLOC(b) sm_sasl_free(b) + +/* +** SASL_READ -- read encrypted information and decrypt it for the caller +** +** Parameters: +** fp -- the file pointer +** buf -- the location to place the decrypted information +** size -- the number of bytes to read after decryption +** +** Results: +** -1 on error +** otherwise the number of bytes read +*/ + +static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t)); static ssize_t -sasl_read(f, buf, size, disc) - Sfio_t *f; - Void_t *buf; +sasl_read(fp, buf, size) + SM_FILE_T *fp; + char *buf; size_t size; - Sfdisc_t *disc; { - int len, result; + int result; + ssize_t len; static char *outbuf = NULL; static unsigned int outlen = 0; static unsigned int offset = 0; - Sasldisc_t *sd = (Sasldisc_t *) disc; + struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; /* ** sasl_decode() may require more data than a single read() returns. @@ -54,10 +193,11 @@ sasl_read(f, buf, size, disc) while (outbuf == NULL && outlen == 0) { - len = sfrd(f, buf, size, disc); + len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size); if (len <= 0) return len; - result = sasl_decode(sd->conn, buf, len, &outbuf, &outlen); + result = sasl_decode(so->conn, buf, + (unsigned int) len, &outbuf, &outlen); if (result != SASL_OK) { outbuf = NULL; @@ -67,66 +207,108 @@ sasl_read(f, buf, size, disc) } } - if (outbuf != NULL) + if (outbuf == NULL) { - if (outlen - offset > size) - { - /* return another part of the buffer */ - (void) memcpy(buf, outbuf + offset, (size_t) size); - offset += size; - result = size; - } - else - { - /* return the rest of the buffer */ - result = outlen - offset; - (void) memcpy(buf, outbuf + offset, (size_t) result); - SASL_DEALLOC(outbuf); - outbuf = NULL; - offset = 0; - outlen = 0; - } + /* be paranoid: outbuf == NULL but outlen != 0 */ + syserr("@sasl_read failure: outbuf == NULL but outlen != 0"); + /* NOTREACHED */ + } + if (outlen - offset > size) + { + /* return another part of the buffer */ + (void) memcpy(buf, outbuf + offset, size); + offset += size; + len = size; } else { - /* be paranoid: outbuf == NULL but outlen != 0 */ - syserr("!sasl_read failure: outbuf == NULL but outlen != 0"); + /* return the rest of the buffer */ + len = outlen - offset; + (void) memcpy(buf, outbuf + offset, (size_t) len); + SASL_DEALLOC(outbuf); + outbuf = NULL; + offset = 0; + outlen = 0; } - return result; + return len; } +/* +** SASL_WRITE -- write information out after encrypting it +** +** Parameters: +** fp -- the file pointer +** buf -- holds the data to be encrypted and written +** size -- the number of bytes to have encrypted and written +** +** Returns: +** -1 on error +** otherwise number of bytes written +*/ + +static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t)); + static ssize_t -sasl_write(f, buf, size, disc) - Sfio_t *f; - const Void_t *buf; +sasl_write(fp, buf, size) + SM_FILE_T *fp; + const char *buf; size_t size; - Sfdisc_t *disc; { int result; char *outbuf; unsigned int outlen; - Sasldisc_t *sd = (Sasldisc_t *) disc; + size_t ret = 0, total = 0; + struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; - result = sasl_encode(sd->conn, buf, size, &outbuf, &outlen); + result = sasl_encode(so->conn, buf, + (unsigned int) size, &outbuf, &outlen); if (result != SASL_OK) return -1; if (outbuf != NULL) { - sfwr(f, outbuf, outlen, disc); + while (outlen > 0) + { + ret = sm_io_write(so->fp, SM_TIME_DEFAULT, + &outbuf[total], outlen); + outlen -= ret; + total += ret; + } SASL_DEALLOC(outbuf); } return size; } +/* +** SFDCSASL -- create sasl file type and open in and out file pointers +** for sendmail to read from and write to. +** +** Parameters: +** fin -- the sm_io file encrypted data to be read from +** fout -- the sm_io file encrypted data to be writen to +** conn -- the sasl connection pointer +** +** Returns: +** -1 on error +** 0 on success +** +** Side effects: +** The arguments "fin" and "fout" are replaced with the new +** SM_FILE_T pointers. +*/ + int sfdcsasl(fin, fout, conn) - Sfio_t *fin; - Sfio_t *fout; + SM_FILE_T **fin; + SM_FILE_T **fout; sasl_conn_t *conn; { - Sasldisc_t *saslin, *saslout; + SM_FILE_T *newin, *newout; + SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, + sasl_read, sasl_write, NULL, sasl_getinfo, NULL, + SM_TIME_FOREVER); + struct sasl_info info; if (conn == NULL) { @@ -134,265 +316,392 @@ sfdcsasl(fin, fout, conn) return 0; } - saslin = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t)); - saslout = (Sasldisc_t *) xalloc(sizeof(Sasldisc_t)); - saslin->disc.readf = sasl_read; - saslin->disc.writef = sasl_write; - saslin->disc.seekf = NULL; - saslin->disc.exceptf = NULL; + SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, + sasl_read, sasl_write, NULL, sasl_getinfo, NULL, + SM_TIME_FOREVER); + info.fp = *fin; + info.conn = conn; + newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY, + NULL); - saslout->disc.readf = sasl_read; - saslout->disc.writef = sasl_write; - saslout->disc.seekf = NULL; - saslout->disc.exceptf = NULL; + if (newin == NULL) + return -1; - saslin->conn = conn; - saslout->conn = conn; + info.fp = *fout; + info.conn = conn; + newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY, + NULL); - if (sfdisc(fin, (Sfdisc_t *) saslin) != (Sfdisc_t *) saslin || - sfdisc(fout, (Sfdisc_t *) saslout) != (Sfdisc_t *) saslout) + if (newout == NULL) { - sm_free(saslin); - sm_free(saslout); + (void) sm_io_close(newin, SM_TIME_DEFAULT); return -1; } + sm_io_automode(newin, newout); + + *fin = newin; + *fout = newout; return 0; } -#endif /* SASL && SFIO */ +#endif /* SASL */ + +#if STARTTLS +# include "sfsasl.h" +# include <openssl/err.h> + +/* Structure used by the "tls" file type */ +struct tls_obj +{ + SM_FILE_T *fp; + SSL *con; +}; + +struct tls_info +{ + SM_FILE_T *fp; + SSL *con; +}; -#if STARTTLS && (SFIO || _FFR_TLS_TOREK) /* -** STARTTLS +** TLS_GETINFO - returns requested information about a "tls" file +** descriptor. +** +** Parameters: +** fp -- the file descriptor +** what -- the type of information requested +** valp -- the thang to return the information in (unused) +** +** Returns: +** -1 for unknown requests +** >=0 on success with valp filled in (if possible). */ -# include "sfsasl.h" -# include <openssl/err.h> +static int tls_getinfo __P((SM_FILE_T *, int, void *)); -# if SFIO -static ssize_t -tls_read(f, buf, size, disc) - Sfio_t *f; - Void_t *buf; - size_t size; - Sfdisc_t *disc; -# else /* SFIO */ +/* ARGSUSED2 */ static int -tls_read(disc, buf, size) - void *disc; - char *buf; - int size; -# endif /* SFIO */ +tls_getinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; { - int r; - Tlsdisc_t *sd; + struct tls_obj *so = (struct tls_obj *) fp->f_cookie; - /* Cast back to correct type */ - sd = (Tlsdisc_t *) disc; - - r = SSL_read(sd->con, (char *) buf, size); - if (r < 0 && LogLevel > 7) + switch (what) { - char *err; + case SM_IO_WHAT_FD: + if (so->fp == NULL) + return -1; + return so->fp->f_file; /* for stdio fileno() compatability */ + + case SM_IO_IS_READABLE: + return SSL_pending(so->con) > 0; + + default: + return -1; + } +} - err = NULL; - switch (SSL_get_error(sd->con, r)) - { - case SSL_ERROR_NONE: - break; - case SSL_ERROR_WANT_WRITE: - err = "write W BLOCK"; - break; - case SSL_ERROR_WANT_READ: - err = "write R BLOCK"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: - err = "write X BLOCK"; - break; - case SSL_ERROR_ZERO_RETURN: - break; - case SSL_ERROR_SYSCALL: - err = "syscall error"; /* - get_last_socket_error()); +** TLS_OPEN -- creates the tls specific information for opening a +** file of the tls type. +** +** Parameters: +** fp -- the file pointer associated with the new open +** info -- the sm_io file pointer holding the open and the +** TLS encryption connection to be read from or written to +** flags -- ignored +** rpool -- ignored +** +** Returns: +** 0 on success */ - break; - case SSL_ERROR_SSL: - err = "generic SSL error"; - break; - } - if (err != NULL) - sm_syslog(LOG_WARNING, NOQID, "TLS: read error: %s", - err); + +static int tls_open __P((SM_FILE_T *, const void *, int, const void *)); + +/* ARGSUSED2 */ +static int +tls_open(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + struct tls_obj *so; + struct tls_info *ti = (struct tls_info *) info; + + so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj)); + so->fp = ti->fp; + so->con = ti->con; + + /* + ** We try to get the "raw" file descriptor that TLS uses to + ** do the actual read/write with. This is to allow us control + ** over the file descriptor being a blocking or non-blocking type. + ** Under the covers TLS handles the change and this allows us + ** to do timeouts with sm_io. + */ + + fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL); + (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0); + fp->f_cookie = so; + return 0; +} + +/* +** TLS_CLOSE -- close the tls specific parts of the tls file pointer +** +** Parameters: +** fp -- the file pointer to close +** +** Returns: +** 0 on success +*/ + +static int tls_close __P((SM_FILE_T *)); + +static int +tls_close(fp) + SM_FILE_T *fp; +{ + struct tls_obj *so; + + so = (struct tls_obj *) fp->f_cookie; + if (so->fp != NULL) + { + sm_io_close(so->fp, SM_TIME_DEFAULT); + so->fp = NULL; } - return r; + sm_free(so); + so = NULL; + return 0; } -# if SFIO +/* maximum number of retries for TLS related I/O due to handshakes */ +# define MAX_TLS_IOS 4 + +/* +** TLS_READ -- read secured information for the caller +** +** Parameters: +** fp -- the file pointer +** buf -- the location to place the data +** size -- the number of bytes to read from connection +** +** Results: +** -1 on error +** otherwise the number of bytes read +*/ + +static ssize_t tls_read __P((SM_FILE_T *, char *, size_t)); + static ssize_t -tls_write(f, buf, size, disc) - Sfio_t *f; - const Void_t *buf; +tls_read(fp, buf, size) + SM_FILE_T *fp; + char *buf; size_t size; - Sfdisc_t *disc; -# else /* SFIO */ -static int -tls_write(disc, buf, size) - void *disc; - const char *buf; - int size; -# endif /* SFIO */ { int r; - Tlsdisc_t *sd; + static int again = MAX_TLS_IOS; + struct tls_obj *so = (struct tls_obj *) fp->f_cookie; + char *err; - /* Cast back to correct type */ - sd = (Tlsdisc_t *) disc; + r = SSL_read(so->con, (char *) buf, size); - r = SSL_write(sd->con, (char *)buf, size); - if (r < 0 && LogLevel > 7) + if (r > 0) { - char *err; + again = MAX_TLS_IOS; + return r; + } - err = NULL; - switch (SSL_get_error(sd->con, r)) - { - case SSL_ERROR_NONE: - break; - case SSL_ERROR_WANT_WRITE: - err = "write W BLOCK"; - break; - case SSL_ERROR_WANT_READ: - err = "write R BLOCK"; - break; - case SSL_ERROR_WANT_X509_LOOKUP: - err = "write X BLOCK"; - break; - case SSL_ERROR_ZERO_RETURN: - break; - case SSL_ERROR_SYSCALL: - err = "syscall error"; -/* - get_last_socket_error()); -*/ - break; - case SSL_ERROR_SSL: - err = "generic SSL error"; + err = NULL; + switch (SSL_get_error(so->con, r)) + { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + again = MAX_TLS_IOS; + break; + case SSL_ERROR_WANT_WRITE: + if (--again <= 0) + err = "read W BLOCK"; + else + errno = EAGAIN; + break; + case SSL_ERROR_WANT_READ: + if (--again <= 0) + err = "read R BLOCK"; + else + errno = EAGAIN; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + err = "write X BLOCK"; + break; + case SSL_ERROR_SYSCALL: + if (r == 0 && errno == 0) /* out of protocol EOF found */ + break; + err = "syscall error"; /* - ERR_GET_REASON(ERR_peek_error())); + get_last_socket_error()); */ - break; - } - if (err != NULL) - sm_syslog(LOG_WARNING, NOQID, "TLS: write error: %s", - err); + break; + case SSL_ERROR_SSL: + err = "generic SSL error"; + if (LogLevel > 9) + tlslogerr("read"); + break; + } + if (err != NULL) + { + again = MAX_TLS_IOS; + if (errno == 0) + errno = EIO; + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: read error=%s (%d)", err, r); } return r; } -# if !SFIO -static int -tls_close(cookie) - void *cookie; +/* +** TLS_WRITE -- write information out through secure connection +** +** Parameters: +** fp -- the file pointer +** buf -- holds the data to be securely written +** size -- the number of bytes to write +** +** Returns: +** -1 on error +** otherwise number of bytes written +*/ + +static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t)); + +static ssize_t +tls_write(fp, buf, size) + SM_FILE_T *fp; + const char *buf; + size_t size; { - int retval = 0; - Tlsdisc_t *tc; + int r; + static int again = MAX_TLS_IOS; + struct tls_obj *so = (struct tls_obj *) fp->f_cookie; + char *err; - /* Cast back to correct type */ - tc = (Tlsdisc_t *)cookie; + r = SSL_write(so->con, (char *) buf, size); - if (tc->fp != NULL) + if (r > 0) { - retval = fclose(tc->fp); - tc->fp = NULL; + again = MAX_TLS_IOS; + return r; } - - sm_free(tc); - return retval; + err = NULL; + switch (SSL_get_error(so->con, r)) + { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + again = MAX_TLS_IOS; + break; + case SSL_ERROR_WANT_WRITE: + if (--again <= 0) + err = "write W BLOCK"; + else + errno = EAGAIN; + break; + case SSL_ERROR_WANT_READ: + if (--again <= 0) + err = "write R BLOCK"; + else + errno = EAGAIN; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + err = "write X BLOCK"; + break; + case SSL_ERROR_SYSCALL: + if (r == 0 && errno == 0) /* out of protocol EOF found */ + break; + err = "syscall error"; +/* + get_last_socket_error()); +*/ + break; + case SSL_ERROR_SSL: + err = "generic SSL error"; +/* + ERR_GET_REASON(ERR_peek_error())); +*/ + if (LogLevel > 9) + tlslogerr("write"); + break; + } + if (err != NULL) + { + again = MAX_TLS_IOS; + if (errno == 0) + errno = EIO; + if (LogLevel > 7) + sm_syslog(LOG_WARNING, NOQID, + "STARTTLS: write error=%s (%d)", err, r); + } + return r; } -# endif /* !SFIO */ + +/* +** SFDCTLS -- create tls file type and open in and out file pointers +** for sendmail to read from and write to. +** +** Parameters: +** fin -- data input source being replaced +** fout -- data output source being replaced +** conn -- the tls connection pointer +** +** Returns: +** -1 on error +** 0 on success +** +** Side effects: +** The arguments "fin" and "fout" are replaced with the new +** SM_FILE_T pointers. +** The original "fin" and "fout" are preserved in the tls file +** type but are not actually used because of the design of TLS. +*/ int sfdctls(fin, fout, con) -# if SFIO - Sfio_t *fin; - Sfio_t *fout; -# else /* SFIO */ - FILE **fin; - FILE **fout; -# endif /* SFIO */ + SM_FILE_T **fin; + SM_FILE_T **fout; SSL *con; { - Tlsdisc_t *tlsin, *tlsout; -# if !SFIO - FILE *fp; -# else /* !SFIO */ - int rfd, wfd; -# endif /* !SFIO */ - - if (con == NULL) - return 0; - - tlsin = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t)); - tlsout = (Tlsdisc_t *) xalloc(sizeof(Tlsdisc_t)); -# if SFIO - tlsin->disc.readf = tls_read; - tlsin->disc.writef = tls_write; - tlsin->disc.seekf = NULL; - tlsin->disc.exceptf = NULL; - tlsin->con = con; - - tlsout->disc.readf = tls_read; - tlsout->disc.writef = tls_write; - tlsout->disc.seekf = NULL; - tlsout->disc.exceptf = NULL; - tlsout->con = con; - - rfd = fileno(fin); - wfd = fileno(fout); - if (rfd < 0 || wfd < 0 || - SSL_set_rfd(con, rfd) <= 0 || SSL_set_wfd(con, wfd) <= 0) - { - sm_free(tlsin); - sm_free(tlsout); - return -1; - } - if (sfdisc(fin, (Sfdisc_t *) tlsin) != (Sfdisc_t *) tlsin || - sfdisc(fout, (Sfdisc_t *) tlsout) != (Sfdisc_t *) tlsout) - { - sm_free(tlsin); - sm_free(tlsout); + SM_FILE_T *tlsin, *tlsout; + SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close, + tls_read, tls_write, NULL, tls_getinfo, NULL, + SM_TIME_FOREVER); + struct tls_info info; + + SM_ASSERT(con != NULL); + + SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close, + tls_read, tls_write, NULL, tls_getinfo, NULL, + SM_TIME_FOREVER); + info.fp = *fin; + info.con = con; + tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY, + NULL); + if (tlsin == NULL) return -1; - } -# else /* SFIO */ - tlsin->fp = *fin; - tlsin->con = con; - fp = funopen(tlsin, tls_read, tls_write, NULL, tls_close); - if (fp == NULL) - { - sm_free(tlsin); - return -1; - } - *fin = fp; - tlsout->fp = *fout; - tlsout->con = con; - fp = funopen(tlsout, tls_read, tls_write, NULL, tls_close); - if (fp == NULL) + info.fp = *fout; + tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY, + NULL); + if (tlsout == NULL) { - FILE *save; - - /* Hack: Don't close underlying fp */ - save = tlsin->fp; - tlsin->fp = NULL; - fclose(*fin); - *fin = save; - sm_free(tlsout); + (void) sm_io_close(tlsin, SM_TIME_DEFAULT); return -1; } - *fout = fp; - SSL_set_rfd(con, fileno(tlsin->fp)); - SSL_set_wfd(con, fileno(tlsout->fp)); -# endif /* SFIO */ + sm_io_automode(tlsin, tlsout); + + *fin = tlsin; + *fout = tlsout; return 0; } -#endif /* STARTTLS && (SFIO || _FFR_TLS_TOREK) */ +#endif /* STARTTLS */ |