summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2013-05-28 17:50:38 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2013-05-28 20:14:44 +0400
commitfa170dd2b241bc0f22f88071158686075c3b269e (patch)
tree4cf4ceb0114a1db802bda56a8aa5a90747c27cdc
parent28f4c15eb49e9b7f1a430f39f0f930c38adeff60 (diff)
downloadnode-new-fa170dd2b241bc0f22f88071158686075c3b269e.tar.gz
tls: ignore .shutdown() syscall error
Quote from SSL_shutdown man page: The output of SSL_get_error(3) may be misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred. Also, handle all other errors to prevent assertion in `ClearError()`.
-rw-r--r--lib/tls.js6
-rw-r--r--src/node_crypto.cc45
-rw-r--r--src/node_crypto.h7
3 files changed, 47 insertions, 11 deletions
diff --git a/lib/tls.js b/lib/tls.js
index 7bf0ca1886..4441bd1d65 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -282,8 +282,14 @@ function onCryptoStreamFinish() {
// NOTE: first call checks if client has sent us shutdown,
// second call enqueues shutdown into the BIO.
if (this.pair.ssl.shutdown() !== 1) {
+ if (this.pair.ssl && this.pair.ssl.error)
+ return this.pair.error();
+
this.pair.ssl.shutdown();
}
+
+ if (this.pair.ssl && this.pair.ssl.error)
+ return this.pair.error();
}
} else {
debug('encrypted.onfinish');
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index 93f88202f7..b5b5ae41ba 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -915,7 +915,10 @@ int Connection::HandleBIOError(BIO *bio, const char* func, int rv) {
}
-int Connection::HandleSSLError(const char* func, int rv, ZeroStatus zs) {
+int Connection::HandleSSLError(const char* func,
+ int rv,
+ ZeroStatus zs,
+ SyscallStatus ss) {
ClearErrorOnReturn clear_error_on_return;
(void) &clear_error_on_return; // Silence unused variable warning.
@@ -940,6 +943,9 @@ int Connection::HandleSSLError(const char* func, int rv, ZeroStatus zs) {
Exception::Error(String::New("ZERO_RETURN")));
return rv;
+ } else if ((err == SSL_ERROR_SYSCALL) && (ss == kIgnoreSyscall)) {
+ return 0;
+
} else {
HandleScope scope;
BUF_MEM* mem;
@@ -1372,17 +1378,26 @@ Handle<Value> Connection::ClearOut(const Arguments& args) {
if (ss->is_server_) {
rv = SSL_accept(ss->ssl_);
- ss->HandleSSLError("SSL_accept:ClearOut", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_accept:ClearOut",
+ rv,
+ kZeroIsAnError,
+ kSyscallError);
} else {
rv = SSL_connect(ss->ssl_);
- ss->HandleSSLError("SSL_connect:ClearOut", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_connect:ClearOut",
+ rv,
+ kZeroIsAnError,
+ kSyscallError);
}
if (rv < 0) return scope.Close(Integer::New(rv));
}
int bytes_read = SSL_read(ss->ssl_, buffer_data + off, len);
- ss->HandleSSLError("SSL_read:ClearOut", bytes_read, kZeroIsNotAnError);
+ ss->HandleSSLError("SSL_read:ClearOut",
+ bytes_read,
+ kZeroIsNotAnError,
+ kSyscallError);
ss->SetShutdownFlags();
return scope.Close(Integer::New(bytes_read));
@@ -1472,10 +1487,16 @@ Handle<Value> Connection::ClearIn(const Arguments& args) {
int rv;
if (ss->is_server_) {
rv = SSL_accept(ss->ssl_);
- ss->HandleSSLError("SSL_accept:ClearIn", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_accept:ClearIn",
+ rv,
+ kZeroIsAnError,
+ kSyscallError);
} else {
rv = SSL_connect(ss->ssl_);
- ss->HandleSSLError("SSL_connect:ClearIn", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_connect:ClearIn",
+ rv,
+ kZeroIsAnError,
+ kSyscallError);
}
if (rv < 0) return scope.Close(Integer::New(rv));
@@ -1485,7 +1506,8 @@ Handle<Value> Connection::ClearIn(const Arguments& args) {
ss->HandleSSLError("SSL_write:ClearIn",
bytes_written,
- len == 0 ? kZeroIsNotAnError : kZeroIsAnError);
+ len == 0 ? kZeroIsNotAnError : kZeroIsAnError,
+ kSyscallError);
ss->SetShutdownFlags();
return scope.Close(Integer::New(bytes_written));
@@ -1725,10 +1747,13 @@ Handle<Value> Connection::Start(const Arguments& args) {
int rv;
if (ss->is_server_) {
rv = SSL_accept(ss->ssl_);
- ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError, kSyscallError);
} else {
rv = SSL_connect(ss->ssl_);
- ss->HandleSSLError("SSL_connect:Start", rv, kZeroIsAnError);
+ ss->HandleSSLError("SSL_connect:Start",
+ rv,
+ kZeroIsAnError,
+ kSyscallError);
}
return scope.Close(Integer::New(rv));
@@ -1745,7 +1770,7 @@ Handle<Value> Connection::Shutdown(const Arguments& args) {
if (ss->ssl_ == NULL) return False();
int rv = SSL_shutdown(ss->ssl_);
- ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError);
+ ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError, kIgnoreSyscall);
ss->SetShutdownFlags();
return scope.Close(Integer::New(rv));
diff --git a/src/node_crypto.h b/src/node_crypto.h
index 80262ba3ab..f1f6334b24 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -218,7 +218,12 @@ class Connection : ObjectWrap {
kZeroIsAnError
};
- int HandleSSLError(const char* func, int rv, ZeroStatus zs);
+ enum SyscallStatus {
+ kIgnoreSyscall,
+ kSyscallError
+ };
+
+ int HandleSSLError(const char* func, int rv, ZeroStatus zs, SyscallStatus ss);
void ClearError();
void SetShutdownFlags();