1 // Copyright Joyent, Inc. and other Node contributors.
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #include "async-wrap.h"
24 #include "async-wrap-inl.h"
25 #include "node_buffer.h" // Buffer
26 #include "node_crypto.h" // SecureContext
27 #include "node_crypto_bio.h" // NodeBIO
28 #include "node_crypto_clienthello.h" // ClientHelloParser
29 #include "node_crypto_clienthello-inl.h"
30 #include "node_wrap.h" // WithGenericStream
31 #include "node_counters.h"
32 #include "node_internals.h"
38 using crypto::SSLWrap;
39 using crypto::SecureContext;
44 using v8::FunctionCallbackInfo;
45 using v8::FunctionTemplate;
47 using v8::HandleScope;
55 static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
56 | ASN1_STRFLGS_ESC_MSB
57 | XN_FLAG_SEP_MULTILINE
61 size_t TLSCallbacks::error_off_;
62 char TLSCallbacks::error_buf_[1024];
65 TLSCallbacks::TLSCallbacks(Environment* env,
68 StreamWrapCallbacks* old)
69 : SSLWrap<TLSCallbacks>(env, Unwrap<SecureContext>(sc), kind),
70 StreamWrapCallbacks(old),
71 AsyncWrap(env, env->tls_wrap_constructor_function()->NewInstance()),
72 sc_(Unwrap<SecureContext>(sc)),
73 sc_handle_(env->isolate(), sc),
83 node::Wrap<TLSCallbacks>(object(), this);
85 // Initialize queue for clearIn writes
86 QUEUE_INIT(&write_item_queue_);
87 QUEUE_INIT(&pending_write_items_);
89 // We've our own session callbacks
90 SSL_CTX_sess_set_get_cb(sc_->ctx_, SSLWrap<TLSCallbacks>::GetSessionCallback);
91 SSL_CTX_sess_set_new_cb(sc_->ctx_, SSLWrap<TLSCallbacks>::NewSessionCallback);
97 TLSCallbacks::~TLSCallbacks() {
104 sc_handle_.Dispose();
105 persistent().Dispose();
107 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
108 sni_context_.Dispose();
109 #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
111 // Move all writes to pending
115 while (!QUEUE_EMPTY(&pending_write_items_)) {
116 QUEUE* q = QUEUE_HEAD(&pending_write_items_);
119 WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
125 void TLSCallbacks::MakePending() {
127 QUEUE* from = &write_item_queue_;
128 QUEUE* to = &pending_write_items_;
130 if (QUEUE_EMPTY(from))
133 // Add items to pending
136 // Empty original queue
141 bool TLSCallbacks::InvokeQueued(int status) {
142 if (QUEUE_EMPTY(&pending_write_items_))
146 while (!QUEUE_EMPTY(&pending_write_items_)) {
147 QUEUE* q = QUEUE_HEAD(&pending_write_items_);
150 WriteItem* wi = QUEUE_DATA(q, WriteItem, member_);
151 wi->cb_(&wi->w_->req_, status);
159 void TLSCallbacks::InitSSL() {
161 enc_in_ = NodeBIO::New();
162 enc_out_ = NodeBIO::New();
164 SSL_set_bio(ssl_, enc_in_, enc_out_);
166 // NOTE: This could be overriden in SetVerifyMode
167 SSL_set_verify(ssl_, SSL_VERIFY_NONE, crypto::VerifyCallback);
169 #ifdef SSL_MODE_RELEASE_BUFFERS
170 long mode = SSL_get_mode(ssl_);
171 SSL_set_mode(ssl_, mode | SSL_MODE_RELEASE_BUFFERS);
172 #endif // SSL_MODE_RELEASE_BUFFERS
174 SSL_set_app_data(ssl_, this);
175 SSL_set_info_callback(ssl_, SSLInfoCallback);
177 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
179 SSL_CTX_set_tlsext_servername_callback(sc_->ctx_, SelectSNIContextCallback);
180 SSL_CTX_set_tlsext_servername_arg(sc_->ctx_, this);
182 #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
187 SSL_set_accept_state(ssl_);
188 } else if (is_client()) {
189 SSL_set_connect_state(ssl_);
195 // Initialize ring for queud clear data
196 clear_in_ = new NodeBIO();
200 void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
201 HandleScope handle_scope(args.GetIsolate());
202 Environment* env = Environment::GetCurrent(args.GetIsolate());
204 if (args.Length() < 1 || !args[0]->IsObject())
205 return ThrowTypeError("First argument should be a StreamWrap instance");
206 if (args.Length() < 2 || !args[1]->IsObject())
207 return ThrowTypeError("Second argument should be a SecureContext instance");
208 if (args.Length() < 3 || !args[2]->IsBoolean())
209 return ThrowTypeError("Third argument should be boolean");
211 Local<Object> stream = args[0].As<Object>();
212 Local<Object> sc = args[1].As<Object>();
213 Kind kind = args[2]->IsTrue() ? SSLWrap<TLSCallbacks>::kServer :
214 SSLWrap<TLSCallbacks>::kClient;
216 TLSCallbacks* callbacks = NULL;
217 WITH_GENERIC_STREAM(env, stream, {
218 callbacks = new TLSCallbacks(env, kind, sc, wrap->callbacks());
219 wrap->OverrideCallbacks(callbacks);
222 if (callbacks == NULL) {
223 return args.GetReturnValue().SetNull();
226 args.GetReturnValue().Set(callbacks->persistent());
230 void TLSCallbacks::Receive(const FunctionCallbackInfo<Value>& args) {
231 HandleScope handle_scope(args.GetIsolate());
233 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
235 CHECK(Buffer::HasInstance(args[0]));
236 char* data = Buffer::Data(args[0]);
237 size_t len = Buffer::Length(args[0]);
240 uv_stream_t* stream = wrap->wrap()->stream();
242 // Copy given buffer entirely or partiall if handle becomes closed
243 while (len > 0 && !uv_is_closing(reinterpret_cast<uv_handle_t*>(stream))) {
244 wrap->DoAlloc(reinterpret_cast<uv_handle_t*>(stream), len, &buf);
245 size_t copy = buf.len > len ? len : buf.len;
246 memcpy(buf.base, data, copy);
247 wrap->DoRead(stream, buf.len, &buf, UV_UNKNOWN_HANDLE);
255 void TLSCallbacks::Start(const FunctionCallbackInfo<Value>& args) {
256 HandleScope scope(node_isolate);
258 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
261 return ThrowError("Already started.");
262 wrap->started_ = true;
264 // Send ClientHello handshake
265 assert(wrap->is_client());
271 void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
272 if (!(where & (SSL_CB_HANDSHAKE_START | SSL_CB_HANDSHAKE_DONE)))
275 // Be compatible with older versions of OpenSSL. SSL_get_app_data() wants
276 // a non-const SSL* in OpenSSL <= 0.9.7e.
277 SSL* ssl = const_cast<SSL*>(ssl_);
278 TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
279 Environment* env = c->env();
280 HandleScope handle_scope(env->isolate());
281 Context::Scope context_scope(env->context());
282 Local<Object> object = c->object();
284 if (where & SSL_CB_HANDSHAKE_START) {
285 Local<Value> callback = object->Get(env->onhandshakestart_string());
286 if (callback->IsFunction()) {
287 c->MakeCallback(callback.As<Function>(), 0, NULL);
291 if (where & SSL_CB_HANDSHAKE_DONE) {
292 c->established_ = true;
293 Local<Value> callback = object->Get(env->onhandshakedone_string());
294 if (callback->IsFunction()) {
295 c->MakeCallback(callback.As<Function>(), 0, NULL);
301 void TLSCallbacks::EncOut() {
302 // Ignore cycling data if ClientHello wasn't yet parsed
303 if (!hello_parser_.IsEnded())
307 if (write_size_ != 0)
311 if (established_ && !QUEUE_EMPTY(&write_item_queue_))
315 if (BIO_pending(enc_out_) == 0) {
316 if (clear_in_->Length() == 0)
321 char* data[kSimultaneousBufferCount];
322 size_t size[ARRAY_SIZE(data)];
323 size_t count = ARRAY_SIZE(data);
324 write_size_ = NodeBIO::FromBIO(enc_out_)->PeekMultiple(data, size, &count);
325 assert(write_size_ != 0 && count != 0);
327 write_req_.data = this;
328 uv_buf_t buf[ARRAY_SIZE(data)];
329 for (size_t i = 0; i < count; i++)
330 buf[i] = uv_buf_init(data[i], size[i]);
331 int r = uv_write(&write_req_, wrap()->stream(), buf, count, EncOutCb);
333 // Ignore errors, this should be already handled in js
335 if (wrap()->is_tcp()) {
336 NODE_COUNT_NET_BYTES_SENT(write_size_);
337 } else if (wrap()->is_named_pipe()) {
338 NODE_COUNT_PIPE_BYTES_SENT(write_size_);
344 void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
345 TLSCallbacks* callbacks = static_cast<TLSCallbacks*>(req->data);
349 // Ignore errors after shutdown
350 if (callbacks->shutdown_)
353 // Notify about error
354 callbacks->InvokeQueued(status);
359 NodeBIO::FromBIO(callbacks->enc_out_)->Read(NULL, callbacks->write_size_);
361 // Try writing more data
362 callbacks->write_size_ = 0;
367 int TLSCallbacks::PrintErrorsCb(const char* str, size_t len, void* arg) {
368 size_t to_copy = error_off_;
369 size_t avail = sizeof(error_buf_) - error_off_ - 1;
374 memcpy(error_buf_, str, avail);
376 assert(error_off_ < sizeof(error_buf_));
379 error_buf_[error_off_] = '\0';
385 const char* TLSCallbacks::PrintErrors() {
387 ERR_print_errors_cb(PrintErrorsCb, this);
393 Local<Value> TLSCallbacks::GetSSLError(int status, int* err, const char** msg) {
394 HandleScope scope(node_isolate);
396 *err = SSL_get_error(ssl_, status);
399 case SSL_ERROR_WANT_READ:
400 case SSL_ERROR_WANT_WRITE:
402 case SSL_ERROR_ZERO_RETURN:
403 return scope.Close(FIXED_ONE_BYTE_STRING(node_isolate, "ZERO_RETURN"));
407 assert(*err == SSL_ERROR_SSL || *err == SSL_ERROR_SYSCALL);
409 const char* buf = PrintErrors();
411 Local<String> message =
412 OneByteString(node_isolate, buf, strlen(buf));
413 Local<Value> exception = Exception::Error(message);
416 assert(*msg == NULL);
420 return scope.Close(exception);
423 return Local<Value>();
427 void TLSCallbacks::ClearOut() {
428 // Ignore cycling data if ClientHello wasn't yet parsed
429 if (!hello_parser_.IsEnded())
432 HandleScope handle_scope(env()->isolate());
433 Context::Scope context_scope(env()->context());
435 assert(ssl_ != NULL);
437 char out[kClearOutChunkSize];
440 read = SSL_read(ssl_, out, sizeof(out));
442 Local<Value> argv[] = {
443 Integer::New(read, node_isolate),
444 Buffer::New(env(), out, read)
446 wrap()->MakeCallback(env()->onread_string(), ARRAY_SIZE(argv), argv);
450 int flags = SSL_get_shutdown(ssl_);
451 if (!eof_ && flags & SSL_RECEIVED_SHUTDOWN) {
453 Local<Value> arg = Integer::New(UV_EOF, node_isolate);
454 wrap()->MakeCallback(env()->onread_string(), 1, &arg);
459 Local<Value> arg = GetSSLError(read, &err, NULL);
461 if (!arg.IsEmpty()) {
462 MakeCallback(env()->onerror_string(), 1, &arg);
468 bool TLSCallbacks::ClearIn() {
469 // Ignore cycling data if ClientHello wasn't yet parsed
470 if (!hello_parser_.IsEnded())
474 while (clear_in_->Length() > 0) {
476 char* data = clear_in_->Peek(&avail);
477 written = SSL_write(ssl_, data, avail);
478 assert(written == -1 || written == static_cast<int>(avail));
481 clear_in_->Read(NULL, avail);
485 if (clear_in_->Length() == 0) {
486 assert(written >= 0);
490 HandleScope handle_scope(env()->isolate());
491 Context::Scope context_scope(env()->context());
493 // Error or partial write
495 Local<Value> arg = GetSSLError(written, &err, &error_);
496 if (!arg.IsEmpty()) {
498 if (!InvokeQueued(UV_EPROTO))
507 const char* TLSCallbacks::Error() {
508 const char* ret = error_;
514 int TLSCallbacks::TryWrite(uv_buf_t** bufs, size_t* count) {
515 // TODO(indutny): Support it
520 int TLSCallbacks::DoWrite(WriteWrap* w,
523 uv_stream_t* send_handle,
525 assert(send_handle == NULL);
527 // Queue callback to execute it on next tick
528 WriteItem* wi = new WriteItem(w, cb);
531 // Empty writes should not go through encryption process
533 for (i = 0; i < count; i++)
534 if (bufs[i].len > 0) {
540 // However if there any data that should be written to socket,
541 // callback should not be invoked immediately
542 if (BIO_pending(enc_out_) == 0)
543 return uv_write(&w->req_, wrap()->stream(), bufs, count, cb);
546 QUEUE_INSERT_TAIL(&write_item_queue_, &wi->member_);
554 // Process enqueued data first
556 // If there're still data to process - enqueue current one
557 for (i = 0; i < count; i++)
558 clear_in_->Write(bufs[i].base, bufs[i].len);
563 for (i = 0; i < count; i++) {
564 written = SSL_write(ssl_, bufs[i].base, bufs[i].len);
565 assert(written == -1 || written == static_cast<int>(bufs[i].len));
572 HandleScope handle_scope(env()->isolate());
573 Context::Scope context_scope(env()->context());
574 Local<Value> arg = GetSSLError(written, &err, &error_);
578 // No errors, queue rest
579 for (; i < count; i++)
580 clear_in_->Write(bufs[i].base, bufs[i].len);
583 // Try writing data immediately
590 void TLSCallbacks::AfterWrite(WriteWrap* w) {
591 // Intentionally empty
595 void TLSCallbacks::DoAlloc(uv_handle_t* handle,
596 size_t suggested_size,
598 buf->base = NodeBIO::FromBIO(enc_in_)->PeekWritable(&suggested_size);
599 buf->len = suggested_size;
603 void TLSCallbacks::DoRead(uv_stream_t* handle,
606 uv_handle_type pending) {
608 // Error should be emitted only after all data was read
611 // Ignore EOF if received close_notify
612 if (nread == UV_EOF) {
618 HandleScope handle_scope(env()->isolate());
619 Context::Scope context_scope(env()->context());
620 Local<Value> arg = Integer::New(nread, node_isolate);
621 wrap()->MakeCallback(env()->onread_string(), 1, &arg);
625 // Only client connections can receive data
626 assert(ssl_ != NULL);
629 NodeBIO* enc_in = NodeBIO::FromBIO(enc_in_);
630 enc_in->Commit(nread);
632 // Parse ClientHello first
633 if (!hello_parser_.IsEnded()) {
635 uint8_t* data = reinterpret_cast<uint8_t*>(enc_in->Peek(&avail));
636 assert(avail == 0 || data != NULL);
637 return hello_parser_.Parse(data, avail);
640 // Cycle OpenSSL's state
645 int TLSCallbacks::DoShutdown(ShutdownWrap* req_wrap, uv_shutdown_cb cb) {
646 if (SSL_shutdown(ssl_) == 0)
650 return StreamWrapCallbacks::DoShutdown(req_wrap, cb);
654 void TLSCallbacks::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
655 HandleScope scope(node_isolate);
657 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
659 if (args.Length() < 2 || !args[0]->IsBoolean() || !args[1]->IsBoolean())
660 return ThrowTypeError("Bad arguments, expected two booleans");
663 if (wrap->is_server()) {
664 bool request_cert = args[0]->IsTrue();
666 // Note reject_unauthorized ignored.
667 verify_mode = SSL_VERIFY_NONE;
669 bool reject_unauthorized = args[1]->IsTrue();
670 verify_mode = SSL_VERIFY_PEER;
671 if (reject_unauthorized)
672 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
675 // Note request_cert and reject_unauthorized are ignored for clients.
676 verify_mode = SSL_VERIFY_NONE;
679 // Always allow a connection. We'll reject in javascript.
680 SSL_set_verify(wrap->ssl_, verify_mode, crypto::VerifyCallback);
684 void TLSCallbacks::EnableSessionCallbacks(
685 const FunctionCallbackInfo<Value>& args) {
686 HandleScope scope(node_isolate);
688 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
690 wrap->enable_session_callbacks();
691 EnableHelloParser(args);
695 void TLSCallbacks::EnableHelloParser(const FunctionCallbackInfo<Value>& args) {
696 HandleScope scope(node_isolate);
698 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
700 wrap->hello_parser_.Start(SSLWrap<TLSCallbacks>::OnClientHello,
701 OnClientHelloParseEnd,
706 void TLSCallbacks::OnClientHelloParseEnd(void* arg) {
707 TLSCallbacks* c = static_cast<TLSCallbacks*>(arg);
712 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
713 void TLSCallbacks::GetServername(const FunctionCallbackInfo<Value>& args) {
714 HandleScope scope(node_isolate);
716 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
718 const char* servername = SSL_get_servername(wrap->ssl_,
719 TLSEXT_NAMETYPE_host_name);
720 if (servername != NULL) {
721 args.GetReturnValue().Set(OneByteString(node_isolate, servername));
723 args.GetReturnValue().Set(false);
728 void TLSCallbacks::SetServername(const FunctionCallbackInfo<Value>& args) {
729 HandleScope scope(node_isolate);
731 TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
733 if (args.Length() < 1 || !args[0]->IsString())
734 return ThrowTypeError("First argument should be a string");
737 return ThrowError("Already started.");
739 if (!wrap->is_client())
742 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
743 String::Utf8Value servername(args[0].As<String>());
744 SSL_set_tlsext_host_name(wrap->ssl_, *servername);
745 #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
749 int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
750 HandleScope scope(node_isolate);
752 TLSCallbacks* p = static_cast<TLSCallbacks*>(arg);
753 Environment* env = p->env();
755 const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
757 if (servername != NULL) {
758 // Call the SNI callback and use its return value as context
759 Local<Object> object = p->object();
760 Local<Value> ctx = object->Get(env->sni_context_string());
762 if (!ctx->IsObject())
763 return SSL_TLSEXT_ERR_NOACK;
765 p->sni_context_.Dispose();
766 p->sni_context_.Reset(node_isolate, ctx);
768 SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>());
770 SSL_set_SSL_CTX(s, sc->ctx_);
773 return SSL_TLSEXT_ERR_OK;
775 #endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
778 void TLSCallbacks::Initialize(Handle<Object> target,
779 Handle<Value> unused,
780 Handle<Context> context) {
781 Environment* env = Environment::GetCurrent(context);
783 NODE_SET_METHOD(target, "wrap", TLSCallbacks::Wrap);
785 Local<FunctionTemplate> t = FunctionTemplate::New();
786 t->InstanceTemplate()->SetInternalFieldCount(1);
787 t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TLSWrap"));
789 NODE_SET_PROTOTYPE_METHOD(t, "receive", Receive);
790 NODE_SET_PROTOTYPE_METHOD(t, "start", Start);
791 NODE_SET_PROTOTYPE_METHOD(t, "setVerifyMode", SetVerifyMode);
792 NODE_SET_PROTOTYPE_METHOD(t,
793 "enableSessionCallbacks",
794 EnableSessionCallbacks);
795 NODE_SET_PROTOTYPE_METHOD(t,
799 SSLWrap<TLSCallbacks>::AddMethods(t);
801 #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
802 NODE_SET_PROTOTYPE_METHOD(t, "getServername", GetServername);
803 NODE_SET_PROTOTYPE_METHOD(t, "setServername", SetServername);
804 #endif // SSL_CRT_SET_TLSEXT_SERVERNAME_CB
806 env->set_tls_wrap_constructor_function(t->GetFunction());
811 NODE_MODULE_CONTEXT_AWARE_BUILTIN(tls_wrap, node::TLSCallbacks::Initialize)