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 | |
15 | static SSL *get_ssl(BIO *bio) { |
16 | return reinterpret_cast<SSL *>(bio->ptr); |
17 | } |
18 | |
19 | static int ssl_read(BIO *bio, char *out, int outl) { |
20 | SSL *ssl = get_ssl(bio); |
21 | if (ssl == NULL) { |
22 | return 0; |
23 | } |
24 | |
25 | BIO_clear_retry_flags(bio); |
26 | |
27 | const int ret = SSL_read(ssl, out, outl); |
28 | |
29 | switch (SSL_get_error(ssl, ret)) { |
30 | case SSL_ERROR_WANT_READ: |
31 | BIO_set_retry_read(bio); |
32 | break; |
33 | |
34 | case SSL_ERROR_WANT_WRITE: |
35 | BIO_set_retry_write(bio); |
36 | break; |
37 | |
38 | case SSL_ERROR_WANT_ACCEPT: |
39 | BIO_set_retry_special(bio); |
40 | bio->retry_reason = BIO_RR_ACCEPT; |
41 | break; |
42 | |
43 | case SSL_ERROR_WANT_CONNECT: |
44 | BIO_set_retry_special(bio); |
45 | bio->retry_reason = BIO_RR_CONNECT; |
46 | break; |
47 | |
48 | case SSL_ERROR_NONE: |
49 | case SSL_ERROR_SYSCALL: |
50 | case SSL_ERROR_SSL: |
51 | case SSL_ERROR_ZERO_RETURN: |
52 | default: |
53 | break; |
54 | } |
55 | |
56 | return ret; |
57 | } |
58 | |
59 | static int ssl_write(BIO *bio, const char *out, int outl) { |
60 | SSL *ssl = get_ssl(bio); |
61 | if (ssl == NULL) { |
62 | return 0; |
63 | } |
64 | |
65 | BIO_clear_retry_flags(bio); |
66 | |
67 | const int ret = SSL_write(ssl, out, outl); |
68 | |
69 | switch (SSL_get_error(ssl, ret)) { |
70 | case SSL_ERROR_WANT_WRITE: |
71 | BIO_set_retry_write(bio); |
72 | break; |
73 | |
74 | case SSL_ERROR_WANT_READ: |
75 | BIO_set_retry_read(bio); |
76 | break; |
77 | |
78 | case SSL_ERROR_WANT_CONNECT: |
79 | BIO_set_retry_special(bio); |
80 | bio->retry_reason = BIO_RR_CONNECT; |
81 | break; |
82 | |
83 | case SSL_ERROR_NONE: |
84 | case SSL_ERROR_SYSCALL: |
85 | case SSL_ERROR_SSL: |
86 | default: |
87 | break; |
88 | } |
89 | |
90 | return ret; |
91 | } |
92 | |
93 | static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) { |
94 | SSL *ssl = get_ssl(bio); |
95 | if (ssl == NULL && cmd != BIO_C_SET_SSL) { |
96 | return 0; |
97 | } |
98 | |
99 | switch (cmd) { |
100 | case BIO_C_SET_SSL: |
101 | bio->shutdown = num; |
102 | bio->ptr = ptr; |
103 | bio->init = 1; |
104 | return 1; |
105 | |
106 | case BIO_CTRL_GET_CLOSE: |
107 | return bio->shutdown; |
108 | |
109 | case BIO_CTRL_SET_CLOSE: |
110 | bio->shutdown = num; |
111 | return 1; |
112 | |
113 | case BIO_CTRL_WPENDING: |
114 | return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr); |
115 | |
116 | case BIO_CTRL_PENDING: |
117 | return SSL_pending(ssl); |
118 | |
119 | case BIO_CTRL_FLUSH: { |
120 | BIO_clear_retry_flags(bio); |
121 | long ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr); |
122 | BIO_copy_next_retry(bio); |
123 | return ret; |
124 | } |
125 | |
126 | case BIO_CTRL_PUSH: |
127 | case BIO_CTRL_POP: |
128 | case BIO_CTRL_DUP: |
129 | return -1; |
130 | |
131 | default: |
132 | return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr); |
133 | } |
134 | } |
135 | |
136 | static int ssl_new(BIO *bio) { |
137 | return 1; |
138 | } |
139 | |
140 | static int ssl_free(BIO *bio) { |
141 | SSL *ssl = get_ssl(bio); |
142 | |
143 | if (ssl == NULL) { |
144 | return 1; |
145 | } |
146 | |
147 | SSL_shutdown(ssl); |
148 | if (bio->shutdown) { |
149 | SSL_free(ssl); |
150 | } |
151 | |
152 | return 1; |
153 | } |
154 | |
155 | static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { |
156 | SSL *ssl = get_ssl(bio); |
157 | if (ssl == NULL) { |
158 | return 0; |
159 | } |
160 | |
161 | switch (cmd) { |
162 | case BIO_CTRL_SET_CALLBACK: |
163 | return -1; |
164 | |
165 | default: |
166 | return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp); |
167 | } |
168 | } |
169 | |
170 | static const BIO_METHOD ssl_method = { |
171 | BIO_TYPE_SSL, "SSL" , ssl_write, ssl_read, NULL, |
172 | NULL, ssl_ctrl, ssl_new, ssl_free, ssl_callback_ctrl, |
173 | }; |
174 | |
175 | const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; } |
176 | |
177 | long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) { |
178 | return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl); |
179 | } |
180 | |