/** * @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 #include #include #include #include #include #include "llxorcipher.h" #include #include #include #include #include #include #include #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(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; } // ------------------------------------------------------------------------------------------- // 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" ); const std::string mPemRootCert( "Certificate:\n" " Data:\n" " Version: 3 (0x2)\n" " Serial Number:\n" " bb:28:84:73:42:18:8b:67\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: Apr 10 19:28:59 2017 GMT\n" " Not After : Apr 5 19:28:59 2037 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:af:ea:5d:a6:b3:e2:28:d6:98:48:69:4e:10:b8:\n" " 03:3e:5c:6b:af:e3:d6:f5:e6:1e:b5:6e:77:f0:eb:\n" " 9c:72:2a:ba:f0:9e:f9:a9:d3:7f:9d:64:5c:a5:f2:\n" " 16:99:7c:96:67:69:aa:f1:3e:27:b6:03:c3:f6:8e:\n" " c1:f9:01:3e:35:04:bf:a4:ff:12:78:77:4b:39:e7:\n" " e4:93:09:e7:74:b3:3a:07:47:a2:9c:d2:1d:8c:e8:\n" " 77:d9:c2:1c:4e:eb:51:dd:28:82:d4:e0:22:6d:32:\n" " 4a:2e:25:53:b1:46:ff:49:18:99:8d:d6:ad:db:16:\n" " a5:0d:4a:d1:7c:19:d6:c7:08:7e:d2:90:1f:f9:e1:\n" " 9c:54:bd:bd:c4:75:4f:10:01:78:09:35:5a:f2:2f:\n" " e5:42:36:76:17:cf:42:c9:ab:ef:aa:23:1e:50:3d:\n" " f2:9d:17:d1:d0:e9:6c:94:8e:a8:5d:d1:a1:8b:13:\n" " be:45:cc:77:6b:cb:4b:ad:23:87:1d:16:4a:ac:9d:\n" " e2:b8:07:c4:17:2b:53:ca:87:7b:81:dd:ad:5c:0a:\n" " 87:00:8a:87:ae:84:cb:81:e2:9f:75:49:2b:e5:b7:\n" " 78:63:be:68:fd:2f:f1:ee:10:f9:51:ef:7f:f1:59:\n" " f1:43:8d:c3:6d:33:29:4a:e5:25:cb:e1:0f:2a:e7:\n" " e5:8a:92:cf:5e:56:25:79:92:5e:70:d7:5f:de:55:\n" " a5:09:77:cf:06:26:62:2d:f6:86:a8:39:02:1d:0b:\n" " 2d:d6:06:d1:68:2e:03:cf:7f:a5:2a:bb:b2:f5:48:\n" " 22:57:bc:1a:18:f0:f9:33:99:f7:20:b7:ac:b7:06:\n" " 01:5d:0b:62:7e:83:f0:00:a0:96:51:9b:0d:1d:23:\n" " c5:62:b9:27:ba:f8:bd:16:45:cf:13:31:79:6d:5f:\n" " a9:8b:59:f5:74:97:30:ac:a8:e8:05:fa:72:e5:f0:\n" " c7:33:8d:20:3d:4c:f3:6b:8e:43:3e:0e:51:9a:2e:\n" " e2:1d:e6:29:f2:d7:bc:a2:5d:54:e8:90:d3:07:20:\n" " b0:6e:71:3f:13:ef:c3:7e:9a:cb:57:83:1b:f6:32:\n" " 82:65:cd:69:73:9c:ab:95:76:97:47:2f:ab:b5:3c:\n" " eb:90:a9:5c:0c:03:24:02:0f:3a:00:08:37:ee:b4:\n" " e9:21:af:92:cd:a2:49:fe:d5:f3:8f:89:5d:2b:53:\n" " 66:cf:bc:78:d0:37:76:b8:16:d5:8d:21:bf:8f:98:\n" " b5:43:29:a1:32:ec:8c:58:9b:6b:3a:52:12:89:d1:\n" " 3f:63:01:5f:e5:1b:d2:be:75:d9:65:29:9e:12:a1:\n" " c4:de:3a:a9:25:94:94:32:d7:e8:ca:d3:02:9b:2f:\n" " 92:9a:11\n" " Exponent: 65537 (0x10001)\n" " X509v3 extensions:\n" " X509v3 Subject Key Identifier: \n" " CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\n" " X509v3 Authority Key Identifier: \n" " keyid:CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\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" " 68:b8:c5:d6:dd:e2:2f:5d:29:0b:aa:9f:10:66:88:fd:61:5d:\n" " 3a:0a:e0:aa:29:7f:42:4f:db:86:57:c3:96:e3:97:ff:bd:e7:\n" " 1e:c5:4d:00:87:64:3c:80:68:d6:f9:61:00:47:5e:f1:92:7f:\n" " 6f:0c:c7:8a:87:2b:b3:10:ff:22:8c:0a:8f:9f:5d:14:88:90:\n" " 52:12:a0:32:29:ea:8c:21:90:ed:0c:6a:70:26:43:81:bb:6e:\n" " e2:36:4f:72:10:36:87:61:5d:27:f6:19:d9:83:ad:4b:51:7f:\n" " 5c:33:64:fd:2e:ac:86:80:95:bc:12:c6:26:02:06:9a:46:8b:\n" " 76:d9:89:e4:d6:02:bc:34:7c:f5:9a:51:e1:14:42:c9:7e:68:\n" " 16:be:b3:50:e1:42:4b:05:32:8c:d0:2d:44:df:3e:d2:86:a7:\n" " 89:20:b6:ee:bd:c8:dd:ad:f9:96:a2:1b:84:ad:51:87:23:66:\n" " c0:fa:09:df:c0:d1:72:5e:a8:28:60:3f:6d:75:1d:6b:bc:a6:\n" " d1:10:d7:be:d9:ac:26:b4:df:58:10:6e:09:33:6b:42:c8:79:\n" " f5:38:53:4d:56:11:15:b8:39:2c:97:e4:7e:a9:63:b7:9a:b4:\n" " b1:ab:7d:4c:3e:80:97:47:f8:dd:2e:74:e2:43:ad:6c:b4:88:\n" " 26:2c:1f:f2:88:ab:49:35:bc:65:27:db:59:c2:e6:1a:e5:ad:\n" " f1:c3:44:fb:92:8a:1c:0e:b5:11:7a:00:26:90:e7:73:ee:c0:\n" " 8b:d6:b8:fd:ec:e7:80:a7:d2:6f:68:8c:bc:4d:4c:90:20:97:\n" " 85:33:7e:03:1b:88:8a:4d:5e:3c:00:f7:78:ec:2d:80:ec:09:\n" " 37:27:50:62:54:da:48:64:c9:30:1c:8a:3e:de:08:82:60:8b:\n" " 19:da:e2:a7:19:fb:0e:1f:95:b7:cd:1c:c2:cb:07:06:97:c0:\n" " 03:65:d5:a0:6f:03:66:22:11:e8:23:c9:98:83:d4:0e:a4:4b:\n" " e5:62:02:62:67:b6:bd:3c:80:92:60:20:2e:0f:0a:59:75:7e:\n" " b1:8e:0c:53:08:bd:12:09:2f:a0:53:dc:8d:46:77:68:bc:99:\n" " 7d:1d:41:66:f6:93:86:d4:64:f7:f6:5e:97:8c:4a:1d:93:38:\n" " 9c:3b:7c:4e:e9:69:e8:83:c8:0f:f3:3a:42:b5:44:d1:5f:d2:\n" " 9a:33:e3:be:1b:8f:74:23:c4:4e:ca:cf:91:38:d6:ee:67:32:\n" " 25:62:4f:a1:64:1a:b9:52:98:39:c2:a0:e0:7f:b9:51:74:78:\n" " cc:af:55:08:d6:86:11:62:80:7f:b6:39:a2:60:ee:b7:99:a6:\n" " 59:04:76:51:85:e3:ba:59\n" "-----BEGIN CERTIFICATE-----\n" "MIIGXDCCBESgAwIBAgIJALsohHNCGItnMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n" "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n" "aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n" "RW5naW5lZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEk\n" "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTE3MDQxMDE5\n" "Mjg1OVoXDTM3MDQwNTE5Mjg1OVowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n" "YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5k\n" "ZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEhMB8GA1UE\n" "AwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZIhvcNAQkBFhVub3Jl\n" "cGx5QGxpbmRlbmxhYi5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" "AQCv6l2ms+Io1phIaU4QuAM+XGuv49b15h61bnfw65xyKrrwnvmp03+dZFyl8haZ\n" "fJZnaarxPie2A8P2jsH5AT41BL+k/xJ4d0s55+STCed0szoHR6Kc0h2M6HfZwhxO\n" "61HdKILU4CJtMkouJVOxRv9JGJmN1q3bFqUNStF8GdbHCH7SkB/54ZxUvb3EdU8Q\n" "AXgJNVryL+VCNnYXz0LJq++qIx5QPfKdF9HQ6WyUjqhd0aGLE75FzHdry0utI4cd\n" "FkqsneK4B8QXK1PKh3uB3a1cCocAioeuhMuB4p91SSvlt3hjvmj9L/HuEPlR73/x\n" "WfFDjcNtMylK5SXL4Q8q5+WKks9eViV5kl5w11/eVaUJd88GJmIt9oaoOQIdCy3W\n" "BtFoLgPPf6Uqu7L1SCJXvBoY8Pkzmfcgt6y3BgFdC2J+g/AAoJZRmw0dI8ViuSe6\n" "+L0WRc8TMXltX6mLWfV0lzCsqOgF+nLl8MczjSA9TPNrjkM+DlGaLuId5iny17yi\n" "XVTokNMHILBucT8T78N+mstXgxv2MoJlzWlznKuVdpdHL6u1POuQqVwMAyQCDzoA\n" "CDfutOkhr5LNokn+1fOPiV0rU2bPvHjQN3a4FtWNIb+PmLVDKaEy7IxYm2s6UhKJ\n" "0T9jAV/lG9K+ddllKZ4SocTeOqkllJQy1+jK0wKbL5KaEQIDAQABo2MwYTAdBgNV\n" "HQ4EFgQUzE7PoOJgT77yd1Edbj7Gtlo4I6gwHwYDVR0jBBgwFoAUzE7PoOJgT77y\n" "d1Edbj7Gtlo4I6gwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJ\n" "KoZIhvcNAQELBQADggIBAGi4xdbd4i9dKQuqnxBmiP1hXToK4Kopf0JP24ZXw5bj\n" "l/+95x7FTQCHZDyAaNb5YQBHXvGSf28Mx4qHK7MQ/yKMCo+fXRSIkFISoDIp6owh\n" "kO0ManAmQ4G7buI2T3IQNodhXSf2GdmDrUtRf1wzZP0urIaAlbwSxiYCBppGi3bZ\n" "ieTWArw0fPWaUeEUQsl+aBa+s1DhQksFMozQLUTfPtKGp4kgtu69yN2t+ZaiG4St\n" "UYcjZsD6Cd/A0XJeqChgP211HWu8ptEQ177ZrCa031gQbgkza0LIefU4U01WERW4\n" "OSyX5H6pY7eatLGrfUw+gJdH+N0udOJDrWy0iCYsH/KIq0k1vGUn21nC5hrlrfHD\n" "RPuSihwOtRF6ACaQ53PuwIvWuP3s54Cn0m9ojLxNTJAgl4UzfgMbiIpNXjwA93js\n" "LYDsCTcnUGJU2khkyTAcij7eCIJgixna4qcZ+w4flbfNHMLLBwaXwANl1aBvA2Yi\n" "EegjyZiD1A6kS+ViAmJntr08gJJgIC4PCll1frGODFMIvRIJL6BT3I1Gd2i8mX0d\n" "QWb2k4bUZPf2XpeMSh2TOJw7fE7paeiDyA/zOkK1RNFf0poz474bj3QjxE7Kz5E4\n" "1u5nMiViT6FkGrlSmDnCoOB/uVF0eMyvVQjWhhFigH+2OaJg7reZplkEdlGF47pZ\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: Apr 10 20:24:52 2017 GMT\n" " Not After : Apr 8 20:24:52 2027 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:b4:9b:29:c6:22:c4:de:78:71:ed:2d:0d:90:32:\n" " fc:da:e7:8c:51:51:d2:fe:ec:e4:ca:5c:c8:5e:e0:\n" " c2:97:50:b7:c2:bd:22:91:35:4b:fd:b4:ac:20:21:\n" " b0:59:15:49:40:ff:91:9e:94:22:91:59:68:f4:ed:\n" " 84:81:8d:be:15:67:02:8e:bf:6d:86:39:7e:42:3a:\n" " ea:72:9e:ca:5b:ef:1e:96:6c:bc:30:65:c1:73:f6:\n" " 87:92:1f:24:f7:fb:39:77:b1:49:6b:27:5c:21:ba:\n" " f6:f9:1d:d5:6d:cc:58:8e:6d:d1:6b:fe:ec:89:34:\n" " 34:80:d9:03:27:d5:6f:bc:7f:c7:b3:8c:63:4d:34:\n" " 37:61:d0:f9:54:2e:2a:a8:85:03:04:22:b7:19:5b:\n" " a3:57:e4:43:a1:88:3c:42:04:c8:c3:fb:ef:0c:78:\n" " da:76:8c:e1:27:90:b1:b4:e2:c5:f3:b0:7c:0c:95:\n" " 3e:cd:ed:ee:f8:28:28:c0:ba:64:e9:b5:0a:42:f3:\n" " 8f:b1:dd:cc:41:58:a7:e7:a1:b0:2c:8e:58:55:3e:\n" " 8c:d7:db:f2:51:38:96:4f:ae:1d:8e:ae:e3:87:1a:\n" " 6c:8f:6b:3b:5a:1a:a9:49:bc:69:79:9f:28:6f:e2:\n" " ac:08:40:52:d9:87:c9:f2:27:d7:fb:62:85:5f:7f:\n" " 09:a9:64:07:7b:7a:0e:ba:a5:58:18:23:aa:b2:df:\n" " 66:77:f6:6a:ee:f7:79:18:30:12:b2:cf:60:79:af:\n" " 86:d5:b8:db:ee:a0:13:2f:80:e1:69:0d:67:14:e5:\n" " 9a:99:4c:10:2d:b1:26:6c:b8:3c:10:2f:8e:db:cb:\n" " 4a:9e:9e:50:a2:98:76:49:7b:26:c1:8f:bf:50:00:\n" " f3:af:06:98:0a:af:78:03:84:5d:56:41:e0:90:7c:\n" " 9a:a7:4d:5a:62:4d:8f:6a:cd:0e:27:c3:0c:4a:ba:\n" " 68:8c:ff:e5:b9:21:a1:60:a3:d6:7b:2c:5c:09:3d:\n" " 46:ec:4d:c9:b3:09:72:2a:ce:9b:65:f9:56:5e:6e:\n" " 2e:24:64:4a:29:7f:17:1d:92:1d:bd:6e:d7:ce:73:\n" " cf:57:23:00:1d:db:bc:77:d4:fe:b1:ea:40:34:5c:\n" " 01:94:ee:c5:6a:5e:ce:63:d2:61:c9:55:ca:13:93:\n" " e8:be:0f:00:0a:f5:6c:fc:31:e3:08:05:a4:9a:b2:\n" " 8e:85:b5:0d:fd:fd:6f:d9:10:e4:68:8a:1b:81:27:\n" " da:14:c6:08:5a:bd:f1:ec:c6:41:ac:05:d7:cc:63:\n" " 4e:e8:e0:18:7e:f3:ed:4b:60:81:dd:07:fe:5d:ad:\n" " 9a:7c:80:99:6b:06:0f:ae:f6:7d:27:27:a0:3d:05:\n" " c6:cb:dd\n" " Exponent: 65537 (0x10001)\n" " X509v3 extensions:\n" " X509v3 Subject Key Identifier: \n" " CC:57:77:7A:16:10:AE:94:99:A1:9F:AB:2F:79:42:74:D7:BE:8E:63\n" " X509v3 Authority Key Identifier: \n" " keyid:CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\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" " 41:78:c6:7d:0f:1f:0e:82:c8:7e:3a:56:7d:f7:a6:5e:c3:dc:\n" " 88:9e:e5:77:7d:c5:3c:70:2f:8a:cf:93:59:92:8f:17:04:5b:\n" " d7:d5:58:d9:cc:d6:df:77:0b:5f:db:ea:54:b6:3b:ec:d6:c4:\n" " 26:4f:63:54:06:ae:bc:5f:c3:b5:00:52:6f:2a:f6:c0:84:0b:\n" " 3e:fd:fe:82:87:82:40:5f:f7:08:5b:17:42:5e:46:60:66:77:\n" " 8f:04:2d:c0:7a:50:c2:58:42:10:fc:99:f8:30:3a:c6:ba:fa:\n" " 13:a5:ee:19:f8:4c:c8:72:37:64:16:16:ef:7e:a1:cb:df:af:\n" " 26:c5:ff:88:46:30:04:80:4c:cd:1a:56:f6:7a:4a:7b:c2:5e:\n" " 58:3b:ec:84:30:92:9c:7c:83:39:59:7f:57:f2:e7:1a:2c:ed:\n" " d9:e4:8a:1f:7e:ce:92:25:d9:78:c5:1b:f4:c6:31:10:79:3d:\n" " 8b:1d:e9:50:6d:87:2d:01:55:e0:59:c1:45:cd:ad:de:68:00:\n" " 91:9b:2a:9d:f5:aa:56:8d:48:9a:bf:aa:46:57:90:ba:4b:5d:\n" " 70:cf:1b:b2:9d:5d:21:8d:5d:b5:9e:35:96:e5:34:2b:37:52:\n" " ec:f7:03:9e:ca:e4:80:dd:1c:e3:89:e4:cd:67:5e:45:5e:88:\n" " 3b:2c:28:19:f2:ae:d2:51:7d:9b:12:5a:74:64:ea:41:b4:98:\n" " 6c:85:87:58:45:01:29:c3:0f:e7:1a:76:72:0f:d1:2a:c8:62:\n" " b6:2d:67:42:3c:0b:bf:1d:2a:ab:85:19:aa:7c:42:b3:0f:c1:\n" " 9f:1b:b7:b5:ff:19:cb:2e:d8:98:b7:99:35:a3:34:ba:31:0a:\n" " ba:59:fd:fe:72:53:3d:19:a7:36:4f:e1:a5:51:dd:ff:9f:6d:\n" " a1:22:64:01:dc:f4:8a:19:d3:5a:95:b6:a0:59:f8:28:f8:a1:\n" " bc:50:41:f5:f7:1a:42:e2:a1:aa:cc:44:36:64:ba:eb:b0:06:\n" " 05:58:2c:92:57:cd:8f:6a:ac:04:ba:4f:4d:71:4b:d4:c4:0d:\n" " 13:a2:75:de:48:c7:af:ef:1a:0d:d1:ac:94:53:68:c4:b8:2b:\n" " 88:4f:9d:78:b0:9b:a7:c4:a6:57:ad:3d:f5:1e:b4:fe:1d:d7:\n" " 42:6c:c4:c5:f6:8c:29:5c:92:3a:7d:79:f2:0d:01:ff:3c:29:\n" " 01:b9:91:59:7a:ea:e3:59:bd:67:28:3b:46:60:2c:e4:fd:61:\n" " 49:8d:3d:7f:ce:c2:d7:1d:2f:da:74:2f:38:e6:b2:f0:1f:5f:\n" " 43:dc:43:6c:e2:e3:c8:25:e6:6e:72:6b:90:50:f8:5c:9a:98:\n" " 20:0e:04:e2:b3:59:c9:3a\n" "-----BEGIN CERTIFICATE-----\n" "MIIGSDCCBDCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgboxCzAJBgNVBAYTAlVT\n" "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMw\n" "EQYDVQQKDApMaW5kZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVl\n" "cmluZzEhMB8GA1UEAwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZI\n" "hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcNMTcwNDEwMjAyNDUyWhcN\n" "MjcwNDA4MjAyNDUyWjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\n" "aWExEzARBgNVBAoMCkxpbmRlbiBMYWIxIDAeBgNVBAsMF1NlY29uZCBMaWZlIEVu\n" "Z2luZWVyaW5nMSkwJwYDVQQDDCBJbnRlZ3JhdGlvbiBUZXN0IEludGVybWVkaWF0\n" "ZSBDQTEkMCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMIICIjAN\n" "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtJspxiLE3nhx7S0NkDL82ueMUVHS\n" "/uzkylzIXuDCl1C3wr0ikTVL/bSsICGwWRVJQP+RnpQikVlo9O2EgY2+FWcCjr9t\n" "hjl+Qjrqcp7KW+8elmy8MGXBc/aHkh8k9/s5d7FJaydcIbr2+R3VbcxYjm3Ra/7s\n" "iTQ0gNkDJ9VvvH/Hs4xjTTQ3YdD5VC4qqIUDBCK3GVujV+RDoYg8QgTIw/vvDHja\n" "dozhJ5CxtOLF87B8DJU+ze3u+CgowLpk6bUKQvOPsd3MQVin56GwLI5YVT6M19vy\n" "UTiWT64djq7jhxpsj2s7WhqpSbxpeZ8ob+KsCEBS2YfJ8ifX+2KFX38JqWQHe3oO\n" "uqVYGCOqst9md/Zq7vd5GDASss9gea+G1bjb7qATL4DhaQ1nFOWamUwQLbEmbLg8\n" "EC+O28tKnp5Qoph2SXsmwY+/UADzrwaYCq94A4RdVkHgkHyap01aYk2Pas0OJ8MM\n" "SrpojP/luSGhYKPWeyxcCT1G7E3JswlyKs6bZflWXm4uJGRKKX8XHZIdvW7XznPP\n" "VyMAHdu8d9T+sepANFwBlO7Fal7OY9JhyVXKE5Povg8ACvVs/DHjCAWkmrKOhbUN\n" "/f1v2RDkaIobgSfaFMYIWr3x7MZBrAXXzGNO6OAYfvPtS2CB3Qf+Xa2afICZawYP\n" "rvZ9JyegPQXGy90CAwEAAaNmMGQwHQYDVR0OBBYEFMxXd3oWEK6UmaGfqy95QnTX\n" "vo5jMB8GA1UdIwQYMBaAFMxOz6DiYE++8ndRHW4+xrZaOCOoMBIGA1UdEwEB/wQI\n" "MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBBeMZ9\n" "Dx8Ogsh+OlZ996Zew9yInuV3fcU8cC+Kz5NZko8XBFvX1VjZzNbfdwtf2+pUtjvs\n" "1sQmT2NUBq68X8O1AFJvKvbAhAs+/f6Ch4JAX/cIWxdCXkZgZnePBC3AelDCWEIQ\n" "/Jn4MDrGuvoTpe4Z+EzIcjdkFhbvfqHL368mxf+IRjAEgEzNGlb2ekp7wl5YO+yE\n" "MJKcfIM5WX9X8ucaLO3Z5Ioffs6SJdl4xRv0xjEQeT2LHelQbYctAVXgWcFFza3e\n" "aACRmyqd9apWjUiav6pGV5C6S11wzxuynV0hjV21njWW5TQrN1Ls9wOeyuSA3Rzj\n" "ieTNZ15FXog7LCgZ8q7SUX2bElp0ZOpBtJhshYdYRQEpww/nGnZyD9EqyGK2LWdC\n" "PAu/HSqrhRmqfEKzD8GfG7e1/xnLLtiYt5k1ozS6MQq6Wf3+clM9Gac2T+GlUd3/\n" "n22hImQB3PSKGdNalbagWfgo+KG8UEH19xpC4qGqzEQ2ZLrrsAYFWCySV82PaqwE\n" "uk9NcUvUxA0TonXeSMev7xoN0ayUU2jEuCuIT514sJunxKZXrT31HrT+HddCbMTF\n" "9owpXJI6fXnyDQH/PCkBuZFZeurjWb1nKDtGYCzk/WFJjT1/zsLXHS/adC845rLw\n" "H19D3ENs4uPIJeZucmuQUPhcmpggDgTis1nJOg==\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: Apr 10 21:35:07 2017 GMT\n" " Not After : Apr 20 21:35:07 2018 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:ba:51:fb:01:57:44:2f:99:03:36:82:c0:6a:d2:\n" " 17:1d:f9:e1:49:71:b1:d1:61:c4:90:61:40:99:aa:\n" " 8e:78:99:40:c8:b7:f5:bd:78:a5:7a:c8:fb:73:33:\n" " 74:c0:78:ee:2d:55:08:78:6c:e4:e0:87:4a:34:df:\n" " 6a:25:f7:8c:86:87:0e:f6:df:00:a7:42:4f:89:e3:\n" " b1:c0:db:2a:9d:96:2b:6f:47:66:04:9b:e8:f0:18:\n" " ce:7b:4b:bf:8b:6e:24:7e:df:89:07:b4:f5:69:1d:\n" " 4e:9d:9d:c1:6b:19:51:60:56:3e:4a:b8:c2:c0:9d:\n" " 67:fb:fe:d7:73:fa:61:38:85:9b:b0:5f:80:db:a1:\n" " 57:5e:9f:90:af:7d:33:31:7d:bd:73:0b:a2:d5:1e:\n" " ff:10:a5:6d:fb:c7:55:e6:a0:81:21:f5:d7:23:e5:\n" " 9c:c1:f2:29:8a:aa:83:9f:75:9f:84:fc:65:4c:29:\n" " b3:98:1f:a6:05:0b:1a:a8:0d:68:2e:20:47:2d:06:\n" " 46:de:92:3d:eb:02:a3:b2:9f:65:66:44:7c:b0:da:\n" " 55:77:f5:5a:9f:c0:58:b6:ff:7d:31:41:72:cc:bd:\n" " 7a:1d:58:36:a8:f2:ca:6a:ca:6b:03:29:ac:94:ad:\n" " 93:f4:7a:14:52:b3:ce:61:e1:7e:6c:8f:08:ad:a9:\n" " 5d:37\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" " 6B:69:AA:91:99:C8:8C:01:72:58:D3:1F:F8:29:73:9C:98:F7:3F:5F\n" " X509v3 Authority Key Identifier: \n" " keyid:CC:57:77:7A:16:10:AE:94:99:A1:9F:AB:2F:79:42:74:D7:BE:8E:63\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" " ac:35:1a:96:65:28:7c:ed:c5:e3:b9:ef:52:9e:66:b8:63:2e:\n" " de:73:97:3c:91:d5:02:a3:62:9e:c6:5f:f7:18:ed:7f:f8:a1:\n" " 66:d2:bc:12:fd:90:b8:fb:ef:ce:fe:e4:21:5e:b9:d1:c9:65:\n" " 13:4b:d0:e5:d0:9a:9b:f3:d6:79:bd:9b:af:25:93:01:32:5c:\n" " 14:48:03:c1:f7:c6:19:80:d4:1b:f7:e3:82:59:0c:50:0d:85:\n" " 97:64:e5:4e:2f:5e:cb:b6:dc:a0:44:64:32:ba:57:ee:45:26:\n" " 58:c2:36:71:a8:90:3a:37:48:33:75:79:8e:4f:b1:2d:65:6e:\n" " 04:9f:35:28:40:97:f3:80:c1:c8:bb:b9:cd:a2:aa:42:a9:9a:\n" " c6:ab:ac:48:a4:eb:0a:17:19:a0:44:9d:8a:7f:b1:21:a1:14:\n" " ac:0f:71:e0:e8:28:07:44:8a:e7:70:c9:af:19:08:8f:be:2c:\n" " 79:af:62:af:9f:8e:d8:4a:c5:09:d5:27:1a:29:c3:2a:f1:b9:\n" " a2:df:0b:e4:22:22:4e:26:11:ad:3d:39:4c:e6:53:49:d5:65:\n" " 8c:e8:68:98:91:50:40:ff:fd:ac:ef:71:12:28:a8:b3:5f:f7:\n" " b3:26:2e:eb:f4:d0:d4:68:31:ee:4a:78:b3:85:60:37:1b:21:\n" " 2d:e9:f2:67:5a:64:17:e5:30:fc:2d:ed:59:a0:06:8d:90:ea:\n" " ba:26:2f:d8:ac:68:98:db:42:87:39:65:64:b6:08:9f:70:dc:\n" " 74:8d:ac:26:ce:8e:a7:dc:1d:41:de:82:7c:00:46:d0:23:74:\n" " b5:5a:4c:91:e4:92:11:a4:13:fd:50:05:86:89:c4:fd:11:ce:\n" " 17:44:8f:35:ea:c8:4e:8c:a5:e1:ed:62:32:ff:2f:f7:92:f3:\n" " f7:5c:d2:e7:27:d8:ff:f7:92:7d:dc:a6:ca:d9:e0:92:9d:db:\n" " 34:9e:6e:c8:f4:f1:d0:d8:30:c2:85:87:c5:f6:ed:0b:d4:b1:\n" " a6:7c:c1:cd:55:41:c0:e4:cf:06:62:31:fd:4e:b1:eb:45:71:\n" " 5b:7c:42:02:4c:ee:74:27:8a:81:11:f1:32:89:40:c9:85:03:\n" " bb:e8:73:55:53:f0:73:eb:47:68:4c:34:9a:1d:7d:cb:54:50:\n" " 59:c7:82:3e:42:5c:81:51:7a:01:71:86:a1:b0:da:e6:09:3a:\n" " 29:ee:e9:9e:58:19:d7:81:69:bd:3c:5a:02:49:6f:3c:03:0e:\n" " 4a:79:06:50:40:8a:60:11:35:6b:56:fc:34:46:52:68:ca:d3:\n" " 3a:c1:85:bc:e4:25:57:70:b4:ab:36:d8:8b:0a:6b:8d:7b:b7:\n" " 88:7d:10:33:6e:be:83:e6\n" "-----BEGIN CERTIFICATE-----\n" "MIIGbjCCBFagAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAlVT\n" "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQKDApMaW5kZW4gTGFiMSAwHgYD\n" "VQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEpMCcGA1UEAwwgSW50ZWdyYXRp\n" "b24gVGVzdCBJbnRlcm1lZGlhdGUgQ0ExJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlA\n" "bGluZGVubGFiLmNvbTAeFw0xNzA0MTAyMTM1MDdaFw0xODA0MjAyMTM1MDdaMIG+\n" "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n" "IEZyYW5jaXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25k\n" "IExpZmUgRW5naW5lZXJpbmcxJTAjBgNVBAMMHEludGVncmF0aW9uIFRlc3QgU2Vy\n" "dmVyIENlcnQxJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlAbGluZGVubGFiLmNvbTCC\n" "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpR+wFXRC+ZAzaCwGrSFx35\n" "4UlxsdFhxJBhQJmqjniZQMi39b14pXrI+3MzdMB47i1VCHhs5OCHSjTfaiX3jIaH\n" "DvbfAKdCT4njscDbKp2WK29HZgSb6PAYzntLv4tuJH7fiQe09WkdTp2dwWsZUWBW\n" "Pkq4wsCdZ/v+13P6YTiFm7BfgNuhV16fkK99MzF9vXMLotUe/xClbfvHVeaggSH1\n" "1yPlnMHyKYqqg591n4T8ZUwps5gfpgULGqgNaC4gRy0GRt6SPesCo7KfZWZEfLDa\n" "VXf1Wp/AWLb/fTFBcsy9eh1YNqjyymrKawMprJStk/R6FFKzzmHhfmyPCK2pXTcC\n" "AwEAAaOCAYYwggGCMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCG\n" "SAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUw\n" "HQYDVR0OBBYEFGtpqpGZyIwBcljTH/gpc5yY9z9fMIHoBgNVHSMEgeAwgd2AFMxX\n" "d3oWEK6UmaGfqy95QnTXvo5joYHApIG9MIG6MQswCQYDVQQGEwJVUzETMBEGA1UE\n" "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK\n" "TGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUgRW5naW5lZXJpbmcxITAf\n" "BgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEkMCIGCSqGSIb3DQEJARYV\n" "bm9yZXBseUBsaW5kZW5sYWIuY29tggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l\n" "BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAKw1GpZlKHztxeO571Ke\n" "ZrhjLt5zlzyR1QKjYp7GX/cY7X/4oWbSvBL9kLj7787+5CFeudHJZRNL0OXQmpvz\n" "1nm9m68lkwEyXBRIA8H3xhmA1Bv344JZDFANhZdk5U4vXsu23KBEZDK6V+5FJljC\n" "NnGokDo3SDN1eY5PsS1lbgSfNShAl/OAwci7uc2iqkKpmsarrEik6woXGaBEnYp/\n" "sSGhFKwPceDoKAdEiudwya8ZCI++LHmvYq+fjthKxQnVJxopwyrxuaLfC+QiIk4m\n" "Ea09OUzmU0nVZYzoaJiRUED//azvcRIoqLNf97MmLuv00NRoMe5KeLOFYDcbIS3p\n" "8mdaZBflMPwt7VmgBo2Q6romL9isaJjbQoc5ZWS2CJ9w3HSNrCbOjqfcHUHegnwA\n" "RtAjdLVaTJHkkhGkE/1QBYaJxP0RzhdEjzXqyE6MpeHtYjL/L/eS8/dc0ucn2P/3\n" "kn3cpsrZ4JKd2zSebsj08dDYMMKFh8X27QvUsaZ8wc1VQcDkzwZiMf1OsetFcVt8\n" "QgJM7nQnioER8TKJQMmFA7voc1VT8HPrR2hMNJodfctUUFnHgj5CXIFRegFxhqGw\n" "2uYJOinu6Z5YGdeBab08WgJJbzwDDkp5BlBAimARNWtW/DRGUmjK0zrBhbzkJVdw\n" "tKs22IsKa417t4h9EDNuvoPm\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_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 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 test_cert(new LLBasicCertificate(mPemChildCert, &mValidationDate)); LLSD llsd_cert; test_cert->getLLSD(llsd_cert); //std::ostringstream llsd_value; //llsd_value << LLSDOStreamer(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"], "2017-04-10T21:35:07Z"); ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2018-04-20T21:35:07Z"); 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 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 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 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 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 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 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 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"] = "6b:69:aa:91:99:c8:8c:01:72:58:d3:1f:f8:29:73:9c:98:f7:3f:5f"; 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 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 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 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 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); } };