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 15 static SSL *get_ssl(BIO *bio) { 16 return reinterpret_cast<SSL *>(bio->ptr); 17 } 18 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 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 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 136 static int ssl_new(BIO *bio) { 137 return 1; 138 } 139 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 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 175 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; } 176 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