]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ssl/gadgets.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ssl / gadgets.cc
CommitLineData
bbc27441 1/*
4ac4a490 2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
bbc27441
AJ
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
f7f3304a 9#include "squid.h"
95d2589c 10#include "ssl/gadgets.h"
cb4f4424 11
a594dbfa
CT
12#if HAVE_OPENSSL_X509V3_H
13#include <openssl/x509v3.h>
14#endif
95d2589c 15
95d2589c
CT
16EVP_PKEY * Ssl::createSslPrivateKey()
17{
18 Ssl::EVP_PKEY_Pointer pkey(EVP_PKEY_new());
19
20 if (!pkey)
21 return NULL;
22
2a268a06
CT
23 BIGNUM_Pointer bn(BN_new());
24 if (!bn)
25 return NULL;
26
27 if (!BN_set_word(bn.get(), RSA_F4))
28 return NULL;
29
30 Ssl::RSA_Pointer rsa(RSA_new());
31 if (!rsa)
32 return NULL;
ac756c8c 33
2a268a06
CT
34 int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable?
35 if (!RSA_generate_key_ex(rsa.get(), num, bn.get(), NULL))
36 return NULL;
95d2589c
CT
37
38 if (!rsa)
39 return NULL;
40
41 if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get())))
42 return NULL;
43
44 rsa.release();
45 return pkey.release();
46}
47
95d2589c
CT
48/**
49 \ingroup ServerProtocolSSLInternal
50 * Set serial random serial number or set random serial number.
51 */
52static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial)
53{
54 if (!ai)
55 return false;
56 Ssl::BIGNUM_Pointer bn(BN_new());
57 if (serial) {
58 bn.reset(BN_dup(serial));
59 } else {
60 if (!bn)
61 return false;
62
63 if (!BN_pseudo_rand(bn.get(), 64, 0, 0))
64 return false;
65 }
66
67 if (ai && !BN_to_ASN1_INTEGER(bn.get(), ai))
68 return false;
69 return true;
70}
71
f97700a0 72bool Ssl::writeCertAndPrivateKeyToMemory(Security::CertPointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, std::string & bufferToWrite)
95d2589c
CT
73{
74 bufferToWrite.clear();
75 if (!pkey || !cert)
76 return false;
77 BIO_Pointer bio(BIO_new(BIO_s_mem()));
78 if (!bio)
79 return false;
80
81 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
82 return false;
83
84 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
85 return false;
86
87 char *ptr = NULL;
88 long len = BIO_get_mem_data(bio.get(), &ptr);
89 if (!ptr)
90 return false;
91
92 bufferToWrite = std::string(ptr, len);
93 return true;
94}
95
f97700a0 96bool Ssl::appendCertToMemory(Security::CertPointer const & cert, std::string & bufferToWrite)
9a90aace
CT
97{
98 if (!cert)
99 return false;
100
101 BIO_Pointer bio(BIO_new(BIO_s_mem()));
102 if (!bio)
103 return false;
104
105 if (!PEM_write_bio_X509 (bio.get(), cert.get()))
106 return false;
107
108 char *ptr = NULL;
109 long len = BIO_get_mem_data(bio.get(), &ptr);
110 if (!ptr)
111 return false;
112
87f237a9 113 if (!bufferToWrite.empty())
9a90aace
CT
114 bufferToWrite.append(" "); // add a space...
115
116 bufferToWrite.append(ptr, len);
117 return true;
118}
119
f97700a0 120bool Ssl::writeCertAndPrivateKeyToFile(Security::CertPointer const & cert, Ssl::EVP_PKEY_Pointer const & pkey, char const * filename)
95d2589c
CT
121{
122 if (!pkey || !cert)
123 return false;
124
093deea9 125 Ssl::BIO_Pointer bio(BIO_new(BIO_s_file()));
95d2589c
CT
126 if (!bio)
127 return false;
128 if (!BIO_write_filename(bio.get(), const_cast<char *>(filename)))
129 return false;
130
131 if (!PEM_write_bio_X509(bio.get(), cert.get()))
132 return false;
133
134 if (!PEM_write_bio_PrivateKey(bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL))
135 return false;
136
137 return true;
138}
139
f97700a0 140bool Ssl::readCertAndPrivateKeyFromMemory(Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * bufferToRead)
95d2589c
CT
141{
142 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
143 BIO_puts(bio.get(), bufferToRead);
144
145 X509 * certPtr = NULL;
35b3559c 146 cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
95d2589c
CT
147 if (!cert)
148 return false;
149
150 EVP_PKEY * pkeyPtr = NULL;
35b3559c 151 pkey.resetWithoutLocking(PEM_read_bio_PrivateKey(bio.get(), &pkeyPtr, 0, 0));
95d2589c
CT
152 if (!pkey)
153 return false;
154
155 return true;
156}
157
f97700a0 158bool Ssl::readCertFromMemory(Security::CertPointer & cert, char const * bufferToRead)
9a90aace
CT
159{
160 Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
161 BIO_puts(bio.get(), bufferToRead);
162
163 X509 * certPtr = NULL;
35b3559c 164 cert.resetWithoutLocking(PEM_read_bio_X509(bio.get(), &certPtr, 0, 0));
9a90aace
CT
165 if (!cert)
166 return false;
167
168 return true;
169}
170
bf94620c
CT
171// According to RFC 5280 (Section A.1), the common name length in a certificate
172// can be at most 64 characters
173static const size_t MaxCnLen = 64;
174
fb2178bb 175// Replace certs common name with the given
f97700a0 176static bool replaceCommonName(Security::CertPointer & cert, std::string const &rawCn)
fb2178bb 177{
4a962df3
AR
178 std::string cn = rawCn;
179
bf94620c
CT
180 if (cn.length() > MaxCnLen) {
181 // In the case the length od CN is more than the maximum supported size
182 // try to use the first upper level domain.
183 size_t pos = 0;
184 do {
185 pos = cn.find('.', pos + 1);
87f237a9 186 } while (pos != std::string::npos && (cn.length() - pos + 2) > MaxCnLen);
bf94620c
CT
187
188 // If no short domain found or this domain is a toplevel domain
189 // we failed to find a good cn name.
190 if (pos == std::string::npos || cn.find('.', pos + 1) == std::string::npos)
191 return false;
192
4a962df3 193 std::string fixedCn(1, '*');
bf94620c 194 fixedCn.append(cn.c_str() + pos);
4a962df3 195 cn = fixedCn;
bf94620c
CT
196 }
197
4a962df3
AR
198 // Assume [] surround an IPv6 address and strip them because browsers such
199 // as Firefox, Chromium, and Safari prefer bare IPv6 addresses in CNs.
200 if (cn.length() > 2 && *cn.begin() == '[' && *cn.rbegin() == ']')
201 cn = cn.substr(1, cn.size()-2);
202
fb2178bb
CT
203 X509_NAME *name = X509_get_subject_name(cert.get());
204 if (!name)
205 return false;
206 // Remove the CN part:
207 int loc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
aebe6888
CT
208 if (loc >=0) {
209 X509_NAME_ENTRY *tmp = X509_NAME_get_entry(name, loc);
210 X509_NAME_delete_entry(name, loc);
211 X509_NAME_ENTRY_free(tmp);
212 }
fb2178bb
CT
213
214 // Add a new CN
215 return X509_NAME_add_entry_by_NID(name, NID_commonName, MBSTRING_ASC,
4a962df3 216 (unsigned char *)(cn.c_str()), -1, -1, 0);
fb2178bb
CT
217}
218
aebe6888
CT
219const char *Ssl::CertSignAlgorithmStr[] = {
220 "signTrusted",
87f237a9 221 "signUntrusted",
aebe6888
CT
222 "signSelf",
223 NULL
224};
225
fb2178bb
CT
226const char *Ssl::CertAdaptAlgorithmStr[] = {
227 "setValidAfter",
228 "setValidBefore",
229 "setCommonName",
230 NULL
231};
232
a0b971d5 233Ssl::CertificateProperties::CertificateProperties():
f53969cc
SM
234 setValidAfter(false),
235 setValidBefore(false),
236 setCommonName(false),
237 signAlgorithm(Ssl::algSignEnd),
238 signHash(NULL)
aebe6888
CT
239{}
240
06997a38
CT
241std::string & Ssl::CertificateProperties::dbKey() const
242{
243 static std::string certKey;
7fc31d31 244 certKey.clear();
06997a38
CT
245 certKey.reserve(4096);
246 if (mimicCert.get()) {
247 char buf[1024];
7fc31d31 248 certKey.append(X509_NAME_oneline(X509_get_subject_name(mimicCert.get()), buf, sizeof(buf)));
06997a38
CT
249 }
250
7fc31d31
AR
251 if (certKey.empty()) {
252 certKey.append("/CN=", 4);
253 certKey.append(commonName);
254 }
06997a38
CT
255
256 if (setValidAfter)
257 certKey.append("+SetValidAfter=on", 17);
258
259 if (setValidBefore)
260 certKey.append("+SetValidBefore=on", 18);
261
262 if (setCommonName) {
263 certKey.append("+SetCommonName=", 15);
264 certKey.append(commonName);
265 }
266
267 if (signAlgorithm != Ssl::algSignEnd) {
268 certKey.append("+Sign=", 6);
269 certKey.append(certSignAlgorithm(signAlgorithm));
270 }
271
3c26b00a
CT
272 if (signHash != NULL) {
273 certKey.append("+SignHash=", 10);
274 certKey.append(EVP_MD_name(signHash));
275 }
276
06997a38
CT
277 return certKey;
278}
279
5f1318b1
CT
280/// Check if mimicCert certificate has the Authority Key Identifier extension
281/// and if yes add the extension to cert certificate with the same fields if
5ff0af8e 282/// possible. If the issuerCert certificate does not have the Subject Key
5f1318b1
CT
283/// Identifier extension (required to build the keyIdentifier field of
284/// AuthorityKeyIdentifier) then the authorityCertIssuer and
285/// authorityCertSerialNumber fields added.
286static bool
287mimicAuthorityKeyId(Security::CertPointer &cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
288{
289 if (!mimicCert.get() || !issuerCert.get())
290 return false;
291
292 Ssl::AUTHORITY_KEYID_Pointer akid((AUTHORITY_KEYID *)X509_get_ext_d2i(mimicCert.get(), NID_authority_key_identifier, nullptr, nullptr));
293
294 bool addKeyId = false, addIssuer = false;
295 if (akid.get()) {
296 addKeyId = (akid.get()->keyid != nullptr);
297 addIssuer = (akid.get()->issuer && akid.get()->serial);
298 }
299
300 if (!addKeyId && !addIssuer)
301 return false; // No need to add AuthorityKeyIdentifier
302
303 Ssl::ASN1_OCTET_STRING_Pointer issuerKeyId;
304 if (addKeyId) {
305 X509_EXTENSION *ext;
306 // Check if the issuer has the Subject Key Identifier extension
307 const int indx = X509_get_ext_by_NID(issuerCert.get(), NID_subject_key_identifier, -1);
308 if (indx >= 0 && (ext = X509_get_ext(issuerCert.get(), indx))) {
309 issuerKeyId.reset((ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext));
310 }
311 }
312
313 Ssl::X509_NAME_Pointer issuerName;
314 Ssl::ASN1_INT_Pointer issuerSerial;
315 if (issuerKeyId.get() == nullptr || addIssuer) {
316 issuerName.reset(X509_NAME_dup(X509_get_issuer_name(issuerCert.get())));
2a268a06 317 issuerSerial.reset(ASN1_INTEGER_dup(X509_get_serialNumber(issuerCert.get())));
5f1318b1
CT
318 }
319
320 Ssl::AUTHORITY_KEYID_Pointer theAuthKeyId(AUTHORITY_KEYID_new());
321 if (!theAuthKeyId.get())
322 return false;
323 theAuthKeyId.get()->keyid = issuerKeyId.release();
324 if (issuerName && issuerSerial) {
325 Ssl::GENERAL_NAME_STACK_Pointer genNames(sk_GENERAL_NAME_new_null());
326 if (genNames.get()) {
327 if (GENERAL_NAME *aname = GENERAL_NAME_new()) {
328 sk_GENERAL_NAME_push(genNames.get(), aname);
329 aname->type = GEN_DIRNAME;
330 aname->d.dirn = issuerName.release();
331 theAuthKeyId.get()->issuer = genNames.release();
332 theAuthKeyId.get()->serial = issuerSerial.release();
333 }
334 }
335 }
336
337 // The Authority Key Identifier extension should include KeyId or/and both
338 /// issuer name and issuer serial
339 if (!theAuthKeyId.get()->keyid && (!theAuthKeyId.get()->issuer || !theAuthKeyId.get()->serial))
340 return false;
341
342 const X509V3_EXT_METHOD *method = X509V3_EXT_get_nid(NID_authority_key_identifier);
343 if (!method)
344 return false;
345
346 unsigned char *ext_der = NULL;
347 int ext_len = ASN1_item_i2d((ASN1_VALUE *)theAuthKeyId.get(), &ext_der, ASN1_ITEM_ptr(method->it));
2a268a06 348 Ssl::ASN1_OCTET_STRING_Pointer extOct(ASN1_OCTET_STRING_new());
5f1318b1
CT
349 extOct.get()->data = ext_der;
350 extOct.get()->length = ext_len;
351 Ssl::X509_EXTENSION_Pointer extAuthKeyId(X509_EXTENSION_create_by_NID(NULL, NID_authority_key_identifier, 0, extOct.get()));
352 if (!extAuthKeyId.get())
353 return false;
354
355 extOct.release();
356 if (!X509_add_ext(cert.get(), extAuthKeyId.get(), -1))
357 return false;
358
359 return true;
360}
361
5c80eab2
CT
362/// Copy certificate extensions from cert to mimicCert.
363/// Returns the number of extensions copied.
bee6354e
CT
364// Currently only extensions which are reported by the users that required are
365// mimicked. More safe to mimic extensions would be added here if users request
366// them.
5c80eab2 367static int
5f1318b1 368mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimicCert, Security::CertPointer const &issuerCert)
bee6354e
CT
369{
370 static int extensions[]= {
371 NID_key_usage,
dcc9214e 372 NID_ext_key_usage,
bee6354e
CT
373 NID_basic_constraints,
374 0
375 };
376
789bf810
CT
377 // key usage bit names
378 enum {
379 DigitalSignature,
380 NonRepudiation,
381 KeyEncipherment, // NSS requires for RSA but not EC
382 DataEncipherment,
383 KeyAgreement,
384 KeyCertificateSign,
385 CRLSign,
386 EncipherOnly,
387 DecipherOnly
388 };
389
2a268a06
CT
390#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
391 const int mimicAlgo = OBJ_obj2nid(mimicCert.get()->cert_info->key->algor->algorithm);
392 const bool rsaPkey = (mimicAlgo == NID_rsaEncryption);
393#else
394 EVP_PKEY *certKey = X509_get_pubkey(mimicCert.get());
395 const bool rsaPkey = (EVP_PKEY_get0_RSA(certKey) != NULL);
396#endif
397
5c80eab2 398 int added = 0;
bee6354e
CT
399 int nid;
400 for (int i = 0; (nid = extensions[i]) != 0; ++i) {
401 const int pos = X509_get_ext_by_NID(mimicCert.get(), nid, -1);
789bf810
CT
402 if (X509_EXTENSION *ext = X509_get_ext(mimicCert.get(), pos)) {
403 // Mimic extension exactly.
5c80eab2
CT
404 if (X509_add_ext(cert.get(), ext, -1))
405 ++added;
2a268a06 406 if (nid == NID_key_usage && !rsaPkey) {
789bf810
CT
407 // NSS does not requre the KeyEncipherment flag on EC keys
408 // but it does require it for RSA keys. Since ssl-bump
409 // substitutes RSA keys for EC ones, we need to ensure that
410 // that the more stringent requirements are met.
411
412 const int p = X509_get_ext_by_NID(cert.get(), NID_key_usage, -1);
413 if ((ext = X509_get_ext(cert.get(), p)) != NULL) {
414 ASN1_BIT_STRING *keyusage = (ASN1_BIT_STRING *)X509V3_EXT_d2i(ext);
415 ASN1_BIT_STRING_set_bit(keyusage, KeyEncipherment, 1);
e061c75e
CT
416
417 //Build the ASN1_OCTET_STRING
418 const X509V3_EXT_METHOD *method = X509V3_EXT_get(ext);
419 assert(method && method->it);
420 unsigned char *ext_der = NULL;
421 int ext_len = ASN1_item_i2d((ASN1_VALUE *)keyusage,
f53969cc 422 &ext_der,
e061c75e
CT
423 (const ASN1_ITEM *)ASN1_ITEM_ptr(method->it));
424
2a268a06 425 ASN1_OCTET_STRING *ext_oct = ASN1_OCTET_STRING_new();
e061c75e
CT
426 ext_oct->data = ext_der;
427 ext_oct->length = ext_len;
428 X509_EXTENSION_set_data(ext, ext_oct);
429
2a268a06 430 ASN1_OCTET_STRING_free(ext_oct);
789bf810
CT
431 ASN1_BIT_STRING_free(keyusage);
432 }
433 }
434 }
bee6354e
CT
435 }
436
5f1318b1
CT
437 if (mimicAuthorityKeyId(cert, mimicCert, issuerCert))
438 ++added;
439
bee6354e
CT
440 // We could also restrict mimicking of the CA extension to CA:FALSE
441 // because Squid does not generate valid fake CA certificates.
5c80eab2
CT
442
443 return added;
bee6354e
CT
444}
445
f97700a0 446static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificateProperties const &properties)
87f237a9 447{
9a90aace
CT
448 // not an Ssl::X509_NAME_Pointer because X509_REQ_get_subject_name()
449 // returns a pointer to the existing subject name. Nothing to clean here.
aebe6888 450 if (properties.mimicCert.get()) {
0d57adf9
CT
451 // Leave subject empty if we cannot extract it from true cert.
452 if (X509_NAME *name = X509_get_subject_name(properties.mimicCert.get())) {
87f237a9 453 // X509_set_subject_name will call X509_dup for name
5367d845
CT
454 X509_set_subject_name(cert.get(), name);
455 }
aebe6888
CT
456 }
457
458 if (properties.setCommonName || !properties.mimicCert.get()) {
459 // In this case the CN of the certificate given by the user
bf94620c 460 // Ignore errors: it is better to make a certificate with no CN
051da40c 461 // than to quit ssl-crtd helper because we cannot make a certificate.
bf94620c
CT
462 // Most errors are caused by user input such as huge domain names.
463 (void)replaceCommonName(cert, properties.commonName);
fb2178bb 464 }
9a90aace 465
87f237a9 466 // We should get caCert notBefore and notAfter fields and do not allow
9a90aace
CT
467 // notBefore/notAfter values from certToMimic before/after notBefore/notAfter
468 // fields from caCert.
87f237a9 469 // Currently there is not any way in openssl tollkit to compare two ASN1_TIME
9a90aace 470 // objects.
fb2178bb 471 ASN1_TIME *aTime = NULL;
aebe6888
CT
472 if (!properties.setValidBefore && properties.mimicCert.get())
473 aTime = X509_get_notBefore(properties.mimicCert.get());
474 if (!aTime && properties.signWithX509.get())
475 aTime = X509_get_notBefore(properties.signWithX509.get());
fb2178bb
CT
476
477 if (aTime) {
9a90aace
CT
478 if (!X509_set_notBefore(cert.get(), aTime))
479 return false;
87f237a9 480 } else if (!X509_gmtime_adj(X509_get_notBefore(cert.get()), (-2)*24*60*60))
9a90aace
CT
481 return false;
482
fb2178bb 483 aTime = NULL;
aebe6888
CT
484 if (!properties.setValidAfter && properties.mimicCert.get())
485 aTime = X509_get_notAfter(properties.mimicCert.get());
486 if (!aTime && properties.signWithX509.get())
487 aTime = X509_get_notAfter(properties.signWithX509.get());
fb2178bb 488 if (aTime) {
9a90aace 489 if (!X509_set_notAfter(cert.get(), aTime))
b0137cd1 490 return false;
9a90aace 491 } else if (!X509_gmtime_adj(X509_get_notAfter(cert.get()), 60*60*24*356*3))
b0137cd1 492 return false;
9a90aace 493
ad88633d 494 // mimic the alias and possibly subjectAltName
aebe6888
CT
495 if (properties.mimicCert.get()) {
496 unsigned char *alStr;
497 int alLen;
498 alStr = X509_alias_get0(properties.mimicCert.get(), &alLen);
499 if (alStr) {
500 X509_alias_set1(cert.get(), alStr, alLen);
501 }
502
5c80eab2
CT
503 int addedExtensions = 0;
504
ad88633d
AR
505 // Mimic subjectAltName unless we used a configured CN: browsers reject
506 // certificates with CN unrelated to subjectAltNames.
3b7ed55f 507 if (!properties.setCommonName) {
3b7ed55f 508 int pos=X509_get_ext_by_NID (properties.mimicCert.get(), OBJ_sn2nid("subjectAltName"), -1);
87f237a9 509 X509_EXTENSION *ext=X509_get_ext(properties.mimicCert.get(), pos);
4a874fbd 510 if (ext) {
5c80eab2
CT
511 if (X509_add_ext(cert.get(), ext, -1))
512 ++addedExtensions;
4a874fbd 513 }
3b7ed55f 514 }
bee6354e 515
5f1318b1 516 addedExtensions += mimicExtensions(cert, properties.mimicCert, properties.signWithX509);
5c80eab2
CT
517
518 // According to RFC 5280, using extensions requires v3 certificate.
519 if (addedExtensions)
520 X509_set_version(cert.get(), 2); // value 2 means v3
aebe6888 521 }
9a90aace
CT
522
523 return true;
524}
525
f97700a0 526static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties, Ssl::BIGNUM_Pointer const &serial)
9a90aace 527{
aebe6888 528 Ssl::EVP_PKEY_Pointer pkey;
95588170
CT
529 // Use signing certificates private key as generated certificate private key
530 if (properties.signWithPkey.get())
531 pkey.resetAndLock(properties.signWithPkey.get());
532 else // if not exist generate one
35b3559c 533 pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
95588170 534
9a90aace
CT
535 if (!pkey)
536 return false;
537
f97700a0 538 Security::CertPointer cert(X509_new());
9a90aace
CT
539 if (!cert)
540 return false;
541
542 // Set pub key and serial given by the caller
543 if (!X509_set_pubkey(cert.get(), pkey.get()))
544 return false;
a0b971d5 545 if (!setSerialNumber(X509_get_serialNumber(cert.get()), serial.get()))
9a90aace
CT
546 return false;
547
aebe6888
CT
548 // Fill the certificate with the required properties
549 if (!buildCertificate(cert, properties))
9a90aace
CT
550 return false;
551
aebe6888 552 int ret = 0;
9a90aace 553 // Set issuer name, from CA or our subject name for self signed cert
aebe6888
CT
554 if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithX509.get())
555 ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(properties.signWithX509.get()));
556 else // Self signed certificate, set issuer to self
557 ret = X509_set_issuer_name(cert.get(), X509_get_subject_name(cert.get()));
558 if (!ret)
9a90aace
CT
559 return false;
560
3c26b00a
CT
561 const EVP_MD *hash = properties.signHash ? properties.signHash : EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE);
562 assert(hash);
9a90aace 563 /*Now sign the request */
aebe6888 564 if (properties.signAlgorithm != Ssl::algSignSelf && properties.signWithPkey.get())
3c26b00a 565 ret = X509_sign(cert.get(), properties.signWithPkey.get(), hash);
9a90aace 566 else //else sign with self key (self signed request)
3c26b00a 567 ret = X509_sign(cert.get(), pkey.get(), hash);
9a90aace
CT
568
569 if (!ret)
570 return false;
571
35b3559c
AJ
572 certToStore = std::move(cert);
573 pkeyToStore = std::move(pkey);
9a90aace
CT
574 return true;
575}
576
4ece76b2
CT
577static BIGNUM *createCertSerial(unsigned char *md, unsigned int n)
578{
87f237a9 579
4ece76b2
CT
580 assert(n == 20); //for sha1 n is 20 (for md5 n is 16)
581
582 BIGNUM *serial = NULL;
583 serial = BN_bin2bn(md, n, NULL);
584
585 // if the serial is "0" set it to '1'
b9bb9562 586 if (BN_is_zero(serial) == true)
4ece76b2
CT
587 BN_one(serial);
588
c5bd24d6
CT
589 // serial size does not exceed 20 bytes
590 assert(BN_num_bits(serial) <= 160);
591
4ece76b2
CT
592 // According the RFC 5280, serial is an 20 bytes ASN.1 INTEGER (a signed big integer)
593 // and the maximum value for X.509 certificate serial number is 2^159-1 and
594 // the minimum 0. If the first bit of the serial is '1' ( eg 2^160-1),
595 // will result to a negative integer.
596 // To handle this, if the produced serial is greater than 2^159-1
597 // truncate the last bit
598 if (BN_is_bit_set(serial, 159))
599 BN_clear_bit(serial, 159);
600
601 return serial;
602}
603
a0b971d5
CT
604/// Return the SHA1 digest of the DER encoded version of the certificate
605/// stored in a BIGNUM
f97700a0 606static BIGNUM *x509Digest(Security::CertPointer const & cert)
a0b971d5
CT
607{
608 unsigned int n;
609 unsigned char md[EVP_MAX_MD_SIZE];
610
611 if (!X509_digest(cert.get(),EVP_sha1(),md,&n))
612 return NULL;
613
4ece76b2
CT
614 return createCertSerial(md, n);
615}
616
f97700a0 617static BIGNUM *x509Pubkeydigest(Security::CertPointer const & cert)
4ece76b2
CT
618{
619 unsigned int n;
620 unsigned char md[EVP_MAX_MD_SIZE];
621
622 if (!X509_pubkey_digest(cert.get(),EVP_sha1(),md,&n))
623 return NULL;
a0b971d5 624
4ece76b2 625 return createCertSerial(md, n);
a0b971d5
CT
626}
627
87f237a9
A
628/// Generate a unique serial number based on a Ssl::CertificateProperties object
629/// for a new generated certificate
a0b971d5
CT
630static bool createSerial(Ssl::BIGNUM_Pointer &serial, Ssl::CertificateProperties const &properties)
631{
632 Ssl::EVP_PKEY_Pointer fakePkey;
f97700a0 633 Security::CertPointer fakeCert;
a0b971d5 634
4ece76b2 635 serial.reset(x509Pubkeydigest(properties.signWithX509));
5cc307f3
CT
636 if (!serial.get()) {
637 serial.reset(BN_new());
0e62e0d6 638 BN_zero(serial.get());
5cc307f3 639 }
4ece76b2 640
a0b971d5
CT
641 if (!generateFakeSslCertificate(fakeCert, fakePkey, properties, serial))
642 return false;
643
644 // The x509Fingerprint return an SHA1 hash.
645 // both SHA1 hash and maximum serial number size are 20 bytes.
4ece76b2 646 BIGNUM *r = x509Digest(fakeCert);
a0b971d5
CT
647 if (!r)
648 return false;
649
a0b971d5
CT
650 serial.reset(r);
651 return true;
652}
653
f97700a0 654bool Ssl::generateSslCertificate(Security::CertPointer & certToStore, Ssl::EVP_PKEY_Pointer & pkeyToStore, Ssl::CertificateProperties const &properties)
a0b971d5
CT
655{
656 Ssl::BIGNUM_Pointer serial;
657
658 if (!createSerial(serial, properties))
659 return false;
660
661 return generateFakeSslCertificate(certToStore, pkeyToStore, properties, serial);
662}
663
95d2589c
CT
664/**
665 \ingroup ServerProtocolSSLInternal
666 * Read certificate from file.
667 */
668static X509 * readSslX509Certificate(char const * certFilename)
669{
670 if (!certFilename)
671 return NULL;
093deea9 672 Ssl::BIO_Pointer bio(BIO_new(BIO_s_file()));
95d2589c
CT
673 if (!bio)
674 return NULL;
675 if (!BIO_read_filename(bio.get(), certFilename))
676 return NULL;
677 X509 *certificate = PEM_read_bio_X509(bio.get(), NULL, NULL, NULL);
678 return certificate;
679}
680
780b55ee 681EVP_PKEY * Ssl::readSslPrivateKey(char const * keyFilename, pem_password_cb *passwd_callback)
95d2589c
CT
682{
683 if (!keyFilename)
684 return NULL;
093deea9 685 Ssl::BIO_Pointer bio(BIO_new(BIO_s_file()));
95d2589c
CT
686 if (!bio)
687 return NULL;
688 if (!BIO_read_filename(bio.get(), keyFilename))
689 return NULL;
780b55ee 690 EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio.get(), NULL, passwd_callback, NULL);
95d2589c
CT
691 return pkey;
692}
693
f97700a0 694void Ssl::readCertAndPrivateKeyFromFiles(Security::CertPointer & cert, Ssl::EVP_PKEY_Pointer & pkey, char const * certFilename, char const * keyFilename)
95d2589c
CT
695{
696 if (keyFilename == NULL)
697 keyFilename = certFilename;
35b3559c
AJ
698 pkey.resetWithoutLocking(readSslPrivateKey(keyFilename));
699 cert.resetWithoutLocking(readSslX509Certificate(certFilename));
95d2589c 700 if (!pkey || !cert || !X509_check_private_key(cert.get(), pkey.get())) {
58a5291c
AJ
701 pkey.reset();
702 cert.reset();
95d2589c
CT
703 }
704}
705
706bool Ssl::sslDateIsInTheFuture(char const * date)
707{
708 ASN1_UTCTIME tm;
709 tm.flags = 0;
710 tm.type = 23;
711 tm.data = (unsigned char *)date;
712 tm.length = strlen(date);
713
714 return (X509_cmp_current_time(&tm) > 0);
715}
e7bcc25f
CT
716
717/// Print the time represented by a ASN1_TIME struct to a string using GeneralizedTime format
718static bool asn1timeToGeneralizedTimeStr(ASN1_TIME *aTime, char *buf, int bufLen)
719{
87f237a9 720 // ASN1_Time holds time to UTCTime or GeneralizedTime form.
e7bcc25f
CT
721 // UTCTime has the form YYMMDDHHMMSS[Z | [+|-]offset]
722 // GeneralizedTime has the form YYYYMMDDHHMMSS[Z | [+|-] offset]
723
724 // length should have space for data plus 2 extra bytes for the two extra year fields
725 // plus the '\0' char.
726 if ((aTime->length + 3) > bufLen)
727 return false;
728
729 char *str;
730 if (aTime->type == V_ASN1_UTCTIME) {
731 if (aTime->data[0] > '5') { // RFC 2459, section 4.1.2.5.1
732 buf[0] = '1';
733 buf[1] = '9';
734 } else {
735 buf[0] = '2';
736 buf[1] = '0';
737 }
738 str = buf +2;
87f237a9 739 } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
e7bcc25f
CT
740 str = buf;
741
742 memcpy(str, aTime->data, aTime->length);
743 str[aTime->length] = '\0';
744 return true;
745}
746
747static int asn1time_cmp(ASN1_TIME *asnTime1, ASN1_TIME *asnTime2)
748{
749 char strTime1[64], strTime2[64];
750 if (!asn1timeToGeneralizedTimeStr(asnTime1, strTime1, sizeof(strTime1)))
751 return -1;
752 if (!asn1timeToGeneralizedTimeStr(asnTime2, strTime2, sizeof(strTime2)))
753 return -1;
87f237a9 754
e7bcc25f
CT
755 return strcmp(strTime1, strTime2);
756}
757
4ece76b2 758bool Ssl::certificateMatchesProperties(X509 *cert, CertificateProperties const &properties)
e7bcc25f 759{
4ece76b2
CT
760 assert(cert);
761
762 // For non self-signed certificates we have to check if the signing certificate changed
763 if (properties.signAlgorithm != Ssl::algSignSelf) {
f4e4d4d6 764 assert(properties.signWithX509.get());
4ece76b2
CT
765 if (X509_check_issued(properties.signWithX509.get(), cert) != X509_V_OK)
766 return false;
767 }
87f237a9 768
4ece76b2
CT
769 X509 *cert2 = properties.mimicCert.get();
770 // If there is not certificate to mimic stop here
771 if (!cert2)
772 return true;
773
774 if (!properties.setCommonName) {
775 X509_NAME *cert1_name = X509_get_subject_name(cert);
776 X509_NAME *cert2_name = X509_get_subject_name(cert2);
777 if (X509_NAME_cmp(cert1_name, cert2_name) != 0)
778 return false;
87f237a9
A
779 } else if (properties.commonName != CommonHostName(cert))
780 return false;
781
4ece76b2
CT
782 if (!properties.setValidBefore) {
783 ASN1_TIME *aTime = X509_get_notBefore(cert);
784 ASN1_TIME *bTime = X509_get_notBefore(cert2);
785 if (asn1time_cmp(aTime, bTime) != 0)
786 return false;
0efa4d01
CT
787 } else if (X509_cmp_current_time(X509_get_notBefore(cert)) >= 0) {
788 // notBefore does not exist (=0) or it is in the future (>0)
789 return false;
4ece76b2 790 }
e7bcc25f 791
4ece76b2
CT
792 if (!properties.setValidAfter) {
793 ASN1_TIME *aTime = X509_get_notAfter(cert);
794 ASN1_TIME *bTime = X509_get_notAfter(cert2);
795 if (asn1time_cmp(aTime, bTime) != 0)
796 return false;
0efa4d01
CT
797 } else if (X509_cmp_current_time(X509_get_notAfter(cert)) <= 0) {
798 // notAfter does not exist (0) or it is in the past (<0)
799 return false;
4ece76b2 800 }
0efa4d01 801
e7bcc25f
CT
802 char *alStr1;
803 int alLen;
4ece76b2 804 alStr1 = (char *)X509_alias_get0(cert, &alLen);
e7bcc25f
CT
805 char *alStr2 = (char *)X509_alias_get0(cert2, &alLen);
806 if ((!alStr1 && alStr2) || (alStr1 && !alStr2) ||
87f237a9 807 (alStr1 && alStr2 && strcmp(alStr1, alStr2)) != 0)
e7bcc25f 808 return false;
87f237a9 809
e7bcc25f
CT
810 // Compare subjectAltName extension
811 STACK_OF(GENERAL_NAME) * cert1_altnames;
4ece76b2 812 cert1_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
e7bcc25f
CT
813 STACK_OF(GENERAL_NAME) * cert2_altnames;
814 cert2_altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert2, NID_subject_alt_name, NULL, NULL);
815 bool match = true;
816 if (cert1_altnames) {
817 int numalts = sk_GENERAL_NAME_num(cert1_altnames);
a38ec4b1 818 for (int i = 0; match && i < numalts; ++i) {
2a268a06 819 GENERAL_NAME *aName = sk_GENERAL_NAME_value(cert1_altnames, i);
e7bcc25f
CT
820 match = sk_GENERAL_NAME_find(cert2_altnames, aName);
821 }
87f237a9 822 } else if (cert2_altnames)
e7bcc25f 823 match = false;
87f237a9 824
e7bcc25f
CT
825 sk_GENERAL_NAME_pop_free(cert1_altnames, GENERAL_NAME_free);
826 sk_GENERAL_NAME_pop_free(cert2_altnames, GENERAL_NAME_free);
827
828 return match;
829}
0efa4d01
CT
830
831static const char *getSubjectEntry(X509 *x509, int nid)
832{
833 static char name[1024] = ""; // stores common name (CN)
834
835 if (!x509)
836 return NULL;
837
838 // TODO: What if the entry is a UTF8String? See X509_NAME_get_index_by_NID(3ssl).
839 const int nameLen = X509_NAME_get_text_by_NID(
87f237a9
A
840 X509_get_subject_name(x509),
841 nid, name, sizeof(name));
0efa4d01
CT
842
843 if (nameLen > 0)
844 return name;
845
846 return NULL;
847}
848
849const char *Ssl::CommonHostName(X509 *x509)
850{
851 return getSubjectEntry(x509, NID_commonName);
852}
853
854const char *Ssl::getOrganization(X509 *x509)
855{
856 return getSubjectEntry(x509, NID_organizationName);
857}
858