// 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_SECURITY_CONTEXT_H_
#define RUNTIME_BIN_SECURITY_CONTEXT_H_

#include <openssl/ssl.h>
#include <openssl/x509.h>

#include "bin/lockers.h"
#include "bin/reference_counting.h"
#include "bin/socket.h"

namespace dart {
namespace bin {

// Forward declaration
class SSLFilter;

typedef void (*TrustEvaluateHandlerFunc)(Dart_Port dest_port_id,
                                         Dart_CObject* message);

class SSLCertContext : public ReferenceCounted<SSLCertContext> {
 public:
  static const intptr_t kApproximateSize;
  static const int kSecurityContextNativeFieldIndex = 0;
  static const int kX509NativeFieldIndex = 0;

  explicit SSLCertContext(SSL_CTX* context)
      : ReferenceCounted(),
        context_(context),
        alpn_protocol_string_(NULL),
        trust_builtin_(false) {}

  ~SSLCertContext() {
    SSL_CTX_free(context_);
    if (alpn_protocol_string_ != NULL) {
      free(alpn_protocol_string_);
    }
  }

  static int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx);

  static SSLCertContext* GetSecurityContext(Dart_NativeArguments args);
  static const char* GetPasswordArgument(Dart_NativeArguments args,
                                         intptr_t index);
  static void SetAlpnProtocolList(Dart_Handle protocols_handle,
                                  SSL* ssl,
                                  SSLCertContext* context,
                                  bool is_server);

  static const char* root_certs_file() { return root_certs_file_; }
  static void set_root_certs_file(const char* root_certs_file) {
    root_certs_file_ = root_certs_file;
  }
  static const char* root_certs_cache() { return root_certs_cache_; }
  static void set_root_certs_cache(const char* root_certs_cache) {
    root_certs_cache_ = root_certs_cache;
  }

  void SetTrustedCertificatesBytes(Dart_Handle cert_bytes,
                                   const char* password);

  void SetClientAuthoritiesBytes(Dart_Handle client_authorities_bytes,
                                 const char* password);

  int UseCertificateChainBytes(Dart_Handle cert_chain_bytes,
                               const char* password);

  void TrustBuiltinRoots();

  SSL_CTX* context() const { return context_; }

  uint8_t* alpn_protocol_string() const { return alpn_protocol_string_; }

  void set_alpn_protocol_string(uint8_t* protocol_string) {
    if (alpn_protocol_string_ != NULL) {
      free(alpn_protocol_string_);
    }
    alpn_protocol_string_ = protocol_string;
  }

  bool trust_builtin() const { return trust_builtin_; }

  void set_trust_builtin(bool trust_builtin) { trust_builtin_ = trust_builtin; }

  void RegisterCallbacks(SSL* ssl);
  TrustEvaluateHandlerFunc GetTrustEvaluateHandler() const;

  static bool long_ssl_cert_evaluation() { return long_ssl_cert_evaluation_; }
  static void set_long_ssl_cert_evaluation(bool long_ssl_cert_evaluation) {
    long_ssl_cert_evaluation_ = long_ssl_cert_evaluation;
  }

  static bool bypass_trusting_system_roots() {
    return bypass_trusting_system_roots_;
  }
  static void set_bypass_trusting_system_roots(
      bool bypass_trusting_system_roots) {
    bypass_trusting_system_roots_ = bypass_trusting_system_roots;
  }

 private:
  void AddCompiledInCerts();
  void LoadRootCertFile(const char* file);
  void LoadRootCertCache(const char* cache);

  static const char* root_certs_file_;
  static const char* root_certs_cache_;

  SSL_CTX* context_;
  uint8_t* alpn_protocol_string_;

  bool trust_builtin_;

  static bool long_ssl_cert_evaluation_;
  static bool bypass_trusting_system_roots_;

  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
};

class X509Helper : public AllStatic {
 public:
  static Dart_Handle GetDer(Dart_NativeArguments args);
  static Dart_Handle GetPem(Dart_NativeArguments args);
  static Dart_Handle GetSha1(Dart_NativeArguments args);
  static Dart_Handle GetSubject(Dart_NativeArguments args);
  static Dart_Handle GetIssuer(Dart_NativeArguments args);
  static Dart_Handle GetStartValidity(Dart_NativeArguments args);
  static Dart_Handle GetEndValidity(Dart_NativeArguments args);
  static Dart_Handle WrappedX509Certificate(X509* certificate);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_SECURITY_CONTEXT_H_
