• 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->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 
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->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 
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       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 
ssl_new(BIO * bio)136 static int ssl_new(BIO *bio) {
137   return 1;
138 }
139 
ssl_free(BIO * bio)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 
ssl_callback_ctrl(BIO * bio,int cmd,bio_info_cb fp)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 
BIO_f_ssl(void)175 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
176 
BIO_set_ssl(BIO * bio,SSL * ssl,int take_owership)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