From 5e5b53666c852fd4f29a893cef3f0aeb53690a1e Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Wed, 21 Jan 2009 10:39:46 -0800 Subject: [PATCH] rpcrt4: Use pseudo-random numbers to generate UUIDs rather than using the (old, deprecated) MAC-address-and-time generation algorithm. --- dlls/rpcrt4/Makefile.in | 2 +- dlls/rpcrt4/rpcrt4_main.c | 152 ++++---------------------------------- dlls/rpcrt4/tests/rpc.c | 2 - 3 files changed, 16 insertions(+), 140 deletions(-) diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index 14ee4a3f8f6..b44bfb0f56a 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -5,7 +5,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = rpcrt4.dll IMPORTLIB = rpcrt4 -IMPORTS = uuid iphlpapi advapi32 kernel32 ntdll +IMPORTS = uuid advapi32 kernel32 ntdll DELAYIMPORTS = secur32 user32 C_SRCS = \ diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c index 1a6b61dd90c..f1a966f3649 100644 --- a/dlls/rpcrt4/rpcrt4_main.c +++ b/dlls/rpcrt4/rpcrt4_main.c @@ -43,8 +43,7 @@ #include "winuser.h" #include "winnt.h" #include "winternl.h" -#include "iptypes.h" -#include "iphlpapi.h" +#include "ntsecapi.h" #include "wine/unicode.h" #include "rpc.h" @@ -60,15 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc); static UUID uuid_nil; -static CRITICAL_SECTION uuid_cs; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &uuid_cs, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") } -}; -static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; - static CRITICAL_SECTION threaddata_cs; static CRITICAL_SECTION_DEBUG threaddata_cs_debug = { @@ -280,61 +270,6 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) return RPC_S_OK; } -/* Number of 100ns ticks per clock tick. To be safe, assume that the clock - resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ -#define TICKS_PER_CLOCK_TICK 1000 -#define SECSPERDAY 86400 -#define TICKSPERSEC 10000000 -/* UUID system time starts at October 15, 1582 */ -#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY) -#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC) - -static void RPC_UuidGetSystemTime(ULONGLONG *time) -{ - FILETIME ft; - - GetSystemTimeAsFileTime(&ft); - - *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; - *time += TICKS_15_OCT_1582_TO_1601; -} - -/* Assume that a hardware address is at least 6 bytes long */ -#define ADDRESS_BYTES_NEEDED 6 - -static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) -{ - int i; - DWORD status = RPC_S_OK; - - ULONG buflen = sizeof(IP_ADAPTER_INFO); - PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen); - - if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) { - HeapFree(GetProcessHeap(), 0, adapter); - adapter = HeapAlloc(GetProcessHeap(), 0, buflen); - } - - if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) { - for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { - address[i] = adapter->Address[i]; - } - } - /* We can't get a hardware address, just use random numbers. - Set the multicast bit to prevent conflicts with real cards. */ - else { - for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { - address[i] = rand() & 0xff; - } - - address[0] |= 0x01; - status = RPC_S_UUID_LOCAL_ONLY; - } - - HeapFree(GetProcessHeap(), 0, adapter); - return status; -} - /************************************************************************* * UuidCreate [RPCRT4.@] * @@ -345,83 +280,26 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) * RPC_S_OK if successful. * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * - * FIXME: No compensation for changes across reloading - * this dll or across reboots (e.g. clock going - * backwards and swapped network cards). The RFC - * suggests using NVRAM for storing persistent - * values. + * NOTES + * + * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from + * Truly Random or Pseudo-Random Numbers) */ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) { - static int initialised, count; - - ULONGLONG time; - static ULONGLONG timelast; - static WORD sequence; - - static DWORD status; - static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH]; - - EnterCriticalSection(&uuid_cs); - - if (!initialised) { - RPC_UuidGetSystemTime(&timelast); - count = TICKS_PER_CLOCK_TICK; - - sequence = ((rand() & 0xff) << 8) + (rand() & 0xff); - sequence &= 0x1fff; - - status = RPC_UuidGetNodeAddress(address); - initialised = 1; - } - - /* Generate time element of the UUID. Account for going faster - than our clock as well as the clock going backwards. */ - while (1) { - RPC_UuidGetSystemTime(&time); - if (time > timelast) { - count = 0; - break; - } - if (time < timelast) { - sequence = (sequence + 1) & 0x1fff; - count = 0; - break; - } - if (count < TICKS_PER_CLOCK_TICK) { - count++; - break; - } - } - - timelast = time; - time += count; - - /* Pack the information into the UUID structure. */ - - Uuid->Data1 = (unsigned long)(time & 0xffffffff); - Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); - Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); - - /* This is a version 1 UUID */ - Uuid->Data3 |= (1 << 12); - - Uuid->Data4[0] = sequence & 0xff; - Uuid->Data4[1] = (sequence & 0x3f00) >> 8; - Uuid->Data4[1] |= 0x80; - - Uuid->Data4[2] = address[0]; - Uuid->Data4[3] = address[1]; - Uuid->Data4[4] = address[2]; - Uuid->Data4[5] = address[3]; - Uuid->Data4[6] = address[4]; - Uuid->Data4[7] = address[5]; - - LeaveCriticalSection(&uuid_cs); + RtlGenRandom(Uuid, sizeof(*Uuid)); + /* Clear the version bits and set the version (4) */ + Uuid->Data3 &= 0x0fff; + Uuid->Data3 |= (4 << 12); + /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as + * specified in RFC 4122, section 4.4. + */ + Uuid->Data4[0] &= 0x3f; + Uuid->Data4[0] |= 0x80; TRACE("%s\n", debugstr_guid(Uuid)); - return status; + return RPC_S_OK; } /************************************************************************* diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c index 9ac6d271cae..e50dcdc9f78 100644 --- a/dlls/rpcrt4/tests/rpc.c +++ b/dlls/rpcrt4/tests/rpc.c @@ -780,7 +780,6 @@ static void test_UuidCreate(void) UuidCreate(&guid); version = (guid.Data3 & 0xf000) >> 12; - todo_wine ok(version == 4 || broken(version == 1), "unexpected version %d\n", version); if (version == 4) @@ -826,7 +825,6 @@ static void test_UuidCreate(void) * present. Just check that Data4[0]'s most significant bits are * set as expected. */ - todo_wine ok((guid.Data4[0] & 0xc0) == 0x80, "unexpected value in Data4[0]: %02x\n", guid.Data4[0] & 0xc0); }