phoenix-firestorm/indra/newview/tests/llsechandler_basic_test.cpp

1415 lines
72 KiB
C++

/**
* @file llsechandler_basic_test.cpp
* @author Roxie
* @date 2009-02-10
* @brief Test the 'basic' sec handler functions
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "../llviewerprecompiledheaders.h"
#include "../test/lltut.h"
#include "../llsecapi.h"
#include "../llsechandler_basic.h"
#include "../../llxml/llcontrol.h"
#include "../llviewernetwork.h"
#include "lluuid.h"
#include "lldate.h"
#include "llxorcipher.h"
#include "apr_base64.h"
#include <vector>
#include <ios>
#include <llsdserialize.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "llxorcipher.h"
#include <openssl/ossl_typ.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/pem.h>
#include <openssl/asn1.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include "../llmachineid.h"
#define ensure_throws(str, exc_type, cert, func, ...) \
try \
{ \
func(__VA_ARGS__); \
fail("throws, " str); \
} \
catch(exc_type& except) \
{ \
LLSD cert_data; \
cert->getLLSD(cert_data); \
ensure("Exception cert is incorrect for " str, valueCompareLLSD(except.getCertData(), cert_data)); \
}
extern bool _cert_hostname_wildcard_match(const std::string& hostname, const std::string& wildcard_string);
//----------------------------------------------------------------------------
// Mock objects for the dependencies of the code we're testing
std::string gFirstName;
std::string gLastName;
LLControlGroup::LLControlGroup(const std::string& name)
: LLInstanceTracker<LLControlGroup, std::string>(name) {}
LLControlGroup::~LLControlGroup() {}
LLControlVariable* LLControlGroup::declareString(const std::string& name,
const std::string& initial_val,
const std::string& comment,
LLControlVariable::ePersist persist) {return NULL;}
void LLControlGroup::setString(const std::string& name, const std::string& val){}
std::string LLControlGroup::getString(const std::string& name)
{
if (name == "FirstName")
return gFirstName;
else if (name == "LastName")
return gLastName;
return "";
}
// Stub for --no-verify-ssl-cert
BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
LLSD LLCredential::getLoginParams()
{
LLSD result = LLSD::emptyMap();
// legacy credential
result["passwd"] = "$1$testpasssd";
result["first"] = "myfirst";
result["last"] ="mylast";
return result;
}
void LLCredential::identifierType(std::string &idType)
{
}
void LLCredential::authenticatorType(std::string &idType)
{
}
LLControlGroup gSavedSettings("test");
unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2};
S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
{
memcpy(unique_id, gMACAddress, len);
return 1;
}
S32 LLMachineID::init() { return 1; }
LLCertException::LLCertException(const LLSD& cert_data, const std::string& msg)
: LLException(msg),
mCertData(cert_data)
{
LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;
}
// -------------------------------------------------------------------------------------------
// TUT
// -------------------------------------------------------------------------------------------
namespace tut
{
const std::string mPemTestCert(
"Certificate:\n"
" Data:\n"
" Version: 3 (0x2)\n"
" Serial Number:\n"
" 04:00:00:00:00:01:15:4b:5a:c3:94\n"
" Signature Algorithm: sha1WithRSAEncryption\n"
" Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA\n"
" Validity\n"
" Not Before: Sep 1 12:00:00 1998 GMT\n"
" Not After : Jan 28 12:00:00 2028 GMT\n"
" Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA\n"
" Subject Public Key Info:\n"
" Public Key Algorithm: rsaEncryption\n"
" Public-Key: (2048 bit)\n"
" Modulus:\n"
" 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b:\n"
" 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0:\n"
" 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89:\n"
" 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c:\n"
" 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50:\n"
" 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0:\n"
" 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2:\n"
" 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7:\n"
" 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c:\n"
" 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2:\n"
" 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9:\n"
" c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b:\n"
" bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91:\n"
" ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51:\n"
" 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa:\n"
" 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a:\n"
" 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93:\n"
" 90:cf\n"
" Exponent: 65537 (0x10001)\n"
" X509v3 extensions:\n"
" X509v3 Key Usage: critical\n"
" Certificate Sign, CRL Sign\n"
" X509v3 Basic Constraints: critical\n"
" CA:TRUE\n"
" X509v3 Subject Key Identifier: \n"
" 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B\n"
" Signature Algorithm: sha1WithRSAEncryption\n"
" d6:73:e7:7c:4f:76:d0:8d:bf:ec:ba:a2:be:34:c5:28:32:b5:\n"
" 7c:fc:6c:9c:2c:2b:bd:09:9e:53:bf:6b:5e:aa:11:48:b6:e5:\n"
" 08:a3:b3:ca:3d:61:4d:d3:46:09:b3:3e:c3:a0:e3:63:55:1b:\n"
" f2:ba:ef:ad:39:e1:43:b9:38:a3:e6:2f:8a:26:3b:ef:a0:50:\n"
" 56:f9:c6:0a:fd:38:cd:c4:0b:70:51:94:97:98:04:df:c3:5f:\n"
" 94:d5:15:c9:14:41:9c:c4:5d:75:64:15:0d:ff:55:30:ec:86:\n"
" 8f:ff:0d:ef:2c:b9:63:46:f6:aa:fc:df:bc:69:fd:2e:12:48:\n"
" 64:9a:e0:95:f0:a6:ef:29:8f:01:b1:15:b5:0c:1d:a5:fe:69:\n"
" 2c:69:24:78:1e:b3:a7:1c:71:62:ee:ca:c8:97:ac:17:5d:8a:\n"
" c2:f8:47:86:6e:2a:c4:56:31:95:d0:67:89:85:2b:f9:6c:a6:\n"
" 5d:46:9d:0c:aa:82:e4:99:51:dd:70:b7:db:56:3d:61:e4:6a:\n"
" e1:5c:d6:f6:fe:3d:de:41:cc:07:ae:63:52:bf:53:53:f4:2b:\n"
" e9:c7:fd:b6:f7:82:5f:85:d2:41:18:db:81:b3:04:1c:c5:1f:\n"
" a4:80:6f:15:20:c9:de:0c:88:0a:1d:d6:66:55:e2:fc:48:c9:\n"
" 29:26:69:e0\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n"
"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n"
"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n"
"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n"
"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n"
"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n"
"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n"
"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n"
"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n"
"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n"
"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n"
"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n"
"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n"
"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n"
"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n"
"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n"
"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n"
"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n"
"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\n"
"-----END CERTIFICATE-----\n"
);
/*
* The following certificates were generated using the instructions at
* https://jamielinux.com/docs/openssl-certificate-authority/sign-server-and-client-certificates.html
* with the exception that the server certificate has a longer expiration time, and the full text
* expansion was included in the certificates.
*/
const std::string mPemRootCert(
"Certificate:\n"
" Data:\n"
" Version: 3 (0x2)\n"
" Serial Number:\n"
" 82:2f:8f:eb:8d:06:24:b0\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"
" Validity\n"
" Not Before: May 22 22:19:45 2018 GMT\n"
" Not After : May 17 22:19:45 2038 GMT\n"
" Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"
" Subject Public Key Info:\n"
" Public Key Algorithm: rsaEncryption\n"
" Public-Key: (4096 bit)\n"
" Modulus:\n"
" 00:bd:e0:79:dd:3b:a6:ac:87:d0:39:f0:58:c7:a4:\n"
" 42:42:f6:5f:93:b0:36:04:b5:e2:d5:f7:2a:c0:6c:\n"
" a0:13:d2:1e:02:81:57:02:50:4c:57:b7:ef:27:9e:\n"
" f6:f1:f1:30:30:72:1e:57:34:e5:3f:82:3c:21:c4:\n"
" 66:d2:73:63:6c:91:e6:dd:49:9e:9c:b1:34:6a:81:\n"
" 45:a1:6e:c4:50:28:f2:d8:e3:fe:80:2f:83:aa:28:\n"
" 91:b4:8c:57:c9:f1:16:d9:0c:87:3c:25:80:a0:81:\n"
" 8d:71:f2:96:e2:16:f1:97:c4:b0:d8:53:bb:13:6c:\n"
" 73:54:2f:29:94:85:cf:86:6e:75:71:ad:39:e3:fc:\n"
" 39:12:53:93:1c:ce:39:e0:33:da:49:b7:3d:af:b0:\n"
" 37:ce:77:09:03:27:32:70:c0:9c:7f:9c:89:ce:90:\n"
" 45:b0:7d:94:8b:ff:13:27:ba:88:7f:ae:c4:aa:73:\n"
" d5:47:b8:87:69:89:80:0c:c1:22:18:78:c2:0d:47:\n"
" d9:10:ff:80:79:0d:46:71:ec:d9:ba:c9:f3:77:fd:\n"
" 92:6d:1f:0f:d9:54:18:6d:f6:72:24:5c:5c:3d:43:\n"
" 49:35:3e:1c:28:de:7e:44:dc:29:c3:9f:62:04:46:\n"
" aa:c4:e6:69:6a:15:f8:e3:74:1c:14:e9:f4:97:7c:\n"
" 30:6c:d4:28:fc:2a:0e:1d:6d:39:2e:1d:f9:17:43:\n"
" 35:5d:23:e7:ba:e3:a8:e9:97:6b:3c:3e:23:ef:d8:\n"
" bc:fb:7a:57:37:39:93:59:03:fc:78:ca:b1:31:ef:\n"
" 26:19:ed:56:e1:63:c3:ad:99:80:5b:47:b5:03:35:\n"
" 5f:fe:6a:a6:21:63:ec:50:fb:4e:c9:f9:ae:a5:66:\n"
" d0:55:33:8d:e6:c5:50:5a:c6:8f:5c:34:45:a7:72:\n"
" da:50:f6:66:4c:19:f5:d1:e4:fb:11:8b:a1:b5:4e:\n"
" 09:43:81:3d:39:28:86:3b:fe:07:28:97:02:b5:3a:\n"
" 07:5f:4a:20:80:1a:7d:a4:8c:f7:6c:f6:c5:9b:f6:\n"
" 61:e5:c7:b0:c3:d5:58:38:7b:bb:47:1e:34:d6:16:\n"
" 55:c5:d2:6c:b0:93:77:b1:90:69:06:b1:53:cb:1b:\n"
" 84:71:cf:b8:87:1b:1e:44:35:b4:2b:bb:04:59:58:\n"
" 0b:e8:93:d8:ae:21:9b:b1:1c:89:30:ae:11:80:77:\n"
" cc:16:f3:d6:35:ed:a1:b3:70:b3:4f:cd:a1:56:99:\n"
" ee:0e:c0:00:a4:09:70:c3:5b:0b:be:a1:07:18:dd:\n"
" c6:f4:6d:8b:58:bc:f9:bb:4b:01:2c:f6:cc:2c:9b:\n"
" 87:0e:b1:4f:9c:10:be:fc:45:e2:a4:ec:7e:fc:ff:\n"
" 45:b8:53\n"
" Exponent: 65537 (0x10001)\n"
" X509v3 extensions:\n"
" X509v3 Subject Key Identifier: \n"
" 8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"
" X509v3 Authority Key Identifier: \n"
" keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"
"\n"
" X509v3 Basic Constraints: critical\n"
" CA:TRUE\n"
" X509v3 Key Usage: critical\n"
" Digital Signature, Certificate Sign, CRL Sign\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" b3:cb:33:eb:0e:02:64:f4:55:9a:3d:03:9a:cf:6a:4c:18:43:\n"
" f7:42:cb:65:dc:61:52:e5:9f:2f:42:97:3c:93:16:22:d4:af:\n"
" ae:b2:0f:c3:9b:ef:e0:cc:ee:b6:b1:69:a3:d8:da:26:c3:ad:\n"
" 3b:c5:64:dc:9f:d4:c2:53:4b:91:6d:c4:92:09:0b:ac:f0:99:\n"
" be:6f:b9:3c:03:4a:6d:9f:01:5d:ec:5a:9a:f3:a7:e5:3b:2c:\n"
" 99:57:7d:7e:25:15:68:20:12:30:96:16:86:f5:db:74:90:60:\n"
" fe:8b:df:99:f6:f7:62:49:9f:bc:8d:45:23:0a:c8:73:b8:79:\n"
" 80:3c:b9:e5:72:85:4b:b3:81:66:74:a2:72:92:4c:44:fd:7b:\n"
" 46:2e:21:a2:a9:81:a2:f3:26:4d:e3:89:7d:78:b0:c6:6f:b5:\n"
" 87:cb:ee:25:ed:27:1f:75:13:fa:6d:e9:37:73:ad:07:bb:af:\n"
" d3:6c:87:ea:02:01:70:bd:53:aa:ce:39:2c:d4:66:39:33:aa:\n"
" d1:9c:ee:67:e3:a9:45:d2:7b:2e:54:09:af:70:5f:3f:5a:67:\n"
" 2e:6c:72:ef:e0:9d:92:28:4a:df:ba:0b:b7:23:ca:5b:04:11:\n"
" 45:d1:51:e9:ea:c9:ec:54:fa:34:46:ae:fc:dc:6c:f8:1e:2c:\n"
" 9e:f4:71:51:8d:b5:a1:26:9a:13:30:be:1e:41:25:59:58:05:\n"
" 2c:64:c8:f9:5e:38:ae:dc:93:b0:8a:d6:38:74:02:cb:ce:ce:\n"
" 95:31:76:f6:7c:bf:a4:a1:8e:27:fd:ca:74:82:d1:e1:4d:b6:\n"
" 48:51:fa:c5:17:59:22:a3:84:be:82:c8:83:ec:61:a0:f4:ee:\n"
" 2c:e3:a3:ea:e5:51:c9:d3:4f:db:85:bd:ba:7a:52:14:b6:03:\n"
" ed:43:17:d8:d7:1c:22:5e:c9:56:d9:d6:81:96:11:e3:5e:01:\n"
" 40:91:30:09:da:a3:5f:d3:27:60:e5:9d:6c:da:d0:f0:39:01:\n"
" 23:4a:a6:15:7a:4a:82:eb:ec:72:4a:1d:36:dc:6f:83:c4:85:\n"
" 84:b5:8d:cd:09:e5:12:63:f3:21:56:c8:64:6b:db:b8:cf:d4:\n"
" df:ca:a8:24:8e:df:8d:63:a5:96:84:bf:ff:8b:7e:46:7a:f0:\n"
" c7:73:7c:70:8a:f5:17:d0:ac:c8:89:1e:d7:89:42:0f:4d:66:\n"
" c4:d8:bb:36:a8:ae:ca:e1:cf:e2:88:f6:cf:b0:44:4a:5f:81:\n"
" 50:4b:d6:28:81:cd:6c:f0:ec:e6:09:08:f2:59:91:a2:69:ac:\n"
" c7:81:fa:ab:61:3e:db:6f:f6:7f:db:1a:9e:b9:5d:cc:cc:33:\n"
" fa:95:c6:f7:8d:4b:30:f3\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIGXDCCBESgAwIBAgIJAIIvj+uNBiSwMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n"
"VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n"
"aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n"
"RW5naW5lZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEk\n"
"MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTE4MDUyMjIy\n"
"MTk0NVoXDTM4MDUxNzIyMTk0NVowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n"
"YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5k\n"
"ZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEhMB8GA1UE\n"
"AwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZIhvcNAQkBFhVub3Jl\n"
"cGx5QGxpbmRlbmxhYi5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n"
"AQC94HndO6ash9A58FjHpEJC9l+TsDYEteLV9yrAbKAT0h4CgVcCUExXt+8nnvbx\n"
"8TAwch5XNOU/gjwhxGbSc2NskebdSZ6csTRqgUWhbsRQKPLY4/6AL4OqKJG0jFfJ\n"
"8RbZDIc8JYCggY1x8pbiFvGXxLDYU7sTbHNULymUhc+GbnVxrTnj/DkSU5Mczjng\n"
"M9pJtz2vsDfOdwkDJzJwwJx/nInOkEWwfZSL/xMnuoh/rsSqc9VHuIdpiYAMwSIY\n"
"eMINR9kQ/4B5DUZx7Nm6yfN3/ZJtHw/ZVBht9nIkXFw9Q0k1Phwo3n5E3CnDn2IE\n"
"RqrE5mlqFfjjdBwU6fSXfDBs1Cj8Kg4dbTkuHfkXQzVdI+e646jpl2s8PiPv2Lz7\n"
"elc3OZNZA/x4yrEx7yYZ7VbhY8OtmYBbR7UDNV/+aqYhY+xQ+07J+a6lZtBVM43m\n"
"xVBaxo9cNEWnctpQ9mZMGfXR5PsRi6G1TglDgT05KIY7/gcolwK1OgdfSiCAGn2k\n"
"jPds9sWb9mHlx7DD1Vg4e7tHHjTWFlXF0mywk3exkGkGsVPLG4Rxz7iHGx5ENbQr\n"
"uwRZWAvok9iuIZuxHIkwrhGAd8wW89Y17aGzcLNPzaFWme4OwACkCXDDWwu+oQcY\n"
"3cb0bYtYvPm7SwEs9swsm4cOsU+cEL78ReKk7H78/0W4UwIDAQABo2MwYTAdBgNV\n"
"HQ4EFgQUiiLGnC4R80AMzoIMIln/+H/QuRMwHwYDVR0jBBgwFoAUiiLGnC4R80AM\n"
"zoIMIln/+H/QuRMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJ\n"
"KoZIhvcNAQELBQADggIBALPLM+sOAmT0VZo9A5rPakwYQ/dCy2XcYVLlny9ClzyT\n"
"FiLUr66yD8Ob7+DM7raxaaPY2ibDrTvFZNyf1MJTS5FtxJIJC6zwmb5vuTwDSm2f\n"
"AV3sWprzp+U7LJlXfX4lFWggEjCWFob123SQYP6L35n292JJn7yNRSMKyHO4eYA8\n"
"ueVyhUuzgWZ0onKSTET9e0YuIaKpgaLzJk3jiX14sMZvtYfL7iXtJx91E/pt6Tdz\n"
"rQe7r9Nsh+oCAXC9U6rOOSzUZjkzqtGc7mfjqUXSey5UCa9wXz9aZy5scu/gnZIo\n"
"St+6C7cjylsEEUXRUenqyexU+jRGrvzcbPgeLJ70cVGNtaEmmhMwvh5BJVlYBSxk\n"
"yPleOK7ck7CK1jh0AsvOzpUxdvZ8v6Shjif9ynSC0eFNtkhR+sUXWSKjhL6CyIPs\n"
"YaD07izjo+rlUcnTT9uFvbp6UhS2A+1DF9jXHCJeyVbZ1oGWEeNeAUCRMAnao1/T\n"
"J2DlnWza0PA5ASNKphV6SoLr7HJKHTbcb4PEhYS1jc0J5RJj8yFWyGRr27jP1N/K\n"
"qCSO341jpZaEv/+LfkZ68MdzfHCK9RfQrMiJHteJQg9NZsTYuzaorsrhz+KI9s+w\n"
"REpfgVBL1iiBzWzw7OYJCPJZkaJprMeB+qthPttv9n/bGp65XczMM/qVxveNSzDz\n"
"-----END CERTIFICATE-----\n"
);
const std::string mPemIntermediateCert(
"Certificate:\n"
" Data:\n"
" Version: 3 (0x2)\n"
" Serial Number: 4096 (0x1000)\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"
" Validity\n"
" Not Before: May 22 22:39:08 2018 GMT\n"
" Not After : May 19 22:39:08 2028 GMT\n"
" Subject: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n"
" Subject Public Key Info:\n"
" Public Key Algorithm: rsaEncryption\n"
" Public-Key: (4096 bit)\n"
" Modulus:\n"
" 00:ce:a3:70:e2:c4:fb:4b:97:90:a1:30:bb:c1:1b:\n"
" 13:b9:aa:7e:46:17:a3:26:8d:69:3f:5e:73:95:e8:\n"
" 6a:b1:0a:b4:8f:50:65:e3:c6:5c:39:24:34:df:0b:\n"
" b7:cc:ce:62:0c:36:5a:12:2c:fe:35:4c:e9:1c:ac:\n"
" 80:5e:24:99:d7:aa:bd:be:48:c0:62:64:77:36:88:\n"
" 66:ce:f4:a8:dd:d2:76:24:62:90:55:41:fc:1d:13:\n"
" 4e:a7:4e:57:bc:a8:a4:59:4b:2c:5a:1c:d8:cc:16:\n"
" de:e8:88:30:c9:95:df:2f:a6:14:28:0f:eb:34:46:\n"
" 12:58:ba:da:0e:e6:de:9c:15:f6:f4:e3:9f:74:aa:\n"
" 70:89:79:8b:e9:5a:7b:18:54:15:94:3a:23:0a:65:\n"
" 78:05:d9:33:90:2a:ce:15:18:0d:52:fc:5c:31:65:\n"
" 20:d0:12:37:8c:11:80:ba:d4:b0:82:73:00:4b:49:\n"
" be:cb:d6:bc:e7:cd:61:f3:00:98:99:74:5a:37:81:\n"
" 49:96:7e:14:01:1b:86:d2:d0:06:94:40:63:63:46:\n"
" 11:fc:33:5c:bd:3a:5e:d4:e5:44:47:64:50:bd:a6:\n"
" 97:55:70:64:9b:26:cc:de:20:82:90:6a:83:41:9c:\n"
" 6f:71:47:14:be:cb:68:7c:85:be:ef:2e:76:12:19:\n"
" d3:c9:87:32:b4:ac:60:20:16:28:2d:af:bc:e8:01:\n"
" c6:7f:fb:d8:11:d5:f4:b7:14:bd:27:08:5b:72:be:\n"
" 09:e0:91:c8:9c:7b:b4:b3:12:ef:32:36:be:b1:b9:\n"
" a2:b7:e3:69:47:30:76:ba:9c:9b:19:99:4d:53:dd:\n"
" 5c:e8:2c:f1:b2:64:69:cf:15:bd:f8:bb:58:95:73:\n"
" 58:38:95:b4:7a:cf:84:29:a6:c2:db:f0:bd:ef:97:\n"
" 26:d4:99:ac:d7:c7:be:b0:0d:11:f4:26:86:2d:77:\n"
" 42:52:25:d7:56:c7:e3:97:b1:36:5c:97:71:d0:9b:\n"
" f5:b5:50:8d:f9:ff:fb:10:77:3c:b5:53:6d:a1:43:\n"
" 35:a9:03:32:05:ab:d7:f5:d1:19:bd:5f:92:a3:00:\n"
" 2a:79:37:a4:76:4f:e9:32:0d:e4:86:bb:ea:c3:1a:\n"
" c5:33:e8:16:d4:a5:d8:e0:e8:bb:c2:f0:22:15:e2:\n"
" d9:8c:ae:ac:7d:2b:bf:eb:a3:4c:3b:29:1d:94:ac:\n"
" a3:bb:6d:ba:6d:03:91:03:cf:46:12:c4:66:21:c5:\n"
" c6:67:d8:11:19:79:01:0e:6e:84:1c:76:6f:11:3d:\n"
" eb:94:89:c5:6a:26:1f:cd:e0:11:8b:51:ee:99:35:\n"
" 69:e5:7f:0b:77:2a:94:e4:4b:64:b9:83:04:30:05:\n"
" e4:a2:e3\n"
" Exponent: 65537 (0x10001)\n"
" X509v3 extensions:\n"
" X509v3 Subject Key Identifier: \n"
" 83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n"
" X509v3 Authority Key Identifier: \n"
" keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"
"\n"
" X509v3 Basic Constraints: critical\n"
" CA:TRUE, pathlen:0\n"
" X509v3 Key Usage: critical\n"
" Digital Signature, Certificate Sign, CRL Sign\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" a3:6c:85:9a:2e:4e:7e:5d:83:63:0f:f5:4f:a9:7d:ec:0e:6f:\n"
" ae:d7:ba:df:64:e0:46:0e:3d:da:18:15:2c:f3:73:ca:81:b1:\n"
" 10:d9:53:14:21:7d:72:5c:94:88:a5:9d:ad:ab:45:42:c6:64:\n"
" a9:d9:2e:4e:29:47:2c:b1:95:07:b7:62:48:68:1f:68:13:1c:\n"
" d2:a0:fb:5e:38:24:4a:82:0a:87:c9:93:20:43:7e:e9:f9:79:\n"
" ef:03:a2:bd:9e:24:6b:0a:01:5e:4a:36:c5:7d:7a:fe:d6:aa:\n"
" 2f:c2:8c:38:8a:99:3c:b0:6a:e5:60:be:56:d6:eb:60:03:55:\n"
" 24:42:a0:1a:fa:91:24:a3:53:15:75:5d:c8:eb:7c:1e:68:5a:\n"
" 7e:13:34:e3:85:37:1c:76:3f:77:67:1b:ed:1b:52:17:fc:4a:\n"
" a3:e2:74:84:80:2c:69:fc:dd:7d:26:97:c4:2a:69:7d:9c:dc:\n"
" 61:97:70:29:a7:3f:2b:5b:2b:22:51:fd:fe:6a:5d:f9:e7:14:\n"
" 48:b7:2d:c8:33:58:fc:f2:5f:27:f7:26:16:be:be:b5:aa:a2:\n"
" 64:53:3c:69:e8:b5:61:eb:ab:91:a5:b4:09:9b:f6:98:b8:5c:\n"
" 5b:24:2f:93:f5:2b:9c:8c:58:fb:26:3f:67:53:d7:42:64:e8:\n"
" 79:77:73:41:4e:e3:02:39:0b:b6:68:97:8b:84:e8:1d:83:a8:\n"
" 15:f1:06:46:47:80:42:5e:14:e2:61:8a:76:84:d5:d4:71:7f:\n"
" 4e:ff:d9:74:87:ff:32:c5:87:20:0a:d4:59:40:3e:d8:17:ef:\n"
" da:65:e9:0a:51:fe:1e:c3:46:91:d2:ee:e4:23:57:97:87:d4:\n"
" a6:a5:eb:ef:81:6a:d8:8c:d6:1f:8e:b1:18:4c:6b:89:32:55:\n"
" 53:68:26:9e:bb:03:be:2c:e9:8b:ff:97:9c:1c:ac:28:c3:9f:\n"
" 0b:b7:93:23:24:31:63:e4:19:13:f2:bb:08:71:b7:c5:c5:c4:\n"
" 10:ff:dc:fc:33:54:a4:5e:ec:a3:fe:0a:80:ca:9c:bc:95:6f:\n"
" 5f:39:91:3b:61:69:16:94:0f:57:4b:fc:4b:b1:be:72:98:5d:\n"
" 10:f9:08:a7:d6:e0:e8:3d:5d:54:7d:fa:4b:6a:dd:98:41:ed:\n"
" 84:a1:39:67:5c:6c:7f:0c:b0:e1:98:c1:14:ed:fe:1e:e8:05:\n"
" 8d:7f:6a:24:cb:1b:05:42:0d:7f:13:ba:ca:b5:91:db:a5:f0:\n"
" 40:2b:70:7a:2a:a5:5d:ed:56:0c:f0:c2:72:ee:63:dd:cb:5d:\n"
" 76:f6:08:e6:e6:30:ef:3a:b2:16:34:41:a4:e1:30:14:bc:c7:\n"
" f9:23:3a:1a:70:df:b8:cc\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIGSDCCBDCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgboxCzAJBgNVBAYTAlVT\n"
"MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMw\n"
"EQYDVQQKDApMaW5kZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVl\n"
"cmluZzEhMB8GA1UEAwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZI\n"
"hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcNMTgwNTIyMjIzOTA4WhcN\n"
"MjgwNTE5MjIzOTA4WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\n"
"aWExEzARBgNVBAoMCkxpbmRlbiBMYWIxIDAeBgNVBAsMF1NlY29uZCBMaWZlIEVu\n"
"Z2luZWVyaW5nMSkwJwYDVQQDDCBJbnRlZ3JhdGlvbiBUZXN0IEludGVybWVkaWF0\n"
"ZSBDQTEkMCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMIICIjAN\n"
"BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzqNw4sT7S5eQoTC7wRsTuap+Rhej\n"
"Jo1pP15zlehqsQq0j1Bl48ZcOSQ03wu3zM5iDDZaEiz+NUzpHKyAXiSZ16q9vkjA\n"
"YmR3NohmzvSo3dJ2JGKQVUH8HRNOp05XvKikWUssWhzYzBbe6IgwyZXfL6YUKA/r\n"
"NEYSWLraDubenBX29OOfdKpwiXmL6Vp7GFQVlDojCmV4BdkzkCrOFRgNUvxcMWUg\n"
"0BI3jBGAutSwgnMAS0m+y9a8581h8wCYmXRaN4FJln4UARuG0tAGlEBjY0YR/DNc\n"
"vTpe1OVER2RQvaaXVXBkmybM3iCCkGqDQZxvcUcUvstofIW+7y52EhnTyYcytKxg\n"
"IBYoLa+86AHGf/vYEdX0txS9Jwhbcr4J4JHInHu0sxLvMja+sbmit+NpRzB2upyb\n"
"GZlNU91c6CzxsmRpzxW9+LtYlXNYOJW0es+EKabC2/C975cm1Jms18e+sA0R9CaG\n"
"LXdCUiXXVsfjl7E2XJdx0Jv1tVCN+f/7EHc8tVNtoUM1qQMyBavX9dEZvV+SowAq\n"
"eTekdk/pMg3khrvqwxrFM+gW1KXY4Oi7wvAiFeLZjK6sfSu/66NMOykdlKyju226\n"
"bQORA89GEsRmIcXGZ9gRGXkBDm6EHHZvET3rlInFaiYfzeARi1HumTVp5X8LdyqU\n"
"5EtkuYMEMAXkouMCAwEAAaNmMGQwHQYDVR0OBBYEFIMh3uzAeQNtHoPz5Zcp1VrA\n"
"lkD6MB8GA1UdIwQYMBaAFIoixpwuEfNADM6CDCJZ//h/0LkTMBIGA1UdEwEB/wQI\n"
"MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQCjbIWa\n"
"Lk5+XYNjD/VPqX3sDm+u17rfZOBGDj3aGBUs83PKgbEQ2VMUIX1yXJSIpZ2tq0VC\n"
"xmSp2S5OKUcssZUHt2JIaB9oExzSoPteOCRKggqHyZMgQ37p+XnvA6K9niRrCgFe\n"
"SjbFfXr+1qovwow4ipk8sGrlYL5W1utgA1UkQqAa+pEko1MVdV3I63weaFp+EzTj\n"
"hTccdj93ZxvtG1IX/Eqj4nSEgCxp/N19JpfEKml9nNxhl3Appz8rWysiUf3+al35\n"
"5xRIty3IM1j88l8n9yYWvr61qqJkUzxp6LVh66uRpbQJm/aYuFxbJC+T9SucjFj7\n"
"Jj9nU9dCZOh5d3NBTuMCOQu2aJeLhOgdg6gV8QZGR4BCXhTiYYp2hNXUcX9O/9l0\n"
"h/8yxYcgCtRZQD7YF+/aZekKUf4ew0aR0u7kI1eXh9SmpevvgWrYjNYfjrEYTGuJ\n"
"MlVTaCaeuwO+LOmL/5ecHKwow58Lt5MjJDFj5BkT8rsIcbfFxcQQ/9z8M1SkXuyj\n"
"/gqAypy8lW9fOZE7YWkWlA9XS/xLsb5ymF0Q+Qin1uDoPV1UffpLat2YQe2EoTln\n"
"XGx/DLDhmMEU7f4e6AWNf2okyxsFQg1/E7rKtZHbpfBAK3B6KqVd7VYM8MJy7mPd\n"
"y1129gjm5jDvOrIWNEGk4TAUvMf5IzoacN+4zA==\n"
"-----END CERTIFICATE-----\n"
);
const std::string mPemChildCert(
"Certificate:\n"
" Data:\n"
" Version: 3 (0x2)\n"
" Serial Number: 4096 (0x1000)\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" Issuer: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n"
" Validity\n"
" Not Before: May 22 22:58:15 2018 GMT\n"
" Not After : Jul 19 22:58:15 2024 GMT\n"
" Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Server Cert/emailAddress=noreply@lindenlab.com\n"
" Subject Public Key Info:\n"
" Public Key Algorithm: rsaEncryption\n"
" Public-Key: (2048 bit)\n"
" Modulus:\n"
" 00:bf:a1:1c:76:82:4a:10:1d:25:0e:02:e2:7a:64:\n"
" 54:c7:94:c5:c0:98:d5:35:f3:cb:cb:30:ba:31:9c:\n"
" bd:4c:2f:4a:4e:24:03:4b:87:5c:c1:5c:fe:d9:89:\n"
" 3b:cb:01:bc:eb:a5:b7:78:dc:b3:58:e5:78:a7:15:\n"
" 34:50:30:aa:16:3a:b2:94:17:6d:1e:7f:b2:70:1e:\n"
" 96:41:bb:1d:e3:22:80:fa:dc:00:6a:fb:34:3e:67:\n"
" e7:c2:21:2f:1b:d3:af:04:49:91:eb:bb:60:e0:26:\n"
" 52:75:28:8a:08:5b:91:56:4e:51:50:40:51:70:af:\n"
" cb:80:66:c8:59:e9:e2:48:a8:62:d0:26:67:80:0a:\n"
" 12:16:d1:f6:15:9e:1f:f5:92:37:f3:c9:2f:03:9e:\n"
" 22:f6:60:5a:76:45:8c:01:2c:99:54:72:19:db:b7:\n"
" 72:e6:5a:69:f3:e9:31:65:5d:0f:c7:5c:9c:17:29:\n"
" 71:14:7f:db:47:c9:1e:65:a2:41:b0:2f:14:17:ec:\n"
" 4b:25:f2:43:8f:b4:a3:8d:37:1a:07:34:b3:29:bb:\n"
" 8a:44:8e:84:08:a2:1b:76:7a:cb:c2:39:2f:6e:e3:\n"
" fc:d6:91:b5:1f:ce:58:91:57:70:35:6e:25:a9:48:\n"
" 0e:07:cf:4e:dd:16:42:65:cf:8a:42:b3:27:e6:fe:\n"
" 6a:e3\n"
" Exponent: 65537 (0x10001)\n"
" X509v3 extensions:\n"
" X509v3 Basic Constraints: \n"
" CA:FALSE\n"
" Netscape Cert Type: \n"
" SSL Server\n"
" Netscape Comment: \n"
" OpenSSL Generated Server Certificate\n"
" X509v3 Subject Key Identifier: \n"
" BB:59:9F:DE:6B:51:A7:6C:B3:6D:5B:8B:42:F7:B1:65:77:17:A4:E4\n"
" X509v3 Authority Key Identifier: \n"
" keyid:83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n"
" DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab/OU=Second Life Engineering/CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"
" serial:10:00\n"
"\n"
" X509v3 Key Usage: critical\n"
" Digital Signature, Key Encipherment\n"
" X509v3 Extended Key Usage: \n"
" TLS Web Server Authentication\n"
" Signature Algorithm: sha256WithRSAEncryption\n"
" 18:a6:58:55:9b:d4:af:7d:8a:27:d3:28:3a:4c:4b:42:4e:f0:\n"
" 30:d6:d9:95:11:48:12:0a:96:40:d9:2b:21:39:c5:d4:8d:e5:\n"
" 10:bc:68:78:69:0b:9f:15:4a:0b:f1:ab:99:45:0c:20:5f:27:\n"
" df:e7:14:2d:4a:30:f2:c2:8d:37:73:36:1a:27:55:5a:08:5f:\n"
" 71:a1:5e:05:83:b2:59:fe:02:5e:d7:4a:30:15:23:58:04:cf:\n"
" 48:cc:b0:71:88:9c:6b:57:f0:04:0a:d3:a0:64:6b:ee:f3:5f:\n"
" ea:ac:e1:2b:b9:7f:79:b8:db:ce:72:48:72:db:c8:5c:38:72:\n"
" 31:55:d0:ff:6b:bd:73:23:a7:30:18:5d:ed:47:18:0a:67:8e:\n"
" 53:32:0e:99:9b:96:72:45:7f:c6:00:2c:5d:1a:97:53:75:3a:\n"
" 0b:49:3d:3a:00:37:14:67:0c:28:97:34:87:aa:c5:32:e4:ae:\n"
" 34:83:12:4a:10:f7:0e:74:d4:5f:73:bd:ef:0c:b7:d8:0a:7d:\n"
" 8e:8d:5a:48:bd:f4:8e:7b:f9:4a:15:3b:61:c9:5e:40:59:6e:\n"
" c7:a8:a4:02:28:72:c5:54:8c:77:f4:55:a7:86:c0:38:a0:68:\n"
" 19:da:0f:72:5a:a9:7e:69:9f:9c:3a:d6:66:aa:e1:f4:fd:f9:\n"
" b8:4b:6c:71:9e:f0:38:02:c7:6a:9e:dc:e6:fb:ef:23:59:4f:\n"
" 5c:84:0a:df:ea:86:1f:fd:0e:5c:fa:c4:e5:50:1c:10:cf:89:\n"
" 4e:08:0e:4c:4b:61:1a:49:12:f7:e9:4b:17:71:43:7b:6d:b6:\n"
" b5:9f:d4:3b:c7:88:53:48:63:b6:00:80:8f:49:0a:c5:7e:58:\n"
" ac:78:d8:b9:06:b0:bc:86:e2:2e:48:5b:c3:24:fa:aa:72:d8:\n"
" ec:f6:c7:91:9f:0f:c8:b5:fd:2b:b2:a7:bc:2f:40:20:2b:47:\n"
" e0:d1:1d:94:52:6f:6b:be:12:b6:8c:dc:11:db:71:e6:19:ef:\n"
" a8:71:8b:ad:d3:32:c0:1c:a4:3f:b3:0f:af:e5:50:e1:ff:41:\n"
" a4:b7:6f:57:71:af:fd:16:4c:e8:24:b3:99:1b:cf:12:8f:43:\n"
" 05:80:ba:18:19:0a:a5:ec:49:81:41:4c:7e:28:b2:21:f2:59:\n"
" 6e:4a:ed:de:f9:fa:99:85:60:1f:e6:c2:42:5c:08:00:3c:84:\n"
" 06:a9:24:d4:cf:7b:6e:1b:59:1d:f4:70:16:03:a1:e0:0b:00:\n"
" 95:5c:39:03:fc:9d:1c:8e:f7:59:0c:61:47:f6:7f:07:22:48:\n"
" 83:40:ac:e1:98:5f:c7:be:05:d5:29:2b:bf:0d:03:0e:e9:5e:\n"
" 2b:dd:09:18:fe:5e:30:61\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIGbjCCBFagAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAlVT\n"
"MRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQKDApMaW5kZW4gTGFiMSAwHgYD\n"
"VQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEpMCcGA1UEAwwgSW50ZWdyYXRp\n"
"b24gVGVzdCBJbnRlcm1lZGlhdGUgQ0ExJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlA\n"
"bGluZGVubGFiLmNvbTAeFw0xODA1MjIyMjU4MTVaFw0yNDA3MTkyMjU4MTVaMIG+\n"
"MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n"
"IEZyYW5jaXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25k\n"
"IExpZmUgRW5naW5lZXJpbmcxJTAjBgNVBAMMHEludGVncmF0aW9uIFRlc3QgU2Vy\n"
"dmVyIENlcnQxJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlAbGluZGVubGFiLmNvbTCC\n"
"ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL+hHHaCShAdJQ4C4npkVMeU\n"
"xcCY1TXzy8swujGcvUwvSk4kA0uHXMFc/tmJO8sBvOult3jcs1jleKcVNFAwqhY6\n"
"spQXbR5/snAelkG7HeMigPrcAGr7ND5n58IhLxvTrwRJkeu7YOAmUnUoighbkVZO\n"
"UVBAUXCvy4BmyFnp4kioYtAmZ4AKEhbR9hWeH/WSN/PJLwOeIvZgWnZFjAEsmVRy\n"
"Gdu3cuZaafPpMWVdD8dcnBcpcRR/20fJHmWiQbAvFBfsSyXyQ4+0o403Ggc0sym7\n"
"ikSOhAiiG3Z6y8I5L27j/NaRtR/OWJFXcDVuJalIDgfPTt0WQmXPikKzJ+b+auMC\n"
"AwEAAaOCAYYwggGCMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCG\n"
"SAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUw\n"
"HQYDVR0OBBYEFLtZn95rUadss21bi0L3sWV3F6TkMIHoBgNVHSMEgeAwgd2AFIMh\n"
"3uzAeQNtHoPz5Zcp1VrAlkD6oYHApIG9MIG6MQswCQYDVQQGEwJVUzETMBEGA1UE\n"
"CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK\n"
"TGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUgRW5naW5lZXJpbmcxITAf\n"
"BgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEkMCIGCSqGSIb3DQEJARYV\n"
"bm9yZXBseUBsaW5kZW5sYWIuY29tggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l\n"
"BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBABimWFWb1K99iifTKDpM\n"
"S0JO8DDW2ZURSBIKlkDZKyE5xdSN5RC8aHhpC58VSgvxq5lFDCBfJ9/nFC1KMPLC\n"
"jTdzNhonVVoIX3GhXgWDsln+Al7XSjAVI1gEz0jMsHGInGtX8AQK06Bka+7zX+qs\n"
"4Su5f3m4285ySHLbyFw4cjFV0P9rvXMjpzAYXe1HGApnjlMyDpmblnJFf8YALF0a\n"
"l1N1OgtJPToANxRnDCiXNIeqxTLkrjSDEkoQ9w501F9zve8Mt9gKfY6NWki99I57\n"
"+UoVO2HJXkBZbseopAIocsVUjHf0VaeGwDigaBnaD3JaqX5pn5w61maq4fT9+bhL\n"
"bHGe8DgCx2qe3Ob77yNZT1yECt/qhh/9Dlz6xOVQHBDPiU4IDkxLYRpJEvfpSxdx\n"
"Q3tttrWf1DvHiFNIY7YAgI9JCsV+WKx42LkGsLyG4i5IW8Mk+qpy2Oz2x5GfD8i1\n"
"/Suyp7wvQCArR+DRHZRSb2u+EraM3BHbceYZ76hxi63TMsAcpD+zD6/lUOH/QaS3\n"
"b1dxr/0WTOgks5kbzxKPQwWAuhgZCqXsSYFBTH4osiHyWW5K7d75+pmFYB/mwkJc\n"
"CAA8hAapJNTPe24bWR30cBYDoeALAJVcOQP8nRyO91kMYUf2fwciSINArOGYX8e+\n"
"BdUpK78NAw7pXivdCRj+XjBh\n"
"-----END CERTIFICATE-----\n"
);
// Test wrapper declaration : wrapping nothing for the moment
struct sechandler_basic_test
{
X509 *mX509TestCert, *mX509RootCert, *mX509IntermediateCert, *mX509ChildCert;
LLSD mValidationDate;
sechandler_basic_test()
{
LLMachineID::init();
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
ERR_load_crypto_strings();
gFirstName = "";
gLastName = "";
mValidationDate[CERT_VALIDATION_DATE] = LLDate("2017-04-11T00:00:00.00Z");
LLFile::remove("test_password.dat");
LLFile::remove("sechandler_settings.tmp");
mX509TestCert = NULL;
mX509RootCert = NULL;
mX509IntermediateCert = NULL;
mX509ChildCert = NULL;
// Read each of the 4 Pem certs and store in mX509*Cert pointers
BIO * validation_bio;
validation_bio = BIO_new_mem_buf((void*)mPemTestCert.c_str(), mPemTestCert.length());
PEM_read_bio_X509(validation_bio, &mX509TestCert, 0, NULL);
BIO_free(validation_bio);
validation_bio = BIO_new_mem_buf((void*)mPemRootCert.c_str(), mPemRootCert.length());
PEM_read_bio_X509(validation_bio, &mX509RootCert, 0, NULL);
BIO_free(validation_bio);
validation_bio = BIO_new_mem_buf((void*)mPemIntermediateCert.c_str(), mPemIntermediateCert.length());
PEM_read_bio_X509(validation_bio, &mX509IntermediateCert, 0, NULL);
BIO_free(validation_bio);
validation_bio = BIO_new_mem_buf((void*)mPemChildCert.c_str(), mPemChildCert.length());
PEM_read_bio_X509(validation_bio, &mX509ChildCert, 0, NULL);
BIO_free(validation_bio);
}
~sechandler_basic_test()
{
LLFile::remove("test_password.dat");
LLFile::remove("sechandler_settings.tmp");
LLFile::remove("mycertstore.pem");
X509_free(mX509TestCert);
X509_free(mX509RootCert);
X509_free(mX509IntermediateCert);
X509_free(mX509ChildCert);
}
};
// Tut templating thingamagic: test group, object and test instance
typedef test_group<sechandler_basic_test> sechandler_basic_test_factory;
typedef sechandler_basic_test_factory::object sechandler_basic_test_object;
tut::sechandler_basic_test_factory tut_test("LLSecHandler");
// ---------------------------------------------------------------------------------------
// Test functions
// ---------------------------------------------------------------------------------------
// test cert data retrieval
template<> template<>
void sechandler_basic_test_object::test<1>()
{
try
{
LLPointer<LLBasicCertificate> test_cert(new LLBasicCertificate(mPemTestCert, &mValidationDate));
LL_INFOS() << "ok" << LL_ENDL;
}
catch (LLCertException& cert_exception)
{
LL_INFOS() << "cert ex: " << cert_exception.getCertData() << LL_ENDL;
fail("cert exception");
}
catch (...)
{
LOG_UNHANDLED_EXCEPTION("test 1");
fail("other exception");
}
}
template<> template<>
void sechandler_basic_test_object::test<2>()
{
LLPointer<LLCertificate> test_cert(new LLBasicCertificate(mPemChildCert, &mValidationDate));
LLSD llsd_cert;
test_cert->getLLSD(llsd_cert);
//std::ostringstream llsd_value;
//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(llsd_cert) << std::endl;
LL_DEBUGS() << "test 1 cert " << llsd_cert << LL_ENDL;
ensure_equals("Issuer Name/commonName", (std::string)llsd_cert["issuer_name"]["commonName"], "Integration Test Intermediate CA");
ensure_equals("Issuer Name/countryName", (std::string)llsd_cert["issuer_name"]["countryName"], "US");
ensure_equals("Issuer Name/state", (std::string)llsd_cert["issuer_name"]["stateOrProvinceName"], "California");
ensure_equals("Issuer Name/org name", (std::string)llsd_cert["issuer_name"]["organizationName"], "Linden Lab");
ensure_equals("Issuer Name/org unit", (std::string)llsd_cert["issuer_name"]["organizationalUnitName"], "Second Life Engineering");
ensure_equals("Issuer name string", (std::string)llsd_cert["issuer_name_string"],
"emailAddress=noreply@lindenlab.com,CN=Integration Test Intermediate CA,OU=Second Life Engineering,O=Linden Lab,ST=California,C=US");
ensure_equals("subject Name/commonName", (std::string)llsd_cert["subject_name"]["commonName"],
"Integration Test Server Cert");
ensure_equals("subject Name/countryName", (std::string)llsd_cert["subject_name"]["countryName"], "US");
ensure_equals("subject Name/state", (std::string)llsd_cert["subject_name"]["stateOrProvinceName"], "California");
ensure_equals("subject Name/localityName", (std::string)llsd_cert["subject_name"]["localityName"], "San Francisco");
ensure_equals("subject Name/org name", (std::string)llsd_cert["subject_name"]["organizationName"], "Linden Lab");
ensure_equals("subjectName/org unit",
(std::string)llsd_cert["subject_name"]["organizationalUnitName"], "Second Life Engineering");
ensure_equals("subject name string",
(std::string)llsd_cert["subject_name_string"],
"emailAddress=noreply@lindenlab.com,CN=Integration Test Server Cert,OU=Second Life Engineering,O=Linden Lab,L=San Francisco,ST=California,C=US");
ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "1000");
ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2018-05-22T22:58:15Z");
ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2024-07-19T22:58:15Z");
LLSD expectedKeyUsage = LLSD::emptyArray();
expectedKeyUsage.append(LLSD((std::string)"digitalSignature"));
expectedKeyUsage.append(LLSD((std::string)"keyEncipherment"));
ensure("key usage", valueCompareLLSD(llsd_cert["keyUsage"], expectedKeyUsage));
ensure_equals("basic constraints", llsd_cert["basicConstraints"]["CA"].asInteger(), 0);
ensure("x509 is equal", !X509_cmp(mX509ChildCert, test_cert->getOpenSSLX509()));
}
// test protected data
template<> template<>
void sechandler_basic_test_object::test<3>()
{
std::string protected_data = "sUSh3wj77NG9oAMyt3XIhaej3KLZhLZWFZvI6rIGmwUUOmmelrRg0NI9rkOj8ZDpTPxpwToaBT5u"
"GQhakdaGLJznr9bHr4/6HIC1bouKj4n2rs4TL6j2WSjto114QdlNfLsE8cbbE+ghww58g8SeyLQO"
"nyzXoz+/PBz0HD5SMFDuObccoPW24gmqYySz8YoEWhSwO0pUtEEqOjVRsAJgF5wLAtJZDeuilGsq"
"4ZT9Y4wZ9Rh8nnF3fDUL6IGamHe1ClXM1jgBu10F6UMhZbnH4C3aJ2E9+LiOntU+l3iCb2MpkEpr"
"82r2ZAMwIrpnirL/xoYoyz7MJQYwUuMvBPToZJrxNSsjI+S2Z+I3iEJAELMAAA==";
std::vector<U8> binary_data(apr_base64_decode_len(protected_data.c_str()));
apr_base64_decode_binary(&binary_data[0], protected_data.c_str());
LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
cipher.decrypt(&binary_data[0], 16);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher2(unique_id, sizeof(unique_id));
cipher2.encrypt(&binary_data[0], 16);
std::ofstream temp_file("sechandler_settings.tmp", std::ofstream::binary);
temp_file.write((const char *)&binary_data[0], binary_data.size());
temp_file.close();
LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp",
"test_password.dat");
handler->init();
// data retrieval for existing data
LLSD data = handler->getProtectedData("test_data_type", "test_data_id");
ensure_equals("retrieve existing data1", (std::string)data["data1"], "test_data_1");
ensure_equals("retrieve existing data2", (std::string)data["data2"], "test_data_2");
ensure_equals("retrieve existing data3", (std::string)data["data3"]["elem1"], "test element1");
// data storage
LLSD store_data = LLSD::emptyMap();
store_data["store_data1"] = "test_store_data1";
store_data["store_data2"] = 27;
store_data["store_data3"] = LLSD::emptyMap();
store_data["store_data3"]["subelem1"] = "test_subelem1";
handler->setProtectedData("test_data_type", "test_data_id1", store_data);
data = handler->getProtectedData("test_data_type", "test_data_id");
data = handler->getProtectedData("test_data_type", "test_data_id");
// verify no overwrite of existing data
ensure_equals("verify no overwrite 1", (std::string)data["data1"], "test_data_1");
ensure_equals("verify no overwrite 2", (std::string)data["data2"], "test_data_2");
ensure_equals("verify no overwrite 3", (std::string)data["data3"]["elem1"], "test element1");
// verify written data is good
data = handler->getProtectedData("test_data_type", "test_data_id1");
ensure_equals("verify stored data1", (std::string)data["store_data1"], "test_store_data1");
ensure_equals("verify stored data2", (int)data["store_data2"], 27);
ensure_equals("verify stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1");
// verify overwrite works
handler->setProtectedData("test_data_type", "test_data_id", store_data);
data = handler->getProtectedData("test_data_type", "test_data_id");
ensure_equals("verify overwrite stored data1", (std::string)data["store_data1"], "test_store_data1");
ensure_equals("verify overwrite stored data2", (int)data["store_data2"], 27);
ensure_equals("verify overwrite stored data3", (std::string)data["store_data3"]["subelem1"], "test_subelem1");
// verify other datatype doesn't conflict
store_data["store_data3"] = "test_store_data3";
store_data["store_data4"] = 28;
store_data["store_data5"] = LLSD::emptyMap();
store_data["store_data5"]["subelem2"] = "test_subelem2";
handler->setProtectedData("test_data_type1", "test_data_id", store_data);
data = handler->getProtectedData("test_data_type1", "test_data_id");
ensure_equals("verify datatype stored data3", (std::string)data["store_data3"], "test_store_data3");
ensure_equals("verify datatype stored data4", (int)data["store_data4"], 28);
ensure_equals("verify datatype stored data5", (std::string)data["store_data5"]["subelem2"], "test_subelem2");
// test data not found
data = handler->getProtectedData("test_data_type1", "test_data_not_found");
ensure("not found", data.isUndefined());
// cause a 'write' by using 'LLPointer' to delete then instantiate a handler
handler = NULL;
handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
handler->init();
data = handler->getProtectedData("test_data_type1", "test_data_id");
ensure_equals("verify datatype stored data3a", (std::string)data["store_data3"], "test_store_data3");
ensure_equals("verify datatype stored data4a", (int)data["store_data4"], 28);
ensure_equals("verify datatype stored data5a", (std::string)data["store_data5"]["subelem2"], "test_subelem2");
// rewrite the initial file to verify reloads
handler = NULL;
std::ofstream temp_file2("sechandler_settings.tmp", std::ofstream::binary);
temp_file2.write((const char *)&binary_data[0], binary_data.size());
temp_file2.close();
// cause a 'write'
handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
handler->init();
data = handler->getProtectedData("test_data_type1", "test_data_id");
ensure("not found", data.isUndefined());
handler->deleteProtectedData("test_data_type", "test_data_id");
ensure("Deleted data not found", handler->getProtectedData("test_data_type", "test_data_id").isUndefined());
LLFile::remove("sechandler_settings.tmp");
handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
handler->init();
data = handler->getProtectedData("test_data_type1", "test_data_id");
ensure("not found", data.isUndefined());
handler = NULL;
ensure(LLFile::isfile("sechandler_settings.tmp"));
}
// test credenitals
template<> template<>
void sechandler_basic_test_object::test<4>()
{
LLPointer<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat");
handler->init();
LLSD my_id = LLSD::emptyMap();
LLSD my_authenticator = LLSD::emptyMap();
my_id["type"] = "test_type";
my_id["username"] = "testuser@lindenlab.com";
my_authenticator["type"] = "test_auth";
my_authenticator["creds"] = "12345";
// test creation of credentials
LLPointer<LLCredential> my_cred = handler->createCredential("my_grid", my_id, my_authenticator);
// test retrieval of credential components
ensure_equals("basic credential creation: identifier", my_id, my_cred->getIdentifier());
ensure_equals("basic credential creation: authenticator", my_authenticator, my_cred->getAuthenticator());
ensure_equals("basic credential creation: grid", "my_grid", my_cred->getGrid());
// test setting/overwriting of credential components
my_id["first_name"] = "firstname";
my_id.erase("username");
my_authenticator.erase("creds");
my_authenticator["hash"] = "6563245";
my_cred->setCredentialData(my_id, my_authenticator);
ensure_equals("set credential data: identifier", my_id, my_cred->getIdentifier());
ensure_equals("set credential data: authenticator", my_authenticator, my_cred->getAuthenticator());
ensure_equals("set credential data: grid", "my_grid", my_cred->getGrid());
// test loading of a credential, that hasn't been saved, without
// any legacy saved credential data
LLPointer<LLCredential> my_new_cred = handler->loadCredential("my_grid2");
ensure("unknown credential load test", my_new_cred->getIdentifier().isMap());
ensure("unknown credential load test", !my_new_cred->getIdentifier().has("type"));
ensure("unknown credential load test", my_new_cred->getAuthenticator().isMap());
ensure("unknown credential load test", !my_new_cred->getAuthenticator().has("type"));
// test saving of a credential
handler->saveCredential(my_cred, true);
// test loading of a known credential
my_new_cred = handler->loadCredential("my_grid");
ensure_equals("load a known credential: identifier", my_id, my_new_cred->getIdentifier());
ensure_equals("load a known credential: authenticator",my_authenticator, my_new_cred->getAuthenticator());
ensure_equals("load a known credential: grid", "my_grid", my_cred->getGrid());
// test deletion of a credential
handler->deleteCredential(my_new_cred);
ensure("delete credential: identifier", my_new_cred->getIdentifier().isUndefined());
ensure("delete credentialt: authenticator", my_new_cred->getIdentifier().isUndefined());
ensure_equals("delete credential: grid", "my_grid", my_cred->getGrid());
// load unknown cred
my_new_cred = handler->loadCredential("my_grid");
ensure("deleted credential load test", my_new_cred->getIdentifier().isMap());
ensure("deleted credential load test", !my_new_cred->getIdentifier().has("type"));
ensure("deleted credential load test", my_new_cred->getAuthenticator().isMap());
ensure("deleted credential load test", !my_new_cred->getAuthenticator().has("type"));
// test loading of an unknown credential with legacy saved username, but without
// saved password
gFirstName = "myfirstname";
gLastName = "mylastname";
my_new_cred = handler->loadCredential("my_legacy_grid");
ensure_equals("legacy credential with no password: type",
(const std::string)my_new_cred->getIdentifier()["type"], "agent");
ensure_equals("legacy credential with no password: first_name",
(const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname");
ensure_equals("legacy credential with no password: last_name",
(const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname");
ensure("legacy credential with no password: no authenticator", my_new_cred->getAuthenticator().isUndefined());
// test loading of an unknown credential with legacy saved password and username
std::string hashed_password = "fSQcLG03eyIWJmkzfyYaKm81dSweLmsxeSAYKGE7fSQ=";
int length = apr_base64_decode_len(hashed_password.c_str());
std::vector<char> decoded_password(length);
apr_base64_decode(&decoded_password[0], hashed_password.c_str());
LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
cipher.decrypt((U8*)&decoded_password[0], length);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher2(unique_id, sizeof(unique_id));
cipher2.encrypt((U8*)&decoded_password[0], length);
llofstream password_file("test_password.dat", std::ofstream::binary);
password_file.write(&decoded_password[0], length);
password_file.close();
my_new_cred = handler->loadCredential("my_legacy_grid2");
ensure_equals("legacy credential with password: type",
(const std::string)my_new_cred->getIdentifier()["type"], "agent");
ensure_equals("legacy credential with password: first_name",
(const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname");
ensure_equals("legacy credential with password: last_name",
(const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname");
LLSD legacy_authenticator = my_new_cred->getAuthenticator();
ensure_equals("legacy credential with password: type",
(std::string)legacy_authenticator["type"],
"hash");
ensure_equals("legacy credential with password: algorithm",
(std::string)legacy_authenticator["algorithm"],
"md5");
ensure_equals("legacy credential with password: algorithm",
(std::string)legacy_authenticator["secret"],
"01234567890123456789012345678901");
// test creation of credentials
my_cred = handler->createCredential("mysavedgrid", my_id, my_authenticator);
// test save without saving authenticator.
handler->saveCredential(my_cred, FALSE);
my_new_cred = handler->loadCredential("mysavedgrid");
ensure_equals("saved credential without auth",
(const std::string)my_new_cred->getIdentifier()["type"], "test_type");
ensure("no authenticator values were saved", my_new_cred->getAuthenticator().isUndefined());
}
// test cert vector
template<> template<>
void sechandler_basic_test_object::test<5>()
{
// validate create from empty vector
LLPointer<LLBasicCertificateVector> test_vector = new LLBasicCertificateVector();
ensure_equals("when loading with nothing, we should result in no certs in vector", test_vector->size(), 0);
test_vector->add(new LLBasicCertificate(mPemTestCert, &mValidationDate));
ensure_equals("one element in vector", test_vector->size(), 1);
test_vector->add(new LLBasicCertificate(mPemChildCert, &mValidationDate));
ensure_equals("two elements in vector after add", test_vector->size(), 2);
// add duplicate; should be a no-op (and log at DEBUG level)
test_vector->add(new LLBasicCertificate(mPemChildCert, &mValidationDate));
ensure_equals("two elements in vector after re-add", test_vector->size(), 2);
// validate order
X509* test_cert = (*test_vector)[0]->getOpenSSLX509();
ensure("first cert added remains first cert", !X509_cmp(test_cert, mX509TestCert));
X509_free(test_cert);
test_cert = (*test_vector)[1]->getOpenSSLX509();
ensure("second cert is second cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
//
// validate iterator
//
LLBasicCertificateVector::iterator current_cert = test_vector->begin();
LLBasicCertificateVector::iterator copy_current_cert = current_cert;
// operator++(int)
ensure("validate iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[0]);
ensure("validate 2nd iterator++ element in vector is expected cert", *current_cert++ == (*test_vector)[1]);
ensure("validate end iterator++", current_cert == test_vector->end());
// copy
ensure("validate copy iterator element in vector is expected cert", *copy_current_cert == (*test_vector)[0]);
// operator--(int)
current_cert--;
ensure("validate iterator-- element in vector is expected cert", *current_cert-- == (*test_vector)[1]);
ensure("validate iterator-- element in vector is expected cert", *current_cert == (*test_vector)[0]);
ensure("begin iterator is equal", current_cert == test_vector->begin());
// operator++
ensure("validate ++iterator element in vector is expected cert", *++current_cert == (*test_vector)[1]);
ensure("end of cert vector after ++iterator", ++current_cert == test_vector->end());
// operator--
ensure("validate --iterator element in vector is expected cert", *--current_cert == (*test_vector)[1]);
ensure("validate 2nd --iterator element in vector is expected cert", *--current_cert == (*test_vector)[0]);
test_vector->erase(test_vector->begin());
ensure_equals("one element in store after remove", test_vector->size(), 1);
test_cert = (*test_vector)[0]->getOpenSSLX509();
ensure("Child cert remains", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
// validate insert
test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemIntermediateCert, &mValidationDate));
test_cert = (*test_vector)[0]->getOpenSSLX509();
ensure_equals("two elements in store after insert", test_vector->size(), 2);
ensure("validate intermediate cert was inserted at first position", !X509_cmp(test_cert, mX509IntermediateCert));
X509_free(test_cert);
test_cert = (*test_vector)[1]->getOpenSSLX509();
ensure("validate child cert still there", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
//validate find
LLSD find_info = LLSD::emptyMap();
find_info["subjectKeyIdentifier"] = "bb:59:9f:de:6b:51:a7:6c:b3:6d:5b:8b:42:f7:b1:65:77:17:a4:e4";
LLBasicCertificateVector::iterator found_cert = test_vector->find(find_info);
ensure("found some cert", found_cert != test_vector->end());
X509* found_x509 = (*found_cert).get()->getOpenSSLX509();
ensure("child cert was found", !X509_cmp(found_x509, mX509ChildCert));
X509_free(found_x509);
find_info["subjectKeyIdentifier"] = "00:00:00:00"; // bogus
current_cert =test_vector->find(find_info);
ensure("didn't find cert", current_cert == test_vector->end());
}
// test cert store
template<> template<>
void sechandler_basic_test_object::test<6>()
{
// validate load with nothing
LLFile::remove("mycertstore.pem");
LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0);
// validate load with empty file
test_store->save();
test_store = NULL;
test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_equals("when loading with nothing, we should result in no certs in store", test_store->size(), 0);
test_store=NULL;
// instantiate a cert store from a file
llofstream certstorefile("mycertstore.pem", std::ios::out);
certstorefile << mPemChildCert << std::endl << mPemTestCert << std::endl;
certstorefile.close();
// validate loaded certs
test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_equals("two elements in store", test_store->size(), 2);
// operator[]
X509* test_cert = (*test_store)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
test_cert = (*test_store)[1]->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));
X509_free(test_cert);
// validate save
LLFile::remove("mycertstore.pem");
test_store->save();
test_store = NULL;
test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_equals("two elements in store after save", test_store->size(), 2);
LLCertificateStore::iterator current_cert = test_store->begin();
test_cert = (*current_cert)->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
current_cert++;
X509_free(test_cert);
test_cert = (*current_cert)->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509TestCert));
X509_free(test_cert);
current_cert++;
ensure("end of cert store", current_cert == test_store->end());
}
// cert name wildcard matching
template<> template<>
void sechandler_basic_test_object::test<7>()
{
ensure("simple name match",
_cert_hostname_wildcard_match("foo", "foo"));
ensure("simple name match, with end period",
_cert_hostname_wildcard_match("foo.", "foo."));
ensure("simple name match, with begin period",
_cert_hostname_wildcard_match(".foo", ".foo"));
ensure("simple name match, with mismatched period cn",
_cert_hostname_wildcard_match("foo.", "foo"));
ensure("simple name match, with mismatched period hostname",
_cert_hostname_wildcard_match("foo", "foo."));
ensure("simple name match, with subdomain",
_cert_hostname_wildcard_match("foo.bar", "foo.bar"));
ensure("stutter name match",
_cert_hostname_wildcard_match("foobbbbfoo", "foo*bbbfoo"));
ensure("simple name match, with beginning wildcard",
_cert_hostname_wildcard_match("foobar", "*bar"));
ensure("simple name match, with ending wildcard",
_cert_hostname_wildcard_match("foobar", "foo*"));
ensure("simple name match, with beginning null wildcard",
_cert_hostname_wildcard_match("foobar", "*foobar"));
ensure("simple name match, with ending null wildcard",
_cert_hostname_wildcard_match("foobar", "foobar*"));
ensure("simple name match, with embedded wildcard",
_cert_hostname_wildcard_match("foobar", "f*r"));
ensure("simple name match, with embedded null wildcard",
_cert_hostname_wildcard_match("foobar", "foo*bar"));
ensure("simple name match, with dual embedded wildcard",
_cert_hostname_wildcard_match("foobar", "f*o*ar"));
ensure("simple name mismatch",
!_cert_hostname_wildcard_match("bar", "foo"));
ensure("simple name mismatch, with end period",
!_cert_hostname_wildcard_match("foobar.", "foo."));
ensure("simple name mismatch, with begin period",
!_cert_hostname_wildcard_match(".foobar", ".foo"));
ensure("simple name mismatch, with subdomain",
!_cert_hostname_wildcard_match("foobar.bar", "foo.bar"));
ensure("simple name mismatch, with beginning wildcard",
!_cert_hostname_wildcard_match("foobara", "*bar"));
ensure("simple name mismatch, with ending wildcard",
!_cert_hostname_wildcard_match("oobar", "foo*"));
ensure("simple name mismatch, with embedded wildcard",
!_cert_hostname_wildcard_match("oobar", "f*r"));
ensure("simple name mismatch, with dual embedded wildcard",
!_cert_hostname_wildcard_match("foobar", "f*d*ar"));
ensure("simple wildcard",
_cert_hostname_wildcard_match("foobar", "*"));
ensure("long domain",
_cert_hostname_wildcard_match("foo.bar.com", "foo.bar.com"));
ensure("long domain with multiple wildcards",
_cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com"));
ensure("end periods",
_cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com."));
ensure("match end period",
_cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com"));
ensure("match end period2",
_cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com."));
ensure("wildcard mismatch",
!_cert_hostname_wildcard_match("bar.com", "*.bar.com"));
ensure("wildcard match",
_cert_hostname_wildcard_match("foo.bar.com", "*.bar.com"));
ensure("wildcard match",
_cert_hostname_wildcard_match("foo.foo.bar.com", "*.bar.com"));
ensure("wildcard match",
_cert_hostname_wildcard_match("foo.foo.bar.com", "*.*.com"));
ensure("wildcard mismatch",
!_cert_hostname_wildcard_match("foo.foo.bar.com", "*.foo.com"));
}
// test cert chain
template<> template<>
void sechandler_basic_test_object::test<8>()
{
// validate create from empty chain
LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL);
ensure_equals("when loading with nothing, we should result in no certs in chain", test_chain->size(), 0);
// Single cert in the chain.
X509_STORE_CTX *test_store = X509_STORE_CTX_new();
test_store->cert = mX509ChildCert;
test_store->untrusted = NULL;
test_chain = new LLBasicCertificateChain(test_store);
X509_STORE_CTX_free(test_store);
ensure_equals("two elements in store", test_chain->size(), 1);
X509* test_cert = (*test_chain)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
// cert + CA
test_store = X509_STORE_CTX_new();
test_store->cert = mX509ChildCert;
test_store->untrusted = sk_X509_new_null();
sk_X509_push(test_store->untrusted, mX509IntermediateCert);
test_chain = new LLBasicCertificateChain(test_store);
X509_STORE_CTX_free(test_store);
ensure_equals("two elements in store", test_chain->size(), 2);
test_cert = (*test_chain)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
test_cert = (*test_chain)[1]->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));
X509_free(test_cert);
// cert + nonrelated
test_store = X509_STORE_CTX_new();
test_store->cert = mX509ChildCert;
test_store->untrusted = sk_X509_new_null();
sk_X509_push(test_store->untrusted, mX509TestCert);
test_chain = new LLBasicCertificateChain(test_store);
X509_STORE_CTX_free(test_store);
ensure_equals("two elements in store", test_chain->size(), 1);
test_cert = (*test_chain)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
// cert + CA + nonrelated
test_store = X509_STORE_CTX_new();
test_store->cert = mX509ChildCert;
test_store->untrusted = sk_X509_new_null();
sk_X509_push(test_store->untrusted, mX509IntermediateCert);
sk_X509_push(test_store->untrusted, mX509TestCert);
test_chain = new LLBasicCertificateChain(test_store);
X509_STORE_CTX_free(test_store);
ensure_equals("two elements in store", test_chain->size(), 2);
test_cert = (*test_chain)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
test_cert = (*test_chain)[1]->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));
X509_free(test_cert);
// cert + intermediate + CA
test_store = X509_STORE_CTX_new();
test_store->cert = mX509ChildCert;
test_store->untrusted = sk_X509_new_null();
sk_X509_push(test_store->untrusted, mX509IntermediateCert);
sk_X509_push(test_store->untrusted, mX509RootCert);
test_chain = new LLBasicCertificateChain(test_store);
X509_STORE_CTX_free(test_store);
ensure_equals("three elements in store", test_chain->size(), 3);
test_cert = (*test_chain)[0]->getOpenSSLX509();
ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509ChildCert));
X509_free(test_cert);
test_cert = (*test_chain)[1]->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509IntermediateCert));
X509_free(test_cert);
test_cert = (*test_chain)[2]->getOpenSSLX509();
ensure("validate second element in store is expected cert", !X509_cmp(test_cert, mX509RootCert));
X509_free(test_cert);
}
// test cert validation
template<> template<>
void sechandler_basic_test_object::test<9>()
{
// start with a trusted store with our known root cert
LLFile::remove("mycertstore.pem");
LLPointer<LLBasicCertificateStore> test_store = new LLBasicCertificateStore("mycertstore.pem");
test_store->add(new LLBasicCertificate(mX509RootCert, &mValidationDate));
LLSD validation_params;
// validate basic trust for a chain containing only the intermediate cert. (1 deep)
LLPointer<LLBasicCertificateChain> test_chain = new LLBasicCertificateChain(NULL);
test_chain->add(new LLBasicCertificate(mX509IntermediateCert, &mValidationDate));
test_store->validate(0, test_chain, validation_params);
// add the root certificate to the chain and revalidate
test_chain->add(new LLBasicCertificate(mX509RootCert, &mValidationDate));
test_store->validate(0, test_chain, validation_params);
// add the child cert at the head of the chain, and revalidate (3 deep chain)
test_chain->insert(test_chain->begin(), new LLBasicCertificate(mX509ChildCert, &mValidationDate));
test_store->validate(0, test_chain, validation_params);
// basic failure cases
test_chain = new LLBasicCertificateChain(NULL);
//validate with only the child cert in chain, but child cert was previously
// trusted
test_chain->add(new LLBasicCertificate(mX509ChildCert, &mValidationDate));
// validate without the trust flag.
test_store->validate(VALIDATION_POLICY_TRUSTED, test_chain, validation_params);
// Validate with child cert but no parent, and no parent in CA store
test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_throws("no CA, with only a child cert",
LLCertValidationTrustException,
(*test_chain)[0],
test_store->validate,
VALIDATION_POLICY_TRUSTED,
test_chain,
validation_params);
// validate without the trust flag.
test_store->validate(0, test_chain, validation_params);
// clear out the store
test_store = new LLBasicCertificateStore("mycertstore.pem");
// append the intermediate cert
test_chain->add(new LLBasicCertificate(mX509IntermediateCert, &mValidationDate));
ensure_throws("no CA, with child and intermediate certs",
LLCertValidationTrustException,
(*test_chain)[1],
test_store->validate,
VALIDATION_POLICY_TRUSTED | VALIDATION_POLICY_TRUSTED,
test_chain,
validation_params);
// validate without the trust flag
test_store->validate(0, test_chain, validation_params);
// Test time validity
LLSD child_info;
((*test_chain)[0])->getLLSD(child_info);
validation_params = LLSD::emptyMap();
validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() + 1.0);
test_store->validate(VALIDATION_POLICY_TIME | VALIDATION_POLICY_TRUSTED,
test_chain, validation_params);
validation_params = LLSD::emptyMap();
validation_params[CERT_VALIDATION_DATE] = child_info[CERT_VALID_FROM].asDate();
validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() - 1.0);
// test not yet valid
ensure_throws("Child cert not yet valid" ,
LLCertValidationExpirationException,
(*test_chain)[0],
test_store->validate,
VALIDATION_POLICY_TIME | VALIDATION_POLICY_TRUSTED,
test_chain,
validation_params);
validation_params = LLSD::emptyMap();
validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_TO].asDate().secondsSinceEpoch() + 1.0);
// test cert expired
ensure_throws("Child cert expired",
LLCertValidationExpirationException,
(*test_chain)[0],
test_store->validate,
VALIDATION_POLICY_TIME | VALIDATION_POLICY_TRUSTED,
test_chain,
validation_params);
// test SSL KU
// validate basic trust for a chain containing child and intermediate.
test_chain = new LLBasicCertificateChain(NULL);
test_chain->add(new LLBasicCertificate(mX509ChildCert, &mValidationDate));
test_chain->add(new LLBasicCertificate(mX509IntermediateCert, &mValidationDate));
test_store->validate(VALIDATION_POLICY_SSL_KU | VALIDATION_POLICY_TRUSTED,
test_chain, validation_params);
test_chain = new LLBasicCertificateChain(NULL);
test_chain->add(new LLBasicCertificate(mX509TestCert, &mValidationDate));
test_store = new LLBasicCertificateStore("mycertstore.pem");
ensure_throws("Cert doesn't have ku",
LLCertKeyUsageValidationException,
(*test_chain)[0],
test_store->validate,
VALIDATION_POLICY_SSL_KU | VALIDATION_POLICY_TRUSTED,
test_chain,
validation_params);
test_store->validate(0, test_chain, validation_params);
}
};