Browse Source

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()`.
v0.10.9-release
Fedor Indutny 12 years ago
parent
commit
fa170dd2b2
  1. 6
      lib/tls.js
  2. 45
      src/node_crypto.cc
  3. 7
      src/node_crypto.h

6
lib/tls.js

@ -282,8 +282,14 @@ function onCryptoStreamFinish() {
// NOTE: first call checks if client has sent us shutdown, // NOTE: first call checks if client has sent us shutdown,
// second call enqueues shutdown into the BIO. // second call enqueues shutdown into the BIO.
if (this.pair.ssl.shutdown() !== 1) { if (this.pair.ssl.shutdown() !== 1) {
if (this.pair.ssl && this.pair.ssl.error)
return this.pair.error();
this.pair.ssl.shutdown(); this.pair.ssl.shutdown();
} }
if (this.pair.ssl && this.pair.ssl.error)
return this.pair.error();
} }
} else { } else {
debug('encrypted.onfinish'); debug('encrypted.onfinish');

45
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; ClearErrorOnReturn clear_error_on_return;
(void) &clear_error_on_return; // Silence unused variable warning. (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"))); Exception::Error(String::New("ZERO_RETURN")));
return rv; return rv;
} else if ((err == SSL_ERROR_SYSCALL) && (ss == kIgnoreSyscall)) {
return 0;
} else { } else {
HandleScope scope; HandleScope scope;
BUF_MEM* mem; BUF_MEM* mem;
@ -1372,17 +1378,26 @@ Handle<Value> Connection::ClearOut(const Arguments& args) {
if (ss->is_server_) { if (ss->is_server_) {
rv = SSL_accept(ss->ssl_); rv = SSL_accept(ss->ssl_);
ss->HandleSSLError("SSL_accept:ClearOut", rv, kZeroIsAnError); ss->HandleSSLError("SSL_accept:ClearOut",
rv,
kZeroIsAnError,
kSyscallError);
} else { } else {
rv = SSL_connect(ss->ssl_); 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)); if (rv < 0) return scope.Close(Integer::New(rv));
} }
int bytes_read = SSL_read(ss->ssl_, buffer_data + off, len); 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(); ss->SetShutdownFlags();
return scope.Close(Integer::New(bytes_read)); return scope.Close(Integer::New(bytes_read));
@ -1472,10 +1487,16 @@ Handle<Value> Connection::ClearIn(const Arguments& args) {
int rv; int rv;
if (ss->is_server_) { if (ss->is_server_) {
rv = SSL_accept(ss->ssl_); rv = SSL_accept(ss->ssl_);
ss->HandleSSLError("SSL_accept:ClearIn", rv, kZeroIsAnError); ss->HandleSSLError("SSL_accept:ClearIn",
rv,
kZeroIsAnError,
kSyscallError);
} else { } else {
rv = SSL_connect(ss->ssl_); 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)); 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", ss->HandleSSLError("SSL_write:ClearIn",
bytes_written, bytes_written,
len == 0 ? kZeroIsNotAnError : kZeroIsAnError); len == 0 ? kZeroIsNotAnError : kZeroIsAnError,
kSyscallError);
ss->SetShutdownFlags(); ss->SetShutdownFlags();
return scope.Close(Integer::New(bytes_written)); return scope.Close(Integer::New(bytes_written));
@ -1725,10 +1747,13 @@ Handle<Value> Connection::Start(const Arguments& args) {
int rv; int rv;
if (ss->is_server_) { if (ss->is_server_) {
rv = SSL_accept(ss->ssl_); rv = SSL_accept(ss->ssl_);
ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError); ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError, kSyscallError);
} else { } else {
rv = SSL_connect(ss->ssl_); 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)); return scope.Close(Integer::New(rv));
@ -1745,7 +1770,7 @@ Handle<Value> Connection::Shutdown(const Arguments& args) {
if (ss->ssl_ == NULL) return False(); if (ss->ssl_ == NULL) return False();
int rv = SSL_shutdown(ss->ssl_); int rv = SSL_shutdown(ss->ssl_);
ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError); ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError, kIgnoreSyscall);
ss->SetShutdownFlags(); ss->SetShutdownFlags();
return scope.Close(Integer::New(rv)); return scope.Close(Integer::New(rv));

7
src/node_crypto.h

@ -218,7 +218,12 @@ class Connection : ObjectWrap {
kZeroIsAnError 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 ClearError();
void SetShutdownFlags(); void SetShutdownFlags();

Loading…
Cancel
Save