Browse Source

tls, crypto: deduplicate code

Commit 03e008d introduced src/tls_wrap.cc and src/tls_wrap.h but
said files copied on the order of 1 kLoC from src/node_crypto.cc
and src/node_crypto.h.  This commit undoes some of the duplication.

Fixes #6024.
v0.11.6-release
Fedor Indutny 12 years ago
committed by Ben Noordhuis
parent
commit
b9a0eb0688
  1. 1
      lib/_tls_legacy.js
  2. 1875
      src/node_crypto.cc
  3. 154
      src/node_crypto.h
  4. 670
      src/tls_wrap.cc
  5. 63
      src/tls_wrap.h

1
lib/_tls_legacy.js

@ -604,6 +604,7 @@ function onclienthello(hello) {
if (err) return self.socket.destroy(err);
self.ssl.loadSession(session);
self.ssl.endParser();
// Cycle data
self._resumingSession = false;

1875
src/node_crypto.cc

File diff suppressed because it is too large

154
src/node_crypto.h

@ -49,6 +49,8 @@
namespace node {
namespace crypto {
extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx);
static X509_STORE* root_cert_store;
// Forward declaration
@ -84,12 +86,6 @@ class SecureContext : ObjectWrap {
static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
static SSL_SESSION* GetSessionCallback(SSL* s,
unsigned char* key,
int len,
int* copy);
static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
SecureContext() : ObjectWrap() {
ctx_ = NULL;
ca_store_ = NULL;
@ -119,7 +115,96 @@ class SecureContext : ObjectWrap {
private:
};
class Connection : ObjectWrap {
template <class Base>
class SSLWrap {
public:
enum Kind {
kClient,
kServer
};
SSLWrap(SecureContext* sc, Kind kind) : kind_(kind),
next_sess_(NULL),
session_callbacks_(false) {
ssl_ = SSL_new(sc->ctx_);
assert(ssl_ != NULL);
}
~SSLWrap() {
if (ssl_ != NULL) {
SSL_free(ssl_);
ssl_ = NULL;
}
if (next_sess_ != NULL) {
SSL_SESSION_free(next_sess_);
next_sess_ = NULL;
}
#ifdef OPENSSL_NPN_NEGOTIATED
npn_protos_.Dispose();
selected_npn_proto_.Dispose();
#endif
}
inline SSL* ssl() const { return ssl_; }
inline void enable_session_callbacks() { session_callbacks_ = true; }
inline bool is_server() const { return kind_ == kServer; }
inline bool is_client() const { return kind_ == kClient; }
protected:
static void AddMethods(v8::Handle<v8::FunctionTemplate> t);
static SSL_SESSION* GetSessionCallback(SSL* s,
unsigned char* key,
int len,
int* copy);
static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
static void OnClientHello(void* arg,
const ClientHelloParser::ClientHello& hello);
static void GetPeerCertificate(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsInitFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ReceivedShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
#ifdef OPENSSL_NPN_NEGOTIATED
static void GetNegotiatedProto(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
static int AdvertiseNextProtoCallback(SSL* s,
const unsigned char** data,
unsigned int* len,
void* arg);
static int SelectNextProtoCallback(SSL* s,
unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
unsigned int inlen,
void* arg);
#endif // OPENSSL_NPN_NEGOTIATED
Kind kind_;
SSL_SESSION* next_sess_;
SSL* ssl_;
bool session_callbacks_;
ClientHelloParser hello_parser_;
#ifdef OPENSSL_NPN_NEGOTIATED
v8::Persistent<v8::Object> npn_protos_;
v8::Persistent<v8::Value> selected_npn_proto_;
#endif // OPENSSL_NPN_NEGOTIATED
friend class SecureContext;
};
class Connection : public SSLWrap<Connection>, public ObjectWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
@ -142,37 +227,10 @@ class Connection : ObjectWrap {
static void EncPending(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EncOut(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ClearIn(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetPeerCertificate(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsInitFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ReceivedShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
#ifdef OPENSSL_NPN_NEGOTIATED
// NPN
static void GetNegotiatedProto(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
static int AdvertiseNextProtoCallback_(SSL* s,
const unsigned char** data,
unsigned int* len,
void* arg);
static int SelectNextProtoCallback_(SSL* s,
unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
unsigned int inlen,
void* arg);
#endif
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
// SNI
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
@ -180,8 +238,6 @@ class Connection : ObjectWrap {
static int SelectSNIContextCallback_(SSL* s, int* ad, void* arg);
#endif
static void OnClientHello(void* arg,
const ClientHelloParser::ClientHello& hello);
static void OnClientHelloParseEnd(void* arg);
int HandleBIOError(BIO* bio, const char* func, int rv);
@ -207,11 +263,15 @@ class Connection : ObjectWrap {
return conn;
}
Connection() : ObjectWrap(), hello_offset_(0) {
Connection(SecureContext* sc, SSLWrap<Connection>::Kind kind)
: SSLWrap<Connection>(sc, kind),
hello_offset_(0) {
bio_read_ = bio_write_ = NULL;
ssl_ = NULL;
next_sess_ = NULL;
hello_parser_.Start(OnClientHello, OnClientHelloParseEnd, this);
hello_parser_.Start(SSLWrap<Connection>::OnClientHello,
OnClientHelloParseEnd,
this);
enable_session_callbacks();
}
~Connection() {
@ -220,16 +280,6 @@ class Connection : ObjectWrap {
ssl_ = NULL;
}
if (next_sess_ != NULL) {
SSL_SESSION_free(next_sess_);
next_sess_ = NULL;
}
#ifdef OPENSSL_NPN_NEGOTIATED
npnProtos_.Dispose();
selectedNPNProto_.Dispose();
#endif
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
sniObject_.Dispose();
sniContext_.Dispose();
@ -242,12 +292,6 @@ class Connection : ObjectWrap {
BIO *bio_read_;
BIO *bio_write_;
SSL *ssl_;
ClientHelloParser hello_parser_;
bool is_server_; /* coverity[member_decl] */
SSL_SESSION* next_sess_;
uint8_t hello_data_[18432];
size_t hello_offset_;

670
src/tls_wrap.cc

@ -32,6 +32,7 @@
namespace node {
using crypto::SecureContext;
using crypto::SSLWrap;
using v8::Array;
using v8::Boolean;
using v8::Exception;
@ -53,7 +54,6 @@ static Cached<String> onerror_sym;
static Cached<String> onhandshakestart_sym;
static Cached<String> onhandshakedone_sym;
static Cached<String> onclienthello_sym;
static Cached<String> onnewsession_sym;
static Cached<String> subject_sym;
static Cached<String> subjectaltname_sym;
static Cached<String> modulus_sym;
@ -65,9 +65,6 @@ static Cached<String> fingerprint_sym;
static Cached<String> name_sym;
static Cached<String> version_sym;
static Cached<String> ext_key_usage_sym;
static Cached<String> sessionid_sym;
static Cached<String> tls_ticket_sym;
static Cached<String> servername_sym;
static Cached<String> sni_context_sym;
static Persistent<Function> tlsWrap;
@ -81,9 +78,8 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
TLSCallbacks::TLSCallbacks(Kind kind,
Handle<Object> sc,
StreamWrapCallbacks* old)
: StreamWrapCallbacks(old),
kind_(kind),
ssl_(NULL),
: SSLWrap<TLSCallbacks>(ObjectWrap::Unwrap<SecureContext>(sc), kind),
StreamWrapCallbacks(old),
enc_in_(NULL),
enc_out_(NULL),
clear_in_(NULL),
@ -91,9 +87,7 @@ TLSCallbacks::TLSCallbacks(Kind kind,
pending_write_item_(NULL),
started_(false),
established_(false),
shutdown_(false),
session_callbacks_(false),
next_sess_(NULL) {
shutdown_(false) {
// Persist SecureContext
sc_ = ObjectWrap::Unwrap<SecureContext>(sc);
@ -107,60 +101,14 @@ TLSCallbacks::TLSCallbacks(Kind kind,
QUEUE_INIT(&write_item_queue_);
// We've our own session callbacks
SSL_CTX_sess_set_get_cb(sc_->ctx_, GetSessionCallback);
SSL_CTX_sess_set_new_cb(sc_->ctx_, NewSessionCallback);
SSL_CTX_sess_set_get_cb(sc_->ctx_, SSLWrap<TLSCallbacks>::GetSessionCallback);
SSL_CTX_sess_set_new_cb(sc_->ctx_, SSLWrap<TLSCallbacks>::NewSessionCallback);
InitSSL();
}
SSL_SESSION* TLSCallbacks::GetSessionCallback(SSL* s,
unsigned char* key,
int len,
int* copy) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(s));
*copy = 0;
SSL_SESSION* sess = c->next_sess_;
c->next_sess_ = NULL;
return sess;
}
int TLSCallbacks::NewSessionCallback(SSL* s, SSL_SESSION* sess) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(s));
if (!c->session_callbacks_)
return 0;
// Check if session is small enough to be stored
int size = i2d_SSL_SESSION(sess, NULL);
if (size > SecureContext::kMaxSessionSize)
return 0;
// Serialize session
Local<Object> buff = Buffer::New(size);
unsigned char* serialized = reinterpret_cast<unsigned char*>(
Buffer::Data(buff));
memset(serialized, 0, size);
i2d_SSL_SESSION(sess, &serialized);
Local<Object> session = Buffer::New(reinterpret_cast<char*>(sess->session_id),
sess->session_id_length);
Handle<Value> argv[2] = { session, buff };
MakeCallback(c->object(), onnewsession_sym, ARRAY_SIZE(argv), argv);
return 0;
}
TLSCallbacks::~TLSCallbacks() {
SSL_free(ssl_);
ssl_ = NULL;
enc_in_ = NULL;
enc_out_ = NULL;
delete clear_in_;
@ -170,11 +118,6 @@ TLSCallbacks::~TLSCallbacks() {
sc_handle_.Dispose();
persistent().Dispose();
#ifdef OPENSSL_NPN_NEGOTIATED
npn_protos_.Dispose();
selected_npn_proto_.Dispose();
#endif // OPENSSL_NPN_NEGOTIATED
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
sni_context_.Dispose();
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
@ -200,64 +143,15 @@ void TLSCallbacks::InvokeQueued(int status) {
}
static int VerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) {
// Quoting SSL_set_verify(3ssl):
//
// The VerifyCallback function is used to control the behaviour when
// the SSL_VERIFY_PEER flag is set. It must be supplied by the
// application and receives two arguments: preverify_ok indicates,
// whether the verification of the certificate in question was passed
// (preverify_ok=1) or not (preverify_ok=0). x509_ctx is a pointer to
// the complete context used for the certificate chain verification.
//
// The certificate chain is checked starting with the deepest nesting
// level (the root CA certificate) and worked upward to the peer's
// certificate. At each level signatures and issuer attributes are
// checked. Whenever a verification error is found, the error number is
// stored in x509_ctx and VerifyCallback is called with preverify_ok=0.
// By applying X509_CTX_store_* functions VerifyCallback can locate the
// certificate in question and perform additional steps (see EXAMPLES).
// If no error is found for a certificate, VerifyCallback is called
// with preverify_ok=1 before advancing to the next level.
//
// The return value of VerifyCallback controls the strategy of the
// further verification process. If VerifyCallback returns 0, the
// verification process is immediately stopped with "verification
// failed" state. If SSL_VERIFY_PEER is set, a verification failure
// alert is sent to the peer and the TLS/SSL handshake is terminated. If
// VerifyCallback returns 1, the verification process is continued. If
// VerifyCallback always returns 1, the TLS/SSL handshake will not be
// terminated with respect to verification failures and the connection
// will be established. The calling process can however retrieve the
// error code of the last verification error using
// SSL_get_verify_result(3) or by maintaining its own error storage
// managed by VerifyCallback.
//
// If no VerifyCallback is specified, the default callback will be
// used. Its return value is identical to preverify_ok, so that any
// verification failure will lead to a termination of the TLS/SSL
// handshake with an alert message, if SSL_VERIFY_PEER is set.
//
// Since we cannot perform I/O quickly enough in this callback, we ignore
// all preverify_ok errors and let the handshake continue. It is
// imparative that the user use Connection::VerifyError after the
// 'secure' callback has been made.
return 1;
}
void TLSCallbacks::InitSSL() {
assert(ssl_ == NULL);
// Initialize SSL
ssl_ = SSL_new(sc_->ctx_);
enc_in_ = BIO_new(NodeBIO::GetMethod());
enc_out_ = BIO_new(NodeBIO::GetMethod());
SSL_set_bio(ssl_, enc_in_, enc_out_);
// NOTE: This could be overriden in SetVerifyMode
SSL_set_verify(ssl_, SSL_VERIFY_NONE, VerifyCallback);
SSL_set_verify(ssl_, SSL_VERIFY_NONE, crypto::VerifyCallback);
#ifdef SSL_MODE_RELEASE_BUFFERS
long mode = SSL_get_mode(ssl_);
@ -267,29 +161,31 @@ void TLSCallbacks::InitSSL() {
SSL_set_app_data(ssl_, this);
SSL_set_info_callback(ssl_, SSLInfoCallback);
if (kind_ == kTLSServer) {
if (is_server()) {
SSL_set_accept_state(ssl_);
#ifdef OPENSSL_NPN_NEGOTIATED
// Server should advertise NPN protocols
SSL_CTX_set_next_protos_advertised_cb(sc_->ctx_,
AdvertiseNextProtoCallback,
this);
SSL_CTX_set_next_protos_advertised_cb(
sc_->ctx_,
SSLWrap<TLSCallbacks>::AdvertiseNextProtoCallback,
this);
#endif // OPENSSL_NPN_NEGOTIATED
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
SSL_CTX_set_tlsext_servername_callback(sc_->ctx_, SelectSNIContextCallback);
SSL_CTX_set_tlsext_servername_arg(sc_->ctx_, this);
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
} else if (kind_ == kTLSClient) {
} else if (is_client()) {
SSL_set_connect_state(ssl_);
#ifdef OPENSSL_NPN_NEGOTIATED
// Client should select protocol from list of advertised
// If server supports NPN
SSL_CTX_set_next_proto_select_cb(sc_->ctx_,
SelectNextProtoCallback,
this);
SSL_CTX_set_next_proto_select_cb(
sc_->ctx_,
SSLWrap<TLSCallbacks>::SelectNextProtoCallback,
this);
#endif // OPENSSL_NPN_NEGOTIATED
} else {
// Unexpected
@ -313,7 +209,8 @@ void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
Local<Object> stream = args[0].As<Object>();
Local<Object> sc = args[1].As<Object>();
Kind kind = args[2]->IsTrue() ? kTLSServer : kTLSClient;
Kind kind = args[2]->IsTrue() ? SSLWrap<TLSCallbacks>::kServer :
SSLWrap<TLSCallbacks>::kClient;
TLSCallbacks* callbacks = NULL;
WITH_GENERIC_STREAM(stream, {
@ -340,7 +237,7 @@ void TLSCallbacks::Start(const FunctionCallbackInfo<Value>& args) {
wrap->started_ = true;
// Send ClientHello handshake
assert(wrap->kind_ == kTLSClient);
assert(wrap->is_client());
wrap->ClearOut();
wrap->EncOut();
}
@ -353,7 +250,7 @@ void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
if (where & SSL_CB_HANDSHAKE_START) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
Local<Object> object = c->object();
Local<Object> object = c->object(node_isolate);
if (object->Has(onhandshakestart_sym))
MakeCallback(object, onhandshakestart_sym, 0, NULL);
}
@ -361,7 +258,7 @@ void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
c->established_ = true;
Local<Object> object = c->object();
Local<Object> object = c->object(node_isolate);
if (object->Has(onhandshakedone_sym))
MakeCallback(object, onhandshakedone_sym, 0, NULL);
}
@ -370,7 +267,7 @@ void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
void TLSCallbacks::EncOut() {
// Ignore cycling data if ClientHello wasn't yet parsed
if (!hello_.IsEnded())
if (!hello_parser_.IsEnded())
return;
// Write in progress
@ -424,7 +321,7 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
Local<Value> arg = String::Concat(
FIXED_ONE_BYTE_STRING(node_isolate, "write cb error, status: "),
Integer::New(status, node_isolate)->ToString());
MakeCallback(callbacks->object(), onerror_sym, 1, &arg);
MakeCallback(callbacks->object(node_isolate), onerror_sym, 1, &arg);
callbacks->InvokeQueued(status);
return;
}
@ -475,7 +372,7 @@ Handle<Value> TLSCallbacks::GetSSLError(int status, int* err) {
void TLSCallbacks::ClearOut() {
// Ignore cycling data if ClientHello wasn't yet parsed
if (!hello_.IsEnded())
if (!hello_parser_.IsEnded())
return;
HandleScope scope(node_isolate);
@ -500,14 +397,14 @@ void TLSCallbacks::ClearOut() {
Handle<Value> argv = GetSSLError(read, &err);
if (!argv.IsEmpty())
MakeCallback(object(), onerror_sym, 1, &argv);
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
}
}
bool TLSCallbacks::ClearIn() {
// Ignore cycling data if ClientHello wasn't yet parsed
if (!hello_.IsEnded())
if (!hello_parser_.IsEnded())
return false;
HandleScope scope(node_isolate);
@ -533,7 +430,7 @@ bool TLSCallbacks::ClearIn() {
int err;
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty())
MakeCallback(object(), onerror_sym, 1, &argv);
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
return false;
}
@ -595,7 +492,7 @@ int TLSCallbacks::DoWrite(WriteWrap* w,
int err;
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty()) {
MakeCallback(object(), onerror_sym, 1, &argv);
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
return -1;
}
@ -643,11 +540,11 @@ void TLSCallbacks::DoRead(uv_stream_t* handle,
enc_in->Commit(nread);
// Parse ClientHello first
if (!hello_.IsEnded()) {
if (!hello_parser_.IsEnded()) {
size_t avail = 0;
uint8_t* data = reinterpret_cast<uint8_t*>(enc_in->Peek(&avail));
assert(avail == 0 || data != NULL);
return hello_.Parse(data, avail);
return hello_parser_.Parse(data, avail);
}
// Cycle OpenSSL's state
@ -664,74 +561,6 @@ int TLSCallbacks::DoShutdown(ShutdownWrap* req_wrap, uv_shutdown_cb cb) {
}
#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: reason = #CODE; break;
void TLSCallbacks::VerifyError(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
// XXX Do this check in JS land?
X509* peer_cert = SSL_get_peer_certificate(wrap->ssl_);
if (peer_cert == NULL) {
// We requested a certificate and they did not send us one.
// Definitely an error.
// XXX is this the right error message?
Local<String> s =
FIXED_ONE_BYTE_STRING(node_isolate, "UNABLE_TO_GET_ISSUER_CERT");
return args.GetReturnValue().Set(Exception::Error(s));
}
X509_free(peer_cert);
long x509_verify_error = SSL_get_verify_result(wrap->ssl_);
const char* reason = NULL;
Local<String> s;
switch (x509_verify_error) {
case X509_V_OK:
return args.GetReturnValue().SetNull();
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
CASE_X509_ERR(UNABLE_TO_GET_CRL)
CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
CASE_X509_ERR(CERT_NOT_YET_VALID)
CASE_X509_ERR(CERT_HAS_EXPIRED)
CASE_X509_ERR(CRL_NOT_YET_VALID)
CASE_X509_ERR(CRL_HAS_EXPIRED)
CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
CASE_X509_ERR(OUT_OF_MEM)
CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
CASE_X509_ERR(CERT_REVOKED)
CASE_X509_ERR(INVALID_CA)
CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
CASE_X509_ERR(INVALID_PURPOSE)
CASE_X509_ERR(CERT_UNTRUSTED)
CASE_X509_ERR(CERT_REJECTED)
default:
s = OneByteString(node_isolate,
X509_verify_cert_error_string(x509_verify_error));
break;
}
if (s.IsEmpty()) {
s = OneByteString(node_isolate, reason);
}
args.GetReturnValue().Set(Exception::Error(s));
}
#undef CASE_X509_ERR
void TLSCallbacks::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
@ -742,7 +571,7 @@ void TLSCallbacks::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
return ThrowTypeError("Bad arguments, expected two booleans");
int verify_mode;
if (wrap->kind_ == kTLSServer) {
if (wrap->is_server()) {
bool request_cert = args[0]->IsTrue();
if (!request_cert) {
// Note reject_unauthorized ignored.
@ -758,16 +587,7 @@ void TLSCallbacks::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
}
// Always allow a connection. We'll reject in javascript.
SSL_set_verify(wrap->ssl_, verify_mode, VerifyCallback);
}
void TLSCallbacks::IsSessionReused(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
bool yes = SSL_session_reused(wrap->ssl_);
args.GetReturnValue().Set(yes);
SSL_set_verify(wrap->ssl_, verify_mode, crypto::VerifyCallback);
}
@ -778,7 +598,7 @@ void TLSCallbacks::EnableSessionCallbacks(
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
wrap->session_callbacks_ = true;
wrap->enable_session_callbacks();
EnableHelloParser(args);
}
@ -789,33 +609,9 @@ void TLSCallbacks::EnableHelloParser(const FunctionCallbackInfo<Value>& args) {
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
wrap->hello_.Start(OnClientHello, OnClientHelloParseEnd, wrap);
}
void TLSCallbacks::OnClientHello(void* arg,
const ClientHelloParser::ClientHello& hello) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(arg);
Local<Object> hello_obj = Object::New();
Local<Object> buff = Buffer::New(
reinterpret_cast<const char*>(hello.session_id()),
hello.session_size());
hello_obj->Set(sessionid_sym, buff);
if (hello.servername() == NULL) {
hello_obj->Set(servername_sym, String::Empty(node_isolate));
} else {
Local<String> servername = OneByteString(node_isolate,
hello.servername(),
hello.servername_size());
hello_obj->Set(servername_sym, servername);
}
hello_obj->Set(tls_ticket_sym, Boolean::New(hello.has_ticket()));
Handle<Value> argv[1] = { hello_obj };
MakeCallback(c->object(), onclienthello_sym, 1, argv);
wrap->hello_parser_.Start(SSLWrap<TLSCallbacks>::OnClientHello,
OnClientHelloParseEnd,
wrap);
}
@ -825,377 +621,6 @@ void TLSCallbacks::OnClientHelloParseEnd(void* arg) {
}
void TLSCallbacks::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
Local<Object> info = Object::New();
X509* peer_cert = SSL_get_peer_certificate(wrap->ssl_);
if (peer_cert != NULL) {
BIO* bio = BIO_new(BIO_s_mem());
BUF_MEM* mem;
if (X509_NAME_print_ex(bio,
X509_get_subject_name(peer_cert),
0,
X509_NAME_FLAGS) > 0) {
BIO_get_mem_ptr(bio, &mem);
info->Set(subject_sym,
OneByteString(node_isolate, mem->data, mem->length));
}
(void) BIO_reset(bio);
if (X509_NAME_print_ex(bio,
X509_get_issuer_name(peer_cert),
0,
X509_NAME_FLAGS) > 0) {
BIO_get_mem_ptr(bio, &mem);
info->Set(issuer_sym,
OneByteString(node_isolate, mem->data, mem->length));
}
(void) BIO_reset(bio);
int index = X509_get_ext_by_NID(peer_cert, NID_subject_alt_name, -1);
if (index >= 0) {
X509_EXTENSION* ext;
int rv;
ext = X509_get_ext(peer_cert, index);
assert(ext != NULL);
rv = X509V3_EXT_print(bio, ext, 0, 0);
assert(rv == 1);
BIO_get_mem_ptr(bio, &mem);
info->Set(subjectaltname_sym,
OneByteString(node_isolate, mem->data, mem->length));
(void) BIO_reset(bio);
}
EVP_PKEY* pkey = NULL;
RSA* rsa = NULL;
if (NULL != (pkey = X509_get_pubkey(peer_cert)) &&
NULL != (rsa = EVP_PKEY_get1_RSA(pkey))) {
BN_print(bio, rsa->n);
BIO_get_mem_ptr(bio, &mem);
info->Set(modulus_sym,
OneByteString(node_isolate, mem->data, mem->length));
(void) BIO_reset(bio);
BN_print(bio, rsa->e);
BIO_get_mem_ptr(bio, &mem);
info->Set(exponent_sym,
OneByteString(node_isolate, mem->data, mem->length));
(void) BIO_reset(bio);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
if (rsa != NULL) {
RSA_free(rsa);
rsa = NULL;
}
ASN1_TIME_print(bio, X509_get_notBefore(peer_cert));
BIO_get_mem_ptr(bio, &mem);
info->Set(valid_from_sym,
OneByteString(node_isolate, mem->data, mem->length));
(void) BIO_reset(bio);
ASN1_TIME_print(bio, X509_get_notAfter(peer_cert));
BIO_get_mem_ptr(bio, &mem);
info->Set(valid_to_sym,
OneByteString(node_isolate, mem->data, mem->length));
BIO_free_all(bio);
unsigned int md_size, i;
unsigned char md[EVP_MAX_MD_SIZE];
if (X509_digest(peer_cert, EVP_sha1(), md, &md_size)) {
const char hex[] = "0123456789ABCDEF";
char fingerprint[EVP_MAX_MD_SIZE * 3];
for (i = 0; i < md_size; i++) {
fingerprint[3*i] = hex[(md[i] & 0xf0) >> 4];
fingerprint[(3*i)+1] = hex[(md[i] & 0x0f)];
fingerprint[(3*i)+2] = ':';
}
if (md_size > 0)
fingerprint[(3*(md_size-1))+2] = '\0';
else
fingerprint[0] = '\0';
info->Set(fingerprint_sym, OneByteString(node_isolate, fingerprint));
}
STACK_OF(ASN1_OBJECT)* eku = static_cast<STACK_OF(ASN1_OBJECT)*>(
X509_get_ext_d2i(peer_cert,
NID_ext_key_usage,
NULL,
NULL));
if (eku != NULL) {
Local<Array> ext_key_usage = Array::New();
char buf[256];
for (int i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
memset(buf, 0, sizeof(buf));
OBJ_obj2txt(buf, sizeof(buf) - 1, sk_ASN1_OBJECT_value(eku, i), 1);
ext_key_usage->Set(i, OneByteString(node_isolate, buf));
}
sk_ASN1_OBJECT_pop_free(eku, ASN1_OBJECT_free);
info->Set(ext_key_usage_sym, ext_key_usage);
}
X509_free(peer_cert);
}
args.GetReturnValue().Set(info);
}
void TLSCallbacks::GetSession(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
SSL_SESSION* sess = SSL_get_session(wrap->ssl_);
if (!sess) return;
int slen = i2d_SSL_SESSION(sess, NULL);
assert(slen > 0);
if (slen > 0) {
unsigned char* sbuf = new unsigned char[slen];
unsigned char* p = sbuf;
i2d_SSL_SESSION(sess, &p);
Local<Value> s = Encode(sbuf, slen, BINARY);
args.GetReturnValue().Set(s);
delete[] sbuf;
return;
}
args.GetReturnValue().SetNull();
}
void TLSCallbacks::SetSession(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
if (wrap->started_)
return ThrowError("Already started.");
if (args.Length() < 1 ||
(!args[0]->IsString() && !Buffer::HasInstance(args[0]))) {
return ThrowTypeError("Bad argument");
}
size_t slen = Buffer::Length(args[0]);
char* sbuf = new char[slen];
ssize_t wlen = DecodeWrite(sbuf, slen, args[0], BINARY);
assert(wlen == static_cast<ssize_t>(slen));
const unsigned char* p = reinterpret_cast<const unsigned char*>(sbuf);
SSL_SESSION* sess = d2i_SSL_SESSION(NULL, &p, wlen);
delete[] sbuf;
if (!sess) return;
int r = SSL_set_session(wrap->ssl_, sess);
SSL_SESSION_free(sess);
if (!r) {
return ThrowError("SSL_set_session error");
}
}
void TLSCallbacks::LoadSession(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
if (args.Length() >= 1 && Buffer::HasInstance(args[0])) {
ssize_t slen = Buffer::Length(args[0]);
char* sbuf = Buffer::Data(args[0]);
const unsigned char* p = reinterpret_cast<unsigned char*>(sbuf);
SSL_SESSION* sess = d2i_SSL_SESSION(NULL, &p, slen);
// Setup next session and move hello to the BIO buffer
if (wrap->next_sess_ != NULL)
SSL_SESSION_free(wrap->next_sess_);
wrap->next_sess_ = sess;
Local<Object> info = Object::New();
#ifndef OPENSSL_NO_TLSEXT
if (sess->tlsext_hostname == NULL) {
info->Set(servername_sym, False(node_isolate));
} else {
info->Set(servername_sym,
OneByteString(node_isolate, sess->tlsext_hostname));
}
#endif
args.GetReturnValue().Set(info);
}
}
void TLSCallbacks::EndParser(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
wrap->hello_.End();
}
void TLSCallbacks::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
const SSL_CIPHER* c;
c = SSL_get_current_cipher(wrap->ssl_);
if (c == NULL)
return;
const char* cipher_name = SSL_CIPHER_get_name(c);
const char* cipher_version = SSL_CIPHER_get_version(c);
Local<Object> info = Object::New();
info->Set(name_sym, OneByteString(node_isolate, cipher_name));
info->Set(version_sym, OneByteString(node_isolate, cipher_version));
args.GetReturnValue().Set(info);
}
#ifdef OPENSSL_NPN_NEGOTIATED
int TLSCallbacks::AdvertiseNextProtoCallback(SSL* s,
const unsigned char** data,
unsigned int* len,
void* arg) {
TLSCallbacks* p = static_cast<TLSCallbacks*>(arg);
if (p->npn_protos_.IsEmpty()) {
// No initialization - no NPN protocols
*data = reinterpret_cast<const unsigned char*>("");
*len = 0;
} else {
Local<Object> obj = PersistentToLocal(node_isolate, p->npn_protos_);
*data = reinterpret_cast<const unsigned char*>(Buffer::Data(obj));
*len = Buffer::Length(obj);
}
return SSL_TLSEXT_ERR_OK;
}
int TLSCallbacks::SelectNextProtoCallback(SSL* s,
unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
unsigned int inlen,
void* arg) {
TLSCallbacks* p = static_cast<TLSCallbacks*>(arg);
// Release old protocol handler if present
p->selected_npn_proto_.Dispose();
if (p->npn_protos_.IsEmpty()) {
// We should at least select one protocol
// If server is using NPN
*out = reinterpret_cast<unsigned char*>(const_cast<char*>("http/1.1"));
*outlen = 8;
// set status: unsupported
p->selected_npn_proto_.Reset(node_isolate, False(node_isolate));
return SSL_TLSEXT_ERR_OK;
}
Local<Object> obj = PersistentToLocal(node_isolate, p->npn_protos_);
const unsigned char* npn_protos =
reinterpret_cast<const unsigned char*>(Buffer::Data(obj));
size_t len = Buffer::Length(obj);
int status = SSL_select_next_proto(out, outlen, in, inlen, npn_protos, len);
Handle<Value> result;
switch (status) {
case OPENSSL_NPN_UNSUPPORTED:
result = Null(node_isolate);
break;
case OPENSSL_NPN_NEGOTIATED:
result = OneByteString(node_isolate, *out, *outlen);
break;
case OPENSSL_NPN_NO_OVERLAP:
result = False(node_isolate);
break;
default:
break;
}
if (!result.IsEmpty())
p->selected_npn_proto_.Reset(node_isolate, result);
return SSL_TLSEXT_ERR_OK;
}
void TLSCallbacks::GetNegotiatedProto(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
if (wrap->kind_ == kTLSClient) {
if (wrap->selected_npn_proto_.IsEmpty() == false) {
args.GetReturnValue().Set(wrap->selected_npn_proto_);
}
return;
}
const unsigned char* npn_proto;
unsigned int npn_proto_len;
SSL_get0_next_proto_negotiated(wrap->ssl_, &npn_proto, &npn_proto_len);
if (!npn_proto) {
return args.GetReturnValue().Set(false);
}
args.GetReturnValue().Set(
OneByteString(node_isolate, npn_proto, npn_proto_len));
}
void TLSCallbacks::SetNPNProtocols(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
TLSCallbacks* wrap;
NODE_UNWRAP(args.This(), TLSCallbacks, wrap);
if (args.Length() < 1 || !Buffer::HasInstance(args[0]))
return ThrowTypeError("Must give a Buffer as first argument");
wrap->npn_protos_.Reset(node_isolate, args[0].As<Object>());
}
#endif // OPENSSL_NPN_NEGOTIATED
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
void TLSCallbacks::GetServername(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
@ -1225,7 +650,7 @@ void TLSCallbacks::SetServername(const FunctionCallbackInfo<Value>& args) {
if (wrap->started_)
return ThrowError("Already started.");
if (wrap->kind_ != kTLSClient)
if (!wrap->is_client())
return;
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
@ -1244,7 +669,7 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
if (servername != NULL) {
// Call the SNI callback and use its return value as context
Local<Object> object = p->object();
Local<Object> object = p->object(node_isolate);
Local<Value> ctx;
if (object->Has(sni_context_sym)) {
ctx = object->Get(sni_context_sym);
@ -1275,15 +700,7 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TLSWrap"));
NODE_SET_PROTOTYPE_METHOD(t, "start", Start);
NODE_SET_PROTOTYPE_METHOD(t, "getPeerCertificate", GetPeerCertificate);
NODE_SET_PROTOTYPE_METHOD(t, "getSession", GetSession);
NODE_SET_PROTOTYPE_METHOD(t, "setSession", SetSession);
NODE_SET_PROTOTYPE_METHOD(t, "loadSession", LoadSession);
NODE_SET_PROTOTYPE_METHOD(t, "endParser", EndParser);
NODE_SET_PROTOTYPE_METHOD(t, "getCurrentCipher", GetCurrentCipher);
NODE_SET_PROTOTYPE_METHOD(t, "verifyError", VerifyError);
NODE_SET_PROTOTYPE_METHOD(t, "setVerifyMode", SetVerifyMode);
NODE_SET_PROTOTYPE_METHOD(t, "isSessionReused", IsSessionReused);
NODE_SET_PROTOTYPE_METHOD(t,
"enableSessionCallbacks",
EnableSessionCallbacks);
@ -1291,10 +708,7 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
"enableHelloParser",
EnableHelloParser);
#ifdef OPENSSL_NPN_NEGOTIATED
NODE_SET_PROTOTYPE_METHOD(t, "getNegotiatedProtocol", GetNegotiatedProto);
NODE_SET_PROTOTYPE_METHOD(t, "setNPNProtocols", SetNPNProtocols);
#endif // OPENSSL_NPN_NEGOTIATED
SSLWrap<TLSCallbacks>::AddMethods(t);
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
NODE_SET_PROTOTYPE_METHOD(t, "getServername", GetServername);
@ -1309,7 +723,6 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
FIXED_ONE_BYTE_STRING(node_isolate, "onhandshakestart");
onhandshakedone_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onhandshakedone");
onclienthello_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onclienthello");
onnewsession_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onnewsession");
subject_sym = FIXED_ONE_BYTE_STRING(node_isolate, "subject");
issuer_sym = FIXED_ONE_BYTE_STRING(node_isolate, "issuer");
@ -1322,9 +735,6 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
name_sym = FIXED_ONE_BYTE_STRING(node_isolate, "name");
version_sym = FIXED_ONE_BYTE_STRING(node_isolate, "version");
ext_key_usage_sym = FIXED_ONE_BYTE_STRING(node_isolate, "ext_key_usage");
sessionid_sym = FIXED_ONE_BYTE_STRING(node_isolate, "sessionId");
tls_ticket_sym = FIXED_ONE_BYTE_STRING(node_isolate, "tlsTicket");
servername_sym = FIXED_ONE_BYTE_STRING(node_isolate, "servername");
sni_context_sym = FIXED_ONE_BYTE_STRING(node_isolate, "sni_context");
}

63
src/tls_wrap.h

@ -23,7 +23,7 @@
#define SRC_TLS_WRAP_H_
#include "node.h"
#include "node_crypto_clienthello.h"
#include "node_crypto.h" // SSLWrap
#include "queue.h"
#include "stream_wrap.h"
#include "v8.h"
@ -39,13 +39,9 @@ namespace crypto {
class SecureContext;
}
class TLSCallbacks : public StreamWrapCallbacks {
class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
public StreamWrapCallbacks {
public:
enum Kind {
kTLSClient,
kTLSServer
};
static void Initialize(v8::Handle<v8::Object> target);
int DoWrite(WriteWrap* w,
@ -61,6 +57,11 @@ class TLSCallbacks : public StreamWrapCallbacks {
uv_handle_type pending);
int DoShutdown(ShutdownWrap* req_wrap, uv_shutdown_cb cb);
// Just for compliance with Connection
inline v8::Local<v8::Object> handle(v8::Isolate* isolate) {
return object(isolate);
}
protected:
static const int kClearOutChunkSize = 1024;
@ -97,69 +98,33 @@ class TLSCallbacks : public StreamWrapCallbacks {
}
v8::Handle<v8::Value> GetSSLError(int status, int* err);
static void OnClientHello(void* arg,
const ClientHelloParser::ClientHello& hello);
static void OnClientHelloParseEnd(void* arg);
static void Wrap(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetPeerCertificate(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EndParser(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetVerifyMode(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnableSessionCallbacks(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void EnableHelloParser(
const v8::FunctionCallbackInfo<v8::Value>& args);
// TLS Session API
static SSL_SESSION* GetSessionCallback(SSL* s,
unsigned char* key,
int len,
int* copy);
static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
#ifdef OPENSSL_NPN_NEGOTIATED
static void GetNegotiatedProto(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
static int AdvertiseNextProtoCallback(SSL* s,
const unsigned char** data,
unsigned int* len,
void* arg);
static int SelectNextProtoCallback(SSL* s,
unsigned char** out,
unsigned char* outlen,
const unsigned char* in,
unsigned int inlen,
void* arg);
#endif // OPENSSL_NPN_NEGOTIATED
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
static int SelectSNIContextCallback(SSL* s, int* ad, void* arg);
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
inline v8::Local<v8::Object> object() {
return PersistentToLocal(node_isolate, persistent());
inline v8::Local<v8::Object> object(v8::Isolate* isolate) {
return PersistentToLocal(isolate, persistent());
}
inline v8::Persistent<v8::Object>& persistent() {
return object_;
}
Kind kind_;
crypto::SecureContext* sc_;
v8::Persistent<v8::Object> sc_handle_;
v8::Persistent<v8::Object> object_;
SSL* ssl_;
BIO* enc_in_;
BIO* enc_out_;
NodeBIO* clear_in_;
@ -171,14 +136,6 @@ class TLSCallbacks : public StreamWrapCallbacks {
bool started_;
bool established_;
bool shutdown_;
bool session_callbacks_;
SSL_SESSION* next_sess_;
ClientHelloParser hello_;
#ifdef OPENSSL_NPN_NEGOTIATED
v8::Persistent<v8::Object> npn_protos_;
v8::Persistent<v8::Value> selected_npn_proto_;
#endif // OPENSSL_NPN_NEGOTIATED
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
v8::Persistent<v8::Value> sni_context_;

Loading…
Cancel
Save