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