@@ -49,7 +49,6 @@ using v8::Value;
49
49
50
50
static Cached<String> onread_sym;
51
51
static Cached<String> onerror_sym;
52
- static Cached<String> onsniselect_sym;
53
52
static Cached<String> onhandshakestart_sym;
54
53
static Cached<String> onhandshakedone_sym;
55
54
static Cached<String> onclienthello_sym;
@@ -67,6 +66,8 @@ static Cached<String> version_sym;
67
66
static Cached<String> ext_key_usage_sym;
68
67
static Cached<String> sessionid_sym;
69
68
static Cached<String> tls_ticket_sym;
69
+ static Cached<String> servername_sym;
70
+ static Cached<String> sni_context_sym;
70
71
71
72
static Persistent<Function> tlsWrap;
72
73
@@ -174,7 +175,6 @@ TLSCallbacks::~TLSCallbacks() {
174
175
#endif // OPENSSL_NPN_NEGOTIATED
175
176
176
177
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
177
- servername_.Dispose ();
178
178
sni_context_.Dispose ();
179
179
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
180
180
}
@@ -640,7 +640,6 @@ void TLSCallbacks::DoRead(uv_stream_t* handle,
640
640
641
641
// Parse ClientHello first
642
642
if (!hello_.IsEnded ()) {
643
- assert (session_callbacks_);
644
643
size_t avail = 0 ;
645
644
uint8_t * data = reinterpret_cast <uint8_t *>(enc_in->Peek (&avail));
646
645
assert (avail == 0 || data != NULL );
@@ -770,6 +769,16 @@ void TLSCallbacks::EnableSessionCallbacks(
770
769
UNWRAP (TLSCallbacks);
771
770
772
771
wrap->session_callbacks_ = true ;
772
+ EnableHelloParser (args);
773
+ }
774
+
775
+
776
+ void TLSCallbacks::EnableHelloParser (
777
+ const FunctionCallbackInfo<Value>& args) {
778
+ HandleScope scope (node_isolate);
779
+
780
+ UNWRAP (TLSCallbacks);
781
+
773
782
wrap->hello_ .Start (OnClientHello, OnClientHelloParseEnd, wrap);
774
783
}
775
784
@@ -785,6 +794,14 @@ void TLSCallbacks::OnClientHello(void* arg,
785
794
reinterpret_cast <const char *>(hello.session_id ()),
786
795
hello.session_size ());
787
796
hello_obj->Set (sessionid_sym, buff);
797
+ if (hello.servername () == NULL ) {
798
+ hello_obj->Set (servername_sym, String::Empty (node_isolate));
799
+ } else {
800
+ Local<String> servername = String::New (
801
+ reinterpret_cast <const char *>(hello.servername ()),
802
+ hello.servername_size ());
803
+ hello_obj->Set (servername_sym, servername);
804
+ }
788
805
hello_obj->Set (tls_ticket_sym, Boolean::New (hello.has_ticket ()));
789
806
790
807
Handle <Value> argv[1 ] = { hello_obj };
@@ -999,7 +1016,23 @@ void TLSCallbacks::LoadSession(const FunctionCallbackInfo<Value>& args) {
999
1016
if (wrap->next_sess_ != NULL )
1000
1017
SSL_SESSION_free (wrap->next_sess_ );
1001
1018
wrap->next_sess_ = sess;
1019
+
1020
+ Local<Object> info = Object::New ();
1021
+ #ifndef OPENSSL_NO_TLSEXT
1022
+ if (sess->tlsext_hostname == NULL ) {
1023
+ info->Set (servername_sym, False (node_isolate));
1024
+ } else {
1025
+ info->Set (servername_sym, String::New (sess->tlsext_hostname ));
1026
+ }
1027
+ #endif
1028
+ args.GetReturnValue ().Set (info);
1002
1029
}
1030
+ }
1031
+
1032
+ void TLSCallbacks::EndParser (const FunctionCallbackInfo<Value>& args) {
1033
+ HandleScope scope (node_isolate);
1034
+
1035
+ UNWRAP (TLSCallbacks);
1003
1036
1004
1037
wrap->hello_ .End ();
1005
1038
}
@@ -1143,8 +1176,10 @@ void TLSCallbacks::GetServername(const FunctionCallbackInfo<Value>& args) {
1143
1176
1144
1177
UNWRAP (TLSCallbacks);
1145
1178
1146
- if (wrap->kind_ == kTLSServer && !wrap->servername_ .IsEmpty ()) {
1147
- args.GetReturnValue ().Set (wrap->servername_ );
1179
+ const char * servername = SSL_get_servername (wrap->ssl_ ,
1180
+ TLSEXT_NAMETYPE_host_name);
1181
+ if (servername != NULL ) {
1182
+ args.GetReturnValue ().Set (String::New (servername));
1148
1183
} else {
1149
1184
args.GetReturnValue ().Set (false );
1150
1185
}
@@ -1179,25 +1214,22 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
1179
1214
1180
1215
const char * servername = SSL_get_servername (s, TLSEXT_NAMETYPE_host_name);
1181
1216
1182
- if (servername) {
1183
- p->servername_ .Reset (node_isolate, String::New (servername));
1184
-
1217
+ if (servername != NULL ) {
1185
1218
// Call the SNI callback and use its return value as context
1186
1219
Local<Object> object = p->object ();
1187
- if (object->Has (onsniselect_sym)) {
1188
- p->sni_context_ .Dispose ();
1220
+ Local<Value> ctx;
1221
+ if (object->Has (sni_context_sym)) {
1222
+ ctx = object->Get (sni_context_sym);
1223
+ }
1189
1224
1190
- Local<Value> arg = PersistentToLocal (node_isolate, p-> servername_ );
1191
- Handle <Value> ret = MakeCallback (object, onsniselect_sym, 1 , &arg) ;
1225
+ if (ctx. IsEmpty () || ctx-> IsUndefined ())
1226
+ return SSL_TLSEXT_ERR_NOACK ;
1192
1227
1193
- // If ret is SecureContext
1194
- if (ret->IsUndefined ())
1195
- return SSL_TLSEXT_ERR_NOACK;
1228
+ p->sni_context_ .Dispose ();
1229
+ p->sni_context_ .Reset (node_isolate, ctx);
1196
1230
1197
- p->sni_context_ .Reset (node_isolate, ret);
1198
- SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(ret.As <Object>());
1199
- SSL_set_SSL_CTX (s, sc->ctx_ );
1200
- }
1231
+ SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(ctx.As <Object>());
1232
+ SSL_set_SSL_CTX (s, sc->ctx_ );
1201
1233
}
1202
1234
1203
1235
return SSL_TLSEXT_ERR_OK;
@@ -1219,13 +1251,17 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
1219
1251
NODE_SET_PROTOTYPE_METHOD (t, " getSession" , GetSession);
1220
1252
NODE_SET_PROTOTYPE_METHOD (t, " setSession" , SetSession);
1221
1253
NODE_SET_PROTOTYPE_METHOD (t, " loadSession" , LoadSession);
1254
+ NODE_SET_PROTOTYPE_METHOD (t, " endParser" , EndParser);
1222
1255
NODE_SET_PROTOTYPE_METHOD (t, " getCurrentCipher" , GetCurrentCipher);
1223
1256
NODE_SET_PROTOTYPE_METHOD (t, " verifyError" , VerifyError);
1224
1257
NODE_SET_PROTOTYPE_METHOD (t, " setVerifyMode" , SetVerifyMode);
1225
1258
NODE_SET_PROTOTYPE_METHOD (t, " isSessionReused" , IsSessionReused);
1226
1259
NODE_SET_PROTOTYPE_METHOD (t,
1227
1260
" enableSessionCallbacks" ,
1228
1261
EnableSessionCallbacks);
1262
+ NODE_SET_PROTOTYPE_METHOD (t,
1263
+ " enableHelloParser" ,
1264
+ EnableHelloParser);
1229
1265
1230
1266
#ifdef OPENSSL_NPN_NEGOTIATED
1231
1267
NODE_SET_PROTOTYPE_METHOD (t, " getNegotiatedProtocol" , GetNegotiatedProto);
@@ -1240,7 +1276,6 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
1240
1276
tlsWrap.Reset (node_isolate, t->GetFunction ());
1241
1277
1242
1278
onread_sym = String::New (" onread" );
1243
- onsniselect_sym = String::New (" onsniselect" );
1244
1279
onerror_sym = String::New (" onerror" );
1245
1280
onhandshakestart_sym = String::New (" onhandshakestart" );
1246
1281
onhandshakedone_sym = String::New (" onhandshakedone" );
@@ -1260,6 +1295,8 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
1260
1295
ext_key_usage_sym = String::New (" ext_key_usage" );
1261
1296
sessionid_sym = String::New (" sessionId" );
1262
1297
tls_ticket_sym = String::New (" tlsTicket" );
1298
+ servername_sym = String::New (" servername" );
1299
+ sni_context_sym = String::New (" sni_context" );
1263
1300
}
1264
1301
1265
1302
} // namespace node
0 commit comments