155714Skris/* ssl/bio_ssl.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296341Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296341Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296341Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296341Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296341Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include <stdlib.h> 6155714Skris#include <string.h> 6255714Skris#include <errno.h> 6355714Skris#include <openssl/crypto.h> 6455714Skris#include <openssl/bio.h> 6555714Skris#include <openssl/err.h> 6655714Skris#include <openssl/ssl.h> 6755714Skris 6868651Skrisstatic int ssl_write(BIO *h, const char *buf, int num); 6968651Skrisstatic int ssl_read(BIO *h, char *buf, int size); 7068651Skrisstatic int ssl_puts(BIO *h, const char *str); 7168651Skrisstatic long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); 7255714Skrisstatic int ssl_new(BIO *h); 7355714Skrisstatic int ssl_free(BIO *data); 7468651Skrisstatic long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 75296341Sdelphijtypedef struct bio_ssl_st { 76296341Sdelphij SSL *ssl; /* The ssl handle :-) */ 77296341Sdelphij /* re-negotiate every time the total number of bytes is this size */ 78296341Sdelphij int num_renegotiates; 79296341Sdelphij unsigned long renegotiate_count; 80296341Sdelphij unsigned long byte_count; 81296341Sdelphij unsigned long renegotiate_timeout; 82296341Sdelphij unsigned long last_time; 83296341Sdelphij} BIO_SSL; 8455714Skris 85296341Sdelphijstatic BIO_METHOD methods_sslp = { 86296341Sdelphij BIO_TYPE_SSL, "ssl", 87296341Sdelphij ssl_write, 88296341Sdelphij ssl_read, 89296341Sdelphij ssl_puts, 90296341Sdelphij NULL, /* ssl_gets, */ 91296341Sdelphij ssl_ctrl, 92296341Sdelphij ssl_new, 93296341Sdelphij ssl_free, 94296341Sdelphij ssl_callback_ctrl, 95296341Sdelphij}; 9655714Skris 9755714SkrisBIO_METHOD *BIO_f_ssl(void) 98296341Sdelphij{ 99296341Sdelphij return (&methods_sslp); 100296341Sdelphij} 10155714Skris 10255714Skrisstatic int ssl_new(BIO *bi) 103296341Sdelphij{ 104296341Sdelphij BIO_SSL *bs; 10555714Skris 106296341Sdelphij bs = (BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); 107296341Sdelphij if (bs == NULL) { 108296341Sdelphij BIOerr(BIO_F_SSL_NEW, ERR_R_MALLOC_FAILURE); 109296341Sdelphij return (0); 110296341Sdelphij } 111296341Sdelphij memset(bs, 0, sizeof(BIO_SSL)); 112296341Sdelphij bi->init = 0; 113296341Sdelphij bi->ptr = (char *)bs; 114296341Sdelphij bi->flags = 0; 115296341Sdelphij return (1); 116296341Sdelphij} 11755714Skris 11855714Skrisstatic int ssl_free(BIO *a) 119296341Sdelphij{ 120296341Sdelphij BIO_SSL *bs; 12155714Skris 122296341Sdelphij if (a == NULL) 123296341Sdelphij return (0); 124296341Sdelphij bs = (BIO_SSL *)a->ptr; 125296341Sdelphij if (bs->ssl != NULL) 126296341Sdelphij SSL_shutdown(bs->ssl); 127296341Sdelphij if (a->shutdown) { 128296341Sdelphij if (a->init && (bs->ssl != NULL)) 129296341Sdelphij SSL_free(bs->ssl); 130296341Sdelphij a->init = 0; 131296341Sdelphij a->flags = 0; 132296341Sdelphij } 133296341Sdelphij if (a->ptr != NULL) 134296341Sdelphij OPENSSL_free(a->ptr); 135296341Sdelphij return (1); 136296341Sdelphij} 137296341Sdelphij 13855714Skrisstatic int ssl_read(BIO *b, char *out, int outl) 139296341Sdelphij{ 140296341Sdelphij int ret = 1; 141296341Sdelphij BIO_SSL *sb; 142296341Sdelphij SSL *ssl; 143296341Sdelphij int retry_reason = 0; 144296341Sdelphij int r = 0; 14555714Skris 146296341Sdelphij if (out == NULL) 147296341Sdelphij return (0); 148296341Sdelphij sb = (BIO_SSL *)b->ptr; 149296341Sdelphij ssl = sb->ssl; 15055714Skris 151296341Sdelphij BIO_clear_retry_flags(b); 15255714Skris 15355714Skris#if 0 154296341Sdelphij if (!SSL_is_init_finished(ssl)) { 155296341Sdelphij/* ret=SSL_do_handshake(ssl); */ 156296341Sdelphij if (ret > 0) { 15755714Skris 158296341Sdelphij outflags = (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY); 159296341Sdelphij ret = -1; 160296341Sdelphij goto end; 161296341Sdelphij } 162296341Sdelphij } 16355714Skris#endif 164296341Sdelphij/* if (ret > 0) */ 165296341Sdelphij ret = SSL_read(ssl, out, outl); 16655714Skris 167296341Sdelphij switch (SSL_get_error(ssl, ret)) { 168296341Sdelphij case SSL_ERROR_NONE: 169296341Sdelphij if (ret <= 0) 170296341Sdelphij break; 171296341Sdelphij if (sb->renegotiate_count > 0) { 172296341Sdelphij sb->byte_count += ret; 173296341Sdelphij if (sb->byte_count > sb->renegotiate_count) { 174296341Sdelphij sb->byte_count = 0; 175296341Sdelphij sb->num_renegotiates++; 176296341Sdelphij SSL_renegotiate(ssl); 177296341Sdelphij r = 1; 178296341Sdelphij } 179296341Sdelphij } 180296341Sdelphij if ((sb->renegotiate_timeout > 0) && (!r)) { 181296341Sdelphij unsigned long tm; 18255714Skris 183296341Sdelphij tm = (unsigned long)time(NULL); 184296341Sdelphij if (tm > sb->last_time + sb->renegotiate_timeout) { 185296341Sdelphij sb->last_time = tm; 186296341Sdelphij sb->num_renegotiates++; 187296341Sdelphij SSL_renegotiate(ssl); 188296341Sdelphij } 189296341Sdelphij } 19055714Skris 191296341Sdelphij break; 192296341Sdelphij case SSL_ERROR_WANT_READ: 193296341Sdelphij BIO_set_retry_read(b); 194296341Sdelphij break; 195296341Sdelphij case SSL_ERROR_WANT_WRITE: 196296341Sdelphij BIO_set_retry_write(b); 197296341Sdelphij break; 198296341Sdelphij case SSL_ERROR_WANT_X509_LOOKUP: 199296341Sdelphij BIO_set_retry_special(b); 200296341Sdelphij retry_reason = BIO_RR_SSL_X509_LOOKUP; 201296341Sdelphij break; 202296341Sdelphij case SSL_ERROR_WANT_ACCEPT: 203296341Sdelphij BIO_set_retry_special(b); 204296341Sdelphij retry_reason = BIO_RR_ACCEPT; 205296341Sdelphij break; 206296341Sdelphij case SSL_ERROR_WANT_CONNECT: 207296341Sdelphij BIO_set_retry_special(b); 208296341Sdelphij retry_reason = BIO_RR_CONNECT; 209296341Sdelphij break; 210296341Sdelphij case SSL_ERROR_SYSCALL: 211296341Sdelphij case SSL_ERROR_SSL: 212296341Sdelphij case SSL_ERROR_ZERO_RETURN: 213296341Sdelphij default: 214296341Sdelphij break; 215296341Sdelphij } 21655714Skris 217296341Sdelphij b->retry_reason = retry_reason; 218296341Sdelphij return (ret); 219296341Sdelphij} 22055714Skris 22168651Skrisstatic int ssl_write(BIO *b, const char *out, int outl) 222296341Sdelphij{ 223296341Sdelphij int ret, r = 0; 224296341Sdelphij int retry_reason = 0; 225296341Sdelphij SSL *ssl; 226296341Sdelphij BIO_SSL *bs; 22755714Skris 228296341Sdelphij if (out == NULL) 229296341Sdelphij return (0); 230296341Sdelphij bs = (BIO_SSL *)b->ptr; 231296341Sdelphij ssl = bs->ssl; 23255714Skris 233296341Sdelphij BIO_clear_retry_flags(b); 23455714Skris 235296341Sdelphij /* 236296341Sdelphij * ret=SSL_do_handshake(ssl); if (ret > 0) 237296341Sdelphij */ 238296341Sdelphij ret = SSL_write(ssl, out, outl); 23955714Skris 240296341Sdelphij switch (SSL_get_error(ssl, ret)) { 241296341Sdelphij case SSL_ERROR_NONE: 242296341Sdelphij if (ret <= 0) 243296341Sdelphij break; 244296341Sdelphij if (bs->renegotiate_count > 0) { 245296341Sdelphij bs->byte_count += ret; 246296341Sdelphij if (bs->byte_count > bs->renegotiate_count) { 247296341Sdelphij bs->byte_count = 0; 248296341Sdelphij bs->num_renegotiates++; 249296341Sdelphij SSL_renegotiate(ssl); 250296341Sdelphij r = 1; 251296341Sdelphij } 252296341Sdelphij } 253296341Sdelphij if ((bs->renegotiate_timeout > 0) && (!r)) { 254296341Sdelphij unsigned long tm; 25555714Skris 256296341Sdelphij tm = (unsigned long)time(NULL); 257296341Sdelphij if (tm > bs->last_time + bs->renegotiate_timeout) { 258296341Sdelphij bs->last_time = tm; 259296341Sdelphij bs->num_renegotiates++; 260296341Sdelphij SSL_renegotiate(ssl); 261296341Sdelphij } 262296341Sdelphij } 263296341Sdelphij break; 264296341Sdelphij case SSL_ERROR_WANT_WRITE: 265296341Sdelphij BIO_set_retry_write(b); 266296341Sdelphij break; 267296341Sdelphij case SSL_ERROR_WANT_READ: 268296341Sdelphij BIO_set_retry_read(b); 269296341Sdelphij break; 270296341Sdelphij case SSL_ERROR_WANT_X509_LOOKUP: 271296341Sdelphij BIO_set_retry_special(b); 272296341Sdelphij retry_reason = BIO_RR_SSL_X509_LOOKUP; 273296341Sdelphij break; 274296341Sdelphij case SSL_ERROR_WANT_CONNECT: 275296341Sdelphij BIO_set_retry_special(b); 276296341Sdelphij retry_reason = BIO_RR_CONNECT; 277296341Sdelphij case SSL_ERROR_SYSCALL: 278296341Sdelphij case SSL_ERROR_SSL: 279296341Sdelphij default: 280296341Sdelphij break; 281296341Sdelphij } 28255714Skris 283296341Sdelphij b->retry_reason = retry_reason; 284296341Sdelphij return (ret); 285296341Sdelphij} 28655714Skris 28768651Skrisstatic long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) 288296341Sdelphij{ 289296341Sdelphij SSL **sslp, *ssl; 290296341Sdelphij BIO_SSL *bs; 291296341Sdelphij BIO *dbio, *bio; 292296341Sdelphij long ret = 1; 29355714Skris 294296341Sdelphij bs = (BIO_SSL *)b->ptr; 295296341Sdelphij ssl = bs->ssl; 296296341Sdelphij if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) 297296341Sdelphij return (0); 298296341Sdelphij switch (cmd) { 299296341Sdelphij case BIO_CTRL_RESET: 300296341Sdelphij SSL_shutdown(ssl); 30155714Skris 302296341Sdelphij if (ssl->handshake_func == ssl->method->ssl_connect) 303296341Sdelphij SSL_set_connect_state(ssl); 304296341Sdelphij else if (ssl->handshake_func == ssl->method->ssl_accept) 305296341Sdelphij SSL_set_accept_state(ssl); 30655714Skris 307296341Sdelphij SSL_clear(ssl); 30855714Skris 309296341Sdelphij if (b->next_bio != NULL) 310296341Sdelphij ret = BIO_ctrl(b->next_bio, cmd, num, ptr); 311296341Sdelphij else if (ssl->rbio != NULL) 312296341Sdelphij ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 313296341Sdelphij else 314296341Sdelphij ret = 1; 315296341Sdelphij break; 316296341Sdelphij case BIO_CTRL_INFO: 317296341Sdelphij ret = 0; 318296341Sdelphij break; 319296341Sdelphij case BIO_C_SSL_MODE: 320296341Sdelphij if (num) /* client mode */ 321296341Sdelphij SSL_set_connect_state(ssl); 322296341Sdelphij else 323296341Sdelphij SSL_set_accept_state(ssl); 324296341Sdelphij break; 325296341Sdelphij case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: 326296341Sdelphij ret = bs->renegotiate_timeout; 327296341Sdelphij if (num < 60) 328296341Sdelphij num = 5; 329296341Sdelphij bs->renegotiate_timeout = (unsigned long)num; 330296341Sdelphij bs->last_time = (unsigned long)time(NULL); 331296341Sdelphij break; 332296341Sdelphij case BIO_C_SET_SSL_RENEGOTIATE_BYTES: 333296341Sdelphij ret = bs->renegotiate_count; 334296341Sdelphij if ((long)num >= 512) 335296341Sdelphij bs->renegotiate_count = (unsigned long)num; 336296341Sdelphij break; 337296341Sdelphij case BIO_C_GET_SSL_NUM_RENEGOTIATES: 338296341Sdelphij ret = bs->num_renegotiates; 339296341Sdelphij break; 340296341Sdelphij case BIO_C_SET_SSL: 341296341Sdelphij if (ssl != NULL) { 342296341Sdelphij ssl_free(b); 343296341Sdelphij if (!ssl_new(b)) 344296341Sdelphij return 0; 345296341Sdelphij } 346296341Sdelphij b->shutdown = (int)num; 347296341Sdelphij ssl = (SSL *)ptr; 348296341Sdelphij ((BIO_SSL *)b->ptr)->ssl = ssl; 349296341Sdelphij bio = SSL_get_rbio(ssl); 350296341Sdelphij if (bio != NULL) { 351296341Sdelphij if (b->next_bio != NULL) 352296341Sdelphij BIO_push(bio, b->next_bio); 353296341Sdelphij b->next_bio = bio; 354296341Sdelphij CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO); 355296341Sdelphij } 356296341Sdelphij b->init = 1; 357296341Sdelphij break; 358296341Sdelphij case BIO_C_GET_SSL: 359296341Sdelphij if (ptr != NULL) { 360296341Sdelphij sslp = (SSL **)ptr; 361296341Sdelphij *sslp = ssl; 362296341Sdelphij } else 363296341Sdelphij ret = 0; 364296341Sdelphij break; 365296341Sdelphij case BIO_CTRL_GET_CLOSE: 366296341Sdelphij ret = b->shutdown; 367296341Sdelphij break; 368296341Sdelphij case BIO_CTRL_SET_CLOSE: 369296341Sdelphij b->shutdown = (int)num; 370296341Sdelphij break; 371296341Sdelphij case BIO_CTRL_WPENDING: 372296341Sdelphij ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); 373296341Sdelphij break; 374296341Sdelphij case BIO_CTRL_PENDING: 375296341Sdelphij ret = SSL_pending(ssl); 376296341Sdelphij if (ret == 0) 377296341Sdelphij ret = BIO_pending(ssl->rbio); 378296341Sdelphij break; 379296341Sdelphij case BIO_CTRL_FLUSH: 380296341Sdelphij BIO_clear_retry_flags(b); 381296341Sdelphij ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); 382296341Sdelphij BIO_copy_next_retry(b); 383296341Sdelphij break; 384296341Sdelphij case BIO_CTRL_PUSH: 385296341Sdelphij if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) { 386296341Sdelphij SSL_set_bio(ssl, b->next_bio, b->next_bio); 387296341Sdelphij CRYPTO_add(&b->next_bio->references, 1, CRYPTO_LOCK_BIO); 388296341Sdelphij } 389296341Sdelphij break; 390296341Sdelphij case BIO_CTRL_POP: 391296341Sdelphij /* Only detach if we are the BIO explicitly being popped */ 392296341Sdelphij if (b == ptr) { 393296341Sdelphij /* 394296341Sdelphij * Shouldn't happen in practice because the rbio and wbio are the 395296341Sdelphij * same when pushed. 396296341Sdelphij */ 397296341Sdelphij if (ssl->rbio != ssl->wbio) 398296341Sdelphij BIO_free_all(ssl->wbio); 399296341Sdelphij if (b->next_bio != NULL) 400296341Sdelphij CRYPTO_add(&b->next_bio->references, -1, CRYPTO_LOCK_BIO); 401296341Sdelphij ssl->wbio = NULL; 402296341Sdelphij ssl->rbio = NULL; 403296341Sdelphij } 404296341Sdelphij break; 405296341Sdelphij case BIO_C_DO_STATE_MACHINE: 406296341Sdelphij BIO_clear_retry_flags(b); 40755714Skris 408296341Sdelphij b->retry_reason = 0; 409296341Sdelphij ret = (int)SSL_do_handshake(ssl); 41055714Skris 411296341Sdelphij switch (SSL_get_error(ssl, (int)ret)) { 412296341Sdelphij case SSL_ERROR_WANT_READ: 413296341Sdelphij BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY); 414296341Sdelphij break; 415296341Sdelphij case SSL_ERROR_WANT_WRITE: 416296341Sdelphij BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY); 417296341Sdelphij break; 418296341Sdelphij case SSL_ERROR_WANT_CONNECT: 419296341Sdelphij BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY); 420296341Sdelphij b->retry_reason = b->next_bio->retry_reason; 421296341Sdelphij break; 422296341Sdelphij default: 423296341Sdelphij break; 424296341Sdelphij } 425296341Sdelphij break; 426296341Sdelphij case BIO_CTRL_DUP: 427296341Sdelphij dbio = (BIO *)ptr; 428296341Sdelphij if (((BIO_SSL *)dbio->ptr)->ssl != NULL) 429296341Sdelphij SSL_free(((BIO_SSL *)dbio->ptr)->ssl); 430296341Sdelphij ((BIO_SSL *)dbio->ptr)->ssl = SSL_dup(ssl); 431296341Sdelphij ((BIO_SSL *)dbio->ptr)->renegotiate_count = 432296341Sdelphij ((BIO_SSL *)b->ptr)->renegotiate_count; 433296341Sdelphij ((BIO_SSL *)dbio->ptr)->byte_count = ((BIO_SSL *)b->ptr)->byte_count; 434296341Sdelphij ((BIO_SSL *)dbio->ptr)->renegotiate_timeout = 435296341Sdelphij ((BIO_SSL *)b->ptr)->renegotiate_timeout; 436296341Sdelphij ((BIO_SSL *)dbio->ptr)->last_time = ((BIO_SSL *)b->ptr)->last_time; 437296341Sdelphij ret = (((BIO_SSL *)dbio->ptr)->ssl != NULL); 438296341Sdelphij break; 439296341Sdelphij case BIO_C_GET_FD: 440296341Sdelphij ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 441296341Sdelphij break; 442296341Sdelphij case BIO_CTRL_SET_CALLBACK: 443296341Sdelphij { 444296341Sdelphij#if 0 /* FIXME: Should this be used? -- Richard 445296341Sdelphij * Levitte */ 446296341Sdelphij SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 447296341Sdelphij ret = -1; 44859191Skris#else 449296341Sdelphij ret = 0; 45059191Skris#endif 451296341Sdelphij } 452296341Sdelphij break; 453296341Sdelphij case BIO_CTRL_GET_CALLBACK: 454296341Sdelphij { 455296341Sdelphij void (**fptr) (const SSL *xssl, int type, int val); 45655714Skris 457296341Sdelphij fptr = (void (**)(const SSL *xssl, int type, int val))ptr; 458296341Sdelphij *fptr = SSL_get_info_callback(ssl); 459296341Sdelphij } 460296341Sdelphij break; 461296341Sdelphij default: 462296341Sdelphij ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 463296341Sdelphij break; 464296341Sdelphij } 465296341Sdelphij return (ret); 466296341Sdelphij} 46755714Skris 46868651Skrisstatic long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 469296341Sdelphij{ 470296341Sdelphij SSL *ssl; 471296341Sdelphij BIO_SSL *bs; 472296341Sdelphij long ret = 1; 47359191Skris 474296341Sdelphij bs = (BIO_SSL *)b->ptr; 475296341Sdelphij ssl = bs->ssl; 476296341Sdelphij switch (cmd) { 477296341Sdelphij case BIO_CTRL_SET_CALLBACK: 478296341Sdelphij { 479296341Sdelphij /* 480296341Sdelphij * FIXME: setting this via a completely different prototype seems 481296341Sdelphij * like a crap idea 482296341Sdelphij */ 483296341Sdelphij SSL_set_info_callback(ssl, (void (*)(const SSL *, int, int))fp); 484296341Sdelphij } 485296341Sdelphij break; 486296341Sdelphij default: 487296341Sdelphij ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); 488296341Sdelphij break; 489296341Sdelphij } 490296341Sdelphij return (ret); 491296341Sdelphij} 49259191Skris 49368651Skrisstatic int ssl_puts(BIO *bp, const char *str) 494296341Sdelphij{ 495296341Sdelphij int n, ret; 49655714Skris 497296341Sdelphij n = strlen(str); 498296341Sdelphij ret = BIO_write(bp, str, n); 499296341Sdelphij return (ret); 500296341Sdelphij} 50155714Skris 50255714SkrisBIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) 503296341Sdelphij{ 504111147Snectar#ifndef OPENSSL_NO_SOCK 505296341Sdelphij BIO *ret = NULL, *buf = NULL, *ssl = NULL; 50655714Skris 507296341Sdelphij if ((buf = BIO_new(BIO_f_buffer())) == NULL) 508296341Sdelphij return (NULL); 509296341Sdelphij if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) 510296341Sdelphij goto err; 511296341Sdelphij if ((ret = BIO_push(buf, ssl)) == NULL) 512296341Sdelphij goto err; 513296341Sdelphij return (ret); 514296341Sdelphij err: 515296341Sdelphij if (buf != NULL) 516296341Sdelphij BIO_free(buf); 517296341Sdelphij if (ssl != NULL) 518296341Sdelphij BIO_free(ssl); 519111147Snectar#endif 520296341Sdelphij return (NULL); 521296341Sdelphij} 52255714Skris 52355714SkrisBIO *BIO_new_ssl_connect(SSL_CTX *ctx) 524296341Sdelphij{ 525238405Sjkim#ifndef OPENSSL_NO_SOCK 526296341Sdelphij BIO *ret = NULL, *con = NULL, *ssl = NULL; 52755714Skris 528296341Sdelphij if ((con = BIO_new(BIO_s_connect())) == NULL) 529296341Sdelphij return (NULL); 530296341Sdelphij if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) 531296341Sdelphij goto err; 532296341Sdelphij if ((ret = BIO_push(ssl, con)) == NULL) 533296341Sdelphij goto err; 534296341Sdelphij return (ret); 535296341Sdelphij err: 536296341Sdelphij if (con != NULL) 537296341Sdelphij BIO_free(con); 538238405Sjkim#endif 539296341Sdelphij return (NULL); 540296341Sdelphij} 54155714Skris 54255714SkrisBIO *BIO_new_ssl(SSL_CTX *ctx, int client) 543296341Sdelphij{ 544296341Sdelphij BIO *ret; 545296341Sdelphij SSL *ssl; 54655714Skris 547296341Sdelphij if ((ret = BIO_new(BIO_f_ssl())) == NULL) 548296341Sdelphij return (NULL); 549296341Sdelphij if ((ssl = SSL_new(ctx)) == NULL) { 550296341Sdelphij BIO_free(ret); 551296341Sdelphij return (NULL); 552296341Sdelphij } 553296341Sdelphij if (client) 554296341Sdelphij SSL_set_connect_state(ssl); 555296341Sdelphij else 556296341Sdelphij SSL_set_accept_state(ssl); 55755714Skris 558296341Sdelphij BIO_set_ssl(ret, ssl, BIO_CLOSE); 559296341Sdelphij return (ret); 560296341Sdelphij} 561296341Sdelphij 56255714Skrisint BIO_ssl_copy_session_id(BIO *t, BIO *f) 563296341Sdelphij{ 564296341Sdelphij t = BIO_find_type(t, BIO_TYPE_SSL); 565296341Sdelphij f = BIO_find_type(f, BIO_TYPE_SSL); 566296341Sdelphij if ((t == NULL) || (f == NULL)) 567296341Sdelphij return (0); 568296341Sdelphij if ((((BIO_SSL *)t->ptr)->ssl == NULL) || 569296341Sdelphij (((BIO_SSL *)f->ptr)->ssl == NULL)) 570296341Sdelphij return (0); 571296341Sdelphij SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl, ((BIO_SSL *)f->ptr)->ssl); 572296341Sdelphij return (1); 573296341Sdelphij} 57455714Skris 57555714Skrisvoid BIO_ssl_shutdown(BIO *b) 576296341Sdelphij{ 577296341Sdelphij SSL *s; 57855714Skris 579296341Sdelphij while (b != NULL) { 580296341Sdelphij if (b->method->type == BIO_TYPE_SSL) { 581296341Sdelphij s = ((BIO_SSL *)b->ptr)->ssl; 582296341Sdelphij SSL_shutdown(s); 583296341Sdelphij break; 584296341Sdelphij } 585296341Sdelphij b = b->next_bio; 586296341Sdelphij } 587296341Sdelphij} 588