Add new mechanism for getting a unique machine id.

master
karina 2010-05-26 23:46:42 -07:00
parent 5e353cbf86
commit cca5aa48ae
8 changed files with 380 additions and 18 deletions

View File

@ -272,6 +272,7 @@ set(viewer_SOURCE_FILES
lllogchat.cpp
llloginhandler.cpp
lllogininstance.cpp
llmachineid.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
@ -787,6 +788,7 @@ set(viewer_HEADER_FILES
lllogchat.h
llloginhandler.h
lllogininstance.h
llmachineid.h
llmanip.h
llmaniprotate.h
llmanipscale.h

View File

@ -195,6 +195,7 @@
// Include for security api initialization
#include "llsecapi.h"
#include "llmachineid.h"
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
@ -619,6 +620,7 @@ bool LLAppViewer::init()
// *NOTE:Mani - LLCurl::initClass is not thread safe.
// Called before threads are created.
LLCurl::initClass();
LLMachineID::init();
initThreads();
writeSystemInfo();

View File

@ -0,0 +1,267 @@
/**
* @file llmachineid.cpp
* @brief retrieves unique machine ids
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lluuid.h"
#include "llmachineid.h"
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
unsigned char static_unique_id[] = {0,0,0,0,0,0};
bool static has_static_unique_id = false;
// get an unique machine id.
// NOT THREAD SAFE - do before setting up threads.
// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot, Go figure??
S32 LLMachineID::init()
{
memset(static_unique_id,0,sizeof(static_unique_id));
size_t len = sizeof(static_unique_id);
S32 ret_code = 0;
#if LL_WINDOWS
# pragma comment(lib, "wbemuuid.lib")
// algorithm to detect BIOS serial number found at:
// http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx
// we can't use the MAC address since on Windows 7, the first returned MAC address changes with every reboot.
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hex << hres << LL_ENDL;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Failed to initialize security. Error code = 0x" << hex << hres << LL_ENDL;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << LL_ENDL;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Could not connect. Error code = 0x" << hex << hres << LL_ENDL;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hex << hres << LL_ENDL;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
LL_DEBUGS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << hex << hres << LL_ENDL;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
LL_DEBUGS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL;
// use characters in the returned Serial Number to create a byte array of size len
BSTR serialNumber ( vtProp.bstrVal);
unsigned int j = 0;
while( vtProp.bstrVal[j] != 0)
{
for (unsigned int i = 0; i < len; i++)
{
if (vtProp.bstrVal[j] == 0)
break;
static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]);
j++;
}
}
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
break;
}
// Cleanup
// ========
if (pSvc)
pSvc->Release();
if (pLoc)
pLoc->Release();
if (pEnumerator)
pEnumerator->Release();
CoUninitialize();
ret_code=0;
#else
ret_code = LLUUID::getNodeID(&static_unique_id);
#endif
has_static_unique_id = true;
return ret_code;
}
S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
{
if (has_static_unique_id)
{
memcpy ( unique_id, &static_unique_id, len);
LL_DEBUGS("AppInit") << "UniqueID: " << unique_id[0] << unique_id[1]<< unique_id[2] << unique_id[3] << unique_id[4] << unique_id [5] << LL_ENDL;
return 1;
}
return 0;
}

View File

@ -0,0 +1,56 @@
/**
* @file llmachineid.h
* @brief retrieves unique machine ids
*
* $LicenseInfo:firstyear=2010&license=viewergpl$
*
* Copyright (c) 2010, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLMACHINEID_H
#define LL_LLMACHINEID_H
class LLMachineID
{
public:
LLMachineID();
virtual ~LLMachineID();
static S32 getUniqueID(unsigned char *unique_id, size_t len);
static S32 init();
protected:
private:
};
#endif // LL_LLMACHINEID_H

View File

@ -52,6 +52,7 @@ LLS * By copying, modifying or distributing this software, you acknowledge
#include <iostream>
#include <iomanip>
#include <time.h>
#include "llmachineid.h"
@ -1195,9 +1196,9 @@ void LLSecAPIBasicHandler::_readProtectedData()
U8 buffer[BUFFER_READ_SIZE];
U8 decrypted_buffer[BUFFER_READ_SIZE];
int decrypted_length;
unsigned char MACAddress[MAC_ADDRESS_BYTES];
LLUUID::getNodeID(MACAddress);
LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher(unique_id, sizeof(unique_id));
// read in the salt and key
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
@ -1281,9 +1282,9 @@ void LLSecAPIBasicHandler::_writeProtectedData()
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit(&ctx, EVP_rc4(), salt, NULL);
unsigned char MACAddress[MAC_ADDRESS_BYTES];
LLUUID::getNodeID(MACAddress);
LLXORCipher cipher(MACAddress, MAC_ADDRESS_BYTES);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher(unique_id, sizeof(unique_id));
cipher.encrypt(salt, STORE_SALT_SIZE);
protected_data_stream.write((const char *)salt, STORE_SALT_SIZE);
@ -1501,9 +1502,9 @@ std::string LLSecAPIBasicHandler::_legacyLoadPassword()
}
// Decipher with MAC address
unsigned char MACAddress[MAC_ADDRESS_BYTES];
LLUUID::getNodeID(MACAddress);
LLXORCipher cipher(MACAddress, 6);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher(unique_id, sizeof(unique_id));
cipher.decrypt(&buffer[0], buffer.size());
return std::string((const char*)&buffer[0], buffer.size());

View File

@ -514,7 +514,9 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status,
"Despite our best efforts, something unexpected has gone wrong. \n"
" \n"
"Please check secondlife.com/status \n"
"to see if there is a known problem with the service.";
"to see if there is a known problem with the service.\n"
"If you continue to experience problems,"
"Please check your network and firewall setup.\n";
mStatusURI = "http://secondlife.com/status/";
}
@ -550,7 +552,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code)
"Often this means that your computer\'s clock is set incorrectly.\n"
"Please go to Control Panels and make sure the time and date\n"
"are set correctly.\n"
"\n"
"Also check that your network and firewall are setup correctly.\n"
"If you continue to receive this error, please go\n"
"to the Support section of the SecondLife.com web site\n"
"and report the problem.";

View File

@ -6182,6 +6182,37 @@ Avatar '[NAME]' entered appearance mode.
Avatar '[NAME]' left appearance mode.
</notification>
<notification
icon="alertmodal.tga"
name="NoConnect"
type="alertmodal">
We're having trouble connecting using [PROTOCOL] [HOSTID].
Please check your network and firewall setup.
<form name="form">
<button
default="true"
index="0"
name="OK"
text="OK"/>
</form>
</notification>
<notification
icon="alertmodal.tga"
name="NoVoiceConnect"
type="alertmodal">
We're having trouble connecting your voiceserver using [HOSTID].
Voice communications will not be available.
Please check your network and firewall setup.
<form name="form">
<button
default="true"
index="0"
name="OK"
text="OK"/>
</form>
</notification>
<notification
icon="notifytip.tga"
name="AvatarRezLeftNotification"

View File

@ -54,7 +54,7 @@
#include <openssl/asn1.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include "../llmachineid.h"
#define ensure_throws(str, exc_type, cert, func, ...) \
try \
@ -129,6 +129,7 @@ namespace tut
sechandler_basic_test()
{
LLMachineID::init();
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
@ -376,8 +377,6 @@ namespace tut
void sechandler_basic_test_object::test<2>()
{
unsigned char MACAddress[MAC_ADDRESS_BYTES];
LLUUID::getNodeID(MACAddress);
std::string protected_data = "sUSh3wj77NG9oAMyt3XIhaej3KLZhLZWFZvI6rIGmwUUOmmelrRg0NI9rkOj8ZDpTPxpwToaBT5u"
"GQhakdaGLJznr9bHr4/6HIC1bouKj4n2rs4TL6j2WSjto114QdlNfLsE8cbbE+ghww58g8SeyLQO"
@ -390,7 +389,9 @@ namespace tut
LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
cipher.decrypt(&binary_data[0], 16);
LLXORCipher cipher2(MACAddress, MAC_ADDRESS_BYTES);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher2(unique_id, sizeof(unique_id));
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());
@ -571,11 +572,11 @@ namespace tut
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);
unsigned char unique_id[MAC_ADDRESS_BYTES];
LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
LLXORCipher cipher2(unique_id, sizeof(unique_id));
cipher2.encrypt((U8*)&decoded_password[0], length);
llofstream password_file("test_password.dat", std::ofstream::binary);
password_file.write(&decoded_password[0], length);