1 /*
2 Copyright (c) DataStax, Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 #ifndef DATASTAX_INTERNAL_SSL_HPP
18 #define DATASTAX_INTERNAL_SSL_HPP
19
20 #include "address.hpp"
21 #include "allocated.hpp"
22 #include "cassandra.h"
23 #include "driver_config.hpp"
24 #include "external.hpp"
25 #include "ref_counted.hpp"
26 #include "ring_buffer.hpp"
27 #include "string.hpp"
28
29 #include <uv.h>
30
31 namespace datastax { namespace internal { namespace core {
32
33 class SslSession : public Allocated {
34 public:
SslSession(const Address & address,const String & hostname,const String & sni_server_name,int flags)35 SslSession(const Address& address, const String& hostname, const String& sni_server_name,
36 int flags)
37 : address_(address)
38 , hostname_(hostname)
39 , sni_server_name_(sni_server_name)
40 , verify_flags_(flags)
41 , error_code_(CASS_OK) {}
42
~SslSession()43 virtual ~SslSession() {}
44
has_error() const45 bool has_error() const { return error_code() != CASS_OK; }
46
error_code() const47 CassError error_code() const { return error_code_; }
48
error_message() const49 String error_message() const { return error_message_; }
50
51 virtual bool is_handshake_done() const = 0;
52 virtual void do_handshake() = 0;
53 virtual void verify() = 0;
54
55 virtual int encrypt(const char* data, size_t data_size) = 0;
56 virtual int decrypt(char* data, size_t data_size) = 0;
57
incoming()58 rb::RingBuffer& incoming() { return incoming_; }
outgoing()59 rb::RingBuffer& outgoing() { return outgoing_; }
60
61 protected:
62 Address address_;
63 String hostname_;
64 String sni_server_name_;
65 int verify_flags_;
66 rb::RingBuffer incoming_;
67 rb::RingBuffer outgoing_;
68 CassError error_code_;
69 String error_message_;
70 };
71
72 class SslContext : public RefCounted<SslContext> {
73 public:
74 typedef SharedRefPtr<SslContext> Ptr;
75
SslContext()76 SslContext()
77 : verify_flags_(CASS_SSL_VERIFY_PEER_CERT) {}
78
~SslContext()79 virtual ~SslContext() {}
80
set_verify_flags(int flags)81 void set_verify_flags(int flags) { verify_flags_ = flags; }
is_cert_validation_enabled()82 bool is_cert_validation_enabled() { return verify_flags_ != CASS_SSL_VERIFY_NONE; }
83
84 virtual SslSession* create_session(const Address& address, const String& hostname,
85 const String& sni_server_name) = 0;
86 virtual CassError add_trusted_cert(const char* cert, size_t cert_length) = 0;
87 virtual CassError set_cert(const char* cert, size_t cert_length) = 0;
88 virtual CassError set_private_key(const char* key, size_t key_length, const char* password,
89 size_t password_length) = 0;
90
91 protected:
92 int verify_flags_;
93 };
94
95 template <class T>
96 class SslContextFactoryBase {
97 public:
98 static SslContext::Ptr create();
99 static void init_once();
100 static void thread_cleanup();
101
102 static void init(); // Tests only
103 static void cleanup(); // Tests only
104
105 private:
106 static uv_once_t ssl_init_guard;
107 };
108
109 template <class T>
create()110 SslContext::Ptr SslContextFactoryBase<T>::create() {
111 return T::create();
112 }
113
114 template <class T>
init_once()115 void SslContextFactoryBase<T>::init_once() {
116 uv_once(&ssl_init_guard, T::init);
117 }
118
119 template <class T>
thread_cleanup()120 void SslContextFactoryBase<T>::thread_cleanup() {
121 T::internal_thread_cleanup();
122 }
123
124 template <class T>
init()125 void SslContextFactoryBase<T>::init() {
126 T::internal_init();
127 }
128
129 template <class T>
cleanup()130 void SslContextFactoryBase<T>::cleanup() {
131 T::internal_cleanup();
132 }
133
134 }}} // namespace datastax::internal::core
135
136 #ifdef HAVE_OPENSSL
137 #include "ssl/ssl_openssl_impl.hpp"
138 #else
139 #include "ssl/ssl_no_impl.hpp"
140 #endif
141
142 EXTERNAL_TYPE(datastax::internal::core::SslContext, CassSsl)
143
144 #endif
145