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