From 658ccc3e85487f9f24ff3b5926e60d6cce7f42e0 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Wed, 7 Apr 2010 11:08:04 -0700 Subject: Re-insert backed out SLE checkin so we can fix it --- indra/newview/tests/lllogininstance_test.cpp | 115 ++- indra/newview/tests/llsecapi_test.cpp | 188 +++++ indra/newview/tests/llsechandler_basic_test.cpp | 964 ++++++++++++++++++++++++ indra/newview/tests/llslurl_test.cpp | 258 +++++++ indra/newview/tests/llviewernetwork_test.cpp | 486 ++++++++++++ 5 files changed, 1988 insertions(+), 23 deletions(-) create mode 100644 indra/newview/tests/llsecapi_test.cpp create mode 100644 indra/newview/tests/llsechandler_basic_test.cpp create mode 100644 indra/newview/tests/llslurl_test.cpp create mode 100644 indra/newview/tests/llviewernetwork_test.cpp (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index ef93586c6e..67da9f2cdf 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -10,7 +10,10 @@ // Precompiled header #include "../llviewerprecompiledheaders.h" // Own header +#include "../llsecapi.h" +#include "../llviewernetwork.h" #include "../lllogininstance.h" + // STL headers // std headers // external library headers @@ -33,7 +36,12 @@ const std::string APPVIEWER_SERIALNUMBER("appviewer_serialno"); //----------------------------------------------------------------------------- static LLEventStream gTestPump("test_pump"); +#include "../llslurl.h" +#include "../llstartup.h" +LLSLURL LLStartUp::sStartSLURL; + #include "lllogin.h" + static std::string gLoginURI; static LLSD gLoginCreds; static bool gDisconnectCalled = false; @@ -54,17 +62,68 @@ void LLLogin::disconnect() gDisconnectCalled = true; } +LLSD LLCredential::getLoginParams() +{ + LLSD result = LLSD::emptyMap(); + + // legacy credential + result["passwd"] = "$1$testpasssd"; + result["first"] = "myfirst"; + result["last"] ="mylast"; + return result; +} + //----------------------------------------------------------------------------- #include "../llviewernetwork.h" -unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {'1','2','3','4','5','6'}; +LLGridManager::~LLGridManager() +{ +} + +void LLGridManager::addGrid(LLSD& grid_data) +{ +} +LLGridManager::LLGridManager() +{ +} -LLViewerLogin::LLViewerLogin() : mGridChoice(GRID_INFO_NONE) {} -LLViewerLogin::~LLViewerLogin() {} -void LLViewerLogin::getLoginURIs(std::vector& uris) const +void LLGridManager::getLoginURIs(std::vector& uris) { uris.push_back(VIEWERLOGIN_URI); } -std::string LLViewerLogin::getGridLabel() const { return VIEWERLOGIN_GRIDLABEL; } + +void LLGridManager::addSystemGrid(const std::string& label, + const std::string& name, + const std::string& login, + const std::string& helper, + const std::string& login_page, + const std::string& login_id) +{ +} +std::map LLGridManager::getKnownGrids(bool favorite_only) +{ + std::map result; + return result; +} + +void LLGridManager::setGridChoice(const std::string& grid_name) +{ +} + +bool LLGridManager::isInProductionGrid() +{ + return false; +} + +void LLGridManager::saveFavorites() +{} +std::string LLGridManager::getSLURLBase(const std::string& grid_name) +{ + return "myslurl"; +} +std::string LLGridManager::getAppSLURLBase(const std::string& grid_name) +{ + return "myappslurl"; +} //----------------------------------------------------------------------------- #include "../llviewercontrol.h" @@ -86,10 +145,6 @@ BOOL LLControlGroup::declareString(const std::string& name, const std::string &i #include "lluicolortable.h" void LLUIColorTable::saveUserSettings(void)const {} -//----------------------------------------------------------------------------- -#include "../llurlsimstring.h" -LLURLSimString LLURLSimString::sInstance; -bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- #include "llnotifications.h" @@ -197,15 +252,29 @@ namespace tut gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); - credentials["first"] = "testfirst"; - credentials["last"] = "testlast"; - credentials["passwd"] = "testpass"; + LLSD authenticator = LLSD::emptyMap(); + LLSD identifier = LLSD::emptyMap(); + identifier["type"] = "agent"; + identifier["first_name"] = "testfirst"; + identifier["last_name"] = "testlast"; + authenticator["passwd"] = "testpass"; + agentCredential = new LLCredential(); + agentCredential->setCredentialData(identifier, authenticator); + + authenticator = LLSD::emptyMap(); + identifier = LLSD::emptyMap(); + identifier["type"] = "account"; + identifier["username"] = "testuser"; + authenticator["secret"] = "testsecret"; + accountCredential = new LLCredential(); + accountCredential->setCredentialData(identifier, authenticator); logininstance->setNotificationsInterface(¬ifications); } LLLoginInstance* logininstance; - LLSD credentials; + LLPointer agentCredential; + LLPointer accountCredential; MockNotifications notifications; }; @@ -219,7 +288,7 @@ namespace tut set_test_name("Test Simple Success And Disconnect"); // Test default connect. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -260,7 +329,7 @@ namespace tut const std::string test_uri = "testing-uri"; // Test default connect. - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); // connect should call LLLogin::connect to init gLoginURI and gLoginCreds. ensure_equals("Default connect uri", gLoginURI, "testing-uri"); @@ -282,7 +351,7 @@ namespace tut ensure("No TOS, failed auth", logininstance->authFailure()); // Start again. - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); gTestPump.post(response); // Fail for tos again. gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); @@ -294,11 +363,11 @@ namespace tut gTestPump.post(response); ensure("TOS auth failure", logininstance->authFailure()); - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); ensure_equals("Reset to default for agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), false); // Critical Message failure response. - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); response["data"]["reason"] = "critical"; // Change response to "critical message" gTestPump.post(response); @@ -312,7 +381,7 @@ namespace tut response["data"]["reason"] = "key"; // bad creds. gTestPump.post(response); ensure("TOS auth failure", logininstance->authFailure()); - logininstance->connect(test_uri, credentials); + logininstance->connect(test_uri, agentCredential); ensure_equals("Default for agree to tos", gLoginCreds["params"]["read_critical"].asBoolean(), false); } @@ -323,7 +392,7 @@ namespace tut // Part 1 - Mandatory Update, with User accepts response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -349,7 +418,7 @@ namespace tut set_test_name("Test Mandatory Update User Decline"); // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -375,7 +444,7 @@ namespace tut // Part 3 - Mandatory Update, with bogus response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); @@ -401,7 +470,7 @@ namespace tut // Part 3 - Mandatory Update, with bogus response. // Test connect with update needed. - logininstance->connect(credentials); + logininstance->connect(agentCredential); ensure_equals("Default connect uri", gLoginURI, VIEWERLOGIN_URI); diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp new file mode 100644 index 0000000000..caa1461987 --- /dev/null +++ b/indra/newview/tests/llsecapi_test.cpp @@ -0,0 +1,188 @@ +/** + * @file llsecapi_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the sec api functionality + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden LregisterSecAPIab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../llsecapi.h" +#include "../../llxml/llcontrol.h" + + +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, + const std::string& initial_val, + const std::string& comment, + BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} +std::string LLControlGroup::getString(const std::string& name) +{ + return ""; +} + + +LLControlGroup gSavedSettings("test"); +class LLSecAPIBasicHandler : public LLSecAPIHandler +{ +protected: + LLPointer mCertChain; + LLPointer mCert; + LLPointer mCertStore; + LLSD mLLSD; + +public: + LLSecAPIBasicHandler() {} + + virtual ~LLSecAPIBasicHandler() {} + + // instantiate a certificate from a pem string + virtual LLPointer getCertificate(const std::string& pem_cert) + { + return mCert; + } + + + // instiate a certificate from an openssl X509 structure + virtual LLPointer getCertificate(X509* openssl_cert) + { + return mCert; + } + + + // instantiate a chain from an X509_STORE_CTX + virtual LLPointer getCertificateChain(const X509_STORE_CTX* chain) + { + return mCertChain; + } + + // instantiate a cert store given it's id. if a persisted version + // exists, it'll be loaded. If not, one will be created (but not + // persisted) + virtual LLPointer getCertificateStore(const std::string& store_id) + { + return mCertStore; + } + + // persist data in a protected store + virtual void setProtectedData(const std::string& data_type, + const std::string& data_id, + const LLSD& data) {} + + // retrieve protected data + virtual LLSD getProtectedData(const std::string& data_type, + const std::string& data_id) + { + return mLLSD; + } + + virtual void deleteProtectedData(const std::string& data_type, + const std::string& data_id) + { + } + + virtual LLPointer createCredential(const std::string& grid, + const LLSD& identifier, + const LLSD& authenticator) + { + LLPointer cred = NULL; + return cred; + } + + virtual LLPointer loadCredential(const std::string& grid) + { + LLPointer cred = NULL; + return cred; + } + + virtual void saveCredential(LLPointer cred, bool save_authenticator) {} + + virtual void deleteCredential(LLPointer cred) {} +}; + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct secapiTest + { + + secapiTest() + { + } + ~secapiTest() + { + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group secapiTestFactory; + typedef secapiTestFactory::object secapiTestObject; + tut::secapiTestFactory tut_test("llsecapi"); + + // --------------------------------------------------------------------------------------- + // Test functions + // --------------------------------------------------------------------------------------- + // registration + template<> template<> + void secapiTestObject::test<1>() + { + // retrieve an unknown handler + + ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); + LLPointer test1_handler = new LLSecAPIBasicHandler(); + registerSecHandler("sectest1", test1_handler); + ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); + LLPointer retrieved_test1_handler = getSecHandler("sectest1"); + ensure("Retrieved sectest1 handler should be the same", + retrieved_test1_handler == test1_handler); + + // insert a second handler + LLPointer test2_handler = new LLSecAPIBasicHandler(); + registerSecHandler("sectest2", test2_handler); + ensure("'Unknown' handler should be NULL", !(BOOL)getSecHandler("unknown")); + retrieved_test1_handler = getSecHandler("sectest1"); + ensure("Retrieved sectest1 handler should be the same", + retrieved_test1_handler == test1_handler); + + LLPointer retrieved_test2_handler = getSecHandler("sectest2"); + ensure("Retrieved sectest1 handler should be the same", + retrieved_test2_handler == test2_handler); + + } +} diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp new file mode 100644 index 0000000000..236d17c591 --- /dev/null +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -0,0 +1,964 @@ +/** + * @file llsechandler_basic_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the 'basic' sec handler functions + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/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 "llxorcipher.h" +#include "apr_base64.h" +#include +#include +#include +#include +#include +#include +#include "llxorcipher.h" + +#define ensure_throws(str, exc_type, cert, func, ...) \ +try \ +{ \ +func(__VA_ARGS__); \ +fail("throws, " str); \ +} \ +catch(exc_type& except) \ +{ \ +ensure("Exception cert is incorrect for " str, except.getCert() == cert); \ +} + +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() {} +BOOL LLControlGroup::declareString(const std::string& name, + const std::string& initial_val, + const std::string& comment, + BOOL persist) {return TRUE;} +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 ""; +} + +LLSD LLCredential::getLoginParams() +{ + LLSD result = LLSD::emptyMap(); + + // legacy credential + result["passwd"] = "$1$testpasssd"; + result["first"] = "myfirst"; + result["last"] ="mylast"; + return result; +} + + + +LLControlGroup gSavedSettings("test"); +unsigned char gMACAddress[MAC_ADDRESS_BYTES] = {77,21,46,31,89,2}; + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct sechandler_basic_test + { + std::string mPemTestCert, mPemRootCert, mPemIntermediateCert, mPemChildCert; + std::string mDerFormat; + X509 *mX509TestCert, *mX509RootCert, *mX509IntermediateCert, *mX509ChildCert; + + sechandler_basic_test() + { + OpenSSL_add_all_algorithms(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); + ERR_load_crypto_strings(); + gFirstName = ""; + gLastName = ""; + LLFile::remove("test_password.dat"); + LLFile::remove("sechandler_settings.tmp"); + mPemTestCert = "-----BEGIN CERTIFICATE-----\n" + "MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx\n" + "EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h\n" + "bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy\n" + "YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp\n" + "Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy\n" + "MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG\n" + "A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt\n" + "YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD\n" + "VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB\n" + "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA\n" + "isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj\n" + "Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50\n" + "QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt\n" + "bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR\n" + "yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID\n" + "AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0\n" + "cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f\n" + "BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj\n" + "cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB\n" + "/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1\n" + "U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl\n" + "YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos\n" + "SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/\n" + "t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u\n" + "mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb\n" + "K+9A46sd33oqK8n8\n" + "-----END CERTIFICATE-----\n"; + + mPemRootCert = "-----BEGIN CERTIFICATE-----\n" + "MIIB0TCCATqgAwIBAgIJANaTqrzEvHaRMA0GCSqGSIb3DQEBBAUAMBsxGTAXBgNV\n" + "BAMTEFJveGllcyB0ZXN0IHJvb3QwHhcNMDkwNDE1MjEwNzQ3WhcNMTAwNDE1MjEw\n" + "NzQ3WjAbMRkwFwYDVQQDExBSb3hpZXMgdGVzdCByb290MIGfMA0GCSqGSIb3DQEB\n" + "AQUAA4GNADCBiQKBgQCpo5nDW6RNz9IHUVZd7Tw2XAQiBniDF4xH0N1w7sUYTiFq\n" + "21mABsnOPJD3ra+MtOsXPHcaljm661JjTD8L40v5sfEbqDUPcOw76ClrPqnuAeyT\n" + "38qk8DHku/mT8YdprevGZdVcUXQg3vosVzOL93HOOHK+u61mEEoM9W5xoNVEdQID\n" + "AQABox0wGzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQF\n" + "AAOBgQAzn0aW/+zWPmcTbvxonyiYYUr9b4SOB/quhAkT8KT4ir1dcZAXRR59+kEn\n" + "HSTu1FAodV0gvESqyobftF5hZ1XMxdJqGu//xP+YCwlv244G/0pp7KLI8ihNO2+N\n" + "lPBUJgbo++ZkhiE1jotZi9Ay0Oedh3s/AfbMZPyfpJ23ll6+BA==\n" + "-----END CERTIFICATE-----\n"; + + + + mPemIntermediateCert = "-----BEGIN CERTIFICATE-----\n" + "MIIBzzCCATigAwIBAgIBATANBgkqhkiG9w0BAQQFADAbMRkwFwYDVQQDExBSb3hp\n" + "ZXMgdGVzdCByb290MB4XDTA5MDQxNTIxMzE1NloXDTEwMDQxNTIxMzE1NlowITEf\n" + "MB0GA1UEAxMWUm94aWVzIGludGVybWVkaWF0ZSBDQTCBnzANBgkqhkiG9w0BAQEF\n" + "AAOBjQAwgYkCgYEA15MM0W1R37rx/24Q2Qkb5bSiQZxTUcQAhJ2pA8mwUucXuCVt\n" + "6ayI2TuN32nkjmsCgUkiT/bdXWp0OJo7/MXRIFeUNMCRxrpeFnxuigYEqbIXAdN6\n" + "qu/vdG2X4PRv/v9Ijrju4cBEiKIldIgOurWEIfXEsVSFP2XmFQHesF04qDcCAwEA\n" + "AaMdMBswDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEEBQAD\n" + "gYEAYljikYgak3W1jSo0vYthNHUy3lBVAKzDhpM96lY5OuXFslpCRX42zNL8X3kN\n" + "U/4IaJUVtZqx8WsUXl1eXHzBCaXCftapV4Ir6cENLIsXCdXs8paFYzN5nPJA5GYU\n" + "zWgkSEl1MEhNIc+bJW34vwi29EjrAShAhsIZ84Mt/lvD3Pc=\n" + "-----END CERTIFICATE-----\n"; + + mPemChildCert = "-----BEGIN CERTIFICATE-----\n" + "MIIB5DCCAU0CBEnm9eUwDQYJKoZIhvcNAQEEBQAwITEfMB0GA1UEAxMWUm94aWVz\n" + "IGludGVybWVkaWF0ZSBDQTAeFw0wOTA0MTYwMDAzNDlaFw0xMDA0MTYwMDAzNDla\n" + "MCAxHjAcBgNVBAMTFWVuaWFjNjMubGluZGVubGFiLmNvbTCBnzANBgkqhkiG9w0B\n" + "AQEFAAOBjQAwgYkCgYEAp9I5rofEzbjNht+9QejfnsIlEPqSxskoWKCG255TesWR\n" + "RTmw9wafHQQkJk/VIsaU4RMBYHkknGbHX2dGvMHmKZoWUPSQ/8FZz09o0Qx3TNUZ\n" + "l7KlGOD2d1c7ZxXDPqlLC6QW8DrE1/8zfwJ5cbYBXc8e7OKdSZeRrnwHyw4Q8r8C\n" + "AwEAAaMvMC0wEwYDVR0lBAwwCgYIKwYBBQUHAwEwCQYDVR0TBAIwADALBgNVHQ8E\n" + "BAMCBaAwDQYJKoZIhvcNAQEEBQADgYEAIG0M5tqYlXyMiGKPZfXy/R3M3ZZOapDk\n" + "W0dsXJYXAc35ftwtn0VYu9CNnZCcli17/d+AKhkK8a/oGPazqudjFF6WLJLTXaY9\n" + "NmhkJcOPADXkbyQPUPXzLe4YRrkEQeGhzMb4rKDQ1TKAcXfs0Y068pTpsixNSxja\n" + "NhAUUcve5Is=\n" + "-----END CERTIFICATE-----\n"; + + mDerFormat = "MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIxEzARBgNVBAoT" +"CklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25hbCBkZSBUZWNub2xvZ2lhIGRh" +"IEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJyYXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UE" +"AxMoQXV0b3JpZGFkZSBDZXJ0aWZpY2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4" +"MDBaFw0xMTExMzAyMzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9" +"MDsGA1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3JtYWNhbyAt" +"IElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYDVQQDEyhBdXRvcmlkYWRl" +"IENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB" +"CgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVAisamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma" +"/3pUpgcfNAj0vYm5gsyjQo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt" +"4CyNrY50QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYtbRhF" +"boUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbURyEeNvZneVRKAAU6o" +"uwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwIDAQABo4HSMIHPME4GA1UdIARHMEUw" +"QwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQ" +"Q2FjcmFpei5wZGYwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292" +"LmJyL0xDUmFjcmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB" +"/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1U/hgIh6OcgLA" +"fiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGlYjJe+9zd+izPRbBqXPVQA34E" +"Xcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75FosSzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQf" +"S//JYeIc7Fue2JNLd00UOSMMaiK/t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr" +"1ME7a55lFEnSeT0umlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5" +"nmPbK+9A46sd33oqK8n8"; + + mX509TestCert = NULL; + mX509RootCert = NULL; + mX509IntermediateCert = NULL; + mX509ChildCert = NULL; + + 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_basic"); + + // --------------------------------------------------------------------------------------- + // Test functions + // --------------------------------------------------------------------------------------- + // test cert data retrieval + template<> template<> + void sechandler_basic_test_object::test<1>() + + { + char buffer[4096]; + LLPointer test_cert = new LLBasicCertificate(mPemTestCert); + + ensure_equals("Resultant pem is correct", + mPemTestCert, test_cert->getPem()); + std::vector binary_cert = test_cert->getBinary(); + + apr_base64_encode(buffer, (const char *)&binary_cert[0], binary_cert.size()); + + ensure_equals("Der Format is correct", memcmp(buffer, mDerFormat.c_str(), mDerFormat.length()), 0); + + LLSD llsd_cert = test_cert->getLLSD(); + std::ostringstream llsd_value; + llsd_value << LLSDOStreamer(llsd_cert) << std::endl; + std::string llsd_cert_str = llsd_value.str(); + ensure_equals("Issuer Name/commonName", + (std::string)llsd_cert["issuer_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira"); + ensure_equals("Issure Name/countryName", (std::string)llsd_cert["issuer_name"]["countryName"], "BR"); + ensure_equals("Issuer Name/localityName", (std::string)llsd_cert["issuer_name"]["localityName"], "Brasilia"); + ensure_equals("Issuer Name/org name", (std::string)llsd_cert["issuer_name"]["organizationName"], "ICP-Brasil"); + ensure_equals("IssuerName/org unit", + (std::string)llsd_cert["issuer_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI"); + ensure_equals("IssuerName/state", (std::string)llsd_cert["issuer_name"]["stateOrProvinceName"], "DF"); + ensure_equals("Issuer name string", + (std::string)llsd_cert["issuer_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF," + "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR"); + ensure_equals("subject Name/commonName", + (std::string)llsd_cert["subject_name"]["commonName"], "Autoridade Certificadora Raiz Brasileira"); + ensure_equals("subject Name/countryName", (std::string)llsd_cert["subject_name"]["countryName"], "BR"); + ensure_equals("subject Name/localityName", (std::string)llsd_cert["subject_name"]["localityName"], "Brasilia"); + ensure_equals("subject Name/org name", (std::string)llsd_cert["subject_name"]["organizationName"], "ICP-Brasil"); + ensure_equals("subjectName/org unit", + (std::string)llsd_cert["subject_name"]["organizationalUnitName"], "Instituto Nacional de Tecnologia da Informacao - ITI"); + ensure_equals("subjectName/state", (std::string)llsd_cert["subject_name"]["stateOrProvinceName"], "DF"); + ensure_equals("subject name string", + (std::string)llsd_cert["subject_name_string"], "CN=Autoridade Certificadora Raiz Brasileira,ST=DF," + "L=Brasilia,OU=Instituto Nacional de Tecnologia da Informacao - ITI,O=ICP-Brasil,C=BR"); + + ensure_equals("md5 digest", (std::string)llsd_cert["md5_digest"], "96:89:7d:61:d1:55:2b:27:e2:5a:39:b4:2a:6c:44:6f"); + ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "04"); + // sha1 digest is giving a weird value, and I've no idea why...feh + //ensure_equals("sha1 digest", (std::string)llsd_cert["sha1_digest"], "8e:fd:ca:bc:93:e6:1e:92:5d:4d:1d:ed:18:1a:43:20:a4:67:a1:39"); + ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2001-11-30T12:58:00Z"); + ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2011-11-30T23:59:00Z"); + LLSD expectedKeyUsage = LLSD::emptyArray(); + expectedKeyUsage.append(LLSD((std::string)"certSigning")); + expectedKeyUsage.append(LLSD((std::string)"crlSigning")); + ensure("key usage", valueCompareLLSD(llsd_cert["keyUsage"], expectedKeyUsage)); + ensure("basic constraints", (bool)llsd_cert["basicConstraints"]["CA"]); + + ensure("x509 is equal", !X509_cmp(mX509TestCert, test_cert->getOpenSSLX509())); + } + + + // test protected data + template<> template<> + void sechandler_basic_test_object::test<2>() + + { + unsigned char MACAddress[MAC_ADDRESS_BYTES]; + LLUUID::getNodeID(MACAddress); + + 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); + LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES); + 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<3>() + { + 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()); + unsigned char MACAddress[MAC_ADDRESS_BYTES]; + LLUUID::getNodeID(MACAddress); + LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES); + cipher.decrypt((U8*)&decoded_password[0], length); + LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES); + 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<4>() + { + + // 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)); + ensure_equals("one element in vector", test_vector->size(), 1); + test_vector->add(new LLBasicCertificate(mPemChildCert)); + ensure_equals("two elements in vector after add", test_vector->size(), 2); + + test_vector->add(new LLBasicCertificate(mPemChildCert)); + 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("adding a duplicate 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]); + + // validate remove + // validate create from empty vector + test_vector = new LLBasicCertificateVector(); + test_vector->add(new LLBasicCertificate(mPemTestCert)); + test_vector->add(new LLBasicCertificate(mPemChildCert)); + 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("validate cert was removed", !X509_cmp(test_cert, mX509ChildCert)); + X509_free(test_cert); + + // validate insert + test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemChildCert)); + test_cert = (*test_vector)[0]->getOpenSSLX509(); + + ensure("validate cert was inserted", !X509_cmp(test_cert, mX509ChildCert)); + X509_free(test_cert); + + //validate find + LLSD find_info = LLSD::emptyMap(); + test_vector->insert(test_vector->begin(), new LLBasicCertificate(mPemRootCert)); + find_info["issuer_name"] = LLSD::emptyMap(); + find_info["issuer_name"]["commonName"] = "Roxies intermediate CA"; + find_info["md5_digest"] = "97:24:c7:4c:d4:ba:2d:0e:9c:a1:18:8e:3a:c6:1f:c3"; + current_cert = test_vector->find(find_info); + ensure("found", current_cert != test_vector->end()); + ensure("found cert", (*current_cert).get() == (*test_vector)[1].get()); + find_info["sha1_digest"] = "bad value"; + 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<5>() + { + // 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<6>() + { + 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 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("mismatch end period", + !_cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com")); + + ensure("mismatch end period2", + !_cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com.")); + } + + // test cert chain + template<> template<> + void sechandler_basic_test_object::test<7>() + { + // 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<8>() + { + // 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)); + 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)); + + test_chain->validate(0, test_store, validation_params); + + // add the root certificate to the chain and revalidate + test_chain->add(new LLBasicCertificate(mX509RootCert)); + test_chain->validate(0, test_store, 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)); + test_chain->validate(0, test_store, validation_params); + + // basic failure cases + test_chain = new LLBasicCertificateChain(NULL); + //validate with only the child cert + test_chain->add(new LLBasicCertificate(mX509ChildCert)); + ensure_throws("no CA, with only a child cert", + LLCertValidationTrustException, + (*test_chain)[0], + test_chain->validate, + VALIDATION_POLICY_TRUSTED, + test_store, + validation_params); + + + // validate without the trust flag. + test_chain->validate(0, test_store, validation_params); + + // clear out the store + test_store = new LLBasicCertificateStore("mycertstore.pem"); + // append the intermediate cert + test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); + ensure_throws("no CA, with child and intermediate certs", + LLCertValidationTrustException, + (*test_chain)[1], + test_chain->validate, + VALIDATION_POLICY_TRUSTED, + test_store, + validation_params); + // validate without the trust flag + test_chain->validate(0, test_store, validation_params); + + // Test time validity + LLSD child_info = (*test_chain)[0]->getLLSD(); + validation_params = LLSD::emptyMap(); + validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() + 1.0); + test_chain->validate(VALIDATION_POLICY_TIME, test_store, 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_chain->validate, + VALIDATION_POLICY_TIME, + test_store, + 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_chain->validate, + VALIDATION_POLICY_TIME, + test_store, + 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)); + test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); + test_chain->validate(VALIDATION_POLICY_SSL_KU, test_store, validation_params); + + test_chain = new LLBasicCertificateChain(NULL); + test_chain->add(new LLBasicCertificate(mX509TestCert)); + + ensure_throws("Cert doesn't have ku", + LLCertKeyUsageValidationException, + (*test_chain)[0], + test_chain->validate, + VALIDATION_POLICY_SSL_KU, + test_store, + validation_params); + } +}; + diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp new file mode 100644 index 0000000000..803020dc7a --- /dev/null +++ b/indra/newview/tests/llslurl_test.cpp @@ -0,0 +1,258 @@ +/** + * @file llsecapi_test.cpp + * @author Roxie + * @date 2009-02-10 + * @brief Test the sec api functionality + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version maps.secondlife.com2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../llslurl.h" +#include "../../llxml/llcontrol.h" +#include "llsdserialize.h" +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, + const std::string& initial_val, + const std::string& comment, + BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} + +std::string gCmdLineLoginURI; +std::string gCmdLineGridChoice; +std::string gCmdLineHelperURI; +std::string gLoginPage; +std::string gCurrentGrid; +std::string LLControlGroup::getString(const std::string& name) +{ + if (name == "CmdLineGridChoice") + return gCmdLineGridChoice; + else if (name == "CmdLineHelperURI") + return gCmdLineHelperURI; + else if (name == "LoginPage") + return gLoginPage; + else if (name == "CurrentGrid") + return gCurrentGrid; + return ""; +} + +LLSD LLControlGroup::getLLSD(const std::string& name) +{ + if (name == "CmdLineLoginURI") + { + if(!gCmdLineLoginURI.empty()) + { + return LLSD(gCmdLineLoginURI); + } + } + return LLSD(); +} + + +LLControlGroup gSavedSettings("test"); + +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct slurlTest + { + slurlTest() + { + LLGridManager::getInstance()->initialize(std::string("")); + } + ~slurlTest() + { + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group slurlTestFactory; + typedef slurlTestFactory::object slurlTestObject; + tut::slurlTestFactory tut_test("llslurl"); + + // --------------------------------------------------------------------------------------- + // Test functions + // --------------------------------------------------------------------------------------- + // construction from slurl string + template<> template<> + void slurlTestObject::test<1>() + { + LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); + + LLSLURL slurl = LLSLURL(""); + ensure_equals("null slurl", (int)slurl.getType(), LLSLURL::LAST_LOCATION); + + slurl = LLSLURL("http://slurl.com/secondlife/myregion"); + ensure_equals("slurl.com slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("slurl.com slurl, region only", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + + slurl = LLSLURL("http://maps.secondlife.com/secondlife/myregion/1/2/3"); + ensure_equals("maps.secondlife.com slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("maps.secondlife.com slurl, region + coords", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + + slurl = LLSLURL("secondlife://myregion"); + ensure_equals("secondlife: slurl, region only - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("secondlife: slurl, region only", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + + slurl = LLSLURL("secondlife://myregion/1/2/3"); + ensure_equals("secondlife: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("secondlife slurl, region + coords", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + + slurl = LLSLURL("/myregion"); + ensure_equals("/region slurl, region- type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("/region slurl, region ", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/128/128/0"); + + slurl = LLSLURL("/myregion/1/2/3"); + ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("/ slurl, region + coords", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/myregion/1/2/3"); + + slurl = LLSLURL("my region/1/2/3"); + ensure_equals(" slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals(" slurl, region + coords", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/my%20region/1/2/3"); + + slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); + ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("grid slurl, region + coords", slurl.getSLURLString(), + "https://my.grid.com/region/my%20region/1/2/3"); + + slurl = LLSLURL("https://my.grid.com/region/my region"); + ensure_equals("grid slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("grid slurl, region + coords", slurl.getSLURLString(), + "https://my.grid.com/region/my%20region/128/128/0"); + + LLGridManager::getInstance()->setGridChoice("foo.bar.com"); + slurl = LLSLURL("/myregion/1/2/3"); + ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("/ slurl, region + coords", slurl.getSLURLString(), + "https://foo.bar.com/region/myregion/1/2/3"); + + slurl = LLSLURL("myregion/1/2/3"); + ensure_equals(": slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals(" slurl, region + coords", slurl.getSLURLString(), + "https://foo.bar.com/region/myregion/1/2/3"); + + slurl = LLSLURL(LLSLURL::SIM_LOCATION_HOME); + ensure_equals("home", slurl.getType(), LLSLURL::HOME_LOCATION); + + slurl = LLSLURL(LLSLURL::SIM_LOCATION_LAST); + ensure_equals("last", slurl.getType(), LLSLURL::LAST_LOCATION); + + slurl = LLSLURL("secondlife:///app/foo/bar?12345"); + ensure_equals("app", slurl.getType(), LLSLURL::APP); + ensure_equals("appcmd", slurl.getAppCmd(), "foo"); + ensure_equals("apppath", slurl.getAppPath().size(), 1); + ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); + ensure_equals("appquery", slurl.getAppQuery(), "12345"); + ensure_equals("grid1", "foo.bar.com", slurl.getGrid()); + + slurl = LLSLURL("secondlife://Aditi/app/foo/bar?12345"); + ensure_equals("app", slurl.getType(), LLSLURL::APP); + ensure_equals("appcmd", slurl.getAppCmd(), "foo"); + ensure_equals("apppath", slurl.getAppPath().size(), 1); + ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); + ensure_equals("appquery", slurl.getAppQuery(), "12345"); + ensure_equals("grid2", "util.aditi.lindenlab.com", slurl.getGrid()); + + LLGridManager::getInstance()->setGridChoice("foo.bar.com"); + slurl = LLSLURL("secondlife:///secondlife/myregion/1/2/3"); + ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("location", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("region" , "myregion", slurl.getRegion()); + ensure_equals("grid3", "util.agni.lindenlab.com", slurl.getGrid()); + + slurl = LLSLURL("secondlife://Aditi/secondlife/myregion/1/2/3"); + ensure_equals("/: slurl, region + coords - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("location", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("region" , "myregion", slurl.getRegion()); + ensure_equals("grid4", "util.aditi.lindenlab.com", slurl.getGrid()); + + slurl = LLSLURL("https://my.grid.com/app/foo/bar?12345"); + ensure_equals("app", slurl.getType(), LLSLURL::APP); + ensure_equals("appcmd", slurl.getAppCmd(), "foo"); + ensure_equals("apppath", slurl.getAppPath().size(), 1); + ensure_equals("apppath2", slurl.getAppPath()[0].asString(), "bar"); + ensure_equals("appquery", slurl.getAppQuery(), "12345"); + + } + + // construction from grid/region/vector combos + template<> template<> + void slurlTestObject::test<2>() + { + LLSLURL slurl = LLSLURL("mygrid.com", "my region"); + ensure_equals("grid/region - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals("grid/region", slurl.getSLURLString(), + "https://mygrid.com/region/my%20region/128/128/0"); + + slurl = LLSLURL("mygrid.com", "my region", LLVector3(1,2,3)); + ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals(" grid/region/vector", slurl.getSLURLString(), + "https://mygrid.com/region/my%20region/1/2/3"); + + LLGridManager::getInstance()->setGridChoice("foo.bar.com.bar"); + slurl = LLSLURL("my region", LLVector3(1,2,3)); + ensure_equals("grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals(" grid/region/vector", slurl.getSLURLString(), + "https://foo.bar.com.bar/region/my%20region/1/2/3"); + + LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); + slurl = LLSLURL("my region", LLVector3(1,2,3)); + ensure_equals("default grid/region/vector - type", slurl.getType(), LLSLURL::LOCATION); + ensure_equals(" default grid/region/vector", slurl.getSLURLString(), + "http://maps.secondlife.com/secondlife/my%20region/1/2/3"); + + } + // Accessors + template<> template<> + void slurlTestObject::test<3>() + { + LLSLURL slurl = LLSLURL("https://my.grid.com/region/my%20region/1/2/3"); + ensure_equals("login string", slurl.getLoginString(), "uri:my region&1&2&3"); + ensure_equals("location string", slurl.getLocationString(), "my region/1/2/3"); + ensure_equals("grid", slurl.getGrid(), "my.grid.com"); + ensure_equals("region", slurl.getRegion(), "my region"); + ensure_equals("position", slurl.getPosition(), LLVector3(1, 2, 3)); + + } +} diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp new file mode 100644 index 0000000000..f9f42cfc86 --- /dev/null +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -0,0 +1,486 @@ +/** + * @file llviewernetwork_test.cpp + * @author Roxie + * @date 2009-03-9 + * @brief Test the viewernetwork functionality + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden LregisterSecAPIab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../llviewerprecompiledheaders.h" +#include "../llviewernetwork.h" +#include "../test/lltut.h" +#include "../../llxml/llcontrol.h" +#include "llfile.h" + +//---------------------------------------------------------------------------- +// Mock objects for the dependencies of the code we're testing + +LLControlGroup::LLControlGroup(const std::string& name) +: LLInstanceTracker(name) {} +LLControlGroup::~LLControlGroup() {} +BOOL LLControlGroup::declareString(const std::string& name, + const std::string& initial_val, + const std::string& comment, + BOOL persist) {return TRUE;} +void LLControlGroup::setString(const std::string& name, const std::string& val){} + +std::string gCmdLineLoginURI; +std::string gCmdLineGridChoice; +std::string gCmdLineHelperURI; +std::string gLoginPage; +std::string gCurrentGrid; +std::string LLControlGroup::getString(const std::string& name) +{ + if (name == "CmdLineGridChoice") + return gCmdLineGridChoice; + else if (name == "CmdLineHelperURI") + return gCmdLineHelperURI; + else if (name == "LoginPage") + return gLoginPage; + else if (name == "CurrentGrid") + return gCurrentGrid; + return ""; +} + +LLSD LLControlGroup::getLLSD(const std::string& name) +{ + if (name == "CmdLineLoginURI") + { + if(!gCmdLineLoginURI.empty()) + { + return LLSD(gCmdLineLoginURI); + } + } + return LLSD(); +} + + +LLControlGroup gSavedSettings("test"); + +const char *gSampleGridFile = "" +"grid1" +" favorite1" +" helper_urihttps://helper1/helpers/" +" labelmylabel" +" login_pageloginpage" +" login_urimyloginuri" +" namegrid1" +" visible1" +" credential_typeagent" +" grid_login_idMyGrid" +"" +"util.agni.lindenlab.com" +" favorite1" +" helper_urihttps://helper1/helpers/" +" labelmylabel" +" login_pageloginpage" +" login_urimyloginuri" +" nameutil.agni.lindenlab.com" +""; +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ + // Test wrapper declaration : wrapping nothing for the moment + struct viewerNetworkTest + { + viewerNetworkTest() + { + LLFile::remove("grid_test.xml"); + gCmdLineLoginURI.clear(); + gCmdLineGridChoice.clear(); + gCmdLineHelperURI.clear(); + gLoginPage.clear(); + gCurrentGrid.clear(); + } + ~viewerNetworkTest() + { + LLFile::remove("grid_test.xml"); + } + }; + + // Tut templating thingamagic: test group, object and test instance + typedef test_group viewerNetworkTestFactory; + typedef viewerNetworkTestFactory::object viewerNetworkTestObject; + tut::viewerNetworkTestFactory tut_test("llviewernetwork"); + + // --------------------------------------------------------------------------------------- + // Test functions + // --------------------------------------------------------------------------------------- + // initialization without a grid file + template<> template<> + void viewerNetworkTestObject::test<1>() + { + + LLGridManager *manager = LLGridManager::getInstance(); + // grid file doesn't exist + manager->initialize("grid_test.xml"); + // validate that some of the defaults are available. + std::map known_grids = manager->getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18); + ensure_equals("Agni has the right name and label", + known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Known grids is a string-string map of size 2", known_grids.size(), 2); + ensure_equals("Agni has the right name and label", + known_grids[std::string("util.agni.lindenlab.com")], std::string("Secondlife.com")); +#endif // LL_RELEASE_FOR_DOWNLOAD + + + ensure_equals("None exists", known_grids[""], "None"); + + LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); + ensure("Grid info for agni is a map", grid.isMap()); + ensure_equals("name is correct for agni", + grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("label is correct for agni", + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("label is correct for agni", + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); +#endif // LL_RELEASE_FOR_DOWNLOAD + ensure("Login URI is an array", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("Agni login uri is correct", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); + ensure_equals("Agni helper uri is correct", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://secondlife.com/helpers/")); + ensure_equals("Agni login page is correct", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("http://secondlife.com/app/login/")); + ensure("Agni is a favorite", + grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("Agni is a system grid", + grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + ensure("Grid file wasn't greated as it wasn't saved", + !LLFile::isfile("grid_test.xml")); + } + + // initialization with a grid file + template<> template<> + void viewerNetworkTestObject::test<2>() + { + llofstream gridfile("grid_test.xml"); + gridfile << gSampleGridFile; + gridfile.close(); + + LLGridManager::getInstance()->initialize("grid_test.xml"); + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("adding a grid via a grid file increases known grid size", + known_grids.size(), 19); + ensure_equals("Agni is still there after we've added a grid via a grid file", + known_grids["util.agni.lindenlab.com"], std::string("Agni")); + +#else + ensure_equals("adding a grid via a grid file increases known grid size", + known_grids.size(), 3); + ensure_equals("Agni is still there after we've added a grid via a grid file", + known_grids["util.agni.lindenlab.com"], std::string("Secondlife.com")); + +#endif + + + // assure Agni doesn't get overwritten + LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Agni grid label was not modified by grid file", + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); +#else \\ LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Agni grid label was not modified by grid file", + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); +#endif \\ LL_RELEASE_FOR_DOWNLOAD + + ensure_equals("Agni name wasn't modified by grid file", + grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); + ensure("Agni grid URI is still an array after grid file", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("Agni login uri still the same after grid file", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); + ensure_equals("Agni helper uri still the same after grid file", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://secondlife.com/helpers/")); + ensure_equals("Agni login page the same after grid file", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("http://secondlife.com/app/login/")); + ensure("Agni still a favorite after grid file", + grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("Agni system grid still set after grid file", + grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + + ensure_equals("Grid file adds to name<->label map", + known_grids["grid1"], std::string("mylabel")); + grid = LLGridManager::getInstance()->getGridInfo("grid1"); + ensure_equals("grid file grid name is set", + grid[GRID_VALUE].asString(), std::string("grid1")); + ensure_equals("grid file label is set", + grid[GRID_LABEL_VALUE].asString(), std::string("mylabel")); + ensure("grid file login uri is an array", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("grid file login uri is set", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("myloginuri")); + ensure_equals("grid file helper uri is set", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://helper1/helpers/")); + ensure_equals("grid file login page is set", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("loginpage")); + ensure("grid file favorite is set", + grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("grid file isn't a system grid", + !grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + ensure("Grid file still exists after loading", + LLFile::isfile("grid_test.xml")); + } + + // Initialize via command line + + template<> template<> + void viewerNetworkTestObject::test<3>() + { + gCmdLineLoginURI = "https://my.login.uri/cgi-bin/login.cgi"; + + LLGridManager::getInstance()->initialize("grid_test.xml"); + // with single login uri specified. + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure_equals("adding a command line grid increases known grid size", + known_grids.size(), 19); + ensure_equals("Command line grid is added to the list of grids", + known_grids["my.login.uri"], std::string("my.login.uri")); + LLSD grid = LLGridManager::getInstance()->getGridInfo("my.login.uri"); + ensure_equals("Command line grid name is set", + grid[GRID_VALUE].asString(), std::string("my.login.uri")); + ensure_equals("Command line grid label is set", + grid[GRID_LABEL_VALUE].asString(), std::string("my.login.uri")); + ensure("Command line grid login uri is an array", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("Command line grid login uri is set", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("https://my.login.uri/cgi-bin/login.cgi")); + ensure_equals("Command line grid helper uri is set", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://my.login.uri/helpers/")); + ensure_equals("Command line grid login page is set", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("http://my.login.uri/app/login/")); + ensure("Command line grid favorite is set", + !grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("Command line grid isn't a system grid", + !grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + + // now try a command line with a custom grid identifier + gCmdLineGridChoice = "mycustomgridchoice"; + LLGridManager::getInstance()->initialize("grid_test.xml"); + known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure_equals("adding a command line grid with custom name increases known grid size", + known_grids.size(), 19); + ensure_equals("Custom Command line grid is added to the list of grids", + known_grids["mycustomgridchoice"], std::string("mycustomgridchoice")); + grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice"); + ensure_equals("Custom Command line grid name is set", + grid[GRID_VALUE].asString(), std::string("mycustomgridchoice")); + ensure_equals("Custom Command line grid label is set", + grid[GRID_LABEL_VALUE].asString(), std::string("mycustomgridchoice")); + ensure("Custom Command line grid login uri is an array", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("Custom Command line grid login uri is set", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("https://my.login.uri/cgi-bin/login.cgi")); + + // add a helperuri + gCmdLineHelperURI = "myhelperuri"; + LLGridManager::getInstance()->initialize("grid_test.xml"); + grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice"); + ensure_equals("Validate command line helper uri", + grid[GRID_HELPER_URI_VALUE].asString(), std::string("myhelperuri")); + + // add a login page + gLoginPage = "myloginpage"; + LLGridManager::getInstance()->initialize("grid_test.xml"); + grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice"); + ensure_equals("Validate command line helper uri", + grid[GRID_LOGIN_PAGE_VALUE].asString(), std::string("myloginpage")); + } + + // validate grid selection + template<> template<> + void viewerNetworkTestObject::test<4>() + { + LLSD loginURI = LLSD::emptyArray(); + LLSD grid = LLSD::emptyMap(); + // adding a grid with simply a name will populate the values. + grid[GRID_VALUE] = "myaddedgrid"; + + LLGridManager::getInstance()->initialize("grid_test.xml"); + LLGridManager::getInstance()->addGrid(grid); + LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); +#ifndef LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Secondlife.com")); +#endif // LL_RELEASE_FOR_DOWNLOAD + ensure_equals("getGrid", LLGridManager::getInstance()->getGrid(), + std::string("util.agni.lindenlab.com")); + ensure_equals("getHelperURI", LLGridManager::getInstance()->getHelperURI(), + std::string("https://secondlife.com/helpers/")); + ensure_equals("getLoginPage", LLGridManager::getInstance()->getLoginPage(), + std::string("http://secondlife.com/app/login/")); + ensure_equals("getLoginPage2", LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"), + std::string("http://secondlife.com/app/login/")); + ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid()); + std::vector uris; + LLGridManager::getInstance()->getLoginURIs(uris); + ensure_equals("getLoginURIs size", uris.size(), 1); + ensure_equals("getLoginURIs", uris[0], + std::string("https://login.agni.lindenlab.com/cgi-bin/login.cgi")); + LLGridManager::getInstance()->setGridChoice("myaddedgrid"); + ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("myaddedgrid")); + ensure("Is myaddedgrid a production grid", !LLGridManager::getInstance()->isInProductionGrid()); + + LLGridManager::getInstance()->setFavorite(); + grid = LLGridManager::getInstance()->getGridInfo("myaddedgrid"); + ensure("setting favorite", grid.has(GRID_IS_FAVORITE_VALUE)); + } + + // name based grid population + template<> template<> + void viewerNetworkTestObject::test<5>() + { + LLGridManager::getInstance()->initialize("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + // adding a grid with simply a name will populate the values. + grid[GRID_VALUE] = "myaddedgrid"; + LLGridManager::getInstance()->addGrid(grid); + grid = LLGridManager::getInstance()->getGridInfo("myaddedgrid"); + + ensure_equals("name based grid has name value", + grid[GRID_VALUE].asString(), + std::string("myaddedgrid")); + ensure_equals("name based grid has label value", + grid[GRID_LABEL_VALUE].asString(), + std::string("myaddedgrid")); + ensure_equals("name based grid has name value", + grid[GRID_HELPER_URI_VALUE].asString(), + std::string("https://myaddedgrid/helpers/")); + ensure_equals("name based grid has name value", + grid[GRID_LOGIN_PAGE_VALUE].asString(), + std::string("http://myaddedgrid/app/login/")); + ensure("name based grid has array loginuri", + grid[GRID_LOGIN_URI_VALUE].isArray()); + ensure_equals("name based grid has single login uri value", + grid[GRID_LOGIN_URI_VALUE].size(), 1); + ensure_equals("Name based grid login uri is correct", + grid[GRID_LOGIN_URI_VALUE][0].asString(), + std::string("https://myaddedgrid/cgi-bin/login.cgi")); + ensure("name based grid is not a favorite yet", + !grid.has(GRID_IS_FAVORITE_VALUE)); + ensure("name based grid does not have system setting", + !grid.has(GRID_IS_SYSTEM_GRID_VALUE)); + + llofstream gridfile("grid_test.xml"); + gridfile << gSampleGridFile; + gridfile.close(); + } + + // persistence of the grid list with an empty gridfile. + template<> template<> + void viewerNetworkTestObject::test<6>() + { + // try with initial grid list without a grid file, + // without setting the grid to a saveable favorite. + LLGridManager::getInstance()->initialize("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + grid[GRID_VALUE] = std::string("mynewgridname"); + LLGridManager::getInstance()->addGrid(grid); + LLGridManager::getInstance()->saveFavorites(); + ensure("Grid file exists after saving", + LLFile::isfile("grid_test.xml")); + LLGridManager::getInstance()->initialize("grid_test.xml"); + // should not be there + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure("New grid wasn't added to persisted list without being marked a favorite", + known_grids.find(std::string("mynewgridname")) == known_grids.end()); + + // mark a grid a favorite to make sure it's persisted + LLGridManager::getInstance()->addGrid(grid); + LLGridManager::getInstance()->setGridChoice("mynewgridname"); + LLGridManager::getInstance()->setFavorite(); + LLGridManager::getInstance()->saveFavorites(); + ensure("Grid file exists after saving", + LLFile::isfile("grid_test.xml")); + LLGridManager::getInstance()->initialize("grid_test.xml"); + // should not be there + known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure("New grid wasn't added to persisted list after being marked a favorite", + known_grids.find(std::string("mynewgridname")) != + known_grids.end()); + } + + // persistence of the grid file with existing gridfile + template<> template<> + void viewerNetworkTestObject::test<7>() + { + + llofstream gridfile("grid_test.xml"); + gridfile << gSampleGridFile; + gridfile.close(); + + LLGridManager::getInstance()->initialize("grid_test.xml"); + LLSD grid = LLSD::emptyMap(); + grid[GRID_VALUE] = std::string("mynewgridname"); + LLGridManager::getInstance()->addGrid(grid); + LLGridManager::getInstance()->saveFavorites(); + // validate we didn't lose existing favorites + LLGridManager::getInstance()->initialize("grid_test.xml"); + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure("New grid wasn't added to persisted list after being marked a favorite", + known_grids.find(std::string("grid1")) != + known_grids.end()); + + // add a grid + LLGridManager::getInstance()->addGrid(grid); + LLGridManager::getInstance()->setGridChoice("mynewgridname"); + LLGridManager::getInstance()->setFavorite(); + LLGridManager::getInstance()->saveFavorites(); + known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure("New grid wasn't added to persisted list after being marked a favorite", + known_grids.find(std::string("grid1")) != + known_grids.end()); + known_grids = LLGridManager::getInstance()->getKnownGrids(); + ensure("New grid wasn't added to persisted list after being marked a favorite", + known_grids.find(std::string("mynewgridname")) != + known_grids.end()); + } +} -- cgit v1.3 From 9fdba53b09193290ab33fc6aa414329d126505ed Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Wed, 21 Apr 2010 00:17:58 -0700 Subject: Show beta grids depending on a settings.xml setting. for SLE, this will be turned off. For trunk, it's turned on. Also, fixed an issue with manual entry of locations into the location dropdown. --- indra/newview/app_settings/settings.xml | 11 ++++ indra/newview/llpanellogin.cpp | 82 +++++----------------------- indra/newview/llpanellogin.h | 3 +- indra/newview/llviewernetwork.cpp | 17 +----- indra/newview/tests/llviewernetwork_test.cpp | 44 +++------------ 5 files changed, 36 insertions(+), 121 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24add573dc..0b2e657fbb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7973,6 +7973,17 @@ Value 0 + ShowBetaGrids + + Comment + Display the beta grids in the grid selection control. + Persist + 1 + Type + Boolean + Value + 1 + ShowCrosshairs Comment diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index a9e6484061..2bd763c681 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -221,16 +221,12 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLLineEditor* edit = getChild("password_edit"); if (edit) edit->setDrawAsterixes(TRUE); - LLComboBox* combo = getChild("start_location_combo"); - if(LLStartUp::getStartSLURL().getType() != LLSLURL::LOCATION) { LLSLURL slurl(gSavedSettings.getString("LoginLocation")); LLStartUp::setStartSLURL(slurl); } updateLocationCombo(false); - - combo->setCommitCallback(onSelectLocation, NULL); LLComboBox* server_choice_combo = sInstance->getChild("server_combo"); server_choice_combo->setCommitCallback(onSelectServer, NULL); @@ -692,7 +688,6 @@ void LLPanelLogin::updateLocationCombo( bool force_visible ) return; } - llinfos << "updatelocationcombo " << LLStartUp::getStartSLURL().asString() << llendl; LLComboBox* combo = sInstance->getChild("start_location_combo"); switch(LLStartUp::getStartSLURL().getType()) @@ -724,7 +719,7 @@ void LLPanelLogin::updateLocationCombo( bool force_visible ) } // static -void LLPanelLogin::onSelectLocation(LLUICtrl*, void*) +void LLPanelLogin::updateStartSLURL() { if (!sInstance) return; @@ -733,30 +728,11 @@ void LLPanelLogin::onSelectLocation(LLUICtrl*, void*) switch (index) { - case 2: + case 0: { - LLSLURL slurl = LLSLURL(combo->getSelectedValue()); - if((slurl.getType() == LLSLURL::LOCATION) && - (slurl.getGrid() != LLStartUp::getStartSLURL().getGrid())) - { - - - // we've changed the grid, so update the grid selection - try - { - LLStartUp::setStartSLURL(slurl); - } - catch (LLInvalidGridName ex) - { - LLSD args; - args["GRID"] = slurl.getGrid(); - LLNotificationsUtil::add("InvalidGrid", args); - return; - } - loadLoginPage(); - } + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST)); break; - } + } case 1: { LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); @@ -764,44 +740,18 @@ void LLPanelLogin::onSelectLocation(LLUICtrl*, void*) } default: { - LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_LAST)); + LLSLURL slurl = LLSLURL(combo->getValue().asString()); + if(slurl.getType() == LLSLURL::LOCATION) + { + // we've changed the grid, so update the grid selection + LLStartUp::setStartSLURL(slurl); + } break; - } + } } } -// static -void LLPanelLogin::getLocation(LLSLURL& slurl) -{ - LLSLURL result; - if (!sInstance) - { - llwarns << "Attempted getLocation with no login view shown" << llendl; - } - - LLComboBox* combo = sInstance->getChild("start_location_combo"); - - switch(combo->getCurrentIndex()) - { - case 0: - { - slurl = LLSLURL(LLSLURL::SIM_LOCATION_HOME); - break; - } - case 1: - { - slurl = LLSLURL(LLSLURL::SIM_LOCATION_LAST); - break; - } - default: - { - slurl = LLSLURL(combo->getValue().asString()); - break; - } - } -} - void LLPanelLogin::setLocation(const LLSLURL& slurl) { LLStartUp::setStartSLURL(slurl); @@ -1024,7 +974,7 @@ void LLPanelLogin::onClickConnect(void *) LLNotificationsUtil::add("InvalidGrid", args); return; } - + updateStartSLURL(); std::string username = sInstance->childGetText("username_edit"); if(username.empty()) { @@ -1134,11 +1084,9 @@ void LLPanelLogin::updateServerCombo() // We add all of the possible values, sorted, and then add a bar and the current value at the top LLComboBox* server_choice_combo = sInstance->getChild("server_combo"); server_choice_combo->removeall(); -#ifdef LL_RELEASE_FOR_DOWNLOAD - std::map known_grids = LLGridManager::getInstance()->getKnownGrids(TRUE); -#else - std::map known_grids = LLGridManager::getInstance()->getKnownGrids(FALSE); -#endif + + std::map known_grids = LLGridManager::getInstance()->getKnownGrids(!gSavedSettings.getBOOL("ShowBetaGrids")); + for (std::map::iterator grid_choice = known_grids.begin(); grid_choice != known_grids.end(); grid_choice++) diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 9301c263da..bca051691b 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -73,7 +73,6 @@ public: static BOOL isGridComboDirty(); static BOOL areCredentialFieldsDirty(); - static void getLocation(LLSLURL& slurl); static void setLocation(const LLSLURL& slurl); static void updateLocationCombo(bool force_visible); // simply update the combo box @@ -102,7 +101,7 @@ private: static void onSelectServer(LLUICtrl*, void*); static void onServerComboLostFocus(LLFocusableElement*); static void updateServerCombo(); - static void onSelectLocation(LLUICtrl*, void*); + static void updateStartSLURL(); static void updateLoginPanelLinks(); diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index d7bb4efe85..2673ba4e17 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -92,20 +92,11 @@ void LLGridManager::initialize(const std::string& grid_file) -#ifndef LL_RELEASE_FOR_DOWNLOAD - addSystemGrid("Agni", + addSystemGrid("Secondlife.com (Agni)", MAINGRID, "https://login.agni.lindenlab.com/cgi-bin/login.cgi", "https://secondlife.com/helpers/", DEFAULT_LOGIN_PAGE); -#else - addSystemGrid("Secondlife.com", - MAINGRID, - "https://login.agni.lindenlab.com/cgi-bin/login.cgi", - "https://secondlife.com/helpers/", - DEFAULT_LOGIN_PAGE, - "Agni"); -#endif // LL_RELEASE_FOR_DOWNLOAD addSystemGrid("Aditi", "util.aditi.lindenlab.com", "https://login.aditi.lindenlab.com/cgi-bin/login.cgi", @@ -313,11 +304,7 @@ void LLGridManager::initialize(const std::string& grid_file) // the grid name was empty, or the grid isn't actually in the list, then set it to the // appropriate default. LL_INFOS("GridManager") << "Resetting grid as grid name " << mGrid << " is not in the list" << LL_ENDL; -#if LL_RELEASE_FOR_DOWNLOAD mGrid = MAINGRID; -#else - mGrid = ""; -#endif } LL_INFOS("GridManager") << "Selected grid is " << mGrid << LL_ENDL; gSavedSettings.setString("CurrentGrid", mGrid); @@ -418,7 +405,7 @@ void LLGridManager::addSystemGrid(const std::string& label, } else { - grid[GRID_SLURL_BASE] = llformat(SYSTEM_GRID_SLURL_BASE, label.c_str()); + grid[GRID_SLURL_BASE] = llformat(SYSTEM_GRID_SLURL_BASE, label.c_str()); } addGrid(grid); } diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index f9f42cfc86..90c8357453 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -143,30 +143,17 @@ namespace tut manager->initialize("grid_test.xml"); // validate that some of the defaults are available. std::map known_grids = manager->getKnownGrids(); -#ifndef LL_RELEASE_FOR_DOWNLOAD ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18); ensure_equals("Agni has the right name and label", - known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni")); -#else // LL_RELEASE_FOR_DOWNLOAD - ensure_equals("Known grids is a string-string map of size 2", known_grids.size(), 2); - ensure_equals("Agni has the right name and label", - known_grids[std::string("util.agni.lindenlab.com")], std::string("Secondlife.com")); -#endif // LL_RELEASE_FOR_DOWNLOAD - - + known_grids[std::string("util.agni.lindenlab.com")], std::string("Secondlife.com (Agni)")); ensure_equals("None exists", known_grids[""], "None"); LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); ensure("Grid info for agni is a map", grid.isMap()); ensure_equals("name is correct for agni", grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); -#ifndef LL_RELEASE_FOR_DOWNLOAD ensure_equals("label is correct for agni", - grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); -#else // LL_RELEASE_FOR_DOWNLOAD - ensure_equals("label is correct for agni", - grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); -#endif // LL_RELEASE_FOR_DOWNLOAD + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com (Agni)")); ensure("Login URI is an array", grid[GRID_LOGIN_URI_VALUE].isArray()); ensure_equals("Agni login uri is correct", @@ -196,30 +183,17 @@ namespace tut LLGridManager::getInstance()->initialize("grid_test.xml"); std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); -#ifndef LL_RELEASE_FOR_DOWNLOAD ensure_equals("adding a grid via a grid file increases known grid size", known_grids.size(), 19); ensure_equals("Agni is still there after we've added a grid via a grid file", - known_grids["util.agni.lindenlab.com"], std::string("Agni")); - -#else - ensure_equals("adding a grid via a grid file increases known grid size", - known_grids.size(), 3); - ensure_equals("Agni is still there after we've added a grid via a grid file", - known_grids["util.agni.lindenlab.com"], std::string("Secondlife.com")); - -#endif + known_grids["util.agni.lindenlab.com"], std::string("Secondlife.com (Agni)")); // assure Agni doesn't get overwritten LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); -#ifndef LL_RELEASE_FOR_DOWNLOAD - ensure_equals("Agni grid label was not modified by grid file", - grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); -#else \\ LL_RELEASE_FOR_DOWNLOAD + ensure_equals("Agni grid label was not modified by grid file", - grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com")); -#endif \\ LL_RELEASE_FOR_DOWNLOAD + grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com (Agni)")); ensure_equals("Agni name wasn't modified by grid file", grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); @@ -345,12 +319,8 @@ namespace tut LLGridManager::getInstance()->initialize("grid_test.xml"); LLGridManager::getInstance()->addGrid(grid); - LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); -#ifndef LL_RELEASE_FOR_DOWNLOAD - ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni")); -#else // LL_RELEASE_FOR_DOWNLOAD - ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Secondlife.com")); -#endif // LL_RELEASE_FOR_DOWNLOAD + LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); + ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Secondlife.com (Agni)")); ensure_equals("getGrid", LLGridManager::getInstance()->getGrid(), std::string("util.agni.lindenlab.com")); ensure_equals("getHelperURI", LLGridManager::getInstance()->getHelperURI(), -- cgit v1.3 From 5e727964dbd6d5e55dd3a0921e8e1f0f77a99747 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 22 Apr 2010 15:09:34 -0700 Subject: DEV-49332 - cryptic error message when typing in single username when logging into maingrid. Needs to be changed when IE is checked in, of course. Now we check the expected credential formats for a given grid against the format that is typed in, and throw an error if it's invalid. --- indra/newview/llpanellogin.cpp | 42 ++++++++++++++--- indra/newview/llpanellogin.h | 2 +- indra/newview/llsecapi.cpp | 52 +++++++++++++++++----- indra/newview/llsecapi.h | 6 +++ indra/newview/llstartup.cpp | 2 +- indra/newview/llviewernetwork.cpp | 18 ++++++-- indra/newview/llviewernetwork.h | 6 +-- .../newview/skins/default/xui/en/notifications.xml | 8 ++++ indra/newview/tests/lllogininstance_test.cpp | 7 +++ indra/newview/tests/llviewernetwork_test.cpp | 10 ++--- 10 files changed, 122 insertions(+), 31 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 22fb70de73..63fe7bfa91 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -571,7 +571,7 @@ void LLPanelLogin::setFields(LLPointer credential, // static void LLPanelLogin::getFields(LLPointer& credential, - BOOL remember) + BOOL& remember) { if (!sInstance) { @@ -603,14 +603,14 @@ void LLPanelLogin::getFields(LLPointer& credential, { LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL; // single username, so this is a 'clear' identifier - identifier["type"] = "account"; + identifier["type"] = CRED_IDENTIFIER_TYPE_ACCOUNT; identifier["account_name"] = username; if (LLPanelLogin::sInstance->mPasswordModified) { authenticator = LLSD::emptyMap(); // password is plaintext - authenticator["type"] = "clear"; + authenticator["type"] = CRED_AUTHENTICATOR_TYPE_CLEAR; authenticator["secret"] = password; } } @@ -618,14 +618,14 @@ void LLPanelLogin::getFields(LLPointer& credential, { LL_INFOS2("Credentials", "Authentication") << "agent: " << username << LL_ENDL; // traditional firstname / lastname - identifier["type"] = "agent"; + identifier["type"] = CRED_IDENTIFIER_TYPE_AGENT; identifier["first_name"] = username.substr(0, separator_index); identifier["last_name"] = username.substr(separator_index+1, username.npos); if (LLPanelLogin::sInstance->mPasswordModified) { authenticator = LLSD::emptyMap(); - authenticator["type"] = "hash"; + authenticator["type"] = CRED_AUTHENTICATOR_TYPE_HASH; authenticator["algorithm"] = "md5"; LLMD5 pass((const U8 *)password.c_str()); char md5pass[33]; /* Flawfinder: ignore */ @@ -978,14 +978,42 @@ void LLPanelLogin::onClickConnect(void *) } updateStartSLURL(); std::string username = sInstance->childGetText("username_edit"); + + if(username.empty()) { + // user must type in something into the username field LLNotificationsUtil::add("MustHaveAccountToLogIn"); } else { - // has both first and last name typed - sInstance->mCallback(0, sInstance->mCallbackData); + LLPointer cred; + BOOL remember; + getFields(cred, remember); + std::string identifier_type; + cred->identifierType(identifier_type); + LLSD allowed_credential_types; + LLGridManager::getInstance()->getLoginIdentifierTypes(allowed_credential_types); + + // check the typed in credential type against the credential types expected by the server. + for(LLSD::array_iterator i = allowed_credential_types.beginArray(); + i != allowed_credential_types.endArray(); + i++) + { + + if(i->asString() == identifier_type) + { + // yay correct credential type + sInstance->mCallback(0, sInstance->mCallbackData); + return; + } + } + + // Right now, maingrid is the only thing that is picky about + // credential format, as it doesn't yet allow account (single username) + // format creds. - Rox. James, we wanna fix the message when we change + // this. + LLNotificationsUtil::add("InvalidCredentialFormat"); } } } diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index bca051691b..aa6884ea97 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -69,7 +69,7 @@ public: static void setFields(LLPointer credential, BOOL remember); - static void getFields(LLPointer& credential, BOOL remember); + static void getFields(LLPointer& credential, BOOL& remember); static BOOL isGridComboDirty(); static BOOL areCredentialFieldsDirty(); diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index ba343f5387..b3e96298d2 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -143,19 +143,51 @@ int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param) LLSD LLCredential::getLoginParams() { LLSD result = LLSD::emptyMap(); - if (mIdentifier["type"].asString() == "agent") + try { - // legacy credential - result["passwd"] = "$1$" + mAuthenticator["secret"].asString(); - result["first"] = mIdentifier["first_name"]; - result["last"] = mIdentifier["last_name"]; - + if (mIdentifier["type"].asString() == "agent") + { + // legacy credential + result["passwd"] = "$1$" + mAuthenticator["secret"].asString(); + result["first"] = mIdentifier["first_name"]; + result["last"] = mIdentifier["last_name"]; + + } + else if (mIdentifier["type"].asString() == "account") + { + result["username"] = mIdentifier["account_name"]; + result["passwd"] = mAuthenticator["secret"]; + + } } - else if (mIdentifier["type"].asString() == "account") + catch (...) { - result["username"] = mIdentifier["account_name"]; - result["passwd"] = mAuthenticator["secret"]; - + // we could have corrupt data, so simply return a null login param if so + LL_WARNS("AppInit") << "Invalid credential" << LL_ENDL; } return result; } + +void LLCredential::identifierType(std::string &idType) +{ + if(mIdentifier.has("type")) + { + idType = mIdentifier["type"].asString(); + } + else { + idType = std::string(); + + } +} + +void LLCredential::authenticatorType(std::string &idType) +{ + if(mAuthenticator.has("type")) + { + idType = mAuthenticator["type"].asString(); + } + else { + idType = std::string(); + + } +} \ No newline at end of file diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 5211dc2699..59a1e1eff0 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -286,6 +286,10 @@ bool operator!=(const LLCertificateVector::iterator& _lhs, const LLCertificateVe } +#define CRED_IDENTIFIER_TYPE_ACCOUNT "account" +#define CRED_IDENTIFIER_TYPE_AGENT "agent" +#define CRED_AUTHENTICATOR_TYPE_CLEAR "clear" +#define CRED_AUTHENTICATOR_TYPE_HASH "hash" // // LLCredential - interface for credentials providing the following functionality: // * persistance of credential information based on grid (for saving username/password) @@ -312,7 +316,9 @@ public: mAuthenticator = authenticator; } virtual LLSD getIdentifier() { return mIdentifier; } + virtual void identifierType(std::string& idType); virtual LLSD getAuthenticator() { return mAuthenticator; } + virtual void authenticatorType(std::string& authType); virtual LLSD getLoginParams(); virtual std::string getGrid() { return mGrid; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index eee92ac413..8e2097762a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -799,7 +799,7 @@ bool idle_startup() gViewerWindow->moveProgressViewToFront(); //reset the values that could have come in from a slurl - // DEV-42215: Make sure they're not empty -- gFirstname and gLastname + // DEV-42215: Make sure they're not empty -- gUserCredential // might already have been set from gSavedSettings, and it's too bad // to overwrite valid values with empty strings. diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 2673ba4e17..a160572f7a 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -35,6 +35,7 @@ #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llsdserialize.h" +#include "llsecapi.h" #include "llweb.h" @@ -92,7 +93,7 @@ void LLGridManager::initialize(const std::string& grid_file) - addSystemGrid("Secondlife.com (Agni)", + addSystemGrid("Agni", MAINGRID, "https://login.agni.lindenlab.com/cgi-bin/login.cgi", "https://secondlife.com/helpers/", @@ -361,7 +362,17 @@ void LLGridManager::addGrid(LLSD& grid_data) if (!grid_data.has(GRID_HELPER_URI_VALUE)) { grid_data[GRID_HELPER_URI_VALUE] = std::string("https://") + grid + "/helpers/"; - } + } + + if (!grid_data.has(GRID_LOGIN_IDENTIFIER_TYPES)) + { + // non system grids and grids that haven't already been configured with values + // get both types of credentials. + grid_data[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray(); + grid_data[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT); + grid_data[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_ACCOUNT); + } + LL_INFOS("GridManager") << "ADDING: " << grid << LL_ENDL; mGridList[grid] = grid_data; } @@ -384,7 +395,8 @@ void LLGridManager::addSystemGrid(const std::string& label, grid[GRID_LOGIN_URI_VALUE].append(login); grid[GRID_LOGIN_PAGE_VALUE] = login_page; grid[GRID_IS_SYSTEM_GRID_VALUE] = TRUE; - grid[GRID_LOGIN_CREDENTIAL_PAGE_TYPE_VALUE] = GRID_LOGIN_CREDENTIAL_PAGE_TYPE_AGENT; + grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray(); + grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT); grid[GRID_APP_SLURL_BASE] = SYSTEM_GRID_APP_SLURL_BASE; if (login_id.empty()) diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 46f21bf20f..0271e7a7a5 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -43,11 +43,8 @@ extern const char* DEFAULT_LOGIN_PAGE; #define GRID_LOGIN_PAGE_VALUE "login_page" #define GRID_IS_SYSTEM_GRID_VALUE "system_grid" #define GRID_IS_FAVORITE_VALUE "favorite" -#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_VALUE "credential_type" -#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_AGENT "agent" -#define GRID_LOGIN_CREDENTIAL_PAGE_TYPE_ACCOUNT "account" #define MAINGRID "util.agni.lindenlab.com" - +#define GRID_LOGIN_IDENTIFIER_TYPES "login_identifier_types" // defines slurl formats associated with various grids. // we need to continue to support existing forms, as slurls // are shared between viewers that may not understand newer @@ -119,6 +116,7 @@ public: std::string getLoginPage() {return mGridList[mGrid][GRID_LOGIN_PAGE_VALUE];} std::string getGridLoginID() { return mGridList[mGrid][GRID_ID_VALUE]; } std::string getLoginPage(const std::string& grid) { return mGridList[grid][GRID_LOGIN_PAGE_VALUE]; } + void getLoginIdentifierTypes(LLSD& idTypes) { idTypes = mGridList[mGrid][GRID_LOGIN_IDENTIFIER_TYPES]; } // build a slurl for the given region within the selected grid std::string getSLURLBase(const std::string& grid); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e06f36c823..a0a1113b4d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -733,6 +733,14 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now? yestext="Create a new account"/> + +You need to enter both the First and Last name of your avatar into the Username field, then login again. + + + known_grids = manager->getKnownGrids(); ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18); ensure_equals("Agni has the right name and label", - known_grids[std::string("util.agni.lindenlab.com")], std::string("Secondlife.com (Agni)")); + known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni")); ensure_equals("None exists", known_grids[""], "None"); LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); @@ -153,7 +153,7 @@ namespace tut ensure_equals("name is correct for agni", grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); ensure_equals("label is correct for agni", - grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com (Agni)")); + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); ensure("Login URI is an array", grid[GRID_LOGIN_URI_VALUE].isArray()); ensure_equals("Agni login uri is correct", @@ -186,14 +186,14 @@ namespace tut ensure_equals("adding a grid via a grid file increases known grid size", known_grids.size(), 19); ensure_equals("Agni is still there after we've added a grid via a grid file", - known_grids["util.agni.lindenlab.com"], std::string("Secondlife.com (Agni)")); + known_grids["util.agni.lindenlab.com"], std::string("Agni")); // assure Agni doesn't get overwritten LLSD grid = LLGridManager::getInstance()->getGridInfo("util.agni.lindenlab.com"); ensure_equals("Agni grid label was not modified by grid file", - grid[GRID_LABEL_VALUE].asString(), std::string("Secondlife.com (Agni)")); + grid[GRID_LABEL_VALUE].asString(), std::string("Agni")); ensure_equals("Agni name wasn't modified by grid file", grid[GRID_VALUE].asString(), std::string("util.agni.lindenlab.com")); @@ -320,7 +320,7 @@ namespace tut LLGridManager::getInstance()->initialize("grid_test.xml"); LLGridManager::getInstance()->addGrid(grid); LLGridManager::getInstance()->setGridChoice("util.agni.lindenlab.com"); - ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Secondlife.com (Agni)")); + ensure_equals("getGridLabel", LLGridManager::getInstance()->getGridLabel(), std::string("Agni")); ensure_equals("getGrid", LLGridManager::getInstance()->getGrid(), std::string("util.agni.lindenlab.com")); ensure_equals("getHelperURI", LLGridManager::getInstance()->getHelperURI(), -- cgit v1.3 From b0473a8d47792e94aaea9c273122fae42577ad8f Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 22 Apr 2010 16:30:50 -0700 Subject: Fix test build break --- indra/newview/tests/llsechandler_basic_test.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/newview/tests') diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 236d17c591..3f4474e23a 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -95,6 +95,13 @@ LLSD LLCredential::getLoginParams() return result; } +void LLCredential::identifierType(std::string &idType) +{ +} + +void LLCredential::authenticatorType(std::string &idType) +{ +} LLControlGroup gSavedSettings("test"); -- cgit v1.3 From d82a10217ad5ac09500e272b74cdacb4bf04414b Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Mon, 26 Apr 2010 17:41:21 -0700 Subject: Fix issue parsing wildcard cns in certificates CR: Karina --- indra/newview/llsechandler_basic.cpp | 46 +++++++++++++++++++------ indra/newview/tests/llsechandler_basic_test.cpp | 31 ++++++++++++++--- 2 files changed, 62 insertions(+), 15 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 51e250ffc6..df55ccf142 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -782,23 +782,49 @@ bool _cert_hostname_wildcard_match(const std::string& hostname, const std::strin { std::string new_hostname = hostname; std::string new_cn = common_name; - int subdomain_pos = new_hostname.find_first_of('.'); - int subcn_pos = new_cn.find_first_of('.'); - while((subcn_pos != std::string::npos) && (subdomain_pos != std::string::npos)) + // find the last '.' in the hostname and the match name. + int subdomain_pos = new_hostname.find_last_of('.'); + int subcn_pos = new_cn.find_last_of('.'); + + // if the last char is a '.', strip it + if(subdomain_pos == (new_hostname.length()-1)) + { + new_hostname = new_hostname.substr(0, subdomain_pos); + subdomain_pos = new_hostname.find_last_of('.'); + } + if(subcn_pos == (new_cn.length()-1)) { - // snip out the first subdomain and cn element + new_cn = new_cn.substr(0, subcn_pos); + subcn_pos = new_cn.find_last_of('.'); + } - if(!_cert_subdomain_wildcard_match(new_hostname.substr(0, subdomain_pos), - new_cn.substr(0, subcn_pos))) + // Check to see if there are any further '.' in the string. + while((subcn_pos != std::string::npos) && (subdomain_pos != std::string::npos)) + { + // snip out last subdomain in both the match string and the hostname + // The last bit for 'my.current.host.com' would be 'com' + std::string cn_part = new_cn.substr(subcn_pos+1, std::string::npos); + std::string hostname_part = new_hostname.substr(subdomain_pos+1, std::string::npos); + + if(!_cert_subdomain_wildcard_match(new_hostname.substr(subdomain_pos+1, std::string::npos), + cn_part)) { return FALSE; } - new_hostname = new_hostname.substr(subdomain_pos+1, std::string::npos); - new_cn = new_cn.substr(subcn_pos+1, std::string::npos); - subdomain_pos = new_hostname.find_first_of('.'); - subcn_pos = new_cn.find_first_of('.'); + new_hostname = new_hostname.substr(0, subdomain_pos); + new_cn = new_cn.substr(0, subcn_pos); + subdomain_pos = new_hostname.find_last_of('.'); + subcn_pos = new_cn.find_last_of('.'); + } + // check to see if the most significant portion of the common name is '*'. If so, we can + // simply return success as child domains are also matched. + if(new_cn == "*") + { + // if it's just a '*' we support all child domains as well, so '*. + return TRUE; } + return _cert_subdomain_wildcard_match(new_hostname, new_cn); } diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 3f4474e23a..ba448d4b5b 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -702,12 +702,18 @@ namespace tut { 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")); @@ -772,11 +778,26 @@ namespace tut ensure("end periods", _cert_hostname_wildcard_match("foo.bar.com.", "*.b*r.com.")); - ensure("mismatch end period", - !_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("mismatch end period2", - !_cert_hostname_wildcard_match("foo.bar.com", "*.b*r.com.")); + ensure("wildcard mismatch", + !_cert_hostname_wildcard_match("foo.foo.bar.com", "*.foo.com")); } // test cert chain -- cgit v1.3 From 2173bb5f6a58e6f5e1123e89b695e337a3203aae Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Thu, 29 Apr 2010 02:07:12 -0700 Subject: Add test for sha1WithRSAEncryption signed certs. Also removed redundant openssl initialization --- indra/newview/llsecapi.cpp | 5 +- indra/newview/tests/llsechandler_basic_test.cpp | 63 ++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 066ac40793..89b799f297 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -35,6 +35,7 @@ #include "llsecapi.h" #include "llsechandler_basic.h" #include +#include #include #include "llhttpclient.h" @@ -45,9 +46,9 @@ LLPointer gSecAPIHandler; void initializeSecHandler() { + ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); + gHandlerMap[BASIC_SECHANDLER] = new LLSecAPIBasicHandler(); diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index ba448d4b5b..fd680b24f0 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -47,6 +47,14 @@ #include #include #include "llxorcipher.h" +#include +#include +#include +#include +#include +#include +#include + #define ensure_throws(str, exc_type, cert, func, ...) \ try \ @@ -115,7 +123,7 @@ namespace tut // Test wrapper declaration : wrapping nothing for the moment struct sechandler_basic_test { - std::string mPemTestCert, mPemRootCert, mPemIntermediateCert, mPemChildCert; + std::string mPemTestCert, mPemRootCert, mPemIntermediateCert, mPemChildCert, mSha1RSATestCert, mSha1RSATestCA; std::string mDerFormat; X509 *mX509TestCert, *mX509RootCert, *mX509IntermediateCert, *mX509ChildCert; @@ -223,6 +231,49 @@ namespace tut "1ME7a55lFEnSeT0umlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5" "nmPbK+9A46sd33oqK8n8"; + mSha1RSATestCert = "-----BEGIN CERTIFICATE-----\n" + "MIIDFDCCAn2gAwIBAgIDDqqYMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n" + "MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n" + "aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTAwMTA1MDAzNjMwWhcNMTEwMTA3MjAyMTE0\n" + "WjCBnjEpMCcGA1UEBRMgQmNmc0RBRkl1U0YwdFpWVm5vOFJKbjVUbW9hNGR2Wkgx\n" + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4g\n" + "RnJhbmNpc2NvMR0wGwYDVQQKExRMaW5kZW4gUmVzZWFyY2ggSW5jLjEYMBYGA1UE\n" + "AxQPKi5saW5kZW5sYWIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD2\n" + "14Jdko8v6GB33hHbW+lNQyloFQtc2h4ykjf+fYPJ27dw6tQO2if7N3k/5XDkwC1N\n" + "krGgE9vt3iecCPgasue6k67Zyfj9HbEP2D+j38eROudrsxLaRFDQx50BvZ5YMNl3\n" + "4zQCj8/gCMsuq8cvaP9/rbJTUpgYWFGLsm8yAYOgWwIDAQABo4GuMIGrMA4GA1Ud\n" + "DwEB/wQEAwIE8DAdBgNVHQ4EFgQUIBK/JB9AyqquSEbkzt2Zux6v9sYwOgYDVR0f\n" + "BDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVj\n" + "YS5jcmwwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9QwHQYDVR0lBBYw\n" + "FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAKKR84+hvLuB\n" + "pop9VG7HQPIyEKtZq3Nnk+UlJGfjGY3csLWSFmxU727r5DzdEP1W1PwF3rxuoKcZ\n" + "4nJJpKdzoGVujgBMP2U/J0PJvU7D8U3Zqu7nrXAjOHj7iVnvJ3EKJ1bvwXaisgPN\n" + "wt21kKfGnA4OlhJtJ6VQvUkcF12I3pTP\n" + "-----END CERTIFICATE-----\n"; + + mSha1RSATestCA = "-----BEGIN CERTIFICATE-----\n" + "MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV\n" + "UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy\n" + "dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1\n" + "MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx\n" + "dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B\n" + "AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f\n" + "BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A\n" + "cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC\n" + "AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ\n" + "MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm\n" + "aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw\n" + "ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj\n" + "IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF\n" + "MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA\n" + "A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y\n" + "7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh\n" + "1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4\n" + "-----END CERTIFICATE-----\n"; + + + + mX509TestCert = NULL; mX509RootCert = NULL; mX509IntermediateCert = NULL; @@ -951,7 +1002,7 @@ namespace tut 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", + ensure_throws("Child cert not yet valid" , LLCertValidationExpirationException, (*test_chain)[0], test_chain->validate, @@ -987,6 +1038,14 @@ namespace tut VALIDATION_POLICY_SSL_KU, test_store, validation_params); + + // test sha1RSA validation + test_chain = new LLBasicCertificateChain(NULL); + test_chain->add(new LLBasicCertificate(mSha1RSATestCert)); + test_chain->add(new LLBasicCertificate(mSha1RSATestCA)); + + test_chain->validate(0, test_store, validation_params); } + }; -- cgit v1.3 From 75755a675120002fd7cbc3dc324bd8b50a9dba23 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Tue, 18 May 2010 15:56:42 -0700 Subject: Add missing debug grids --- indra/newview/llviewernetwork.cpp | 26 +++++++++++++++++++++++++- indra/newview/tests/llviewernetwork_test.cpp | 8 ++++---- 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index a160572f7a..7812867667 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -108,6 +108,26 @@ void LLGridManager::initialize(const std::string& grid_file) "https://login.aruna.lindenlab.com/cgi-bin/login.cgi", "http://aruna-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); + addSystemGrid("Bharati", + "util.bharati.lindenlab.com", + "https://login.bharati.lindenlab.com/cgi-bin/login.cgi", + "http://bharati-secondlife.webdev.lindenlab.com/helpers/", + DEFAULT_LOGIN_PAGE); + addSystemGrid("Chandra", + "util.chandra.lindenlab.com", + "https://login.chandra.lindenlab.com/cgi-bin/login.cgi", + "http://chandra-secondlife.webdev.lindenlab.com/helpers/", + DEFAULT_LOGIN_PAGE); + addSystemGrid("Damballah", + "util.damballah.lindenlab.com", + "https://login.damballah.lindenlab.com/cgi-bin/login.cgi", + "http://damballah-secondlife.webdev.lindenlab.com/helpers/", + DEFAULT_LOGIN_PAGE); + addSystemGrid("Danu", + "util.danu.lindenlab.com", + "https://login.danu.lindenlab.com/cgi-bin/login.cgi", + "http://danu-secondlife.webdev.lindenlab.com/helpers/", + DEFAULT_LOGIN_PAGE); addSystemGrid("Durga", "util.durga.lindenlab.com", "https://login.durga.lindenlab.com/cgi-bin/login.cgi", @@ -133,6 +153,11 @@ void LLGridManager::initialize(const std::string& grid_file) "https://login.nandi.lindenlab.com/cgi-bin/login.cgi", "http://nandi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); + addSystemGrid("Parvati", + "util.parvati.lindenlab.com", + "https://login.parvati.lindenlab.com/cgi-bin/login.cgi", + "http://parvati-secondlife.webdev.lindenlab.com/helpers/", + DEFAULT_LOGIN_PAGE); addSystemGrid("Radha", "util.radha.lindenlab.com", "https://login.radha.lindenlab.com/cgi-bin/login.cgi", @@ -158,7 +183,6 @@ void LLGridManager::initialize(const std::string& grid_file) "https://login.soma.lindenlab.com/cgi-bin/login.cgi", "http://soma-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE); - addSystemGrid("Uma", "util.uma.lindenlab.com", "https://login.uma.lindenlab.com/cgi-bin/login.cgi", diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index 025b570be2..d819b44564 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -143,7 +143,7 @@ namespace tut manager->initialize("grid_test.xml"); // validate that some of the defaults are available. std::map known_grids = manager->getKnownGrids(); - ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 18); + ensure_equals("Known grids is a string-string map of size 23", known_grids.size(), 23); ensure_equals("Agni has the right name and label", known_grids[std::string("util.agni.lindenlab.com")], std::string("Agni")); ensure_equals("None exists", known_grids[""], "None"); @@ -184,7 +184,7 @@ namespace tut LLGridManager::getInstance()->initialize("grid_test.xml"); std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); ensure_equals("adding a grid via a grid file increases known grid size", - known_grids.size(), 19); + known_grids.size(), 24); ensure_equals("Agni is still there after we've added a grid via a grid file", known_grids["util.agni.lindenlab.com"], std::string("Agni")); @@ -250,7 +250,7 @@ namespace tut // with single login uri specified. std::map known_grids = LLGridManager::getInstance()->getKnownGrids(); ensure_equals("adding a command line grid increases known grid size", - known_grids.size(), 19); + known_grids.size(), 24); ensure_equals("Command line grid is added to the list of grids", known_grids["my.login.uri"], std::string("my.login.uri")); LLSD grid = LLGridManager::getInstance()->getGridInfo("my.login.uri"); @@ -279,7 +279,7 @@ namespace tut LLGridManager::getInstance()->initialize("grid_test.xml"); known_grids = LLGridManager::getInstance()->getKnownGrids(); ensure_equals("adding a command line grid with custom name increases known grid size", - known_grids.size(), 19); + known_grids.size(), 24); ensure_equals("Custom Command line grid is added to the list of grids", known_grids["mycustomgridchoice"], std::string("mycustomgridchoice")); grid = LLGridManager::getInstance()->getGridInfo("mycustomgridchoice"); -- cgit v1.3 From 1ad46b5cd0fcac0d3224d37d555092258593eabd Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Mon, 24 May 2010 13:59:10 -0700 Subject: DEV-50173 - investigate certificate code performance DEV-50166 - LLBasicCertificateChain::validate calls in log Added caching of certificates that have been validated. The sha1 hash for the certificate is stored and is associated with the from and to times. When the certificate is validated, the code determines whether the certificate has successfully been validated before by looking for it in the cache, and then checks the date of the cert. If that is successful, the validation calls with success. Otherwise, it proceeds to do a full validation of the certificate. --- indra/newview/llsecapi.cpp | 2 +- indra/newview/llsecapi.h | 31 ++++--- indra/newview/llsechandler_basic.cpp | 114 +++++++++++++++++------- indra/newview/llsechandler_basic.h | 23 +++-- indra/newview/llstartup.cpp | 3 +- indra/newview/llxmlrpctransaction.cpp | 3 +- indra/newview/tests/llsechandler_basic_test.cpp | 34 +++---- 7 files changed, 134 insertions(+), 76 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 1caeec5b04..9e636f38c0 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -124,7 +124,7 @@ int secapiSSLCertVerifyCallback(X509_STORE_CTX *ctx, void *param) // we rely on libcurl to validate the hostname, as libcurl does more extensive validation // leaving our hostname validation call mechanism for future additions with respect to // OS native (Mac keyring, windows CAPI) validation. - chain->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), store, validation_params); + store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params); } catch (LLCertValidationTrustException& cert_exception) { diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 59a1e1eff0..5a1a3879d4 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -154,7 +154,7 @@ public: // return an LLSD object containing information about the certificate // such as its name, signature, expiry time, serial number - virtual LLSD getLLSD() const=0; + virtual void getLLSD(LLSD& llsd)=0; // return an openSSL X509 struct for the certificate virtual X509* getOpenSSLX509() const=0; @@ -231,6 +231,18 @@ public: virtual LLPointer erase(iterator cert)=0; }; +// class LLCertificateChain +// Class representing a chain of certificates in order, with the +// first element being the child cert. +class LLCertificateChain : virtual public LLCertificateVector +{ + +public: + LLCertificateChain() {} + + virtual ~LLCertificateChain() {} + +}; // class LLCertificateStore // represents a store of certificates, typically a store of root CA @@ -250,30 +262,17 @@ public: // return the store id virtual std::string storeId() const=0; -}; - -// class LLCertificateChain -// Class representing a chain of certificates in order, with the -// first element being the child cert. -class LLCertificateChain : virtual public LLCertificateVector -{ - -public: - LLCertificateChain() {} - virtual ~LLCertificateChain() {} - // validate a certificate chain given the params. // Will throw exceptions on error virtual void validate(int validation_policy, - LLPointer ca_store, + LLPointer cert_chain, const LLSD& validation_params) =0; + }; - - inline bool operator==(const LLCertificateVector::iterator& _lhs, const LLCertificateVector::iterator& _rhs) { diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index edf5ce9b60..84ab9b9175 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -85,7 +85,6 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) { throw LLInvalidCertificate(this); } - _initLLSD(); } @@ -96,7 +95,6 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert) throw LLInvalidCertificate(this); } mCert = X509_dup(pCert); - _initLLSD(); } LLBasicCertificate::~LLBasicCertificate() @@ -150,9 +148,13 @@ std::vector LLBasicCertificate::getBinary() const } -LLSD LLBasicCertificate::getLLSD() const +void LLBasicCertificate::getLLSD(LLSD &llsd) { - return mLLSDInfo; + if (mLLSDInfo.isUndefined()) + { + _initLLSD(); + } + llsd = mLLSDInfo; } // Initialize the LLSD info for the certificate @@ -516,8 +518,9 @@ LLBasicCertificateVector::iterator LLBasicCertificateVector::find(const LLSD& pa cert++) { - found= TRUE; - LLSD cert_info = (*cert)->getLLSD(); + found= TRUE; + LLSD cert_info; + (*cert)->getLLSD(cert_info); for (LLSD::map_const_iterator param = params.beginMap(); param != params.endMap(); param++) @@ -543,7 +546,8 @@ LLBasicCertificateVector::iterator LLBasicCertificateVector::find(const LLSD& pa void LLBasicCertificateVector::insert(iterator _iter, LLPointer cert) { - LLSD cert_info = cert->getLLSD(); + LLSD cert_info; + cert->getLLSD(cert_info); if (cert_info.isMap() && cert_info.has(CERT_SHA1_DIGEST)) { LLSD existing_cert_info = LLSD::emptyMap(); @@ -691,7 +695,8 @@ LLBasicCertificateChain::LLBasicCertificateChain(const X509_STORE_CTX* store) while(untrusted_certs.size() > 0) { LLSD find_data = LLSD::emptyMap(); - LLSD cert_data = current->getLLSD(); + LLSD cert_data; + current->getLLSD(cert_data); // we simply build the chain via subject/issuer name as the // client should not have passed in multiple CA's with the same // subject name. If they did, it'll come out in the wash during @@ -850,12 +855,13 @@ bool _LLSDArrayIncludesValue(const LLSD& llsd_set, LLSD llsd_value) } void _validateCert(int validation_policy, - const LLPointer cert, + LLPointer cert, const LLSD& validation_params, int depth) { - LLSD current_cert_info = cert->getLLSD(); + LLSD current_cert_info; + cert->getLLSD(current_cert_info); // check basic properties exist in the cert if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING)) { @@ -943,8 +949,9 @@ bool _verify_signature(LLPointer parent, LLPointer child) { bool verify_result = FALSE; - LLSD cert1 = parent->getLLSD(); - LLSD cert2 = child->getLLSD(); + LLSD cert1, cert2; + parent->getLLSD(cert1); + child->getLLSD(cert2); X509 *signing_cert = parent->getOpenSSLX509(); X509 *child_cert = child->getOpenSSLX509(); if((signing_cert != NULL) && (child_cert != NULL)) @@ -979,6 +986,7 @@ bool _verify_signature(LLPointer parent, return verify_result; } + // validate the certificate chain against a store. // There are many aspects of cert validatioin policy involved in // trust validation. The policies in this validation algorithm include @@ -993,8 +1001,8 @@ bool _verify_signature(LLPointer parent, // and verify the last cert is in the certificate store, or points // to a cert in the store. It validates whether any cert in the chain // is trusted in the store, even if it's not the last one. -void LLBasicCertificateChain::validate(int validation_policy, - LLPointer ca_store, +void LLBasicCertificateStore::validate(int validation_policy, + LLPointer cert_chain, const LLSD& validation_params) { @@ -1002,8 +1010,8 @@ void LLBasicCertificateChain::validate(int validation_policy, { throw LLCertException(NULL, "No certs in chain"); } - iterator current_cert = begin(); - LLSD current_cert_info = (*current_cert)->getLLSD(); + iterator current_cert = cert_chain->begin(); + LLSD current_cert_info; LLSD validation_date; if (validation_params.has(CERT_VALIDATION_DATE)) { @@ -1012,6 +1020,7 @@ void LLBasicCertificateChain::validate(int validation_policy, if (validation_policy & VALIDATION_POLICY_HOSTNAME) { + (*current_cert)->getLLSD(current_cert_info); if(!validation_params.has(CERT_HOSTNAME)) { throw LLCertException((*current_cert), "No hostname passed in for validation"); @@ -1021,7 +1030,7 @@ void LLBasicCertificateChain::validate(int validation_policy, throw LLInvalidCertificate((*current_cert)); } - LL_INFOS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << + LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << "against the cert CN " << current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString() << LL_ENDL; if(!_cert_hostname_wildcard_match(validation_params[CERT_HOSTNAME].asString(), current_cert_info[CERT_SUBJECT_NAME][CERT_NAME_CN].asString())) @@ -1030,16 +1039,50 @@ void LLBasicCertificateChain::validate(int validation_policy, (*current_cert)); } } - + // check the cache of already validated certs + X509* cert_x509 = (*current_cert)->getOpenSSLX509(); + if(!cert_x509) + { + throw LLInvalidCertificate((*current_cert)); + } + std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); + t_cert_cache::iterator cache_entry = mTrustedCertCache.find(sha1_hash); + if(cache_entry != mTrustedCertCache.end()) + { + LL_DEBUGS("SECAPI") << "Found cert in cache" << LL_ENDL; + // this cert is in the cache, so validate the time. + if (validation_policy & VALIDATION_POLICY_TIME) + { + LLDate validation_date(time(NULL)); + if(validation_params.has(CERT_VALIDATION_DATE)) + { + validation_date = validation_params[CERT_VALIDATION_DATE]; + } + + if((validation_date < cache_entry->second.first) || + (validation_date > cache_entry->second.second)) + { + throw LLCertValidationExpirationException((*current_cert), validation_date); + } + } + // successfully found in cache + return; + } + if(current_cert_info.isUndefined()) + { + (*current_cert)->getLLSD(current_cert_info); + } + LLDate from_time = current_cert_info[CERT_VALID_FROM].asDate(); + LLDate to_time = current_cert_info[CERT_VALID_TO].asDate(); int depth = 0; LLPointer previous_cert; // loop through the cert chain, validating the current cert against the next one. - while(current_cert != end()) + while(current_cert != cert_chain->end()) { int local_validation_policy = validation_policy; - if(current_cert == begin()) + if(current_cert == cert_chain->begin()) { // for the child cert, we don't validate CA stuff local_validation_policy &= ~(VALIDATION_POLICY_CA_KU | @@ -1061,23 +1104,23 @@ void LLBasicCertificateChain::validate(int validation_policy, depth); // look for a CA in the CA store that may belong to this chain. - LLSD cert_llsd = (*current_cert)->getLLSD(); LLSD cert_search_params = LLSD::emptyMap(); // is the cert itself in the store? - cert_search_params[CERT_SHA1_DIGEST] = cert_llsd[CERT_SHA1_DIGEST]; - LLCertificateStore::iterator found_store_cert = ca_store->find(cert_search_params); - if(found_store_cert != ca_store->end()) + cert_search_params[CERT_SHA1_DIGEST] = current_cert_info[CERT_SHA1_DIGEST]; + LLCertificateStore::iterator found_store_cert = find(cert_search_params); + if(found_store_cert != end()) { + mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); return; } // is the parent in the cert store? cert_search_params = LLSD::emptyMap(); - cert_search_params[CERT_SUBJECT_NAME_STRING] = cert_llsd[CERT_ISSUER_NAME_STRING]; - if (cert_llsd.has(CERT_AUTHORITY_KEY_IDENTIFIER)) + cert_search_params[CERT_SUBJECT_NAME_STRING] = current_cert_info[CERT_ISSUER_NAME_STRING]; + if (current_cert_info.has(CERT_AUTHORITY_KEY_IDENTIFIER)) { - LLSD cert_aki = cert_llsd[CERT_AUTHORITY_KEY_IDENTIFIER]; + LLSD cert_aki = current_cert_info[CERT_AUTHORITY_KEY_IDENTIFIER]; if(cert_aki.has(CERT_AUTHORITY_KEY_IDENTIFIER_ID)) { cert_search_params[CERT_SUBJECT_KEY_IDENTFIER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_ID]; @@ -1087,11 +1130,10 @@ void LLBasicCertificateChain::validate(int validation_policy, cert_search_params[CERT_SERIAL_NUMBER] = cert_aki[CERT_AUTHORITY_KEY_IDENTIFIER_SERIAL]; } } - found_store_cert = ca_store->find(cert_search_params); + found_store_cert = find(cert_search_params); - if(found_store_cert != ca_store->end()) + if(found_store_cert != end()) { - LLSD foo = (*found_store_cert)->getLLSD(); // validate the store cert against the depth _validateCert(validation_policy & VALIDATION_POLICY_CA_BASIC_CONSTRAINTS, (*found_store_cert), @@ -1105,11 +1147,16 @@ void LLBasicCertificateChain::validate(int validation_policy, throw LLCertValidationInvalidSignatureException(*current_cert); } // successfully validated. + mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); return; } previous_cert = (*current_cert); current_cert++; - depth++; + depth++; + if(current_cert != current_cert != cert_chain->end()) + { + (*current_cert)->getLLSD(current_cert_info); + } } if (validation_policy & VALIDATION_POLICY_TRUSTED) { @@ -1118,6 +1165,7 @@ void LLBasicCertificateChain::validate(int validation_policy, throw LLCertValidationTrustException((*this)[size()-1]); } + mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); } @@ -1155,7 +1203,7 @@ void LLSecAPIBasicHandler::init() "CA.pem"); - LL_INFOS("SECAPI") << "Loading certificate store from " << store_file << LL_ENDL; + LL_DEBUGS("SECAPI") << "Loading certificate store from " << store_file << LL_ENDL; mStore = new LLBasicCertificateStore(store_file); // grab the application CA.pem file that contains the well-known certs shipped @@ -1465,7 +1513,7 @@ void LLSecAPIBasicHandler::saveCredential(LLPointer cred, bool sav { credential["authenticator"] = cred->getAuthenticator(); } - LL_INFOS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL; + LL_DEBUGS("SECAPI") << "Saving Credential " << cred->getGrid() << ":" << cred->userID() << " " << save_authenticator << LL_ENDL; setProtectedData("credential", cred->getGrid(), credential); //*TODO: If we're saving Agni credentials, should we write the // credentials to the legacy password.dat/etc? diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h index 4bbb73f062..3ddd36a81a 100644 --- a/indra/newview/llsechandler_basic.h +++ b/indra/newview/llsechandler_basic.h @@ -59,12 +59,13 @@ public: virtual std::string getPem() const; virtual std::vector getBinary() const; - virtual LLSD getLLSD() const; + virtual void getLLSD(LLSD &llsd); virtual X509* getOpenSSLX509() const; // set llsd elements for testing void setLLSD(const std::string name, const LLSD& value) { mLLSDInfo[name] = value; } + protected: // certificates are stored as X509 objects, as validation and @@ -173,8 +174,21 @@ public: // return the store id virtual std::string storeId() const; + // validate a certificate chain against a certificate store, using the + // given validation policy. + virtual void validate(int validation_policy, + LLPointer ca_chain, + const LLSD& validation_params); + protected: - std::vector >mCerts; + std::vector > mCerts; + + // cache of cert sha1 hashes to from/to date pairs, to improve + // performance of cert trust. Note, these are not the CA certs, + // but the certs that have been validated against this store. + typedef std::map > t_cert_cache; + t_cert_cache mTrustedCertCache; + std::string mFilename; }; @@ -189,11 +203,6 @@ public: virtual ~LLBasicCertificateChain() {} - // validate a certificate chain against a certificate store, using the - // given validation policy. - virtual void validate(int validation_policy, - LLPointer ca_store, - const LLSD& validation_params); }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0a464b3b6c..7022d83868 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2702,7 +2702,8 @@ LLSD transform_cert_args(LLPointer cert) { LLSD args = LLSD::emptyMap(); std::string value; - LLSD cert_info = cert->getLLSD(); + LLSD cert_info; + cert->getLLSD(cert_info); // convert all of the elements in the cert into // args for the xml dialog, so we have flexability to // display various parts of the cert by only modifying diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index da61840761..bc1a48e26a 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -247,7 +247,8 @@ int LLXMLRPCTransaction::Impl::_sslCertVerifyCallback(X509_STORE_CTX *ctx, void validation_params[CERT_HOSTNAME] = uri.hostName(); try { - chain->validate(VALIDATION_POLICY_SSL, store, validation_params); + // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects + store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params); } catch (LLCertValidationTrustException& cert_exception) { diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index fd680b24f0..d1330e2270 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -950,15 +950,15 @@ namespace tut test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); - test_chain->validate(0, test_store, validation_params); + test_store->validate(0, test_chain, validation_params); // add the root certificate to the chain and revalidate test_chain->add(new LLBasicCertificate(mX509RootCert)); - test_chain->validate(0, test_store, validation_params); + 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)); - test_chain->validate(0, test_store, validation_params); + test_store->validate(0, test_chain, validation_params); // basic failure cases test_chain = new LLBasicCertificateChain(NULL); @@ -967,14 +967,14 @@ namespace tut ensure_throws("no CA, with only a child cert", LLCertValidationTrustException, (*test_chain)[0], - test_chain->validate, + test_store->validate, VALIDATION_POLICY_TRUSTED, - test_store, + test_chain, validation_params); // validate without the trust flag. - test_chain->validate(0, test_store, validation_params); + test_store->validate(0, test_chain, validation_params); // clear out the store test_store = new LLBasicCertificateStore("mycertstore.pem"); @@ -983,9 +983,9 @@ namespace tut ensure_throws("no CA, with child and intermediate certs", LLCertValidationTrustException, (*test_chain)[1], - test_chain->validate, + test_store->validate, VALIDATION_POLICY_TRUSTED, - test_store, + test_chain, validation_params); // validate without the trust flag test_chain->validate(0, test_store, validation_params); @@ -994,7 +994,7 @@ namespace tut LLSD child_info = (*test_chain)[0]->getLLSD(); validation_params = LLSD::emptyMap(); validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_FROM].asDate().secondsSinceEpoch() + 1.0); - test_chain->validate(VALIDATION_POLICY_TIME, test_store, validation_params); + test_store->validate(VALIDATION_POLICY_TIME, test_chain, validation_params); validation_params = LLSD::emptyMap(); validation_params[CERT_VALIDATION_DATE] = child_info[CERT_VALID_FROM].asDate(); @@ -1005,9 +1005,9 @@ namespace tut ensure_throws("Child cert not yet valid" , LLCertValidationExpirationException, (*test_chain)[0], - test_chain->validate, + test_store->validate, VALIDATION_POLICY_TIME, - test_store, + test_chain, validation_params); validation_params = LLSD::emptyMap(); validation_params[CERT_VALIDATION_DATE] = LLDate(child_info[CERT_VALID_TO].asDate().secondsSinceEpoch() + 1.0); @@ -1016,9 +1016,9 @@ namespace tut ensure_throws("Child cert expired", LLCertValidationExpirationException, (*test_chain)[0], - test_chain->validate, + test_store->validate, VALIDATION_POLICY_TIME, - test_store, + test_chain, validation_params); // test SSL KU @@ -1026,7 +1026,7 @@ namespace tut test_chain = new LLBasicCertificateChain(NULL); test_chain->add(new LLBasicCertificate(mX509ChildCert)); test_chain->add(new LLBasicCertificate(mX509IntermediateCert)); - test_chain->validate(VALIDATION_POLICY_SSL_KU, test_store, validation_params); + test_store->validate(VALIDATION_POLICY_SSL_KU, test_chain, validation_params); test_chain = new LLBasicCertificateChain(NULL); test_chain->add(new LLBasicCertificate(mX509TestCert)); @@ -1034,9 +1034,9 @@ namespace tut ensure_throws("Cert doesn't have ku", LLCertKeyUsageValidationException, (*test_chain)[0], - test_chain->validate, + test_store->validate, VALIDATION_POLICY_SSL_KU, - test_store, + test_chain, validation_params); // test sha1RSA validation @@ -1044,7 +1044,7 @@ namespace tut test_chain->add(new LLBasicCertificate(mSha1RSATestCert)); test_chain->add(new LLBasicCertificate(mSha1RSATestCA)); - test_chain->validate(0, test_store, validation_params); + test_store->validate(0, test_chain, validation_params); } }; -- cgit v1.3 From a7d1c68c787fcccf888632b9787c4cc9b30393f7 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Mon, 24 May 2010 15:31:10 -0700 Subject: Fixup some certificate related unit tests --- indra/newview/llsechandler_basic.cpp | 2 +- indra/newview/tests/llsechandler_basic_test.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 84ab9b9175..a81cde3126 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1153,7 +1153,7 @@ void LLBasicCertificateStore::validate(int validation_policy, previous_cert = (*current_cert); current_cert++; depth++; - if(current_cert != current_cert != cert_chain->end()) + if(current_cert != cert_chain->end()) { (*current_cert)->getLLSD(current_cert_info); } diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index d1330e2270..dfbd596d39 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -328,7 +328,8 @@ namespace tut ensure_equals("Der Format is correct", memcmp(buffer, mDerFormat.c_str(), mDerFormat.length()), 0); - LLSD llsd_cert = test_cert->getLLSD(); + LLSD llsd_cert; + test_cert->getLLSD(llsd_cert); std::ostringstream llsd_value; llsd_value << LLSDOStreamer(llsd_cert) << std::endl; std::string llsd_cert_str = llsd_value.str(); @@ -988,10 +989,11 @@ namespace tut test_chain, validation_params); // validate without the trust flag - test_chain->validate(0, test_store, validation_params); + test_store->validate(0, test_chain, validation_params); // Test time validity - LLSD child_info = (*test_chain)[0]->getLLSD(); + 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, test_chain, validation_params); -- cgit v1.3 From 32ad37b3f7ca48564bd15de2664f323ad4a2d367 Mon Sep 17 00:00:00 2001 From: Roxie Linden Date: Mon, 24 May 2010 16:21:29 -0700 Subject: Few more touchups for the cert performance code --- indra/newview/llsechandler_basic.cpp | 5 ++--- indra/newview/tests/llsechandler_basic_test.cpp | 10 +++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'indra/newview/tests') diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index a81cde3126..5f24d4398a 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1006,7 +1006,7 @@ void LLBasicCertificateStore::validate(int validation_policy, const LLSD& validation_params) { - if(size() < 1) + if(cert_chain->size() < 1) { throw LLCertException(NULL, "No certs in chain"); } @@ -1160,9 +1160,8 @@ void LLBasicCertificateStore::validate(int validation_policy, } if (validation_policy & VALIDATION_POLICY_TRUSTED) { - LLPointer untrusted_ca_cert = (*this)[size()-1]; // we reached the end without finding a trusted cert. - throw LLCertValidationTrustException((*this)[size()-1]); + throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]); } mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index dfbd596d39..df0673a159 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -963,8 +963,15 @@ namespace tut // basic failure cases test_chain = new LLBasicCertificateChain(NULL); - //validate with only the child cert + //validate with only the child cert in chain, but child cert was previously + // trusted test_chain->add(new LLBasicCertificate(mX509ChildCert)); + + // 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], @@ -1033,6 +1040,7 @@ namespace tut test_chain = new LLBasicCertificateChain(NULL); test_chain->add(new LLBasicCertificate(mX509TestCert)); + test_store = new LLBasicCertificateStore("mycertstore.pem"); ensure_throws("Cert doesn't have ku", LLCertKeyUsageValidationException, (*test_chain)[0], -- cgit v1.3 From cca5aa48ae07a2d0e4f4a26e647b360c098cd831 Mon Sep 17 00:00:00 2001 From: karina Date: Wed, 26 May 2010 23:46:42 -0700 Subject: Add new mechanism for getting a unique machine id. --- indra/newview/CMakeLists.txt | 2 + indra/newview/llappviewer.cpp | 2 + indra/newview/llmachineid.cpp | 267 +++++++++++++++++++++ indra/newview/llmachineid.h | 56 +++++ indra/newview/llsechandler_basic.cpp | 19 +- indra/newview/llxmlrpctransaction.cpp | 6 +- .../newview/skins/default/xui/en/notifications.xml | 31 +++ indra/newview/tests/llsechandler_basic_test.cpp | 15 +- 8 files changed, 380 insertions(+), 18 deletions(-) create mode 100644 indra/newview/llmachineid.cpp create mode 100644 indra/newview/llmachineid.h (limited to 'indra/newview/tests') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d77d53f6af..ec0116bd87 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -272,6 +272,7 @@ set(viewer_SOURCE_FILES lllogchat.cpp llloginhandler.cpp lllogininstance.cpp + llmachineid.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -787,6 +788,7 @@ set(viewer_HEADER_FILES lllogchat.h llloginhandler.h lllogininstance.h + llmachineid.h llmanip.h llmaniprotate.h llmanipscale.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f7f7cb599e..5756eade87 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -195,6 +195,7 @@ // Include for security api initialization #include "llsecapi.h" +#include "llmachineid.h" // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either @@ -619,6 +620,7 @@ bool LLAppViewer::init() // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. LLCurl::initClass(); + LLMachineID::init(); initThreads(); writeSystemInfo(); diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp new file mode 100644 index 0000000000..b691baaf08 --- /dev/null +++ b/indra/newview/llmachineid.cpp @@ -0,0 +1,267 @@ +/** + * @file llmachineid.cpp + * @brief retrieves unique machine ids + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "lluuid.h" +#include "llmachineid.h" +#define _WIN32_DCOM +#include +using namespace std; +#include +#include + +unsigned char static_unique_id[] = {0,0,0,0,0,0}; +bool static has_static_unique_id = false; + +// get an unique machine id. +// NOT THREAD SAFE - do before setting up threads. +// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot, Go figure?? + +S32 LLMachineID::init() +{ + memset(static_unique_id,0,sizeof(static_unique_id)); + size_t len = sizeof(static_unique_id); + S32 ret_code = 0; +#if LL_WINDOWS +# pragma comment(lib, "wbemuuid.lib") + + // algorithm to detect BIOS serial number found at: + // http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx + // we can't use the MAC address since on Windows 7, the first returned MAC address changes with every reboot. + + + HRESULT hres; + + // Step 1: -------------------------------------------------- + // Initialize COM. ------------------------------------------ + + hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hex << hres << LL_ENDL; + return 1; // Program has failed. + } + + // Step 2: -------------------------------------------------- + // Set general COM security levels -------------------------- + // Note: If you are using Windows 2000, you need to specify - + // the default authentication credentials for a user by using + // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ---- + // parameter of CoInitializeSecurity ------------------------ + + hres = CoInitializeSecurity( + NULL, + -1, // COM authentication + NULL, // Authentication services + NULL, // Reserved + RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication + RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation + NULL, // Authentication info + EOAC_NONE, // Additional capabilities + NULL // Reserved + ); + + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Failed to initialize security. Error code = 0x" << hex << hres << LL_ENDL; + CoUninitialize(); + return 1; // Program has failed. + } + + // Step 3: --------------------------------------------------- + // Obtain the initial locator to WMI ------------------------- + + IWbemLocator *pLoc = NULL; + + hres = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *) &pLoc); + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << LL_ENDL; + CoUninitialize(); + return 1; // Program has failed. + } + + // Step 4: ----------------------------------------------------- + // Connect to WMI through the IWbemLocator::ConnectServer method + + IWbemServices *pSvc = NULL; + + // Connect to the root\cimv2 namespace with + // the current user and obtain pointer pSvc + // to make IWbemServices calls. + hres = pLoc->ConnectServer( + _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace + NULL, // User name. NULL = current user + NULL, // User password. NULL = current + 0, // Locale. NULL indicates current + NULL, // Security flags. + 0, // Authority (e.g. Kerberos) + 0, // Context object + &pSvc // pointer to IWbemServices proxy + ); + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Could not connect. Error code = 0x" << hex << hres << LL_ENDL; + pLoc->Release(); + CoUninitialize(); + return 1; // Program has failed. + } + + LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL; + + + // Step 5: -------------------------------------------------- + // Set security levels on the proxy ------------------------- + + hres = CoSetProxyBlanket( + pSvc, // Indicates the proxy to set + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + NULL, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + NULL, // client identity + EOAC_NONE // proxy capabilities + ); + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hex << hres << LL_ENDL; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return 1; // Program has failed. + } + + // Step 6: -------------------------------------------------- + // Use the IWbemServices pointer to make requests of WMI ---- + + // For example, get the name of the operating system + IEnumWbemClassObject* pEnumerator = NULL; + hres = pSvc->ExecQuery( + bstr_t("WQL"), + bstr_t("SELECT * FROM Win32_OperatingSystem"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &pEnumerator); + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << hex << hres << LL_ENDL; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return 1; // Program has failed. + } + + // Step 7: ------------------------------------------------- + // Get the data from the query in step 6 ------------------- + + IWbemClassObject *pclsObj = NULL; + ULONG uReturn = 0; + + while (pEnumerator) + { + HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, + &pclsObj, &uReturn); + + if(0 == uReturn) + { + break; + } + + VARIANT vtProp; + + // Get the value of the Name property + hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); + LL_DEBUGS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL; + // use characters in the returned Serial Number to create a byte array of size len + BSTR serialNumber ( vtProp.bstrVal); + unsigned int j = 0; + while( vtProp.bstrVal[j] != 0) + { + for (unsigned int i = 0; i < len; i++) + { + if (vtProp.bstrVal[j] == 0) + break; + + static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]); + j++; + } + } + VariantClear(&vtProp); + + pclsObj->Release(); + pclsObj = NULL; + break; + } + + // Cleanup + // ======== + + if (pSvc) + pSvc->Release(); + if (pLoc) + pLoc->Release(); + if (pEnumerator) + pEnumerator->Release(); + CoUninitialize(); + ret_code=0; +#else + ret_code = LLUUID::getNodeID(&static_unique_id); +#endif + has_static_unique_id = true; + return ret_code; +} + + +S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len) +{ + if (has_static_unique_id) + { + memcpy ( unique_id, &static_unique_id, len); + LL_DEBUGS("AppInit") << "UniqueID: " << unique_id[0] << unique_id[1]<< unique_id[2] << unique_id[3] << unique_id[4] << unique_id [5] << LL_ENDL; + return 1; + } + return 0; +} + + + + diff --git a/indra/newview/llmachineid.h b/indra/newview/llmachineid.h new file mode 100644 index 0000000000..8160309b47 --- /dev/null +++ b/indra/newview/llmachineid.h @@ -0,0 +1,56 @@ +/** + * @file llmachineid.h + * @brief retrieves unique machine ids + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMACHINEID_H +#define LL_LLMACHINEID_H + + +class LLMachineID +{ +public: + LLMachineID(); + virtual ~LLMachineID(); + static S32 getUniqueID(unsigned char *unique_id, size_t len); + static S32 init(); + +protected: + +private: + + +}; + + + + + +#endif // LL_LLMACHINEID_H diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index edf5ce9b60..c006f4dd0d 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -52,6 +52,7 @@ LLS * By copying, modifying or distributing this software, you acknowledge #include #include #include +#include "llmachineid.h" @@ -1195,9 +1196,9 @@ void LLSecAPIBasicHandler::_readProtectedData() U8 buffer[BUFFER_READ_SIZE]; U8 decrypted_buffer[BUFFER_READ_SIZE]; int decrypted_length; - unsigned char MACAddress[MAC_ADDRESS_BYTES]; - LLUUID::getNodeID(MACAddress); - LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES); + unsigned char unique_id[MAC_ADDRESS_BYTES]; + LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); + LLXORCipher cipher(unique_id, sizeof(unique_id)); // read in the salt and key protected_data_stream.read((char *)salt, STORE_SALT_SIZE); @@ -1281,9 +1282,9 @@ void LLSecAPIBasicHandler::_writeProtectedData() EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit(&ctx, EVP_rc4(), salt, NULL); - unsigned char MACAddress[MAC_ADDRESS_BYTES]; - LLUUID::getNodeID(MACAddress); - LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES); + unsigned char unique_id[MAC_ADDRESS_BYTES]; + LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); + LLXORCipher cipher(unique_id, sizeof(unique_id)); cipher.encrypt(salt, STORE_SALT_SIZE); protected_data_stream.write((const char *)salt, STORE_SALT_SIZE); @@ -1501,9 +1502,9 @@ std::string LLSecAPIBasicHandler::_legacyLoadPassword() } // Decipher with MAC address - unsigned char MACAddress[MAC_ADDRESS_BYTES]; - LLUUID::getNodeID(MACAddress); - LLXORCipher cipher(MACAddress, 6); + unsigned char unique_id[MAC_ADDRESS_BYTES]; + LLMachineID::getUniqueID(unique_id, sizeof(unique_id)); + LLXORCipher cipher(unique_id, sizeof(unique_id)); cipher.decrypt(&buffer[0], buffer.size()); return std::string((const char*)&buffer[0], buffer.size()); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index da61840761..58ba9e1378 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -514,7 +514,9 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status, "Despite our best efforts, something unexpected has gone wrong. \n" " \n" "Please check secondlife.com/status \n" - "to see if there is a known problem with the service."; + "to see if there is a known problem with the service.\n" + "If you continue to experience problems," + "Please check your network and firewall setup.\n"; mStatusURI = "http://secondlife.com/status/"; } @@ -550,7 +552,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code) "Often this means that your computer\'s clock is set incorrectly.\n" "Please go to Control Panels and make sure the time and date\n" "are set correctly.\n" - "\n" + "Also check that your network and firewall are setup correctly.\n" "If you continue to receive this error, please go\n" "to the Support section of the SecondLife.com web site\n" "and report the problem."; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 999f804e71..b9aec7dd63 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6182,6 +6182,37 @@ Avatar '[NAME]' entered appearance mode. Avatar '[NAME]' left appearance mode. + + We're having trouble connecting using [PROTOCOL] [HOSTID]. + Please check your network and firewall setup. +
+