1e71b7053SJung-uk Kim /* 2*a7148ab3SEnji Cooper * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. 374664626SKris Kennaway * 4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 874664626SKris Kennaway */ 974664626SKris Kennaway 1074664626SKris Kennaway #include <stdio.h> 1174664626SKris Kennaway #include <stdlib.h> 1274664626SKris Kennaway #include <string.h> 1374664626SKris Kennaway #include <errno.h> 1474664626SKris Kennaway #include <openssl/crypto.h> 15e71b7053SJung-uk Kim #include "internal/bio.h" 1674664626SKris Kennaway #include <openssl/err.h> 1717f01e99SJung-uk Kim #include "ssl_local.h" 1874664626SKris Kennaway 19e71b7053SJung-uk Kim static int ssl_write(BIO *h, const char *buf, size_t size, size_t *written); 20e71b7053SJung-uk Kim static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes); 21ddd58736SKris Kennaway static int ssl_puts(BIO *h, const char *str); 22ddd58736SKris Kennaway static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); 2374664626SKris Kennaway static int ssl_new(BIO *h); 2474664626SKris Kennaway static int ssl_free(BIO *data); 25e71b7053SJung-uk Kim static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); 266f9291ceSJung-uk Kim typedef struct bio_ssl_st { 2774664626SKris Kennaway SSL *ssl; /* The ssl handle :-) */ 2874664626SKris Kennaway /* re-negotiate every time the total number of bytes is this size */ 2974664626SKris Kennaway int num_renegotiates; 3074664626SKris Kennaway unsigned long renegotiate_count; 31e71b7053SJung-uk Kim size_t byte_count; 3274664626SKris Kennaway unsigned long renegotiate_timeout; 3374664626SKris Kennaway unsigned long last_time; 3474664626SKris Kennaway } BIO_SSL; 3574664626SKris Kennaway 36e71b7053SJung-uk Kim static const BIO_METHOD methods_sslp = { 37e71b7053SJung-uk Kim BIO_TYPE_SSL, 38e71b7053SJung-uk Kim "ssl", 3974664626SKris Kennaway ssl_write, 40e71b7053SJung-uk Kim NULL, /* ssl_write_old, */ 4174664626SKris Kennaway ssl_read, 42e71b7053SJung-uk Kim NULL, /* ssl_read_old, */ 4374664626SKris Kennaway ssl_puts, 4474664626SKris Kennaway NULL, /* ssl_gets, */ 4574664626SKris Kennaway ssl_ctrl, 4674664626SKris Kennaway ssl_new, 4774664626SKris Kennaway ssl_free, 48f579bf8eSKris Kennaway ssl_callback_ctrl, 4974664626SKris Kennaway }; 5074664626SKris Kennaway 51e71b7053SJung-uk Kim const BIO_METHOD *BIO_f_ssl(void) 5274664626SKris Kennaway { 53e71b7053SJung-uk Kim return &methods_sslp; 5474664626SKris Kennaway } 5574664626SKris Kennaway 5674664626SKris Kennaway static int ssl_new(BIO *bi) 5774664626SKris Kennaway { 58e71b7053SJung-uk Kim BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs)); 5974664626SKris Kennaway 606f9291ceSJung-uk Kim if (bs == NULL) { 61b077aed3SPierre Pronchery ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 62e71b7053SJung-uk Kim return 0; 6374664626SKris Kennaway } 64e71b7053SJung-uk Kim BIO_set_init(bi, 0); 65e71b7053SJung-uk Kim BIO_set_data(bi, bs); 66e71b7053SJung-uk Kim /* Clear all flags */ 67e71b7053SJung-uk Kim BIO_clear_flags(bi, ~0); 68e71b7053SJung-uk Kim 69e71b7053SJung-uk Kim return 1; 7074664626SKris Kennaway } 7174664626SKris Kennaway 7274664626SKris Kennaway static int ssl_free(BIO *a) 7374664626SKris Kennaway { 7474664626SKris Kennaway BIO_SSL *bs; 7574664626SKris Kennaway 766f9291ceSJung-uk Kim if (a == NULL) 77e71b7053SJung-uk Kim return 0; 78e71b7053SJung-uk Kim bs = BIO_get_data(a); 79b2bf0c7eSJung-uk Kim if (BIO_get_shutdown(a)) { 80*a7148ab3SEnji Cooper if (bs->ssl != NULL && !SSL_in_init(bs->ssl)) 816f9291ceSJung-uk Kim SSL_shutdown(bs->ssl); 82e71b7053SJung-uk Kim if (BIO_get_init(a)) 8374664626SKris Kennaway SSL_free(bs->ssl); 84b2bf0c7eSJung-uk Kim BIO_clear_flags(a, ~0); /* Clear all flags */ 85e71b7053SJung-uk Kim BIO_set_init(a, 0); 8674664626SKris Kennaway } 87e71b7053SJung-uk Kim OPENSSL_free(bs); 88e71b7053SJung-uk Kim return 1; 8974664626SKris Kennaway } 9074664626SKris Kennaway 91e71b7053SJung-uk Kim static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes) 9274664626SKris Kennaway { 9374664626SKris Kennaway int ret = 1; 9474664626SKris Kennaway BIO_SSL *sb; 9574664626SKris Kennaway SSL *ssl; 9674664626SKris Kennaway int retry_reason = 0; 9774664626SKris Kennaway int r = 0; 9874664626SKris Kennaway 99e71b7053SJung-uk Kim if (buf == NULL) 100e71b7053SJung-uk Kim return 0; 101e71b7053SJung-uk Kim sb = BIO_get_data(b); 10274664626SKris Kennaway ssl = sb->ssl; 10374664626SKris Kennaway 10474664626SKris Kennaway BIO_clear_retry_flags(b); 10574664626SKris Kennaway 106e71b7053SJung-uk Kim ret = ssl_read_internal(ssl, buf, size, readbytes); 10774664626SKris Kennaway 1086f9291ceSJung-uk Kim switch (SSL_get_error(ssl, ret)) { 10974664626SKris Kennaway case SSL_ERROR_NONE: 1106f9291ceSJung-uk Kim if (sb->renegotiate_count > 0) { 111e71b7053SJung-uk Kim sb->byte_count += *readbytes; 1126f9291ceSJung-uk Kim if (sb->byte_count > sb->renegotiate_count) { 11374664626SKris Kennaway sb->byte_count = 0; 11474664626SKris Kennaway sb->num_renegotiates++; 11574664626SKris Kennaway SSL_renegotiate(ssl); 11674664626SKris Kennaway r = 1; 11774664626SKris Kennaway } 11874664626SKris Kennaway } 1196f9291ceSJung-uk Kim if ((sb->renegotiate_timeout > 0) && (!r)) { 12074664626SKris Kennaway unsigned long tm; 12174664626SKris Kennaway 12274664626SKris Kennaway tm = (unsigned long)time(NULL); 1236f9291ceSJung-uk Kim if (tm > sb->last_time + sb->renegotiate_timeout) { 12474664626SKris Kennaway sb->last_time = tm; 12574664626SKris Kennaway sb->num_renegotiates++; 12674664626SKris Kennaway SSL_renegotiate(ssl); 12774664626SKris Kennaway } 12874664626SKris Kennaway } 12974664626SKris Kennaway 13074664626SKris Kennaway break; 13174664626SKris Kennaway case SSL_ERROR_WANT_READ: 13274664626SKris Kennaway BIO_set_retry_read(b); 13374664626SKris Kennaway break; 13474664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 13574664626SKris Kennaway BIO_set_retry_write(b); 13674664626SKris Kennaway break; 13774664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 13874664626SKris Kennaway BIO_set_retry_special(b); 13974664626SKris Kennaway retry_reason = BIO_RR_SSL_X509_LOOKUP; 14074664626SKris Kennaway break; 1415c87c606SMark Murray case SSL_ERROR_WANT_ACCEPT: 1425c87c606SMark Murray BIO_set_retry_special(b); 1435c87c606SMark Murray retry_reason = BIO_RR_ACCEPT; 1445c87c606SMark Murray break; 14574664626SKris Kennaway case SSL_ERROR_WANT_CONNECT: 14674664626SKris Kennaway BIO_set_retry_special(b); 14774664626SKris Kennaway retry_reason = BIO_RR_CONNECT; 14874664626SKris Kennaway break; 14974664626SKris Kennaway case SSL_ERROR_SYSCALL: 15074664626SKris Kennaway case SSL_ERROR_SSL: 15174664626SKris Kennaway case SSL_ERROR_ZERO_RETURN: 15274664626SKris Kennaway default: 15374664626SKris Kennaway break; 15474664626SKris Kennaway } 15574664626SKris Kennaway 156e71b7053SJung-uk Kim BIO_set_retry_reason(b, retry_reason); 157e71b7053SJung-uk Kim 158e71b7053SJung-uk Kim return ret; 15974664626SKris Kennaway } 16074664626SKris Kennaway 161e71b7053SJung-uk Kim static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written) 16274664626SKris Kennaway { 16374664626SKris Kennaway int ret, r = 0; 16474664626SKris Kennaway int retry_reason = 0; 16574664626SKris Kennaway SSL *ssl; 16674664626SKris Kennaway BIO_SSL *bs; 16774664626SKris Kennaway 168e71b7053SJung-uk Kim if (buf == NULL) 169e71b7053SJung-uk Kim return 0; 170e71b7053SJung-uk Kim bs = BIO_get_data(b); 17174664626SKris Kennaway ssl = bs->ssl; 17274664626SKris Kennaway 17374664626SKris Kennaway BIO_clear_retry_flags(b); 17474664626SKris Kennaway 175e71b7053SJung-uk Kim ret = ssl_write_internal(ssl, buf, size, written); 17674664626SKris Kennaway 1776f9291ceSJung-uk Kim switch (SSL_get_error(ssl, ret)) { 17874664626SKris Kennaway case SSL_ERROR_NONE: 1796f9291ceSJung-uk Kim if (bs->renegotiate_count > 0) { 180e71b7053SJung-uk Kim bs->byte_count += *written; 1816f9291ceSJung-uk Kim if (bs->byte_count > bs->renegotiate_count) { 18274664626SKris Kennaway bs->byte_count = 0; 18374664626SKris Kennaway bs->num_renegotiates++; 18474664626SKris Kennaway SSL_renegotiate(ssl); 18574664626SKris Kennaway r = 1; 18674664626SKris Kennaway } 18774664626SKris Kennaway } 1886f9291ceSJung-uk Kim if ((bs->renegotiate_timeout > 0) && (!r)) { 18974664626SKris Kennaway unsigned long tm; 19074664626SKris Kennaway 19174664626SKris Kennaway tm = (unsigned long)time(NULL); 1926f9291ceSJung-uk Kim if (tm > bs->last_time + bs->renegotiate_timeout) { 19374664626SKris Kennaway bs->last_time = tm; 19474664626SKris Kennaway bs->num_renegotiates++; 19574664626SKris Kennaway SSL_renegotiate(ssl); 19674664626SKris Kennaway } 19774664626SKris Kennaway } 19874664626SKris Kennaway break; 19974664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 20074664626SKris Kennaway BIO_set_retry_write(b); 20174664626SKris Kennaway break; 20274664626SKris Kennaway case SSL_ERROR_WANT_READ: 20374664626SKris Kennaway BIO_set_retry_read(b); 20474664626SKris Kennaway break; 20574664626SKris Kennaway case SSL_ERROR_WANT_X509_LOOKUP: 20674664626SKris Kennaway BIO_set_retry_special(b); 20774664626SKris Kennaway retry_reason = BIO_RR_SSL_X509_LOOKUP; 20874664626SKris Kennaway break; 20974664626SKris Kennaway case SSL_ERROR_WANT_CONNECT: 21074664626SKris Kennaway BIO_set_retry_special(b); 21174664626SKris Kennaway retry_reason = BIO_RR_CONNECT; 21274664626SKris Kennaway case SSL_ERROR_SYSCALL: 21374664626SKris Kennaway case SSL_ERROR_SSL: 21474664626SKris Kennaway default: 21574664626SKris Kennaway break; 21674664626SKris Kennaway } 21774664626SKris Kennaway 218e71b7053SJung-uk Kim BIO_set_retry_reason(b, retry_reason); 219e71b7053SJung-uk Kim 220e71b7053SJung-uk Kim return ret; 22174664626SKris Kennaway } 22274664626SKris Kennaway 223ddd58736SKris Kennaway static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) 22474664626SKris Kennaway { 22574664626SKris Kennaway SSL **sslp, *ssl; 226e71b7053SJung-uk Kim BIO_SSL *bs, *dbs; 22774664626SKris Kennaway BIO *dbio, *bio; 22874664626SKris Kennaway long ret = 1; 229e71b7053SJung-uk Kim BIO *next; 23074664626SKris Kennaway 231e71b7053SJung-uk Kim bs = BIO_get_data(b); 232e71b7053SJung-uk Kim next = BIO_next(b); 23374664626SKris Kennaway ssl = bs->ssl; 23474664626SKris Kennaway if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) 235e71b7053SJung-uk Kim return 0; 2366f9291ceSJung-uk Kim switch (cmd) { 23774664626SKris Kennaway case BIO_CTRL_RESET: 23874664626SKris Kennaway SSL_shutdown(ssl); 23974664626SKris Kennaway 24074664626SKris Kennaway if (ssl->handshake_func == ssl->method->ssl_connect) 24174664626SKris Kennaway SSL_set_connect_state(ssl); 24274664626SKris Kennaway else if (ssl->handshake_func == ssl->method->ssl_accept) 24374664626SKris Kennaway SSL_set_accept_state(ssl); 24474664626SKris Kennaway 245e71b7053SJung-uk Kim if (!SSL_clear(ssl)) { 246e71b7053SJung-uk Kim ret = 0; 247e71b7053SJung-uk Kim break; 248e71b7053SJung-uk Kim } 24974664626SKris Kennaway 250e71b7053SJung-uk Kim if (next != NULL) 251e71b7053SJung-uk Kim ret = BIO_ctrl(next, cmd, num, ptr); 25274664626SKris Kennaway else if (ssl->rbio != NULL) 25374664626SKris Kennaway ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 25474664626SKris Kennaway else 25574664626SKris Kennaway ret = 1; 25674664626SKris Kennaway break; 25774664626SKris Kennaway case BIO_CTRL_INFO: 25874664626SKris Kennaway ret = 0; 25974664626SKris Kennaway break; 26074664626SKris Kennaway case BIO_C_SSL_MODE: 26174664626SKris Kennaway if (num) /* client mode */ 26274664626SKris Kennaway SSL_set_connect_state(ssl); 26374664626SKris Kennaway else 26474664626SKris Kennaway SSL_set_accept_state(ssl); 26574664626SKris Kennaway break; 26674664626SKris Kennaway case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: 26774664626SKris Kennaway ret = bs->renegotiate_timeout; 2686f9291ceSJung-uk Kim if (num < 60) 2696f9291ceSJung-uk Kim num = 5; 27074664626SKris Kennaway bs->renegotiate_timeout = (unsigned long)num; 27174664626SKris Kennaway bs->last_time = (unsigned long)time(NULL); 27274664626SKris Kennaway break; 27374664626SKris Kennaway case BIO_C_SET_SSL_RENEGOTIATE_BYTES: 27474664626SKris Kennaway ret = bs->renegotiate_count; 27574664626SKris Kennaway if ((long)num >= 512) 27674664626SKris Kennaway bs->renegotiate_count = (unsigned long)num; 27774664626SKris Kennaway break; 27874664626SKris Kennaway case BIO_C_GET_SSL_NUM_RENEGOTIATES: 27974664626SKris Kennaway ret = bs->num_renegotiates; 28074664626SKris Kennaway break; 28174664626SKris Kennaway case BIO_C_SET_SSL: 2826f9291ceSJung-uk Kim if (ssl != NULL) { 28374664626SKris Kennaway ssl_free(b); 28412de4ed2SJung-uk Kim if (!ssl_new(b)) 28512de4ed2SJung-uk Kim return 0; 28658f35182SJung-uk Kim bs = BIO_get_data(b); 28712de4ed2SJung-uk Kim } 288e71b7053SJung-uk Kim BIO_set_shutdown(b, num); 28974664626SKris Kennaway ssl = (SSL *)ptr; 290e71b7053SJung-uk Kim bs->ssl = ssl; 29174664626SKris Kennaway bio = SSL_get_rbio(ssl); 2926f9291ceSJung-uk Kim if (bio != NULL) { 293e71b7053SJung-uk Kim if (next != NULL) 294e71b7053SJung-uk Kim BIO_push(bio, next); 295e71b7053SJung-uk Kim BIO_set_next(b, bio); 296e71b7053SJung-uk Kim BIO_up_ref(bio); 29774664626SKris Kennaway } 298e71b7053SJung-uk Kim BIO_set_init(b, 1); 29974664626SKris Kennaway break; 30074664626SKris Kennaway case BIO_C_GET_SSL: 3016f9291ceSJung-uk Kim if (ptr != NULL) { 30274664626SKris Kennaway sslp = (SSL **)ptr; 30374664626SKris Kennaway *sslp = ssl; 3046f9291ceSJung-uk Kim } else 30574664626SKris Kennaway ret = 0; 30674664626SKris Kennaway break; 30774664626SKris Kennaway case BIO_CTRL_GET_CLOSE: 308e71b7053SJung-uk Kim ret = BIO_get_shutdown(b); 30974664626SKris Kennaway break; 31074664626SKris Kennaway case BIO_CTRL_SET_CLOSE: 311e71b7053SJung-uk Kim BIO_set_shutdown(b, (int)num); 31274664626SKris Kennaway break; 31374664626SKris Kennaway case BIO_CTRL_WPENDING: 31474664626SKris Kennaway ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); 31574664626SKris Kennaway break; 31674664626SKris Kennaway case BIO_CTRL_PENDING: 31774664626SKris Kennaway ret = SSL_pending(ssl); 31874664626SKris Kennaway if (ret == 0) 31974664626SKris Kennaway ret = BIO_pending(ssl->rbio); 32074664626SKris Kennaway break; 32174664626SKris Kennaway case BIO_CTRL_FLUSH: 32274664626SKris Kennaway BIO_clear_retry_flags(b); 32374664626SKris Kennaway ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); 32474664626SKris Kennaway BIO_copy_next_retry(b); 32574664626SKris Kennaway break; 32674664626SKris Kennaway case BIO_CTRL_PUSH: 327e71b7053SJung-uk Kim if ((next != NULL) && (next != ssl->rbio)) { 328e71b7053SJung-uk Kim /* 329e71b7053SJung-uk Kim * We are going to pass ownership of next to the SSL object...but 330e71b7053SJung-uk Kim * we don't own a reference to pass yet - so up ref 331e71b7053SJung-uk Kim */ 332e71b7053SJung-uk Kim BIO_up_ref(next); 333e71b7053SJung-uk Kim SSL_set_bio(ssl, next, next); 33474664626SKris Kennaway } 33574664626SKris Kennaway break; 33674664626SKris Kennaway case BIO_CTRL_POP: 3371f13597dSJung-uk Kim /* Only detach if we are the BIO explicitly being popped */ 3386f9291ceSJung-uk Kim if (b == ptr) { 339e71b7053SJung-uk Kim /* This will clear the reference we obtained during push */ 340e71b7053SJung-uk Kim SSL_set_bio(ssl, NULL, NULL); 3411f13597dSJung-uk Kim } 34274664626SKris Kennaway break; 34374664626SKris Kennaway case BIO_C_DO_STATE_MACHINE: 34474664626SKris Kennaway BIO_clear_retry_flags(b); 34574664626SKris Kennaway 346e71b7053SJung-uk Kim BIO_set_retry_reason(b, 0); 34774664626SKris Kennaway ret = (int)SSL_do_handshake(ssl); 34874664626SKris Kennaway 3496f9291ceSJung-uk Kim switch (SSL_get_error(ssl, (int)ret)) { 35074664626SKris Kennaway case SSL_ERROR_WANT_READ: 3516f9291ceSJung-uk Kim BIO_set_flags(b, BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY); 35274664626SKris Kennaway break; 35374664626SKris Kennaway case SSL_ERROR_WANT_WRITE: 3546f9291ceSJung-uk Kim BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY); 35574664626SKris Kennaway break; 35674664626SKris Kennaway case SSL_ERROR_WANT_CONNECT: 3576f9291ceSJung-uk Kim BIO_set_flags(b, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY); 358e71b7053SJung-uk Kim BIO_set_retry_reason(b, BIO_get_retry_reason(next)); 35974664626SKris Kennaway break; 36080815a77SJung-uk Kim case SSL_ERROR_WANT_X509_LOOKUP: 36180815a77SJung-uk Kim BIO_set_retry_special(b); 362e71b7053SJung-uk Kim BIO_set_retry_reason(b, BIO_RR_SSL_X509_LOOKUP); 36380815a77SJung-uk Kim break; 36474664626SKris Kennaway default: 36574664626SKris Kennaway break; 36674664626SKris Kennaway } 36774664626SKris Kennaway break; 36874664626SKris Kennaway case BIO_CTRL_DUP: 36974664626SKris Kennaway dbio = (BIO *)ptr; 370e71b7053SJung-uk Kim dbs = BIO_get_data(dbio); 371e71b7053SJung-uk Kim SSL_free(dbs->ssl); 372e71b7053SJung-uk Kim dbs->ssl = SSL_dup(ssl); 373e71b7053SJung-uk Kim dbs->num_renegotiates = bs->num_renegotiates; 374e71b7053SJung-uk Kim dbs->renegotiate_count = bs->renegotiate_count; 375e71b7053SJung-uk Kim dbs->byte_count = bs->byte_count; 376e71b7053SJung-uk Kim dbs->renegotiate_timeout = bs->renegotiate_timeout; 377e71b7053SJung-uk Kim dbs->last_time = bs->last_time; 378e71b7053SJung-uk Kim ret = (dbs->ssl != NULL); 37974664626SKris Kennaway break; 38074664626SKris Kennaway case BIO_C_GET_FD: 38174664626SKris Kennaway ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 38274664626SKris Kennaway break; 38374664626SKris Kennaway case BIO_CTRL_SET_CALLBACK: 384e71b7053SJung-uk Kim ret = 0; /* use callback ctrl */ 38574664626SKris Kennaway break; 38674664626SKris Kennaway default: 38774664626SKris Kennaway ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); 38874664626SKris Kennaway break; 38974664626SKris Kennaway } 390e71b7053SJung-uk Kim return ret; 39174664626SKris Kennaway } 39274664626SKris Kennaway 393e71b7053SJung-uk Kim static long ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) 394f579bf8eSKris Kennaway { 395f579bf8eSKris Kennaway SSL *ssl; 396f579bf8eSKris Kennaway BIO_SSL *bs; 397f579bf8eSKris Kennaway long ret = 1; 398f579bf8eSKris Kennaway 399e71b7053SJung-uk Kim bs = BIO_get_data(b); 400f579bf8eSKris Kennaway ssl = bs->ssl; 4016f9291ceSJung-uk Kim switch (cmd) { 402f579bf8eSKris Kennaway case BIO_CTRL_SET_CALLBACK: 403f579bf8eSKris Kennaway ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); 404f579bf8eSKris Kennaway break; 405e71b7053SJung-uk Kim default: 406e71b7053SJung-uk Kim ret = 0; 407e71b7053SJung-uk Kim break; 408f579bf8eSKris Kennaway } 409e71b7053SJung-uk Kim return ret; 410f579bf8eSKris Kennaway } 411f579bf8eSKris Kennaway 412ddd58736SKris Kennaway static int ssl_puts(BIO *bp, const char *str) 41374664626SKris Kennaway { 41474664626SKris Kennaway int n, ret; 41574664626SKris Kennaway 41674664626SKris Kennaway n = strlen(str); 41774664626SKris Kennaway ret = BIO_write(bp, str, n); 418e71b7053SJung-uk Kim return ret; 41974664626SKris Kennaway } 42074664626SKris Kennaway 42174664626SKris Kennaway BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) 42274664626SKris Kennaway { 423fceca8a3SJacques Vidrine #ifndef OPENSSL_NO_SOCK 42474664626SKris Kennaway BIO *ret = NULL, *buf = NULL, *ssl = NULL; 42574664626SKris Kennaway 42674664626SKris Kennaway if ((buf = BIO_new(BIO_f_buffer())) == NULL) 427e71b7053SJung-uk Kim return NULL; 42874664626SKris Kennaway if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) 42974664626SKris Kennaway goto err; 43074664626SKris Kennaway if ((ret = BIO_push(buf, ssl)) == NULL) 43174664626SKris Kennaway goto err; 432e71b7053SJung-uk Kim return ret; 43374664626SKris Kennaway err: 4346f9291ceSJung-uk Kim BIO_free(buf); 4356f9291ceSJung-uk Kim BIO_free(ssl); 436fceca8a3SJacques Vidrine #endif 437e71b7053SJung-uk Kim return NULL; 43874664626SKris Kennaway } 43974664626SKris Kennaway 44074664626SKris Kennaway BIO *BIO_new_ssl_connect(SSL_CTX *ctx) 44174664626SKris Kennaway { 4421f13597dSJung-uk Kim #ifndef OPENSSL_NO_SOCK 44374664626SKris Kennaway BIO *ret = NULL, *con = NULL, *ssl = NULL; 44474664626SKris Kennaway 44574664626SKris Kennaway if ((con = BIO_new(BIO_s_connect())) == NULL) 446e71b7053SJung-uk Kim return NULL; 44774664626SKris Kennaway if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) 44874664626SKris Kennaway goto err; 44974664626SKris Kennaway if ((ret = BIO_push(ssl, con)) == NULL) 45074664626SKris Kennaway goto err; 451e71b7053SJung-uk Kim return ret; 45274664626SKris Kennaway err: 4539a3ae0cdSJung-uk Kim BIO_free(ssl); 4546f9291ceSJung-uk Kim BIO_free(con); 4551f13597dSJung-uk Kim #endif 456e71b7053SJung-uk Kim return NULL; 45774664626SKris Kennaway } 45874664626SKris Kennaway 45974664626SKris Kennaway BIO *BIO_new_ssl(SSL_CTX *ctx, int client) 46074664626SKris Kennaway { 46174664626SKris Kennaway BIO *ret; 46274664626SKris Kennaway SSL *ssl; 46374664626SKris Kennaway 46474664626SKris Kennaway if ((ret = BIO_new(BIO_f_ssl())) == NULL) 465e71b7053SJung-uk Kim return NULL; 4666f9291ceSJung-uk Kim if ((ssl = SSL_new(ctx)) == NULL) { 46774664626SKris Kennaway BIO_free(ret); 468e71b7053SJung-uk Kim return NULL; 46974664626SKris Kennaway } 47074664626SKris Kennaway if (client) 47174664626SKris Kennaway SSL_set_connect_state(ssl); 47274664626SKris Kennaway else 47374664626SKris Kennaway SSL_set_accept_state(ssl); 47474664626SKris Kennaway 47574664626SKris Kennaway BIO_set_ssl(ret, ssl, BIO_CLOSE); 476e71b7053SJung-uk Kim return ret; 47774664626SKris Kennaway } 47874664626SKris Kennaway 47974664626SKris Kennaway int BIO_ssl_copy_session_id(BIO *t, BIO *f) 48074664626SKris Kennaway { 481e71b7053SJung-uk Kim BIO_SSL *tdata, *fdata; 48274664626SKris Kennaway t = BIO_find_type(t, BIO_TYPE_SSL); 48374664626SKris Kennaway f = BIO_find_type(f, BIO_TYPE_SSL); 48474664626SKris Kennaway if ((t == NULL) || (f == NULL)) 485e71b7053SJung-uk Kim return 0; 486e71b7053SJung-uk Kim tdata = BIO_get_data(t); 487e71b7053SJung-uk Kim fdata = BIO_get_data(f); 488e71b7053SJung-uk Kim if ((tdata->ssl == NULL) || (fdata->ssl == NULL)) 489e71b7053SJung-uk Kim return 0; 490e71b7053SJung-uk Kim if (!SSL_copy_session_id(tdata->ssl, (fdata->ssl))) 491e71b7053SJung-uk Kim return 0; 492e71b7053SJung-uk Kim return 1; 49374664626SKris Kennaway } 49474664626SKris Kennaway 49574664626SKris Kennaway void BIO_ssl_shutdown(BIO *b) 49674664626SKris Kennaway { 497e71b7053SJung-uk Kim BIO_SSL *bdata; 49874664626SKris Kennaway 499e71b7053SJung-uk Kim for (; b != NULL; b = BIO_next(b)) { 500e71b7053SJung-uk Kim if (BIO_method_type(b) != BIO_TYPE_SSL) 501e71b7053SJung-uk Kim continue; 502e71b7053SJung-uk Kim bdata = BIO_get_data(b); 503e71b7053SJung-uk Kim if (bdata != NULL && bdata->ssl != NULL) 504e71b7053SJung-uk Kim SSL_shutdown(bdata->ssl); 50574664626SKris Kennaway } 50674664626SKris Kennaway } 507