1 /*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <openssl/ssl.h>
11
12 #include <openssl/bio.h>
13
14
get_ssl(BIO * bio)15 static SSL *get_ssl(BIO *bio) { return reinterpret_cast<SSL *>(bio->ptr); }
16
ssl_read(BIO * bio,char * out,int outl)17 static int ssl_read(BIO *bio, char *out, int outl) {
18 SSL *ssl = get_ssl(bio);
19 if (ssl == NULL) {
20 return 0;
21 }
22
23 BIO_clear_retry_flags(bio);
24
25 const int ret = SSL_read(ssl, out, outl);
26
27 switch (SSL_get_error(ssl, ret)) {
28 case SSL_ERROR_WANT_READ:
29 BIO_set_retry_read(bio);
30 break;
31
32 case SSL_ERROR_WANT_WRITE:
33 BIO_set_retry_write(bio);
34 break;
35
36 case SSL_ERROR_WANT_ACCEPT:
37 BIO_set_retry_special(bio);
38 BIO_set_retry_reason(bio, BIO_RR_ACCEPT);
39 break;
40
41 case SSL_ERROR_WANT_CONNECT:
42 BIO_set_retry_special(bio);
43 BIO_set_retry_reason(bio, BIO_RR_CONNECT);
44 break;
45
46 case SSL_ERROR_NONE:
47 case SSL_ERROR_SYSCALL:
48 case SSL_ERROR_SSL:
49 case SSL_ERROR_ZERO_RETURN:
50 default:
51 break;
52 }
53
54 return ret;
55 }
56
ssl_write(BIO * bio,const char * out,int outl)57 static int ssl_write(BIO *bio, const char *out, int outl) {
58 SSL *ssl = get_ssl(bio);
59 if (ssl == NULL) {
60 return 0;
61 }
62
63 BIO_clear_retry_flags(bio);
64
65 const int ret = SSL_write(ssl, out, outl);
66
67 switch (SSL_get_error(ssl, ret)) {
68 case SSL_ERROR_WANT_WRITE:
69 BIO_set_retry_write(bio);
70 break;
71
72 case SSL_ERROR_WANT_READ:
73 BIO_set_retry_read(bio);
74 break;
75
76 case SSL_ERROR_WANT_CONNECT:
77 BIO_set_retry_special(bio);
78 BIO_set_retry_reason(bio, BIO_RR_CONNECT);
79 break;
80
81 case SSL_ERROR_NONE:
82 case SSL_ERROR_SYSCALL:
83 case SSL_ERROR_SSL:
84 default:
85 break;
86 }
87
88 return ret;
89 }
90
ssl_ctrl(BIO * bio,int cmd,long num,void * ptr)91 static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) {
92 SSL *ssl = get_ssl(bio);
93 if (ssl == NULL && cmd != BIO_C_SET_SSL) {
94 return 0;
95 }
96
97 switch (cmd) {
98 case BIO_C_SET_SSL:
99 if (ssl != NULL) {
100 // OpenSSL allows reusing an SSL BIO with a different SSL object. We do
101 // not support this.
102 OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
103 return 0;
104 }
105
106 // Note this differs from upstream OpenSSL, which synchronizes
107 // |bio->next_bio| with |ssl|'s rbio here, and on |BIO_CTRL_PUSH|. We call
108 // into the corresponding |BIO| directly. (We can implement the upstream
109 // behavior if it ends up necessary.)
110 bio->shutdown = static_cast<int>(num);
111 bio->ptr = ptr;
112 bio->init = 1;
113 return 1;
114
115 case BIO_CTRL_GET_CLOSE:
116 return bio->shutdown;
117
118 case BIO_CTRL_SET_CLOSE:
119 bio->shutdown = static_cast<int>(num);
120 return 1;
121
122 case BIO_CTRL_WPENDING:
123 return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
124
125 case BIO_CTRL_PENDING:
126 return SSL_pending(ssl);
127
128 case BIO_CTRL_FLUSH: {
129 BIO *wbio = SSL_get_wbio(ssl);
130 BIO_clear_retry_flags(bio);
131 long ret = BIO_ctrl(wbio, cmd, num, ptr);
132 BIO_set_flags(bio, BIO_get_retry_flags(wbio));
133 BIO_set_retry_reason(bio, BIO_get_retry_reason(wbio));
134 return ret;
135 }
136
137 case BIO_CTRL_PUSH:
138 case BIO_CTRL_POP:
139 case BIO_CTRL_DUP:
140 return -1;
141
142 default:
143 return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
144 }
145 }
146
ssl_new(BIO * bio)147 static int ssl_new(BIO *bio) { return 1; }
148
ssl_free(BIO * bio)149 static int ssl_free(BIO *bio) {
150 SSL *ssl = get_ssl(bio);
151
152 if (ssl == NULL) {
153 return 1;
154 }
155
156 SSL_shutdown(ssl);
157 if (bio->shutdown) {
158 SSL_free(ssl);
159 }
160
161 return 1;
162 }
163
ssl_callback_ctrl(BIO * bio,int cmd,bio_info_cb fp)164 static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
165 SSL *ssl = get_ssl(bio);
166 if (ssl == NULL) {
167 return 0;
168 }
169
170 switch (cmd) {
171 case BIO_CTRL_SET_CALLBACK:
172 return -1;
173
174 default:
175 return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
176 }
177 }
178
179 static const BIO_METHOD ssl_method = {
180 BIO_TYPE_SSL, "SSL", ssl_write, ssl_read, NULL,
181 NULL, ssl_ctrl, ssl_new, ssl_free, ssl_callback_ctrl,
182 };
183
BIO_f_ssl(void)184 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
185
BIO_set_ssl(BIO * bio,SSL * ssl,int take_owership)186 long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
187 return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
188 }
189