Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Centralize error handling in SecureStream
Browse files Browse the repository at this point in the history
and add a start method, to kick off SSL handshaking, without writing a zero
byte buffer
  • Loading branch information
pquerna authored and ry committed Oct 26, 2010
1 parent 446d2ec commit 1ce4684
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 23 deletions.
92 changes: 69 additions & 23 deletions src/node_crypto.cc
Expand Up @@ -242,6 +242,31 @@ Handle<Value> 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<Object> target) {
HandleScope scope;
Expand All @@ -260,6 +285,7 @@ void SecureStream::Initialize(Handle<Object> 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);

Expand Down Expand Up @@ -333,7 +359,7 @@ Handle<Value> 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();
Expand Down Expand Up @@ -379,32 +405,19 @@ Handle<Value> 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));
Expand Down Expand Up @@ -460,7 +473,7 @@ Handle<Value> 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));
}
Expand Down Expand Up @@ -500,13 +513,21 @@ Handle<Value> 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));
}
Expand Down Expand Up @@ -570,6 +591,31 @@ Handle<Value> SecureStream::GetPeerCertificate(const Arguments& args) {
return scope.Close(info);
}

Handle<Value> SecureStream::Start(const Arguments& args) {
HandleScope scope;
int rv;

SecureStream *ss = ObjectWrap::Unwrap<SecureStream>(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<Value> SecureStream::Shutdown(const Arguments& args) {
HandleScope scope;
Expand Down
1 change: 1 addition & 0 deletions src/node_crypto.h
Expand Up @@ -62,6 +62,7 @@ class SecureStream : ObjectWrap {
static v8::Handle<v8::Value> VerifyPeer(const v8::Arguments& args);
static v8::Handle<v8::Value> GetCurrentCipher(const v8::Arguments& args);
static v8::Handle<v8::Value> Shutdown(const v8::Arguments& args);
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);

SecureStream() : ObjectWrap() {
Expand Down

0 comments on commit 1ce4684

Please sign in to comment.