Files
sdk/runtime/bin/secure_socket_utils.h
T
Alexander Aprelev aa0a4410f4 [vm/certs/win] When adding root certificates consider not_before and not_after properties, only add valid ones.
boringssl seems to be confused when expired certificates are present in trusted root, only picks up the first matching one which could be expired and ignores still-valid-ones.

TEST=secure_socket_utils_test

Fixes https://github.com/dart-lang/sdk/issues/46370

Change-Id: I5bbc0a1a3331ce4dcda46eee41b02b5b6e835b2a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211160
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
2021-08-26 15:34:48 +00:00

184 lines
4.6 KiB
C++

// Copyright (c) 2017, 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.
#ifndef RUNTIME_BIN_SECURE_SOCKET_UTILS_H_
#define RUNTIME_BIN_SECURE_SOCKET_UTILS_H_
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include "platform/globals.h"
#include "bin/dartutils.h"
#include "platform/text_buffer.h"
namespace dart {
namespace bin {
const bool SSL_LOG_STATUS = false;
const bool SSL_LOG_DATA = false;
const bool SSL_LOG_CERTS = false;
class SecureSocketUtils : public AllStatic {
public:
static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
static void ThrowIOException(int status,
const char* exception_type,
const char* message,
const SSL* ssl);
static void CheckStatusSSL(int status,
const char* type,
const char* message,
const SSL* ssl);
static void CheckStatus(int status, const char* type, const char* message);
static bool IsCurrentTimeInsideCertValidDateRange(X509* root_cert);
static bool NoPEMStartLine() {
uint32_t last_error = ERR_peek_last_error();
return (ERR_GET_LIB(last_error) == ERR_LIB_PEM) &&
(ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE);
}
static void FetchErrorString(const SSL* ssl, TextBuffer* text_buffer);
};
// Where the argument to the constructor is the handle for an object
// implementing List<int>, this class creates a scope in which a memory-backed
// BIO is allocated. Leaving the scope cleans up the BIO and the buffer that
// was used to create it.
//
// Do not make Dart_ API calls while in a ScopedMemBIO.
// Do not call Dart_PropagateError while in a ScopedMemBIO.
class ScopedMemBIO {
public:
explicit ScopedMemBIO(Dart_Handle object) {
if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
Dart_ThrowException(
DartUtils::NewDartArgumentError("Argument is not a List<int>"));
}
uint8_t* bytes = NULL;
intptr_t bytes_len = 0;
bool is_typed_data = false;
if (Dart_IsTypedData(object)) {
is_typed_data = true;
Dart_TypedData_Type typ;
ThrowIfError(Dart_TypedDataAcquireData(
object, &typ, reinterpret_cast<void**>(&bytes), &bytes_len));
} else {
ASSERT(Dart_IsList(object));
ThrowIfError(Dart_ListLength(object, &bytes_len));
bytes = Dart_ScopeAllocate(bytes_len);
ASSERT(bytes != NULL);
ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
}
object_ = object;
bytes_ = bytes;
bytes_len_ = bytes_len;
bio_ = BIO_new_mem_buf(bytes, bytes_len);
ASSERT(bio_ != NULL);
is_typed_data_ = is_typed_data;
}
~ScopedMemBIO() {
ASSERT(bio_ != NULL);
if (is_typed_data_) {
BIO_free(bio_);
ThrowIfError(Dart_TypedDataReleaseData(object_));
} else {
BIO_free(bio_);
}
}
BIO* bio() {
ASSERT(bio_ != NULL);
return bio_;
}
uint8_t* data() { return bytes_; }
intptr_t length() { return bytes_len_; }
private:
Dart_Handle object_;
uint8_t* bytes_;
intptr_t bytes_len_;
BIO* bio_;
bool is_typed_data_;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO);
};
template <typename T, void (*free_func)(T*)>
class ScopedSSLType {
public:
explicit ScopedSSLType(T* obj) : obj_(obj) {}
~ScopedSSLType() {
if (obj_ != NULL) {
free_func(obj_);
}
}
T* get() { return obj_; }
const T* get() const { return obj_; }
T* release() {
T* result = obj_;
obj_ = NULL;
return result;
}
private:
T* obj_;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ScopedSSLType);
};
template <typename T, typename E, void (*func)(E*)>
class ScopedSSLStackType {
public:
explicit ScopedSSLStackType(T* obj) : obj_(obj) {}
~ScopedSSLStackType() {
if (obj_ != NULL) {
sk_pop_free(reinterpret_cast<_STACK*>(obj_),
reinterpret_cast<void (*)(void*)>(func));
}
}
T* get() { return obj_; }
const T* get() const { return obj_; }
T* release() {
T* result = obj_;
obj_ = NULL;
return result;
}
private:
T* obj_;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType);
};
typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12;
typedef ScopedSSLType<X509, X509_free> ScopedX509;
typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack;
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_SECURE_SOCKET_UTILS_H_