1
#include "source/common/tls/client_ssl_socket.h"
2

            
3
#include "envoy/stats/scope.h"
4

            
5
#include "source/common/common/assert.h"
6
#include "source/common/common/empty_string.h"
7
#include "source/common/common/hex.h"
8
#include "source/common/http/headers.h"
9
#include "source/common/runtime/runtime_features.h"
10
#include "source/common/tls/io_handle_bio.h"
11
#include "source/common/tls/ssl_handshaker.h"
12
#include "source/common/tls/utility.h"
13

            
14
#include "absl/strings/str_replace.h"
15
#include "openssl/err.h"
16
#include "openssl/x509v3.h"
17

            
18
namespace Envoy {
19
namespace Extensions {
20
namespace TransportSockets {
21
namespace Tls {
22

            
23
namespace {
24
3529
SslSocketFactoryStats generateStats(Stats::Scope& store) {
25
3529
  return {ALL_SSL_SOCKET_FACTORY_STATS(POOL_COUNTER_PREFIX(store, "client_ssl_socket_factory."))};
26
3529
}
27
} // namespace
28

            
29
absl::StatusOr<std::unique_ptr<ClientSslSocketFactory>>
30
ClientSslSocketFactory::create(Envoy::Ssl::ClientContextConfigPtr config,
31
3529
                               Envoy::Ssl::ContextManager& manager, Stats::Scope& stats_scope) {
32
3529
  absl::Status creation_status = absl::OkStatus();
33
3529
  auto ret = std::unique_ptr<ClientSslSocketFactory>(
34
3529
      new ClientSslSocketFactory(std::move(config), manager, stats_scope, creation_status));
35
3529
  RETURN_IF_NOT_OK(creation_status);
36
3528
  return ret;
37
3529
}
38

            
39
ClientSslSocketFactory::ClientSslSocketFactory(Envoy::Ssl::ClientContextConfigPtr config,
40
                                               Envoy::Ssl::ContextManager& manager,
41
                                               Stats::Scope& stats_scope,
42
                                               absl::Status& creation_status)
43
3529
    : manager_(manager), stats_scope_(stats_scope), stats_(generateStats(stats_scope)),
44
3529
      config_(std::move(config)) {
45
3529
  {
46
3529
    absl::WriterMutexLock l(ssl_ctx_mu_);
47
3529
    auto ctx_or_error = manager_.createSslClientContext(stats_scope_, *config_);
48
3529
    SET_AND_RETURN_IF_NOT_OK(ctx_or_error.status(), creation_status);
49
3528
    ssl_ctx_ = *ctx_or_error;
50
3528
  }
51
56
  config_->setSecretUpdateCallback([this]() { return onAddOrUpdateSecret(); });
52
3528
}
53

            
54
3529
ClientSslSocketFactory::~ClientSslSocketFactory() { manager_.removeContext(ssl_ctx_); }
55

            
56
Network::TransportSocketPtr ClientSslSocketFactory::createTransportSocket(
57
    Network::TransportSocketOptionsConstSharedPtr transport_socket_options,
58
1201
    Upstream::HostDescriptionConstSharedPtr host) const {
59
  // onAddOrUpdateSecret() could be invoked in the middle of checking the existence of ssl_ctx and
60
  // creating SslSocket using ssl_ctx. Capture ssl_ctx_ into a local variable so that we check and
61
  // use the same ssl_ctx to create SslSocket.
62
1201
  Envoy::Ssl::ClientContextSharedPtr ssl_ctx;
63
1201
  {
64
1201
    absl::ReaderMutexLock l(ssl_ctx_mu_);
65
1201
    ssl_ctx = ssl_ctx_;
66
1201
  }
67
1201
  if (ssl_ctx) {
68
1198
    auto status_or_socket =
69
1198
        SslSocket::create(std::move(ssl_ctx), InitialState::Client, transport_socket_options,
70
1198
                          config_->createHandshaker(), host);
71
1198
    if (status_or_socket.ok()) {
72
1196
      return std::move(*status_or_socket);
73
1196
    }
74
2
    return std::make_unique<ErrorSslSocket>(status_or_socket.status().message());
75
1198
  } else {
76
3
    ENVOY_LOG(debug, "Create NotReadySslSocket");
77
3
    stats_.upstream_context_secrets_not_ready_.inc();
78
3
    return std::make_unique<NotReadySslSocket>();
79
3
  }
80
1201
}
81

            
82
121
bool ClientSslSocketFactory::implementsSecureTransport() const { return true; }
83

            
84
56
absl::Status ClientSslSocketFactory::onAddOrUpdateSecret() {
85
56
  ENVOY_LOG(debug, "Secret is updated.");
86
56
  auto ctx_or_error = manager_.createSslClientContext(stats_scope_, *config_);
87
56
  RETURN_IF_NOT_OK(ctx_or_error.status());
88
56
  {
89
56
    absl::WriterMutexLock l(ssl_ctx_mu_);
90
56
    std::swap(*ctx_or_error, ssl_ctx_);
91
56
  }
92
56
  manager_.removeContext(*ctx_or_error);
93
56
  stats_.ssl_context_update_by_sds_.inc();
94
56
  return absl::OkStatus();
95
56
}
96

            
97
6515
Envoy::Ssl::ClientContextSharedPtr ClientSslSocketFactory::sslCtx() {
98
6515
  absl::ReaderMutexLock l(ssl_ctx_mu_);
99
6515
  return ssl_ctx_;
100
6515
}
101

            
102
} // namespace Tls
103
} // namespace TransportSockets
104
} // namespace Extensions
105
} // namespace Envoy