Merge viewer-vivox
commit
2fff7fe963
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 (...)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue