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