xref: /reactos/dll/win32/lsasrv/privileges.c (revision 03422451)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         Local Security Authority (LSA) Server
4  * FILE:            reactos/dll/win32/lsasrv/privileges.c
5  * PURPOSE:         Privilege lookup functions
6  *
7  * PROGRAMMERS:     Eric Kohl <eric.kohl@reactos.org>
8  */
9 
10 #include "lsasrv.h"
11 #include "resources.h"
12 
13 typedef struct
14 {
15     LUID Luid;
16     LPCWSTR Name;
17     INT DisplayNameId;
18 } PRIVILEGE_DATA;
19 
20 typedef struct
21 {
22     ULONG Flag;
23     LPCWSTR Name;
24 } RIGHT_DATA;
25 
26 
27 /* GLOBALS *****************************************************************/
28 
29 static const PRIVILEGE_DATA WellKnownPrivileges[] =
30 {
31     {{SE_CREATE_TOKEN_PRIVILEGE, 0}, SE_CREATE_TOKEN_NAME, IDS_CREATE_TOKEN_PRIVILEGE},
32     {{SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0}, SE_ASSIGNPRIMARYTOKEN_NAME, IDS_ASSIGNPRIMARYTOKEN_PRIVILEGE},
33     {{SE_LOCK_MEMORY_PRIVILEGE, 0}, SE_LOCK_MEMORY_NAME, IDS_LOCK_MEMORY_PRIVILEGE},
34     {{SE_INCREASE_QUOTA_PRIVILEGE, 0}, SE_INCREASE_QUOTA_NAME, IDS_INCREASE_QUOTA_PRIVILEGE},
35     {{SE_MACHINE_ACCOUNT_PRIVILEGE, 0}, SE_MACHINE_ACCOUNT_NAME, IDS_MACHINE_ACCOUNT_PRIVILEGE},
36     {{SE_TCB_PRIVILEGE, 0}, SE_TCB_NAME, IDS_TCB_PRIVILEGE},
37     {{SE_SECURITY_PRIVILEGE, 0}, SE_SECURITY_NAME, IDS_SECURITY_PRIVILEGE},
38     {{SE_TAKE_OWNERSHIP_PRIVILEGE, 0}, SE_TAKE_OWNERSHIP_NAME, IDS_TAKE_OWNERSHIP_PRIVILEGE},
39     {{SE_LOAD_DRIVER_PRIVILEGE, 0}, SE_LOAD_DRIVER_NAME, IDS_LOAD_DRIVER_PRIVILEGE},
40     {{SE_SYSTEM_PROFILE_PRIVILEGE, 0}, SE_SYSTEM_PROFILE_NAME, IDS_SYSTEM_PROFILE_PRIVILEGE},
41     {{SE_SYSTEMTIME_PRIVILEGE, 0}, SE_SYSTEMTIME_NAME, IDS_SYSTEMTIME_PRIVILEGE},
42     {{SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0}, SE_PROF_SINGLE_PROCESS_NAME, IDS_PROF_SINGLE_PROCESS_PRIVILEGE},
43     {{SE_INC_BASE_PRIORITY_PRIVILEGE, 0}, SE_INC_BASE_PRIORITY_NAME, IDS_INC_BASE_PRIORITY_PRIVILEGE},
44     {{SE_CREATE_PAGEFILE_PRIVILEGE, 0}, SE_CREATE_PAGEFILE_NAME, IDS_CREATE_PAGEFILE_PRIVILEGE},
45     {{SE_CREATE_PERMANENT_PRIVILEGE, 0}, SE_CREATE_PERMANENT_NAME, IDS_CREATE_PERMANENT_PRIVILEGE},
46     {{SE_BACKUP_PRIVILEGE, 0}, SE_BACKUP_NAME, IDS_BACKUP_PRIVILEGE},
47     {{SE_RESTORE_PRIVILEGE, 0}, SE_RESTORE_NAME, IDS_RESTORE_PRIVILEGE},
48     {{SE_SHUTDOWN_PRIVILEGE, 0}, SE_SHUTDOWN_NAME, IDS_SHUTDOWN_PRIVILEGE},
49     {{SE_DEBUG_PRIVILEGE, 0}, SE_DEBUG_NAME, IDS_DEBUG_PRIVILEGE},
50     {{SE_AUDIT_PRIVILEGE, 0}, SE_AUDIT_NAME, IDS_AUDIT_PRIVILEGE},
51     {{SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0}, SE_SYSTEM_ENVIRONMENT_NAME, IDS_SYSTEM_ENVIRONMENT_PRIVILEGE},
52     {{SE_CHANGE_NOTIFY_PRIVILEGE, 0}, SE_CHANGE_NOTIFY_NAME, IDS_CHANGE_NOTIFY_PRIVILEGE},
53     {{SE_REMOTE_SHUTDOWN_PRIVILEGE, 0}, SE_REMOTE_SHUTDOWN_NAME, IDS_REMOTE_SHUTDOWN_PRIVILEGE},
54     {{SE_UNDOCK_PRIVILEGE, 0}, SE_UNDOCK_NAME, IDS_UNDOCK_PRIVILEGE},
55     {{SE_SYNC_AGENT_PRIVILEGE, 0}, SE_SYNC_AGENT_NAME, IDS_SYNC_AGENT_PRIVILEGE},
56     {{SE_ENABLE_DELEGATION_PRIVILEGE, 0}, SE_ENABLE_DELEGATION_NAME, IDS_ENABLE_DELEGATION_PRIVILEGE},
57     {{SE_MANAGE_VOLUME_PRIVILEGE, 0}, SE_MANAGE_VOLUME_NAME, IDS_MANAGE_VOLUME_PRIVILEGE},
58     {{SE_IMPERSONATE_PRIVILEGE, 0}, SE_IMPERSONATE_NAME, IDS_IMPERSONATE_PRIVILEGE},
59     {{SE_CREATE_GLOBAL_PRIVILEGE, 0}, SE_CREATE_GLOBAL_NAME, IDS_CREATE_GLOBAL_PRIVILEGE}
60 };
61 
62 static const RIGHT_DATA WellKnownRights[] =
63 {
64     {SECURITY_ACCESS_INTERACTIVE_LOGON, SE_INTERACTIVE_LOGON_NAME},
65     {SECURITY_ACCESS_NETWORK_LOGON, SE_NETWORK_LOGON_NAME},
66     {SECURITY_ACCESS_BATCH_LOGON, SE_BATCH_LOGON_NAME},
67     {SECURITY_ACCESS_SERVICE_LOGON, SE_SERVICE_LOGON_NAME},
68     {SECURITY_ACCESS_DENY_INTERACTIVE_LOGON, SE_DENY_INTERACTIVE_LOGON_NAME},
69     {SECURITY_ACCESS_DENY_NETWORK_LOGON, SE_DENY_NETWORK_LOGON_NAME},
70     {SECURITY_ACCESS_DENY_BATCH_LOGON, SE_DENY_BATCH_LOGON_NAME},
71     {SECURITY_ACCESS_DENY_SERVICE_LOGON, SE_DENY_SERVICE_LOGON_NAME},
72     {SECURITY_ACCESS_REMOTE_INTERACTIVE_LOGON, SE_REMOTE_INTERACTIVE_LOGON_NAME},
73     {SECURITY_ACCESS_DENY_REMOTE_INTERACTIVE_LOGON, SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME}
74 };
75 
76 
77 /* FUNCTIONS ***************************************************************/
78 
79 NTSTATUS
LsarpLookupPrivilegeName(PLUID Value,PRPC_UNICODE_STRING * Name)80 LsarpLookupPrivilegeName(PLUID Value,
81                          PRPC_UNICODE_STRING *Name)
82 {
83     PRPC_UNICODE_STRING NameBuffer;
84     ULONG Priv;
85 
86     if (Value->HighPart != 0 ||
87         (Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
88          Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
89     {
90         return STATUS_NO_SUCH_PRIVILEGE;
91     }
92 
93     for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
94     {
95         if (Value->LowPart == WellKnownPrivileges[Priv].Luid.LowPart &&
96             Value->HighPart == WellKnownPrivileges[Priv].Luid.HighPart)
97         {
98             NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
99             if (NameBuffer == NULL)
100                 return STATUS_NO_MEMORY;
101 
102             NameBuffer->Length = (USHORT)wcslen(WellKnownPrivileges[Priv].Name) * sizeof(WCHAR);
103             NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
104 
105             NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
106             if (NameBuffer->Buffer == NULL)
107             {
108                 MIDL_user_free(NameBuffer);
109                 return STATUS_NO_MEMORY;
110             }
111 
112             wcscpy(NameBuffer->Buffer, WellKnownPrivileges[Priv].Name);
113 
114             *Name = NameBuffer;
115 
116             return STATUS_SUCCESS;
117         }
118     }
119 
120     return STATUS_NO_SUCH_PRIVILEGE;
121 }
122 
123 
124 NTSTATUS
LsarpLookupPrivilegeDisplayName(PRPC_UNICODE_STRING Name,USHORT ClientLanguage,USHORT ClientSystemDefaultLanguage,PRPC_UNICODE_STRING * DisplayName,USHORT * LanguageReturned)125 LsarpLookupPrivilegeDisplayName(PRPC_UNICODE_STRING Name,
126                                 USHORT ClientLanguage,
127                                 USHORT ClientSystemDefaultLanguage,
128                                 PRPC_UNICODE_STRING *DisplayName,
129                                 USHORT *LanguageReturned)
130 {
131     PRPC_UNICODE_STRING DisplayNameBuffer;
132     HINSTANCE hInstance;
133     ULONG Index;
134     UINT nLength;
135 
136     TRACE("LsarpLookupPrivilegeDisplayName(%p 0x%04hu 0x%04hu %p %p)\n",
137           Name, ClientLanguage, ClientSystemDefaultLanguage, DisplayName, LanguageReturned);
138 
139     if (Name->Length == 0 || Name->Buffer == NULL)
140         return STATUS_INVALID_PARAMETER;
141 
142     hInstance = GetModuleHandleW(L"lsasrv.dll");
143 
144     for (Index = 0; Index < ARRAYSIZE(WellKnownPrivileges); Index++)
145     {
146         if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Index].Name) == 0)
147         {
148             TRACE("Index: %u\n", Index);
149             nLength = LsapGetResourceStringLengthEx(hInstance,
150                                                     IDS_CREATE_TOKEN_PRIVILEGE + Index,
151                                                     ClientLanguage);
152             if (nLength != 0)
153             {
154                 DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
155                 if (DisplayNameBuffer == NULL)
156                     return STATUS_NO_MEMORY;
157 
158                 DisplayNameBuffer->Length = nLength * sizeof(WCHAR);
159                 DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR);
160 
161                 DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength);
162                 if (DisplayNameBuffer->Buffer == NULL)
163                 {
164                     MIDL_user_free(DisplayNameBuffer);
165                     return STATUS_NO_MEMORY;
166                 }
167 
168                 LsapLoadStringEx(hInstance,
169                                  IDS_CREATE_TOKEN_PRIVILEGE + Index,
170                                  ClientLanguage,
171                                  DisplayNameBuffer->Buffer,
172                                  nLength);
173 
174                 *DisplayName = DisplayNameBuffer;
175                 *LanguageReturned = ClientLanguage;
176             }
177             else
178             {
179                 nLength = LsapGetResourceStringLengthEx(hInstance,
180                                                         IDS_CREATE_TOKEN_PRIVILEGE + Index,
181                                                         ClientSystemDefaultLanguage);
182                 if (nLength != 0)
183                 {
184                     DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
185                     if (DisplayNameBuffer == NULL)
186                         return STATUS_NO_MEMORY;
187 
188                     DisplayNameBuffer->Length = nLength * sizeof(WCHAR);
189                     DisplayNameBuffer->MaximumLength = DisplayNameBuffer->Length + sizeof(WCHAR);
190 
191                     DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength);
192                     if (DisplayNameBuffer->Buffer == NULL)
193                     {
194                         MIDL_user_free(DisplayNameBuffer);
195                         return STATUS_NO_MEMORY;
196                     }
197 
198                     LsapLoadStringEx(hInstance,
199                                      IDS_CREATE_TOKEN_PRIVILEGE + Index,
200                                      ClientSystemDefaultLanguage,
201                                      DisplayNameBuffer->Buffer,
202                                      nLength);
203 
204                     *DisplayName = DisplayNameBuffer;
205                     *LanguageReturned = ClientSystemDefaultLanguage;
206                 }
207                 else
208                 {
209                     return STATUS_INVALID_PARAMETER;
210 #if 0
211                     nLength = LsapGetResourceStringLengthEx(hInstance,
212                                                             IDS_CREATE_TOKEN_PRIVILEGE + Index,
213                                                             0x409);
214 #endif
215                 }
216             }
217 
218             return STATUS_SUCCESS;
219         }
220     }
221 
222     return STATUS_NO_SUCH_PRIVILEGE;
223 }
224 
225 
226 PLUID
LsarpLookupPrivilegeValue(IN PRPC_UNICODE_STRING Name)227 LsarpLookupPrivilegeValue(
228     IN PRPC_UNICODE_STRING Name)
229 {
230     ULONG Priv;
231 
232     if (Name->Length == 0 || Name->Buffer == NULL)
233         return NULL;
234 
235     for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
236     {
237         if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0)
238             return (PLUID)&(WellKnownPrivileges[Priv].Luid);
239     }
240 
241     return NULL;
242 }
243 
244 
245 NTSTATUS
LsarpEnumeratePrivileges(DWORD * EnumerationContext,PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,DWORD PreferedMaximumLength)246 LsarpEnumeratePrivileges(DWORD *EnumerationContext,
247                          PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
248                          DWORD PreferedMaximumLength)
249 {
250     PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL;
251     ULONG EnumIndex;
252     ULONG EnumCount = 0;
253     ULONG RequiredLength = 0;
254     ULONG i;
255     BOOLEAN MoreEntries = FALSE;
256     NTSTATUS Status = STATUS_SUCCESS;
257 
258     EnumIndex = *EnumerationContext;
259 
260     for (; EnumIndex < ARRAYSIZE(WellKnownPrivileges); EnumIndex++)
261     {
262         TRACE("EnumIndex: %lu\n", EnumIndex);
263         TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name);
264         TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name));
265 
266         if ((RequiredLength +
267              wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
268              sizeof(UNICODE_NULL) +
269              sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength)
270         {
271             MoreEntries = TRUE;
272             break;
273         }
274 
275         RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
276                            sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
277         EnumCount++;
278     }
279 
280     TRACE("EnumCount: %lu\n", EnumCount);
281     TRACE("RequiredLength: %lu\n", RequiredLength);
282 
283     if (EnumCount == 0)
284         goto done;
285 
286     Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
287     if (Privileges == NULL)
288     {
289         Status = STATUS_INSUFFICIENT_RESOURCES;
290         goto done;
291     }
292 
293     EnumIndex = *EnumerationContext;
294 
295     for (i = 0; i < EnumCount; i++, EnumIndex++)
296     {
297         Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid;
298 
299         Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR);
300         Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL);
301 
302         Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength);
303         if (Privileges[i].Name.Buffer == NULL)
304         {
305             Status = STATUS_INSUFFICIENT_RESOURCES;
306             goto done;
307         }
308 
309         memcpy(Privileges[i].Name.Buffer,
310                WellKnownPrivileges[EnumIndex].Name,
311                Privileges[i].Name.Length);
312     }
313 
314 done:
315     if (NT_SUCCESS(Status))
316     {
317         EnumerationBuffer->Entries = EnumCount;
318         EnumerationBuffer->Privileges = Privileges;
319         *EnumerationContext += EnumCount;
320     }
321     else
322     {
323         if (Privileges != NULL)
324         {
325             for (i = 0; i < EnumCount; i++)
326             {
327                 if (Privileges[i].Name.Buffer != NULL)
328                     MIDL_user_free(Privileges[i].Name.Buffer);
329             }
330 
331             MIDL_user_free(Privileges);
332         }
333     }
334 
335     if ((Status == STATUS_SUCCESS) && (MoreEntries != FALSE))
336         Status = STATUS_MORE_ENTRIES;
337 
338     return Status;
339 }
340 
341 
342 NTSTATUS
LsapLookupAccountRightName(ULONG RightValue,PRPC_UNICODE_STRING * Name)343 LsapLookupAccountRightName(ULONG RightValue,
344                            PRPC_UNICODE_STRING *Name)
345 {
346     PRPC_UNICODE_STRING NameBuffer;
347     ULONG i;
348 
349     for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
350     {
351         if (WellKnownRights[i].Flag == RightValue)
352         {
353             NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
354             if (NameBuffer == NULL)
355                 return STATUS_NO_MEMORY;
356 
357             NameBuffer->Length = (USHORT)wcslen(WellKnownRights[i].Name) * sizeof(WCHAR);
358             NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
359 
360             NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
361             if (NameBuffer->Buffer == NULL)
362             {
363                 MIDL_user_free(NameBuffer);
364                 return STATUS_INSUFFICIENT_RESOURCES;
365             }
366 
367             wcscpy(NameBuffer->Buffer, WellKnownRights[i].Name);
368 
369             *Name = NameBuffer;
370 
371             return STATUS_SUCCESS;
372         }
373     }
374 
375     return STATUS_NO_SUCH_PRIVILEGE;
376 }
377 
378 
379 ACCESS_MASK
LsapLookupAccountRightValue(IN PRPC_UNICODE_STRING Name)380 LsapLookupAccountRightValue(
381     IN PRPC_UNICODE_STRING Name)
382 {
383     ULONG i;
384 
385     if (Name->Length == 0 || Name->Buffer == NULL)
386         return 0;
387 
388     for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
389     {
390         if (_wcsicmp(Name->Buffer, WellKnownRights[i].Name) == 0)
391             return WellKnownRights[i].Flag;
392     }
393 
394     return 0;
395 }
396 
397 /* EOF */
398