xref: /freebsd-src/crypto/openssl/ssl/bio_ssl.c (revision a7148ab39c03abd4d1a84997c70bf96f15dd2a09)
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