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