1 // Windows/SecurityUtils.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "SecurityUtils.h"
6 
7 namespace NWindows {
8 namespace NSecurity {
9 
10 /*
11 bool MyLookupAccountSid(LPCTSTR systemName, PSID sid,
12   CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse)
13 {
14   DWORD accountNameSize = 0, domainNameSize = 0;
15 
16   if (!::LookupAccountSid(systemName, sid,
17       accountName.GetBuffer(0), &accountNameSize,
18       domainName.GetBuffer(0), &domainNameSize, sidNameUse))
19   {
20     if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
21       return false;
22   }
23   bool result = BOOLToBool(::LookupAccountSid(systemName, sid,
24       accountName.GetBuffer(accountNameSize), &accountNameSize,
25       domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse));
26   accountName.ReleaseBuffer();
27   domainName.ReleaseBuffer();
28   return result;
29 }
30 */
31 
SetLsaString(LPWSTR src,PLSA_UNICODE_STRING dest)32 static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)
33 {
34   int len = (int)wcslen(src);
35   dest->Length = (USHORT)(len * sizeof(WCHAR));
36   dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));
37   dest->Buffer = src;
38 }
39 
40 /*
41 static void MyLookupSids(CPolicy &policy, PSID ps)
42 {
43   LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL;
44   LSA_TRANSLATED_NAME *names = NULL;
45   NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names);
46   int res = LsaNtStatusToWinError(nts);
47   LsaFreeMemory(referencedDomains);
48   LsaFreeMemory(names);
49 }
50 */
51 
52 #ifndef _UNICODE
53 typedef BOOL (WINAPI * LookupAccountNameWP)(
54     LPCWSTR lpSystemName,
55     LPCWSTR lpAccountName,
56     PSID Sid,
57     LPDWORD cbSid,
58     LPWSTR ReferencedDomainName,
59     LPDWORD cchReferencedDomainName,
60     PSID_NAME_USE peUse
61     );
62 #endif
63 
GetSid(LPWSTR accountName)64 static PSID GetSid(LPWSTR accountName)
65 {
66   #ifndef _UNICODE
67   HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll"));
68   if (hModule == NULL)
69     return NULL;
70   LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW");
71   if (lookupAccountNameW == NULL)
72     return NULL;
73   #endif
74 
75   DWORD sidLen = 0, domainLen = 0;
76   SID_NAME_USE sidNameUse;
77   if (!
78     #ifdef _UNICODE
79     ::LookupAccountNameW
80     #else
81     lookupAccountNameW
82     #endif
83     (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse))
84   {
85     if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
86     {
87       PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen);
88       LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR));
89       BOOL res =
90         #ifdef _UNICODE
91         ::LookupAccountNameW
92         #else
93         lookupAccountNameW
94         #endif
95         (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse);
96       ::HeapFree(GetProcessHeap(), 0, domainName);
97       if (res)
98         return pSid;
99     }
100   }
101   return NULL;
102 }
103 
104 #define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege"
105 
AddLockMemoryPrivilege()106 bool AddLockMemoryPrivilege()
107 {
108   CPolicy policy;
109   LSA_OBJECT_ATTRIBUTES attr;
110   attr.Length = sizeof(attr);
111   attr.RootDirectory = NULL;
112   attr.ObjectName  = NULL;
113   attr.Attributes = 0;
114   attr.SecurityDescriptor = NULL;
115   attr.SecurityQualityOfService  = NULL;
116   if (policy.Open(NULL, &attr,
117       // GENERIC_WRITE)
118       POLICY_ALL_ACCESS)
119       // STANDARD_RIGHTS_REQUIRED,
120       // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES)
121       != 0)
122     return false;
123   LSA_UNICODE_STRING userRights;
124   wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME;
125   SetLsaString(s, &userRights);
126   WCHAR userName[256 + 2];
127   DWORD size = 256;
128   if (!GetUserNameW(userName, &size))
129     return false;
130   PSID psid = GetSid(userName);
131   if (psid == NULL)
132     return false;
133   bool res = false;
134 
135   /*
136   PLSA_UNICODE_STRING userRightsArray;
137   ULONG countOfRights;
138   NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights);
139   if (status != 0)
140     return false;
141   bool finded = false;
142   for (ULONG i = 0; i < countOfRights; i++)
143   {
144     LSA_UNICODE_STRING &ur = userRightsArray[i];
145     if (ur.Length != s.Length() * sizeof(WCHAR))
146       continue;
147     if (wcsncmp(ur.Buffer, s, s.Length()) != 0)
148       continue;
149     finded = true;
150     res = true;
151     break;
152   }
153   if (!finded)
154   */
155   {
156     /*
157     LSA_ENUMERATION_INFORMATION *enums;
158     ULONG countReturned;
159     NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned);
160     if (status == 0)
161     {
162       for (ULONG i = 0; i < countReturned; i++)
163         MyLookupSids(policy, enums[i].Sid);
164       if (enums)
165         ::LsaFreeMemory(enums);
166       res = true;
167     }
168     */
169     NTSTATUS status = policy.AddAccountRights(psid, &userRights);
170     if (status == 0)
171       res = true;
172     // ULONG res = LsaNtStatusToWinError(status);
173   }
174   HeapFree(GetProcessHeap(), 0, psid);
175   return res;
176 }
177 
178 }}
179 
180