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