diff options
37 files changed, 2479 insertions, 1096 deletions
| diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 104629c157..db7ac2f154 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -171,6 +171,7 @@ void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp)  	resp->mUri = LLURI(uri);  	search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(),  		   RES_SRV, resp); +	llinfos << "Rewritten " << uri << llendl;  }  LLQueryResponder::LLQueryResponder() diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index b2b17fdd56..296d827a20 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -555,26 +555,23 @@ std::string LLDir::getForbiddenFileChars()  	return "\\/:*?\"<>|";  } -void LLDir::setLindenUserDir(const std::string &first, const std::string &last) +void LLDir::setLindenUserDir(const std::string &username)  {  	// if both first and last aren't set, assume we're grabbing the cached dir -	if (!first.empty() && !last.empty()) +	if (!username.empty())  	{  		// some platforms have case-sensitive filesystems, so be  		// utterly consistent with our firstname/lastname case. -		std::string firstlower(first); -		LLStringUtil::toLower(firstlower); -		std::string lastlower(last); -		LLStringUtil::toLower(lastlower); +		std::string userlower(username); +		LLStringUtil::toLower(userlower); +		LLStringUtil::replaceChar(userlower, ' ', '_');  		mLindenUserDir = getOSUserAppDir();  		mLindenUserDir += mDirDelimiter; -		mLindenUserDir += firstlower; -		mLindenUserDir += "_"; -		mLindenUserDir += lastlower; +		mLindenUserDir += userlower;  	}  	else  	{ -		llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl; +		llerrs << "NULL name for LLDir::setLindenUserDir" << llendl;  	}  	dumpCurrentDirectories();	 @@ -592,27 +589,25 @@ void LLDir::setChatLogsDir(const std::string &path)  	}  } -void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last) +void LLDir::setPerAccountChatLogsDir(const std::string &username)  {  	// if both first and last aren't set, assume we're grabbing the cached dir -	if (!first.empty() && !last.empty()) +	if (!username.empty())  	{  		// some platforms have case-sensitive filesystems, so be  		// utterly consistent with our firstname/lastname case. -		std::string firstlower(first); -		LLStringUtil::toLower(firstlower); -		std::string lastlower(last); -		LLStringUtil::toLower(lastlower); -		mPerAccountChatLogsDir = getChatLogsDir(); -		mPerAccountChatLogsDir += mDirDelimiter; -		mPerAccountChatLogsDir += firstlower; -		mPerAccountChatLogsDir += "_"; -		mPerAccountChatLogsDir += lastlower; +		std::string userlower(username); +		LLStringUtil::toLower(userlower); +		LLStringUtil::replaceChar(userlower, ' ', '_'); +		mLindenUserDir = getChatLogsDir(); +		mLindenUserDir += mDirDelimiter; +		mLindenUserDir += userlower;  	}  	else  	{ -		llwarns << "Invalid name for LLDir::setPerAccountChatLogsDir" << llendl; +		llerrs << "NULL name for LLDir::setPerAccountChatLogsDir" << llendl;  	} +	  }  void LLDir::setSkinFolder(const std::string &skin_folder) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 206e3223e3..9c1e992eca 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -137,8 +137,8 @@ class LLDir  	static std::string getForbiddenFileChars();  	virtual void setChatLogsDir(const std::string &path);		// Set the chat logs dir to this user's dir -	virtual void setPerAccountChatLogsDir(const std::string &first, const std::string &last);		// Set the per user chat log directory. -	virtual void setLindenUserDir(const std::string &first, const std::string &last);		// Set the linden user dir to this user's dir +	virtual void setPerAccountChatLogsDir(const std::string &username);		// Set the per user chat log directory. +	virtual void setLindenUserDir(const std::string &username);		// Set the linden user dir to this user's dir  	virtual void setSkinFolder(const std::string &skin_folder);  	virtual bool setCacheDir(const std::string &path); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9430bb1d56..4be6fb940e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1407,11 +1407,11 @@ if (WINDOWS)        # Note the need to specify multiple names explicitly.        set(GOOGLE_PERF_TOOLS_SOURCE          ${SHARED_LIB_STAGING_DIR}/Release/libtcmalloc_minimal.dll -	${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll -	${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll -	) -    endif(USE_GOOGLE_PERFTOOLS) -	   +        ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libtcmalloc_minimal.dll +        ${SHARED_LIB_STAGING_DIR}/Debug/libtcmalloc_minimal-debug.dll +        ) +     endif(USE_GOOGLE_PERFTOOLS) +       set(COPY_INPUT_DEPENDECIES        # The following commented dependencies are determined at variably at build time. Can't do this here. @@ -1504,11 +1504,11 @@ if (WINDOWS)          --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}          --grid=${GRID}          --source=${CMAKE_CURRENT_SOURCE_DIR} -	--touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat +        --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/copy_touched.bat        DEPENDS  -	${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py -	stage_third_party_libs -	${COPY_INPUT_DEPENDECIES} +        ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py +        stage_third_party_libs +        ${COPY_INPUT_DEPENDECIES}        COMMENT "Performing viewer_manifest copy"        ) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index d7bb64ce8a..0eb98e3311 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -20,11 +20,7 @@  					<key>tags</key>  						<array>  							<string>AppInit</string> -							<string>SystemInfo</string> -							<string>TextureCache</string> -							<string>AppCache</string> -							<string>Window</string> -							<string>RenderInit</string> +							<string>LLLogin</string>  						</array>  				</map>  				<map> @@ -40,6 +36,8 @@  						</array>  					<key>tags</key>  						<array> +							<string>AppInit</string> +							<string>LLLogin</string>  						</array>  				</map>  			</array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7d98a4b6ce..75ee389750 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1629,6 +1629,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>CurrentGrid</key> +    <map> +      <key>Comment</key> +      <string>Currently Selected Grid</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string></string> +    </map>      <key>CustomServer</key>      <map>        <key>Comment</key> @@ -3420,7 +3431,7 @@        <key>Type</key>        <string>Boolean</string>        <key>Value</key> -      <integer>0</integer> +      <integer>1</integer>      </map>      <key>ForceMandatoryUpdate</key>      <map> @@ -7594,6 +7605,17 @@        <key>Value</key>        <integer>0</integer>      </map> +    <key>SecondLifeEnterprise</key> +    <map> +      <key>Comment</key> +      <string>Enables Second Life Enterprise features</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>	      <key>SelectMovableOnly</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fb1bded795..cc32346441 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -191,6 +191,9 @@  #include "llparcel.h"  #include "llavatariconctrl.h" +// Include for security api initialization +#include "llsecapi.h" +  // *FIX: These extern globals should be cleaned up.  // The globals either represent state/config/resource-storage of either   // this app, or another 'component' of the viewer. App globals should be  @@ -506,35 +509,6 @@ public:  	}  }; -void LLAppViewer::initGridChoice() -{ -	// Load	up the initial grid	choice from: -	//	- hard coded defaults... -	//	- command line settings... -	//	- if dev build,	persisted settings... - -	// Set the "grid choice", this is specified	by command line. -	std::string	grid_choice	= gSavedSettings.getString("CmdLineGridChoice"); -	LLViewerLogin::getInstance()->setGridChoice(grid_choice); - -	// Load last server choice by default  -	// ignored if the command line grid	choice has been	set -	if(grid_choice.empty()) -	{ -		S32	server = gSavedSettings.getS32("ServerChoice"); -		server = llclamp(server, 0,	(S32)GRID_INFO_COUNT - 1); -		if(server == GRID_INFO_OTHER) -		{ -			std::string custom_server = gSavedSettings.getString("CustomServer"); -			LLViewerLogin::getInstance()->setGridChoice(custom_server); -		} -		else if(server != (S32)GRID_INFO_NONE) -		{ -			LLViewerLogin::getInstance()->setGridChoice((EGridInfo)server); -		} -	} -} -  //virtual  bool LLAppViewer::initSLURLHandler()  { @@ -646,7 +620,7 @@ bool LLAppViewer::init()      LLCurl::initClass();      initThreads(); - +    initializeSecHandler();      writeSystemInfo();  	// Build a string representing the current version number. @@ -776,10 +750,6 @@ bool LLAppViewer::init()  		return false;  	} -	// Always fetch the Ethernet MAC address, needed both for login -	// and password load. -	LLUUID::getNodeID(gMACAddress); -  	// Prepare for out-of-memory situations, during which we will crash on  	// purpose and save a dump.  #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP @@ -1462,13 +1432,6 @@ bool LLAppViewer::cleanup()  	llinfos << "Saving Data" << llendflush; -	// Quitting with "Remember Password" turned off should always stomp your -	// saved password, whether or not you successfully logged in.  JC -	if (!gSavedSettings.getBOOL("RememberPassword")) -	{ -		LLStartUp::deletePasswordFromDisk(); -	} -	  	// Store the time of our current logoff  	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); @@ -2022,7 +1985,6 @@ bool LLAppViewer::initConfiguration()          }      } -    initGridChoice();  	// If we have specified crash on startup, set the global so we'll trigger the crash at the right time  	if(clp.hasOption("crashonstartup")) @@ -2511,7 +2473,7 @@ void LLAppViewer::writeSystemInfo()  	// The user is not logged on yet, but record the current grid choice login url  	// which may have been the intended grid. This can b -	gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); +	gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();  	// *FIX:Mani - move this ddown in llappviewerwin32  #ifdef LL_WINDOWS @@ -2678,10 +2640,10 @@ void LLAppViewer::handleViewerCrash()  		gMessageSystem->stopLogging();  	} -	LLWorld::getInstance()->getInfo(gDebugInfo); +	//LLWorld::getInstance()->getInfo(gDebugInfo);  	// Close the debug file -	pApp->writeDebugInfo(); +	//pApp->writeDebugInfo();  	LLError::logToFile(""); @@ -4271,7 +4233,7 @@ void LLAppViewer::launchUpdater()  #endif  	// *TODO change userserver to be grid on both viewer and sim, since  	// userserver no longer exists. -	query_map["userserver"] = LLViewerLogin::getInstance()->getGridLabel(); +	query_map["userserver"] = LLGridManager::getInstance()->getGridLabel();  	query_map["channel"] = gSavedSettings.getString("VersionChannelName");  	// *TODO constantize this guy  	// *NOTE: This URL is also used in win_setup/lldownloader.cpp diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 40e74061b5..870d47aa79 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -186,7 +186,6 @@ private:  	bool initThreads(); // Initialize viewer threads, return false on failure.  	bool initConfiguration(); // Initialize settings from the command line/config file. -	void initGridChoice();  	bool initCache(); // Initialize local client cache. diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index 00c05445e1..207270c0ad 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -284,7 +284,7 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,  	static std::string transactionURI;  	if (transactionURI.empty())  	{ -		transactionURI = LLViewerLogin::getInstance()->getHelperURI() + "currency.php"; +		transactionURI = LLGridManager::getInstance()->getHelperURI() + "currency.php";  	}  	delete mTransaction; diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 9b88923e7e..10a4908f3a 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -837,7 +837,7 @@ void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCVa  	static std::string transaction_uri;  	if (transaction_uri.empty())  	{ -		transaction_uri = LLViewerLogin::getInstance()->getHelperURI() + "landtool.php"; +		transaction_uri = LLGridManager::getInstance()->getHelperURI() + "landtool.php";  	}  	const char* method; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index e0f2fca580..a52fe131cd 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -545,7 +545,7 @@ LLSD LLFloaterReporter::gatherReport()  	mCopyrightWarningSeen = FALSE;  	std::ostringstream summary; -	if (!LLViewerLogin::getInstance()->isInProductionGrid()) +	if (!LLGridManager::getInstance()->isInProductionGrid())  	{  		summary << "Preview ";  	} diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp index 1be3430e07..7d43f6a8cc 100644 --- a/indra/newview/llloginhandler.cpp +++ b/indra/newview/llloginhandler.cpp @@ -35,12 +35,13 @@  #include "llloginhandler.h"  // viewer includes +#include "llsecapi.h"  #include "llpanellogin.h"			// save_password_to_disk()  #include "llstartup.h"				// getStartupState()  #include "llurlsimstring.h"  #include "llviewercontrol.h"		// gSavedSettings  #include "llviewernetwork.h"		// EGridInfo -#include "llviewerwindow.h"			// getWindow() +#include "llviewerwindow.h"                    // getWindow()  // library includes  #include "llmd5.h" @@ -59,109 +60,28 @@ bool LLLoginHandler::parseDirectLogin(std::string url)  	LLURI uri(url);  	parse(uri.queryMap()); -	if (/*mWebLoginKey.isNull() ||*/ -		mFirstName.empty() || -		mLastName.empty()) -	{ -		return false; -	} -	else -	{ -		return true; -	} +	// NOTE: Need to add direct login as per identity evolution +	return true;  } -  void LLLoginHandler::parse(const LLSD& queryMap)  { -	//mWebLoginKey = queryMap["web_login_key"].asUUID(); -	mFirstName = queryMap["first_name"].asString(); -	mLastName = queryMap["last_name"].asString(); -	EGridInfo grid_choice = GRID_INFO_NONE; -	if (queryMap["grid"].asString() == "aditi") -	{ -		grid_choice = GRID_INFO_ADITI; -	} -	else if (queryMap["grid"].asString() == "agni") -	{ -		grid_choice = GRID_INFO_AGNI; -	} -	else if (queryMap["grid"].asString() == "siva") -	{ -		grid_choice = GRID_INFO_SIVA; -	} -	else if (queryMap["grid"].asString() == "damballah") -	{ -		grid_choice = GRID_INFO_DAMBALLAH; -	} -	else if (queryMap["grid"].asString() == "durga") +	if (queryMap.has("grid"))  	{ -		grid_choice = GRID_INFO_DURGA; +		LLGridManager::getInstance()->setGridChoice(queryMap["grid"].asString());  	} -	else if (queryMap["grid"].asString() == "shakti") -	{ -		grid_choice = GRID_INFO_SHAKTI; -	} -	else if (queryMap["grid"].asString() == "soma") -	{ -		grid_choice = GRID_INFO_SOMA; -	} -	else if (queryMap["grid"].asString() == "ganga") -	{ -		grid_choice = GRID_INFO_GANGA; -	} -	else if (queryMap["grid"].asString() == "vaak") -	{ -		grid_choice = GRID_INFO_VAAK; -	} -	else if (queryMap["grid"].asString() == "uma") -	{ -		grid_choice = GRID_INFO_UMA; -	} -	else if (queryMap["grid"].asString() == "mohini") -	{ -		grid_choice = GRID_INFO_MOHINI; -	} -	else if (queryMap["grid"].asString() == "yami") -	{ -		grid_choice = GRID_INFO_YAMI; -	} -	else if (queryMap["grid"].asString() == "nandi") -	{ -		grid_choice = GRID_INFO_NANDI; -	} -	else if (queryMap["grid"].asString() == "mitra") -	{ -		grid_choice = GRID_INFO_MITRA; -	} -	else if (queryMap["grid"].asString() == "radha") -	{ -		grid_choice = GRID_INFO_RADHA; -	} -	else if (queryMap["grid"].asString() == "ravi") -	{ -		grid_choice = GRID_INFO_RAVI; -	} -	else if (queryMap["grid"].asString() == "aruna") -	{ -		grid_choice = GRID_INFO_ARUNA; -	} - -	if(grid_choice != GRID_INFO_NONE) -	{ -		LLViewerLogin::getInstance()->setGridChoice(grid_choice); -	} - +	 +	  	std::string startLocation = queryMap["location"].asString(); - +	  	if (startLocation == "specify")  	{ -		LLURLSimString::setString(queryMap["region"].asString()); +	  LLURLSimString::setString(queryMap["region"].asString());  	} -	else if (!startLocation.empty()) // "last" or "home" or ??? (let LLURLSimString figure it out) +	else if (!startLocation.empty())  	{ -		LLURLSimString::setString(startLocation); +	  LLURLSimString::setString(startLocation);  	}  } @@ -212,40 +132,68 @@ bool LLLoginHandler::handle(const LLSD& tokens,  		return true;  	} -	std::string password = query_map["password"].asString(); - -	if (!password.empty()) +	if  (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page           	{ -		gSavedSettings.setBOOL("RememberPassword", TRUE); - -		if (password.substr(0,3) != "$1$") -		{ -			LLMD5 pass((unsigned char*)password.c_str()); -			char md5pass[33];		/* Flawfinder: ignore */ -			pass.hex_digest(md5pass); -			std::string hashed_password = ll_safe_string(md5pass, 32); -			LLStartUp::savePasswordToDisk(hashed_password); -		} +	  // as the login page may change from grid to grid, as well as +	  // things like username/password/etc, we simply refresh the +	  // login page to make sure everything is set up correctly +	  LLPanelLogin::loadLoginPage(); +	  LLStartUp::setStartupState( STATE_LOGIN_CLEANUP );  	} -			 +	return true; +} + + -	if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page +//  Initialize the credentials                                                                                               +// If the passed in URL contains login info, parse                                                                           +// that into a credential and web login key.  Otherwise                                                                      +// check the command line.  If the command line                                                                              +// does not contain any login creds, load the last saved                                                                     +// ones from the protected credential store.                                                                                 +// This always returns with a credential structure set in the                                                                +// login handler                                                                                                             +LLPointer<LLCredential> LLLoginHandler::initializeLoginInfo(const std::string& url)                                          +{                                                                                                                            +	LLURI uri(url);                                                                                                       +	LLPointer<LLCredential> result = NULL;                                                                                +	parse(uri.queryMap());                                                                                                +	// we weren't able to parse login info from the slurl,                                                                +	// so try to load it from the UserLoginInfo                                                                           +	result = loadSavedUserLoginInfo();                                                                                    +	if (result.isNull())                                                                                                  +	{                                                                                                                     +		result =  gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGridName());                        +	}                                                                                                                     +	 +	return result;                                                                                                        +}  + + +LLPointer<LLCredential> LLLoginHandler::loadSavedUserLoginInfo() +{ +  // load the saved user login info into a LLCredential. +  // perhaps this should be moved. +	LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); +	if (cmd_line_login.size() == 3)   	{ -		if (!mFirstName.empty() || !mLastName.empty()) -		{ -			// Fill in the name, and maybe the password -			LLPanelLogin::setFields(mFirstName, mLastName, password); -		} - -		//if (mWebLoginKey.isNull()) -		//{ -		//	LLPanelLogin::loadLoginPage(); -		//} -		//else -		//{ -		//	LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); -		//} -		LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); -	} -	return true; +	 +		LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); +		char md5pass[33];               /* Flawfinder: ignore */ +		pass.hex_digest(md5pass); +		LLSD identifier = LLSD::emptyMap(); +		identifier["type"] = "agent"; +		identifier["first_name"] = cmd_line_login[0]; +		identifier["last_name"] = cmd_line_login[1]; +		 +		LLSD authenticator = LLSD::emptyMap(); +		authenticator["type"] = "hash"; +		authenticator["algorithm"] = "md5"; +		authenticator["secret"] = md5pass; +		// yuck, we'll fix this with mani's changes. +		gSavedSettings.setBOOL("AutoLogin", TRUE); +		return gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGridName(),  +													   identifier, authenticator); +	} +	return NULL;  } diff --git a/indra/newview/llloginhandler.h b/indra/newview/llloginhandler.h index ac4648761b..ec2459c835 100644 --- a/indra/newview/llloginhandler.h +++ b/indra/newview/llloginhandler.h @@ -34,6 +34,7 @@  #define LLLOGINHANDLER_H  #include "llcommandhandler.h" +#include "llsecapi.h"  class LLLoginHandler : public LLCommandHandler  { @@ -46,19 +47,15 @@ class LLLoginHandler : public LLCommandHandler  	// secondlife:///app/login?first=Bob&last=Dobbs  	bool parseDirectLogin(std::string url); -	std::string getFirstName() const { return mFirstName; } -	std::string getLastName() const { return mLastName; } -  	// Web-based login unsupported  	//LLUUID getWebLoginKey() const { return mWebLoginKey; } +	LLPointer<LLCredential> loadSavedUserLoginInfo();   +	LLPointer<LLCredential> initializeLoginInfo(const std::string& url); +  private:  	void parse(const LLSD& queryMap); -private: -	std::string mFirstName; -	std::string mLastName; -	//LLUUID mWebLoginKey;  };  extern LLLoginHandler gLoginHandler; diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 24c72c65ce..bb45cc93ea 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -55,6 +55,7 @@  #if LL_LINUX || LL_SOLARIS  #include "lltrans.h"  #endif +#include "llsecapi.h"  static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";  static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; @@ -83,14 +84,14 @@ LLLoginInstance::~LLLoginInstance()  {  } -void LLLoginInstance::connect(const LLSD& credentials) +void LLLoginInstance::connect(LLPointer<LLCredential> credentials)  {  	std::vector<std::string> uris; -	LLViewerLogin::getInstance()->getLoginURIs(uris); +	LLGridManager::getInstance()->getLoginURIs(uris);  	connect(uris.front(), credentials);  } -void LLLoginInstance::connect(const std::string& uri, const LLSD& credentials) +void LLLoginInstance::connect(const std::string& uri, LLPointer<LLCredential> credentials)  {  	mAttemptComplete = false; // Reset attempt complete at this point!  	constructAuthParams(credentials); @@ -102,7 +103,7 @@ void LLLoginInstance::reconnect()  	// Sort of like connect, only using the pre-existing  	// request params.  	std::vector<std::string> uris; -	LLViewerLogin::getInstance()->getLoginURIs(uris); +	LLGridManager::getInstance()->getLoginURIs(uris);  	mLoginModule->connect(uris.front(), mRequestData);  } @@ -118,7 +119,7 @@ LLSD LLLoginInstance::getResponse()  	return mResponseData;   } -void LLLoginInstance::constructAuthParams(const LLSD& credentials) +void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credential)  {  	// Set up auth request options.  //#define LL_MINIMIAL_REQUESTED_OPTIONS @@ -155,20 +156,18 @@ void LLLoginInstance::constructAuthParams(const LLSD& credentials)  		gSavedSettings.setBOOL("UseDebugMenus", TRUE);  		requested_options.append("god-connect");  	} +	 +	// (re)initialize the request params with creds. +	LLSD request_params = user_credential->getLoginParams();  	char hashed_mac_string[MD5HEX_STR_SIZE];		/* Flawfinder: ignore */  	LLMD5 hashed_mac; -	hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); +	unsigned char MACAddress[MAC_ADDRESS_BYTES]; +	LLUUID::getNodeID(MACAddress);	 +	hashed_mac.update( MACAddress, MAC_ADDRESS_BYTES );  	hashed_mac.finalize();  	hashed_mac.hex_digest(hashed_mac_string); - -	// prepend "$1$" to the password to indicate its the md5'd version. -	std::string dpasswd("$1$"); -	dpasswd.append(credentials["passwd"].asString()); - -	// (re)initialize the request params with creds. -	LLSD request_params(credentials); -	request_params["passwd"] = dpasswd; +	  	request_params["start"] = construct_start_string();  	request_params["skipoptional"] = mSkipOptionalUpdate;  	request_params["agree_to_tos"] = false; // Always false here. Set true in  diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index c8704eddb4..44271bb75e 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -36,6 +36,7 @@  #include "lleventdispatcher.h"  #include <boost/scoped_ptr.hpp>  #include <boost/function.hpp> +#include "llsecapi.h"  class LLLogin;  class LLEventStream;  class LLNotificationsInterface; @@ -48,8 +49,8 @@ public:  	LLLoginInstance();  	~LLLoginInstance(); -	void connect(const LLSD& credential); // Connect to the current grid choice. -	void connect(const std::string& uri, const LLSD& credential);	// Connect to the given uri. +	void connect(LLPointer<LLCredential> credentials); // Connect to the current grid choice. +	void connect(const std::string& uri, LLPointer<LLCredential> credentials);	// Connect to the given uri.  	void reconnect(); // reconnect using the current credentials.  	void disconnect(); @@ -81,7 +82,7 @@ public:  	void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; }  private: -	void constructAuthParams(const LLSD& credentials);  +	void constructAuthParams(LLPointer<LLCredential> user_credentials);  	void updateApp(bool mandatory, const std::string& message);  	bool updateDialogCallback(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 87d101b00f..6978d05389 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -51,6 +51,7 @@  #include "llfocusmgr.h"  #include "lllineeditor.h"  #include "llnotificationsutil.h" +#include "llsecapi.h"  #include "llstartup.h"  #include "lltextbox.h"  #include "llui.h" @@ -77,6 +78,7 @@  #pragma warning(disable: 4355)      // 'this' used in initializer list  #endif  // LL_WINDOWS +#include "llsdserialize.h"  #define USE_VIEWER_AUTH 0  const S32 BLACK_BORDER_HEIGHT = 160; @@ -187,6 +189,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  		delete LLPanelLogin::sInstance;  	} +	mPasswordModified = FALSE;  	LLPanelLogin::sInstance = this;  	// add to front so we are the bottom-most child @@ -213,10 +216,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	}  #if !USE_VIEWER_AUTH -	childSetPrevalidate("first_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace); -	childSetPrevalidate("last_name_edit", LLLineEditor::prevalidateASCIIPrintableNoSpace); - -	childSetCommitCallback("password_edit", mungePassword, this); +	childSetPrevalidate("username_edit", LLLineEditor::prevalidateASCIIPrintableNoPipe);  	getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this);  	// change z sort of clickable text to be behind buttons @@ -248,6 +248,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");  	server_choice_combo->setCommitCallback(onSelectServer, NULL);  	server_choice_combo->setFocusLostCallback(boost::bind(onServerComboLostFocus, _1)); +	updateServerCombo();  	childSetAction("connect_btn", onClickConnect, this); @@ -303,12 +304,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	// kick off a request to grab the url manually  	gResponsePtr = LLIamHereLogin::build( this ); -	std::string login_page = gSavedSettings.getString("LoginPage"); -	if (login_page.empty()) -	{ -		login_page = getString( "real_url" ); -	} -	LLHTTPClient::head( login_page, gResponsePtr ); + +	LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr );  #if !USE_VIEWER_AUTH  	// Initialize visibility (and don't force visibility - use prefs) @@ -377,21 +374,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive )  	}  } -void LLPanelLogin::mungePassword(LLUICtrl* caller, void* user_data) -{ -	LLPanelLogin* self = (LLPanelLogin*)user_data; -	LLLineEditor* editor = (LLLineEditor*)caller; -	std::string password = editor->getText(); - -	// Re-md5 if we've changed at all -	if (password != self->mIncomingPassword) -	{ -		LLMD5 pass((unsigned char *)password.c_str()); -		char munged_password[MD5HEX_STR_SIZE]; -		pass.hex_digest(munged_password); -		self->mMungedPassword = munged_password; -	} -}  LLPanelLogin::~LLPanelLogin()  { @@ -498,14 +480,14 @@ void LLPanelLogin::giveFocus()  	if( sInstance )  	{  		// Grab focus and move cursor to first blank input field -		std::string first = sInstance->childGetText("first_name_edit"); +		std::string username = sInstance->childGetText("username_edit");  		std::string pass = sInstance->childGetText("password_edit"); -		BOOL have_first = !first.empty(); +		BOOL have_username = !username.empty();  		BOOL have_pass = !pass.empty();  		LLLineEditor* edit = NULL; -		if (have_first && !have_pass) +		if (have_username && !have_pass)  		{  			// User saved his name but not his password.  Move  			// focus to password field. @@ -514,7 +496,7 @@ void LLPanelLogin::giveFocus()  		else  		{  			// User doesn't have a name, so start there. -			edit = sInstance->getChild<LLLineEditor>("first_name_edit"); +			edit = sInstance->getChild<LLLineEditor>("username_edit");  		}  		if (edit) @@ -559,77 +541,120 @@ void LLPanelLogin::show(const LLRect &rect,  }  // static -void LLPanelLogin::setFields(const std::string& firstname, -			     const std::string& lastname, -			     const std::string& password) +void LLPanelLogin::setFields(LLPointer<LLCredential> credential, +							 BOOL remember)  {  	if (!sInstance)  	{  		llwarns << "Attempted fillFields with no login view shown" << llendl;  		return;  	} +	LL_INFOS("Credentials") << "Setting login fields to " << *credential << LL_ENDL; -	sInstance->childSetText("first_name_edit", firstname); -	sInstance->childSetText("last_name_edit", lastname); - -	// Max "actual" password length is 16 characters. -	// Hex digests are always 32 characters. -	if (password.length() == 32) +	LLSD identifier = credential->getIdentifier(); +	if((std::string)identifier["type"] == "agent")  +	{ +		sInstance->childSetText("username_edit", (std::string)identifier["first_name"] + " " +  +								(std::string)identifier["last_name"]);	 +	} +	else if((std::string)identifier["type"] == "account") +	{ +		sInstance->childSetText("username_edit", (std::string)identifier["account_name"]);		 +	} +	else +	{ +	  sInstance->childSetText("username_edit", std::string());	 +	} +	// if the password exists in the credential, set the password field with +	// a filler to get some stars +	LLSD authenticator = credential->getAuthenticator(); +	LL_INFOS("Credentials") << "Setting authenticator field " << authenticator["type"].asString() << LL_ENDL; +	if(authenticator.isMap() &&  +	   authenticator.has("secret") &&  +	   (authenticator["secret"].asString().size() > 0))  	{ +		  		// This is a MD5 hex digest of a password.  		// We don't actually use the password input field,   		// fill it with MAX_PASSWORD characters so we get a   		// nice row of asterixes.  		const std::string filler("123456789!123456"); -		sInstance->childSetText("password_edit", filler); -		sInstance->mIncomingPassword = filler; -		sInstance->mMungedPassword = password; +		sInstance->childSetText("password_edit", std::string("123456789!123456"));  	}  	else  	{ -		// this is a normal text password -		sInstance->childSetText("password_edit", password); -		sInstance->mIncomingPassword = password; -		LLMD5 pass((unsigned char *)password.c_str()); -		char munged_password[MD5HEX_STR_SIZE]; -		pass.hex_digest(munged_password); -		sInstance->mMungedPassword = munged_password; +		sInstance->childSetText("password_edit", std::string());		  	} +	sInstance->childSetValue("remember_check", remember);  }  // static -void LLPanelLogin::addServer(const std::string& server, S32 domain_name) +void LLPanelLogin::getFields(LLPointer<LLCredential>& credential, +							 BOOL &remember)  {  	if (!sInstance)  	{ -		llwarns << "Attempted addServer with no login view shown" << llendl; +		llwarns << "Attempted getFields with no login view shown" << llendl;  		return;  	} +	 +	// load the credential so we can pass back the stored password or hash if the user did +	// not modify the password field. +	 +	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGridName()); -	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo"); -	combo->add(server, LLSD(domain_name) ); -	combo->setCurrentByIndex(0); -} - -// static -void LLPanelLogin::getFields(std::string *firstname, -			     std::string *lastname, -			     std::string *password) -{ -	if (!sInstance) +	LLSD identifier = LLSD::emptyMap(); +	LLSD authenticator = LLSD::emptyMap(); +	 +	if(credential.notNull())  	{ -		llwarns << "Attempted getFields with no login view shown" << llendl; -		return; +		authenticator = credential->getAuthenticator();  	} -	*firstname = sInstance->childGetText("first_name_edit"); -	LLStringUtil::trim(*firstname); - -	*lastname = sInstance->childGetText("last_name_edit"); -	LLStringUtil::trim(*lastname); +	std::string username = sInstance->childGetText("username_edit"); +	LLStringUtil::trim(username); +	std::string password = sInstance->childGetText("password_edit"); -	*password = sInstance->mMungedPassword; +	LL_INFOS2("Credentials", "Authentication") << "retrieving username:" << username << LL_ENDL; +	// determine if the username is a first/last form or not. +	size_t separator_index = username.find_first_of(' '); +	if (separator_index == username.npos) +	{ +		LL_INFOS2("Credentials", "Authentication") << "account: " << username << LL_ENDL; +		// single username, so this is a 'clear' identifier +		identifier["type"] = "account"; +		identifier["account_name"] = username; +		 +		if (LLPanelLogin::sInstance->mPasswordModified) +		{ +			authenticator = LLSD::emptyMap(); +			// password is plaintext +			authenticator["type"] = "clear"; +			authenticator["secret"] = password; +		} +	} +	else if (separator_index == username.find_last_of(' ')) +	{ +		LL_INFOS2("Credentials", "Authentication") << "agent: " << username << LL_ENDL; +		// traditional firstname / lastname +		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["algorithm"] = "md5"; +			LLMD5 pass((const U8 *)password.c_str()); +			char md5pass[33];               /* Flawfinder: ignore */ +			pass.hex_digest(md5pass); +			authenticator["secret"] = md5pass; +		} +	} +	credential = gSecAPIHandler->createCredential(LLGridManager::getInstance()->getGridName(), identifier, authenticator); +	remember = sInstance->childGetValue("remember_check");  }  // static @@ -682,6 +707,7 @@ void LLPanelLogin::refreshLocation( bool force_visible )  	sInstance->childSetVisible("start_location_combo", show_start);  	sInstance->childSetVisible("start_location_text", show_start); +	// should be true for enterprise viewer  	BOOL show_server = gSavedSettings.getBOOL("ForceShowGrid");  	sInstance->childSetVisible("server_combo", show_server); @@ -721,15 +747,12 @@ void LLPanelLogin::loadLoginPage()  	std::ostringstream oStr; -	std::string login_page = gSavedSettings.getString("LoginPage"); -	if (login_page.empty()) -	{ -		login_page = sInstance->getString( "real_url" ); -	} +	std::string login_page = LLGridManager::getInstance()->getLoginPage();  	oStr << login_page;  	// Use the right delimeter depending on how LLURI parses the URL  	LLURI login_page_uri = LLURI(login_page); +	  	std::string first_query_delimiter = "&";  	if (login_page_uri.queryMap().size() == 0)  	{ @@ -761,11 +784,10 @@ void LLPanelLogin::loadLoginPage()  	curl_free(curl_version);  	// Grid -	char* curl_grid = curl_escape(LLViewerLogin::getInstance()->getGridLabel().c_str(), 0); +	char* curl_grid = curl_escape(LLGridManager::getInstance()->getGridLabel().c_str(), 0);  	oStr << "&grid=" << curl_grid;  	curl_free(curl_grid); - -	gViewerWindow->setMenuBackgroundColor(false, !LLViewerLogin::getInstance()->isInProductionGrid()); +	gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid());  	gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor()); @@ -790,30 +812,20 @@ void LLPanelLogin::loadLoginPage()  		location = gSavedSettings.getString("LoginLocation");  	} -	std::string firstname, lastname; +	std::string username;      if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3)      {          LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); -		firstname = cmd_line_login[0].asString(); -		lastname = cmd_line_login[1].asString(); +		username = cmd_line_login[0].asString() + " " + cmd_line_login[1];          password = cmd_line_login[2].asString();      } -	if (firstname.empty()) -	{ -		firstname = gSavedSettings.getString("FirstName"); -	} -	 -	if (lastname.empty()) -	{ -		lastname = gSavedSettings.getString("LastName"); -	}  	char* curl_region = curl_escape(region.c_str(), 0); -	oStr <<"firstname=" << firstname << -		"&lastname=" << lastname << "&location=" << location <<	"®ion=" << curl_region; +	oStr <<"username=" << username << +		 "&location=" << location <<	"®ion=" << curl_region;  	curl_free(curl_region); @@ -896,34 +908,33 @@ void LLPanelLogin::onClickConnect(void *)  		// JC - Make sure the fields all get committed.  		sInstance->setFocus(FALSE); -		std::string first = sInstance->childGetText("first_name_edit"); -		std::string last  = sInstance->childGetText("last_name_edit"); -		LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo"); -		std::string combo_text = combo->getSimple(); -		 -		bool has_first_and_last = !(first.empty() || last.empty()); -		bool has_location = false; - -		if(combo_text=="<Type region name>" || combo_text =="") +		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo"); +		LLSD combo_val = combo->getSelectedValue(); +		if (combo_val.isUndefined())  		{ -			// *NOTE: Mani - Location field is not always committed by this point! -			// This may be duplicate work, but better than not doing the work! -			LLURLSimString::sInstance.setString(""); +			combo_val = combo->getValue();  		} -		else  +		if(combo_val.isUndefined()) +		{ +			LLNotificationsUtil::add("StartRegionEmpty"); +			return; +		}		 +		try  		{ -			// *NOTE: Mani - Location field is not always committed by this point! -			LLURLSimString::sInstance.setString(combo_text); -			has_location = true; +			LLGridManager::getInstance()->setGridChoice(combo_val.asString());  		} - -		if(!has_first_and_last) +		catch (LLInvalidGridName ex)  		{ -			LLNotificationsUtil::add("MustHaveAccountToLogIn"); +			LLSD args; +			args["GRID"] = combo_val.asString(); +			LLNotificationsUtil::add("InvalidGrid", args); +			return;  		} -		else if(!has_location) +		 +		std::string username = sInstance->childGetText("username_edit"); +		if(username.empty())  		{ -			LLNotificationsUtil::add("StartRegionEmpty"); +			LLNotificationsUtil::add("MustHaveAccountToLogIn");  		}  		else  		{ @@ -986,6 +997,8 @@ void LLPanelLogin::onClickHelp(void*)  // static  void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)  { +	LLPanelLogin *This = (LLPanelLogin *) user_data; +	This->mPasswordModified = TRUE;  	if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)  	{  		LLNotificationsUtil::add("CapsKeyOn"); @@ -993,6 +1006,34 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)  	}  } +void LLPanelLogin::updateServerCombo() +{ +	// We add all of the possible values, sorted, and then add a bar and the current value at the top +	LLGridManager* viewer_login = LLGridManager::getInstance(); +	LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");	 +	server_choice_combo->removeall(); +	std::map<std::string, std::string> known_grids = viewer_login->getKnownGrids(); +	for (std::map<std::string, std::string>::iterator grid_choice = known_grids.begin(); +		 grid_choice != known_grids.end(); +		 grid_choice++) +		{ +			//if (!grid_choice->first.empty()) +			{ +				LL_INFOS("Credentials") << "adding " << grid_choice->second << ":" << grid_choice->first << LL_ENDL; +				server_choice_combo->add(grid_choice->second, grid_choice->first, ADD_SORTED); +			} +		} +	 +	server_choice_combo->addSeparator(ADD_TOP); +	 +	LL_INFOS("Credentials") << "adding top grid choice by " << viewer_login->getGridLabel() << LL_ENDL; +	server_choice_combo->add(viewer_login->getGridLabel(),  +							 viewer_login->getGridName(),  +							 ADD_TOP);	 +	 +	server_choice_combo->selectFirstItem();	 +} +  // static  void LLPanelLogin::onSelectServer(LLUICtrl*, void*)  { @@ -1002,45 +1043,34 @@ void LLPanelLogin::onSelectServer(LLUICtrl*, void*)  	// The user twiddled with the grid choice ui.  	// apply the selection to the grid setting. -	std::string grid_label; -	S32 grid_index; +	LLPointer<LLCredential> credential; +	BOOL remember = FALSE;  	LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo"); -	LLSD combo_val = combo->getValue(); - -	if (LLSD::TypeInteger == combo_val.type()) -	{ -		grid_index = combo->getValue().asInteger(); - -		if ((S32)GRID_INFO_OTHER == grid_index) -		{ -			// This happens if the user specifies a custom grid -			// via command line. -			grid_label = combo->getSimple(); -		} -	} -	else +	LLSD combo_val = combo->getSelectedValue(); +	if (combo_val.isUndefined())  	{ -		// no valid selection, return other -		grid_index = (S32)GRID_INFO_OTHER; -		grid_label = combo_val.asString(); +	  combo_val = combo->getValue();  	} -	// This new seelction will override preset uris +	// This new selection will override preset uris  	// from the command line. -	LLViewerLogin* vl = LLViewerLogin::getInstance(); -	vl->resetURIs(); -	if(grid_index != GRID_INFO_OTHER) -	{ -		vl->setGridChoice((EGridInfo)grid_index); -	} -	else -	{ -		vl->setGridChoice(grid_label); -	} + +	LLGridManager::getInstance()->setGridChoice(combo_val.asString()); +	updateServerCombo();  	// grid changed so show new splash screen (possibly)  	loadLoginPage(); +	 +	// if they've selected another grid, we should load the credentials +	// for that grid and set them to the UI. +	credential = gSecAPIHandler->loadCredential(LLGridManager::getInstance()->getGridName()); +	 + +	remember = sInstance->childGetValue("remember_check"); +	sInstance->setFields(credential, remember); + +	LL_INFOS("Credentials") << "Grid changed to:" << LLGridManager::getInstance()->getGridName() << LL_ENDL;  }  void LLPanelLogin::onServerComboLostFocus(LLFocusableElement* fe) diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 97350ce5c7..d33aa2d550 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -37,6 +37,7 @@  #include "llpointer.h"			// LLPointer<>  #include "llmediactrl.h"	// LLMediaCtrlObserver  #include <boost/scoped_ptr.hpp> +#include "llsecapi.h"  class LLLineEditor;  class LLUIImage; @@ -65,15 +66,11 @@ public:  		void (*callback)(S32 option, void* user_data),   		void* callback_data); -	// Remember password checkbox is set via gSavedSettings "RememberPassword" -	static void setFields(const std::string& firstname, const std::string& lastname,  -		const std::string& password); +	static void setFields(LLPointer<LLCredential> credential, BOOL remember); -	static void addServer(const std::string& server, S32 domain_name);  	static void refreshLocation( bool force_visible ); -	static void getFields(std::string *firstname, std::string *lastname, -						  std::string *password); +	static void getFields(LLPointer<LLCredential>& credential, BOOL& remember);  	static BOOL isGridComboDirty();  	static void getLocation(std::string &location); @@ -85,7 +82,6 @@ public:  	static void loadLoginPage();	  	static void giveFocus();  	static void setAlwaysRefresh(bool refresh);  -	static void mungePassword(LLUICtrl* caller, void* user_data);  	// inherited from LLViewerMediaObserver  	/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); @@ -102,6 +98,7 @@ private:  	static void onPassKey(LLLineEditor* caller, void* user_data);  	static void onSelectServer(LLUICtrl*, void*);  	static void onServerComboLostFocus(LLFocusableElement*); +	static void updateServerCombo();  private:  	LLPointer<LLUIImage> mLogoImage; @@ -110,8 +107,7 @@ private:  	void			(*mCallback)(S32 option, void *userdata);  	void*			mCallbackData; -	std::string mIncomingPassword; -	std::string mMungedPassword; +	BOOL            mPasswordModified;  	static LLPanelLogin* sInstance;  	static BOOL		sCapslockDidNotification; diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index c2cfde0dc7..cdf4a3fe01 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -38,11 +38,17 @@  std::map<std::string, LLPointer<LLSecAPIHandler> > gHandlerMap; - +LLPointer<LLSecAPIHandler> gSecAPIHandler;  void initializeSecHandler()  {  	gHandlerMap[BASIC_SECHANDLER] = new LLSecAPIBasicHandler(); +	 +	// Currently, we only have the Basic handler, so we can point the main sechandler +	// pointer to the basic handler.  Later, we'll create a wrapper handler that +	// selects the appropriate sechandler as needed, for instance choosing the +	// mac keyring handler, with fallback to the basic sechandler +	gSecAPIHandler = gHandlerMap[BASIC_SECHANDLER];  }  // start using a given security api handler.  If the string is empty  // the default is used @@ -64,6 +70,28 @@ void registerSecHandler(const std::string& handler_type,  	gHandlerMap[handler_type] = handler;  } +std::ostream& operator <<(std::ostream& s, const LLCredential& cred) +{ +	return s << (std::string)cred; +} - +LLSD LLCredential::getLoginParams() +{ +	LLSD result = LLSD::emptyMap(); +	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["username"]; +		result["passwd"] = mAuthenticator["secret"]; +                                     +	} +	return result; +} diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 743d3d6770..d456ca95b1 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -34,6 +34,7 @@  #define LLSECAPI_H  #include <vector>  #include <openssl/x509.h> +#include <ostream>  // All error handling is via exceptions. @@ -156,7 +157,7 @@ public:  	LLCertificateStore() {}  	virtual ~LLCertificateStore() {} -	virtual X509_STORE getOpenSSLX509Store()=0;  // return an openssl X509_STORE   +	virtual X509_STORE* getOpenSSLX509Store()=0;  // return an openssl X509_STORE    	// for this store  	// add a copy of a cert to the store @@ -169,7 +170,8 @@ public:  	virtual void remove(int index)=0;  	// return a certificate at the index -	virtual LLPointer<LLCertificate>& operator[](int index)=0; +	virtual LLPointer<LLCertificate> operator[](int index)=0; +	  	// return the number of certs in the store  	virtual int len() const =0; @@ -186,6 +188,49 @@ public:  	virtual bool validate(const LLCertificateChain& cert_chain) const=0;  }; +// +// LLCredential - interface for credentials providing the following functionality: +// * persistance of credential information based on grid (for saving username/password) +// * serialization to an OGP identifier/authenticator pair +//  +class LLCredential  : public LLRefCount +{ +public: +	 +	LLCredential() {} +	 +	LLCredential(const std::string& grid) +	{ +		mGrid = grid; +		mIdentifier = LLSD::emptyMap(); +		mAuthenticator = LLSD::emptyMap(); +	} +	 +	virtual ~LLCredential() {} +	 +	virtual void setCredentialData(const LLSD& identifier, const LLSD& authenticator)  +	{  +		mIdentifier = identifier; +		mAuthenticator = authenticator; +	} +	virtual LLSD getIdentifier() { return mIdentifier; } +	virtual LLSD getAuthenticator() { return mAuthenticator; } +	virtual LLSD getLoginParams(); +	virtual std::string getGrid() { return mGrid; } +	 + +	virtual void clearAuthenticator() { mAuthenticator = LLSD(); }  +	virtual std::string userID() const { return std::string("unknown");} +	virtual std::string asString() const { return std::string("unknown");} +	operator std::string() const { return asString(); } +protected: +	LLSD mIdentifier; +	LLSD mAuthenticator; +	std::string mGrid; +}; + +std::ostream& operator <<(std::ostream& s, const LLCredential& cred); +  // LLSecAPIHandler Class  // Interface handler class for the various security storage handlers. @@ -219,9 +264,24 @@ public:  	// retrieve protected data  	virtual LLSD getProtectedData(const std::string& data_type,  								  const std::string& data_id)=0; +	 +	// delete a protected data item from the store +	virtual void deleteProtectedData(const std::string& data_type, +									 const std::string& data_id)=0; +	 +	virtual LLPointer<LLCredential> createCredential(const std::string& grid, +													 const LLSD& identifier,  +													 const LLSD& authenticator)=0; +	 +	virtual LLPointer<LLCredential> loadCredential(const std::string& grid)=0; +	 +	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator)=0; +	 +	virtual void deleteCredential(LLPointer<LLCredential> cred)=0; +	  }; -void secHandlerInitialize(); +void initializeSecHandler();  // retrieve a security api depending on the api type  LLPointer<LLSecAPIHandler> getSecHandler(const std::string& handler_type); @@ -229,4 +289,6 @@ LLPointer<LLSecAPIHandler> getSecHandler(const std::string& handler_type);  void registerSecHandler(const std::string& handler_type,   						LLPointer<LLSecAPIHandler>& handler); +extern LLPointer<LLSecAPIHandler> gSecAPIHandler; +  #endif // LL_SECAPI_H diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index ab6bf034f1..4180f578b9 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,8 +35,11 @@  #include "llsecapi.h"  #include "llsechandler_basic.h"  #include "llsdserialize.h" +#include "llviewernetwork.h" +#include "llxorcipher.h"  #include "llfile.h"  #include "lldir.h" +#include "llviewercontrol.h"  #include <vector>  #include <ios>  #include <openssl/x509.h> @@ -276,22 +279,94 @@ std::string cert_get_digest(const std::string& digest_type, X509 *cert)  } +// +// LLBasicCertificateStore +//  +LLBasicCertificateStore::LLBasicCertificateStore(const std::string& filename) +{ +} +LLBasicCertificateStore::LLBasicCertificateStore(const X509_STORE* store) +{ +} + +LLBasicCertificateStore::~LLBasicCertificateStore() +{ +} + +		 +X509_STORE* LLBasicCertificateStore::getOpenSSLX509Store() +{ +	return NULL; +} +		 +		// add a copy of a cert to the store +void  LLBasicCertificateStore::append(const LLCertificate& cert) +{ +} +		 +		// add a copy of a cert to the store +void LLBasicCertificateStore::insert(const int index, const LLCertificate& cert) +{ +} +		 +		// remove a certificate from the store +void LLBasicCertificateStore::remove(int index) +{ +} +		 +		// return a certificate at the index +LLPointer<LLCertificate> LLBasicCertificateStore::operator[](int index) +{ +	LLPointer<LLCertificate> result = NULL; +	return result; +} +		// return the number of certs in the store +int LLBasicCertificateStore::len() const +{ +	return 0; +} +		 +		// load the store from a persisted location +void LLBasicCertificateStore::load(const std::string& store_id) +{ +} +		 +		// persist the store +void LLBasicCertificateStore::save() +{ +} +		 +		// return the store id +std::string LLBasicCertificateStore::storeId() +{ +	return std::string(""); +} +		 +		// validate a cert chain +bool LLBasicCertificateStore::validate(const LLCertificateChain& cert_chain) const +{ +	return FALSE; +} +  // LLSecAPIBasicHandler Class  // Interface handler class for the various security storage handlers.  // We read the file on construction, and write it on destruction.  This  // means multiple processes cannot modify the datastore. -LLSecAPIBasicHandler::LLSecAPIBasicHandler(const std::string& protected_data_file) +LLSecAPIBasicHandler::LLSecAPIBasicHandler(const std::string& protected_data_file, +										   const std::string& legacy_password_path)  {  	mProtectedDataFilename = protected_data_file;  	mProtectedDataMap = LLSD::emptyMap(); +	mLegacyPasswordPath = legacy_password_path;  	_readProtectedData();  }  LLSecAPIBasicHandler::LLSecAPIBasicHandler()  { -	std::string mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, -														  "bin_conf.dat"); +	mProtectedDataFilename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, +															"bin_conf.dat"); +	mLegacyPasswordPath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "password.dat");  	mProtectedDataMap = LLSD::emptyMap();  	_readProtectedData(); @@ -306,7 +381,6 @@ void LLSecAPIBasicHandler::_readProtectedData()  {	  	// attempt to load the file into our map  	LLPointer<LLSDParser> parser = new LLSDXMLParser(); -	  	llifstream protected_data_stream(mProtectedDataFilename.c_str(),   									llifstream::binary);  	if (!protected_data_stream.fail()) { @@ -314,21 +388,27 @@ void LLSecAPIBasicHandler::_readProtectedData()  		U8 salt[STORE_SALT_SIZE];  		U8 buffer[BUFFER_READ_SIZE];  		U8 decrypted_buffer[BUFFER_READ_SIZE]; -		int decrypted_length;		 -		 +		int decrypted_length;	 +		unsigned char MACAddress[MAC_ADDRESS_BYTES]; +		LLUUID::getNodeID(MACAddress); +		LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES);  		// read in the salt and key  		protected_data_stream.read((char *)salt, STORE_SALT_SIZE);  		offset = 0;  		if (protected_data_stream.gcount() < STORE_SALT_SIZE)  		{ -			throw LLProtectedDataException("Corrupt Protected Data Store"); +			throw LLProtectedDataException("Corrupt Protected Data Store1");  		} -		 + +		cipher.decrypt(salt, STORE_SALT_SIZE);		 +  		// totally lame.  As we're not using the OS level protected data, we need to  		// at least obfuscate the data.  We do this by using a salt stored at the head of the file  		// to encrypt the data, therefore obfuscating it from someone using simple existing tools. -		// It would be better to use the password, but as this store +		// We do include the MAC address as part of the obfuscation, which would require an +		// attacker to get the MAC address as well as the protected store, which improves things +		// somewhat.  It would be better to use the password, but as this store  		// will be used to store the SL password when the user decides to have SL remember it,   		// so we can't use that.  OS-dependent store implementations will use the OS password/storage   		// mechanisms and are considered to be more secure. @@ -369,6 +449,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()  	U8 salt[STORE_SALT_SIZE];  	U8 buffer[BUFFER_READ_SIZE];  	U8 encrypted_buffer[BUFFER_READ_SIZE]; +  	if(mProtectedDataMap.isUndefined())  	{ @@ -377,10 +458,10 @@ void LLSecAPIBasicHandler::_writeProtectedData()  	}  	// create a string with the formatted data.  	LLSDSerialize::toXML(mProtectedDataMap, formatted_data_ostream); -	  	std::istringstream formatted_data_istream(formatted_data_ostream.str());  	// generate the seed  	RAND_bytes(salt, STORE_SALT_SIZE); +  	// write to a temp file so we don't clobber the initial file if there is  	// an error. @@ -394,7 +475,12 @@ void LLSecAPIBasicHandler::_writeProtectedData()  		EVP_CIPHER_CTX ctx;  		EVP_CIPHER_CTX_init(&ctx);  		EVP_EncryptInit(&ctx, EVP_rc4(), salt, NULL); -		protected_data_stream.write((const char *)salt, STORE_SALT_SIZE);	 +		unsigned char MACAddress[MAC_ADDRESS_BYTES]; +		LLUUID::getNodeID(MACAddress); +		LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES); +		cipher.encrypt(salt, STORE_SALT_SIZE); +		protected_data_stream.write((const char *)salt, STORE_SALT_SIZE); +  		while (formatted_data_istream.good())  		{  			formatted_data_istream.read((char *)buffer, BUFFER_READ_SIZE); @@ -423,7 +509,8 @@ void LLSecAPIBasicHandler::_writeProtectedData()  	}  	// move the temporary file to the specified file location. -	if((LLFile::remove(mProtectedDataFilename) != 0) ||  +	if((((LLFile::isfile(mProtectedDataFilename) != 0) &&  +		 (LLFile::remove(mProtectedDataFilename) != 0))) ||   	   (LLFile::rename(tmp_filename, mProtectedDataFilename)))  	{  		LLFile::remove(tmp_filename); @@ -477,14 +564,181 @@ LLSD LLSecAPIBasicHandler::getProtectedData(const std::string& data_type,  	return LLSD();  } +void LLSecAPIBasicHandler::deleteProtectedData(const std::string& data_type, +											   const std::string& data_id) +{ +	if (mProtectedDataMap.has(data_type) && +		mProtectedDataMap[data_type].isMap() && +		mProtectedDataMap[data_type].has(data_id)) +		{ +			mProtectedDataMap[data_type].erase(data_id); +		} +} + + +//  // persist data in a protected store +//  void LLSecAPIBasicHandler::setProtectedData(const std::string& data_type, -									  const std::string& data_id, -									  const LLSD& data) +											const std::string& data_id, +											const LLSD& data)  {  	if (!mProtectedDataMap.has(data_type) || !mProtectedDataMap[data_type].isMap()) {  		mProtectedDataMap[data_type] = LLSD::emptyMap();  	}  	mProtectedDataMap[data_type][data_id] = data;  -}
\ No newline at end of file +} + +// +// Create a credential object from an identifier and authenticator.  credentials are +// per grid. +LLPointer<LLCredential> LLSecAPIBasicHandler::createCredential(const std::string& grid, +															   const LLSD& identifier,  +															   const LLSD& authenticator) +{ +	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid); +	result->setCredentialData(identifier, authenticator); +	return result; +} + +// Load a credential from the credential store, given the grid +LLPointer<LLCredential> LLSecAPIBasicHandler::loadCredential(const std::string& grid) +{ +	LLSD credential = getProtectedData("credential", grid); +	LLPointer<LLSecAPIBasicCredential> result = new LLSecAPIBasicCredential(grid); +	if(credential.isMap() &&  +	   credential.has("identifier")) +	{ + +		LLSD identifier = credential["identifier"]; +		LLSD authenticator; +		if (credential.has("authenticator")) +		{ +			authenticator = credential["authenticator"]; +		} +		result->setCredentialData(identifier, authenticator); +	} +	else +	{ +		// credential was not in protected storage, so pull the credential +		// from the legacy store. +		std::string first_name = gSavedSettings.getString("FirstName"); +		std::string last_name = gSavedSettings.getString("LastName"); +		 +		if ((first_name != "") && +			(last_name != "")) +		{ +			LLSD identifier = LLSD::emptyMap(); +			LLSD authenticator; +			identifier["type"] = "agent"; +			identifier["first_name"] = first_name; +			identifier["last_name"] = last_name; +			 +			std::string legacy_password = _legacyLoadPassword(); +			if (legacy_password.length() > 0) +			{ +				authenticator = LLSD::emptyMap(); +				authenticator["type"] = "hash"; +				authenticator["algorithm"] = "md5"; +				authenticator["secret"] = legacy_password; +			} +			result->setCredentialData(identifier, authenticator); +		}		 +	} +	return result; +} + +// Save the credential to the credential store.  Save the authenticator also if requested. +// That feature is used to implement the 'remember password' functionality. +void LLSecAPIBasicHandler::saveCredential(LLPointer<LLCredential> cred, bool save_authenticator) +{ +	LLSD credential = LLSD::emptyMap(); +	credential["identifier"] = cred->getIdentifier();  +	if (save_authenticator)  +	{ +		credential["authenticator"] = cred->getAuthenticator(); +	} +	LL_INFOS("Credentials") << "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? +} + +// Remove a credential from the credential store. +void LLSecAPIBasicHandler::deleteCredential(LLPointer<LLCredential> cred) +{ +	LLSD undefVal; +	deleteProtectedData("credential", cred->getGrid()); +	cred->setCredentialData(undefVal, undefVal); +} + +// load the legacy hash for agni, and decrypt it given the  +// mac address +std::string LLSecAPIBasicHandler::_legacyLoadPassword() +{ +	const S32 HASHED_LENGTH = 32;	 +	std::vector<U8> buffer(HASHED_LENGTH); +	llifstream password_file(mLegacyPasswordPath, llifstream::binary); +	 +	if(password_file.fail()) +	{ +		return std::string(""); +	} +	 +	password_file.read((char*)&buffer[0], buffer.size()); +	if(password_file.gcount() != buffer.size()) +	{ +		return std::string(""); +	} +	 +	// Decipher with MAC address +	unsigned char MACAddress[MAC_ADDRESS_BYTES]; +	LLUUID::getNodeID(MACAddress); +	LLXORCipher cipher(MACAddress, 6); +	cipher.decrypt(&buffer[0], buffer.size()); +	 +	return std::string((const char*)&buffer[0], buffer.size()); +} + + +// return an identifier for the user +std::string LLSecAPIBasicCredential::userID() const +{ +	if (!mIdentifier.isMap()) +	{ +		return mGrid + "(null)"; +	} +	else if ((std::string)mIdentifier["type"] == "agent") +	{ +		return  (std::string)mIdentifier["first_name"] + "_" + (std::string)mIdentifier["last_name"]; +	} +	else if ((std::string)mIdentifier["type"] == "account") +	{ +		return (std::string)mIdentifier["account_name"]; +	} + +	return "unknown"; + +} + +// return a printable user identifier +std::string LLSecAPIBasicCredential::asString() const +{ +	if (!mIdentifier.isMap()) +	{ +		return mGrid + ":(null)"; +	} +	else if ((std::string)mIdentifier["type"] == "agent") +	{ +		return mGrid + ":" + (std::string)mIdentifier["first_name"] + " " + (std::string)mIdentifier["last_name"]; +	} +	else if ((std::string)mIdentifier["type"] == "account") +	{ +		return mGrid + ":" + (std::string)mIdentifier["account_name"]; +	} + +	return mGrid + ":(unknown type)"; +} + + diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h index 0ec6938583..5d81b6e190 100644 --- a/indra/newview/llsechandler_basic.h +++ b/indra/newview/llsechandler_basic.h @@ -68,13 +68,69 @@ protected:  	X509* mCert;  }; +// class LLCertificateStore +// represents a store of certificates, typically a store of root CA +// certificates.  The store can be persisted, and can be used to validate +// a cert chain +// +class LLBasicCertificateStore : public LLCertificateStore +{ +public: +	LLBasicCertificateStore(const std::string& filename); +	LLBasicCertificateStore(const X509_STORE* store); +	virtual ~LLBasicCertificateStore(); +	 +	virtual X509_STORE* getOpenSSLX509Store();  // return an openssl X509_STORE   +	// for this store +	 +	// add a copy of a cert to the store +	virtual void  append(const LLCertificate& cert); +	 +	// add a copy of a cert to the store +	virtual void insert(const int index, const LLCertificate& cert); +	 +	// remove a certificate from the store +	virtual void remove(int index); +	 +	// return a certificate at the index +	virtual LLPointer<LLCertificate> operator[](int index); +	// return the number of certs in the store +	virtual int len() const; +	 +	// load the store from a persisted location +	virtual void load(const std::string& store_id); +	 +	// persist the store +	virtual void save(); +	 +	// return the store id +	virtual std::string storeId(); +	 +	// validate a cert chain +	virtual bool validate(const LLCertificateChain& cert_chain) const; +}; + +// LLSecAPIBasicCredential class +class LLSecAPIBasicCredential : public LLCredential +{ +public: +	LLSecAPIBasicCredential(const std::string& grid) : LLCredential(grid) {}  +	virtual ~LLSecAPIBasicCredential() {} +	// return a value representing the user id, (could be guid, name, whatever) +	virtual std::string userID() const;	 +	 +	// printible string identifying the credential. +	virtual std::string asString() const; +}; +  // LLSecAPIBasicHandler Class  // Interface handler class for the various security storage handlers.  class LLSecAPIBasicHandler : public LLSecAPIHandler  {  public: -	LLSecAPIBasicHandler(const std::string& protected_data_filename); +	LLSecAPIBasicHandler(const std::string& protected_data_filename, +						 const std::string& legacy_password_path);  	LLSecAPIBasicHandler();  	virtual ~LLSecAPIBasicHandler(); @@ -102,12 +158,32 @@ public:  	// retrieve protected data  	virtual LLSD getProtectedData(const std::string& data_type,  								  const std::string& data_id); +	 +	// delete a protected data item from the store +	virtual void deleteProtectedData(const std::string& data_type, +									 const std::string& data_id); +	 +	// credential management routines +	 +	virtual LLPointer<LLCredential> createCredential(const std::string& grid, +													 const LLSD& identifier,  +													 const LLSD& authenticator); +	 +	virtual LLPointer<LLCredential> loadCredential(const std::string& grid); + +	virtual void saveCredential(LLPointer<LLCredential> cred, bool save_authenticator); +	 +	virtual void deleteCredential(LLPointer<LLCredential> cred); +	  protected:  	void _readProtectedData();  	void _writeProtectedData(); -	 +	std::string _legacyLoadPassword(); +  	std::string mProtectedDataFilename;  	LLSD mProtectedDataMap; +	 +	std::string mLegacyPasswordPath;  };  #endif // LLSECHANDLER_BASIC diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 99fa271b78..dd991c8eff 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -230,10 +230,9 @@ static bool gUseCircuitCallbackCalled = false;  EStartupState LLStartUp::gStartupState = STATE_FIRST; -// *NOTE:Mani - to reconcile with giab changes... -static std::string gFirstname; -static std::string gLastname; -static std::string gPassword; +static LLPointer<LLCredential> gUserCredential; +static std::string gDisplayName; +static BOOL gRememberPassword = TRUE;       static U64 gFirstSimHandle = 0;  static LLHost gFirstSim; @@ -250,7 +249,6 @@ boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener(  void login_show();  void login_callback(S32 option, void* userdata); -bool is_hex_string(U8* str, S32 len);  void show_first_run_dialog();  bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);  void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); @@ -716,69 +714,25 @@ bool idle_startup()  		//  		// Log on to system  		// -		if (!LLStartUp::sSLURLCommand.empty()) -		{ -			// this might be a secondlife:///app/login URL -			gLoginHandler.parseDirectLogin(LLStartUp::sSLURLCommand); -		} -		if (!gLoginHandler.getFirstName().empty() -			|| !gLoginHandler.getLastName().empty() -			/*|| !gLoginHandler.getWebLoginKey().isNull()*/ ) -		{ -			// We have at least some login information on a SLURL -			gFirstname = gLoginHandler.getFirstName(); -			gLastname = gLoginHandler.getLastName(); -			LL_DEBUGS("LLStartup") << "STATE_FIRST: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; - -			// Show the login screen if we don't have everything -			show_connect_box =  -				gFirstname.empty() || gLastname.empty(); -		} -        else if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) -        { -            LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); -			gFirstname = cmd_line_login[0].asString(); -			gLastname = cmd_line_login[1].asString(); -			LL_DEBUGS("LLStartup") << "Setting gFirstname, gLastname from gSavedSettings(\"UserLoginInfo\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; - -			LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); -			char md5pass[33];               /* Flawfinder: ignore */ -			pass.hex_digest(md5pass); -			gPassword = md5pass; -			 -#ifdef USE_VIEWER_AUTH -			show_connect_box = true; -#else -			show_connect_box = false; -#endif -			gSavedSettings.setBOOL("AutoLogin", TRUE); -        } -		else if (gSavedSettings.getBOOL("AutoLogin")) -		{ -			gFirstname = gSavedSettings.getString("FirstName"); -			gLastname = gSavedSettings.getString("LastName"); -			LL_DEBUGS("LLStartup") << "AutoLogin: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; -			gPassword = LLStartUp::loadPasswordFromDisk(); -			gSavedSettings.setBOOL("RememberPassword", TRUE); -			 -#ifdef USE_VIEWER_AUTH -			show_connect_box = true; -#else -			show_connect_box = false; -#endif +		if (gUserCredential.isNull()) +		{ +			gUserCredential = gLoginHandler.initializeLoginInfo(LLStartUp::sSLURLCommand);  		} -		else +		if (gUserCredential.isNull())  		{ -			// if not automatically logging in, display login dialog -			// a valid grid is selected -			gFirstname = gSavedSettings.getString("FirstName"); -			gLastname = gSavedSettings.getString("LastName"); -			LL_DEBUGS("LLStartup") << "normal login: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; -			gPassword = LLStartUp::loadPasswordFromDisk(); -			show_connect_box = true; +			show_connect_box = TRUE; +		} +		else if (gSavedSettings.getBOOL("AutoLogin"))   +		{ +			gRememberPassword = TRUE; +			gSavedSettings.setBOOL("RememberPassword", TRUE);                                                       +			show_connect_box = false;    			 +		} +		else  +		{ +			gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); +			show_connect_box = TRUE;  		} - -  		// Go to the next startup state  		LLStartUp::setStartupState( STATE_BROWSER_INIT );  		return FALSE; @@ -810,8 +764,10 @@ bool idle_startup()  			// Load all the name information out of the login view  			// NOTE: Hits "Attempted getFields with no login view shown" warning, since we don't  			// show the login view until login_show() is called below.   -			// LLPanelLogin::getFields(gFirstname, gLastname, gPassword); - +			if (gUserCredential.isNull())                                                                           +			{                                                                                                       +				gUserCredential = gLoginHandler.initializeLoginInfo(LLStartUp::sSLURLCommand);                  +			}       			if (gNoRender)  			{  				LL_ERRS("AppInit") << "Need to autologin or use command line with norender!" << LL_ENDL; @@ -822,8 +778,10 @@ bool idle_startup()  			// Show the login dialog  			login_show();  			// connect dialog is already shown, so fill in the names -			LLPanelLogin::setFields( gFirstname, gLastname, gPassword); - +			if (gUserCredential.notNull())                                                                          +			{                                                                                                       +				LLPanelLogin::setFields( gUserCredential, gRememberPassword);                                   +			}       			LLPanelLogin::giveFocus();  			gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); @@ -890,36 +848,32 @@ bool idle_startup()  		// DEV-42215: Make sure they're not empty -- gFirstname and gLastname  		// might already have been set from gSavedSettings, and it's too bad  		// to overwrite valid values with empty strings. -		if (! gLoginHandler.getFirstName().empty() && ! gLoginHandler.getLastName().empty()) -		{ -			gFirstname = gLoginHandler.getFirstName(); -			gLastname = gLoginHandler.getLastName(); -			LL_DEBUGS("LLStartup") << "STATE_LOGIN_CLEANUP: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; -		}  		if (show_connect_box)  		{  			// TODO if not use viewer auth  			// Load all the name information out of the login view -			LLPanelLogin::getFields(&gFirstname, &gLastname, &gPassword); +			LLPanelLogin::getFields(gUserCredential, gRememberPassword);   			// end TODO  			// HACK: Try to make not jump on login  			gKeyboard->resetKeys();  		} -		if (!gFirstname.empty() && !gLastname.empty()) -		{ -			gSavedSettings.setString("FirstName", gFirstname); -			gSavedSettings.setString("LastName", gLastname); - -			LL_INFOS("AppInit") << "Attempting login as: " << gFirstname << " " << gLastname << LL_ENDL; -			gDebugInfo["LoginName"] = gFirstname + " " + gLastname;	 +		// save the credentials                                                                                         +		std::string userid = "unknown";                                                                                 +		if(gUserCredential.notNull())                                                                                   +		{   +			userid = gUserCredential->userID();                                                                     +			gSecAPIHandler->saveCredential(gUserCredential, gRememberPassword);    		} - +		gSavedSettings.setBOOL("RememberPassword", gRememberPassword);                                                  +		LL_INFOS("AppInit") << "Attempting login as: " << userid << LL_ENDL;                                            +		gDebugInfo["LoginName"] = userid;                                                                               +           		// create necessary directories  		// *FIX: these mkdir's should error check -		gDirUtilp->setLindenUserDir(gFirstname, gLastname); +		gDirUtilp->setPerAccountChatLogsDir(userid);        	LLFile::mkdir(gDirUtilp->getLindenUserDir());          // Set PerAccountSettingsFile to the default value. @@ -952,8 +906,6 @@ bool idle_startup()  		{  			gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));		  		} -		 -		gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname);  		LLFile::mkdir(gDirUtilp->getChatLogsDir());  		LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir()); @@ -1052,7 +1004,7 @@ bool idle_startup()  	if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())  	{ -		gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); +		gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridLabel();  		// Update progress status and the display loop.  		auth_desc = LLTrans::getString("LoginInProgress"); @@ -1076,11 +1028,7 @@ bool idle_startup()  		// This call to LLLoginInstance::connect() starts the   		// authentication process. -		LLSD credentials; -		credentials["first"] = gFirstname; -		credentials["last"] = gLastname; -		credentials["passwd"] = gPassword; -		login->connect(credentials); +		login->connect(gUserCredential);  		LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );  		return FALSE; @@ -1128,8 +1076,8 @@ bool idle_startup()  			if(reason_response == "key")  			{  				// Couldn't login because user/password is wrong -				// Clear the password -				gPassword = ""; +				// Clear the credential +				gUserCredential->clearAuthenticator();  			}  			if(reason_response == "update"  @@ -1166,7 +1114,8 @@ bool idle_startup()  			if(process_login_success_response())  			{  				// Pass the user information to the voice chat server interface. -				gVoiceClient->userAuthorized(gFirstname, gLastname, gAgentID); +				gVoiceClient->userAuthorized(gUserCredential->userID(), gAgentID); +				LLGridManager::getInstance()->setFavorite();   				LLStartUp::setStartupState( STATE_WORLD_INIT);  			}  			else @@ -2115,20 +2064,9 @@ void login_show()  #endif  	LLPanelLogin::show(	gViewerWindow->getWindowRectScaled(), -						bUseDebugLogin, +						bUseDebugLogin || gSavedSettings.getBOOL("SecondLifeEnterprise"),  						login_callback, NULL ); -	// UI textures have been previously loaded in doPreloadImages() -	 -	LL_DEBUGS("AppInit") << "Setting Servers" << LL_ENDL; - -	LLPanelLogin::addServer(LLViewerLogin::getInstance()->getGridLabel(), LLViewerLogin::getInstance()->getGridChoice()); - -	LLViewerLogin* vl = LLViewerLogin::getInstance(); -	for(int grid_index = GRID_INFO_ADITI; grid_index < GRID_INFO_OTHER; ++grid_index) -	{ -		LLPanelLogin::addServer(vl->getKnownGridLabel((EGridInfo)grid_index), grid_index); -	}  }  // Callback for when login screen is closed.  Option 0 = connect, option 1 = quit. @@ -2144,9 +2082,6 @@ void login_callback(S32 option, void *userdata)  	}  	else if (QUIT_OPTION == option) // *TODO: THIS CODE SEEMS TO BE UNREACHABLE!!!!! login_callback is never called with option equal to QUIT_OPTION  	{ -		// Make sure we don't save the password if the user is trying to clear it. -		std::string first, last, password; -		LLPanelLogin::getFields(&first, &last, &password);  		if (!gSavedSettings.getBOOL("RememberPassword"))  		{  			// turn off the setting and write out to disk @@ -2169,142 +2104,6 @@ void login_callback(S32 option, void *userdata)  	}  } - -// static -std::string LLStartUp::loadPasswordFromDisk() -{ -	// Only load password if we also intend to save it (otherwise the user -	// wonders what we're doing behind his back).  JC -	BOOL remember_password = gSavedSettings.getBOOL("RememberPassword"); -	if (!remember_password) -	{ -		return std::string(""); -	} - -	std::string hashed_password(""); - -	// Look for legacy "marker" password from settings.ini -	hashed_password = gSavedSettings.getString("Marker"); -	if (!hashed_password.empty()) -	{ -		// Stomp the Marker entry. -		gSavedSettings.setString("Marker", ""); - -		// Return that password. -		return hashed_password; -	} - -	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, -													   "password.dat"); -	LLFILE* fp = LLFile::fopen(filepath, "rb");		/* Flawfinder: ignore */ -	if (!fp) -	{ -		return hashed_password; -	} - -	// UUID is 16 bytes, written into ASCII is 32 characters -	// without trailing \0 -	const S32 HASHED_LENGTH = 32; -	U8 buffer[HASHED_LENGTH+1]; - -	if (1 != fread(buffer, HASHED_LENGTH, 1, fp)) -	{ -		return hashed_password; -	} - -	fclose(fp); - -	// Decipher with MAC address -	LLXORCipher cipher(gMACAddress, 6); -	cipher.decrypt(buffer, HASHED_LENGTH); - -	buffer[HASHED_LENGTH] = '\0'; - -	// Check to see if the mac address generated a bad hashed -	// password. It should be a hex-string or else the mac adress has -	// changed. This is a security feature to make sure that if you -	// get someone's password.dat file, you cannot hack their account. -	if(is_hex_string(buffer, HASHED_LENGTH)) -	{ -		hashed_password.assign((char*)buffer); -	} - -	return hashed_password; -} - - -// static -void LLStartUp::savePasswordToDisk(const std::string& hashed_password) -{ -	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, -													   "password.dat"); -	LLFILE* fp = LLFile::fopen(filepath, "wb");		/* Flawfinder: ignore */ -	if (!fp) -	{ -		return; -	} - -	// Encipher with MAC address -	const S32 HASHED_LENGTH = 32; -	U8 buffer[HASHED_LENGTH+1]; - -	LLStringUtil::copy((char*)buffer, hashed_password.c_str(), HASHED_LENGTH+1); - -	LLXORCipher cipher(gMACAddress, 6); -	cipher.encrypt(buffer, HASHED_LENGTH); - -	if (fwrite(buffer, HASHED_LENGTH, 1, fp) != 1) -	{ -		LL_WARNS("AppInit") << "Short write" << LL_ENDL; -	} - -	fclose(fp); -} - - -// static -void LLStartUp::deletePasswordFromDisk() -{ -	std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, -														  "password.dat"); -	LLFile::remove(filepath); -} - - -bool is_hex_string(U8* str, S32 len) -{ -	bool rv = true; -	U8* c = str; -	while(rv && len--) -	{ -		switch(*c) -		{ -		case '0': -		case '1': -		case '2': -		case '3': -		case '4': -		case '5': -		case '6': -		case '7': -		case '8': -		case '9': -		case 'a': -		case 'b': -		case 'c': -		case 'd': -		case 'e': -		case 'f': -			++c; -			break; -		default: -			rv = false; -			break; -		} -	} -	return rv; -} -  void show_first_run_dialog()  {  	LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); @@ -2881,33 +2680,45 @@ bool process_login_success_response()  	text = response["secure_session_id"].asString();  	if(!text.empty()) gAgent.mSecureSessionID.set(text); -	text = response["first_name"].asString(); -	if(!text.empty())  -	{ -		// Remove quotes from string.  Login.cgi sends these to force -		// names that look like numbers into strings. -		gFirstname.assign(text); -		LLStringUtil::replaceChar(gFirstname, '"', ' '); -		LLStringUtil::trim(gFirstname); -	} -	text = response["last_name"].asString(); -	if(!text.empty())  +	// if the response contains a display name, use that, +	// otherwise if the response contains a first and/or last name, +	// use those.  Otherwise use the credential identifier + +	gDisplayName = ""; +	if (response.has("display_name"))  	{ -		gLastname.assign(text); +		gDisplayName.assign(response["display_name"].asString()); +		if(!gDisplayName.empty()) +		{ +			// Remove quotes from string.  Login.cgi sends these to force +			// names that look like numbers into strings. +			LLStringUtil::replaceChar(gDisplayName, '"', ' '); +			LLStringUtil::trim(gDisplayName); +		}  	} -	gSavedSettings.setString("FirstName", gFirstname); -	gSavedSettings.setString("LastName", gLastname); - -	if (gSavedSettings.getBOOL("RememberPassword")) +	if(gDisplayName.empty())  	{ -		// Successful login means the password is valid, so save it. -		LLStartUp::savePasswordToDisk(gPassword); +		if(response.has("first_name")) +		{ +			gDisplayName.assign(response["first_name"].asString()); +			LLStringUtil::replaceChar(gDisplayName, '"', ' '); +			LLStringUtil::trim(gDisplayName); +		} +		if(response.has("last_name")) +		{ +			text.assign(response["last_name"].asString()); +			LLStringUtil::replaceChar(text, '"', ' '); +			LLStringUtil::trim(text); +			if(!gDisplayName.empty()) +			{ +				gDisplayName += " "; +			} +			gDisplayName += text; +		}  	} -	else +	if(gDisplayName.empty())  	{ -		// Don't leave password from previous session sitting around -		// during this login session. -		LLStartUp::deletePasswordFromDisk(); +		gDisplayName.assign(gUserCredential->asString());  	}  	// this is their actual ability to access content @@ -3108,7 +2919,7 @@ bool process_login_success_response()  	bool success = false;  	// JC: gesture loading done below, when we have an asset system -	// in place.  Don't delete/clear user_credentials until then. +	// in place.  Don't delete/clear gUserCredentials until then.  	if(gAgentID.notNull()  	   && gAgentSessionID.notNull()  	   && gMessageSystem->mOurCircuitCode diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index 92fe9521d3..28bc7fcd2a 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -101,14 +101,6 @@ public:  	static void loadInitialOutfit( const std::string& outfit_folder_name,  								   const std::string& gender_name ); -	// Load MD5 of user's password from local disk file. -	static std::string loadPasswordFromDisk(); -	 -	// Record MD5 of user's password for subsequent login. -	static void savePasswordToDisk(const std::string& hashed_password); -	 -	// Delete the saved password local disk file. -	static void deletePasswordFromDisk();  	static bool dispatchURL();  		// if we have a SLURL or sim string ("Ahern/123/45") that started diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 1bff04352c..00f4454fab 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -424,7 +424,7 @@ void init_menus()  	gPopupMenuView->setBackgroundColor( color );  	// If we are not in production, use a different color to make it apparent. -	if (LLViewerLogin::getInstance()->isInProductionGrid()) +	if (LLGridManager::getInstance()->isInProductionGrid())  	{  		color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );  	} @@ -439,7 +439,7 @@ void init_menus()  	gMenuHolder->addChild(gMenuBarView);      gViewerWindow->setMenuBackgroundColor(false,  -        LLViewerLogin::getInstance()->isInProductionGrid()); +        LLGridManager::getInstance()->isInProductionGrid());  	// Assume L$10 for now, the server will tell us the real cost at login  	// *TODO:Also fix cost in llfolderview.cpp for Inventory menus @@ -3415,7 +3415,7 @@ void set_god_level(U8 god_level)          if(gViewerWindow)          {              gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT, -            LLViewerLogin::getInstance()->isInProductionGrid()); +            LLGridManager::getInstance()->isInProductionGrid());          }          LLSD args; @@ -3455,7 +3455,7 @@ BOOL check_toggle_hacked_godmode(void*)  bool enable_toggle_hacked_godmode(void*)  { -  return !LLViewerLogin::getInstance()->isInProductionGrid(); +  return !LLGridManager::getInstance()->isInProductionGrid();  }  #endif @@ -4320,7 +4320,7 @@ BOOL enable_take()  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid()  +		if (!LLGridManager::getInstance()->isInProductionGrid()               && gAgent.isGodlike())  		{  			return TRUE; @@ -4947,7 +4947,7 @@ bool enable_object_delete()  	TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -	(!LLViewerLogin::getInstance()->isInProductionGrid() +	(!LLGridManager::getInstance()->isInProductionGrid()       && gAgent.isGodlike()) ||  # endif  	LLSelectMgr::getInstance()->canDoDelete(); @@ -6556,7 +6556,7 @@ bool enable_object_take_copy()  		all_valid = true;  #ifndef HACKED_GODLIKE_VIEWER  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (LLViewerLogin::getInstance()->isInProductionGrid() +		if (LLGridManager::getInstance()->isInProductionGrid()              || !gAgent.isGodlike())  # endif  		{ @@ -6618,7 +6618,7 @@ BOOL enable_save_into_inventory(void*)  	return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -	if (!LLViewerLogin::getInstance()->isInProductionGrid() +	if (!LLGridManager::getInstance()->isInProductionGrid()          && gAgent.isGodlike())  	{  		return TRUE; diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index d7b55d7e97..fcfaf1eef2 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -5,7 +5,7 @@   *   * $LicenseInfo:firstyear=2006&license=viewergpl$   *  - * Copyright (c) 2006-2009, Linden Research, Inc. + * Copyright (c) 2006-2007, Linden Research, Inc.   *    * Second Life Viewer Source Code   * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,13 +13,12 @@   * ("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 + * online at http://secondlife.com/developers/opensource/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 + * online at http://secondlife.com/developers/opensource/flossexception   *    * By copying, modifying or distributing this software, you acknowledge   * that you have read and understood your obligations described above, @@ -34,302 +33,462 @@  #include "llviewerprecompiledheaders.h"  #include "llviewernetwork.h" +#include "llviewercontrol.h" +#include "llsdserialize.h" +#include "llweb.h" -#include "llevents.h" -#include "net.h" +                                                             +const char* DEFAULT_LOGIN_PAGE = "http://secondlife.com/app/login/"; -#include "llviewercontrol.h" -#include "lllogin.h" +const char* SYSTEM_GRID_SLURL_BASE = "http://slurl.com/secondlife/"; +const char* SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; -struct LLGridData -{ -	const char* mLabel; -	const char* mName; -	const char* mLoginURI; -	const char* mHelperURI; -}; +const char* DEFAULT_SLURL_BASE = "https://%s/region/"; +const char* DEFAULT_APP_SLURL_BASE = "x-grid-location-info://%s/app"; -static LLGridData gGridInfo[GRID_INFO_COUNT] =  +LLGridManager::LLGridManager()  { -	{ "None", "", "", ""}, -	{ "Aditi",  -	  "util.aditi.lindenlab.com",  -	  "https://login.aditi.lindenlab.com/cgi-bin/login.cgi", -	  "http://aditi-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Agni",  -	  "util.agni.lindenlab.com",  -	  "https://login.agni.lindenlab.com/cgi-bin/login.cgi", -	  "https://secondlife.com/helpers/" }, -	{ "Aruna", -	  "util.aruna.lindenlab.com", -	  "https://login.aruna.lindenlab.com/cgi-bin/login.cgi", -	  "http://aruna-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Bharati", -	  "util.bharati.lindenlab.com", -	  "https://login.bharati.lindenlab.com/cgi-bin/login.cgi", -	  "http://bharati-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Chandra", -	  "util.chandra.lindenlab.com", -	  "https://login.chandra.lindenlab.com/cgi-bin/login.cgi", -	  "http://chandra-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Damballah", -	  "util.damballah.lindenlab.com", -	  "https://login.damballah.lindenlab.com/cgi-bin/login.cgi", -	  "http://damballah-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Danu", -	  "util.danu.lindenlab.com", -	  "https://login.danu.lindenlab.com/cgi-bin/login.cgi", -	  "http://danu-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Durga", -	  "util.durga.lindenlab.com", -	  "https://login.durga.lindenlab.com/cgi-bin/login.cgi", -	  "http://durga-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Ganga", -	  "util.ganga.lindenlab.com", -	  "https://login.ganga.lindenlab.com/cgi-bin/login.cgi", -	  "http://ganga-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Mitra", -	  "util.mitra.lindenlab.com", -	  "https://login.mitra.lindenlab.com/cgi-bin/login.cgi", -	  "http://mitra-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Mohini", -	  "util.mohini.lindenlab.com", -	  "https://login.mohini.lindenlab.com/cgi-bin/login.cgi", -	  "http://mohini-secondlife.webdev.lindenlab.com/helpers/" }, -  	{ "Nandi", -	  "util.nandi.lindenlab.com", -	  "https://login.nandi.lindenlab.com/cgi-bin/login.cgi", -	  "http://nandi-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Parvati", -	  "util.parvati.lindenlab.com", -	  "https://login.parvati.lindenlab.com/cgi-bin/login.cgi", -	  "http://parvati-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Radha", -	  "util.radha.lindenlab.com", -	  "https://login.radha.lindenlab.com/cgi-bin/login.cgi", -	  "http://radha-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Ravi", -	  "util.ravi.lindenlab.com", -	  "https://login.ravi.lindenlab.com/cgi-bin/login.cgi", -	  "http://ravi-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Siva",  -	  "util.siva.lindenlab.com", -	  "https://login.siva.lindenlab.com/cgi-bin/login.cgi", -	  "http://siva-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Shakti", -	  "util.shakti.lindenlab.com", -	  "https://login.shakti.lindenlab.com/cgi-bin/login.cgi", -	  "http://shakti-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Skanda", -	  "util.skanda.lindenlab.com", -	  "https://login.skanda.lindenlab.com/cgi-bin/login.cgi", -	  "http://skanda-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Soma", -	  "util.soma.lindenlab.com", -	  "https://login.soma.lindenlab.com/cgi-bin/login.cgi", -	  "http://soma-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Uma", -	  "util.uma.lindenlab.com", -	  "https://login.uma.lindenlab.com/cgi-bin/login.cgi", -	  "http://uma-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Vaak", -	  "util.vaak.lindenlab.com", -	  "https://login.vaak.lindenlab.com/cgi-bin/login.cgi", -	  "http://vaak-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Yami", -	  "util.yami.lindenlab.com", -	  "https://login.yami.lindenlab.com/cgi-bin/login.cgi", -	  "http://yami-secondlife.webdev.lindenlab.com/helpers/" }, -	{ "Local",  -	  "localhost",  -	  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi", -	  "" }, -	{ "Other",  -	  "",  -	  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi", -	  "" } -}; - -const EGridInfo DEFAULT_GRID_CHOICE = GRID_INFO_AGNI; - - -unsigned char gMACAddress[MAC_ADDRESS_BYTES];		/* Flawfinder: ignore */ - -LLViewerLogin::LLViewerLogin() : -	mGridChoice(DEFAULT_GRID_CHOICE) +	// by default, we use the 'grids.xml' file in the user settings directory +	// this file is an LLSD file containing multiple grid definitions. +	// This file does not contain definitions for secondlife.com grids, +	// as that would be a security issue when they are overwritten by +	// an attacker.  Don't want someone snagging a password. +	std::string grid_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, +														   "grids.xml"); +	initialize(grid_file); +	 +} + + +LLGridManager::LLGridManager(const std::string& grid_file)  { +	// initialize with an explicity grid file for testing. +	initialize(grid_file);  } - LLViewerLogin::~LLViewerLogin()  - { - } +// +// LLGridManager - class for managing the list of known grids, and the current +// selection +// + + +// +// LLGridManager::initialze - initialize the list of known grids based +// on the fixed list of linden grids (fixed for security reasons) +// the grids.xml file +// and the command line. +void LLGridManager::initialize(const std::string& grid_file) +{ +	// default grid list. +	// Don't move to a modifiable file for security reasons, +	mGridName.clear() ; +	// set to undefined +	mGridList = LLSD(); +	mGridFile = grid_file; +	// as we don't want an attacker to override our grid list +	// to point the default grid to an invalid grid +	addSystemGrid("None", "", "", "", DEFAULT_LOGIN_PAGE); +	 + + +#ifndef LL_RELEASE_FOR_DOWNLOAD +  	addSystemGrid("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",                    +				  "http://aditi-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Aruna",                                                                                             +				  "util.aruna.lindenlab.com",                                               +				  "https://login.aruna.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://aruna-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Durga",                                                                                             +				  "util.durga.lindenlab.com",                                               +				  "https://login.durga.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://durga-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Ganga",                                                                                             +				  "util.ganga.lindenlab.com",                                               +				  "https://login.ganga.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://ganga-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Mitra",                                                                                             +				  "util.mitra.lindenlab.com",                                               +				  "https://login.mitra.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://mitra-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Mohini",                                                                                            +				  "util.mohini.lindenlab.com",                                              +				  "https://login.mohini.lindenlab.com/cgi-bin/login.cgi",                   +				  "http://mohini-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Nandi",                                                                                             +				  "util.nandi.lindenlab.com",                                               +				  "https://login.nandi.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://nandi-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Radha",                                                                                             +				  "util.radha.lindenlab.com",                                               +				  "https://login.radha.lindenlab.com/cgi-bin/login.cgi",                    +				  "http://radha-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Ravi",                                                                                              +				  "util.ravi.lindenlab.com",                                                +				  "https://login.ravi.lindenlab.com/cgi-bin/login.cgi",                     +				  "http://ravi-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Siva",                                                                                              +				  "util.siva.lindenlab.com",                                                +				  "https://login.siva.lindenlab.com/cgi-bin/login.cgi",                     +				  "http://siva-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Shakti",                                                                                            +				  "util.shakti.lindenlab.com",                                              +				  "https://login.shakti.lindenlab.com/cgi-bin/login.cgi",                   +				  "http://shakti-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Soma",                                                                                              +				  "util.soma.lindenlab.com",                                                +				  "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",                      +				  "http://uma-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Vaak",                                                                                              +				  "util.vaak.lindenlab.com",                                                +				  "https://login.vaak.lindenlab.com/cgi-bin/login.cgi",                     +				  "http://vaak-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Yami",                                                                                              +				  "util.yami.lindenlab.com",                                                +				  "https://login.yami.lindenlab.com/cgi-bin/login.cgi",                     +				  "http://yami-secondlife.webdev.lindenlab.com/helpers/", +				  DEFAULT_LOGIN_PAGE); +	addSystemGrid("Local (Linden)",                                                                                     +				  "localhost",                                                              +				  "https://login.dmz.lindenlab.com/cgi-bin/login.cgi",                      +				  "", +				  DEFAULT_LOGIN_PAGE);  + +	 +	LLSD other_grids; +	llifstream llsd_xml; +	if (!grid_file.empty()) +	{ +		llsd_xml.open( grid_file.c_str(), std::ios::in | std::ios::binary ); -void LLViewerLogin::setGridChoice(EGridInfo grid) -{	 -	if(grid < 0 || grid >= GRID_INFO_COUNT) +		// parse through the gridfile, inserting grids into the list unless +		// they overwrite a linden grid. +		if( llsd_xml.is_open())  +		{ +			LLSDSerialize::fromXMLDocument( other_grids, llsd_xml ); +			if(other_grids.isMap()) +			{ +				for(LLSD::map_iterator grid_itr = other_grids.beginMap();  +					grid_itr != other_grids.endMap(); +					++grid_itr) +				{ +					LLSD::String key_name = grid_itr->first; +					LLSD grid = grid_itr->second; +					// TODO:  Make sure gridfile specified label is not  +					// a system grid label +					LL_INFOS("GridManager") << "reading: " << key_name << LL_ENDL; +					if (mGridList.has(key_name) && +						mGridList[key_name].has(GRID_IS_SYSTEM_GRID_VALUE)) +					{ +						LL_INFOS("GridManager") << "Cannot override grid " << key_name << " as it's a system grid" << LL_ENDL; +						// If the system grid does exist in the grids file, and it's marked as a favorite, set it as a favorite. +						if(grid_itr->second.has(GRID_IS_FAVORITE_VALUE) && grid_itr->second[GRID_IS_FAVORITE_VALUE].asBoolean() ) +						{ +							mGridList[key_name][GRID_IS_FAVORITE_VALUE] = TRUE; +						} +					} +					else +					{ +						try +						{ +							addGrid(grid); +							LL_INFOS("GridManager") << "Added grid: " << key_name << LL_ENDL; +						} +						catch (...) +						{ +						} +					} +				} +				llsd_xml.close(); +			}	 +		}      +	} +	 +	// load a grid from the command line. +	// if the actual grid name is specified from the command line, +	// set it as the 'selected' grid. +	LLSD cmd_line_grid = gSavedSettings.getString("CmdLineGridChoice"); +	if (gSavedSettings.controlExists("CmdLineGridChoice"))  	{ -		llerrs << "Invalid grid index specified." << llendl; +		mGridName = gSavedSettings.getString("CmdLineGridChoice"); +		LL_INFOS("GridManager") << "Grid Name: " << mGridName << LL_ENDL;		  	} +	 +	// If a command line login URI was passed in, so we should add the command +	// line grid to the list of grids -	if(mGridChoice != grid || gSavedSettings.getS32("ServerChoice") != grid) +	LLSD cmd_line_login_uri = gSavedSettings.getLLSD("CmdLineLoginURI"); +	if (cmd_line_login_uri.isString())  	{ -		mGridChoice = grid; -		if(GRID_INFO_LOCAL == mGridChoice) +		LL_INFOS("GridManager") << "adding cmd line login uri" << LL_ENDL; +		// grab the other related URI values +		std::string cmd_line_helper_uri = gSavedSettings.getString("CmdLineHelperURI"); +		std::string cmd_line_login_page = gSavedSettings.getString("LoginPage"); +		 +		// we've a cmd line login, so add a grid for the command line, +		// overwriting any existing grids +		LLSD grid = LLSD::emptyMap(); +		grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray(); +		grid[GRID_LOGIN_URI_VALUE].append(cmd_line_login_uri); +		LL_INFOS("GridManager") << "cmd line login uri: " << cmd_line_login_uri.asString() << LL_ENDL; +		LLURI uri(cmd_line_login_uri.asString()); +		if (mGridName.empty())  		{ -			mGridName = LOOPBACK_ADDRESS_STRING; +			// if a grid name was not passed in via the command line, +			// then set the grid name based on the hostname of the  +			// login uri +			mGridName = uri.hostName();  		} -		else if(GRID_INFO_OTHER == mGridChoice) + +		grid[GRID_NAME_VALUE] = mGridName; + +		if (mGridList.has(mGridName) && mGridList[mGridName].has(GRID_LABEL_VALUE))  		{ -			// *FIX:Mani - could this possibly be valid? -			mGridName = "other";  +			grid[GRID_LABEL_VALUE] = mGridList[mGridName][GRID_LABEL_VALUE];  		}  		else  		{ -			mGridName = gGridInfo[mGridChoice].mLabel; +			grid[GRID_LABEL_VALUE] = mGridName;			 +		} +		if(!cmd_line_helper_uri.empty()) +		{ +			grid[GRID_HELPER_URI_VALUE] = cmd_line_helper_uri; +		} + +		if(!cmd_line_login_page.empty()) +		{ +			grid[GRID_LOGIN_PAGE_VALUE] = cmd_line_login_page; +		} +		// if the login page, helper URI value, and so on are not specified, +		// add grid will generate them. + +		// Also, we will override a system grid if values are passed in via the command +		// line, for testing.  These values will not be remembered though. +		if (mGridList.has(mGridName) && mGridList[mGridName].has(GRID_IS_SYSTEM_GRID_VALUE)) +		{ +			grid[GRID_IS_SYSTEM_GRID_VALUE] = TRUE;  		} +		addGrid(grid); +	} +	 +	// if a grid was not passed in via the command line, grab it from the CurrentGrid setting. +	if (mGridName.empty()) +	{ -		gSavedSettings.setS32("ServerChoice", mGridChoice); -		gSavedSettings.setString("CustomServer", ""); +		mGridName = gSavedSettings.getString("CurrentGrid");  	} -} -void LLViewerLogin::setGridChoice(const std::string& grid_name) -{ -	// Set the grid choice based on a string. -	// The string can be: -	// - a grid label from the gGridInfo table  -	// - an ip address -    if(!grid_name.empty()) -    { -        // find the grid choice from the user setting. -        int grid_index = GRID_INFO_NONE;  -        for(;grid_index < GRID_INFO_OTHER; ++grid_index) -        { -            if(0 == LLStringUtil::compareInsensitive(gGridInfo[grid_index].mLabel, grid_name)) -            { -				// Founding a matching label in the list... -				setGridChoice((EGridInfo)grid_index); -				break; -            } -        } - -        if(GRID_INFO_OTHER == grid_index) -        { -            // *FIX:MEP Can and should we validate that this is an IP address? -            mGridChoice = GRID_INFO_OTHER; -            mGridName = grid_name; -			gSavedSettings.setS32("ServerChoice", mGridChoice); -			gSavedSettings.setString("CustomServer", mGridName); -        } -    } +	if (mGridName.empty() || !mGridList.has(mGridName)) +	{ +		// 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 " << mGridName << " is not in the list" << LL_ENDL; +#if LL_RELEASE_FOR_DOWNLOAD +		mGridName = MAINGRID; +#else +		mGridName = ""; +#endif +	} +	LL_INFOS("GridManager") << "Selected grid is " << mGridName << LL_ENDL;		 +	gSavedSettings.setString("CurrentGrid", mGridName); +  } -void LLViewerLogin::resetURIs() +LLGridManager::~LLGridManager()  { -    // Clear URIs when picking a new server -	gSavedSettings.setLLSD("CmdLineLoginURI", LLSD::emptyArray()); -	gSavedSettings.setString("CmdLineHelperURI", ""); +	saveFavorites();  } -EGridInfo LLViewerLogin::getGridChoice() const +// +// LLGridManager::addGrid - add a grid to the grid list, populating the needed values +// if they're not populated yet. +// + +void LLGridManager::addGrid(LLSD& grid_data)  { -	return mGridChoice; +	if (grid_data.isMap() && grid_data.has(GRID_NAME_VALUE)) +	{ +		std::string grid_name = utf8str_tolower(grid_data[GRID_NAME_VALUE]); + +		// grid_name should be in the form of a dns address +		if (!grid_name.empty() && +			grid_name.find_first_not_of("abcdefghijklmnopqrstuvwxyz1234567890-_. ") != std::string::npos) +		{ +			printf("grid name: %s", grid_name.c_str()); +			throw LLInvalidGridName(grid_name); +		} +		 +		// populate the other values if they don't exist +		if (!grid_data.has(GRID_LABEL_VALUE))  +		{ +			grid_data[GRID_LABEL_VALUE] = grid_name; +		} +		if (!grid_data.has(GRID_ID_VALUE)) +		{ +			grid_data[GRID_ID_VALUE] = grid_name; +		} +		 +		// if the grid data doesn't include any of the URIs, then  +		// generate them from the grid_name, which should be a dns address +		if (!grid_data.has(GRID_LOGIN_URI_VALUE))  +		{ +			grid_data[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray(); +			grid_data[GRID_LOGIN_URI_VALUE].append(std::string("https://") +  +													grid_name + "/cgi-bin/login.cgi"); +		} +		// Populate to the default values +		if (!grid_data.has(GRID_LOGIN_PAGE_VALUE))  +		{ +			grid_data[GRID_LOGIN_PAGE_VALUE] = std::string("http://") + grid_name + "/app/login/"; +		}		 +		if (!grid_data.has(GRID_HELPER_URI_VALUE))  +		{ +			grid_data[GRID_HELPER_URI_VALUE] = std::string("https://") + grid_name + "/helpers/"; +		}		 +		LL_INFOS("GridManager") << "ADDING: " << grid_name << LL_ENDL; +		mGridList[grid_name] = grid_data;		 +	}  } -std::string LLViewerLogin::getGridLabel() const +// +// LLGridManager::addSystemGrid - helper for adding a system grid. +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)  { -	if(mGridChoice == GRID_INFO_NONE) +	LLSD grid = LLSD::emptyMap(); +	grid[GRID_NAME_VALUE] = name; +	grid[GRID_LABEL_VALUE] = label; +	grid[GRID_HELPER_URI_VALUE] = helper; +	grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray(); +	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_SLURL_BASE] = SYSTEM_GRID_SLURL_BASE; +	grid[GRID_APP_SLURL_BASE] = SYSTEM_GRID_APP_SLURL_BASE; +	if (login_id.empty())  	{ -		return "None"; +		grid[GRID_ID_VALUE] = name;  	} -	else if(mGridChoice < GRID_INFO_OTHER) +	else  	{ -		return gGridInfo[mGridChoice].mLabel; +		grid[GRID_ID_VALUE] = login_id;  	} - -	return mGridName; -} - -std::string LLViewerLogin::getKnownGridLabel(EGridInfo grid_index) const -{ -	if(grid_index > GRID_INFO_NONE && grid_index < GRID_INFO_OTHER) +	 +	// only add the system grids beyond agni to the visible list +	// if we're building a debug version. +	if (name == std::string(MAINGRID))  	{ -		return gGridInfo[grid_index].mLabel; +		grid[GRID_IS_FAVORITE_VALUE] = TRUE;		  	} -	return gGridInfo[GRID_INFO_NONE].mLabel; +	addGrid(grid);  } -void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const +// return a list of grid name -> grid label mappings for UI purposes +std::map<std::string, std::string> LLGridManager::getKnownGrids(bool favorite_only)  { -	// return the login uri set on the command line. -	LLControlVariable* c = gSavedSettings.getControl("CmdLineLoginURI"); -	if(c) +	std::map<std::string, std::string> result; +	for(LLSD::map_iterator grid_iter = mGridList.beginMap(); +		grid_iter != mGridList.endMap(); +		grid_iter++)   	{ -		LLSD v = c->getValue(); -		if(v.isArray()) +		if(!favorite_only || grid_iter->second.has(GRID_IS_FAVORITE_VALUE))  		{ -			for(LLSD::array_const_iterator itr = v.beginArray(); -				itr != v.endArray(); ++itr) -			{ -				std::string uri = itr->asString(); -				if(!uri.empty()) -				{ -					uris.push_back(uri); -				} -			} -		} -		else -		{ -			std::string uri = v.asString(); -			if(!uri.empty()) -			{ -				uris.push_back(uri); -			} +			result[grid_iter->first] = grid_iter->second[GRID_LABEL_VALUE].asString();  		}  	} -	// If there was no command line uri... -	if(uris.empty()) +	return result; +} + +void LLGridManager::setGridChoice(const std::string& grid_name) +{ +	// Set the grid choice based on a string. +	// The string can be: +	// - a grid label from the gGridInfo table  +	// - a hostname +	// - an ip address + +	// loop through.  We could do just a hash lookup but we also want to match +	// on label +	for(LLSD::map_iterator grid_iter = mGridList.beginMap(); +		grid_iter != mGridList.endMap(); +		grid_iter++)   	{ -		// If its a known grid choice, get the uri from the table, -		// else try the grid name. -		if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER) +		if((grid_name == grid_iter->first) ||  +		   (grid_name == grid_iter->second[GRID_LABEL_VALUE].asString()))  		{ -			uris.push_back(gGridInfo[mGridChoice].mLoginURI); -		} -		else -		{ -			uris.push_back(mGridName); +			mGridName = grid_iter->second[GRID_NAME_VALUE].asString(); +			gSavedSettings.setString("CurrentGrid", grid_iter->second[GRID_NAME_VALUE]);			 +			return;  +  		}  	} +	LLSD grid = LLSD::emptyMap(); +	grid[GRID_NAME_VALUE] = grid_name; +	addGrid(grid); +	mGridName = grid_name; +	gSavedSettings.setString("CurrentGrid", grid_name);  } -std::string LLViewerLogin::getHelperURI() const +void LLGridManager::getLoginURIs(std::vector<std::string>& uris)  { -	std::string helper_uri = gSavedSettings.getString("CmdLineHelperURI"); -	if (helper_uri.empty()) +	uris.clear(); +	for (LLSD::array_iterator llsd_uri = mGridList[mGridName][GRID_LOGIN_URI_VALUE].beginArray(); +		 llsd_uri != mGridList[mGridName][GRID_LOGIN_URI_VALUE].endArray(); +		 llsd_uri++)  	{ -		// grab URI from selected grid -		if(mGridChoice > GRID_INFO_NONE && mGridChoice < GRID_INFO_OTHER) -		{ -			helper_uri = gGridInfo[mGridChoice].mHelperURI; -		} - -		if (helper_uri.empty()) -		{ -			// what do we do with unnamed/miscellaneous grids? -			// for now, operations that rely on the helper URI (currency/land purchasing) will fail -		} +		uris.push_back(llsd_uri->asString());  	} -	return helper_uri;  } -bool LLViewerLogin::isInProductionGrid() +bool LLGridManager::isInProductionGrid()  {  	// *NOTE:Mani This used to compare GRID_INFO_AGNI to gGridChoice,  	// but it seems that loginURI trumps that.  	std::vector<std::string> uris;  	getLoginURIs(uris); +	if (uris.size() < 1) +	{ +		return 1; +	}  	LLStringUtil::toLower(uris[0]);  	if((uris[0].find("agni") != std::string::npos))  	{ @@ -338,3 +497,51 @@ bool LLViewerLogin::isInProductionGrid()  	return false;  } + +void LLGridManager::saveFavorites() +{ +	// filter out just those marked as favorites +	LLSD output_grid_list = LLSD::emptyMap(); +	for(LLSD::map_iterator grid_iter = mGridList.beginMap(); +		grid_iter != mGridList.endMap(); +		grid_iter++) +	{ +		if(grid_iter->second.has(GRID_IS_FAVORITE_VALUE)) +		{ +			output_grid_list[grid_iter->first] = grid_iter->second; +		} +	}        +	llofstream llsd_xml; +	llsd_xml.open( mGridFile.c_str(), std::ios::out | std::ios::binary);	 +	LLSDSerialize::toPrettyXML(output_grid_list, llsd_xml); +	llsd_xml.close(); +} + + +// build a slurl for the given region within the selected grid +std::string LLGridManager::getSLURLBase(const std::string& grid_name) +{ +	std::string grid_base; +	if(mGridList.has(grid_name) && mGridList[grid_name].has(GRID_SLURL_BASE)) +	{ +		return mGridList[grid_name][GRID_SLURL_BASE].asString(); +	} +	else +	{ +		return  llformat(DEFAULT_SLURL_BASE, grid_name.c_str()); +	} +} + +// build a slurl for the given region within the selected grid +std::string LLGridManager::getAppSLURLBase(const std::string& grid_name) +{ +	std::string grid_base; +	if(mGridList.has(grid_name) && mGridList[grid_name].has(GRID_APP_SLURL_BASE)) +	{ +		return mGridList[grid_name][GRID_APP_SLURL_BASE].asString(); +	} +	else +	{ +		return  llformat(DEFAULT_APP_SLURL_BASE, grid_name.c_str()); +	} +} diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index edae6dc47b..7b3ce9c499 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -5,7 +5,7 @@   *   * $LicenseInfo:firstyear=2006&license=viewergpl$   *  - * Copyright (c) 2006-2009, Linden Research, Inc. + * Copyright (c) 2006-2007, Linden Research, Inc.   *    * Second Life Viewer Source Code   * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,13 +13,12 @@   * ("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 + * online at http://secondlife.com/developers/opensource/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 + * online at http://secondlife.com/developers/opensource/flossexception   *    * By copying, modifying or distributing this software, you acknowledge   * that you have read and understood your obligations described above, @@ -33,83 +32,137 @@  #ifndef LL_LLVIEWERNETWORK_H  #define LL_LLVIEWERNETWORK_H +                                                                                                        +extern const char* DEFAULT_LOGIN_PAGE; +       +#define GRID_NAME_VALUE "name" +#define GRID_LABEL_VALUE "label" +#define GRID_ID_VALUE "grid_login_id" +#define GRID_LOGIN_URI_VALUE "login_uri" +#define GRID_HELPER_URI_VALUE "helper_uri" +#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" -#include <boost/scoped_ptr.hpp> +// 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 +// forms. +#define GRID_SLURL_BASE "slurl_base" +#define GRID_APP_SLURL_BASE "app_slurl_base" -class LLHost; -class LLLogin; - -enum EGridInfo +class LLInvalidGridName  { -	GRID_INFO_NONE, -	GRID_INFO_ADITI, -	GRID_INFO_AGNI, -	GRID_INFO_ARUNA, -	GRID_INFO_BHARATI, -	GRID_INFO_CHANDRA, -	GRID_INFO_DAMBALLAH, -	GRID_INFO_DANU, -	GRID_INFO_DURGA, -	GRID_INFO_GANGA, -	GRID_INFO_MITRA, -	GRID_INFO_MOHINI, -	GRID_INFO_NANDI, -	GRID_INFO_PARVATI, -	GRID_INFO_RADHA, -	GRID_INFO_RAVI, -	GRID_INFO_SIVA, -	GRID_INFO_SHAKTI, -	GRID_INFO_SKANDA, -	GRID_INFO_SOMA, -	GRID_INFO_UMA, -	GRID_INFO_VAAK, -	GRID_INFO_YAMI, -	GRID_INFO_LOCAL, -	GRID_INFO_OTHER, // IP address set via command line option -	GRID_INFO_COUNT +public: +	LLInvalidGridName(std::string grid_name) : mGridName(grid_name) +	{ +	} +protected: +	std::string mGridName;  }; +  /** - * @brief A class to manage the viewer's login state. + * @brief A class to manage the grids available to the viewer + * including persistance.  This class also maintains the currently + * selected grid.   *    **/ -class LLViewerLogin : public LLSingleton<LLViewerLogin> +class LLGridManager : public LLSingleton<LLGridManager>  {  public: -	LLViewerLogin(); -	~LLViewerLogin(); - -	void setGridChoice(EGridInfo grid); -	void setGridChoice(const std::string& grid_name); -	void resetURIs(); +	 +	// when the grid manager is instantiated, the default grids are automatically +	// loaded, and the grids favorites list is loaded from the xml file. +	LLGridManager(const std::string& grid_file); +	LLGridManager(); +	~LLGridManager(); +	 +	void initialize(const std::string& grid_file); +	// grid list management +	 +	// add a grid to the list of grids +	void addGrid(LLSD& grid_info);	 -	/** -	* @brief Get the enumeration of the grid choice. -	* Should only return values > 0 && < GRID_INFO_COUNT -	**/ -	EGridInfo getGridChoice() const; - -	/** -	* @brief Get a readable label for the grid choice. -	* Returns the readable name for the grid choice.  -	* If the grid is 'other', returns something -	* the string used to specifiy the grid. -	**/ -	std::string getGridLabel() const;  - -	std::string getKnownGridLabel(EGridInfo grid_index) const;  - -	void getLoginURIs(std::vector<std::string>& uris) const; -	std::string getHelperURI() const; +	// retrieve a map of grid-name <-> label +	// by default only return the user visible grids +	std::map<std::string, std::string> getKnownGrids(bool favorites_only=FALSE); +	 +	LLSD getGridInfo(const std::string& grid_name) +	{ +		if(mGridList.has(grid_name)) +		{ +			return mGridList[grid_name]; +		} +		else +		{ +			return LLSD(); +		} +	} +	 +	// current grid management +	// select a given grid as the current grid.  If the grid +	// is not a known grid, then it's assumed to be a dns name for the +	// grid, and the various URIs will be automatically generated. +	void setGridChoice(const std::string& grid_name); +	 +	 +	std::string getGridLabel()  +	{  +		return mGridList[mGridName][GRID_LABEL_VALUE];  +	} 	 +	std::string getGridName() const { return mGridName; } +	void getLoginURIs(std::vector<std::string>& uris); +	std::string getHelperURI() {return mGridList[mGridName][GRID_HELPER_URI_VALUE];} +	std::string getLoginPage() {return mGridList[mGridName][GRID_LOGIN_PAGE_VALUE];} +	std::string getGridID() { return mGridList[mGridName][GRID_ID_VALUE]; }	 +	std::string getLoginPage(const std::string& grid_name) { return mGridList[grid_name][GRID_LOGIN_PAGE_VALUE]; } +	 +	// build a slurl for the given region within the selected grid +	std::string getSLURLBase(const std::string& grid_name); +	std::string getSLURLBase() { return getSLURLBase(mGridName); } +	 +	std::string getAppSLURLBase(const std::string& grid_name); +	std::string getAppSLURLBase() { return getAppSLURLBase(mGridName); }	 +	 +	LLSD getGridInfo() { return mGridList[mGridName]; } +	 +	bool isSystemGrid(const std::string& grid)  +	{  +		return mGridList.has(grid) && +		      mGridList[grid].has(GRID_IS_SYSTEM_GRID_VALUE) &&  +	           mGridList[grid][GRID_IS_SYSTEM_GRID_VALUE].asBoolean();  +	} +	bool isSystemGrid() { return isSystemGrid(mGridName); } +	// Mark this grid as a favorite that should be persisited on 'save' +	// this is currently used to persist a grid after a successful login +	void setFavorite() { mGridList[mGridName][GRID_IS_FAVORITE_VALUE] = TRUE; } +	  	bool isInProductionGrid(); +	void saveFavorites(); +	void clearFavorites(); + +protected: -private: -	EGridInfo mGridChoice; +	// helper function for adding the predefined grids +	void 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::string mGridName; +	std::string mGridFile; +	LLSD mGridList;  };  const S32 MAC_ADDRESS_BYTES = 6; -extern unsigned char gMACAddress[MAC_ADDRESS_BYTES];		/* Flawfinder: ignore */  #endif diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 3c79045cc5..ce7b45bc11 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4705,7 +4705,7 @@ BOOL LLViewerObject::permYouOwner() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  		{  			return TRUE; @@ -4742,7 +4742,7 @@ BOOL LLViewerObject::permOwnerModify() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  	{  			return TRUE; @@ -4766,7 +4766,7 @@ BOOL LLViewerObject::permModify() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  	{  			return TRUE; @@ -4790,7 +4790,7 @@ BOOL LLViewerObject::permCopy() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  		{  			return TRUE; @@ -4814,7 +4814,7 @@ BOOL LLViewerObject::permMove() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  		{  			return TRUE; @@ -4838,7 +4838,7 @@ BOOL LLViewerObject::permTransfer() const  		return TRUE;  #else  # ifdef TOGGLE_HACKED_GODLIKE_VIEWER -		if (!LLViewerLogin::getInstance()->isInProductionGrid() +		if (!LLGridManager::getInstance()->isInProductionGrid()              && (gAgent.getGodLevel() >= GOD_MAINTENANCE))  		{  			return TRUE; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 8059f866ba..3f9a10a4a6 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -767,9 +767,11 @@ void send_stats()  	system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();  	system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();  	system["cpu"] = gSysCPU.getCPUString(); +	unsigned char MACAddress[MAC_ADDRESS_BYTES]; +	LLUUID::getNodeID(MACAddress);  	std::string macAddressString = llformat("%02x-%02x-%02x-%02x-%02x-%02x", -											gMACAddress[0],gMACAddress[1],gMACAddress[2], -											gMACAddress[3],gMACAddress[4],gMACAddress[5]); +											MACAddress[0],MACAddress[1],MACAddress[2], +											MACAddress[3],MACAddress[4],MACAddress[5]);  	system["mac_address"] = macAddressString;  	system["serial_number"] = LLAppViewer::instance()->getSerialNumber();  	std::string gpu_desc = llformat( diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 83cbc8a1f9..f8e08dbf7d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1815,7 +1815,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )  		// ...and set the menu color appropriately.  		setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT,  -			LLViewerLogin::getInstance()->isInProductionGrid()); +			LLGridManager::getInstance()->isInProductionGrid());  	}  	if ( gStatusBar ) @@ -1836,15 +1836,15 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)      LLSD args;      LLColor4 new_bg_color; -    if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid()) +    if(god_mode && LLGridManager::getInstance()->isInProductionGrid())      {          new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );      } -    else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) +    else if(god_mode && !LLGridManager::getInstance()->isInProductionGrid())      {          new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );      } -    else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid()) +    else if(!god_mode && !LLGridManager::getInstance()->isInProductionGrid())      {          new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );      } diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 423c46e14c..fc264a6fcf 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -1327,18 +1327,11 @@ void LLVoiceClient::connectorShutdown()  	}  } -void LLVoiceClient::userAuthorized(const std::string& firstName, const std::string& lastName, const LLUUID &agentID) +void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID)  { -	mAccountFirstName = firstName; -	mAccountLastName = lastName; +	LL_INFOS("Voice") << "name \"" << user_id << "\" , ID " << agentID << LL_ENDL; -	mAccountDisplayName = firstName; -	mAccountDisplayName += " "; -	mAccountDisplayName += lastName; - -	LL_INFOS("Voice") << "name \"" << mAccountDisplayName << "\" , ID " << agentID << LL_ENDL; - -	sConnectingToAgni = LLViewerLogin::getInstance()->isInProductionGrid(); +	sConnectingToAgni = LLGridManager::getInstance()->isInProductionGrid();  	mAccountName = nameFromID(agentID);  } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 724179847d..075834f7e0 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -428,10 +428,8 @@ static	void updatePosition(void);  		void connectorShutdown();  		void requestVoiceAccountProvision(S32 retries = 3); -		void userAuthorized( -			const std::string& firstName, -			const std::string& lastName, -			const LLUUID &agentID); +	void userAuthorized(const std::string& user_id, +						const LLUUID &agentID);  		void login(  			const std::string& account_name,  			const std::string& password, diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 7866f735c5..45b4d3cad3 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -146,7 +146,7 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,  	substitution["VERSION_BUILD"] = LLVersionInfo::getBuild();  	substitution["CHANNEL"] = LLVersionInfo::getChannel();  	substitution["LANGUAGE"] = LLUI::getLanguage(); -	substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel(); +	substitution["GRID"] = LLGridManager::getInstance()->getGridLabel();  	substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();  	substitution["SESSION_ID"] = gAgent.getSessionID(); diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 6187b8f1e2..6b6013a6ee 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -47,19 +47,19 @@ auto_resize="false"  follows="left|bottom"  name="login"  layout="topleft" -width="695" -min_width="695" +width="775" +min_width="775"  user_resize="false"  height="80">  <text  follows="left|bottom"  font="SansSerifSmall"  height="16" -name="first_name_text" +name="username_text"  top="20"  left="20"  width="150"> -First name: +Username:  </text>  <line_editor  follows="left|bottom" @@ -68,31 +68,11 @@ height="22"  label="First"  left_delta="0"  max_length="31" -name="first_name_edit" +name="username_edit"  select_on_focus="true" -tool_tip="[SECOND_LIFE] First Name" +tool_tip="[SECOND_LIFE] Username"  top_pad="0" -   width="135" /> -  <text -   follows="left|bottom" -   font="SansSerifSmall" -   height="16" -   left_pad="8" -   name="last_name_text" -   top="20" -   width="150"> -    Last name:   </text> -<line_editor -follows="left|bottom" -handle_edit_keys_directly="true" -height="22" -label="Last" -max_length="31" -name="last_name_edit" -select_on_focus="true" -tool_tip="[SECOND_LIFE] Last Name" -  top_pad="0" -  width="135" /> +width="150" />  <text  follows="left|bottom"  font="SansSerifSmall" @@ -152,18 +132,7 @@ name="MyHome"  label="<Type region name>"  name="Typeregionname"   value="" />  </combo_box> -<combo_box -allow_text_entry="true" -font="SansSerifSmall" -   follows="left|right|bottom" -   height="23" -layout="topleft" -top_pad="2" -name="server_combo" -width="135" -  visible="false" />  <button -  follows="left|bottom"    height="23"    image_unselected="PushButton_On"    image_selected="PushButton_On_Selected" @@ -174,6 +143,16 @@ width="135"    name="connect_btn"    top="35"    width="90" /> +<combo_box +follows="left|bottom" +allow_text_entry="true" +font="SansSerifSmall" +height="23" +name="server_combo" +left_pad="15" +width="200" +max_chars="255" +visible="false" />  </layout_panel>  <layout_panel  follows="right|bottom" diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 7b28a3b72c..9222882f5f 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 @@ -54,17 +57,69 @@ 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'};		/* Flawfinder: ignore */ -LLViewerLogin::LLViewerLogin() {} -LLViewerLogin::~LLViewerLogin() {} -void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const  +LLGridManager::~LLGridManager() +{ +} + +void LLGridManager::addGrid(LLSD& grid_data) +{ +} +LLGridManager::LLGridManager() +{	 +} + +void LLGridManager::getLoginURIs(std::vector<std::string>& 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<std::string, std::string> LLGridManager::getKnownGrids(bool favorite_only) +{ +	std::map<std::string, std::string> 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" @@ -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<LLCredential> agentCredential; +		LLPointer<LLCredential> 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/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp new file mode 100644 index 0000000000..a5554d55a5 --- /dev/null +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -0,0 +1,456 @@ +/**  + * @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 <vector> +#include <ios> +#include <llsdserialize.h> +#include <openssl/pem.h> +#include "llxorcipher.h" + +LLControlGroup gSavedSettings; +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; +		std::string mDerFormat; +		X509 *mX509TestCert; +		LLBasicCertificate* mTestCert; + +		sechandler_basic_test() +		{ +			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" +""; +			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"; +			 +			mTestCert = new LLBasicCertificate(mPemTestCert); +			 +			gSavedSettings.cleanup(); +			gSavedSettings.declareString("FirstName", "", "", FALSE); +			gSavedSettings.declareString("LastName", "", "", FALSE); +			mX509TestCert = 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); + +		} +		~sechandler_basic_test() +		{ +			LLFile::remove("test_password.dat"); +			LLFile::remove("sechandler_settings.tmp"); +			delete mTestCert; +			X509_free(mX509TestCert); +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<sechandler_basic_test> sechandler_basic_test_factory; +	typedef sechandler_basic_test_factory::object sechandler_basic_test_object; +	tut::sechandler_basic_test_factory tut_test("llsechandler_basic"); +	 +	// --------------------------------------------------------------------------------------- +	// Test functions  +	// --------------------------------------------------------------------------------------- +	// test cert data retrieval +	template<> template<> +	void sechandler_basic_test_object::test<1>() +	 +	{ + +		char buffer[4096]; + +		ensure_equals("Resultant pem is correct", +			   mPemTestCert, mTestCert->getPem()); +		std::vector<U8> binary_cert = mTestCert->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 = mTestCert->getLLSD(); +		std::ostringstream llsd_value; +		llsd_value << LLSDOStreamer<LLSDNotationFormatter>(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-30T20:58:00Z"); +		ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2011-12-01T07:59:00Z"); +		 +		ensure("x509 is equal", !X509_cmp(mX509TestCert, mTestCert->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<U8> binary_data(apr_base64_decode_len(protected_data.c_str())); +		apr_base64_decode_binary(&binary_data[0], protected_data.c_str()); + +		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES); +		cipher.decrypt(&binary_data[0], 16); +		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<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", +																		   "test_password.dat"); +		// 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"); + +		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"); +		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"); +		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<LLSecAPIBasicHandler> handler = new LLSecAPIBasicHandler("sechandler_settings.tmp", "test_password.dat"); +		 + +		LLSD my_id = LLSD::emptyMap(); +		LLSD my_authenticator = LLSD::emptyMap(); +		my_id["type"] = "test_type"; +		my_id["username"] = "testuser@lindenlab.com"; +		my_authenticator["type"] = "test_auth"; +		my_authenticator["creds"] = "12345"; + +		// test creation of credentials		 +		LLPointer<LLCredential> my_cred = handler->createCredential("my_grid", my_id, my_authenticator); + +		// test retrieval of credential components +		ensure_equals("basic credential creation: identifier", my_id, my_cred->getIdentifier()); +		ensure_equals("basic credential creation: authenticator", my_authenticator, my_cred->getAuthenticator()); +		ensure_equals("basic credential creation: grid", "my_grid", my_cred->getGrid()); +		 +		// test setting/overwriting of credential components +		my_id["first_name"] = "firstname"; +		my_id.erase("username"); +		my_authenticator.erase("creds"); +		my_authenticator["hash"] = "6563245"; +		 +		my_cred->setCredentialData(my_id, my_authenticator); +		ensure_equals("set credential data: identifier", my_id, my_cred->getIdentifier()); +		ensure_equals("set credential data: authenticator", my_authenticator, my_cred->getAuthenticator()); +		ensure_equals("set credential data: grid", "my_grid", my_cred->getGrid());		 +			 +		// test loading of a credential, that hasn't been saved, without +		// any legacy saved credential data +		LLPointer<LLCredential> my_new_cred = handler->loadCredential("my_grid"); +		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 + +		gSavedSettings.setString("FirstName", "myfirstname"); +		gSavedSettings.setString("LastName", "mylastname"); + +		my_new_cred = handler->loadCredential("my_legacy_grid"); +		ensure_equals("legacy credential with no password: type",  +					  (const std::string)my_new_cred->getIdentifier()["type"], "agent"); +		ensure_equals("legacy credential with no password: first_name",  +					  (const std::string)my_new_cred->getIdentifier()["first_name"], "myfirstname"); +		ensure_equals("legacy credential with no password: last_name", +					  (const std::string)my_new_cred->getIdentifier()["last_name"], "mylastname"); +		 +		ensure("legacy credential with no password: no authenticator", my_new_cred->getAuthenticator().isUndefined()); +		 +		// test loading of an unknown credential with legacy saved password and username + +		std::string hashed_password = "fSQcLG03eyIWJmkzfyYaKm81dSweLmsxeSAYKGE7fSQ=";		 +		int length = apr_base64_decode_len(hashed_password.c_str()); +		std::vector<char> decoded_password(length); +		apr_base64_decode(&decoded_password[0], hashed_password.c_str()); +		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 store +	template<> template<> +	void sechandler_basic_test_object::test<4>() +	{ +		// instantiate a cert store from a file +		llofstream certstorefile("mycertstore.pem", std::ios::out | std::ios::binary); + +		certstorefile << mPemTestCert; +		certstorefile.close(); +		// LLBasicCertificateStore test_store("mycertstore.pem"); +		// X509* test_cert = test_store[0]->getOpenSSLX509(); + +		// ensure("validate first element in store is expected cert", !X509_cmp(test_cert, mX509TestCert)); +	} +}; diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp new file mode 100644 index 0000000000..c7a6b2ad15 --- /dev/null +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -0,0 +1,446 @@ +/**  + * @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" + +LLControlGroup gSavedSettings; +const char *gSampleGridFile = "<llsd><map>" +"<key>grid1</key><map>" +"  <key>favorite</key><integer>1</integer>" +"  <key>helper_uri</key><string>https://helper1/helpers/</string>" +"  <key>label</key><string>mylabel</string>" +"  <key>login_page</key><string>loginpage</string>" +"  <key>login_uri</key><array><string>myloginuri</string></array>" +"  <key>name</key><string>grid1</string>" +"  <key>visible</key><integer>1</integer>" +"  <key>credential_type</key><string>agent</string>" +"  <key>grid_login_id</key><string>MyGrid</string>" +"</map>" +"<key>util.agni.lindenlab.com</key><map>" +"  <key>favorite</key><integer>1</integer>" +"  <key>helper_uri</key><string>https://helper1/helpers/</string>" +"  <key>label</key><string>mylabel</string>" +"  <key>login_page</key><string>loginpage</string>" +"  <key>login_uri</key><array><string>myloginuri</string></array>" +"  <key>name</key><string>util.agni.lindenlab.com</string>" +"</map></map></llsd>"; +// ------------------------------------------------------------------------------------------- +// TUT +// ------------------------------------------------------------------------------------------- +namespace tut +{ +  // Test wrapper declaration : wrapping nothing for the moment +  struct viewerNetworkTest +	{ +		viewerNetworkTest() +		{ +			gSavedSettings.cleanup(); +			gSavedSettings.cleanup(); +			gSavedSettings.declareString("CmdLineGridChoice", "", "", FALSE); +			gSavedSettings.declareString("CmdLineHelperURI", "", "", FALSE); +			gSavedSettings.declareString("LoginPage", "", "", FALSE); +			gSavedSettings.declareString("CurrentGrid", "", "", FALSE); +			gSavedSettings.declareLLSD("CmdLineLoginURI", LLSD(), "", FALSE); +		} +		~viewerNetworkTest() +		{ +			LLFile::remove("grid_test.xml"); +		} +	}; +	 +	// Tut templating thingamagic: test group, object and test instance +	typedef test_group<viewerNetworkTest> 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("grid_test.xml"); +		// validate that some of the defaults are available. +		std::map<std::string, std::string> 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); +#else // LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("Known grids is a string-string map of size 18", known_grids.size(), 2); +#endif // LL_RELEASE_FOR_DOWNLOAD + +		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"); +		 +		LLSD grid = manager.getGridInfo("util.agni.lindenlab.com"); +		ensure("Grid info for agni is a map", grid.isMap()); +		ensure_equals("name is correct for agni",  +					  grid[GRID_NAME_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 not 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 manager("grid_test.xml"); +		std::map<std::string, std::string> known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("adding a grid via a grid file increases known grid size",  +					  known_grids.size(), 19); +#else +		ensure_equals("adding a grid via a grid file increases known grid size",  +					  known_grids.size(), 3); +#endif +		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")); +	 +		// assure Agni doesn't get overwritten +		LLSD grid = manager.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_NAME_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 not 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 = manager.getGridInfo("grid1"); +		ensure_equals("grid file grid name is set", +					  grid[GRID_NAME_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>() +	{	 +		LLSD loginURI = std::string("https://my.login.uri/cgi-bin/login.cgi"); +		gSavedSettings.setLLSD("CmdLineLoginURI", loginURI); +		LLGridManager manager("grid_test.xml"); +		 +		// with single login uri specified. +		std::map<std::string, std::string> known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("adding a command line grid increases known grid size",  +					  known_grids.size(), 19); +#else +		ensure_equals("adding a command line grid increases known grid size",  +					  known_grids.size(), 3); +#endif +		ensure_equals("Command line grid is added to the list of grids",  +					  known_grids["my.login.uri"], std::string("my.login.uri")); +		LLSD grid = manager.getGridInfo("my.login.uri"); +		ensure_equals("Command line grid name is set", +					  grid[GRID_NAME_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 +		gSavedSettings.setString("CmdLineGridChoice", "mycustomgridchoice"); +		manager = LLGridManager("grid_test.xml"); +		known_grids = manager.getKnownGrids(); +#ifndef LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("adding a command line grid with custom name increases known grid size",  +					  known_grids.size(), 19); +#else +		ensure_equals("adding a command line grid with custom name inceases known grid size",  +					  known_grids.size(), 3); +#endif +		ensure_equals("Custom Command line grid is added to the list of grids",  +					  known_grids["mycustomgridchoice"], std::string("mycustomgridchoice")); +		grid = manager.getGridInfo("mycustomgridchoice"); +		ensure_equals("Custom Command line grid name is set", +					  grid[GRID_NAME_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 +		gSavedSettings.setString("CmdLineHelperURI", "myhelperuri"); +		manager = LLGridManager("grid_test.xml"); +		grid = manager.getGridInfo("mycustomgridchoice");		 +		ensure_equals("Validate command line helper uri",  +					  grid[GRID_HELPER_URI_VALUE].asString(), std::string("myhelperuri"));		 +		 +		// add a login page +		gSavedSettings.setString("LoginPage", "myloginpage"); +		manager = LLGridManager("grid_test.xml"); +		grid = manager.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_NAME_VALUE] = "myaddedgrid"; + +		loginURI.append(std::string("https://my.login.uri/cgi-bin/login.cgi")); +		gSavedSettings.setLLSD("CmdLineLoginURI", loginURI); +		LLGridManager manager("grid_test.xml"); +		manager.addGrid(grid); +		manager.setGridChoice("util.agni.lindenlab.com"); +#ifndef LL_RELEASE_FOR_DOWNLOAD		 +		ensure_equals("getGridLabel", manager.getGridLabel(), std::string("Agni")); +#else // LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("getGridLabel", manager.getGridLabel(), std::string("Secondlife.com"));		 +#endif // LL_RELEASE_FOR_DOWNLOAD +		ensure_equals("getGridName", manager.getGridName(),  +					  std::string("util.agni.lindenlab.com")); +		ensure_equals("getHelperURI", manager.getHelperURI(),  +					  std::string("https://secondlife.com/helpers/")); +		ensure_equals("getLoginPage", manager.getLoginPage(),  +					  std::string("http://secondlife.com/app/login/")); +		ensure_equals("getLoginPage2", manager.getLoginPage("util.agni.lindenlab.com"),  +					  std::string("http://secondlife.com/app/login/")); +		ensure("Is Agni a production grid", manager.isInProductionGrid());		 +		std::vector<std::string> uris; +		manager.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")); +		manager.setGridChoice("myaddedgrid"); +		ensure_equals("getGridLabel", manager.getGridLabel(), std::string("myaddedgrid"));		 +		ensure("Is myaddedgrid a production grid", !manager.isInProductionGrid()); +		 +		manager.setFavorite(); +		grid = manager.getGridInfo("myaddedgrid"); +		ensure("setting favorite", grid.has(GRID_IS_FAVORITE_VALUE)); +	} +	 +	// name based grid population +	template<> template<> +	void viewerNetworkTestObject::test<5>() +	{ +		LLGridManager manager("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		// adding a grid with simply a name will populate the values. +		grid[GRID_NAME_VALUE] = "myaddedgrid"; +		manager.addGrid(grid); +		grid = manager.getGridInfo("myaddedgrid"); +		 +		ensure_equals("name based grid has name value",  +					  grid[GRID_NAME_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 manager("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		grid[GRID_NAME_VALUE] = std::string("mynewgridname"); +		manager.addGrid(grid); +		manager.saveFavorites(); +		ensure("Grid file exists after saving",  +			   LLFile::isfile("grid_test.xml")); +		manager = LLGridManager("grid_test.xml"); +		// should not be there +		std::map<std::string, std::string> known_grids = manager.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 +		manager.addGrid(grid); +		manager.setGridChoice("mynewgridname"); +		manager.setFavorite(); +		manager.saveFavorites(); +		ensure("Grid file exists after saving",  +			   LLFile::isfile("grid_test.xml")); +		manager = LLGridManager("grid_test.xml"); +		// should not be there +		known_grids = manager.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 manager("grid_test.xml"); +		LLSD grid = LLSD::emptyMap(); +		grid[GRID_NAME_VALUE] = std::string("mynewgridname"); +		manager.addGrid(grid); +		manager.saveFavorites(); +		// validate we didn't lose existing favorites +		manager = LLGridManager("grid_test.xml"); +		std::map<std::string, std::string> known_grids = manager.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 +		manager.addGrid(grid); +		manager.setGridChoice("mynewgridname"); +		manager.setFavorite(); +		manager.saveFavorites(); +		known_grids = manager.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 = manager.getKnownGrids(); +		ensure("New grid wasn't added to persisted list after being marked a favorite", +			   known_grids.find(std::string("mynewgridname")) != +			   known_grids.end()); +	} +} diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index f5bda71846..7723c3ca8f 100644 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -122,29 +122,34 @@ private:  	LLSD mAuthResponse, mValidAuthResponse;  }; -void LLLogin::Impl::connect(const std::string& uri, const LLSD& credentials) +void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)  { +    LL_DEBUGS("LLLogin") << " connect with  uri '" << uri << "', login_params " << login_params << LL_ENDL; +	      // Launch a coroutine with our login_() method. Run the coroutine until      // its first wait; at that point, return here.      std::string coroname =           LLCoros::instance().launch("LLLogin::Impl::login_", -                                   boost::bind(&Impl::login_, this, _1, uri, credentials)); +                                   boost::bind(&Impl::login_, this, _1, uri, login_params));  } -void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credentials) +void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD login_params)  { -	LLSD printable_credentials = credentials; -	if(printable_credentials.has("params")  -		&& printable_credentials["params"].has("passwd"))  +	try  	{ -		printable_credentials["params"]["passwd"] = "*******"; -	} +	LLSD printable_params = login_params; +	//if(printable_params.has("params")  +	//	&& printable_params["params"].has("passwd"))  +	//{ +	//	printable_params["params"]["passwd"] = "*******"; +	//}      LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self) -                        << " with uri '" << uri << "', credentials " << printable_credentials << LL_ENDL; +                        << " with uri '" << uri << "', parameters " << printable_params << LL_ENDL;  	// Arriving in SRVRequest state      LLEventStream replyPump("reply", true);      // Should be an array of one or more uri strings. +      LLSD rewrittenURIs;      {          LLEventTimeout filter(replyPump); @@ -155,9 +160,9 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential          // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.  		F32 seconds_to_timeout = 5.0f; -		if(credentials.has("cfg_srv_timeout")) +		if(login_params.has("cfg_srv_timeout"))  		{ -			seconds_to_timeout = credentials["cfg_srv_timeout"].asReal(); +			seconds_to_timeout = login_params["cfg_srv_timeout"].asReal();  		}          // If the SRV request times out (e.g. EXT-3934), simulate response: an @@ -167,9 +172,9 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential  		filter.eventAfter(seconds_to_timeout, fakeResponse);  		std::string srv_pump_name = "LLAres"; -		if(credentials.has("cfg_srv_pump")) +		if(login_params.has("cfg_srv_pump"))  		{ -			srv_pump_name = credentials["cfg_srv_pump"].asString(); +			srv_pump_name = login_params["cfg_srv_pump"].asString();  		}  		// Make request @@ -190,7 +195,7 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential               urend(rewrittenURIs.endArray());           urit != urend; ++urit)      { -        LLSD request(credentials); +        LLSD request(login_params);          request["reply"] = replyPump.getName();          request["uri"] = *urit;          std::string status; @@ -289,6 +294,10 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential  	error_response["reason"] = mAuthResponse["status"];  	error_response["message"] = mAuthResponse["error"];  	sendProgressEvent("offline", "fail.login", error_response); +	} +	catch (...) { +		llerrs << "login exception caught" << llendl;  +	}  }  void LLLogin::Impl::disconnect() | 
