4#include <winpr/wtypes.h>
5#include <winpr/string.h>
8#include <winpr/crypto.h>
11const char* sam_entries[] = {
12 "test1:::1910bd9285a6b8c9344d9f5cc74e0878:::",
13 "test2:::1bfc28ca2a4c218b032f4a0309b31f20:::",
14 "test1:domain::eab3412c36d6bbb1e3f6eaaf2775696e:::"
24const test_case_t hashes[] = { { .pwd =
"xxxxxx",
25 .LmHash = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
27 .NtHash = { 0x19, 0x10, 0xbd, 0x92, 0x85, 0xa6, 0xb8, 0xc9, 0x34,
28 0x4d, 0x9f, 0x5c, 0xc7, 0x4e, 0x08, 0x78 } },
29 { .pwd =
"aaaaaabbbbbb",
30 .LmHash = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
32 .NtHash = { 0x1b, 0xfc, 0x28, 0xca, 0x2a, 0x4c, 0x21, 0x8b, 0x03,
33 0x2f, 0x4a, 0x03, 0x09, 0xb3, 0x1f, 0x20 } },
35 .LmHash = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
37 .NtHash = { 0xea, 0xb3, 0x41, 0x2c, 0x36, 0xd6, 0xbb, 0xb1, 0xe3,
38 0xf6, 0xea, 0xaf, 0x27, 0x75, 0x69, 0x6e } } };
40static BOOL testHashA(
const WINPR_SAM_ENTRY* entry,
const char* pwd)
44 for (
size_t x = 0; x < ARRAYSIZE(hashes); x++)
46 const test_case_t* cur = &hashes[x];
47 if (strcmp(cur->pwd, pwd) != 0)
50 if (memcmp(entry->LmHash, cur->LmHash,
sizeof(entry->LmHash)) != 0)
52 return (memcmp(entry->NtHash, cur->NtHash,
sizeof(entry->NtHash)) == 0);
57static BOOL testHashW(
const WINPR_SAM_ENTRY* entry,
const WCHAR* pwd)
61 char* pwdA = ConvertWCharToUtf8Alloc(pwd,
nullptr);
64 const BOOL rc = testHashA(entry, pwdA);
69static BOOL testA(WINPR_SAM* sam,
const char* name,
const char* domain,
const char* pwd,
72 BOOL rc = !expectSuccess;
79 dlen = strlen(domain);
81 WINPR_SAM_ENTRY* entry = SamLookupUserA(sam, name, nlen, domain, dlen);
85 if (entry->UserLength != nlen)
87 if (entry->DomainLength != dlen)
92 if (strncmp(name, entry->User, nlen + 1) != 0)
98 if (strncmp(domain, entry->Domain, dlen + 1) != 0)
102 rc = testHashA(entry, pwd);
107 SamFreeEntry(sam, entry);
111static BOOL testW(WINPR_SAM* sam,
const WCHAR* name,
const WCHAR* domain,
const WCHAR* pwd,
114 BOOL rc = !expectSuccess;
117 nlen = _wcslen(name) *
sizeof(WCHAR);
121 dlen = _wcslen(domain) *
sizeof(WCHAR);
123 WINPR_SAM_ENTRY* entry = SamLookupUserW(sam, name, nlen, domain, dlen);
127 if (entry->UserLength != nlen)
129 if (entry->DomainLength != dlen)
134 if (_wcsncmp(name, (
const WCHAR*)entry->User, nlen /
sizeof(WCHAR) + 1) != 0)
140 if (_wcsncmp(domain, (
const WCHAR*)entry->Domain, dlen /
sizeof(WCHAR) + 1) != 0)
144 rc = testHashW(entry, pwd);
149 SamFreeEntry(sam, entry);
153static BOOL test(WINPR_SAM* sam,
const char* name,
const char* domain,
const char* pwd,
156 if (!testA(sam, name, domain, pwd, expectSuccess))
159 WCHAR* nameW =
nullptr;
160 WCHAR* domainW =
nullptr;
161 WCHAR* pwdW =
nullptr;
163 nameW = ConvertUtf8ToWCharAlloc(name,
nullptr);
165 domainW = ConvertUtf8ToWCharAlloc(domain,
nullptr);
167 pwdW = ConvertUtf8ToWCharAlloc(pwd,
nullptr);
169 const BOOL rc = testW(sam, nameW, domainW, pwdW, expectSuccess);
177WINPR_ATTR_MALLOC(free, 1)
178static
char* prepare(
void)
180 char tpath[MAX_PATH] = WINPR_C_ARRAY_INIT;
183 if (winpr_RAND(&nr,
sizeof(nr)) < 0)
185 (void)snprintf(tpath,
sizeof(tpath),
"sam-test-%016" PRIxz, nr);
186 char* tmp = GetKnownSubPath(KNOWN_PATH_TEMP, tpath);
190 FILE* fp = fopen(tmp,
"w");
197 for (
size_t x = 0; x < ARRAYSIZE(sam_entries); x++)
199 const char* entry = sam_entries[x];
200 (void)fprintf(fp,
"%s\r\n", entry);
207int TestSAM(WINPR_ATTR_UNUSED
int argc, WINPR_ATTR_UNUSED
char* argv[])
211 char* tmp = prepare();
215 WINPR_SAM* sam = SamOpen(tmp, TRUE);
219 if (!test(sam,
"test1",
nullptr,
"xxxxxx", TRUE))
221 if (!test(sam,
"test2",
nullptr,
"aaaaaabbbbbb", TRUE))
223 if (!test(sam,
"test1",
"domain",
"pppppppp", TRUE))
225 if (!test(sam,
"test1",
"foobar",
"xxxxxx", FALSE))
227 if (!test(sam,
"test3",
nullptr,
"xxxxxx", FALSE))
229 if (!test(sam,
"test1",
nullptr,
"xxxxxxe", FALSE))