diff --git a/src/node_crypto.cc b/src/node_crypto.cc index efc48ed9770..9296177daf8 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -242,6 +242,31 @@ Handle SecureContext::Close(const Arguments& args) { return False(); } +char ssl_error_buf[512]; + +static int serr(SSL *ssl, const char* func, int rv) +{ + if (rv >= 0) { + return rv; + } + + int err = SSL_get_error(ssl, rv); + if (err != SSL_ERROR_WANT_WRITE && + err != SSL_ERROR_WANT_READ) { + /* TODO: look at ssl error queue */ + ERR_error_string_n(ERR_get_error(), &ssl_error_buf[0], sizeof(ssl_error_buf)); + /* fprintf(stderr, "[%p] SSL: %s failed: (%d:%d) %s\n", ssl, func, err, rv, buf); */ + return rv; + } + else if (err == SSL_ERROR_WANT_WRITE) { + /* fprintf(stderr, "[%p] SSL: %s want write\n", ssl, func); */ + } + else if (err == SSL_ERROR_WANT_READ) { + /* fprintf(stderr, "[%p] SSL: %s want read\n", ssl, func); */ + } + + return 0; +} void SecureStream::Initialize(Handle target) { HandleScope scope; @@ -260,6 +285,7 @@ void SecureStream::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "isInitFinished", SecureStream::IsInitFinished); NODE_SET_PROTOTYPE_METHOD(t, "verifyPeer", SecureStream::VerifyPeer); NODE_SET_PROTOTYPE_METHOD(t, "getCurrentCipher", SecureStream::GetCurrentCipher); + NODE_SET_PROTOTYPE_METHOD(t, "start", SecureStream::Start); NODE_SET_PROTOTYPE_METHOD(t, "shutdown", SecureStream::Shutdown); NODE_SET_PROTOTYPE_METHOD(t, "close", SecureStream::Close); @@ -333,7 +359,7 @@ Handle SecureStream::EncIn(const Arguments& args) { String::New("Length is extends beyond buffer"))); } - int bytes_written = BIO_write(ss->bio_read_, (char*)buffer_data + off, len); + int bytes_written = serr(ss->ssl_, "BIO_write", BIO_write(ss->bio_read_, (char*)buffer_data + off, len)); if (bytes_written < 0) { if (errno == EAGAIN || errno == EINTR) return Null(); @@ -379,32 +405,19 @@ Handle SecureStream::ClearOut(const Arguments& args) { if (!SSL_is_init_finished(ss->ssl_)) { if (ss->is_server_) { - bytes_read = SSL_accept(ss->ssl_); + bytes_read = serr(ss->ssl_, "SSL_accept:ClearOut", SSL_accept(ss->ssl_)); } else { - bytes_read = SSL_connect(ss->ssl_); + bytes_read = serr(ss->ssl_, "SSL_connect:ClearOut", SSL_connect(ss->ssl_)); } if (bytes_read < 0) { - int err; - if ((err = SSL_get_error(ss->ssl_, bytes_read)) == SSL_ERROR_WANT_READ) { - return scope.Close(Integer::New(0)); - } + return ThrowException(Exception::Error(v8::String::New(ssl_error_buf))); } return scope.Close(Integer::New(0)); } - bytes_read = SSL_read(ss->ssl_, (char*)buffer_data + off, len); + bytes_read = serr(ss->ssl_, "SSL_read:ClearOut", SSL_read(ss->ssl_, (char*)buffer_data + off, len)); if (bytes_read < 0) { - int err = SSL_get_error(ss->ssl_, bytes_read); - if (err == SSL_ERROR_WANT_READ) { - return scope.Close(Integer::New(0)); - } - // SSL read error - return scope.Close(Integer::New(-2)); - } - - if (bytes_read < 0) { - if (errno == EAGAIN || errno == EINTR) return Null(); - return ThrowException(ErrnoException(errno, "read")); + return ThrowException(Exception::Error(v8::String::New(ssl_error_buf))); } return scope.Close(Integer::New(bytes_read)); @@ -460,7 +473,7 @@ Handle SecureStream::EncOut(const Arguments& args) { String::New("Length is extends beyond buffer"))); } - int bytes_read = BIO_read(ss->bio_write_, (char*)buffer_data + off, len); + int bytes_read = serr(ss->ssl_, "BIO_read:EncOut", BIO_read(ss->bio_write_, (char*)buffer_data + off, len)); return scope.Close(Integer::New(bytes_read)); } @@ -500,13 +513,21 @@ Handle SecureStream::ClearIn(const Arguments& args) { if (!SSL_is_init_finished(ss->ssl_)) { int s; if (ss->is_server_) { - s = SSL_accept(ss->ssl_); + s = serr(ss->ssl_, "SSL_accept:ClearIn", SSL_accept(ss->ssl_)); } else { - s = SSL_connect(ss->ssl_); + s = serr(ss->ssl_, "SSL_connect:ClearIn", SSL_connect(ss->ssl_)); + } + if (s < 0) { + return ThrowException(Exception::Error(v8::String::New(ssl_error_buf))); } return scope.Close(Integer::New(0)); } - int bytes_written = SSL_write(ss->ssl_, (char*)buffer_data + off, len); + + int bytes_written = serr(ss->ssl_, "SSL_write:ClearIn", SSL_write(ss->ssl_, (char*)buffer_data + off, len)); + + if (bytes_written < 0) { + return ThrowException(Exception::Error(v8::String::New(ssl_error_buf))); + } return scope.Close(Integer::New(bytes_written)); } @@ -570,6 +591,31 @@ Handle SecureStream::GetPeerCertificate(const Arguments& args) { return scope.Close(info); } +Handle SecureStream::Start(const Arguments& args) { + HandleScope scope; + int rv; + + SecureStream *ss = ObjectWrap::Unwrap(args.Holder()); + + if (!SSL_is_init_finished(ss->ssl_)) { + if (ss->is_server_) { + rv = serr(ss->ssl_, "SSL_accept:Start", SSL_accept(ss->ssl_)); + } else { + rv = serr(ss->ssl_, "SSL_connect:Start", SSL_connect(ss->ssl_)); + } + if (rv < 0) { + return ThrowException(Exception::Error(v8::String::New(ssl_error_buf))); + } + if (rv == 1) { + return True(); + } + else { + return False(); + } + } + + return True(); +} Handle SecureStream::Shutdown(const Arguments& args) { HandleScope scope; diff --git a/src/node_crypto.h b/src/node_crypto.h index a2c027c8320..87ebd178b6f 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -62,6 +62,7 @@ class SecureStream : ObjectWrap { static v8::Handle VerifyPeer(const v8::Arguments& args); static v8::Handle GetCurrentCipher(const v8::Arguments& args); static v8::Handle Shutdown(const v8::Arguments& args); + static v8::Handle Start(const v8::Arguments& args); static v8::Handle Close(const v8::Arguments& args); SecureStream() : ObjectWrap() {