aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llstartup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llstartup.cpp')
-rw-r--r--linden/indra/newview/llstartup.cpp242
1 files changed, 43 insertions, 199 deletions
diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp
index 4028cad..e29dc5a 100644
--- a/linden/indra/newview/llstartup.cpp
+++ b/linden/indra/newview/llstartup.cpp
@@ -76,7 +76,6 @@
76#include "llstring.h" 76#include "llstring.h"
77#include "lluserrelations.h" 77#include "lluserrelations.h"
78#include "llvfs.h" 78#include "llvfs.h"
79#include "llxorcipher.h" // saved password, MAC address
80#include "message.h" 79#include "message.h"
81#include "v3math.h" 80#include "v3math.h"
82 81
@@ -262,7 +261,6 @@ bool LLStartUp::sLoginFailed = false;
262 261
263void login_show(); 262void login_show();
264void login_callback(S32 option, void* userdata); 263void login_callback(S32 option, void* userdata);
265bool is_hex_string(U8* str, S32 len);
266void show_first_run_dialog(); 264void show_first_run_dialog();
267bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); 265bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
268void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); 266void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
@@ -750,12 +748,13 @@ bool idle_startup()
750#endif 748#endif
751 gSavedSettings.setBOOL("AutoLogin", TRUE); 749 gSavedSettings.setBOOL("AutoLogin", TRUE);
752 } 750 }
753 else if (gSavedSettings.getBOOL("AutoLogin")) 751 else if (gSavedSettings.getBOOL("AutoLogin") && gHippoGridManager)
754 { 752 {
755 firstname = gSavedSettings.getString("FirstName"); 753 // at this point, getCurrentGrid is the last logged in grid. Should we create a new entry for this? -- MC
756 lastname = gSavedSettings.getString("LastName"); 754 firstname = gHippoGridManager->getCurrentGrid()->getFirstName();
757 password = LLStartUp::loadPasswordFromDisk(); 755 lastname = gHippoGridManager->getCurrentGrid()->getLastName();
758 gSavedSettings.setBOOL("RememberPassword", TRUE); 756 password = gHippoGridManager->getCurrentGrid()->getPassword();
757 gSavedSettings.setBOOL("RememberPassword", TRUE); // why do we do this, anyway? -- MC
759 758
760#ifdef USE_VIEWER_AUTH 759#ifdef USE_VIEWER_AUTH
761 show_connect_box = true; 760 show_connect_box = true;
@@ -766,9 +765,7 @@ bool idle_startup()
766 else 765 else
767 { 766 {
768 // if not automatically logging in, display login dialog 767 // if not automatically logging in, display login dialog
769 firstname = gSavedSettings.getString("FirstName"); 768 // name and password are now handled in STATE_LOGIN_SHOW when the login screen's shown -- MC
770 lastname = gSavedSettings.getString("LastName");
771 password = LLStartUp::loadPasswordFromDisk();
772 show_connect_box = true; 769 show_connect_box = true;
773 } 770 }
774 771
@@ -826,17 +823,19 @@ bool idle_startup()
826 823
827 // connect dialog is already shown, so fill in the names associated with the grid 824 // connect dialog is already shown, so fill in the names associated with the grid
828 // note how we always remember avatar names, but don't necessarily have to 825 // note how we always remember avatar names, but don't necessarily have to
829 // icky how usernames get bolted on here as a kind of hack -- MC 826 // icky how all this gets bolted on here as a kind of hack -- MC
830 if (gHippoGridManager) 827 if (gHippoGridManager)
831 { 828 {
832 firstname = gHippoGridManager->getCurrentGrid()->getFirstName(); 829 firstname = gHippoGridManager->getCurrentGrid()->getFirstName();
833 lastname = gHippoGridManager->getCurrentGrid()->getLastName(); 830 lastname = gHippoGridManager->getCurrentGrid()->getLastName();
834 // RememberPassword toggles this being saved 831 // RememberPassword toggles this being saved
835 password = gHippoGridManager->getCurrentGrid()->getAvatarPassword(); 832 password = gHippoGridManager->getCurrentGrid()->getPassword();
836 833
834 // empty in case we used logout
837 if (gHippoGridManager->getCurrentGrid()->isUsernameCompat()) 835 if (gHippoGridManager->getCurrentGrid()->isUsernameCompat())
838 { 836 {
839 if (lastname == "resident" || lastname == "Resident") 837 if ((lastname == "resident" || lastname == "Resident") ||
838 (firstname.empty() && lastname.empty()))
840 { 839 {
841 LLPanelLogin::setFields(firstname, password); 840 LLPanelLogin::setFields(firstname, password);
842 } 841 }
@@ -998,8 +997,8 @@ bool idle_startup()
998 997
999 if (!firstname.empty() && !lastname.empty()) 998 if (!firstname.empty() && !lastname.empty())
1000 { 999 {
1001 gSavedSettings.setString("FirstName", firstname); 1000 gHippoGridManager->getCurrentGrid()->setFirstName(firstname);
1002 gSavedSettings.setString("LastName", lastname); 1001 gHippoGridManager->getCurrentGrid()->setLastName(lastname);
1003 1002
1004 //LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << " " << password << LL_ENDL; 1003 //LL_INFOS("AppInit") << "Attempting login as: " << firstname << " " << lastname << " " << password << LL_ENDL;
1005 gDebugInfo["LoginName"] = firstname + " " + lastname; 1004 gDebugInfo["LoginName"] = firstname + " " + lastname;
@@ -1162,7 +1161,9 @@ bool idle_startup()
1162 // color init must be after saved settings loaded 1161 // color init must be after saved settings loaded
1163 init_colors(); 1162 init_colors();
1164 1163
1165 if (gSavedSettings.getBOOL("VivoxLicenseAccepted") || gHippoGridManager->getConnectedGrid()->isSecondLife()) 1164 if (!gSavedSettings.getBOOL("EnableVoiceChat") ||
1165 (gSavedSettings.getBOOL("EnableVoiceChat") && gSavedSettings.getBOOL("VivoxLicenseAccepted")) ||
1166 !gHippoGridManager->getConnectedGrid()->isSecondLife())
1166 { 1167 {
1167 // skipping over STATE_LOGIN_VOICE_LICENSE since we don't need it 1168 // skipping over STATE_LOGIN_VOICE_LICENSE since we don't need it
1168 // skipping over STATE_UPDATE_CHECK because that just waits for input 1169 // skipping over STATE_UPDATE_CHECK because that just waits for input
@@ -1306,6 +1307,21 @@ bool idle_startup()
1306 } 1307 }
1307 } 1308 }
1308 1309
1310 // We hash a temporary password for login auth. The actual stored password
1311 // is in the grid manager, and is XORed with the mac address -- MC
1312 std::string hashed_password("");
1313 if (password.length() == 32)
1314 {
1315 hashed_password = password;
1316 }
1317 else if (!password.empty())
1318 {
1319 LLMD5 pass((unsigned char *)password.c_str());
1320 char munged_password[MD5HEX_STR_SIZE];
1321 pass.hex_digest(munged_password);
1322 hashed_password = munged_password;
1323 }
1324
1309 // TODO if statement here to use web_login_key 1325 // TODO if statement here to use web_login_key
1310 if(web_login_key.isNull()){ 1326 if(web_login_key.isNull()){
1311 sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1); 1327 sAuthUriNum = llclamp(sAuthUriNum, 0, (S32)sAuthUris.size()-1);
@@ -1314,7 +1330,7 @@ bool idle_startup()
1314 auth_method, 1330 auth_method,
1315 firstname, 1331 firstname,
1316 lastname, 1332 lastname,
1317 password, 1333 hashed_password,
1318 //web_login_key, 1334 //web_login_key,
1319 start.str(), 1335 start.str(),
1320 gSkipOptionalUpdate, 1336 gSkipOptionalUpdate,
@@ -1573,10 +1589,8 @@ bool idle_startup()
1573 1589
1574 if(successful_login) 1590 if(successful_login)
1575 { 1591 {
1576 { 1592 std::string current_grid = gHippoGridManager->getConnectedGrid()->getGridNick();
1577 std::string current_grid = gHippoGridManager->getConnectedGrid()->getGridNick(); 1593 gSavedSettings.setString("LastConnectedGrid", current_grid);
1578 gSavedSettings.setString("LastConnectedGrid", current_grid);
1579 }
1580 1594
1581 std::string text; 1595 std::string text;
1582 text = LLUserAuth::getInstance()->getResponse("udp_blacklist"); 1596 text = LLUserAuth::getInstance()->getResponse("udp_blacklist");
@@ -1608,19 +1622,23 @@ bool idle_startup()
1608 } 1622 }
1609 text = LLUserAuth::getInstance()->getResponse("last_name"); 1623 text = LLUserAuth::getInstance()->getResponse("last_name");
1610 if(!text.empty()) lastname.assign(text); 1624 if(!text.empty()) lastname.assign(text);
1611 gSavedSettings.setString("FirstName", firstname); 1625
1612 gSavedSettings.setString("LastName", lastname); 1626 gHippoGridManager->getConnectedGrid()->setFirstName(firstname);
1627 gHippoGridManager->getConnectedGrid()->setLastName(lastname);
1613 1628
1614 if (gSavedSettings.getBOOL("RememberPassword")) 1629 if (gSavedSettings.getBOOL("RememberPassword"))
1615 { 1630 {
1616 // Successful login means the password is valid, so save it. 1631 // Successful login means the password is valid, so save it.
1617 LLStartUp::savePasswordToDisk(password); 1632 // formerly LLStartUp::savePasswordToDisk(password);
1633 // this needs to happen after gMACAddress is set -- MC
1634 gHippoGridManager->getConnectedGrid()->setPassword(password);
1618 } 1635 }
1619 else 1636 else
1620 { 1637 {
1621 // Don't leave password from previous session sitting around 1638 // Don't leave password from previous session sitting around
1622 // during this login session. 1639 // during this login session.
1623 LLStartUp::deletePasswordFromDisk(); 1640 // formerly LLStartUp::deletePasswordFromDisk(); -- MC
1641 gHippoGridManager->getConnectedGrid()->setPassword("");
1624 } 1642 }
1625 1643
1626 // this is their actual ability to access content 1644 // this is their actual ability to access content
@@ -3084,180 +3102,6 @@ void login_callback(S32 option, void *userdata)
3084} 3102}
3085 3103
3086 3104
3087// static
3088std::string LLStartUp::loadPasswordFromDisk()
3089{
3090 // Only load password if we also intend to save it (otherwise the user
3091 // wonders what we're doing behind his back). JC
3092 BOOL remember_password = gSavedSettings.getBOOL("RememberPassword");
3093 if (!remember_password)
3094 {
3095 return std::string("");
3096 }
3097
3098 std::string hashed_password("");
3099
3100 // Look for legacy "marker" password from settings.ini
3101 hashed_password = gSavedSettings.getString("Marker");
3102 if (!hashed_password.empty())
3103 {
3104 // Stomp the Marker entry.
3105 gSavedSettings.setString("Marker", "");
3106
3107 // Return that password.
3108 return hashed_password;
3109 }
3110
3111 // UUID is 16 bytes, written into ASCII is 32 characters
3112 // without trailing \0
3113 const S32 HASHED_LENGTH = 32;
3114
3115 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
3116 "password.dat");
3117 LLFILE* fp = LLFile::fopen(filepath, "rb"); /* Flawfinder: ignore */
3118 if (!fp)
3119 {
3120#if LL_DARWIN
3121 UInt32 passwordLength;
3122 char *passwordData;
3123 OSStatus stat = SecKeychainFindGenericPassword(NULL, 10, "Imprudence", 0, NULL, &passwordLength, (void**)&passwordData, NULL);
3124 if (stat == noErr)
3125 {
3126 if (passwordLength == HASHED_LENGTH)
3127 hashed_password.assign(passwordData, HASHED_LENGTH);
3128 SecKeychainItemFreeContent(NULL, passwordData);
3129 }
3130#endif
3131 return hashed_password;
3132 }
3133
3134 U8 buffer[HASHED_LENGTH+1];
3135
3136 if (1 != fread(buffer, HASHED_LENGTH, 1, fp))
3137 {
3138 return hashed_password;
3139 }
3140
3141 fclose(fp);
3142
3143 // Decipher with MAC address
3144 LLXORCipher cipher(gMACAddress, 6);
3145 cipher.decrypt(buffer, HASHED_LENGTH);
3146
3147 buffer[HASHED_LENGTH] = '\0';
3148
3149 // Check to see if the mac address generated a bad hashed
3150 // password. It should be a hex-string or else the mac adress has
3151 // changed. This is a security feature to make sure that if you
3152 // get someone's password.dat file, you cannot hack their account.
3153 if(is_hex_string(buffer, HASHED_LENGTH))
3154 {
3155 hashed_password.assign((char*)buffer);
3156 }
3157#if LL_DARWIN
3158 // we're migrating to the keychain
3159 LLFile::remove(filepath);
3160#endif
3161
3162 return hashed_password;
3163}
3164
3165
3166// static
3167void LLStartUp::savePasswordToDisk(const std::string& hashed_password)
3168{
3169#if LL_DARWIN
3170 SecKeychainItemRef keychainItem;
3171 OSStatus status = SecKeychainFindGenericPassword(NULL, 10, "Imprudence", 0, NULL, NULL, NULL, &keychainItem);
3172 if (status == noErr)
3173 {
3174 SecKeychainItemModifyAttributesAndData(keychainItem, NULL, hashed_password.length(), hashed_password.c_str());
3175 CFRelease(keychainItem);
3176 }
3177 else
3178 {
3179 SecKeychainAddGenericPassword(NULL, 10, "Imprudence", 0, NULL, hashed_password.length(), hashed_password.c_str(), NULL);
3180 }
3181#else
3182 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
3183 "password.dat");
3184 LLFILE* fp = LLFile::fopen(filepath, "wb"); /* Flawfinder: ignore */
3185 if (!fp)
3186 {
3187 return;
3188 }
3189
3190 // Encipher with MAC address
3191 const S32 HASHED_LENGTH = 32;
3192 U8 buffer[HASHED_LENGTH+1];
3193
3194 LLStringUtil::copy((char*)buffer, hashed_password.c_str(), HASHED_LENGTH+1);
3195
3196 LLXORCipher cipher(gMACAddress, 6);
3197 cipher.encrypt(buffer, HASHED_LENGTH);
3198
3199 if (fwrite(buffer, HASHED_LENGTH, 1, fp) != 1)
3200 {
3201 LL_WARNS("AppInit") << "Short write" << LL_ENDL;
3202 }
3203
3204 fclose(fp);
3205#endif
3206}
3207
3208
3209// static
3210void LLStartUp::deletePasswordFromDisk()
3211{
3212#if LL_DARWIN
3213 SecKeychainItemRef keychainItem;
3214 OSStatus status = SecKeychainFindGenericPassword(NULL, 10, "Imprudence", 0, NULL, NULL, NULL, &keychainItem);
3215 if (status == noErr)
3216 {
3217 SecKeychainItemDelete(keychainItem);
3218 CFRelease(keychainItem);
3219 }
3220#endif
3221 std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
3222 "password.dat");
3223 LLFile::remove(filepath);
3224}
3225
3226
3227bool is_hex_string(U8* str, S32 len)
3228{
3229 bool rv = true;
3230 U8* c = str;
3231 while(rv && len--)
3232 {
3233 switch(*c)
3234 {
3235 case '0':
3236 case '1':
3237 case '2':
3238 case '3':
3239 case '4':
3240 case '5':
3241 case '6':
3242 case '7':
3243 case '8':
3244 case '9':
3245 case 'a':
3246 case 'b':
3247 case 'c':
3248 case 'd':
3249 case 'e':
3250 case 'f':
3251 ++c;
3252 break;
3253 default:
3254 rv = false;
3255 break;
3256 }
3257 }
3258 return rv;
3259}
3260
3261void show_first_run_dialog() 3105void show_first_run_dialog()
3262{ 3106{
3263 LLNotifications::instance().add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); 3107 LLNotifications::instance().add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);