Sync with trunk r62754.
[reactos.git] / 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 < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); 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
122 NTSTATUS
123 LsarpLookupPrivilegeValue(PRPC_UNICODE_STRING Name,
124 PLUID Value)
125 {
126 ULONG Priv;
127
128 if (Name->Length == 0 || Name->Buffer == NULL)
129 return STATUS_NO_SUCH_PRIVILEGE;
130
131 for (Priv = 0; Priv < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); Priv++)
132 {
133 if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0)
134 {
135 *Value = WellKnownPrivileges[Priv].Luid;
136 return STATUS_SUCCESS;
137 }
138 }
139
140 return STATUS_NO_SUCH_PRIVILEGE;
141 }
142
143
144 NTSTATUS
145 LsarpEnumeratePrivileges(DWORD *EnumerationContext,
146 PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
147 DWORD PreferedMaximumLength)
148 {
149 PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL;
150 ULONG EnumIndex;
151 ULONG EnumCount = 0;
152 ULONG RequiredLength = 0;
153 ULONG i;
154 BOOLEAN MoreEntries = FALSE;
155 NTSTATUS Status = STATUS_SUCCESS;
156
157 EnumIndex = *EnumerationContext;
158
159 for (; EnumIndex < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); EnumIndex++)
160 {
161 TRACE("EnumIndex: %lu\n", EnumIndex);
162 TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name);
163 TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name));
164
165 if ((RequiredLength +
166 wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
167 sizeof(UNICODE_NULL) +
168 sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength)
169 {
170 MoreEntries = TRUE;
171 break;
172 }
173
174 RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
175 sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
176 EnumCount++;
177 }
178
179 TRACE("EnumCount: %lu\n", EnumCount);
180 TRACE("RequiredLength: %lu\n", RequiredLength);
181
182 if (EnumCount == 0)
183 goto done;
184
185 Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
186 if (Privileges == NULL)
187 {
188 Status = STATUS_INSUFFICIENT_RESOURCES;
189 goto done;
190 }
191
192 EnumIndex = *EnumerationContext;
193
194 for (i = 0; i < EnumCount; i++, EnumIndex++)
195 {
196 Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid;
197
198 Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR);
199 Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL);
200
201 Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength);
202 if (Privileges[i].Name.Buffer == NULL)
203 {
204 Status = STATUS_INSUFFICIENT_RESOURCES;
205 goto done;
206 }
207
208 memcpy(Privileges[i].Name.Buffer,
209 WellKnownPrivileges[EnumIndex].Name,
210 Privileges[i].Name.Length);
211 }
212
213 done:
214 if (NT_SUCCESS(Status))
215 {
216 EnumerationBuffer->Entries = EnumCount;
217 EnumerationBuffer->Privileges = Privileges;
218 *EnumerationContext += EnumCount;
219 }
220 else
221 {
222 if (Privileges != NULL)
223 {
224 for (i = 0; i < EnumCount; i++)
225 {
226 if (Privileges[i].Name.Buffer != NULL)
227 MIDL_user_free(Privileges[i].Name.Buffer);
228 }
229
230 MIDL_user_free(Privileges);
231 }
232 }
233
234 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
235 Status = STATUS_MORE_ENTRIES;
236
237 return Status;
238 }
239
240
241 NTSTATUS
242 LsapLookupAccountRightName(ULONG RightValue,
243 PRPC_UNICODE_STRING *Name)
244 {
245 PRPC_UNICODE_STRING NameBuffer;
246 ULONG i;
247
248 for (i = 0; i < sizeof(WellKnownRights) / sizeof(WellKnownRights[0]); i++)
249 {
250 if (WellKnownRights[i].Flag == RightValue)
251 {
252 NameBuffer = MIDL_user_allocate(sizeof(RPC_UNICODE_STRING));
253 if (NameBuffer == NULL)
254 return STATUS_NO_MEMORY;
255
256 NameBuffer->Length = wcslen(WellKnownRights[i].Name) * sizeof(WCHAR);
257 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
258
259 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
260 if (NameBuffer->Buffer == NULL)
261 {
262 MIDL_user_free(NameBuffer);
263 return STATUS_INSUFFICIENT_RESOURCES;
264 }
265
266 wcscpy(NameBuffer->Buffer, WellKnownRights[i].Name);
267
268 *Name = NameBuffer;
269
270 return STATUS_SUCCESS;
271 }
272 }
273
274 return STATUS_NO_SUCH_PRIVILEGE;
275 }
276
277 /* EOF */