Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
4.2 KiB
192 lines
4.2 KiB
/* |
|
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
|
* |
|
* Licensed under the OpenSSL license (the "License"). You may not use |
|
* this file except in compliance with the License. You can obtain a copy |
|
* in the file LICENSE in the source distribution or at |
|
* https://www.openssl.org/source/license.html |
|
*/ |
|
|
|
#include <openssl/ssl.h> |
|
|
|
#include <openssl/bio.h> |
|
|
|
|
|
static SSL *get_ssl(BIO *bio) { |
|
return reinterpret_cast<SSL *>(bio->ptr); |
|
} |
|
|
|
static int ssl_read(BIO *bio, char *out, int outl) { |
|
SSL *ssl = get_ssl(bio); |
|
if (ssl == NULL) { |
|
return 0; |
|
} |
|
|
|
BIO_clear_retry_flags(bio); |
|
|
|
const int ret = SSL_read(ssl, out, outl); |
|
|
|
switch (SSL_get_error(ssl, ret)) { |
|
case SSL_ERROR_WANT_READ: |
|
BIO_set_retry_read(bio); |
|
break; |
|
|
|
case SSL_ERROR_WANT_WRITE: |
|
BIO_set_retry_write(bio); |
|
break; |
|
|
|
case SSL_ERROR_WANT_ACCEPT: |
|
BIO_set_retry_special(bio); |
|
BIO_set_retry_reason(bio, BIO_RR_ACCEPT); |
|
break; |
|
|
|
case SSL_ERROR_WANT_CONNECT: |
|
BIO_set_retry_special(bio); |
|
BIO_set_retry_reason(bio, BIO_RR_CONNECT); |
|
break; |
|
|
|
case SSL_ERROR_NONE: |
|
case SSL_ERROR_SYSCALL: |
|
case SSL_ERROR_SSL: |
|
case SSL_ERROR_ZERO_RETURN: |
|
default: |
|
break; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
static int ssl_write(BIO *bio, const char *out, int outl) { |
|
SSL *ssl = get_ssl(bio); |
|
if (ssl == NULL) { |
|
return 0; |
|
} |
|
|
|
BIO_clear_retry_flags(bio); |
|
|
|
const int ret = SSL_write(ssl, out, outl); |
|
|
|
switch (SSL_get_error(ssl, ret)) { |
|
case SSL_ERROR_WANT_WRITE: |
|
BIO_set_retry_write(bio); |
|
break; |
|
|
|
case SSL_ERROR_WANT_READ: |
|
BIO_set_retry_read(bio); |
|
break; |
|
|
|
case SSL_ERROR_WANT_CONNECT: |
|
BIO_set_retry_special(bio); |
|
BIO_set_retry_reason(bio, BIO_RR_CONNECT); |
|
break; |
|
|
|
case SSL_ERROR_NONE: |
|
case SSL_ERROR_SYSCALL: |
|
case SSL_ERROR_SSL: |
|
default: |
|
break; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) { |
|
SSL *ssl = get_ssl(bio); |
|
if (ssl == NULL && cmd != BIO_C_SET_SSL) { |
|
return 0; |
|
} |
|
|
|
switch (cmd) { |
|
case BIO_C_SET_SSL: |
|
if (ssl != NULL) { |
|
// OpenSSL allows reusing an SSL BIO with a different SSL object. We do |
|
// not support this. |
|
OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); |
|
return 0; |
|
} |
|
|
|
// Note this differs from upstream OpenSSL, which synchronizes |
|
// |bio->next_bio| with |ssl|'s rbio here, and on |BIO_CTRL_PUSH|. We call |
|
// into the corresponding |BIO| directly. (We can implement the upstream |
|
// behavior if it ends up necessary.) |
|
bio->shutdown = num; |
|
bio->ptr = ptr; |
|
bio->init = 1; |
|
return 1; |
|
|
|
case BIO_CTRL_GET_CLOSE: |
|
return bio->shutdown; |
|
|
|
case BIO_CTRL_SET_CLOSE: |
|
bio->shutdown = num; |
|
return 1; |
|
|
|
case BIO_CTRL_WPENDING: |
|
return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr); |
|
|
|
case BIO_CTRL_PENDING: |
|
return SSL_pending(ssl); |
|
|
|
case BIO_CTRL_FLUSH: { |
|
BIO *wbio = SSL_get_wbio(ssl); |
|
BIO_clear_retry_flags(bio); |
|
long ret = BIO_ctrl(wbio, cmd, num, ptr); |
|
BIO_set_flags(bio, BIO_get_retry_flags(wbio)); |
|
BIO_set_retry_reason(bio, BIO_get_retry_reason(wbio)); |
|
return ret; |
|
} |
|
|
|
case BIO_CTRL_PUSH: |
|
case BIO_CTRL_POP: |
|
case BIO_CTRL_DUP: |
|
return -1; |
|
|
|
default: |
|
return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr); |
|
} |
|
} |
|
|
|
static int ssl_new(BIO *bio) { |
|
return 1; |
|
} |
|
|
|
static int ssl_free(BIO *bio) { |
|
SSL *ssl = get_ssl(bio); |
|
|
|
if (ssl == NULL) { |
|
return 1; |
|
} |
|
|
|
SSL_shutdown(ssl); |
|
if (bio->shutdown) { |
|
SSL_free(ssl); |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) { |
|
SSL *ssl = get_ssl(bio); |
|
if (ssl == NULL) { |
|
return 0; |
|
} |
|
|
|
switch (cmd) { |
|
case BIO_CTRL_SET_CALLBACK: |
|
return -1; |
|
|
|
default: |
|
return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp); |
|
} |
|
} |
|
|
|
static const BIO_METHOD ssl_method = { |
|
BIO_TYPE_SSL, "SSL", ssl_write, ssl_read, NULL, |
|
NULL, ssl_ctrl, ssl_new, ssl_free, ssl_callback_ctrl, |
|
}; |
|
|
|
const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; } |
|
|
|
long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) { |
|
return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl); |
|
}
|
|
|