• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) {
16   return reinterpret_cast<SSL *>(bio->ptr);
17 }
18 
ssl_read(BIO * bio,char * out,int outl)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_set_retry_reason(bio, BIO_RR_ACCEPT);
41       break;
42 
43     case SSL_ERROR_WANT_CONNECT:
44       BIO_set_retry_special(bio);
45       BIO_set_retry_reason(bio, 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 
ssl_write(BIO * bio,const char * out,int outl)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_set_retry_reason(bio, 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 
ssl_ctrl(BIO * bio,int cmd,long num,void * ptr)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       if (ssl != NULL) {
102         // OpenSSL allows reusing an SSL BIO with a different SSL object. We do
103         // not support this.
104         OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
105         return 0;
106       }
107 
108       // Note this differs from upstream OpenSSL, which synchronizes
109       // |bio->next_bio| with |ssl|'s rbio here, and on |BIO_CTRL_PUSH|. We call
110       // into the corresponding |BIO| directly. (We can implement the upstream
111       // behavior if it ends up necessary.)
112       bio->shutdown = num;
113       bio->ptr = ptr;
114       bio->init = 1;
115       return 1;
116 
117     case BIO_CTRL_GET_CLOSE:
118       return bio->shutdown;
119 
120     case BIO_CTRL_SET_CLOSE:
121       bio->shutdown = num;
122       return 1;
123 
124     case BIO_CTRL_WPENDING:
125       return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
126 
127     case BIO_CTRL_PENDING:
128       return SSL_pending(ssl);
129 
130     case BIO_CTRL_FLUSH: {
131       BIO *wbio = SSL_get_wbio(ssl);
132       BIO_clear_retry_flags(bio);
133       long ret = BIO_ctrl(wbio, cmd, num, ptr);
134       BIO_set_flags(bio, BIO_get_retry_flags(wbio));
135       BIO_set_retry_reason(bio, BIO_get_retry_reason(wbio));
136       return ret;
137     }
138 
139     case BIO_CTRL_PUSH:
140     case BIO_CTRL_POP:
141     case BIO_CTRL_DUP:
142       return -1;
143 
144     default:
145       return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
146   }
147 }
148 
ssl_new(BIO * bio)149 static int ssl_new(BIO *bio) {
150   return 1;
151 }
152 
ssl_free(BIO * bio)153 static int ssl_free(BIO *bio) {
154   SSL *ssl = get_ssl(bio);
155 
156   if (ssl == NULL) {
157     return 1;
158   }
159 
160   SSL_shutdown(ssl);
161   if (bio->shutdown) {
162     SSL_free(ssl);
163   }
164 
165   return 1;
166 }
167 
ssl_callback_ctrl(BIO * bio,int cmd,bio_info_cb fp)168 static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
169   SSL *ssl = get_ssl(bio);
170   if (ssl == NULL) {
171     return 0;
172   }
173 
174   switch (cmd) {
175     case BIO_CTRL_SET_CALLBACK:
176       return -1;
177 
178     default:
179       return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
180   }
181 }
182 
183 static const BIO_METHOD ssl_method = {
184     BIO_TYPE_SSL, "SSL",    ssl_write, ssl_read, NULL,
185     NULL,         ssl_ctrl, ssl_new,   ssl_free, ssl_callback_ctrl,
186 };
187 
BIO_f_ssl(void)188 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
189 
BIO_set_ssl(BIO * bio,SSL * ssl,int take_owership)190 long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
191   return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
192 }
193