Skip to content

Commit

Permalink
tls,crypto: move NPN protcol data to hidden value
Browse files Browse the repository at this point in the history
This fix is to be consistent implementation with ALPN. Tow NPN
protocol data in the persistent memebers move to hidden variables in
the wrap object.

PR-URL: nodejs#2564
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
  • Loading branch information
Shigeki Ohtsu committed Oct 26, 2015
1 parent 802a2e7 commit 7eee372
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 27 deletions.
2 changes: 2 additions & 0 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ namespace node {
V(netmask_string, "netmask") \
V(nice_string, "nice") \
V(nlink_string, "nlink") \
V(npn_buffer_string, "npnBuffer") \
V(nsname_string, "nsname") \
V(ocsp_request_string, "OCSPRequest") \
V(offset_string, "offset") \
Expand Down Expand Up @@ -181,6 +182,7 @@ namespace node {
V(serial_string, "serial") \
V(scavenge_string, "scavenge") \
V(scopeid_string, "scopeid") \
V(selected_npn_buffer_string, "selectedNpnBuffer") \
V(sent_shutdown_string, "sentShutdown") \
V(serial_number_string, "serialNumber") \
V(service_string, "service") \
Expand Down
48 changes: 30 additions & 18 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1917,14 +1917,17 @@ int SSLWrap<Base>::AdvertiseNextProtoCallback(SSL* s,
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());

if (w->npn_protos_.IsEmpty()) {
Local<Value> npn_buffer =
w->object()->GetHiddenValue(env->npn_buffer_string());

if (npn_buffer.IsEmpty()) {
// No initialization - no NPN protocols
*data = reinterpret_cast<const unsigned char*>("");
*len = 0;
} else {
Local<Object> obj = PersistentToLocal(env->isolate(), w->npn_protos_);
*data = reinterpret_cast<const unsigned char*>(Buffer::Data(obj));
*len = Buffer::Length(obj);
CHECK(Buffer::HasInstance(npn_buffer));
*data = reinterpret_cast<const unsigned char*>(Buffer::Data(npn_buffer));
*len = Buffer::Length(npn_buffer);
}

return SSL_TLSEXT_ERR_OK;
Expand All @@ -1943,25 +1946,27 @@ int SSLWrap<Base>::SelectNextProtoCallback(SSL* s,
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());

// Release old protocol handler if present
w->selected_npn_proto_.Reset();
Local<Value> npn_buffer =
w->object()->GetHiddenValue(env->npn_buffer_string());

if (w->npn_protos_.IsEmpty()) {
if (npn_buffer.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
w->selected_npn_proto_.Reset(env->isolate(), False(env->isolate()));
bool r = w->object()->SetHiddenValue(env->selected_npn_buffer_string(),
False(env->isolate()));
CHECK(r);

return SSL_TLSEXT_ERR_OK;
}

Local<Object> obj = PersistentToLocal(env->isolate(), w->npn_protos_);
CHECK(Buffer::HasInstance(npn_buffer));
const unsigned char* npn_protos =
reinterpret_cast<const unsigned char*>(Buffer::Data(obj));
size_t len = Buffer::Length(obj);
reinterpret_cast<const unsigned char*>(Buffer::Data(npn_buffer));
size_t len = Buffer::Length(npn_buffer);

int status = SSL_select_next_proto(out, outlen, in, inlen, npn_protos, len);
Local<Value> result;
Expand All @@ -1979,8 +1984,9 @@ int SSLWrap<Base>::SelectNextProtoCallback(SSL* s,
break;
}

if (!result.IsEmpty())
w->selected_npn_proto_.Reset(env->isolate(), result);
bool r = w->object()->SetHiddenValue(env->selected_npn_buffer_string(),
result);
CHECK(r);

return SSL_TLSEXT_ERR_OK;
}
Expand All @@ -1992,9 +1998,12 @@ void SSLWrap<Base>::GetNegotiatedProto(
Base* w = Unwrap<Base>(args.Holder());

if (w->is_client()) {
if (w->selected_npn_proto_.IsEmpty() == false) {
args.GetReturnValue().Set(w->selected_npn_proto_);
}
Local<Value> selected_npn_buffer =
w->object()->GetHiddenValue(w->env()->selected_npn_buffer_string());

if (selected_npn_buffer.IsEmpty() == false)
args.GetReturnValue().Set(selected_npn_buffer);

return;
}

Expand All @@ -2014,11 +2023,14 @@ void SSLWrap<Base>::GetNegotiatedProto(
template <class Base>
void SSLWrap<Base>::SetNPNProtocols(const FunctionCallbackInfo<Value>& args) {
Base* w = Unwrap<Base>(args.Holder());
Environment* env = w->env();

if (args.Length() < 1 || !Buffer::HasInstance(args[0]))
return w->env()->ThrowTypeError("Must give a Buffer as first argument");
return env->ThrowTypeError("Must give a Buffer as first argument");

w->npn_protos_.Reset(args.GetIsolate(), args[0].As<Object>());
Local<Value> npn_buffer = Local<Value>::New(env->isolate(), args[0]);
bool r = w->object()->SetHiddenValue(env->npn_buffer_string(), npn_buffer);
CHECK(r);
}
#endif // OPENSSL_NPN_NEGOTIATED

Expand Down
9 changes: 0 additions & 9 deletions src/node_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,6 @@ class SSLWrap {
next_sess_ = nullptr;
}

#ifdef OPENSSL_NPN_NEGOTIATED
npn_protos_.Reset();
selected_npn_proto_.Reset();
#endif
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
sni_context_.Reset();
#endif
Expand Down Expand Up @@ -298,11 +294,6 @@ class SSLWrap {
v8::Persistent<v8::Object> ocsp_response_;
#endif // NODE__HAVE_TLSEXT_STATUS_CB

#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_;
#endif
Expand Down

0 comments on commit 7eee372

Please sign in to comment.