Merge viewer-vivox

master
Ansariel 2017-04-20 00:33:01 +02:00
commit 2fff7fe963
12 changed files with 764 additions and 412 deletions

View File

@ -1692,16 +1692,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>62b92325634c6d41f9a9f80d392f1a70</string>
<string>2fd372be3084c956de10a2dbe034bf37</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/2997/6974/llca-201702281708.502986-common-502986.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/3948/10818/llca-201704032213.503937-common-503937.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>201702281708.502986</string>
<string>201704032213.503937</string>
</map>
<key>llceflib</key>
<map>

View File

@ -411,7 +411,7 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount()
{
if (mRef != 0)
{
LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
LL_ERRS() << "deleting referenced object mRef = " << mRef << LL_ENDL;
}
}

View File

@ -188,6 +188,7 @@
///
#include "linden_common.h" // Modifies curl/curl.h interfaces
#include "llsd.h"
#include "boost/intrusive_ptr.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"
@ -447,14 +448,14 @@ struct HttpStatus
mDetails->mMessage = message;
}
/// Retrieves an optionally recorded SSL certificate.
void * getErrorData() const
/// Retrieves data about an optionally recorded SSL certificate.
LLSD getErrorData() const
{
return mDetails->mErrorData;
}
/// Optionally sets an SSL certificate on this status.
void setErrorData(void *data)
void setErrorData(LLSD data)
{
mDetails->mErrorData = data;
}
@ -467,7 +468,7 @@ private:
mType(type),
mStatus(status),
mMessage(),
mErrorData(NULL)
mErrorData()
{}
Details(const Details &rhs) :
@ -485,7 +486,7 @@ private:
type_enum_t mType;
short mStatus;
std::string mMessage;
void * mErrorData;
LLSD mErrorData;
};
boost::shared_ptr<Details> mDetails;

View File

@ -565,9 +565,8 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
// error codes. Should be refactored with login refactoring, perhaps.
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT);
result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
LLSD certdata = cert_exception.getCertData();
result.setErrorData(certdata);
// We should probably have a more generic way of passing information
// back to the error handlers.
}
@ -575,9 +574,8 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,
{
result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE);
result.setMessage(cert_exception.what());
LLPointer<LLCertificate> cert = cert_exception.getCert();
cert->ref(); // adding an extra ref here
result.setErrorData(cert.get());
LLSD certdata = cert_exception.getCertData();
result.setErrorData(certdata);
}
catch (...)
{

View File

@ -334,24 +334,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);
class LLCertException: public LLException
{
public:
LLCertException(LLPointer<LLCertificate> cert, const std::string& msg):
LLException(msg)
LLCertException(const LLSD& cert_data, const std::string& msg): LLException(msg),
mCertData(cert_data)
{
mCert = cert;
LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
}
virtual ~LLCertException() throw() {}
LLPointer<LLCertificate> getCert() const { return mCert; }
LLSD getCertData() const { return mCertData; }
protected:
LLPointer<LLCertificate> mCert;
LLSD mCertData;
};
class LLInvalidCertificate : public LLCertException
{
public:
LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")
LLInvalidCertificate(const LLSD& cert_data) : LLCertException(cert_data, "CertInvalid")
{
}
virtual ~LLInvalidCertificate() throw() {}
@ -361,7 +358,7 @@ protected:
class LLCertValidationTrustException : public LLCertException
{
public:
LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")
LLCertValidationTrustException(const LLSD& cert_data) : LLCertException(cert_data, "CertUntrusted")
{
}
virtual ~LLCertValidationTrustException() throw() {}
@ -372,7 +369,7 @@ class LLCertValidationHostnameException : public LLCertException
{
public:
LLCertValidationHostnameException(std::string hostname,
LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidHostname")
const LLSD& cert_data) : LLCertException(cert_data, "CertInvalidHostname")
{
mHostname = hostname;
}
@ -385,8 +382,8 @@ protected:
class LLCertValidationExpirationException : public LLCertException
{
public:
LLCertValidationExpirationException(LLPointer<LLCertificate> cert,
LLDate current_time) : LLCertException(cert, "CertExpired")
LLCertValidationExpirationException(const LLSD& cert_data,
LLDate current_time) : LLCertException(cert_data, "CertExpired")
{
mTime = current_time;
}
@ -399,7 +396,7 @@ protected:
class LLCertKeyUsageValidationException : public LLCertException
{
public:
LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")
LLCertKeyUsageValidationException(const LLSD& cert_data) : LLCertException(cert_data, "CertKeyUsage")
{
}
virtual ~LLCertKeyUsageValidationException() throw() {}
@ -409,7 +406,7 @@ protected:
class LLCertBasicConstraintsValidationException : public LLCertException
{
public:
LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")
LLCertBasicConstraintsValidationException(const LLSD& cert_data) : LLCertException(cert_data, "CertBasicConstraints")
{
}
virtual ~LLCertBasicConstraintsValidationException() throw() {}
@ -419,7 +416,7 @@ protected:
class LLCertValidationInvalidSignatureException : public LLCertException
{
public:
LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")
LLCertValidationInvalidSignatureException(const LLSD& cert_data) : LLCertException(cert_data, "CertInvalidSignature")
{
}
virtual ~LLCertValidationInvalidSignatureException() throw() {}

View File

@ -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
@ -619,12 +595,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;
@ -888,33 +880,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))
{
@ -924,7 +914,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)
@ -935,14 +925,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)
@ -951,7 +941,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));
}
}
@ -963,13 +953,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));
}
}
}
@ -1043,26 +1033,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() <<
@ -1071,39 +1063,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())
@ -1117,7 +1130,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())
{
@ -1132,7 +1144,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,
@ -1143,12 +1157,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;
}
@ -1182,11 +1204,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);
@ -1200,11 +1227,18 @@ 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));
}
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);
}
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);
}

View File

@ -47,8 +47,9 @@ class LLBasicCertificate : public LLCertificate
public:
LOG_CLASS(LLBasicCertificate);
LLBasicCertificate(const std::string& pem_cert);
LLBasicCertificate(X509* openSSLX509);
// The optional validation_params allow us to make the unit test time-invariant
LLBasicCertificate(const std::string& pem_cert, const LLSD* validation_params = NULL);
LLBasicCertificate(X509* openSSLX509, const LLSD* validation_params = NULL);
virtual ~LLBasicCertificate();

View File

@ -526,7 +526,7 @@ void LLVivoxVoiceClient::connectorCreate()
{
std::ostringstream stream;
// <FS:Ansariel> Set custom Vivox log path everywhere necessary
//std::string logpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
//std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
std::string logdir = gSavedSettings.getString("VivoxLogDirectory");
if (logdir.empty())
{

View File

@ -379,14 +379,9 @@ public:
{
case CURLE_SSL_PEER_CERTIFICATE:
case CURLE_SSL_CACERT:
{
LLPointer<LLCertificate> error_cert(mTransaction->getErrorCert());
if(error_cert)
{
data["certificate"] = error_cert->getPem();
}
data["certificate"] = mTransaction->getErrorCertData();
break;
}
default:
break;
}

View File

@ -206,7 +206,7 @@ public:
std::string mResponseText;
XMLRPC_REQUEST mResponse;
std::string mCertStore;
LLPointer<LLCertificate> mErrorCert;
LLSD mErrorCertData;
Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip);
Impl(const std::string& uri,
@ -247,14 +247,8 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
// (a non cert error), then generate the error message as
// appropriate
mImpl->setHttpStatus(status);
LLCertificate *errordata = static_cast<LLCertificate *>(status.getErrorData());
if (errordata)
{
mImpl->mErrorCert = LLPointer<LLCertificate>(errordata);
status.setErrorData(NULL);
errordata->unref();
}
LLSD errordata = status.getErrorData();
mImpl->mErrorCertData = errordata;
LL_WARNS() << "LLXMLRPCTransaction error "
<< status.toHex() << ": " << status.toString() << LL_ENDL;
@ -565,9 +559,9 @@ std::string LLXMLRPCTransaction::statusMessage()
return impl.mStatusMessage;
}
LLPointer<LLCertificate> LLXMLRPCTransaction::getErrorCert()
LLSD LLXMLRPCTransaction::getErrorCertData()
{
return impl.mErrorCert;
return impl.mErrorCertData;
}
std::string LLXMLRPCTransaction::statusURI()

View File

@ -111,7 +111,7 @@ public:
EStatus status(int* curlCode);
// return status, and extended CURL code, if code isn't null
LLPointer<LLCertificate> getErrorCert();
LLSD getErrorCertData();
std::string statusMessage();
// return a message string, suitable for showing the user
std::string statusURI();

File diff suppressed because it is too large Load Diff