diff options
Diffstat (limited to 'linden/indra/newview/llstartup.cpp')
-rw-r--r-- | linden/indra/newview/llstartup.cpp | 242 |
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 | ||
263 | void login_show(); | 262 | void login_show(); |
264 | void login_callback(S32 option, void* userdata); | 263 | void login_callback(S32 option, void* userdata); |
265 | bool is_hex_string(U8* str, S32 len); | ||
266 | void show_first_run_dialog(); | 264 | void show_first_run_dialog(); |
267 | bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); | 265 | bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); |
268 | void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); | 266 | void 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 | ||
3088 | std::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 | ||
3167 | void 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 | ||
3210 | void 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 | |||
3227 | bool 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 | |||
3261 | void show_first_run_dialog() | 3105 | void 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); |