diff options
author | David Walter Seikel | 2012-03-11 04:31:18 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-03-11 04:31:18 +1000 |
commit | f2715ed85d43b7c7fa4f86e3c3b4118c4cd5ce4d (patch) | |
tree | 09b03f9c806b034090c5e9bafa96faeee0f936b0 /linden/indra/newview/hippogridmanager.cpp | |
parent | Just adding a TODO. (diff) | |
download | meta-impy-f2715ed85d43b7c7fa4f86e3c3b4118c4cd5ce4d.zip meta-impy-f2715ed85d43b7c7fa4f86e3c3b4118c4cd5ce4d.tar.gz meta-impy-f2715ed85d43b7c7fa4f86e3c3b4118c4cd5ce4d.tar.bz2 meta-impy-f2715ed85d43b7c7fa4f86e3c3b4118c4cd5ce4d.tar.xz |
Fix http://redmine.kokuaviewer.org/issues/1126 and as a bonus, now using blowfish to encrypt passwords.
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/hippogridmanager.cpp | 177 |
1 files changed, 131 insertions, 46 deletions
diff --git a/linden/indra/newview/hippogridmanager.cpp b/linden/indra/newview/hippogridmanager.cpp index 1dfb9ac..11b144e 100644 --- a/linden/indra/newview/hippogridmanager.cpp +++ b/linden/indra/newview/hippogridmanager.cpp | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "llviewernetwork.h" // gMacAddress | 49 | #include "llviewernetwork.h" // gMacAddress |
50 | #include "llweb.h" | 50 | #include "llweb.h" |
51 | #include "llxorcipher.h" // saved password, MAC address | 51 | #include "llxorcipher.h" // saved password, MAC address |
52 | #include "llblowfishcipher.h" | ||
52 | 53 | ||
53 | #include "hipporestrequest.h" | 54 | #include "hipporestrequest.h" |
54 | #include <boost/algorithm/string.hpp> | 55 | #include <boost/algorithm/string.hpp> |
@@ -87,6 +88,7 @@ HippoGridInfo::HippoGridInfo(const std::string& gridNick) : | |||
87 | mFirstName(LLStringUtil::null), | 88 | mFirstName(LLStringUtil::null), |
88 | mLastName(LLStringUtil::null), | 89 | mLastName(LLStringUtil::null), |
89 | mPasswordAvatar(LLStringUtil::null), | 90 | mPasswordAvatar(LLStringUtil::null), |
91 | mEncryptedPassword(LLStringUtil::null), | ||
90 | mXmlState(XML_VOID), | 92 | mXmlState(XML_VOID), |
91 | mVoiceConnector("SLVoice"), | 93 | mVoiceConnector("SLVoice"), |
92 | mRenderCompat(false), | 94 | mRenderCompat(false), |
@@ -423,12 +425,115 @@ void HippoGridInfo::formatFee(std::string &fee, S32 cost, bool showFree) const | |||
423 | } | 425 | } |
424 | } | 426 | } |
425 | 427 | ||
428 | const S32 HASHED_LENGTH = 32; | ||
429 | |||
430 | void HippoGridInfo::setEncryptedPassword(const std::string& encrypted_password) | ||
431 | { | ||
432 | int i; | ||
433 | LLBlowfishCipher cipher(gMACAddress, 6); | ||
434 | size_t encrypted_size = cipher.requiredEncryptionSpace(HASHED_LENGTH); | ||
435 | |||
436 | if (encrypted_password.empty()) | ||
437 | { | ||
438 | // Check if we have a password hash to encrypt. | ||
439 | if (mPasswordAvatar.empty()) | ||
440 | mEncryptedPassword = ""; | ||
441 | else | ||
442 | { | ||
443 | // In theory, this is used to convert old style Imprudence 1.4 beta 2 and earlier passwords. | ||
444 | // Encipher with MAC address | ||
445 | char out[HASHED_LENGTH * 2 + 1]; | ||
446 | |||
447 | /* indra/llmessage/llmail.cpp says "blowfish-not-supported-on-windows", but we shall see. | ||
448 | #if LL_WINDOWS | ||
449 | LLXORCipher cipherX(gMACAddress, 6); | ||
450 | cipherX.encrypt(mPasswordAvatar.c_str(), HASHED_LENGTH); | ||
451 | #else | ||
452 | */ | ||
453 | U8* encrypted = new U8[encrypted_size]; | ||
454 | U8* password = (U8 *) mPasswordAvatar.c_str(); | ||
455 | |||
456 | cipher.encrypt(password, HASHED_LENGTH, encrypted, HASHED_LENGTH); | ||
457 | for (i = 0; i < HASHED_LENGTH; i++) | ||
458 | { | ||
459 | sprintf(out + i * 2, "%02x", encrypted[i]); | ||
460 | } | ||
461 | out[HASHED_LENGTH * 2]='\0'; | ||
462 | mEncryptedPassword.assign(out); | ||
463 | } | ||
464 | |||
465 | return; | ||
466 | } | ||
467 | |||
468 | if (encrypted_password == mEncryptedPassword) | ||
469 | { | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | // Max "actual" password length is 16 characters. | ||
474 | // Hex digests are always 32 characters. | ||
475 | // Encrypted passwords stored as hex digits are 64 characters. | ||
476 | if (encrypted_password.length() == (HASHED_LENGTH * 2)) | ||
477 | { | ||
478 | // This is actually encrypted, as found in the grids file. | ||
479 | mEncryptedPassword.assign(encrypted_password); | ||
480 | } | ||
481 | else | ||
482 | { | ||
483 | // Should never happen, this is only called from the file reading bit. | ||
484 | llwarns << "Encrypted password corrupted." << llendl; | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | std::string hashed_password(""); | ||
489 | |||
490 | // Decrypt it for the password hash. | ||
491 | // Decipher with MAC address | ||
492 | U8 buffer[HASHED_LENGTH + 1]; | ||
493 | char in[HASHED_LENGTH * 2 + 1]; | ||
494 | |||
495 | LLStringUtil::copy(in, mEncryptedPassword.c_str(), HASHED_LENGTH * 2 + 1); | ||
496 | /* indra/llmessage/llmail.cpp says "blowfish-not-supported-on-windows", but we shall see. | ||
497 | #if LL_WINDOWS | ||
498 | for (i = 0; i < HASHED_LENGTH; i++) | ||
499 | { | ||
500 | sscanf(in + i * 2, "%2hhx", &buffer[i]); | ||
501 | } | ||
502 | // Note that an XOR "cipher" is a lousy one when the secret is repeated several times like it is here. | ||
503 | LLXORCipher cipher(gMACAddress, 6); | ||
504 | cipher.decrypt(buffer, HASHED_LENGTH); | ||
505 | #else | ||
506 | */ | ||
507 | U8* encrypted = new U8[encrypted_size]; | ||
508 | for (i = 0; i < HASHED_LENGTH; i++) | ||
509 | { | ||
510 | sscanf(in + i * 2, "%2hhx", &encrypted[i]); | ||
511 | } | ||
512 | // Not sure why, but this prints a warning saying it failed, even though it works. Which does not matter that much, we don't use the return value anyway. | ||
513 | cipher.decrypt(encrypted, HASHED_LENGTH, buffer, HASHED_LENGTH); | ||
514 | buffer[HASHED_LENGTH] = '\0'; | ||
515 | |||
516 | // Check to see if the mac address generated a bad hashed | ||
517 | // password. It should be a hex-string or else the mac adress has | ||
518 | // changed. This is a security feature to make sure that if you | ||
519 | // get someone's grid_info.xml file, you cannot hack their account. | ||
520 | // This is a lousy way to check. | ||
521 | if (is_hex_string(buffer, HASHED_LENGTH)) | ||
522 | { | ||
523 | hashed_password.assign((char*)buffer); | ||
524 | } | ||
525 | |||
526 | mPasswordAvatar.assign(hashed_password); | ||
527 | } | ||
426 | 528 | ||
427 | void HippoGridInfo::setPassword(const std::string& unhashed_password) | 529 | void HippoGridInfo::setPassword(const std::string& unhashed_password) |
428 | { | 530 | { |
531 | int i; | ||
532 | |||
429 | if (unhashed_password.empty()) | 533 | if (unhashed_password.empty()) |
430 | { | 534 | { |
431 | mPasswordAvatar = ""; | 535 | mPasswordAvatar = ""; |
536 | mEncryptedPassword = ""; | ||
432 | return; | 537 | return; |
433 | } | 538 | } |
434 | 539 | ||
@@ -454,59 +559,38 @@ void HippoGridInfo::setPassword(const std::string& unhashed_password) | |||
454 | hashed_password = munged_password; | 559 | hashed_password = munged_password; |
455 | } | 560 | } |
456 | 561 | ||
457 | // need to fix the bug in this | 562 | // Encrypt it for storing in the grids file. |
458 | /* | ||
459 | |||
460 | // Encipher with MAC address | 563 | // Encipher with MAC address |
461 | const S32 HASHED_LENGTH = 32; | 564 | char out[HASHED_LENGTH * 2 + 1]; |
462 | U8 buffer[HASHED_LENGTH+1]; | ||
463 | |||
464 | LLStringUtil::copy((char*)buffer, hashed_password.c_str(), HASHED_LENGTH+1); | ||
465 | 565 | ||
466 | LLXORCipher cipher(gMACAddress, 6); | 566 | /* indra/llmessage/llmail.cpp says "blowfish-not-supported-on-windows", but we shall see. |
467 | cipher.encrypt(buffer, HASHED_LENGTH); | 567 | #if LL_WINDOWS |
568 | LLXORCipher cipherX(gMACAddress, 6); | ||
569 | cipherX.encrypt(hashed_password.c_str(), HASHED_LENGTH); | ||
570 | #else | ||
571 | */ | ||
572 | LLBlowfishCipher cipher(gMACAddress, 6); | ||
573 | size_t encrypted_size = cipher.requiredEncryptionSpace(HASHED_LENGTH); | ||
574 | U8* encrypted = new U8[encrypted_size]; | ||
575 | U8* password = (U8 *) hashed_password.c_str(); | ||
468 | 576 | ||
469 | mPasswordAvatar.assign((char*)buffer); | 577 | cipher.encrypt(password, HASHED_LENGTH, encrypted, HASHED_LENGTH); |
470 | */ | 578 | for (i = 0; i < HASHED_LENGTH; i++) |
579 | { | ||
580 | sprintf(out + i * 2, "%02x", encrypted[i]); | ||
581 | } | ||
582 | out[HASHED_LENGTH * 2]='\0'; | ||
583 | mEncryptedPassword.assign(out); | ||
471 | mPasswordAvatar.assign(hashed_password); | 584 | mPasswordAvatar.assign(hashed_password); |
472 | } | 585 | } |
473 | 586 | ||
587 | std::string HippoGridInfo::getEncryptedPassword() const | ||
588 | { | ||
589 | return mEncryptedPassword; | ||
590 | } | ||
474 | 591 | ||
475 | std::string HippoGridInfo::getPassword() const | 592 | std::string HippoGridInfo::getPassword() const |
476 | { | 593 | { |
477 | // need to fix the bug in this | ||
478 | /* | ||
479 | if (mPasswordAvatar.empty() || mPasswordAvatar.length() == 32) | ||
480 | { | ||
481 | return mPasswordAvatar; | ||
482 | } | ||
483 | |||
484 | std::string hashed_password(""); | ||
485 | |||
486 | // UUID is 16 bytes, written into ASCII is 32 characters | ||
487 | // without trailing \0 | ||
488 | const S32 HASHED_LENGTH = 32; | ||
489 | U8 buffer[HASHED_LENGTH+1]; | ||
490 | |||
491 | LLStringUtil::copy((char*)buffer, mPasswordAvatar.c_str(), HASHED_LENGTH+1); | ||
492 | |||
493 | // Decipher with MAC address | ||
494 | LLXORCipher cipher(gMACAddress, 6); | ||
495 | cipher.decrypt(buffer, HASHED_LENGTH); | ||
496 | |||
497 | buffer[HASHED_LENGTH] = '\0'; | ||
498 | |||
499 | // Check to see if the mac address generated a bad hashed | ||
500 | // password. It should be a hex-string or else the mac adress has | ||
501 | // changed. This is a security feature to make sure that if you | ||
502 | // get someone's grid_info.xml file, you cannot hack their account. | ||
503 | if (is_hex_string(buffer, HASHED_LENGTH)) | ||
504 | { | ||
505 | hashed_password.assign((char*)buffer); | ||
506 | } | ||
507 | |||
508 | return hashed_password; | ||
509 | */ | ||
510 | return mPasswordAvatar; | 594 | return mPasswordAvatar; |
511 | } | 595 | } |
512 | 596 | ||
@@ -909,7 +993,9 @@ void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer) | |||
909 | if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]); | 993 | if (gridMap.has("render_compat")) grid->setRenderCompat(gridMap["render_compat"]); |
910 | if (gridMap.has("firstname")) grid->setFirstName(gridMap["firstname"]); | 994 | if (gridMap.has("firstname")) grid->setFirstName(gridMap["firstname"]); |
911 | if (gridMap.has("lastname")) grid->setLastName(gridMap["lastname"]); | 995 | if (gridMap.has("lastname")) grid->setLastName(gridMap["lastname"]); |
996 | // Reading this one coz there are some old files in the wild that have it, but not encryptedpassword. | ||
912 | if (gridMap.has("avatarpassword")) grid->setPassword(gridMap["avatarpassword"]); | 997 | if (gridMap.has("avatarpassword")) grid->setPassword(gridMap["avatarpassword"]); |
998 | if (gridMap.has("encryptedpassword")) grid->setEncryptedPassword(gridMap["encryptedpassword"]); | ||
913 | if (gridMap.has("username")) grid->setUsername(gridMap["username"]); | 999 | if (gridMap.has("username")) grid->setUsername(gridMap["username"]); |
914 | if (gridMap.has("username_compat")) grid->setUsernameCompat(gridMap["username_compat"]); | 1000 | if (gridMap.has("username_compat")) grid->setUsernameCompat(gridMap["username_compat"]); |
915 | if (newGrid) addGrid(grid); | 1001 | if (newGrid) addGrid(grid); |
@@ -945,8 +1031,7 @@ void HippoGridManager::saveFile() | |||
945 | gridInfo[i]["password"] = grid->getPasswordURL(); | 1031 | gridInfo[i]["password"] = grid->getPasswordURL(); |
946 | gridInfo[i]["firstname"] = grid->getFirstName(); | 1032 | gridInfo[i]["firstname"] = grid->getFirstName(); |
947 | gridInfo[i]["lastname"] = grid->getLastName(); | 1033 | gridInfo[i]["lastname"] = grid->getLastName(); |
948 | gridInfo[i]["avatarpassword"] = grid->getPassword(); | 1034 | gridInfo[i]["encryptedpassword"] = grid->getEncryptedPassword(); |
949 | |||
950 | gridInfo[i]["search"] = grid->getSearchURL(); | 1035 | gridInfo[i]["search"] = grid->getSearchURL(); |
951 | gridInfo[i]["render_compat"] = grid->isRenderCompat(); | 1036 | gridInfo[i]["render_compat"] = grid->isRenderCompat(); |
952 | 1037 | ||