2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
10 #include "ssl/gadgets.h"
12 #if HAVE_OPENSSL_X509V3_H
13 #include <openssl/x509v3.h>
16 EVP_PKEY
* Ssl::createSslPrivateKey()
18 Ssl::EVP_PKEY_Pointer
pkey(EVP_PKEY_new());
23 Ssl::RSA_Pointer
rsa(RSA_generate_key(1024, RSA_F4
, NULL
, NULL
));
28 if (!EVP_PKEY_assign_RSA(pkey
.get(), (rsa
.get())))
32 return pkey
.release();
36 \ingroup ServerProtocolSSLInternal
37 * Set serial random serial number or set random serial number.
39 static bool setSerialNumber(ASN1_INTEGER
*ai
, BIGNUM
const* serial
)
43 Ssl::BIGNUM_Pointer
bn(BN_new());
45 bn
.reset(BN_dup(serial
));
50 if (!BN_pseudo_rand(bn
.get(), 64, 0, 0))
54 if (ai
&& !BN_to_ASN1_INTEGER(bn
.get(), ai
))
59 bool Ssl::writeCertAndPrivateKeyToMemory(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, std::string
& bufferToWrite
)
61 bufferToWrite
.clear();
64 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
68 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
71 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
75 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
79 bufferToWrite
= std::string(ptr
, len
);
83 bool Ssl::appendCertToMemory(Ssl::X509_Pointer
const & cert
, std::string
& bufferToWrite
)
88 BIO_Pointer
bio(BIO_new(BIO_s_mem()));
92 if (!PEM_write_bio_X509 (bio
.get(), cert
.get()))
96 long len
= BIO_get_mem_data(bio
.get(), &ptr
);
100 if (!bufferToWrite
.empty())
101 bufferToWrite
.append(" "); // add a space...
103 bufferToWrite
.append(ptr
, len
);
107 bool Ssl::writeCertAndPrivateKeyToFile(Ssl::X509_Pointer
const & cert
, Ssl::EVP_PKEY_Pointer
const & pkey
, char const * filename
)
112 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
115 if (!BIO_write_filename(bio
.get(), const_cast<char *>(filename
)))
118 if (!PEM_write_bio_X509(bio
.get(), cert
.get()))
121 if (!PEM_write_bio_PrivateKey(bio
.get(), pkey
.get(), NULL
, NULL
, 0, NULL
, NULL
))
127 bool Ssl::readCertAndPrivateKeyFromMemory(Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * bufferToRead
)
129 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
130 BIO_puts(bio
.get(), bufferToRead
);
132 X509
* certPtr
= NULL
;
133 cert
.reset(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
137 EVP_PKEY
* pkeyPtr
= NULL
;
138 pkey
.reset(PEM_read_bio_PrivateKey(bio
.get(), &pkeyPtr
, 0, 0));
145 bool Ssl::readCertFromMemory(X509_Pointer
& cert
, char const * bufferToRead
)
147 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_mem()));
148 BIO_puts(bio
.get(), bufferToRead
);
150 X509
* certPtr
= NULL
;
151 cert
.reset(PEM_read_bio_X509(bio
.get(), &certPtr
, 0, 0));
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;
162 // Replace certs common name with the given
163 static bool replaceCommonName(Ssl::X509_Pointer
& cert
, std::string
const &rawCn
)
165 std::string cn
= rawCn
;
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.
172 pos
= cn
.find('.', pos
+ 1);
173 } while (pos
!= std::string::npos
&& (cn
.length() - pos
+ 2) > MaxCnLen
);
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
)
180 std::string
fixedCn(1, '*');
181 fixedCn
.append(cn
.c_str() + pos
);
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);
190 X509_NAME
*name
= X509_get_subject_name(cert
.get());
193 // Remove the CN part:
194 int loc
= X509_NAME_get_index_by_NID(name
, NID_commonName
, -1);
196 X509_NAME_ENTRY
*tmp
= X509_NAME_get_entry(name
, loc
);
197 X509_NAME_delete_entry(name
, loc
);
198 X509_NAME_ENTRY_free(tmp
);
202 return X509_NAME_add_entry_by_NID(name
, NID_commonName
, MBSTRING_ASC
,
203 (unsigned char *)(cn
.c_str()), -1, -1, 0);
206 const char *Ssl::CertSignAlgorithmStr
[] = {
213 const char *Ssl::CertAdaptAlgorithmStr
[] = {
220 Ssl::CertificateProperties::CertificateProperties():
221 setValidAfter(false),
222 setValidBefore(false),
223 setCommonName(false),
224 signAlgorithm(Ssl::algSignEnd
),
228 std::string
& Ssl::CertificateProperties::dbKey() const
230 static std::string certKey
;
232 certKey
.reserve(4096);
233 if (mimicCert
.get()) {
235 certKey
.append(X509_NAME_oneline(X509_get_subject_name(mimicCert
.get()), buf
, sizeof(buf
)));
238 if (certKey
.empty()) {
239 certKey
.append("/CN=", 4);
240 certKey
.append(commonName
);
244 certKey
.append("+SetValidAfter=on", 17);
247 certKey
.append("+SetValidBefore=on", 18);
250 certKey
.append("+SetCommonName=", 15);
251 certKey
.append(commonName
);
254 if (signAlgorithm
!= Ssl::algSignEnd
) {
255 certKey
.append("+Sign=", 6);
256 certKey
.append(certSignAlgorithm(signAlgorithm
));
259 if (signHash
!= NULL
) {
260 certKey
.append("+SignHash=", 10);
261 certKey
.append(EVP_MD_name(signHash
));
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
273 mimicExtensions(Ssl::X509_Pointer
& cert
, Ssl::X509_Pointer
const & mimicCert
)
275 static int extensions
[]= {
278 NID_basic_constraints
,
282 // key usage bit names
286 KeyEncipherment
, // NSS requires for RSA but not EC
295 int mimicAlgo
= OBJ_obj2nid(mimicCert
.get()->cert_info
->key
->algor
->algorithm
);
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))
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.
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);
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
,
322 (const ASN1_ITEM
*)ASN1_ITEM_ptr(method
->it
));
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
);
329 M_ASN1_OCTET_STRING_free(ext_oct
);
330 ASN1_BIT_STRING_free(keyusage
);
336 // We could also restrict mimicking of the CA extension to CA:FALSE
337 // because Squid does not generate valid fake CA certificates.
342 static bool buildCertificate(Ssl::X509_Pointer
& cert
, Ssl::CertificateProperties
const &properties
)
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
);
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
);
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
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());
374 if (!X509_set_notBefore(cert
.get(), aTime
))
376 } else if (!X509_gmtime_adj(X509_get_notBefore(cert
.get()), (-2)*24*60*60))
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());
385 if (!X509_set_notAfter(cert
.get(), aTime
))
387 } else if (!X509_gmtime_adj(X509_get_notAfter(cert
.get()), 60*60*24*356*3))
390 // mimic the alias and possibly subjectAltName
391 if (properties
.mimicCert
.get()) {
392 unsigned char *alStr
;
394 alStr
= X509_alias_get0(properties
.mimicCert
.get(), &alLen
);
396 X509_alias_set1(cert
.get(), alStr
, alLen
);
399 int addedExtensions
= 0;
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
);
407 if (X509_add_ext(cert
.get(), ext
, -1))
412 addedExtensions
+= mimicExtensions(cert
, properties
.mimicCert
);
414 // According to RFC 5280, using extensions requires v3 certificate.
416 X509_set_version(cert
.get(), 2); // value 2 means v3
422 static bool generateFakeSslCertificate(Ssl::X509_Pointer
& certToStore
, Ssl::EVP_PKEY_Pointer
& pkeyToStore
, Ssl::CertificateProperties
const &properties
, Ssl::BIGNUM_Pointer
const &serial
)
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());
434 Ssl::X509_Pointer
cert(X509_new());
438 // Set pub key and serial given by the caller
439 if (!X509_set_pubkey(cert
.get(), pkey
.get()))
441 if (!setSerialNumber(X509_get_serialNumber(cert
.get()), serial
.get()))
444 // Fill the certificate with the required properties
445 if (!buildCertificate(cert
, properties
))
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()));
457 const EVP_MD
*hash
= properties
.signHash
? properties
.signHash
: EVP_get_digestbyname(SQUID_SSL_SIGN_HASH_IF_NONE
);
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
);
468 certToStore
.reset(cert
.release());
469 pkeyToStore
.reset(pkey
.release());
473 static BIGNUM
*createCertSerial(unsigned char *md
, unsigned int n
)
476 assert(n
== 20); //for sha1 n is 20 (for md5 n is 16)
478 BIGNUM
*serial
= NULL
;
479 serial
= BN_bin2bn(md
, n
, NULL
);
481 // if the serial is "0" set it to '1'
482 if (BN_is_zero(serial
) == true)
485 // serial size does not exceed 20 bytes
486 assert(BN_num_bits(serial
) <= 160);
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);
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
)
505 unsigned char md
[EVP_MAX_MD_SIZE
];
507 if (!X509_digest(cert
.get(),EVP_sha1(),md
,&n
))
510 return createCertSerial(md
, n
);
513 static BIGNUM
*x509Pubkeydigest(Ssl::X509_Pointer
const & cert
)
516 unsigned char md
[EVP_MAX_MD_SIZE
];
518 if (!X509_pubkey_digest(cert
.get(),EVP_sha1(),md
,&n
))
521 return createCertSerial(md
, n
);
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
)
528 Ssl::EVP_PKEY_Pointer fakePkey
;
529 Ssl::X509_Pointer fakeCert
;
531 serial
.reset(x509Pubkeydigest(properties
.signWithX509
));
533 serial
.reset(BN_new());
534 BN_zero(serial
.get());
537 if (!generateFakeSslCertificate(fakeCert
, fakePkey
, properties
, serial
))
540 // The x509Fingerprint return an SHA1 hash.
541 // both SHA1 hash and maximum serial number size are 20 bytes.
542 BIGNUM
*r
= x509Digest(fakeCert
);
550 bool Ssl::generateSslCertificate(Ssl::X509_Pointer
& certToStore
, Ssl::EVP_PKEY_Pointer
& pkeyToStore
, Ssl::CertificateProperties
const &properties
)
552 Ssl::BIGNUM_Pointer serial
;
554 if (!createSerial(serial
, properties
))
557 return generateFakeSslCertificate(certToStore
, pkeyToStore
, properties
, serial
);
561 \ingroup ServerProtocolSSLInternal
562 * Read certificate from file.
564 static X509
* readSslX509Certificate(char const * certFilename
)
568 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
571 if (!BIO_read_filename(bio
.get(), certFilename
))
573 X509
*certificate
= PEM_read_bio_X509(bio
.get(), NULL
, NULL
, NULL
);
577 EVP_PKEY
* Ssl::readSslPrivateKey(char const * keyFilename
, pem_password_cb
*passwd_callback
)
581 Ssl::BIO_Pointer
bio(BIO_new(BIO_s_file_internal()));
584 if (!BIO_read_filename(bio
.get(), keyFilename
))
586 EVP_PKEY
*pkey
= PEM_read_bio_PrivateKey(bio
.get(), NULL
, passwd_callback
, NULL
);
590 void Ssl::readCertAndPrivateKeyFromFiles(Ssl::X509_Pointer
& cert
, Ssl::EVP_PKEY_Pointer
& pkey
, char const * certFilename
, char const * keyFilename
)
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())) {
602 bool Ssl::sslDateIsInTheFuture(char const * date
)
607 tm
.data
= (unsigned char *)date
;
608 tm
.length
= strlen(date
);
610 return (X509_cmp_current_time(&tm
) > 0);
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
)
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]
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
)
626 if (aTime
->type
== V_ASN1_UTCTIME
) {
627 if (aTime
->data
[0] > '5') { // RFC 2459, section 4.1.2.5.1
635 } else // if (aTime->type == V_ASN1_GENERALIZEDTIME)
638 memcpy(str
, aTime
->data
, aTime
->length
);
639 str
[aTime
->length
] = '\0';
643 static int asn1time_cmp(ASN1_TIME
*asnTime1
, ASN1_TIME
*asnTime2
)
645 char strTime1
[64], strTime2
[64];
646 if (!asn1timeToGeneralizedTimeStr(asnTime1
, strTime1
, sizeof(strTime1
)))
648 if (!asn1timeToGeneralizedTimeStr(asnTime2
, strTime2
, sizeof(strTime2
)))
651 return strcmp(strTime1
, strTime2
);
654 bool Ssl::certificateMatchesProperties(X509
*cert
, CertificateProperties
const &properties
)
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
)
665 X509
*cert2
= properties
.mimicCert
.get();
666 // If there is not certificate to mimic stop here
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)
675 } else if (properties
.commonName
!= CommonHostName(cert
))
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)
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)
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)
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)
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)
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
);
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
);
718 } else if (cert2_altnames
)
721 sk_GENERAL_NAME_pop_free(cert1_altnames
, GENERAL_NAME_free
);
722 sk_GENERAL_NAME_pop_free(cert2_altnames
, GENERAL_NAME_free
);
727 static const char *getSubjectEntry(X509
*x509
, int nid
)
729 static char name
[1024] = ""; // stores common name (CN)
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
));
745 const char *Ssl::CommonHostName(X509
*x509
)
747 return getSubjectEntry(x509
, NID_commonName
);
750 const char *Ssl::getOrganization(X509
*x509
)
752 return getSubjectEntry(x509
, NID_organizationName
);