[LSASRV]
[reactos.git] / reactos / dll / win32 / lsasrv / privileges.c
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
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 = 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
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)",
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
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
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 == TRUE))
336 Status = STATUS_MORE_ENTRIES;
337
338 return Status;
339 }
340
341
342 NTSTATUS
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 = 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
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 */