266abe8b42759a8d22ae5efd1608111f1fc630d1
[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
8 */
9
10 #include "lsasrv.h"
11
12 typedef struct
13 {
14 LUID Luid;
15 LPCWSTR Name;
16 } PRIVILEGE_DATA;
17
18 typedef struct
19 {
20 ULONG Flag;
21 LPCWSTR Name;
22 } RIGHT_DATA;
23
24
25 /* GLOBALS *****************************************************************/
26
27 static const PRIVILEGE_DATA WellKnownPrivileges[] =
28 {
29 {{SE_CREATE_TOKEN_PRIVILEGE, 0}, SE_CREATE_TOKEN_NAME},
30 {{SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0}, SE_ASSIGNPRIMARYTOKEN_NAME},
31 {{SE_LOCK_MEMORY_PRIVILEGE, 0}, SE_LOCK_MEMORY_NAME},
32 {{SE_INCREASE_QUOTA_PRIVILEGE, 0}, SE_INCREASE_QUOTA_NAME},
33 {{SE_MACHINE_ACCOUNT_PRIVILEGE, 0}, SE_MACHINE_ACCOUNT_NAME},
34 {{SE_TCB_PRIVILEGE, 0}, SE_TCB_NAME},
35 {{SE_SECURITY_PRIVILEGE, 0}, SE_SECURITY_NAME},
36 {{SE_TAKE_OWNERSHIP_PRIVILEGE, 0}, SE_TAKE_OWNERSHIP_NAME},
37 {{SE_LOAD_DRIVER_PRIVILEGE, 0}, SE_LOAD_DRIVER_NAME},
38 {{SE_SYSTEM_PROFILE_PRIVILEGE, 0}, SE_SYSTEM_PROFILE_NAME},
39 {{SE_SYSTEMTIME_PRIVILEGE, 0}, SE_SYSTEMTIME_NAME},
40 {{SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0}, SE_PROF_SINGLE_PROCESS_NAME},
41 {{SE_INC_BASE_PRIORITY_PRIVILEGE, 0}, SE_INC_BASE_PRIORITY_NAME},
42 {{SE_CREATE_PAGEFILE_PRIVILEGE, 0}, SE_CREATE_PAGEFILE_NAME},
43 {{SE_CREATE_PERMANENT_PRIVILEGE, 0}, SE_CREATE_PERMANENT_NAME},
44 {{SE_BACKUP_PRIVILEGE, 0}, SE_BACKUP_NAME},
45 {{SE_RESTORE_PRIVILEGE, 0}, SE_RESTORE_NAME},
46 {{SE_SHUTDOWN_PRIVILEGE, 0}, SE_SHUTDOWN_NAME},
47 {{SE_DEBUG_PRIVILEGE, 0}, SE_DEBUG_NAME},
48 {{SE_AUDIT_PRIVILEGE, 0}, SE_AUDIT_NAME},
49 {{SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0}, SE_SYSTEM_ENVIRONMENT_NAME},
50 {{SE_CHANGE_NOTIFY_PRIVILEGE, 0}, SE_CHANGE_NOTIFY_NAME},
51 {{SE_REMOTE_SHUTDOWN_PRIVILEGE, 0}, SE_REMOTE_SHUTDOWN_NAME},
52 {{SE_UNDOCK_PRIVILEGE, 0}, SE_UNDOCK_NAME},
53 {{SE_SYNC_AGENT_PRIVILEGE, 0}, SE_SYNC_AGENT_NAME},
54 {{SE_ENABLE_DELEGATION_PRIVILEGE, 0}, SE_ENABLE_DELEGATION_NAME},
55 {{SE_MANAGE_VOLUME_PRIVILEGE, 0}, SE_MANAGE_VOLUME_NAME},
56 {{SE_IMPERSONATE_PRIVILEGE, 0}, SE_IMPERSONATE_NAME},
57 {{SE_CREATE_GLOBAL_PRIVILEGE, 0}, SE_CREATE_GLOBAL_NAME}
58 };
59
60 static const RIGHT_DATA WellKnownRights[] =
61 {
62 {SECURITY_ACCESS_INTERACTIVE_LOGON, SE_INTERACTIVE_LOGON_NAME},
63 {SECURITY_ACCESS_NETWORK_LOGON, SE_NETWORK_LOGON_NAME},
64 {SECURITY_ACCESS_BATCH_LOGON, SE_BATCH_LOGON_NAME},
65 {SECURITY_ACCESS_SERVICE_LOGON, SE_SERVICE_LOGON_NAME},
66 {SECURITY_ACCESS_DENY_INTERACTIVE_LOGON, SE_DENY_INTERACTIVE_LOGON_NAME},
67 {SECURITY_ACCESS_DENY_NETWORK_LOGON, SE_DENY_NETWORK_LOGON_NAME},
68 {SECURITY_ACCESS_DENY_BATCH_LOGON, SE_DENY_BATCH_LOGON_NAME},
69 {SECURITY_ACCESS_DENY_SERVICE_LOGON, SE_DENY_SERVICE_LOGON_NAME},
70 {SECURITY_ACCESS_REMOTE_INTERACTIVE_LOGON, SE_REMOTE_INTERACTIVE_LOGON_NAME},
71 {SECURITY_ACCESS_DENY_REMOTE_INTERACTIVE_LOGON, SE_DENY_REMOTE_INTERACTIVE_LOGON_NAME}
72 };
73
74
75 /* FUNCTIONS ***************************************************************/
76
77 NTSTATUS
78 LsarpLookupPrivilegeName(PLUID Value,
79 PRPC_UNICODE_STRING *Name)
80 {
81 PRPC_UNICODE_STRING NameBuffer;
82 ULONG Priv;
83
84 if (Value->HighPart != 0 ||
85 (Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
86 Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
87 {
88 return STATUS_NO_SUCH_PRIVILEGE;
89 }
90
91 for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
92 {
93 if (Value->LowPart == WellKnownPrivileges[Priv].Luid.LowPart &&
94 Value->HighPart == WellKnownPrivileges[Priv].Luid.HighPart)
95 {
96 NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
97 if (NameBuffer == NULL)
98 return STATUS_NO_MEMORY;
99
100 NameBuffer->Length = wcslen(WellKnownPrivileges[Priv].Name) * sizeof(WCHAR);
101 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
102
103 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
104 if (NameBuffer->Buffer == NULL)
105 {
106 MIDL_user_free(NameBuffer);
107 return STATUS_NO_MEMORY;
108 }
109
110 wcscpy(NameBuffer->Buffer, WellKnownPrivileges[Priv].Name);
111
112 *Name = NameBuffer;
113
114 return STATUS_SUCCESS;
115 }
116 }
117
118 return STATUS_NO_SUCH_PRIVILEGE;
119 }
120
121 NTSTATUS
122 LsarpLookupPrivilegeDisplayName(PRPC_UNICODE_STRING Name,
123 USHORT ClientLanguage,
124 USHORT ClientSystemDefaultLanguage,
125 PRPC_UNICODE_STRING *DisplayName,
126 USHORT *LanguageReturned)
127 {
128 PRPC_UNICODE_STRING DisplayNameBuffer;
129 UNIMPLEMENTED;
130
131 /* For now, description is equal to privilege name */
132
133 DisplayNameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
134 if (DisplayNameBuffer == NULL)
135 {
136 return STATUS_NO_MEMORY;
137 }
138 DisplayNameBuffer->Length = Name->Length;
139 DisplayNameBuffer->MaximumLength = Name->MaximumLength;
140
141 DisplayNameBuffer->Buffer = MIDL_user_allocate(DisplayNameBuffer->MaximumLength);
142 if (DisplayNameBuffer->Buffer == NULL)
143 {
144 MIDL_user_free(DisplayNameBuffer);
145 return STATUS_NO_MEMORY;
146 }
147
148 wcscpy(DisplayNameBuffer->Buffer, Name->Buffer);
149
150 *DisplayName = DisplayNameBuffer;
151
152 return STATUS_SUCCESS;
153 }
154
155
156 PLUID
157 LsarpLookupPrivilegeValue(
158 IN PRPC_UNICODE_STRING Name)
159 {
160 ULONG Priv;
161
162 if (Name->Length == 0 || Name->Buffer == NULL)
163 return NULL;
164
165 for (Priv = 0; Priv < ARRAYSIZE(WellKnownPrivileges); Priv++)
166 {
167 if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0)
168 return (PLUID)&(WellKnownPrivileges[Priv].Luid);
169 }
170
171 return NULL;
172 }
173
174
175 NTSTATUS
176 LsarpEnumeratePrivileges(DWORD *EnumerationContext,
177 PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
178 DWORD PreferedMaximumLength)
179 {
180 PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL;
181 ULONG EnumIndex;
182 ULONG EnumCount = 0;
183 ULONG RequiredLength = 0;
184 ULONG i;
185 BOOLEAN MoreEntries = FALSE;
186 NTSTATUS Status = STATUS_SUCCESS;
187
188 EnumIndex = *EnumerationContext;
189
190 for (; EnumIndex < ARRAYSIZE(WellKnownPrivileges); EnumIndex++)
191 {
192 TRACE("EnumIndex: %lu\n", EnumIndex);
193 TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name);
194 TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name));
195
196 if ((RequiredLength +
197 wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
198 sizeof(UNICODE_NULL) +
199 sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength)
200 {
201 MoreEntries = TRUE;
202 break;
203 }
204
205 RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
206 sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
207 EnumCount++;
208 }
209
210 TRACE("EnumCount: %lu\n", EnumCount);
211 TRACE("RequiredLength: %lu\n", RequiredLength);
212
213 if (EnumCount == 0)
214 goto done;
215
216 Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
217 if (Privileges == NULL)
218 {
219 Status = STATUS_INSUFFICIENT_RESOURCES;
220 goto done;
221 }
222
223 EnumIndex = *EnumerationContext;
224
225 for (i = 0; i < EnumCount; i++, EnumIndex++)
226 {
227 Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid;
228
229 Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR);
230 Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL);
231
232 Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength);
233 if (Privileges[i].Name.Buffer == NULL)
234 {
235 Status = STATUS_INSUFFICIENT_RESOURCES;
236 goto done;
237 }
238
239 memcpy(Privileges[i].Name.Buffer,
240 WellKnownPrivileges[EnumIndex].Name,
241 Privileges[i].Name.Length);
242 }
243
244 done:
245 if (NT_SUCCESS(Status))
246 {
247 EnumerationBuffer->Entries = EnumCount;
248 EnumerationBuffer->Privileges = Privileges;
249 *EnumerationContext += EnumCount;
250 }
251 else
252 {
253 if (Privileges != NULL)
254 {
255 for (i = 0; i < EnumCount; i++)
256 {
257 if (Privileges[i].Name.Buffer != NULL)
258 MIDL_user_free(Privileges[i].Name.Buffer);
259 }
260
261 MIDL_user_free(Privileges);
262 }
263 }
264
265 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
266 Status = STATUS_MORE_ENTRIES;
267
268 return Status;
269 }
270
271
272 NTSTATUS
273 LsapLookupAccountRightName(ULONG RightValue,
274 PRPC_UNICODE_STRING *Name)
275 {
276 PRPC_UNICODE_STRING NameBuffer;
277 ULONG i;
278
279 for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
280 {
281 if (WellKnownRights[i].Flag == RightValue)
282 {
283 NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
284 if (NameBuffer == NULL)
285 return STATUS_NO_MEMORY;
286
287 NameBuffer->Length = wcslen(WellKnownRights[i].Name) * sizeof(WCHAR);
288 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
289
290 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
291 if (NameBuffer->Buffer == NULL)
292 {
293 MIDL_user_free(NameBuffer);
294 return STATUS_INSUFFICIENT_RESOURCES;
295 }
296
297 wcscpy(NameBuffer->Buffer, WellKnownRights[i].Name);
298
299 *Name = NameBuffer;
300
301 return STATUS_SUCCESS;
302 }
303 }
304
305 return STATUS_NO_SUCH_PRIVILEGE;
306 }
307
308
309 ACCESS_MASK
310 LsapLookupAccountRightValue(
311 IN PRPC_UNICODE_STRING Name)
312 {
313 ULONG i;
314
315 if (Name->Length == 0 || Name->Buffer == NULL)
316 return 0;
317
318 for (i = 0; i < ARRAYSIZE(WellKnownRights); i++)
319 {
320 if (_wcsicmp(Name->Buffer, WellKnownRights[i].Name) == 0)
321 return WellKnownRights[i].Flag;
322 }
323
324 return 0;
325 }
326
327 /* EOF */