summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/sfsasl.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/sfsasl.c')
-rw-r--r--contrib/sendmail/src/sfsasl.c952
1 files changed, 0 insertions, 952 deletions
diff --git a/contrib/sendmail/src/sfsasl.c b/contrib/sendmail/src/sfsasl.c
deleted file mode 100644
index 216d87e..0000000
--- a/contrib/sendmail/src/sfsasl.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * Copyright (c) 1999-2006 Sendmail, Inc. and its suppliers.
- * All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- */
-
-#include <sm/gen.h>
-SM_RCSID("@(#)$Id: sfsasl.c,v 8.115 2006/04/18 21:34:07 ca Exp $")
-#include <stdlib.h>
-#include <sendmail.h>
-#include <sm/time.h>
-#include <errno.h>
-
-/* allow to disable error handling code just in case... */
-#ifndef DEAL_WITH_ERROR_SSL
-# define DEAL_WITH_ERROR_SSL 1
-#endif /* ! DEAL_WITH_ERROR_SSL */
-
-#if SASL
-# 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;
-};
-
-/*
-** 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).
-*/
-
-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));
- if (so == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
- 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 == NULL)
- return 0;
- 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 */
-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(fp, buf, size)
- SM_FILE_T *fp;
- char *buf;
- size_t size;
-{
- int result;
- ssize_t len;
-# if SASL >= 20000
- static const char *outbuf = NULL;
-# else /* SASL >= 20000 */
- static char *outbuf = NULL;
-# endif /* SASL >= 20000 */
- static unsigned int outlen = 0;
- static unsigned int offset = 0;
- struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
-
- /*
- ** sasl_decode() may require more data than a single read() returns.
- ** Hence we have to put a loop around the decoding.
- ** This also requires that we may have to split up the returned
- ** data since it might be larger than the allowed size.
- ** Therefore we use a static pointer and return portions of it
- ** if necessary.
- ** XXX Note: This function is not thread-safe nor can it be used
- ** on more than one file. A correct implementation would store
- ** this data in fp->f_cookie.
- */
-
-# if SASL >= 20000
- while (outlen == 0)
-# else /* SASL >= 20000 */
- while (outbuf == NULL && outlen == 0)
-# endif /* SASL >= 20000 */
- {
- len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
- if (len <= 0)
- return len;
- result = sasl_decode(so->conn, buf,
- (unsigned int) len, &outbuf, &outlen);
- if (result != SASL_OK)
- {
- if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "AUTH: sasl_decode error=%d", result);
- outbuf = NULL;
- offset = 0;
- outlen = 0;
- return -1;
- }
- }
-
- if (outbuf == NULL)
- {
- /* 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
- {
- /* return the rest of the buffer */
- len = outlen - offset;
- (void) memcpy(buf, outbuf + offset, (size_t) len);
-# if SASL < 20000
- SASL_DEALLOC(outbuf);
-# endif /* SASL < 20000 */
- outbuf = NULL;
- offset = 0;
- outlen = 0;
- }
- 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(fp, buf, size)
- SM_FILE_T *fp;
- const char *buf;
- size_t size;
-{
- int result;
-# if SASL >= 20000
- const char *outbuf;
-# else /* SASL >= 20000 */
- char *outbuf;
-# endif /* SASL >= 20000 */
- unsigned int outlen, *maxencode;
- size_t ret = 0, total = 0;
- struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
-
- /*
- ** Fetch the maximum input buffer size for sasl_encode().
- ** This can be less than the size set in attemptauth()
- ** due to a negotation with the other side, e.g.,
- ** Cyrus IMAP lmtp program sets maxbuf=4096,
- ** digestmd5 substracts 25 and hence we'll get 4071
- ** instead of 8192 (MAXOUTLEN).
- ** Hack (for now): simply reduce the size, callers are (must be)
- ** able to deal with that and invoke sasl_write() again with
- ** the rest of the data.
- ** Note: it would be better to store this value in the context
- ** after the negotiation.
- */
-
- result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
- (const void **) &maxencode);
- if (result == SASL_OK && size > *maxencode && *maxencode > 0)
- size = *maxencode;
-
- result = sasl_encode(so->conn, buf,
- (unsigned int) size, &outbuf, &outlen);
-
- if (result != SASL_OK)
- {
- if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "AUTH: sasl_encode error=%d", result);
- return -1;
- }
-
- if (outbuf != NULL)
- {
- while (outlen > 0)
- {
- errno = 0;
- /* XXX result == 0? */
- ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
- &outbuf[total], outlen);
- if (ret <= 0)
- return ret;
- outlen -= ret;
- total += ret;
- }
-# if SASL < 20000
- SASL_DEALLOC(outbuf);
-# endif /* SASL < 20000 */
- }
- 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 written to
-** conn -- the sasl connection pointer
-** tmo -- timeout
-**
-** 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, tmo)
- SM_FILE_T **fin;
- SM_FILE_T **fout;
- sasl_conn_t *conn;
- int tmo;
-{
- 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_DEFAULT);
- struct sasl_info info;
-
- if (conn == NULL)
- {
- /* no need to do anything */
- return 0;
- }
-
- SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
- sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
- SM_TIME_DEFAULT);
- info.fp = *fin;
- info.conn = conn;
- newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
- SM_IO_RDONLY_B, NULL);
-
- if (newin == NULL)
- return -1;
-
- info.fp = *fout;
- info.conn = conn;
- newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
- SM_IO_WRONLY_B, NULL);
-
- if (newout == NULL)
- {
- (void) sm_io_close(newin, SM_TIME_DEFAULT);
- return -1;
- }
- sm_io_automode(newin, newout);
-
- sm_io_setinfo(*fin, SM_IO_WHAT_TIMEOUT, &tmo);
- sm_io_setinfo(*fout, SM_IO_WHAT_TIMEOUT, &tmo);
-
- *fin = newin;
- *fout = newout;
- return 0;
-}
-#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;
-};
-
-/*
-** 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).
-*/
-
-static int tls_getinfo __P((SM_FILE_T *, int, void *));
-
-/* ARGSUSED2 */
-static int
-tls_getinfo(fp, what, valp)
- SM_FILE_T *fp;
- int what;
- void *valp;
-{
- struct tls_obj *so = (struct tls_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:
- return SSL_pending(so->con) > 0;
-
- default:
- return -1;
- }
-}
-
-/*
-** 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
-*/
-
-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));
- if (so == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
- 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 == NULL)
- return 0;
- if (so->fp != NULL)
- {
- sm_io_close(so->fp, SM_TIME_DEFAULT);
- so->fp = NULL;
- }
- sm_free(so);
- so = NULL;
- return 0;
-}
-
-/* maximum number of retries for TLS related I/O due to handshakes */
-# define MAX_TLS_IOS 4
-
-/*
-** TLS_RETRY -- check whether a failed SSL operation can be retried
-**
-** Parameters:
-** ssl -- TLS structure
-** rfd -- read fd
-** wfd -- write fd
-** tlsstart -- start time of TLS operation
-** timeout -- timeout for TLS operation
-** err -- SSL error
-** where -- description of operation
-**
-** Results:
-** >0 on success
-** 0 on timeout
-** <0 on error
-*/
-
-int
-tls_retry(ssl, rfd, wfd, tlsstart, timeout, err, where)
- SSL *ssl;
- int rfd;
- int wfd;
- time_t tlsstart;
- int timeout;
- int err;
- const char *where;
-{
- int ret;
- time_t left;
- time_t now = curtime();
- struct timeval tv;
-
- ret = -1;
-
- /*
- ** For SSL_ERROR_WANT_{READ,WRITE}:
- ** There is not a complete SSL record available yet
- ** or there is only a partial SSL record removed from
- ** the network (socket) buffer into the SSL buffer.
- ** The SSL_connect will only succeed when a full
- ** SSL record is available (assuming a "real" error
- ** doesn't happen). To handle when a "real" error
- ** does happen the select is set for exceptions too.
- ** The connection may be re-negotiated during this time
- ** so both read and write "want errors" need to be handled.
- ** A select() exception loops back so that a proper SSL
- ** error message can be gotten.
- */
-
- left = timeout - (now - tlsstart);
- if (left <= 0)
- return 0; /* timeout */
- tv.tv_sec = left;
- tv.tv_usec = 0;
-
- if (LogLevel > 14)
- {
- sm_syslog(LOG_INFO, NOQID,
- "STARTTLS=%s, info: fds=%d/%d, err=%d",
- where, rfd, wfd, err);
- }
-
- if (FD_SETSIZE > 0 &&
- ((err == SSL_ERROR_WANT_READ && rfd >= FD_SETSIZE) ||
- (err == SSL_ERROR_WANT_WRITE && wfd >= FD_SETSIZE)))
- {
- if (LogLevel > 5)
- {
- sm_syslog(LOG_ERR, NOQID,
- "STARTTLS=%s, error: fd %d/%d too large",
- where, rfd, wfd);
- if (LogLevel > 8)
- tlslogerr(where);
- }
- errno = EINVAL;
- }
- else if (err == SSL_ERROR_WANT_READ)
- {
- fd_set ssl_maskr, ssl_maskx;
-
- FD_ZERO(&ssl_maskr);
- FD_SET(rfd, &ssl_maskr);
- FD_ZERO(&ssl_maskx);
- FD_SET(rfd, &ssl_maskx);
- do
- {
- ret = select(rfd + 1, &ssl_maskr, NULL, &ssl_maskx,
- &tv);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0 && errno > 0)
- ret = -errno;
- }
- else if (err == SSL_ERROR_WANT_WRITE)
- {
- fd_set ssl_maskw, ssl_maskx;
-
- FD_ZERO(&ssl_maskw);
- FD_SET(wfd, &ssl_maskw);
- FD_ZERO(&ssl_maskx);
- FD_SET(rfd, &ssl_maskx);
- do
- {
- ret = select(wfd + 1, NULL, &ssl_maskw, &ssl_maskx,
- &tv);
- } while (ret < 0 && errno == EINTR);
- if (ret < 0 && errno > 0)
- ret = -errno;
- }
- return ret;
-}
-
-/* errno to force refill() etc to stop (see IS_IO_ERROR()) */
-#ifdef ETIMEDOUT
-# define SM_ERR_TIMEOUT ETIMEDOUT
-#else /* ETIMEDOUT */
-# define SM_ERR_TIMEOUT EIO
-#endif /* ETIMEDOUT */
-
-/*
-** 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_read(fp, buf, size)
- SM_FILE_T *fp;
- char *buf;
- size_t size;
-{
- int r, rfd, wfd, try, ssl_err;
- struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
- time_t tlsstart;
- char *err;
-
- try = 99;
- err = NULL;
- tlsstart = curtime();
-
- retry:
- r = SSL_read(so->con, (char *) buf, size);
-
- if (r > 0)
- return r;
-
- err = NULL;
- switch (ssl_err = SSL_get_error(so->con, r))
- {
- case SSL_ERROR_NONE:
- case SSL_ERROR_ZERO_RETURN:
- break;
- case SSL_ERROR_WANT_WRITE:
- err = "read W BLOCK";
- /* FALLTHROUGH */
- case SSL_ERROR_WANT_READ:
- if (err == NULL)
- err = "read R BLOCK";
- rfd = SSL_get_rfd(so->con);
- wfd = SSL_get_wfd(so->con);
- try = tls_retry(so->con, rfd, wfd, tlsstart,
- TimeOuts.to_datablock, ssl_err, "read");
- if (try > 0)
- goto retry;
- errno = SM_ERR_TIMEOUT;
- 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:
-#if DEAL_WITH_ERROR_SSL
- if (r == 0 && errno == 0) /* out of protocol EOF found */
- break;
-#endif /* DEAL_WITH_ERROR_SSL */
- err = "generic SSL error";
- if (LogLevel > 9)
- tlslogerr("read");
-
-#if DEAL_WITH_ERROR_SSL
- /* avoid repeated calls? */
- if (r == 0)
- r = -1;
-#endif /* DEAL_WITH_ERROR_SSL */
- break;
- }
- if (err != NULL)
- {
- int save_errno;
-
- save_errno = (errno == 0) ? EIO : errno;
- if (try == 0 && save_errno == SM_ERR_TIMEOUT)
- {
- if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: read error=timeout");
- }
- else if (LogLevel > 8)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: read error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
- err, r, errno,
- ERR_error_string(ERR_get_error(), NULL), try,
- ssl_err);
- else if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: read error=%s (%d), retry=%d, ssl_err=%d",
- err, r, errno, try, ssl_err);
- errno = save_errno;
- }
- return r;
-}
-
-/*
-** 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 r, rfd, wfd, try, ssl_err;
- struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
- time_t tlsstart;
- char *err;
-
- try = 99;
- err = NULL;
- tlsstart = curtime();
-
- retry:
- r = SSL_write(so->con, (char *) buf, size);
-
- if (r > 0)
- return r;
- err = NULL;
- switch (ssl_err = SSL_get_error(so->con, r))
- {
- case SSL_ERROR_NONE:
- case SSL_ERROR_ZERO_RETURN:
- break;
- case SSL_ERROR_WANT_WRITE:
- err = "read W BLOCK";
- /* FALLTHROUGH */
- case SSL_ERROR_WANT_READ:
- if (err == NULL)
- err = "read R BLOCK";
- rfd = SSL_get_rfd(so->con);
- wfd = SSL_get_wfd(so->con);
- try = tls_retry(so->con, rfd, wfd, tlsstart,
- DATA_PROGRESS_TIMEOUT, ssl_err, "write");
- if (try > 0)
- goto retry;
- errno = SM_ERR_TIMEOUT;
- 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");
-
-#if DEAL_WITH_ERROR_SSL
- /* avoid repeated calls? */
- if (r == 0)
- r = -1;
-#endif /* DEAL_WITH_ERROR_SSL */
- break;
- }
- if (err != NULL)
- {
- int save_errno;
-
- save_errno = (errno == 0) ? EIO : errno;
- if (try == 0 && save_errno == SM_ERR_TIMEOUT)
- {
- if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: write error=timeout");
- }
- else if (LogLevel > 8)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: write error=%s (%d), errno=%d, get_error=%s, retry=%d, ssl_err=%d",
- err, r, errno,
- ERR_error_string(ERR_get_error(), NULL), try,
- ssl_err);
- else if (LogLevel > 7)
- sm_syslog(LOG_WARNING, NOQID,
- "STARTTLS: write error=%s (%d), errno=%d, retry=%d, ssl_err=%d",
- err, r, errno, try, ssl_err);
- errno = save_errno;
- }
- return r;
-}
-
-/*
-** 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
-** con -- 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)
- SM_FILE_T **fin;
- SM_FILE_T **fout;
- SSL *con;
-{
- 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_B,
- NULL);
- if (tlsin == NULL)
- return -1;
-
- info.fp = *fout;
- tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
- NULL);
- if (tlsout == NULL)
- {
- (void) sm_io_close(tlsin, SM_TIME_DEFAULT);
- return -1;
- }
- sm_io_automode(tlsin, tlsout);
-
- *fin = tlsin;
- *fout = tlsout;
- return 0;
-}
-#endif /* STARTTLS */
OpenPOWER on IntegriCloud