[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
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
22 /* GLOBALS *****************************************************************/
23
24 static const PRIVILEGE_DATA WellKnownPrivileges[] =
25 {
26 {{SE_CREATE_TOKEN_PRIVILEGE, 0}, SE_CREATE_TOKEN_NAME},
27 {{SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, 0}, SE_ASSIGNPRIMARYTOKEN_NAME},
28 {{SE_LOCK_MEMORY_PRIVILEGE, 0}, SE_LOCK_MEMORY_NAME},
29 {{SE_INCREASE_QUOTA_PRIVILEGE, 0}, SE_INCREASE_QUOTA_NAME},
30 {{SE_MACHINE_ACCOUNT_PRIVILEGE, 0}, SE_MACHINE_ACCOUNT_NAME},
31 {{SE_TCB_PRIVILEGE, 0}, SE_TCB_NAME},
32 {{SE_SECURITY_PRIVILEGE, 0}, SE_SECURITY_NAME},
33 {{SE_TAKE_OWNERSHIP_PRIVILEGE, 0}, SE_TAKE_OWNERSHIP_NAME},
34 {{SE_LOAD_DRIVER_PRIVILEGE, 0}, SE_LOAD_DRIVER_NAME},
35 {{SE_SYSTEM_PROFILE_PRIVILEGE, 0}, SE_SYSTEM_PROFILE_NAME},
36 {{SE_SYSTEMTIME_PRIVILEGE, 0}, SE_SYSTEMTIME_NAME},
37 {{SE_PROF_SINGLE_PROCESS_PRIVILEGE, 0}, SE_PROF_SINGLE_PROCESS_NAME},
38 {{SE_INC_BASE_PRIORITY_PRIVILEGE, 0}, SE_INC_BASE_PRIORITY_NAME},
39 {{SE_CREATE_PAGEFILE_PRIVILEGE, 0}, SE_CREATE_PAGEFILE_NAME},
40 {{SE_CREATE_PERMANENT_PRIVILEGE, 0}, SE_CREATE_PERMANENT_NAME},
41 {{SE_BACKUP_PRIVILEGE, 0}, SE_BACKUP_NAME},
42 {{SE_RESTORE_PRIVILEGE, 0}, SE_RESTORE_NAME},
43 {{SE_SHUTDOWN_PRIVILEGE, 0}, SE_SHUTDOWN_NAME},
44 {{SE_DEBUG_PRIVILEGE, 0}, SE_DEBUG_NAME},
45 {{SE_AUDIT_PRIVILEGE, 0}, SE_AUDIT_NAME},
46 {{SE_SYSTEM_ENVIRONMENT_PRIVILEGE, 0}, SE_SYSTEM_ENVIRONMENT_NAME},
47 {{SE_CHANGE_NOTIFY_PRIVILEGE, 0}, SE_CHANGE_NOTIFY_NAME},
48 {{SE_REMOTE_SHUTDOWN_PRIVILEGE, 0}, SE_REMOTE_SHUTDOWN_NAME},
49 {{SE_UNDOCK_PRIVILEGE, 0}, SE_UNDOCK_NAME},
50 {{SE_SYNC_AGENT_PRIVILEGE, 0}, SE_SYNC_AGENT_NAME},
51 {{SE_ENABLE_DELEGATION_PRIVILEGE, 0}, SE_ENABLE_DELEGATION_NAME},
52 {{SE_MANAGE_VOLUME_PRIVILEGE, 0}, SE_MANAGE_VOLUME_NAME},
53 {{SE_IMPERSONATE_PRIVILEGE, 0}, SE_IMPERSONATE_NAME},
54 {{SE_CREATE_GLOBAL_PRIVILEGE, 0}, SE_CREATE_GLOBAL_NAME}
55 };
56
57
58 /* FUNCTIONS ***************************************************************/
59
60 NTSTATUS
61 LsarpLookupPrivilegeName(PLUID Value,
62 PUNICODE_STRING *Name)
63 {
64 PUNICODE_STRING NameBuffer;
65 ULONG Priv;
66
67 if (Value->HighPart != 0 ||
68 (Value->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
69 Value->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
70 {
71 return STATUS_NO_SUCH_PRIVILEGE;
72 }
73
74 for (Priv = 0; Priv < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); Priv++)
75 {
76 if (Value->LowPart == WellKnownPrivileges[Priv].Luid.LowPart &&
77 Value->HighPart == WellKnownPrivileges[Priv].Luid.HighPart)
78 {
79 NameBuffer = MIDL_user_allocate(sizeof(UNICODE_STRING));
80 if (NameBuffer == NULL)
81 return STATUS_NO_MEMORY;
82
83 NameBuffer->Length = wcslen(WellKnownPrivileges[Priv].Name) * sizeof(WCHAR);
84 NameBuffer->MaximumLength = NameBuffer->Length + sizeof(WCHAR);
85
86 NameBuffer->Buffer = MIDL_user_allocate(NameBuffer->MaximumLength);
87 if (NameBuffer == NULL)
88 {
89 MIDL_user_free(NameBuffer);
90 return STATUS_NO_MEMORY;
91 }
92
93 wcscpy(NameBuffer->Buffer, WellKnownPrivileges[Priv].Name);
94
95 *Name = NameBuffer;
96
97 return STATUS_SUCCESS;
98 }
99 }
100
101 return STATUS_NO_SUCH_PRIVILEGE;
102 }
103
104
105 NTSTATUS
106 LsarpLookupPrivilegeValue(PUNICODE_STRING Name,
107 PLUID Value)
108 {
109 ULONG Priv;
110
111 if (Name->Length == 0 || Name->Buffer == NULL)
112 return STATUS_NO_SUCH_PRIVILEGE;
113
114 for (Priv = 0; Priv < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); Priv++)
115 {
116 if (_wcsicmp(Name->Buffer, WellKnownPrivileges[Priv].Name) == 0)
117 {
118 *Value = WellKnownPrivileges[Priv].Luid;
119 return STATUS_SUCCESS;
120 }
121 }
122
123 return STATUS_NO_SUCH_PRIVILEGE;
124 }
125
126
127 NTSTATUS
128 LsarpEnumeratePrivileges(DWORD *EnumerationContext,
129 PLSAPR_PRIVILEGE_ENUM_BUFFER EnumerationBuffer,
130 DWORD PreferedMaximumLength)
131 {
132 PLSAPR_POLICY_PRIVILEGE_DEF Privileges = NULL;
133 ULONG EnumIndex;
134 ULONG EnumCount = 0;
135 ULONG RequiredLength = 0;
136 ULONG i;
137 BOOLEAN MoreEntries = FALSE;
138 NTSTATUS Status = STATUS_SUCCESS;
139
140 EnumIndex = *EnumerationContext;
141
142 for (; EnumIndex < sizeof(WellKnownPrivileges) / sizeof(WellKnownPrivileges[0]); EnumIndex++)
143 {
144 TRACE("EnumIndex: %lu\n", EnumIndex);
145 TRACE("Privilege Name: %S\n", WellKnownPrivileges[EnumIndex].Name);
146 TRACE("Name Length: %lu\n", wcslen(WellKnownPrivileges[EnumIndex].Name));
147
148 if ((RequiredLength +
149 wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
150 sizeof(UNICODE_NULL) +
151 sizeof(LSAPR_POLICY_PRIVILEGE_DEF)) > PreferedMaximumLength)
152 {
153 MoreEntries = TRUE;
154 break;
155 }
156
157 RequiredLength += (wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR) +
158 sizeof(UNICODE_NULL) + sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
159 EnumCount++;
160 }
161
162 TRACE("EnumCount: %lu\n", EnumCount);
163 TRACE("RequiredLength: %lu\n", RequiredLength);
164
165 if (EnumCount == 0)
166 goto done;
167
168 Privileges = MIDL_user_allocate(EnumCount * sizeof(LSAPR_POLICY_PRIVILEGE_DEF));
169 if (Privileges == NULL)
170 {
171 Status = STATUS_INSUFFICIENT_RESOURCES;
172 goto done;
173 }
174
175 EnumIndex = *EnumerationContext;
176
177 for (i = 0; i < EnumCount; i++, EnumIndex++)
178 {
179 Privileges[i].LocalValue = WellKnownPrivileges[EnumIndex].Luid;
180
181 Privileges[i].Name.Length = (USHORT)wcslen(WellKnownPrivileges[EnumIndex].Name) * sizeof(WCHAR);
182 Privileges[i].Name.MaximumLength = (USHORT)Privileges[i].Name.Length + sizeof(UNICODE_NULL);
183
184 Privileges[i].Name.Buffer = MIDL_user_allocate(Privileges[i].Name.MaximumLength);
185 if (Privileges[i].Name.Buffer == NULL)
186 {
187 Status = STATUS_INSUFFICIENT_RESOURCES;
188 goto done;
189 }
190
191 memcpy(Privileges[i].Name.Buffer,
192 WellKnownPrivileges[EnumIndex].Name,
193 Privileges[i].Name.Length);
194 }
195
196 done:
197 if (NT_SUCCESS(Status))
198 {
199 EnumerationBuffer->Entries = EnumCount;
200 EnumerationBuffer->Privileges = Privileges;
201 *EnumerationContext += EnumCount;
202 }
203 else
204 {
205 if (Privileges != NULL)
206 {
207 for (i = 0; i < EnumCount; i++)
208 {
209 if (Privileges[i].Name.Buffer != NULL)
210 MIDL_user_free(Privileges[i].Name.Buffer);
211 }
212
213 MIDL_user_free(Privileges);
214 }
215 }
216
217 if ((Status == STATUS_SUCCESS) && (MoreEntries == TRUE))
218 Status = STATUS_MORE_ENTRIES;
219
220 return Status;
221 }