summaryrefslogtreecommitdiff
path: root/indra/newview/llsechandler_basic.cpp
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2017-04-14 16:05:59 -0400
committerOz Linden <oz@lindenlab.com>2017-04-14 16:05:59 -0400
commitfd3628ef45a8160f2434e0d8b747d31d65685340 (patch)
tree2f96fb0bde4f6e1163cadd7fb55698de8756ad32 /indra/newview/llsechandler_basic.cpp
parent3494eb79529f5fb754e0ae75de96b18c0dafd981 (diff)
Change certificate store infrastructure to key off of the Subject Key
Id rather than sha1 hash, since that is rarely used in modern certs. The previous form was storing trusted certs using an empty sha1 hash value as the key, which meant most certificates matched... not good. Modify the LLCertException to pass certificate information back as LLSD rather than an LLPointer<LLCertificate>, because when the exception is being thown from the certificate constructor that results in one of a couple of other exceptions (even refcounting won't save you when the problem is that the thing you're pointing to never finished coming into being properly). Update the certificates in the llsechandler_basic_test to modern conventions, and extend the classes to allow for an optional validation date so that the test can use a fixed date. Also make all the certificates include the plain text form for ease of reference.
Diffstat (limited to 'indra/newview/llsechandler_basic.cpp')
-rw-r--r--indra/newview/llsechandler_basic.cpp273
1 files changed, 153 insertions, 120 deletions
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index bf7faff13a..ffb9aa1585 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -62,37 +62,45 @@ std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value);
LLSD _basic_constraints_ext(X509* cert);
LLSD _key_usage_ext(X509* cert);
LLSD _ext_key_usage_ext(X509* cert);
-LLSD _subject_key_identifier_ext(X509 *cert);
-LLSD _authority_key_identifier_ext(X509* cert);
+std::string _subject_key_identifier(X509 *cert);
+LLSD _authority_key_identifier(X509* cert);
+void _validateCert(int validation_policy,
+ LLPointer<LLCertificate> cert,
+ const LLSD& validation_params,
+ int depth);
-LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)
+LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert,
+ const LLSD* validation_params)
{
-
// BIO_new_mem_buf returns a read only bio, but takes a void* which isn't const
// so we need to cast it.
BIO * pem_bio = BIO_new_mem_buf((void*)pem_cert.c_str(), pem_cert.length());
if(pem_bio == NULL)
{
LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL;
- LLTHROW(LLInvalidCertificate(this));
+ LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
}
mCert = NULL;
PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);
BIO_free(pem_bio);
if (!mCert)
{
- LLTHROW(LLInvalidCertificate(this));
+ LL_WARNS("SECAPI") << "Could not decode certificate to x509." << LL_ENDL;
+ LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
}
}
-LLBasicCertificate::LLBasicCertificate(X509* pCert)
+LLBasicCertificate::LLBasicCertificate(X509* pCert,
+ const LLSD* validation_params)
{
if (!pCert || !pCert->cert_info)
{
- LLTHROW(LLInvalidCertificate(this));
+ LLTHROW(LLInvalidCertificate(LLSD::emptyMap()));
}
mCert = X509_dup(pCert);
+ // it is tempting to run _validateCert here, but doing so causes problems
+ // the trick is figuring out which aspects to validate. TBD
}
LLBasicCertificate::~LLBasicCertificate()
@@ -100,6 +108,7 @@ LLBasicCertificate::~LLBasicCertificate()
if(mCert)
{
X509_free(mCert);
+ mCert = NULL;
}
}
@@ -172,14 +181,12 @@ LLSD& LLBasicCertificate::_initLLSD()
mLLSDInfo[CERT_VALID_TO] = cert_date_from_asn1_time(X509_get_notAfter(mCert));
mLLSDInfo[CERT_VALID_FROM] = cert_date_from_asn1_time(X509_get_notBefore(mCert));
- mLLSDInfo[CERT_SHA1_DIGEST] = cert_get_digest("sha1", mCert);
- mLLSDInfo[CERT_MD5_DIGEST] = cert_get_digest("md5", mCert);
// add the known extensions
mLLSDInfo[CERT_BASIC_CONSTRAINTS] = _basic_constraints_ext(mCert);
mLLSDInfo[CERT_KEY_USAGE] = _key_usage_ext(mCert);
mLLSDInfo[CERT_EXTENDED_KEY_USAGE] = _ext_key_usage_ext(mCert);
- mLLSDInfo[CERT_SUBJECT_KEY_IDENTFIER] = _subject_key_identifier_ext(mCert);
- mLLSDInfo[CERT_AUTHORITY_KEY_IDENTIFIER] = _authority_key_identifier_ext(mCert);
+ mLLSDInfo[CERT_SUBJECT_KEY_IDENTFIER] = _subject_key_identifier(mCert);
+ mLLSDInfo[CERT_AUTHORITY_KEY_IDENTIFIER] = _authority_key_identifier(mCert);
return mLLSDInfo;
}
@@ -278,21 +285,20 @@ LLSD _ext_key_usage_ext(X509* cert)
}
// retrieve the subject key identifier of the cert
-LLSD _subject_key_identifier_ext(X509 *cert)
+std::string _subject_key_identifier(X509 *cert)
{
- LLSD result;
+ std::string result;
ASN1_OCTET_STRING *skeyid = (ASN1_OCTET_STRING *)X509_get_ext_d2i(cert, NID_subject_key_identifier, NULL, NULL);
if(skeyid)
{
result = cert_string_from_octet_string(skeyid);
-
ASN1_OCTET_STRING_free( skeyid );
}
return result;
}
// retrieve the authority key identifier of the cert
-LLSD _authority_key_identifier_ext(X509* cert)
+LLSD _authority_key_identifier(X509* cert)
{
LLSD result;
AUTHORITY_KEYID *akeyid = (AUTHORITY_KEYID *)X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
@@ -308,14 +314,10 @@ LLSD _authority_key_identifier_ext(X509* cert)
result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial);
}
-
AUTHORITY_KEYID_free( akeyid );
}
-
// we ignore the issuer name in the authority key identifier, we check the issue name via
// the the issuer name entry in the cert.
-
-
return result;
}
@@ -466,44 +468,6 @@ LLDate cert_date_from_asn1_time(ASN1_TIME* asn1_time)
#endif // LL_WINDOWS
}
-
-// Generate a string containing a digest. The digest time is 'ssh1' or
-// 'md5', and the resulting string is of the form "aa:12:5c:' and so on
-std::string cert_get_digest(const std::string& digest_type, X509 *cert)
-{
- unsigned char digest_data[BUFFER_READ_SIZE];
- unsigned int len = sizeof(digest_data);
- std::stringstream result;
- const EVP_MD* digest = NULL;
- // we could use EVP_get_digestbyname, but that requires initializer code which
- // would require us to complicate things by plumbing it into the system.
- if (digest_type == "md5")
- {
- digest = EVP_md5();
- }
- else if (digest_type == "sha1")
- {
- digest = EVP_sha1();
- }
- else
- {
- return std::string();
- }
-
- X509_digest(cert, digest, digest_data, &len);
- result << std::hex << std::setprecision(2);
- for (unsigned int i=0; i < len; i++)
- {
- if (i != 0)
- {
- result << ":";
- }
- result << std::setfill('0') << std::setw(2) << (int)digest_data[i];
- }
- return result.str();
-}
-
-
// class LLBasicCertificateVector
// This class represents a list of certificates, implemented by a vector of certificate pointers.
// it contains implementations of the virtual functions for iterators, search, add, remove, etc.
@@ -513,38 +477,33 @@ std::string cert_get_digest(const std::string& digest_type, X509 *cert)
// It will find a cert that has minimally the params listed, with the values being the same
LLBasicCertificateVector::iterator LLBasicCertificateVector::find(const LLSD& params)
{
- BOOL found = FALSE;
// loop through the entire vector comparing the values in the certs
// against those passed in via the params.
// params should be a map. Only the items specified in the map will be
// checked, but they must match exactly, even if they're maps or arrays.
-
- for(iterator cert = begin();
- cert != end();
- cert++)
+ bool found = false;
+ iterator cert = begin();
+ while ( !found && cert != end() )
{
-
- found= TRUE;
+ found = true;
LLSD cert_info;
(*cert)->getLLSD(cert_info);
- for (LLSD::map_const_iterator param = params.beginMap();
- param != params.endMap();
+ for (LLSD::map_const_iterator param = params.beginMap();
+ found && param != params.endMap();
param++)
{
-
- if (!cert_info.has((std::string)param->first) ||
- (!valueCompareLLSD(cert_info[(std::string)param->first], param->second)))
+ if ( !cert_info.has((std::string)param->first)
+ || !valueCompareLLSD(cert_info[(std::string)param->first], param->second))
{
- found = FALSE;
- break;
+ found = false;
}
}
- if (found)
- {
- return (cert);
- }
+ if (!found)
+ {
+ cert++;
+ }
}
- return end();
+ return cert;
}
// Insert a certificate into the store. If the certificate already
@@ -554,20 +513,37 @@ void LLBasicCertificateVector::insert(iterator _iter,
{
LLSD cert_info;
cert->getLLSD(cert_info);
- if (cert_info.isMap() && cert_info.has(CERT_SHA1_DIGEST))
+ if (cert_info.isMap() && cert_info.has(CERT_SUBJECT_KEY_IDENTFIER))
{
LLSD existing_cert_info = LLSD::emptyMap();
- existing_cert_info[CERT_MD5_DIGEST] = cert_info[CERT_MD5_DIGEST];
+ existing_cert_info[CERT_SUBJECT_KEY_IDENTFIER] = cert_info[CERT_SUBJECT_KEY_IDENTFIER];
if(find(existing_cert_info) == end())
{
BasicIteratorImpl *basic_iter = dynamic_cast<BasicIteratorImpl*>(_iter.mImpl.get());
- llassert(basic_iter);
if (basic_iter)
{
mCerts.insert(basic_iter->mIter, cert);
}
+ else
+ {
+ LL_WARNS("SECAPI") << "Invalid certificate postion vector"
+ << LL_ENDL;
+ }
}
+ else
+ {
+ LL_DEBUGS("SECAPI") << "Certificate already in vector: "
+ << "'" << cert_info << "'"
+ << LL_ENDL;
+ }
+
}
+ else
+ {
+ LL_WARNS("SECAPI") << "Certificate does not have Subject Key Identifier; not inserted: "
+ << "'" << cert_info << "'"
+ << LL_ENDL;
+ }
}
// remove a certificate from the store
@@ -613,12 +589,28 @@ void LLBasicCertificateStore::load_from_file(const std::string& filename)
{
try
{
- add(new LLBasicCertificate(cert_x509));
+ LLPointer<LLBasicCertificate> new_cert(new LLBasicCertificate(cert_x509));
+ LLSD validation_params;
+ _validateCert(VALIDATION_POLICY_TIME,
+ new_cert,
+ validation_params,
+ 0);
+ add(new_cert);
+ LL_DEBUGS("SECAPI") << "Loaded valid cert for "
+ << "Name '" << cert_string_name_from_X509_NAME(X509_get_subject_name(cert_x509)) << "'";
+ std::string skeyid(_subject_key_identifier(cert_x509));
+ LL_CONT << " Id '" << skeyid << "'"
+ << LL_ENDL;
loaded++;
}
+ catch (LLCertException& cert_exception)
+ {
+ LLSD cert_info(cert_exception.getCertData());
+ LL_WARNS("SECAPI") << "invalid certificate (" << cert_exception.what() << "): " << cert_info << LL_ENDL;
+ }
catch (...)
{
- LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");
+ LOG_UNHANDLED_EXCEPTION("creating certificate from the certificate store file");
}
X509_free(cert_x509);
cert_x509 = NULL;
@@ -880,33 +872,31 @@ void _validateCert(int validation_policy,
const LLSD& validation_params,
int depth)
{
-
LLSD current_cert_info;
cert->getLLSD(current_cert_info);
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))
{
- LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));
+ LLTHROW(LLCertException(current_cert_info, "Cert doesn't have a Subject Name"));
}
if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))
{
- LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));
+ LLTHROW(LLCertException(current_cert_info, "Cert doesn't have an Issuer Name"));
}
// check basic properties exist in the cert
if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))
{
- LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));
+ LLTHROW(LLCertException(current_cert_info, "Cert doesn't have an expiration period"));
}
- if (!current_cert_info.has(CERT_SHA1_DIGEST))
+ if (!current_cert_info.has(CERT_SUBJECT_KEY_IDENTFIER))
{
- LLTHROW(LLCertException(cert, "No SHA1 digest"));
+ LLTHROW(LLCertException(current_cert_info, "Cert doesn't have a Subject Key Id"));
}
if (validation_policy & VALIDATION_POLICY_TIME)
{
-
LLDate validation_date(time(NULL));
if(validation_params.has(CERT_VALIDATION_DATE))
{
@@ -916,7 +906,7 @@ void _validateCert(int validation_policy,
if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||
(validation_date > current_cert_info[CERT_VALID_TO].asDate()))
{
- LLTHROW(LLCertValidationExpirationException(cert, validation_date));
+ LLTHROW(LLCertValidationExpirationException(current_cert_info, validation_date));
}
}
if (validation_policy & VALIDATION_POLICY_SSL_KU)
@@ -927,14 +917,14 @@ void _validateCert(int validation_policy,
!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))
{
- LLTHROW(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(current_cert_info));
}
// only validate EKU if the cert has it
if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&
(!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],
LLSD((std::string)CERT_EKU_SERVER_AUTH))))
{
- LLTHROW(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(current_cert_info));
}
}
if (validation_policy & VALIDATION_POLICY_CA_KU)
@@ -943,7 +933,7 @@ void _validateCert(int validation_policy,
(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],
(std::string)CERT_KU_CERT_SIGN)))
{
- LLTHROW(LLCertKeyUsageValidationException(cert));
+ LLTHROW(LLCertKeyUsageValidationException(current_cert_info));
}
}
@@ -955,13 +945,13 @@ void _validateCert(int validation_policy,
if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||
!current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])
{
- LLTHROW(LLCertBasicConstraintsValidationException(cert));
+ LLTHROW(LLCertBasicConstraintsValidationException(current_cert_info));
}
if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&
((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&
(depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))
{
- LLTHROW(LLCertBasicConstraintsValidationException(cert));
+ LLTHROW(LLCertBasicConstraintsValidationException(current_cert_info));
}
}
}
@@ -1035,26 +1025,28 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(cert_chain->size() < 1)
{
- LLTHROW(LLCertException(NULL, "No certs in chain"));
+ LLTHROW(LLCertException(LLSD::emptyMap(), "No certs in chain"));
}
iterator current_cert = cert_chain->begin();
- LLSD current_cert_info;
LLSD validation_date;
if (validation_params.has(CERT_VALIDATION_DATE))
{
validation_date = validation_params[CERT_VALIDATION_DATE];
}
+ // get LLSD info from the cert to throw in any exception
+ LLSD current_cert_info;
+ (*current_cert)->getLLSD(current_cert_info);
+
if (validation_policy & VALIDATION_POLICY_HOSTNAME)
{
- (*current_cert)->getLLSD(current_cert_info);
if(!validation_params.has(CERT_HOSTNAME))
{
- LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));
+ LLTHROW(LLCertException(current_cert_info, "No hostname passed in for validation"));
}
if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))
{
- LLTHROW(LLInvalidCertificate((*current_cert)));
+ LLTHROW(LLInvalidCertificate(current_cert_info));
}
LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<
@@ -1063,39 +1055,60 @@ void LLBasicCertificateStore::validate(int validation_policy,
current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString()))
{
throw LLCertValidationHostnameException(validation_params[CERT_HOSTNAME].asString(),
- (*current_cert));
+ current_cert_info);
}
}
-
+
// check the cache of already validated certs
X509* cert_x509 = (*current_cert)->getOpenSSLX509();
if(!cert_x509)
{
- LLTHROW(LLInvalidCertificate((*current_cert)));
+ LLTHROW(LLInvalidCertificate(current_cert_info));
}
- std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);
+
+ std::string subject_name(cert_string_name_from_X509_NAME(X509_get_subject_name(cert_x509)));
+ std::string skeyid(_subject_key_identifier(cert_x509));
+
+ LL_DEBUGS("SECAPI") << "attempting to validate cert "
+ << " for '" << (validation_params.has(CERT_HOSTNAME) ? validation_params[CERT_HOSTNAME].asString() : "(unknown hostname)") << "'"
+ << " as subject name '" << subject_name << "'"
+ << " subject key id '" << skeyid << "'"
+ << LL_ENDL;
+
X509_free( cert_x509 );
cert_x509 = NULL;
- t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash);
+ if (skeyid.empty())
+ {
+ LLTHROW(LLCertException(current_cert_info, "No Subject Key Id"));
+ }
+
+ t_cert_cache::iterator cache_entry = mTrustedCertCache.find(skeyid);
if(cache_entry != mTrustedCertCache.end())
{
// this cert is in the cache, so validate the time.
if (validation_policy & VALIDATION_POLICY_TIME)
{
- LLDate validation_date(time(NULL));
+ LLDate validation_date;
if(validation_params.has(CERT_VALIDATION_DATE))
{
validation_date = validation_params[CERT_VALIDATION_DATE];
}
+ else
+ {
+ validation_date = LLDate(time(NULL)); // current time
+ }
if((validation_date < cache_entry->second.first) ||
(validation_date > cache_entry->second.second))
{
- LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));
+ LLTHROW(LLCertValidationExpirationException(current_cert_info, validation_date));
}
}
// successfully found in cache
- LL_DEBUGS("SECAPI") << "Valid cert for " << validation_params[CERT_HOSTNAME].asString() << " found in cache" << LL_ENDL;
+ LL_DEBUGS("SECAPI") << "Valid cert for '" << validation_params[CERT_HOSTNAME].asString() << "'"
+ << " skeyid '" << skeyid << "'"
+ << " found in cache"
+ << LL_ENDL;
return;
}
if(current_cert_info.isUndefined())
@@ -1109,7 +1122,6 @@ void LLBasicCertificateStore::validate(int validation_policy,
// loop through the cert chain, validating the current cert against the next one.
while(current_cert != cert_chain->end())
{
-
int local_validation_policy = validation_policy;
if(current_cert == cert_chain->begin())
{
@@ -1124,7 +1136,9 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*current_cert),
previous_cert))
{
- LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));
+ LLSD previous_cert_info;
+ previous_cert->getLLSD(previous_cert_info);
+ LLTHROW(LLCertValidationInvalidSignatureException(previous_cert_info));
}
}
_validateCert(local_validation_policy,
@@ -1135,12 +1149,20 @@ void LLBasicCertificateStore::validate(int validation_policy,
// look for a CA in the CA store that may belong to this chain.
LLSD cert_search_params = LLSD::emptyMap();
// is the cert itself in the store?
- cert_search_params[CERT_SHA1_DIGEST] = current_cert_info[CERT_SHA1_DIGEST];
+ cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = current_cert_info[CERT_SUBJECT_KEY_IDENTFIER];
LLCertificateStore::iterator found_store_cert = find(cert_search_params);
if(found_store_cert != end())
{
- mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
- LL_DEBUGS("SECAPI") << "Valid cert for " << validation_params[CERT_HOSTNAME].asString() << " found in cert store" << LL_ENDL;
+ mTrustedCertCache[skeyid] = std::pair<LLDate, LLDate>(from_time, to_time);
+ LL_DEBUGS("SECAPI") << "Valid cert "
+ << " for '" << (validation_params.has(CERT_HOSTNAME) ? validation_params[CERT_HOSTNAME].asString() : "(unknown hostname)") << "'";
+ X509* cert_x509 = (*found_store_cert)->getOpenSSLX509();
+ std::string found_cert_subject_name(cert_string_name_from_X509_NAME(X509_get_subject_name(cert_x509)));
+ X509_free(cert_x509);
+ LL_CONT << " as '" << found_cert_subject_name << "'"
+ << " skeyid '" << current_cert_info[CERT_SUBJECT_KEY_IDENTFIER].asString() << "'"
+ << " found in cert store"
+ << LL_ENDL;
return;
}
@@ -1174,11 +1196,16 @@ void LLBasicCertificateStore::validate(int validation_policy,
if(!_verify_signature((*found_store_cert),
(*current_cert)))
{
- LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));
+ LLTHROW(LLCertValidationInvalidSignatureException(current_cert_info));
}
// successfully validated.
- mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
- LL_DEBUGS("SECAPI") << "Valid CA cert for " << validation_params[CERT_HOSTNAME].asString() << " found in cert store" << LL_ENDL;
+ mTrustedCertCache[skeyid] = std::pair<LLDate, LLDate>(from_time, to_time);
+ LL_DEBUGS("SECAPI") << "Verified and cached cert for '" << validation_params[CERT_HOSTNAME].asString() << "'"
+ << " as '" << subject_name << "'"
+ << " id '" << skeyid << "'"
+ << " using CA '" << cert_search_params[CERT_SUBJECT_NAME_STRING] << "'"
+ << " with id '" << cert_search_params[CERT_SUBJECT_KEY_IDENTFIER].asString() << "' found in cert store"
+ << LL_ENDL;
return;
}
previous_cert = (*current_cert);
@@ -1192,11 +1219,17 @@ void LLBasicCertificateStore::validate(int validation_policy,
if (validation_policy & VALIDATION_POLICY_TRUSTED)
{
// we reached the end without finding a trusted cert.
- LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));
-
+ LLSD last_cert_info;
+ ((*cert_chain)[cert_chain->size()-1])->getLLSD(last_cert_info);
+ LLTHROW(LLCertValidationTrustException(last_cert_info));
}
- LL_DEBUGS("SECAPI") << "Valid ? cert for " << validation_params[CERT_HOSTNAME].asString() << " found in cert store" << LL_ENDL;
- mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);
+ else
+ {
+ LL_DEBUGS("SECAPI") << "! Caching untrusted cert for '" << subject_name << "'"
+ << " skeyid '" << skeyid << "' in cert store because ! VALIDATION_POLICY_TRUSTED"
+ << LL_ENDL;
+ mTrustedCertCache[skeyid] = std::pair<LLDate, LLDate>(from_time, to_time);
+ }
}