]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ssl/support.cc
TLS: GnuTLS implementation for listening ports and client connections (#81)
[thirdparty/squid.git] / src / ssl / support.cc
1 /*
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 83 SSL accelerator support */
10
11 #include "squid.h"
12
13 /* MS Visual Studio Projects are monolithic, so we need the following
14 * #if to exclude the SSL code from compile process when not needed.
15 */
16 #if USE_OPENSSL
17
18 #include "acl/FilledChecklist.h"
19 #include "anyp/PortCfg.h"
20 #include "fatal.h"
21 #include "fd.h"
22 #include "fde.h"
23 #include "globals.h"
24 #include "ipc/MemMap.h"
25 #include "security/CertError.h"
26 #include "security/Session.h"
27 #include "SquidConfig.h"
28 #include "SquidTime.h"
29 #include "ssl/bio.h"
30 #include "ssl/Config.h"
31 #include "ssl/ErrorDetail.h"
32 #include "ssl/gadgets.h"
33 #include "ssl/support.h"
34 #include "URL.h"
35
36 #include <cerrno>
37
38 // TODO: Move ssl_ex_index_* global variables from global.cc here.
39 int ssl_ex_index_ssl_untrusted_chain = -1;
40
41 static Ssl::CertsIndexedList SquidUntrustedCerts;
42
43 const EVP_MD *Ssl::DefaultSignHash = NULL;
44
45 std::vector<const char *> Ssl::BumpModeStr = {
46 "none",
47 "client-first",
48 "server-first",
49 "peek",
50 "stare",
51 "bump",
52 "splice",
53 "terminate"
54 /*,"err"*/
55 };
56
57 /**
58 \defgroup ServerProtocolSSLInternal Server-Side SSL Internals
59 \ingroup ServerProtocolSSLAPI
60 */
61
62 int
63 Ssl::AskPasswordCb(char *buf, int size, int rwflag, void *userdata)
64 {
65 FILE *in;
66 int len = 0;
67 char cmdline[1024];
68
69 snprintf(cmdline, sizeof(cmdline), "\"%s\" \"%s\"", ::Config.Program.ssl_password, (const char *)userdata);
70 in = popen(cmdline, "r");
71
72 if (fgets(buf, size, in))
73
74 len = strlen(buf);
75
76 while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
77 --len;
78
79 buf[len] = '\0';
80
81 pclose(in);
82
83 return len;
84 }
85
86 /// \ingroup ServerProtocolSSLInternal
87 static void
88 ssl_ask_password(SSL_CTX * context, const char * prompt)
89 {
90 if (Config.Program.ssl_password) {
91 SSL_CTX_set_default_passwd_cb(context, Ssl::AskPasswordCb);
92 SSL_CTX_set_default_passwd_cb_userdata(context, (void *)prompt);
93 }
94 }
95
96 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
97 static RSA *
98 ssl_temp_rsa_cb(SSL * ssl, int anInt, int keylen)
99 {
100 static RSA *rsa_512 = NULL;
101 static RSA *rsa_1024 = NULL;
102 RSA *rsa = NULL;
103 int newkey = 0;
104
105 switch (keylen) {
106
107 case 512:
108
109 if (!rsa_512) {
110 rsa_512 = RSA_generate_key(512, RSA_F4, NULL, NULL);
111 newkey = 1;
112 }
113
114 rsa = rsa_512;
115 break;
116
117 case 1024:
118
119 if (!rsa_1024) {
120 rsa_1024 = RSA_generate_key(1024, RSA_F4, NULL, NULL);
121 newkey = 1;
122 }
123
124 rsa = rsa_1024;
125 break;
126
127 default:
128 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Unexpected key length " << keylen);
129 return NULL;
130 }
131
132 if (rsa == NULL) {
133 debugs(83, DBG_IMPORTANT, "ssl_temp_rsa_cb: Failed to generate key " << keylen);
134 return NULL;
135 }
136
137 if (newkey) {
138 if (Debug::Enabled(83, 5))
139 PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
140
141 debugs(83, DBG_IMPORTANT, "Generated ephemeral RSA key of length " << keylen);
142 }
143
144 return rsa;
145 }
146 #endif
147
148 void
149 Ssl::MaybeSetupRsaCallback(Security::ContextPointer &ctx)
150 {
151 #if HAVE_LIBSSL_SSL_CTX_SET_TMP_RSA_CALLBACK
152 debugs(83, 9, "Setting RSA key generation callback.");
153 SSL_CTX_set_tmp_rsa_callback(ctx.get(), ssl_temp_rsa_cb);
154 #endif
155 }
156
157 int Ssl::asn1timeToString(ASN1_TIME *tm, char *buf, int len)
158 {
159 BIO *bio;
160 int write = 0;
161 bio = BIO_new(BIO_s_mem());
162 if (bio) {
163 if (ASN1_TIME_print(bio, tm))
164 write = BIO_read(bio, buf, len-1);
165 BIO_free(bio);
166 }
167 buf[write]='\0';
168 return write;
169 }
170
171 int Ssl::matchX509CommonNames(X509 *peer_cert, void *check_data, int (*check_func)(void *check_data, ASN1_STRING *cn_data))
172 {
173 assert(peer_cert);
174
175 X509_NAME *name = X509_get_subject_name(peer_cert);
176
177 for (int i = X509_NAME_get_index_by_NID(name, NID_commonName, -1); i >= 0; i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) {
178
179 ASN1_STRING *cn_data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
180
181 if ( (*check_func)(check_data, cn_data) == 0)
182 return 1;
183 }
184
185 STACK_OF(GENERAL_NAME) * altnames;
186 altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(peer_cert, NID_subject_alt_name, NULL, NULL);
187
188 if (altnames) {
189 int numalts = sk_GENERAL_NAME_num(altnames);
190 for (int i = 0; i < numalts; ++i) {
191 const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
192 if (check->type != GEN_DNS) {
193 continue;
194 }
195 ASN1_STRING *cn_data = check->d.dNSName;
196
197 if ( (*check_func)(check_data, cn_data) == 0) {
198 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
199 return 1;
200 }
201 }
202 sk_GENERAL_NAME_pop_free(altnames, GENERAL_NAME_free);
203 }
204 return 0;
205 }
206
207 static int check_domain( void *check_data, ASN1_STRING *cn_data)
208 {
209 char cn[1024];
210 const char *server = (const char *)check_data;
211
212 if (cn_data->length == 0)
213 return 1; // zero length cn, ignore
214
215 if (cn_data->length > (int)sizeof(cn) - 1)
216 return 1; //if does not fit our buffer just ignore
217
218 char *s = reinterpret_cast<char*>(cn_data->data);
219 char *d = cn;
220 for (int i = 0; i < cn_data->length; ++i, ++d, ++s) {
221 if (*s == '\0')
222 return 1; // always a domain mismatch. contains 0x00
223 *d = *s;
224 }
225 cn[cn_data->length] = '\0';
226 debugs(83, 4, "Verifying server domain " << server << " to certificate name/subjectAltName " << cn);
227 return matchDomainName(server, (cn[0] == '*' ? cn + 1 : cn), mdnRejectSubsubDomains);
228 }
229
230 bool Ssl::checkX509ServerValidity(X509 *cert, const char *server)
231 {
232 return matchX509CommonNames(cert, (void *)server, check_domain);
233 }
234
235 #if !HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_CERT
236 static inline X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
237 {
238 return ctx->cert;
239 }
240 #endif
241
242 /// \ingroup ServerProtocolSSLInternal
243 static int
244 ssl_verify_cb(int ok, X509_STORE_CTX * ctx)
245 {
246 // preserve original ctx->error before SSL_ calls can overwrite it
247 Security::ErrorCode error_no = ok ? SSL_ERROR_NONE : X509_STORE_CTX_get_error(ctx);
248
249 char buffer[256] = "";
250 SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
251 SSL_CTX *sslctx = SSL_get_SSL_CTX(ssl);
252 SBuf *server = (SBuf *)SSL_get_ex_data(ssl, ssl_ex_index_server);
253 void *dont_verify_domain = SSL_CTX_get_ex_data(sslctx, ssl_ctx_ex_index_dont_verify_domain);
254 ACLChecklist *check = (ACLChecklist*)SSL_get_ex_data(ssl, ssl_ex_index_cert_error_check);
255 X509 *peeked_cert = (X509 *)SSL_get_ex_data(ssl, ssl_ex_index_ssl_peeked_cert);
256 Security::CertPointer peer_cert;
257 peer_cert.resetAndLock(X509_STORE_CTX_get0_cert(ctx));
258
259 X509_NAME_oneline(X509_get_subject_name(peer_cert.get()), buffer, sizeof(buffer));
260
261 // detect infinite loops
262 uint32_t *validationCounter = static_cast<uint32_t *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_validation_counter));
263 if (!validationCounter) {
264 validationCounter = new uint32_t(1);
265 SSL_set_ex_data(ssl, ssl_ex_index_ssl_validation_counter, validationCounter);
266 } else {
267 // overflows allowed if SQUID_CERT_VALIDATION_ITERATION_MAX >= UINT32_MAX
268 (*validationCounter)++;
269 }
270
271 if ((*validationCounter) >= SQUID_CERT_VALIDATION_ITERATION_MAX) {
272 ok = 0; // or the validation loop will never stop
273 error_no = SQUID_X509_V_ERR_INFINITE_VALIDATION;
274 debugs(83, 2, "SQUID_X509_V_ERR_INFINITE_VALIDATION: " <<
275 *validationCounter << " iterations while checking " << buffer);
276 }
277
278 if (ok) {
279 debugs(83, 5, "SSL Certificate signature OK: " << buffer);
280
281 // Check for domain mismatch only if the current certificate is the peer certificate.
282 if (!dont_verify_domain && server && peer_cert.get() == X509_STORE_CTX_get_current_cert(ctx)) {
283 if (!Ssl::checkX509ServerValidity(peer_cert.get(), server->c_str())) {
284 debugs(83, 2, "SQUID_X509_V_ERR_DOMAIN_MISMATCH: Certificate " << buffer << " does not match domainname " << server);
285 ok = 0;
286 error_no = SQUID_X509_V_ERR_DOMAIN_MISMATCH;
287 }
288 }
289 }
290
291 if (ok && peeked_cert) {
292 // Check whether the already peeked certificate matches the new one.
293 if (X509_cmp(peer_cert.get(), peeked_cert) != 0) {
294 debugs(83, 2, "SQUID_X509_V_ERR_CERT_CHANGE: Certificate " << buffer << " does not match peeked certificate");
295 ok = 0;
296 error_no = SQUID_X509_V_ERR_CERT_CHANGE;
297 }
298 }
299
300 if (!ok) {
301 Security::CertPointer broken_cert;
302 broken_cert.resetAndLock(X509_STORE_CTX_get_current_cert(ctx));
303 if (!broken_cert)
304 broken_cert = peer_cert;
305
306 Security::CertErrors *errs = static_cast<Security::CertErrors *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_errors));
307 const int depth = X509_STORE_CTX_get_error_depth(ctx);
308 if (!errs) {
309 errs = new Security::CertErrors(Security::CertError(error_no, broken_cert, depth));
310 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_errors, (void *)errs)) {
311 debugs(83, 2, "Failed to set ssl error_no in ssl_verify_cb: Certificate " << buffer);
312 delete errs;
313 errs = NULL;
314 }
315 } else // remember another error number
316 errs->push_back_unique(Security::CertError(error_no, broken_cert, depth));
317
318 if (const char *err_descr = Ssl::GetErrorDescr(error_no))
319 debugs(83, 5, err_descr << ": " << buffer);
320 else
321 debugs(83, DBG_IMPORTANT, "SSL unknown certificate error " << error_no << " in " << buffer);
322
323 // Check if the certificate error can be bypassed.
324 // Infinity validation loop errors can not bypassed.
325 if (error_no != SQUID_X509_V_ERR_INFINITE_VALIDATION) {
326 if (check) {
327 ACLFilledChecklist *filledCheck = Filled(check);
328 assert(!filledCheck->sslErrors);
329 filledCheck->sslErrors = new Security::CertErrors(Security::CertError(error_no, broken_cert));
330 filledCheck->serverCert = peer_cert;
331 if (check->fastCheck().allowed()) {
332 debugs(83, 3, "bypassing SSL error " << error_no << " in " << buffer);
333 ok = 1;
334 } else {
335 debugs(83, 5, "confirming SSL error " << error_no);
336 }
337 delete filledCheck->sslErrors;
338 filledCheck->sslErrors = NULL;
339 filledCheck->serverCert.reset();
340 }
341 // If the certificate validator is used then we need to allow all errors and
342 // pass them to certficate validator for more processing
343 else if (Ssl::TheConfig.ssl_crt_validator) {
344 ok = 1;
345 }
346 }
347 }
348
349 if (Ssl::TheConfig.ssl_crt_validator) {
350 // Check if we have stored certificates chain. Store if not.
351 if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
352 STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
353 if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
354 sk_X509_pop_free(certStack, X509_free);
355 }
356 }
357
358 if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
359
360 // Find the broken certificate. It may be intermediate.
361 Security::CertPointer broken_cert(peer_cert); // reasonable default if search fails
362 // Our SQUID_X509_V_ERR_DOMAIN_MISMATCH implies peer_cert is at fault.
363 if (error_no != SQUID_X509_V_ERR_DOMAIN_MISMATCH) {
364 if (auto *last_used_cert = X509_STORE_CTX_get_current_cert(ctx))
365 broken_cert.resetAndLock(last_used_cert);
366 }
367
368 auto *errDetail = new Ssl::ErrorDetail(error_no, peer_cert.get(), broken_cert.get());
369 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_error_detail, errDetail)) {
370 debugs(83, 2, "Failed to set Ssl::ErrorDetail in ssl_verify_cb: Certificate " << buffer);
371 delete errDetail;
372 }
373 }
374
375 return ok;
376 }
377
378 void
379 Ssl::SetupVerifyCallback(Security::ContextPointer &ctx)
380 {
381 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
382 }
383
384 // "dup" function for SSL_get_ex_new_index("cert_err_check")
385 #if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
386 static int
387 ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
388 int, long, void *)
389 #else
390 static int
391 ssl_dupAclChecklist(CRYPTO_EX_DATA *, CRYPTO_EX_DATA *, void *,
392 int, long, void *)
393 #endif
394 {
395 // We do not support duplication of ACLCheckLists.
396 // If duplication is needed, we can count copies with cbdata.
397 assert(false);
398 return 0;
399 }
400
401 // "free" function for SSL_get_ex_new_index("cert_err_check")
402 static void
403 ssl_freeAclChecklist(void *, void *ptr, CRYPTO_EX_DATA *,
404 int, long, void *)
405 {
406 delete static_cast<ACLChecklist *>(ptr); // may be NULL
407 }
408
409 // "free" function for SSL_get_ex_new_index("ssl_error_detail")
410 static void
411 ssl_free_ErrorDetail(void *, void *ptr, CRYPTO_EX_DATA *,
412 int, long, void *)
413 {
414 Ssl::ErrorDetail *errDetail = static_cast <Ssl::ErrorDetail *>(ptr);
415 delete errDetail;
416 }
417
418 static void
419 ssl_free_SslErrors(void *, void *ptr, CRYPTO_EX_DATA *,
420 int, long, void *)
421 {
422 Security::CertErrors *errs = static_cast <Security::CertErrors*>(ptr);
423 delete errs;
424 }
425
426 // "free" function for SSL_get_ex_new_index("ssl_ex_index_ssl_validation_counter")
427 static void
428 ssl_free_int(void *, void *ptr, CRYPTO_EX_DATA *,
429 int, long, void *)
430 {
431 uint32_t *counter = static_cast <uint32_t *>(ptr);
432 delete counter;
433 }
434
435 /// \ingroup ServerProtocolSSLInternal
436 /// Callback handler function to release STACK_OF(X509) "ex" data stored
437 /// in an SSL object.
438 static void
439 ssl_free_CertChain(void *, void *ptr, CRYPTO_EX_DATA *,
440 int, long, void *)
441 {
442 STACK_OF(X509) *certsChain = static_cast <STACK_OF(X509) *>(ptr);
443 sk_X509_pop_free(certsChain,X509_free);
444 }
445
446 // "free" function for X509 certificates
447 static void
448 ssl_free_X509(void *, void *ptr, CRYPTO_EX_DATA *,
449 int, long, void *)
450 {
451 X509 *cert = static_cast <X509 *>(ptr);
452 X509_free(cert);
453 }
454
455 // "free" function for SBuf
456 static void
457 ssl_free_SBuf(void *, void *ptr, CRYPTO_EX_DATA *,
458 int, long, void *)
459 {
460 SBuf *buf = static_cast <SBuf *>(ptr);
461 delete buf;
462 }
463
464 void
465 Ssl::Initialize(void)
466 {
467 static bool initialized = false;
468 if (initialized)
469 return;
470 initialized = true;
471
472 SSL_load_error_strings();
473 SSLeay_add_ssl_algorithms();
474
475 #if HAVE_OPENSSL_ENGINE_H
476 if (::Config.SSL.ssl_engine) {
477 ENGINE_load_builtin_engines();
478 ENGINE *e;
479 if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine)))
480 fatalf("Unable to find SSL engine '%s'\n", ::Config.SSL.ssl_engine);
481
482 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
483 const int ssl_error = ERR_get_error();
484 fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error));
485 }
486 }
487 #else
488 if (::Config.SSL.ssl_engine)
489 fatalf("Your OpenSSL has no SSL engine support\n");
490 #endif
491
492 const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE;
493 Ssl::DefaultSignHash = EVP_get_digestbyname(defName);
494 if (!Ssl::DefaultSignHash)
495 fatalf("Sign hash '%s' is not supported\n", defName);
496
497 ssl_ex_index_server = SSL_get_ex_new_index(0, (void *) "server", NULL, NULL, ssl_free_SBuf);
498 ssl_ctx_ex_index_dont_verify_domain = SSL_CTX_get_ex_new_index(0, (void *) "dont_verify_domain", NULL, NULL, NULL);
499 ssl_ex_index_cert_error_check = SSL_get_ex_new_index(0, (void *) "cert_error_check", NULL, &ssl_dupAclChecklist, &ssl_freeAclChecklist);
500 ssl_ex_index_ssl_error_detail = SSL_get_ex_new_index(0, (void *) "ssl_error_detail", NULL, NULL, &ssl_free_ErrorDetail);
501 ssl_ex_index_ssl_peeked_cert = SSL_get_ex_new_index(0, (void *) "ssl_peeked_cert", NULL, NULL, &ssl_free_X509);
502 ssl_ex_index_ssl_errors = SSL_get_ex_new_index(0, (void *) "ssl_errors", NULL, NULL, &ssl_free_SslErrors);
503 ssl_ex_index_ssl_cert_chain = SSL_get_ex_new_index(0, (void *) "ssl_cert_chain", NULL, NULL, &ssl_free_CertChain);
504 ssl_ex_index_ssl_validation_counter = SSL_get_ex_new_index(0, (void *) "ssl_validation_counter", NULL, NULL, &ssl_free_int);
505 ssl_ex_index_ssl_untrusted_chain = SSL_get_ex_new_index(0, (void *) "ssl_untrusted_chain", NULL, NULL, &ssl_free_CertChain);
506 }
507
508 bool
509 Ssl::InitServerContext(Security::ContextPointer &ctx, AnyP::PortCfg &port)
510 {
511 if (!ctx)
512 return false;
513
514 return true;
515 }
516
517 bool
518 Ssl::InitClientContext(Security::ContextPointer &ctx, Security::PeerOptions &peer, long fl)
519 {
520 if (!ctx)
521 return false;
522
523 if (!peer.sslCipher.isEmpty()) {
524 debugs(83, 5, "Using chiper suite " << peer.sslCipher << ".");
525
526 const char *cipher = peer.sslCipher.c_str();
527 if (!SSL_CTX_set_cipher_list(ctx.get(), cipher)) {
528 const int ssl_error = ERR_get_error();
529 fatalf("Failed to set SSL cipher suite '%s': %s\n",
530 cipher, Security::ErrorString(ssl_error));
531 }
532 }
533
534 if (!peer.certs.empty()) {
535 // TODO: support loading multiple cert/key pairs
536 auto &keys = peer.certs.front();
537 if (!keys.certFile.isEmpty()) {
538 debugs(83, DBG_IMPORTANT, "Using certificate in " << keys.certFile);
539
540 const char *certfile = keys.certFile.c_str();
541 if (!SSL_CTX_use_certificate_chain_file(ctx.get(), certfile)) {
542 const int ssl_error = ERR_get_error();
543 fatalf("Failed to acquire SSL certificate '%s': %s\n",
544 certfile, Security::ErrorString(ssl_error));
545 }
546
547 debugs(83, DBG_IMPORTANT, "Using private key in " << keys.privateKeyFile);
548 const char *keyfile = keys.privateKeyFile.c_str();
549 ssl_ask_password(ctx.get(), keyfile);
550
551 if (!SSL_CTX_use_PrivateKey_file(ctx.get(), keyfile, SSL_FILETYPE_PEM)) {
552 const int ssl_error = ERR_get_error();
553 fatalf("Failed to acquire SSL private key '%s': %s\n",
554 keyfile, Security::ErrorString(ssl_error));
555 }
556
557 debugs(83, 5, "Comparing private and public SSL keys.");
558
559 if (!SSL_CTX_check_private_key(ctx.get())) {
560 const int ssl_error = ERR_get_error();
561 fatalf("SSL private key '%s' does not match public key '%s': %s\n",
562 certfile, keyfile, Security::ErrorString(ssl_error));
563 }
564 }
565 }
566
567 MaybeSetupRsaCallback(ctx);
568
569 if (fl & SSL_FLAG_DONT_VERIFY_PEER) {
570 debugs(83, 2, "SECURITY WARNING: Peer certificates are not verified for validity!");
571 SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_NONE, NULL);
572 } else {
573 debugs(83, 9, "Setting certificate verification callback.");
574 Ssl::SetupVerifyCallback(ctx);
575 }
576
577 return true;
578 }
579
580 /// \ingroup ServerProtocolSSLInternal
581 static const char *
582 ssl_get_attribute(X509_NAME * name, const char *attribute_name)
583 {
584 static char buffer[1024];
585 buffer[0] = '\0';
586
587 if (strcmp(attribute_name, "DN") == 0) {
588 X509_NAME_oneline(name, buffer, sizeof(buffer));
589 } else {
590 int nid = OBJ_txt2nid(const_cast<char *>(attribute_name));
591 if (nid == 0) {
592 debugs(83, DBG_IMPORTANT, "WARNING: Unknown SSL attribute name '" << attribute_name << "'");
593 return nullptr;
594 }
595 X509_NAME_get_text_by_NID(name, nid, buffer, sizeof(buffer));
596 }
597
598 return *buffer ? buffer : nullptr;
599 }
600
601 /// \ingroup ServerProtocolSSLInternal
602 const char *
603 Ssl::GetX509UserAttribute(X509 * cert, const char *attribute_name)
604 {
605 X509_NAME *name;
606 const char *ret;
607
608 if (!cert)
609 return NULL;
610
611 name = X509_get_subject_name(cert);
612
613 ret = ssl_get_attribute(name, attribute_name);
614
615 return ret;
616 }
617
618 const char *
619 Ssl::GetX509Fingerprint(X509 * cert, const char *)
620 {
621 static char buf[1024];
622 if (!cert)
623 return NULL;
624
625 unsigned int n;
626 unsigned char md[EVP_MAX_MD_SIZE];
627 if (!X509_digest(cert, EVP_sha1(), md, &n))
628 return NULL;
629
630 assert(3 * n + 1 < sizeof(buf));
631
632 char *s = buf;
633 for (unsigned int i=0; i < n; ++i, s += 3) {
634 const char term = (i + 1 < n) ? ':' : '\0';
635 snprintf(s, 4, "%02X%c", md[i], term);
636 }
637
638 return buf;
639 }
640
641 /// \ingroup ServerProtocolSSLInternal
642 const char *
643 Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
644 {
645
646 X509_NAME *name;
647 const char *ret;
648
649 if (!cert)
650 return NULL;
651
652 name = X509_get_issuer_name(cert);
653
654 ret = ssl_get_attribute(name, attribute_name);
655
656 return ret;
657 }
658
659 const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name)
660 {
661 if (!ssl)
662 return NULL;
663
664 X509 *cert = SSL_get_peer_certificate(ssl);
665
666 const char *attr = Ssl::GetX509UserAttribute(cert, attribute_name);
667
668 X509_free(cert);
669 return attr;
670 }
671
672 const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name)
673 {
674 if (!ssl)
675 return NULL;
676
677 X509 *cert = SSL_get_peer_certificate(ssl);
678
679 const char *attr = Ssl::GetX509CAAttribute(cert, attribute_name);
680
681 X509_free(cert);
682 return attr;
683 }
684
685 const char *
686 sslGetUserEmail(SSL * ssl)
687 {
688 return sslGetUserAttribute(ssl, "emailAddress");
689 }
690
691 const char *
692 sslGetUserCertificatePEM(SSL *ssl)
693 {
694 X509 *cert;
695 BIO *mem;
696 static char *str = NULL;
697 char *ptr;
698 long len;
699
700 safe_free(str);
701
702 if (!ssl)
703 return NULL;
704
705 cert = SSL_get_peer_certificate(ssl);
706
707 if (!cert)
708 return NULL;
709
710 mem = BIO_new(BIO_s_mem());
711
712 PEM_write_bio_X509(mem, cert);
713
714 len = BIO_get_mem_data(mem, &ptr);
715
716 str = (char *)xmalloc(len + 1);
717
718 memcpy(str, ptr, len);
719
720 str[len] = '\0';
721
722 X509_free(cert);
723
724 BIO_free(mem);
725
726 return str;
727 }
728
729 const char *
730 sslGetUserCertificateChainPEM(SSL *ssl)
731 {
732 STACK_OF(X509) *chain;
733 BIO *mem;
734 static char *str = NULL;
735 char *ptr;
736 long len;
737 int i;
738
739 safe_free(str);
740
741 if (!ssl)
742 return NULL;
743
744 chain = SSL_get_peer_cert_chain(ssl);
745
746 if (!chain)
747 return sslGetUserCertificatePEM(ssl);
748
749 mem = BIO_new(BIO_s_mem());
750
751 for (i = 0; i < sk_X509_num(chain); ++i) {
752 X509 *cert = sk_X509_value(chain, i);
753 PEM_write_bio_X509(mem, cert);
754 }
755
756 len = BIO_get_mem_data(mem, &ptr);
757
758 str = (char *)xmalloc(len + 1);
759 memcpy(str, ptr, len);
760 str[len] = '\0';
761
762 BIO_free(mem);
763
764 return str;
765 }
766
767 /// Create SSL context and apply ssl certificate and private key to it.
768 Security::ContextPointer
769 Ssl::createSSLContext(Security::CertPointer & x509, Security::PrivateKeyPointer & pkey, Security::ServerOptions &options)
770 {
771 Security::ContextPointer ctx(options.createBlankContext());
772
773 if (!SSL_CTX_use_certificate(ctx.get(), x509.get()))
774 return Security::ContextPointer();
775
776 if (!SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()))
777 return Security::ContextPointer();
778
779 if (!options.updateContextConfig(ctx))
780 return Security::ContextPointer();
781
782 return ctx;
783 }
784
785 Security::ContextPointer
786 Ssl::GenerateSslContextUsingPkeyAndCertFromMemory(const char * data, Security::ServerOptions &options, bool trusted)
787 {
788 Security::CertPointer cert;
789 Security::PrivateKeyPointer pkey;
790 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data) || !cert || !pkey)
791 return Security::ContextPointer();
792
793 Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
794 if (ctx && trusted)
795 Ssl::chainCertificatesToSSLContext(ctx, options);
796 return ctx;
797 }
798
799 Security::ContextPointer
800 Ssl::GenerateSslContext(CertificateProperties const &properties, Security::ServerOptions &options, bool trusted)
801 {
802 Security::CertPointer cert;
803 Security::PrivateKeyPointer pkey;
804 if (!generateSslCertificate(cert, pkey, properties) || !cert || !pkey)
805 return Security::ContextPointer();
806
807 Security::ContextPointer ctx(createSSLContext(cert, pkey, options));
808 if (ctx && trusted)
809 Ssl::chainCertificatesToSSLContext(ctx, options);
810 return ctx;
811 }
812
813 void
814 Ssl::chainCertificatesToSSLContext(Security::ContextPointer &ctx, Security::ServerOptions &options)
815 {
816 assert(ctx);
817 // Add signing certificate to the certificates chain
818 X509 *signingCert = options.signingCa.cert.get();
819 if (SSL_CTX_add_extra_chain_cert(ctx.get(), signingCert)) {
820 // increase the certificate lock
821 X509_up_ref(signingCert);
822 } else {
823 const int ssl_error = ERR_get_error();
824 debugs(33, DBG_IMPORTANT, "WARNING: can not add signing certificate to SSL context chain: " << Security::ErrorString(ssl_error));
825 }
826
827 for (auto cert : options.signingCa.chain) {
828 if (SSL_CTX_add_extra_chain_cert(ctx.get(), cert.get())) {
829 // increase the certificate lock
830 X509_up_ref(cert.get());
831 } else {
832 const auto error = ERR_get_error();
833 debugs(83, DBG_IMPORTANT, "WARNING: can not add certificate to SSL dynamic context chain: " << Security::ErrorString(error));
834 }
835 }
836 }
837
838 void
839 Ssl::configureUnconfiguredSslContext(Security::ContextPointer &ctx, Ssl::CertSignAlgorithm signAlgorithm,AnyP::PortCfg &port)
840 {
841 if (ctx && signAlgorithm == Ssl::algSignTrusted)
842 Ssl::chainCertificatesToSSLContext(ctx, port.secure);
843 }
844
845 bool
846 Ssl::configureSSL(SSL *ssl, CertificateProperties const &properties, AnyP::PortCfg &port)
847 {
848 Security::CertPointer cert;
849 Security::PrivateKeyPointer pkey;
850 if (!generateSslCertificate(cert, pkey, properties))
851 return false;
852
853 if (!cert)
854 return false;
855
856 if (!pkey)
857 return false;
858
859 if (!SSL_use_certificate(ssl, cert.get()))
860 return false;
861
862 if (!SSL_use_PrivateKey(ssl, pkey.get()))
863 return false;
864
865 return true;
866 }
867
868 bool
869 Ssl::configureSSLUsingPkeyAndCertFromMemory(SSL *ssl, const char *data, AnyP::PortCfg &port)
870 {
871 Security::CertPointer cert;
872 Security::PrivateKeyPointer pkey;
873 if (!readCertAndPrivateKeyFromMemory(cert, pkey, data))
874 return false;
875
876 if (!cert || !pkey)
877 return false;
878
879 if (!SSL_use_certificate(ssl, cert.get()))
880 return false;
881
882 if (!SSL_use_PrivateKey(ssl, pkey.get()))
883 return false;
884
885 return true;
886 }
887
888 bool
889 Ssl::verifySslCertificate(Security::ContextPointer &ctx, CertificateProperties const &properties)
890 {
891 #if HAVE_SSL_CTX_GET0_CERTIFICATE
892 X509 * cert = SSL_CTX_get0_certificate(ctx.get());
893 #elif SQUID_USE_SSLGETCERTIFICATE_HACK
894 // SSL_get_certificate is buggy in openssl versions 1.0.1d and 1.0.1e
895 // Try to retrieve certificate directly from Security::ContextPointer object
896 X509 ***pCert = (X509 ***)ctx->cert;
897 X509 * cert = pCert && *pCert ? **pCert : NULL;
898 #elif SQUID_SSLGETCERTIFICATE_BUGGY
899 X509 * cert = NULL;
900 assert(0);
901 #else
902 // Temporary ssl for getting X509 certificate from SSL_CTX.
903 Security::SessionPointer ssl(Security::NewSessionObject(ctx));
904 X509 * cert = SSL_get_certificate(ssl.get());
905 #endif
906 if (!cert)
907 return false;
908 ASN1_TIME * time_notBefore = X509_get_notBefore(cert);
909 ASN1_TIME * time_notAfter = X509_get_notAfter(cert);
910 return (X509_cmp_current_time(time_notBefore) < 0 && X509_cmp_current_time(time_notAfter) > 0);
911 }
912
913 void
914 Ssl::setClientSNI(SSL *ssl, const char *fqdn)
915 {
916 const Ip::Address test(fqdn);
917 if (!test.isAnyAddr())
918 return; // raw IP is inappropriate for SNI
919
920 //The SSL_CTRL_SET_TLSEXT_HOSTNAME is a openssl macro which indicates
921 // if the TLS servername extension (SNI) is enabled in openssl library.
922 #if defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
923 if (!SSL_set_tlsext_host_name(ssl, fqdn)) {
924 const int ssl_error = ERR_get_error();
925 debugs(83, 3, "WARNING: unable to set TLS servername extension (SNI): " <<
926 Security::ErrorString(ssl_error) << "\n");
927 }
928 #else
929 debugs(83, 7, "no support for TLS servername extension (SNI)");
930 #endif
931 }
932
933 static const char *
934 hasAuthorityInfoAccessCaIssuers(X509 *cert)
935 {
936 AUTHORITY_INFO_ACCESS *info;
937 if (!cert)
938 return nullptr;
939 info = static_cast<AUTHORITY_INFO_ACCESS *>(X509_get_ext_d2i(cert, NID_info_access, NULL, NULL));
940 if (!info)
941 return nullptr;
942
943 static char uri[MAX_URL];
944 uri[0] = '\0';
945
946 for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
947 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
948 if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers) {
949 if (ad->location->type == GEN_URI) {
950 xstrncpy(uri,
951 reinterpret_cast<const char *>(
952 #if HAVE_LIBCRYPTO_ASN1_STRING_GET0_DATA
953 ASN1_STRING_get0_data(ad->location->d.uniformResourceIdentifier)
954 #else
955 ASN1_STRING_data(ad->location->d.uniformResourceIdentifier)
956 #endif
957 ),
958 sizeof(uri));
959 }
960 break;
961 }
962 }
963 AUTHORITY_INFO_ACCESS_free(info);
964 return uri[0] != '\0' ? uri : nullptr;
965 }
966
967 bool
968 Ssl::loadCerts(const char *certsFile, Ssl::CertsIndexedList &list)
969 {
970 BIO *in = BIO_new_file(certsFile, "r");
971 if (!in) {
972 debugs(83, DBG_IMPORTANT, "Failed to open '" << certsFile << "' to load certificates");
973 return false;
974 }
975
976 X509 *aCert;
977 while((aCert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
978 static char buffer[2048];
979 X509_NAME_oneline(X509_get_subject_name(aCert), buffer, sizeof(buffer));
980 list.insert(std::pair<SBuf, X509 *>(SBuf(buffer), aCert));
981 }
982 debugs(83, 4, "Loaded " << list.size() << " certificates from file: '" << certsFile << "'");
983 BIO_free(in);
984 return true;
985 }
986
987 /// quickly find the issuer certificate of a certificate cert in the
988 /// Ssl::CertsIndexedList list
989 static X509 *
990 findCertIssuerFast(Ssl::CertsIndexedList &list, X509 *cert)
991 {
992 static char buffer[2048];
993
994 if (X509_NAME *issuerName = X509_get_issuer_name(cert))
995 X509_NAME_oneline(issuerName, buffer, sizeof(buffer));
996 else
997 return NULL;
998
999 const auto ret = list.equal_range(SBuf(buffer));
1000 for (Ssl::CertsIndexedList::iterator it = ret.first; it != ret.second; ++it) {
1001 X509 *issuer = it->second;
1002 if (X509_check_issued(issuer, cert) == X509_V_OK) {
1003 return issuer;
1004 }
1005 }
1006 return NULL;
1007 }
1008
1009 /// slowly find the issuer certificate of a given cert using linear search
1010 static bool
1011 findCertIssuer(Security::CertList const &list, X509 *cert)
1012 {
1013 for (Security::CertList::const_iterator it = list.begin(); it != list.end(); ++it) {
1014 if (X509_check_issued(it->get(), cert) == X509_V_OK)
1015 return true;
1016 }
1017 return false;
1018 }
1019
1020 /// \return true if the cert issuer exist in the certificates stored in connContext
1021 static bool
1022 issuerExistInCaDb(X509 *cert, const Security::ContextPointer &connContext)
1023 {
1024 if (!connContext)
1025 return false;
1026
1027 X509_STORE_CTX *storeCtx = X509_STORE_CTX_new();
1028 if (!storeCtx) {
1029 debugs(83, DBG_IMPORTANT, "Failed to allocate STORE_CTX object");
1030 return false;
1031 }
1032
1033 bool gotIssuer = false;
1034 X509_STORE *store = SSL_CTX_get_cert_store(connContext.get());
1035 if (X509_STORE_CTX_init(storeCtx, store, nullptr, nullptr)) {
1036 X509 *issuer = nullptr;
1037 gotIssuer = (X509_STORE_CTX_get1_issuer(&issuer, storeCtx, cert) > 0);
1038 if (issuer)
1039 X509_free(issuer);
1040 } else {
1041 const int ssl_error = ERR_get_error();
1042 debugs(83, DBG_IMPORTANT, "Failed to initialize STORE_CTX object: " << Security::ErrorString(ssl_error));
1043 }
1044 X509_STORE_CTX_free(storeCtx);
1045
1046 return gotIssuer;
1047 }
1048
1049 const char *
1050 Ssl::uriOfIssuerIfMissing(X509 *cert, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
1051 {
1052 if (!cert || !serverCertificates.size())
1053 return nullptr;
1054
1055 if (!findCertIssuer(serverCertificates, cert)) {
1056 //if issuer is missing
1057 if (const char *issuerUri = hasAuthorityInfoAccessCaIssuers(cert)) {
1058 // There is a URI where we can download a certificate.
1059 if (!findCertIssuerFast(SquidUntrustedCerts, cert) &&
1060 !issuerExistInCaDb(cert, context)) {
1061 // and issuer not found in local databases containing
1062 // untrusted certificates and trusted CA certificates
1063 return issuerUri;
1064 }
1065 }
1066 }
1067 return nullptr;
1068 }
1069
1070 void
1071 Ssl::missingChainCertificatesUrls(std::queue<SBuf> &URIs, Security::CertList const &serverCertificates, const Security::ContextPointer &context)
1072 {
1073 if (!serverCertificates.size())
1074 return;
1075
1076 for (const auto &i : serverCertificates) {
1077 if (const char *issuerUri = uriOfIssuerIfMissing(i.get(), serverCertificates, context))
1078 URIs.push(SBuf(issuerUri));
1079 }
1080 }
1081
1082 void
1083 Ssl::SSL_add_untrusted_cert(SSL *ssl, X509 *cert)
1084 {
1085 STACK_OF(X509) *untrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1086 if (!untrustedStack) {
1087 untrustedStack = sk_X509_new_null();
1088 if (!SSL_set_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain, untrustedStack)) {
1089 sk_X509_pop_free(untrustedStack, X509_free);
1090 throw TextException("Failed to attach untrusted certificates chain", Here());
1091 }
1092 }
1093 sk_X509_push(untrustedStack, cert);
1094 }
1095
1096 /// Search for the issuer certificate of cert in sk list.
1097 static X509 *
1098 sk_x509_findIssuer(STACK_OF(X509) *sk, X509 *cert)
1099 {
1100 if (!sk)
1101 return NULL;
1102
1103 const int skItemsNum = sk_X509_num(sk);
1104 for (int i = 0; i < skItemsNum; ++i) {
1105 X509 *issuer = sk_X509_value(sk, i);
1106 if (X509_check_issued(issuer, cert) == X509_V_OK)
1107 return issuer;
1108 }
1109 return NULL;
1110 }
1111
1112 /// add missing issuer certificates to untrustedCerts
1113 static void
1114 completeIssuers(X509_STORE_CTX *ctx, STACK_OF(X509) *untrustedCerts)
1115 {
1116 debugs(83, 2, "completing " << sk_X509_num(untrustedCerts) << " OpenSSL untrusted certs using " << SquidUntrustedCerts.size() << " configured untrusted certificates");
1117
1118 #if HAVE_LIBCRYPTO_X509_VERIFY_PARAM_GET_DEPTH
1119 const X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx);
1120 int depth = X509_VERIFY_PARAM_get_depth(param);
1121 #else
1122 int depth = ctx->param->depth;
1123 #endif
1124 X509 *current = X509_STORE_CTX_get0_cert(ctx);
1125 int i = 0;
1126 for (i = 0; current && (i < depth); ++i) {
1127 if (X509_check_issued(current, current) == X509_V_OK) {
1128 // either ctx->cert is itself self-signed or untrustedCerts
1129 // aready contain the self-signed current certificate
1130 break;
1131 }
1132
1133 // untrustedCerts is short, not worth indexing
1134 X509 *issuer = sk_x509_findIssuer(untrustedCerts, current);
1135 if (!issuer) {
1136 if ((issuer = findCertIssuerFast(SquidUntrustedCerts, current)))
1137 sk_X509_push(untrustedCerts, issuer);
1138 }
1139 current = issuer;
1140 }
1141
1142 if (i >= depth)
1143 debugs(83, 2, "exceeded the maximum certificate chain length: " << depth);
1144 }
1145
1146 /// OpenSSL certificate validation callback.
1147 static int
1148 untrustedToStoreCtx_cb(X509_STORE_CTX *ctx,void *data)
1149 {
1150 debugs(83, 4, "Try to use pre-downloaded intermediate certificates");
1151
1152 SSL *ssl = static_cast<SSL *>(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
1153 STACK_OF(X509) *sslUntrustedStack = static_cast <STACK_OF(X509) *>(SSL_get_ex_data(ssl, ssl_ex_index_ssl_untrusted_chain));
1154
1155 // OpenSSL already maintains ctx->untrusted but we cannot modify
1156 // internal OpenSSL list directly. We have to give OpenSSL our own
1157 // list, but it must include certificates on the OpenSSL ctx->untrusted
1158 #if HAVE_LIBCRYPTO_X509_STORE_CTX_GET0_UNTRUSTED
1159 STACK_OF(X509) *oldUntrusted = X509_STORE_CTX_get0_untrusted(ctx);
1160 #else
1161 STACK_OF(X509) *oldUntrusted = ctx->untrusted;
1162 #endif
1163 STACK_OF(X509) *sk = sk_X509_dup(oldUntrusted); // oldUntrusted is always not NULL
1164
1165 for (int i = 0; i < sk_X509_num(sslUntrustedStack); ++i) {
1166 X509 *cert = sk_X509_value(sslUntrustedStack, i);
1167 sk_X509_push(sk, cert);
1168 }
1169
1170 // If the local untrusted certificates internal database is used
1171 // run completeIssuers to add missing certificates if possible.
1172 if (SquidUntrustedCerts.size() > 0)
1173 completeIssuers(ctx, sk);
1174
1175 X509_STORE_CTX_set_chain(ctx, sk); // No locking/unlocking, just sets ctx->untrusted
1176 int ret = X509_verify_cert(ctx);
1177 #if HAVE_LIBCRYPTO_X509_STORE_CTX_SET0_UNTRUSTED
1178 X509_STORE_CTX_set0_untrusted(ctx, oldUntrusted);
1179 #else
1180 X509_STORE_CTX_set_chain(ctx, oldUntrusted); // Set back the old untrusted list
1181 #endif
1182 sk_X509_free(sk); // Release sk list
1183 return ret;
1184 }
1185
1186 void
1187 Ssl::useSquidUntrusted(SSL_CTX *sslContext)
1188 {
1189 SSL_CTX_set_cert_verify_callback(sslContext, untrustedToStoreCtx_cb, NULL);
1190 }
1191
1192 bool
1193 Ssl::loadSquidUntrusted(const char *path)
1194 {
1195 return Ssl::loadCerts(path, SquidUntrustedCerts);
1196 }
1197
1198 void
1199 Ssl::unloadSquidUntrusted()
1200 {
1201 if (SquidUntrustedCerts.size()) {
1202 for (Ssl::CertsIndexedList::iterator it = SquidUntrustedCerts.begin(); it != SquidUntrustedCerts.end(); ++it) {
1203 X509_free(it->second);
1204 }
1205 SquidUntrustedCerts.clear();
1206 }
1207 }
1208
1209 bool Ssl::generateUntrustedCert(Security::CertPointer &untrustedCert, Security::PrivateKeyPointer &untrustedPkey, Security::CertPointer const &cert, Security::PrivateKeyPointer const & pkey)
1210 {
1211 // Generate the self-signed certificate, using a hard-coded subject prefix
1212 Ssl::CertificateProperties certProperties;
1213 if (const char *cn = CommonHostName(cert.get())) {
1214 certProperties.commonName = "Not trusted by \"";
1215 certProperties.commonName += cn;
1216 certProperties.commonName += "\"";
1217 } else if (const char *org = getOrganization(cert.get())) {
1218 certProperties.commonName = "Not trusted by \"";
1219 certProperties.commonName += org;
1220 certProperties.commonName += "\"";
1221 } else
1222 certProperties.commonName = "Not trusted";
1223 certProperties.setCommonName = true;
1224 // O, OU, and other CA subject fields will be mimicked
1225 // Expiration date and other common properties will be mimicked
1226 certProperties.signAlgorithm = Ssl::algSignSelf;
1227 certProperties.signWithPkey.resetAndLock(pkey.get());
1228 certProperties.mimicCert.resetAndLock(cert.get());
1229 return Ssl::generateSslCertificate(untrustedCert, untrustedPkey, certProperties);
1230 }
1231
1232 void Ssl::InRamCertificateDbKey(const Ssl::CertificateProperties &certProperties, SBuf &key)
1233 {
1234 bool origSignatureAsKey = false;
1235 if (certProperties.mimicCert) {
1236 if (auto *sig = Ssl::X509_get_signature(certProperties.mimicCert)) {
1237 origSignatureAsKey = true;
1238 key.append((const char *)sig->data, sig->length);
1239 }
1240 }
1241
1242 if (!origSignatureAsKey || certProperties.setCommonName) {
1243 // Use common name instead
1244 key.append(certProperties.commonName.c_str());
1245 }
1246 key.append(certProperties.setCommonName ? '1' : '0');
1247 key.append(certProperties.setValidAfter ? '1' : '0');
1248 key.append(certProperties.setValidBefore ? '1' : '0');
1249 key.append(certProperties.signAlgorithm != Ssl:: algSignEnd ? certSignAlgorithm(certProperties.signAlgorithm) : "-");
1250 key.append(certProperties.signHash ? EVP_MD_name(certProperties.signHash) : "-");
1251
1252 if (certProperties.mimicCert) {
1253 Ssl::BIO_Pointer bio(BIO_new_SBuf(&key));
1254 ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bio.get(), (ASN1_VALUE *)certProperties.mimicCert.get());
1255 }
1256 }
1257
1258 static int
1259 bio_sbuf_create(BIO* bio)
1260 {
1261 BIO_set_init(bio, 0);
1262 BIO_set_data(bio, NULL);
1263 return 1;
1264 }
1265
1266 static int
1267 bio_sbuf_destroy(BIO* bio)
1268 {
1269 if (!bio)
1270 return 0;
1271 return 1;
1272 }
1273
1274 int
1275 bio_sbuf_write(BIO* bio, const char* data, int len)
1276 {
1277 SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1278 // TODO: Convert exceptions into BIO errors
1279 buf->append(data, len);
1280 return len;
1281 }
1282
1283 int
1284 bio_sbuf_puts(BIO* bio, const char* data)
1285 {
1286 // TODO: use bio_sbuf_write() instead
1287 SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1288 size_t oldLen = buf->length();
1289 buf->append(data);
1290 return buf->length() - oldLen;
1291 }
1292
1293 long
1294 bio_sbuf_ctrl(BIO* bio, int cmd, long num, void* ptr) {
1295 SBuf *buf = static_cast<SBuf *>(BIO_get_data(bio));
1296 switch (cmd) {
1297 case BIO_CTRL_RESET:
1298 // TODO: Convert exceptions into BIO errors
1299 buf->clear();
1300 return 1;
1301 case BIO_CTRL_FLUSH:
1302 return 1;
1303 default:
1304 return 0;
1305 }
1306 }
1307
1308 BIO *Ssl::BIO_new_SBuf(SBuf *buf)
1309 {
1310 #if HAVE_LIBCRYPTO_BIO_METH_NEW
1311 static BIO_METHOD *BioSBufMethods = nullptr;
1312 if (!BioSBufMethods) {
1313 BioSBufMethods = BIO_meth_new(BIO_TYPE_MEM, "Squid-SBuf");
1314 BIO_meth_set_write(BioSBufMethods, bio_sbuf_write);
1315 BIO_meth_set_read(BioSBufMethods, nullptr);
1316 BIO_meth_set_puts(BioSBufMethods, bio_sbuf_puts);
1317 BIO_meth_set_gets(BioSBufMethods, nullptr);
1318 BIO_meth_set_ctrl(BioSBufMethods, bio_sbuf_ctrl);
1319 BIO_meth_set_create(BioSBufMethods, bio_sbuf_create);
1320 BIO_meth_set_destroy(BioSBufMethods, bio_sbuf_destroy);
1321 }
1322 #else
1323 static BIO_METHOD *BioSBufMethods = new BIO_METHOD({
1324 BIO_TYPE_MEM,
1325 "Squid SBuf",
1326 bio_sbuf_write,
1327 nullptr,
1328 bio_sbuf_puts,
1329 nullptr,
1330 bio_sbuf_ctrl,
1331 bio_sbuf_create,
1332 bio_sbuf_destroy,
1333 NULL
1334 });
1335 #endif
1336 BIO *bio = BIO_new(BioSBufMethods);
1337 Must(bio);
1338 BIO_set_data(bio, buf);
1339 BIO_set_init(bio, 1);
1340 return bio;
1341 }
1342
1343 #endif /* USE_OPENSSL */
1344