• 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) { 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