diff --git a/iphone/Maps/Platform/IPhoneDownload.mm b/iphone/Maps/Platform/IPhoneDownload.mm index 3227da6d9c..289182b11c 100644 --- a/iphone/Maps/Platform/IPhoneDownload.mm +++ b/iphone/Maps/Platform/IPhoneDownload.mm @@ -11,6 +11,8 @@ #include #include +#import + #if !defined(IFT_ETHER) #define IFT_ETHER 0x6 /* Ethernet CSMACD */ #endif @@ -18,8 +20,15 @@ #define TIMEOUT_IN_SECONDS 15.0 #define MAX_AUTOMATIC_RETRIES 3 -NSString * GetEncryptedMac() +string GetDeviceUid() { + NSString * uid = [[UIDevice currentDevice] uniqueIdentifier]; + return [uid UTF8String]; +} + +string GetMacAddress() +{ + string result; // get wifi mac addr ifaddrs * addresses = NULL; if (getifaddrs(&addresses) == 0 && addresses != NULL) @@ -32,19 +41,29 @@ NSString * GetEncryptedMac() { const struct sockaddr_dl * dlAddr = (const struct sockaddr_dl *) currentAddr->ifa_addr; const char * base = &dlAddr->sdl_data[dlAddr->sdl_nlen]; - // generate sha2 hash for mac address - string const hash = sha2::digest224(base, dlAddr->sdl_alen, false); - // and use base64 encoding - return [NSString stringWithUTF8String: base64::encode(hash).c_str()]; + result.assign(base, dlAddr->sdl_alen); + break; } currentAddr = currentAddr->ifa_next; } while (currentAddr->ifa_next); freeifaddrs(addresses); } - return nil; + return result; } +string GetUniqueHashedId() +{ + // generate sha2 hash for mac address + string const hash = sha2::digest256(GetMacAddress() + GetDeviceUid(), false); + // xor it + size_t const offset = hash.size() / 4; + string xoredHash; + for (size_t i = 0; i < offset; ++i) + xoredHash.push_back(hash[i] ^ hash[i + offset] ^ hash[i + offset * 2] ^ hash[i + offset * 3]); + // and use base64 encoding + return base64::encode(xoredHash); +} @implementation IPhoneDownload @@ -93,9 +112,9 @@ NSString * GetEncryptedMac() [val release]; } - NSString * macStr = GetEncryptedMac(); - if (macStr) - [request addValue:macStr forHTTPHeaderField:@"User-Agent"]; + // send unique id in HTTP user agent header + static string const uid = GetUniqueHashedId(); + [request addValue:[NSString stringWithUTF8String: uid.c_str()] forHTTPHeaderField:@"User-Agent"]; return request; } diff --git a/platform/qt_download.cpp b/platform/qt_download.cpp index 9cca18126c..aa31260c9d 100644 --- a/platform/qt_download.cpp +++ b/platform/qt_download.cpp @@ -16,8 +16,21 @@ // How many times we try to automatically reconnect in the case of network errors #define MAX_AUTOMATIC_RETRIES 2 -/// @return mac address of active interface without colons or empty string if not found -/// @note mac is converted to decimal from hex and slightly crypted +#ifdef OMIM_OS_WINDOWS + #define LOGIN_VAR "USERNAME" +#else + #define LOGIN_VAR "USER" +#endif +/// @return login name for active user and local machine hostname +static QString UserLoginAndHostname() +{ + char const * login = getenv(LOGIN_VAR); + QString result(login ? login : ""); + result += QHostInfo::localHostName(); + return result; +} + +/// @return mac address of active interface or empty string if not found static QString MacAddress() { QList interfaces = QNetworkInterface::allInterfaces(); @@ -27,11 +40,8 @@ static QString MacAddress() QString hwAddr = iface.hardwareAddress(); if (!iface.addressEntries().empty() && (iface.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning - | QNetworkInterface::CanBroadcast | QNetworkInterface::CanMulticast)) - == iface.flags() - && hwAddr.size() == 17) // mac length with semicolons + | QNetworkInterface::CanBroadcast | QNetworkInterface::CanMulticast)) == iface.flags()) { - hwAddr.remove(':'); return hwAddr; } } @@ -62,10 +72,17 @@ static QString UniqueClientId() if (result.size() == 0) result = QString("------------"); } + // add salt - login user name and local hostname + result += UserLoginAndHostname(); // calculate one-way hash QByteArray const original = QByteArray::fromHex(result.toLocal8Bit()); - string const hash = sha2::digest224(original.constData(), original.size(), false); - return base64::encode(hash).c_str(); + string const hash = sha2::digest256(original.constData(), original.size(), false); + // xor hash + size_t const offset = hash.size() / 4; + string xoredHash; + for (size_t i = 0; i < offset; ++i) + xoredHash.push_back(hash[i] ^ hash[i + offset] ^ hash[i + offset * 2] ^ hash[i + offset * 3]); + return base64::encode(xoredHash).c_str(); } static QString UserAgent()