Files
sdk/runtime/bin/tls_socket_linux.cc
T
whesse@google.com 5c55f1dd28 Start adding TLS (SSL) sockets to dart:io.
Add Linux implementation for SSL client sockets.

BUG=dart:3950
TEST=standalone/io/tls_socket_test

Committed: https://code.google.com/p/dart/source/detail?r=10565
Reverted: r=10567

Review URL: https://chromiumcodereview.appspot.com//10704159

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10650 260f80e4-7a28-3924-810f-c04153c831b5
2012-08-14 14:34:02 +00:00

131 lines
3.5 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "bin/tls_socket.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include "bin/builtin.h"
class TlsFilterPlatformData {
public:
SSL* ssl;
SSL_CTX* ssl_ctx;
BIO* encrypted;
BIO* plaintext;
BIO* internal;
};
TlsFilter::TlsFilter() : in_handshake_(false) {
LockInitMutex();
if (!library_initialized_) {
InitializeLibrary();
library_initialized_ = true;
}
UnlockInitMutex();
}
void TlsFilter::InitializeLibrary() {
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
}
void TlsFilter::InitializePlatformData() {
data_ = new TlsFilterPlatformData;
data_->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
BIO_new_bio_pair(&(data_->internal), 0, &(data_->encrypted), 0);
data_->plaintext = BIO_new_ssl(data_->ssl_ctx, 1);
data_->plaintext = BIO_push(data_->plaintext, data_->internal);
}
void TlsFilter::Connect() {
int result = BIO_do_handshake(data_->plaintext);
if (result == 1) {
if (in_handshake_) {
HandleError(Dart_InvokeClosure(handshake_finish_, 0, NULL));
in_handshake_ = false;
}
} else if (BIO_should_retry(data_->plaintext)) {
if (!in_handshake_) {
HandleError(Dart_InvokeClosure(handshake_start_, 0, NULL));
in_handshake_ = true;
}
}
}
void TlsFilter::Destroy() {
DestroyPlatformIndependent();
// TODO(whesse): Destroy OpenSSL objects here.
}
intptr_t TlsFilter::ProcessBuffer(int buffer_index) {
Dart_Handle buffer_object = dart_buffer_objects_[buffer_index];
Dart_Handle start_object = HandleError(
Dart_GetField(buffer_object, stringStart_));
Dart_Handle length_object = HandleError(
Dart_GetField(buffer_object, stringLength_));
int64_t unsafe_start = DartUtils::GetIntegerValue(start_object);
int64_t unsafe_length = DartUtils::GetIntegerValue(length_object);
if (unsafe_start < 0 || unsafe_start >= buffer_size_ ||
unsafe_length < 0 || unsafe_length > buffer_size_) {
Dart_ThrowException(DartUtils::NewDartIllegalArgumentException(
"Illegal .start or .length on a _TlsExternalBuffer"));
}
intptr_t start = static_cast<intptr_t>(unsafe_start);
intptr_t length = static_cast<intptr_t>(unsafe_length);
BIO* bio_stream;
if (buffer_index == kReadEncrypted || buffer_index == kWriteEncrypted) {
bio_stream = data_->encrypted;
} else {
bio_stream = data_->plaintext;
}
intptr_t bytes_processed = 0;
int bio_bytes = 0;
switch (buffer_index) {
case kReadPlaintext:
case kWriteEncrypted: {
// Write from the BIO to the buffer.
intptr_t bytes_free = buffer_size_ - start - length;
if (bytes_free > 0) {
bio_bytes = BIO_read(bio_stream,
buffers_[buffer_index] + start + length,
bytes_free);
}
break;
}
case kReadEncrypted:
case kWritePlaintext:
if (length > 0) {
// Call BIO_write.
bio_bytes = BIO_write(bio_stream,
buffers_[buffer_index] + start,
length);
}
break;
}
if (bio_bytes > 0) {
bytes_processed = bio_bytes;
}
return bytes_processed;
}