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 
ssl_read(BIO * bio,char * out,int outl)15 static 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 
ssl_write(BIO * bio,const char * out,int outl)55 static 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 
ssl_ctrl(BIO * bio,int cmd,long num,void * ptr)89 static 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:
110       return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
111 
112     case BIO_CTRL_PENDING:
113       return SSL_pending(ssl);
114 
115     case BIO_CTRL_FLUSH: {
116       BIO_clear_retry_flags(bio);
117       long ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
118       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:
128       return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
129   }
130 }
131 
ssl_new(BIO * bio)132 static int ssl_new(BIO *bio) {
133   return 1;
134 }
135 
ssl_free(BIO * bio)136 static 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 
ssl_callback_ctrl(BIO * bio,int cmd,bio_info_cb fp)151 static 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:
162       return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
163   }
164 }
165 
166 static 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 
BIO_f_ssl(void)171 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
172 
BIO_set_ssl(BIO * bio,SSL * ssl,int take_owership)173 long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
174   return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
175 }
176