Skip to content

Commit

Permalink
crypto: make node_crypto_bio compat w/ OpenSSL 1.1
Browse files Browse the repository at this point in the history
This is cherry-picked from PR #8491 and then tidied up. The original had
an unnecessarily large diff and messed up some public/private bits.

PR-URL: #16130
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Rod Vagg <rod@vagg.org>
  • Loading branch information
davidben authored and evanlucas committed Nov 13, 2017
1 parent 8da4983 commit efd9bc3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 33 deletions.
91 changes: 64 additions & 27 deletions src/node_crypto_bio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,20 @@
namespace node {
namespace crypto {

const BIO_METHOD NodeBIO::method = {
BIO_TYPE_MEM,
"node.js SSL buffer",
NodeBIO::Write,
NodeBIO::Read,
NodeBIO::Puts,
NodeBIO::Gets,
NodeBIO::Ctrl,
NodeBIO::New,
NodeBIO::Free,
nullptr
};
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define BIO_set_data(bio, data) bio->ptr = data
#define BIO_get_data(bio) bio->ptr
#define BIO_set_shutdown(bio, shutdown_) bio->shutdown = shutdown_
#define BIO_get_shutdown(bio) bio->shutdown
#define BIO_set_init(bio, init_) bio->init = init_
#define BIO_get_init(bio) bio->init
#endif


BIO* NodeBIO::New() {
// The const_cast doesn't violate const correctness. OpenSSL's usage of
// BIO_METHOD is effectively const but BIO_new() takes a non-const argument.
return BIO_new(const_cast<BIO_METHOD*>(&method));
return BIO_new(const_cast<BIO_METHOD*>(GetMethod()));
}


Expand All @@ -70,12 +66,11 @@ void NodeBIO::AssignEnvironment(Environment* env) {


int NodeBIO::New(BIO* bio) {
bio->ptr = new NodeBIO();
BIO_set_data(bio, new NodeBIO());

// XXX Why am I doing it?!
bio->shutdown = 1;
bio->init = 1;
bio->num = -1;
BIO_set_shutdown(bio, 1);
BIO_set_init(bio, 1);

return 1;
}
Expand All @@ -85,10 +80,10 @@ int NodeBIO::Free(BIO* bio) {
if (bio == nullptr)
return 0;

if (bio->shutdown) {
if (bio->init && bio->ptr != nullptr) {
if (BIO_get_shutdown(bio)) {
if (BIO_get_init(bio) && BIO_get_data(bio) != nullptr) {
delete FromBIO(bio);
bio->ptr = nullptr;
BIO_set_data(bio, nullptr);
}
}

Expand All @@ -97,13 +92,13 @@ int NodeBIO::Free(BIO* bio) {


int NodeBIO::Read(BIO* bio, char* out, int len) {
int bytes;
BIO_clear_retry_flags(bio);

bytes = FromBIO(bio)->Read(out, len);
NodeBIO* nbio = FromBIO(bio);
int bytes = nbio->Read(out, len);

if (bytes == 0) {
bytes = bio->num;
bytes = nbio->eof_return();
if (bytes != 0) {
BIO_set_retry_read(bio);
}
Expand Down Expand Up @@ -161,7 +156,7 @@ int NodeBIO::Puts(BIO* bio, const char* str) {


int NodeBIO::Gets(BIO* bio, char* out, int size) {
NodeBIO* nbio = FromBIO(bio);
NodeBIO* nbio = FromBIO(bio);

if (nbio->Length() == 0)
return 0;
Expand Down Expand Up @@ -201,7 +196,7 @@ long NodeBIO::Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int)
ret = nbio->Length() == 0;
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
bio->num = num;
nbio->set_eof_return(num);
break;
case BIO_CTRL_INFO:
ret = nbio->Length();
Expand All @@ -216,10 +211,10 @@ long NodeBIO::Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int)
ret = 0;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
ret = BIO_get_shutdown(bio);
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = num;
BIO_set_shutdown(bio, num);
break;
case BIO_CTRL_WPENDING:
ret = 0;
Expand All @@ -241,6 +236,41 @@ long NodeBIO::Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int)
}


const BIO_METHOD* NodeBIO::GetMethod() {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static const BIO_METHOD method = {
BIO_TYPE_MEM,
"node.js SSL buffer",
Write,
Read,
Puts,
Gets,
Ctrl,
New,
Free,
nullptr
};

return &method;
#else
static BIO_METHOD* method = nullptr;

if (method == nullptr) {
method = BIO_meth_new(BIO_TYPE_MEM, "node.js SSL buffer");
BIO_meth_set_write(method, Write);
BIO_meth_set_read(method, Read);
BIO_meth_set_puts(method, Puts);
BIO_meth_set_gets(method, Gets);
BIO_meth_set_ctrl(method, Ctrl);
BIO_meth_set_create(method, New);
BIO_meth_set_destroy(method, Free);
}

return method;
#endif
}


void NodeBIO::TryMoveReadHead() {
// `read_pos_` and `write_pos_` means the position of the reader and writer
// inside the buffer, respectively. When they're equal - its safe to reset
Expand Down Expand Up @@ -488,5 +518,12 @@ NodeBIO::~NodeBIO() {
write_head_ = nullptr;
}


NodeBIO* NodeBIO::FromBIO(BIO* bio) {
CHECK_NE(BIO_get_data(bio), nullptr);
return static_cast<NodeBIO*>(BIO_get_data(bio));
}


} // namespace crypto
} // namespace node
19 changes: 13 additions & 6 deletions src/node_crypto_bio.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class NodeBIO {
NodeBIO() : env_(nullptr),
initial_(kInitialBufferLength),
length_(0),
eof_return_(-1),
read_head_(nullptr),
write_head_(nullptr) {
}
Expand Down Expand Up @@ -95,14 +96,19 @@ class NodeBIO {
return length_;
}

inline void set_eof_return(int num) {
eof_return_ = num;
}

inline int eof_return() {
return eof_return_;
}

inline void set_initial(size_t initial) {
initial_ = initial;
}

static inline NodeBIO* FromBIO(BIO* bio) {
CHECK_NE(bio->ptr, nullptr);
return static_cast<NodeBIO*>(bio->ptr);
}
static NodeBIO* FromBIO(BIO* bio);

private:
static int New(BIO* bio);
Expand All @@ -114,12 +120,12 @@ class NodeBIO {
static long Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int)
void* ptr);

static const BIO_METHOD* GetMethod();

// Enough to handle the most of the client hellos
static const size_t kInitialBufferLength = 1024;
static const size_t kThroughputBufferLength = 16384;

static const BIO_METHOD method;

class Buffer {
public:
Buffer(Environment* env, size_t len) : env_(env),
Expand Down Expand Up @@ -151,6 +157,7 @@ class NodeBIO {
Environment* env_;
size_t initial_;
size_t length_;
int eof_return_;
Buffer* read_head_;
Buffer* write_head_;
};
Expand Down

0 comments on commit efd9bc3

Please sign in to comment.