xref: /reactos/dll/win32/samsrv/alias.c (revision 1734f297)
1 /*
2  * PROJECT:     Local Security Authority Server DLL
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/win32/samsrv/alias.c
5  * PURPOSE:     Alias specific helper functions
6  * COPYRIGHT:   Copyright 2013 Eric Kohl
7  */
8 
9 #include "samsrv.h"
10 
11 /* FUNCTIONS ***************************************************************/
12 
13 NTSTATUS
14 SampOpenAliasObject(IN PSAM_DB_OBJECT DomainObject,
15                     IN ULONG AliasId,
16                     IN ACCESS_MASK DesiredAccess,
17                     OUT PSAM_DB_OBJECT *AliasObject)
18 {
19     WCHAR szRid[9];
20 
21     TRACE("(%p %lu %lx %p)\n",
22           DomainObject, AliasId, DesiredAccess, AliasObject);
23 
24     /* Convert the RID into a string (hex) */
25     swprintf(szRid, L"%08lX", AliasId);
26 
27     /* Create the user object */
28     return SampOpenDbObject(DomainObject,
29                             L"Aliases",
30                             szRid,
31                             AliasId,
32                             SamDbAliasObject,
33                             DesiredAccess,
34                             AliasObject);
35 }
36 
37 
38 NTSTATUS
39 SampAddMemberToAlias(IN PSAM_DB_OBJECT AliasObject,
40                      IN PRPC_SID MemberId)
41 {
42     LPWSTR MemberIdString = NULL;
43     HANDLE MembersKeyHandle = NULL;
44     HANDLE MemberKeyHandle = NULL;
45     ULONG MemberIdLength;
46     NTSTATUS Status;
47 
48     TRACE("(%p %p)\n",
49           AliasObject, MemberId);
50 
51     ConvertSidToStringSidW(MemberId, &MemberIdString);
52     TRACE("Member SID: %S\n", MemberIdString);
53 
54     MemberIdLength = RtlLengthSid(MemberId);
55 
56     Status = SampRegCreateKey(AliasObject->KeyHandle,
57                               L"Members",
58                               KEY_WRITE,
59                               &MembersKeyHandle);
60     if (!NT_SUCCESS(Status))
61     {
62         TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
63         goto done;
64     }
65 
66     Status = SampRegSetValue(MembersKeyHandle,
67                              MemberIdString,
68                              REG_BINARY,
69                              MemberId,
70                              MemberIdLength);
71     if (!NT_SUCCESS(Status))
72     {
73         TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
74         goto done;
75     }
76 
77     Status = SampRegCreateKey(AliasObject->MembersKeyHandle,
78                               MemberIdString,
79                               KEY_WRITE,
80                               &MemberKeyHandle);
81     if (!NT_SUCCESS(Status))
82     {
83         TRACE("SampRegCreateKey failed with status 0x%08lx\n", Status);
84         goto done;
85     }
86 
87     Status = SampRegSetValue(MemberKeyHandle,
88                              AliasObject->Name,
89                              REG_BINARY,
90                              MemberId,
91                              MemberIdLength);
92     if (!NT_SUCCESS(Status))
93     {
94         TRACE("SampRegSetValue failed with status 0x%08lx\n", Status);
95         goto done;
96     }
97 
98 done:
99     SampRegCloseKey(&MemberKeyHandle);
100     SampRegCloseKey(&MembersKeyHandle);
101 
102     if (MemberIdString != NULL)
103         LocalFree(MemberIdString);
104 
105     return Status;
106 }
107 
108 
109 NTSTATUS
110 NTAPI
111 SampRemoveMemberFromAlias(IN PSAM_DB_OBJECT AliasObject,
112                           IN PRPC_SID MemberId)
113 {
114     LPWSTR MemberIdString = NULL;
115     HANDLE MembersKeyHandle = NULL;
116     HANDLE MemberKeyHandle = NULL;
117     ULONG ulValueCount;
118     NTSTATUS Status;
119 
120     TRACE("(%p %p)\n",
121           AliasObject, MemberId);
122 
123     ConvertSidToStringSidW(MemberId, &MemberIdString);
124     TRACE("Member SID: %S\n", MemberIdString);
125 
126     Status = SampRegOpenKey(AliasObject->MembersKeyHandle,
127                             MemberIdString,
128                             KEY_WRITE | KEY_QUERY_VALUE,
129                             &MemberKeyHandle);
130     if (!NT_SUCCESS(Status))
131     {
132         TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
133         goto done;
134     }
135 
136     Status = SampRegDeleteValue(MemberKeyHandle,
137                                 AliasObject->Name);
138     if (!NT_SUCCESS(Status))
139     {
140         TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
141         goto done;
142     }
143 
144     Status = SampRegQueryKeyInfo(MemberKeyHandle,
145                                  NULL,
146                                  &ulValueCount);
147     if (!NT_SUCCESS(Status))
148     {
149         TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
150         goto done;
151     }
152 
153     if (ulValueCount == 0)
154     {
155         SampRegCloseKey(&MemberKeyHandle);
156 
157         Status = SampRegDeleteKey(AliasObject->MembersKeyHandle,
158                                   MemberIdString);
159         if (!NT_SUCCESS(Status))
160         {
161             TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
162             goto done;
163         }
164     }
165 
166     Status = SampRegOpenKey(AliasObject->KeyHandle,
167                             L"Members",
168                             KEY_WRITE | KEY_QUERY_VALUE,
169                             &MembersKeyHandle);
170     if (!NT_SUCCESS(Status))
171     {
172         TRACE("SampRegOpenKey failed with status 0x%08lx\n", Status);
173         goto done;
174     }
175 
176     Status = SampRegDeleteValue(MembersKeyHandle,
177                                 MemberIdString);
178     if (!NT_SUCCESS(Status))
179     {
180         TRACE("SampRegDeleteValue failed with status 0x%08lx\n", Status);
181         goto done;
182     }
183 
184     Status = SampRegQueryKeyInfo(MembersKeyHandle,
185                                  NULL,
186                                  &ulValueCount);
187     if (!NT_SUCCESS(Status))
188     {
189         TRACE("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
190         goto done;
191     }
192 
193     if (ulValueCount == 0)
194     {
195         SampRegCloseKey(&MembersKeyHandle);
196 
197         Status = SampRegDeleteKey(AliasObject->KeyHandle,
198                                   L"Members");
199         if (!NT_SUCCESS(Status))
200         {
201             TRACE("SampRegDeleteKey failed with status 0x%08lx\n", Status);
202             goto done;
203         }
204     }
205 
206 done:
207     SampRegCloseKey(&MemberKeyHandle);
208     SampRegCloseKey(&MembersKeyHandle);
209 
210     if (MemberIdString != NULL)
211         LocalFree(MemberIdString);
212 
213     return Status;
214 }
215 
216 
217 NTSTATUS
218 SampGetMembersInAlias(IN PSAM_DB_OBJECT AliasObject,
219                       OUT PULONG MemberCount,
220                       OUT PSAMPR_SID_INFORMATION *MemberArray)
221 {
222     HANDLE MembersKeyHandle = NULL;
223     PSAMPR_SID_INFORMATION Members = NULL;
224     ULONG Count = 0;
225     ULONG DataLength;
226     ULONG Index;
227     NTSTATUS Status;
228 
229     /* Open the members key of the alias object */
230     Status = SampRegOpenKey(AliasObject->KeyHandle,
231                             L"Members",
232                             KEY_READ,
233                             &MembersKeyHandle);
234     if (!NT_SUCCESS(Status))
235     {
236         ERR("SampRegOpenKey failed with status 0x%08lx\n", Status);
237         goto done;
238     }
239 
240     /* Get the number of members */
241     Status = SampRegQueryKeyInfo(MembersKeyHandle,
242                                  NULL,
243                                  &Count);
244     if (!NT_SUCCESS(Status))
245     {
246         ERR("SampRegQueryKeyInfo failed with status 0x%08lx\n", Status);
247         goto done;
248     }
249 
250     /* Allocate the member array */
251     Members = midl_user_allocate(Count * sizeof(SAMPR_SID_INFORMATION));
252     if (Members == NULL)
253     {
254         Status = STATUS_INSUFFICIENT_RESOURCES;
255         goto done;
256     }
257 
258     /* Enumerate the members */
259     Index = 0;
260     while (TRUE)
261     {
262         /* Get the size of the next SID */
263         DataLength = 0;
264         Status = SampRegEnumerateValue(MembersKeyHandle,
265                                        Index,
266                                        NULL,
267                                        NULL,
268                                        NULL,
269                                        NULL,
270                                        &DataLength);
271         if (!NT_SUCCESS(Status))
272         {
273             if (Status == STATUS_NO_MORE_ENTRIES)
274                 Status = STATUS_SUCCESS;
275             break;
276         }
277 
278         /* Allocate a buffer for the SID */
279         Members[Index].SidPointer = midl_user_allocate(DataLength);
280         if (Members[Index].SidPointer == NULL)
281         {
282             Status = STATUS_INSUFFICIENT_RESOURCES;
283             goto done;
284         }
285 
286         /* Read the SID into the buffer */
287         Status = SampRegEnumerateValue(MembersKeyHandle,
288                                        Index,
289                                        NULL,
290                                        NULL,
291                                        NULL,
292                                        (PVOID)Members[Index].SidPointer,
293                                        &DataLength);
294         if (!NT_SUCCESS(Status))
295         {
296             goto done;
297         }
298 
299         Index++;
300     }
301 
302     if (NT_SUCCESS(Status))
303     {
304         *MemberCount = Count;
305         *MemberArray = Members;
306     }
307 
308 done:
309     return Status;
310 }
311 
312 
313 NTSTATUS
314 SampRemoveAllMembersFromAlias(IN PSAM_DB_OBJECT AliasObject)
315 {
316     HANDLE MembersKeyHandle = NULL;
317     PSAMPR_SID_INFORMATION MemberArray = NULL;
318     ULONG MemberCount = 0;
319     ULONG Index;
320     NTSTATUS Status;
321 
322     TRACE("(%p)\n", AliasObject);
323 
324     /* Open the members key of the alias object */
325     Status = SampRegOpenKey(AliasObject->KeyHandle,
326                             L"Members",
327                             KEY_READ,
328                             &MembersKeyHandle);
329     if (!NT_SUCCESS(Status))
330     {
331         ERR("SampRegOpenKey failed (Status 0x%08lx)\n", Status);
332         goto done;
333     }
334 
335     /* Get a list of all members of the alias */
336     Status = SampGetMembersInAlias(AliasObject,
337                                    &MemberCount,
338                                    &MemberArray);
339     if (!NT_SUCCESS(Status))
340     {
341         ERR("SampGetMembersInAlias failed (Status 0x%08lx)\n", Status);
342         goto done;
343     }
344 
345     /* Remove all members from the alias */
346     for (Index = 0; Index < MemberCount; Index++)
347     {
348         Status = SampRemoveMemberFromAlias(AliasObject,
349                                            MemberArray[Index].SidPointer);
350         if (!NT_SUCCESS(Status))
351             goto done;
352     }
353 
354 done:
355     if (MemberArray != NULL)
356     {
357         for (Index = 0; Index < MemberCount; Index++)
358         {
359             if (MemberArray[Index].SidPointer != NULL)
360                 midl_user_free(MemberArray[Index].SidPointer);
361         }
362 
363         midl_user_free(MemberArray);
364     }
365 
366     SampRegCloseKey(&MembersKeyHandle);
367 
368     return Status;
369 }
370 
371 /* EOF */
372