Cleaned up SAM file parser.
authorakallabeth <akallabeth@posteo.net>
Fri, 16 Apr 2021 13:30:54 +0000 (15:30 +0200)
committerakallabeth <akallabeth@users.noreply.github.com>
Tue, 25 May 2021 13:30:50 +0000 (15:30 +0200)
(cherry picked from commit b500800104d3e07f2c00d3c6bc9a78f24193577e)

winpr/libwinpr/utils/sam.c

index b4af5b3..5c0cfe9 100644 (file)
@@ -52,6 +52,34 @@ struct winpr_sam
        BOOL readOnly;
 };
 
+static WINPR_SAM_ENTRY* SamEntryFromDataA(LPCSTR User, DWORD UserLength, LPCSTR Domain,
+                                          DWORD DomainLength)
+{
+       WINPR_SAM_ENTRY* entry = calloc(1, sizeof(WINPR_SAM_ENTRY));
+       if (!entry)
+               return NULL;
+       entry->User = _strdup(User);
+       entry->UserLength = UserLength;
+       entry->Domain = _strdup(Domain);
+       entry->DomainLength = DomainLength;
+       return entry;
+}
+
+static BOOL SamAreEntriesEqual(const WINPR_SAM_ENTRY* a, const WINPR_SAM_ENTRY* b)
+{
+       if (!a || !b)
+               return FALSE;
+       if (a->UserLength != b->UserLength)
+               return FALSE;
+       if (a->DomainLength != b->DomainLength)
+               return FALSE;
+       if (strncmp(a->User, b->User, a->UserLength) != 0)
+               return FALSE;
+       if (strncmp(a->Domain, b->Domain, a->DomainLength) != 0)
+               return FALSE;
+       return TRUE;
+}
+
 WINPR_SAM* SamOpen(const char* filename, BOOL readOnly)
 {
        FILE* fp = NULL;
@@ -72,7 +100,7 @@ WINPR_SAM* SamOpen(const char* filename, BOOL readOnly)
 
        if (fp)
        {
-               sam = (WINPR_SAM*)malloc(sizeof(WINPR_SAM));
+               sam = (WINPR_SAM*)calloc(1, sizeof(WINPR_SAM));
 
                if (!sam)
                {
@@ -108,7 +136,7 @@ static BOOL SamLookupStart(WINPR_SAM* sam)
                return FALSE;
 
        sam->context = NULL;
-       sam->buffer = (char*)malloc(fileSize + 2);
+       sam->buffer = (char*)calloc(fileSize + 2, 1);
 
        if (!sam->buffer)
                return FALSE;
@@ -141,9 +169,9 @@ static void SamLookupFinish(WINPR_SAM* sam)
        sam->line = NULL;
 }
 
-static void HexStrToBin(char* str, BYTE* bin, int length)
+static void HexStrToBin(const char* str, BYTE* bin, size_t length)
 {
-       int i;
+       size_t i;
        CharUpperBuffA(str, length * 2);
 
        for (i = 0; i < length; i++)
@@ -276,17 +304,14 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L
 {
        size_t length;
        BOOL found = FALSE;
-       WINPR_SAM_ENTRY* entry;
-       entry = (WINPR_SAM_ENTRY*)calloc(1, sizeof(WINPR_SAM_ENTRY));
+       WINPR_SAM_ENTRY* search = SamEntryFromDataA(User, UserLength, Domain, DomainLength);
+       WINPR_SAM_ENTRY* entry = (WINPR_SAM_ENTRY*)calloc(1, sizeof(WINPR_SAM_ENTRY));
 
-       if (!entry)
-               return NULL;
+       if (!entry || !search)
+               goto fail;
 
        if (!SamLookupStart(sam))
-       {
-               free(entry);
-               return NULL;
-       }
+               goto fail;
 
        while (sam->line != NULL)
        {
@@ -301,7 +326,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L
                                        goto out_fail;
                                }
 
-                               if (strcmp(User, entry->User) == 0)
+                               if (SamAreEntriesEqual(entry, search))
                                {
                                        found = 1;
                                        break;
@@ -315,10 +340,12 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L
 
 out_fail:
        SamLookupFinish(sam);
+fail:
+       SamFreeEntry(sam, search);
 
        if (!found)
        {
-               free(entry);
+               SamFreeEntry(sam, entry);
                return NULL;
        }
 
@@ -328,115 +355,23 @@ out_fail:
 WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain,
                                 UINT32 DomainLength)
 {
-       size_t length;
-       BOOL Found = FALSE;
-       BOOL UserMatch;
-       BOOL DomainMatch;
-       LPWSTR EntryUser = NULL;
-       UINT32 EntryUserLength;
-       LPWSTR EntryDomain = NULL;
-       UINT32 EntryDomainLength;
-       WINPR_SAM_ENTRY* entry;
-
-       if (!(entry = (WINPR_SAM_ENTRY*)calloc(1, sizeof(WINPR_SAM_ENTRY))))
-               return NULL;
-
-       if (!SamLookupStart(sam))
-       {
-               free(entry);
-               return NULL;
-       }
-
-       while (sam->line != NULL)
-       {
-               length = strlen(sam->line);
-
-               if (length > 1)
-               {
-                       if (sam->line[0] != '#')
-                       {
-                               DomainMatch = 0;
-                               UserMatch = 0;
-
-                               if (!SamReadEntry(sam, entry))
-                                       goto out_fail;
-
-                               if (DomainLength > 0)
-                               {
-                                       if (entry->DomainLength > 0)
-                                       {
-                                               EntryDomainLength = (UINT32)strlen(entry->Domain) * 2;
-                                               EntryDomain = (LPWSTR)malloc(EntryDomainLength + 2);
-
-                                               if (!EntryDomain)
-                                                       goto out_fail;
-
-                                               MultiByteToWideChar(CP_ACP, 0, entry->Domain, EntryDomainLength / 2,
-                                                                   (LPWSTR)EntryDomain, EntryDomainLength / 2);
-
-                                               if (DomainLength == EntryDomainLength)
-                                               {
-                                                       if (memcmp(Domain, EntryDomain, DomainLength) == 0)
-                                                       {
-                                                               DomainMatch = 1;
-                                                       }
-                                               }
-
-                                               free(EntryDomain);
-                                       }
-                                       else
-                                       {
-                                               DomainMatch = 0;
-                                       }
-                               }
-                               else
-                               {
-                                       DomainMatch = 1;
-                               }
-
-                               if (DomainMatch)
-                               {
-                                       EntryUserLength = (UINT32)strlen(entry->User) * 2;
-                                       EntryUser = (LPWSTR)malloc(EntryUserLength + 2);
-
-                                       if (!EntryUser)
-                                               goto out_fail;
-
-                                       MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2,
-                                                           (LPWSTR)EntryUser, EntryUserLength / 2);
-
-                                       if (UserLength == EntryUserLength)
-                                       {
-                                               if (memcmp(User, EntryUser, UserLength) == 0)
-                                               {
-                                                       UserMatch = 1;
-                                               }
-                                       }
-
-                                       free(EntryUser);
-
-                                       if (UserMatch)
-                                       {
-                                               Found = TRUE;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-
-               SamResetEntry(entry);
-               sam->line = strtok_s(NULL, "\n", &sam->context);
-       }
-
-out_fail:
-       SamLookupFinish(sam);
-
-       if (!Found)
-       {
-               free(entry);
-               return NULL;
-       }
-
+       int rc;
+       WINPR_SAM_ENTRY* entry = NULL;
+       char* utfUser = NULL;
+       char* utfDomain = NULL;
+       const size_t UserCharLength = UserLength / sizeof(WCHAR);
+       const size_t DomainCharLength = DomainLength / sizeof(WCHAR);
+
+       rc = ConvertFromUnicode(CP_UTF8, 0, User, UserCharLength, &utfUser, 0, NULL, NULL);
+       if ((rc < 0) || ((size_t)rc != UserCharLength))
+               goto fail;
+       rc = ConvertFromUnicode(CP_UTF8, 0, Domain, DomainCharLength, &utfDomain, 0, NULL, NULL);
+       if ((rc < 0) || ((size_t)rc != DomainCharLength))
+               goto fail;
+       entry = SamLookupUserA(sam, utfUser, UserCharLength, utfDomain, DomainCharLength);
+fail:
+       free(utfUser);
+       free(utfDomain);
        return entry;
 }