From c70d0f0ee280f5b417426154290a752489cded13 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 8 Dec 2009 00:00:51 -0800 Subject: DEV-42996 GIAB: configuring via CLI tools corrupts viewer certs Added authority key identifier/subject key identifier checking. Whenever a new cert was created, a new private key was also created. Typically you get a new key identifier with that private key which is written to the child cert. The child cert can then find the appropriate parent cert for validation via subject key identifier. --- indra/newview/llsecapi.h | 6 +++ indra/newview/llsechandler_basic.cpp | 75 +++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index b11563ef62..5211dc2699 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -78,6 +78,12 @@ #define CERT_EXTENDED_KEY_USAGE "extendedKeyUsage" #define CERT_EKU_SERVER_AUTH SN_server_auth +#define CERT_SUBJECT_KEY_IDENTFIER "subjectKeyIdentifier" +#define CERT_AUTHORITY_KEY_IDENTIFIER "authorityKeyIdentifier" +#define CERT_AUTHORITY_KEY_IDENTIFIER_ID "authorityKeyIdentifierId" +#define CERT_AUTHORITY_KEY_IDENTIFIER_NAME "authorityKeyIdentifierName" +#define CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL "authorityKeyIdentifierSerial" + // validate the current time lies within // the validation period of the cert #define VALIDATION_POLICY_TIME 1 diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index be5c7b3c61..d41ec96ab6 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -59,10 +59,13 @@ LLS * By copying, modifying or distributing this software, you acknowledge #define STORE_SALT_SIZE 16 #define BUFFER_READ_SIZE 256 std::string cert_string_from_asn1_string(ASN1_STRING* value); +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); LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) { @@ -175,6 +178,8 @@ LLSD& LLBasicCertificate::_initLLSD() 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); return mLLSDInfo; } @@ -269,6 +274,43 @@ LLSD _ext_key_usage_ext(X509* cert) return result; } +// retrieve the subject key identifier of the cert +LLSD _subject_key_identifier_ext(X509 *cert) +{ + LLSD 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); + } + return result; +} + +// retrieve the authority key identifier of the cert +LLSD _authority_key_identifier_ext(X509* cert) +{ + LLSD result; + AUTHORITY_KEYID *akeyid = (AUTHORITY_KEYID *)X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL); + if(akeyid) + { + result = LLSD::emptyMap(); + if(akeyid->keyid) + { + result[CERT_AUTHORITY_KEY_IDENTIFIER_ID] = cert_string_from_octet_string(akeyid->keyid); + } + if(akeyid->serial) + { + result[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL] = cert_string_from_asn1_integer(akeyid->serial); + } + } + + // 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; +} + // retrieve an openssl x509 object, // which must be freed by X509_free X509* LLBasicCertificate::getOpenSSLX509() const @@ -337,6 +379,25 @@ std::string cert_string_from_asn1_integer(ASN1_INTEGER* value) return result; } +// Generate a string from an OCTET string. +// we retrieve as a + +std::string cert_string_from_octet_string(ASN1_OCTET_STRING* value) +{ + + std::stringstream result; + result << std::hex << std::setprecision(2); + for (unsigned int i=0; i < value->length; i++) + { + if (i != 0) + { + result << ":"; + } + result << std::setfill('0') << std::setw(2) << (int)value->data[i]; + } + return result.str(); +} + // Generate a string from an ASN1 integer. ASN1 Integers are // bignums, so they can be 'infinitely' long, therefore we // cannot simply use a conversion to U64 or something. @@ -983,6 +1044,18 @@ void LLBasicCertificateChain::validate(int validation_policy, cert_search_params = LLSD::emptyMap(); cert_search_params[CERT_SUBJECT_NAME_STRING] = cert_llsd[CERT_ISSUER_NAME_STRING]; + if (cert_llsd.has(CERT_AUTHORITY_KEY_IDENTIFIER)) + { + LLSD cert_aki = cert_llsd[CERT_AUTHORITY_KEY_IDENTIFIER]; + if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_ID)) + { + cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_ID]; + } + if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL)) + { + cert_search_params[CERT_SERIAL_NUMBER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL]; + } + } found_store_cert = ca_store->find(cert_search_params); if(found_store_cert != ca_store->end()) -- cgit v1.2.3