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