@@ -63,7 +63,65 @@ using datastax::internal::core::UuidGen;
6363
6464namespace mockssandra {
6565
66- static DH* dh_parameters () {
66+ namespace {
67+
68+ template <class T >
69+ struct FreeDeleterImpl {};
70+
71+ #define MAKE_DELETER (type, free_func ) \
72+ template <> \
73+ struct FreeDeleterImpl <type> { \
74+ static void free (type* ptr) { free_func (ptr); } \
75+ };
76+
77+ MAKE_DELETER (BIO, BIO_free)
78+ MAKE_DELETER (DH, DH_free)
79+ MAKE_DELETER (EVP_PKEY, EVP_PKEY_free)
80+ MAKE_DELETER (EVP_PKEY_CTX, EVP_PKEY_CTX_free)
81+ MAKE_DELETER (X509, X509_free)
82+ MAKE_DELETER (X509_REQ, X509_REQ_free)
83+ MAKE_DELETER (X509_EXTENSION, X509_EXTENSION_free)
84+
85+ template <class T >
86+ struct FreeDeleter {
87+ void operator ()(T* ptr) const { FreeDeleterImpl<T>::free (ptr); }
88+ };
89+
90+ template <class T >
91+ class Scoped : public ScopedPtr <T, FreeDeleter<T> > {
92+ public:
93+ Scoped (T* ptr = NULL )
94+ : ScopedPtr<T, FreeDeleter<T> >(ptr) {}
95+ };
96+
97+ void print_ssl_error () {
98+ unsigned long err = ERR_get_error ();
99+ char buf[256 ];
100+ ERR_error_string_n (err, buf, sizeof (buf));
101+ fprintf (stderr, " %s\n " , buf);
102+ }
103+
104+ X509* load_cert (const String& cert) {
105+ X509* x509 = NULL ;
106+ Scoped<BIO> bio (BIO_new_mem_buf (const_cast <char *>(cert.c_str ()), cert.length ()));
107+ if (PEM_read_bio_X509 (bio.get (), &x509, NULL , NULL ) == NULL ) {
108+ print_ssl_error ();
109+ return NULL ;
110+ }
111+ return x509;
112+ }
113+
114+ EVP_PKEY* load_private_key (const String& key) {
115+ EVP_PKEY* pkey = NULL ;
116+ Scoped<BIO> bio (BIO_new_mem_buf (const_cast <char *>(key.c_str ()), key.length ()));
117+ if (!PEM_read_bio_PrivateKey (bio.get (), &pkey, NULL , NULL )) {
118+ print_ssl_error ();
119+ return NULL ;
120+ }
121+ return pkey;
122+ }
123+
124+ DH* dh_parameters () {
67125 // Generated using the following command: `openssl dhparam -C 2048`
68126 // Prime length of 2048 chosen to bypass client-side error:
69127 // `SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small`
@@ -80,32 +138,32 @@ static DH* dh_parameters() {
80138 " VYp84xAy2M6mWWqUm/kokN9QjAiT/DZRxZK8VhY7O9+oATo7/YPCMd9Em417O13k\n "
81139 " +F0o/8IMaQvpmtlAsLc2ZKwGqqG+HD2dOwIBAg==\n "
82140 " -----END DH PARAMETERS-----" ;
83- BIO* bio = BIO_new_mem_buf (const_cast <char *>(dh_parameters_pem),
84- -1 ); // Use null terminator for length
85- DH* dh = PEM_read_bio_DHparams (bio, NULL , NULL , NULL );
86- BIO_free (bio);
87- return dh;
141+ Scoped<BIO> bio (BIO_new_mem_buf (const_cast <char *>(dh_parameters_pem),
142+ -1 )); // Use null terminator for length
143+ return PEM_read_bio_DHparams (bio.get (), NULL , NULL , NULL );
88144}
89145
146+ } // namespace
147+
90148String Ssl::generate_key () {
91- EVP_PKEY* pkey = NULL ;
92- EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_RSA, NULL );
93- EVP_PKEY_keygen_init (pctx);
94- EVP_PKEY_CTX_set_rsa_keygen_bits (pctx, 2048 );
95- EVP_PKEY_keygen (pctx, &pkey);
96- EVP_PKEY_CTX_free (pctx);
149+ Scoped<EVP_PKEY_CTX> pctx (EVP_PKEY_CTX_new_id (EVP_PKEY_RSA, NULL ));
97150
98- String result;
99- BIO* bio = BIO_new (BIO_s_mem ());
100- PEM_write_bio_PrivateKey (bio, pkey, NULL , NULL , 0 , NULL , NULL );
101- BUF_MEM* mem = NULL ;
102- BIO_get_mem_ptr (bio, &mem);
103- result.append (mem->data , mem->length );
104- BIO_free (bio);
151+ EVP_PKEY_keygen_init (pctx.get ());
152+ EVP_PKEY_CTX_set_rsa_keygen_bits (pctx.get (), 2048 );
105153
106- EVP_PKEY_free (pkey);
154+ Scoped<EVP_PKEY> pkey;
155+ { // Generate RSA key
156+ EVP_PKEY* temp = NULL ;
157+ EVP_PKEY_keygen (pctx.get (), &temp);
158+ pkey.reset (temp);
159+ }
107160
108- return result;
161+ Scoped<BIO> bio (BIO_new (BIO_s_mem ()));
162+ PEM_write_bio_PrivateKey (bio.get (), pkey.get (), NULL , NULL , 0 , NULL , NULL );
163+
164+ BUF_MEM* mem = NULL ;
165+ BIO_get_mem_ptr (bio.get (), &mem);
166+ return String (mem->data , mem->length );
109167}
110168
111169String Ssl::generate_cert (const String& key, String cn, String ca_cert, String ca_key) {
@@ -120,133 +178,75 @@ String Ssl::generate_cert(const String& key, String cn, String ca_cert, String c
120178#endif
121179 }
122180
123- EVP_PKEY* pkey = NULL ;
124- { // Read key from string
125- BIO* bio = BIO_new_mem_buf (const_cast <char *>(key.c_str ()), key.length ());
126- if (!PEM_read_bio_PrivateKey (bio, &pkey, NULL , NULL )) {
127- BIO_free (bio);
128- return " " ;
129- }
130- BIO_free (bio);
131- }
181+ Scoped<EVP_PKEY> pkey (load_private_key (key));
182+ if (!pkey) return " " ;
132183
133- X509_REQ* x509_req = NULL ;
184+ Scoped< X509_REQ> x509_req;
134185 if (!ca_cert.empty () && !ca_key.empty ()) {
135- x509_req = X509_REQ_new ();
136- X509_REQ_set_version (x509_req, 2 );
137- X509_REQ_set_pubkey (x509_req, pkey);
186+ x509_req. reset ( X509_REQ_new () );
187+ X509_REQ_set_version (x509_req. get () , 2 );
188+ X509_REQ_set_pubkey (x509_req. get () , pkey. get () );
138189
139- X509_NAME* name = X509_REQ_get_subject_name (x509_req);
190+ X509_NAME* name = X509_REQ_get_subject_name (x509_req. get () );
140191 X509_NAME_add_entry_by_txt (name, " C" , MBSTRING_ASC,
141192 reinterpret_cast <const unsigned char *>(" US" ), -1 , -1 , 0 );
142193 X509_NAME_add_entry_by_txt (name, " CN" , MBSTRING_ASC,
143194 reinterpret_cast <const unsigned char *>(cn.c_str ()), -1 , -1 , 0 );
144- X509_REQ_sign (x509_req, pkey, EVP_sha256 ());
195+ X509_REQ_sign (x509_req. get () , pkey. get () , EVP_sha256 ());
145196 }
146197
147- X509* x509 = X509_new ();
148- X509_set_version (x509, 2 );
149- ASN1_INTEGER_set (X509_get_serialNumber (x509), 0 );
150- X509_gmtime_adj (X509_get_notBefore (x509), 0 );
151- X509_gmtime_adj (X509_get_notAfter (x509), static_cast <long >(60 * 60 * 24 * 365 ));
152- X509_set_pubkey (x509, pkey);
198+ Scoped< X509> x509 ( X509_new () );
199+ X509_set_version (x509. get () , 2 );
200+ ASN1_INTEGER_set (X509_get_serialNumber (x509. get () ), 0 );
201+ X509_gmtime_adj (X509_get_notBefore (x509. get () ), 0 );
202+ X509_gmtime_adj (X509_get_notAfter (x509. get () ), static_cast <long >(60 * 60 * 24 * 365 ));
203+ X509_set_pubkey (x509. get () , pkey. get () );
153204
154205 if (x509_req) {
155- X509_set_subject_name (x509, X509_REQ_get_subject_name (x509_req));
156-
157- X509* x509_ca = NULL ;
158- { // Read CA from string
159- BIO* bio = BIO_new_mem_buf (const_cast <char *>(ca_cert.c_str ()), ca_cert.length ());
160- if (!PEM_read_bio_X509 (bio, &x509_ca, NULL , NULL )) {
161- X509_free (x509);
162- X509_REQ_free (x509_req);
163- BIO_free (bio);
164- return " " ;
165- }
166- BIO_free (bio);
167- }
168- X509_set_issuer_name (x509, X509_get_issuer_name (x509_ca));
169-
170- EVP_PKEY* pkey_ca = NULL ;
171- { // Read key from string
172- BIO* bio = BIO_new_mem_buf (const_cast <char *>(ca_key.c_str ()), ca_key.length ());
173- if (!PEM_read_bio_PrivateKey (bio, &pkey_ca, NULL , NULL )) {
174- BIO_free (bio);
175- X509_free (x509);
176- X509_free (x509_ca);
177- X509_REQ_free (x509_req);
178- return " " ;
179- }
180- BIO_free (bio);
181- }
182- X509_sign (x509, pkey_ca, EVP_sha256 ());
206+ X509_set_subject_name (x509.get (), X509_REQ_get_subject_name (x509_req.get ()));
207+
208+ Scoped<X509> x509_ca (load_cert (ca_cert));
209+ if (!x509_ca) return " " ;
210+ X509_set_issuer_name (x509.get (), X509_get_issuer_name (x509_ca.get ()));
183211
184- X509_free (x509_ca);
185- EVP_PKEY_free (pkey_ca);
212+ Scoped<EVP_PKEY> pkey_ca (load_private_key (ca_key));
213+ if (!pkey_ca) return " " ;
214+ X509_sign (x509.get (), pkey_ca.get (), EVP_sha256 ());
186215 } else {
187216 if (cn == " CA" ) { // Set the purpose as a CA certificate.
188- X509_EXTENSION* x509_ex;
189217 X509V3_CTX x509v3_ctx;
190218 X509V3_set_ctx_nodb (&x509v3_ctx);
191- X509V3_set_ctx (&x509v3_ctx, x509, x509, NULL , NULL , 0 );
192- x509_ex = X509V3_EXT_conf_nid (NULL , &x509v3_ctx, NID_basic_constraints,
193- const_cast <char *>(" critical,CA:TRUE" ));
194- if (!x509_ex) {
195- X509_free (x509);
196- X509_EXTENSION_free (x509_ex);
197- return " " ;
198- }
199- X509_add_ext (x509, x509_ex, -1 );
200- X509_EXTENSION_free (x509_ex);
219+ X509V3_set_ctx (&x509v3_ctx, x509.get (), x509.get (), NULL , NULL , 0 );
220+
221+ Scoped<X509_EXTENSION> x509_ex (X509V3_EXT_conf_nid (NULL , &x509v3_ctx, NID_basic_constraints,
222+ const_cast <char *>(" critical,CA:TRUE" )));
223+ if (!x509_ex) return " " ;
224+
225+ X509_add_ext (x509.get (), x509_ex.get (), -1 );
201226 }
202- X509_NAME* name = X509_get_subject_name (x509);
227+ X509_NAME* name = X509_get_subject_name (x509. get () );
203228 X509_NAME_add_entry_by_txt (name, " C" , MBSTRING_ASC,
204229 reinterpret_cast <const unsigned char *>(" US" ), -1 , -1 , 0 );
205230 X509_NAME_add_entry_by_txt (name, " CN" , MBSTRING_ASC,
206231 reinterpret_cast <const unsigned char *>(cn.c_str ()), -1 , -1 , 0 );
207- X509_set_issuer_name (x509, name);
208- X509_sign (x509, pkey, EVP_sha256 ());
232+ X509_set_issuer_name (x509. get () , name);
233+ X509_sign (x509. get () , pkey. get () , EVP_sha256 ());
209234 }
210235
211236 String result;
212237 { // Write cert into string
213- BIO* bio = BIO_new (BIO_s_mem ());
214- PEM_write_bio_X509 (bio, x509);
238+ Scoped< BIO> bio ( BIO_new (BIO_s_mem () ));
239+ PEM_write_bio_X509 (bio. get () , x509. get () );
215240 BUF_MEM* mem = NULL ;
216- BIO_get_mem_ptr (bio, &mem);
241+ BIO_get_mem_ptr (bio. get () , &mem);
217242 result.append (mem->data , mem->length );
218- BIO_free (bio);
219243 }
220244
221- X509_free (x509);
222- if (x509_req) X509_REQ_free (x509_req);
223-
224- EVP_PKEY_free (pkey);
225-
226245 return result;
227246}
228247
229248namespace internal {
230249
231- static void print_ssl_error () {
232- unsigned long err = ERR_get_error ();
233- char buf[256 ];
234- ERR_error_string_n (err, buf, sizeof (buf));
235- fprintf (stderr, " %s\n " , buf);
236- }
237-
238- static X509* load_cert (const String& cert) {
239- X509* x509 = NULL ;
240- BIO* bio = BIO_new_mem_buf (const_cast <char *>(cert.c_str ()), cert.length ());
241- if (PEM_read_bio_X509 (bio, &x509, NULL , NULL ) == NULL ) {
242- print_ssl_error ();
243- BIO_free (bio);
244- return NULL ;
245- }
246- BIO_free (bio);
247- return x509;
248- }
249-
250250struct WriteReq {
251251 WriteReq (const char * data, size_t len, ClientConnection* connection)
252252 : data(data, len)
@@ -499,59 +499,55 @@ bool ServerConnection::use_ssl(const String& key, const String& cert,
499499 SSL_CTX_set_verify (ssl_context_, SSL_VERIFY_NONE, NULL );
500500
501501 { // Load server certificate
502- X509* x509 = load_cert (cert);
502+ Scoped< X509> x509 ( load_cert (cert) );
503503 if (!x509) return false ;
504- if (SSL_CTX_use_certificate (ssl_context_, x509) <= 0 ) {
504+ if (SSL_CTX_use_certificate (ssl_context_, x509. get () ) <= 0 ) {
505505 print_ssl_error ();
506- X509_free (x509);
507506 return false ;
508507 }
509- X509_free (x509);
510508 }
511509
512510 if (!ca_cert.empty ()) { // Load CA certificate
513- X509* x509 = load_cert (ca_cert);
514- if (!x509) return false ;
515- if (SSL_CTX_add_extra_chain_cert (ssl_context_, x509) <= 0 ) { // Certificate freed by function
516- print_ssl_error ();
517- X509_free (x509);
518- return false ;
511+
512+ { // Add CA certificate to chain to send to the client
513+ Scoped<X509> x509 (load_cert (ca_cert));
514+ if (!x509) return false ;
515+
516+ if (SSL_CTX_add_extra_chain_cert (ssl_context_, x509.release ()) <=
517+ 0 ) { // Certificate freed by function
518+ print_ssl_error ();
519+ return false ;
520+ }
519521 }
522+
520523 if (require_client_cert) {
524+ Scoped<X509> x509 (load_cert (ca_cert));
525+ if (!x509) return false ;
526+
527+ // Add CA certificate to chain to validate peer certificate
521528 X509_STORE* cert_store = SSL_CTX_get_cert_store (ssl_context_);
522- if (X509_STORE_add_cert (cert_store, x509) <= 0 ) {
529+ if (X509_STORE_add_cert (cert_store, x509. get () ) <= 0 ) {
523530 print_ssl_error ();
524531 return false ;
525532 }
533+
526534 SSL_CTX_set_verify (ssl_context_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL );
527535 }
528536 }
529537
530- EVP_PKEY* pkey = NULL ;
531- { // Read key from string
532- BIO* bio = BIO_new_mem_buf (const_cast <char *>(key.c_str ()), key.length ());
533- if (PEM_read_bio_PrivateKey (bio, &pkey, on_password, (void *)" " ) == NULL ) {
534- print_ssl_error ();
535- BIO_free (bio);
536- return false ;
537- }
538- BIO_free (bio);
539- }
538+ Scoped<EVP_PKEY> pkey (load_private_key (key));
539+ if (!pkey) return false ;
540540
541- if (SSL_CTX_use_PrivateKey (ssl_context_, pkey) <= 0 ) {
541+ if (SSL_CTX_use_PrivateKey (ssl_context_, pkey. get () ) <= 0 ) {
542542 print_ssl_error ();
543- EVP_PKEY_free (pkey);
544543 return false ;
545544 }
546- EVP_PKEY_free (pkey);
547545
548- DH* dh = dh_parameters ();
549- if (!dh || !SSL_CTX_set_tmp_dh (ssl_context_, dh)) {
546+ Scoped<DH> dh ( dh_parameters () );
547+ if (!dh || !SSL_CTX_set_tmp_dh (ssl_context_, dh. get () )) {
550548 print_ssl_error ();
551- DH_free (dh);
552549 return false ;
553550 }
554- DH_free (dh);
555551
556552 return true ;
557553}
0 commit comments