20 #include <winpr/config.h>
21 #include <winpr/path.h>
27 #include <winpr/wtypes.h>
28 #include <winpr/crt.h>
29 #include <winpr/sam.h>
30 #include <winpr/print.h>
31 #include <winpr/file.h>
35 #ifdef WINPR_HAVE_UNISTD_H
39 #define TAG WINPR_TAG("utils")
50 static WINPR_SAM_ENTRY* SamEntryFromDataA(LPCSTR User, DWORD UserLength, LPCSTR Domain,
53 WINPR_SAM_ENTRY* entry = calloc(1,
sizeof(WINPR_SAM_ENTRY));
56 if (User && (UserLength > 0))
57 entry->User = _strdup(User);
58 entry->UserLength = UserLength;
59 if (Domain && (DomainLength > 0))
60 entry->Domain = _strdup(Domain);
61 entry->DomainLength = DomainLength;
65 static BOOL SamAreEntriesEqual(
const WINPR_SAM_ENTRY* a,
const WINPR_SAM_ENTRY* b)
69 if (a->UserLength != b->UserLength)
71 if (a->DomainLength != b->DomainLength)
73 if (a->UserLength > 0)
75 if (!a->User || !b->User)
77 if (strncmp(a->User, b->User, a->UserLength) != 0)
80 if (a->DomainLength > 0)
82 if (!a->Domain || !b->Domain)
84 if (strncmp(a->Domain, b->Domain, a->DomainLength) != 0)
90 WINPR_SAM* SamOpen(
const char* filename, BOOL readOnly)
93 WINPR_SAM* sam = NULL;
94 char* allocatedFileName = NULL;
98 allocatedFileName = winpr_GetConfigFilePath(TRUE,
"SAM");
99 filename = allocatedFileName;
103 fp = winpr_fopen(filename,
"r");
106 fp = winpr_fopen(filename,
"r+");
109 fp = winpr_fopen(filename,
"w+");
111 free(allocatedFileName);
115 sam = (WINPR_SAM*)calloc(1,
sizeof(WINPR_SAM));
123 sam->readOnly = readOnly;
128 WLog_DBG(TAG,
"Could not open SAM file!");
135 static BOOL SamLookupStart(WINPR_SAM* sam)
140 if (!sam || !sam->fp)
143 if (_fseeki64(sam->fp, 0, SEEK_END) != 0)
145 fileSize = _ftelli64(sam->fp);
146 if (_fseeki64(sam->fp, 0, SEEK_SET) != 0)
153 sam->buffer = (
char*)calloc((
size_t)fileSize + 2, 1);
158 readSize = fread(sam->buffer, (
size_t)fileSize, 1, sam->fp);
162 if (!ferror(sam->fp))
163 readSize = (size_t)fileSize;
173 sam->buffer[fileSize] =
'\n';
174 sam->buffer[fileSize + 1] =
'\0';
175 sam->line = strtok_s(sam->buffer,
"\n", &sam->context);
179 static void SamLookupFinish(WINPR_SAM* sam)
186 static BOOL SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry)
189 size_t LmHashLength = 0;
190 size_t NtHashLength = 0;
194 if (!sam || !entry || !sam->line)
199 while ((cur = strchr(cur,
':')) != NULL)
209 p[1] = strchr(p[0],
':') + 1;
210 p[2] = strchr(p[1],
':') + 1;
211 p[3] = strchr(p[2],
':') + 1;
212 p[4] = strchr(p[3],
':') + 1;
213 LmHashLength = (p[3] - p[2] - 1);
214 NtHashLength = (p[4] - p[3] - 1);
216 if ((LmHashLength != 0) && (LmHashLength != 32))
219 if ((NtHashLength != 0) && (NtHashLength != 32))
222 entry->UserLength = (UINT32)(p[1] - p[0] - 1);
223 entry->User = (LPSTR)malloc(entry->UserLength + 1);
228 entry->User[entry->UserLength] =
'\0';
229 entry->DomainLength = (UINT32)(p[2] - p[1] - 1);
230 memcpy(entry->User, p[0], entry->UserLength);
232 if (entry->DomainLength > 0)
234 entry->Domain = (LPSTR)malloc(entry->DomainLength + 1);
243 memcpy(entry->Domain, p[1], entry->DomainLength);
244 entry->Domain[entry->DomainLength] =
'\0';
247 entry->Domain = NULL;
249 if (LmHashLength == 32)
250 winpr_HexStringToBinBuffer(p[2], LmHashLength, entry->LmHash,
sizeof(entry->LmHash));
252 if (NtHashLength == 32)
253 winpr_HexStringToBinBuffer(p[3], NtHashLength, (BYTE*)entry->NtHash,
sizeof(entry->NtHash));
258 void SamFreeEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry)
262 if (entry->UserLength > 0)
265 if (entry->DomainLength > 0)
272 void SamResetEntry(WINPR_SAM_ENTRY* entry)
277 if (entry->UserLength)
283 if (entry->DomainLength)
286 entry->Domain = NULL;
289 ZeroMemory(entry->LmHash,
sizeof(entry->LmHash));
290 ZeroMemory(entry->NtHash,
sizeof(entry->NtHash));
293 WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPCSTR User, UINT32 UserLength, LPCSTR Domain,
298 WINPR_SAM_ENTRY* search = SamEntryFromDataA(User, UserLength, Domain, DomainLength);
299 WINPR_SAM_ENTRY* entry = (WINPR_SAM_ENTRY*)calloc(1,
sizeof(WINPR_SAM_ENTRY));
301 if (!entry || !search)
304 if (!SamLookupStart(sam))
307 while (sam->line != NULL)
309 length = strlen(sam->line);
313 if (sam->line[0] !=
'#')
315 if (!SamReadEntry(sam, entry))
320 if (SamAreEntriesEqual(entry, search))
328 SamResetEntry(entry);
329 sam->line = strtok_s(NULL,
"\n", &sam->context);
333 SamLookupFinish(sam);
335 SamFreeEntry(sam, search);
339 SamFreeEntry(sam, entry);
346 WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPCWSTR User, UINT32 UserLength, LPCWSTR Domain,
349 WINPR_SAM_ENTRY* entry = NULL;
350 char* utfUser = NULL;
351 char* utfDomain = NULL;
352 size_t userCharLen = 0;
353 size_t domainCharLen = 0;
355 utfUser = ConvertWCharNToUtf8Alloc(User, UserLength /
sizeof(WCHAR), &userCharLen);
358 if (DomainLength > 0)
360 utfDomain = ConvertWCharNToUtf8Alloc(Domain, DomainLength /
sizeof(WCHAR), &domainCharLen);
364 entry = SamLookupUserA(sam, utfUser, (UINT32)userCharLen, utfDomain, (UINT32)domainCharLen);
371 void SamClose(WINPR_SAM* sam)
376 (void)fclose(sam->fp);