d58d07b8ac6bcb8fc72efe5a9d6ff911b4791fbc
[reactos.git] / reactos / dll / win32 / lsasrv / database.c
1 /*
2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/lsasrv/database.c
5 * PURPOSE: LSA object database
6 * COPYRIGHT: Copyright 2011 Eric Kohl
7 */
8
9 /* INCLUDES ****************************************************************/
10
11 #include "lsasrv.h"
12
13 WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
14
15
16 /* GLOBALS *****************************************************************/
17
18 static HANDLE SecurityKeyHandle = NULL;
19
20
21 /* FUNCTIONS ***************************************************************/
22
23 static NTSTATUS
24 LsapOpenServiceKey(VOID)
25 {
26 OBJECT_ATTRIBUTES ObjectAttributes;
27 UNICODE_STRING KeyName;
28 NTSTATUS Status;
29
30 RtlInitUnicodeString(&KeyName,
31 L"\\Registry\\Machine\\SECURITY");
32
33 InitializeObjectAttributes(&ObjectAttributes,
34 &KeyName,
35 OBJ_CASE_INSENSITIVE,
36 NULL,
37 NULL);
38
39 Status = RtlpNtOpenKey(&SecurityKeyHandle,
40 KEY_READ | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS,
41 &ObjectAttributes,
42 0);
43
44 return Status;
45 }
46
47
48 static BOOLEAN
49 LsapIsDatabaseInstalled(VOID)
50 {
51 OBJECT_ATTRIBUTES ObjectAttributes;
52 UNICODE_STRING KeyName;
53 HANDLE KeyHandle;
54 NTSTATUS Status;
55
56 RtlInitUnicodeString(&KeyName,
57 L"Policy");
58
59 InitializeObjectAttributes(&ObjectAttributes,
60 &KeyName,
61 OBJ_CASE_INSENSITIVE,
62 SecurityKeyHandle,
63 NULL);
64
65 Status = RtlpNtOpenKey(&KeyHandle,
66 KEY_READ,
67 &ObjectAttributes,
68 0);
69 if (!NT_SUCCESS(Status))
70 return FALSE;
71
72 NtClose(KeyHandle);
73
74 return TRUE;
75 }
76
77
78 static NTSTATUS
79 LsapInstallDatabase(VOID)
80 {
81 OBJECT_ATTRIBUTES ObjectAttributes;
82 UNICODE_STRING KeyName;
83 HANDLE PolicyKeyHandle = NULL;
84 HANDLE AccountsKeyHandle = NULL;
85 HANDLE DomainsKeyHandle = NULL;
86 HANDLE SecretsKeyHandle = NULL;
87 NTSTATUS Status = STATUS_SUCCESS;
88
89 TRACE("LsapInstallDatabase()\n");
90
91 /* Create the 'Policy' key */
92 RtlInitUnicodeString(&KeyName,
93 L"Policy");
94
95 InitializeObjectAttributes(&ObjectAttributes,
96 &KeyName,
97 OBJ_CASE_INSENSITIVE,
98 SecurityKeyHandle,
99 NULL);
100
101 Status = NtCreateKey(&PolicyKeyHandle,
102 KEY_ALL_ACCESS,
103 &ObjectAttributes,
104 0,
105 NULL,
106 0,
107 NULL);
108 if (!NT_SUCCESS(Status))
109 {
110 ERR("Failed to create the 'Policy' key (Status: 0x%08lx)\n", Status);
111 goto Done;
112 }
113
114 /* Create the 'Accounts' key */
115 RtlInitUnicodeString(&KeyName,
116 L"Accounts");
117
118 InitializeObjectAttributes(&ObjectAttributes,
119 &KeyName,
120 OBJ_CASE_INSENSITIVE,
121 PolicyKeyHandle,
122 NULL);
123
124 Status = NtCreateKey(&AccountsKeyHandle,
125 KEY_ALL_ACCESS,
126 &ObjectAttributes,
127 0,
128 NULL,
129 0,
130 NULL);
131 if (!NT_SUCCESS(Status))
132 {
133 ERR("Failed to create the 'Accounts' key (Status: 0x%08lx)\n", Status);
134 goto Done;
135 }
136
137 /* Create the 'Domains' key */
138 RtlInitUnicodeString(&KeyName,
139 L"Domains");
140
141 InitializeObjectAttributes(&ObjectAttributes,
142 &KeyName,
143 OBJ_CASE_INSENSITIVE,
144 PolicyKeyHandle,
145 NULL);
146
147 Status = NtCreateKey(&DomainsKeyHandle,
148 KEY_ALL_ACCESS,
149 &ObjectAttributes,
150 0,
151 NULL,
152 0,
153 NULL);
154 if (!NT_SUCCESS(Status))
155 {
156 ERR("Failed to create the 'Domains' key (Status: 0x%08lx)\n", Status);
157 goto Done;
158 }
159
160 /* Create the 'Secrets' key */
161 RtlInitUnicodeString(&KeyName,
162 L"Secrets");
163
164 InitializeObjectAttributes(&ObjectAttributes,
165 &KeyName,
166 OBJ_CASE_INSENSITIVE,
167 PolicyKeyHandle,
168 NULL);
169
170 Status = NtCreateKey(&SecretsKeyHandle,
171 KEY_ALL_ACCESS,
172 &ObjectAttributes,
173 0,
174 NULL,
175 0,
176 NULL);
177 if (!NT_SUCCESS(Status))
178 {
179 ERR("Failed to create the 'Secrets' key (Status: 0x%08lx)\n", Status);
180 goto Done;
181 }
182
183
184 Done:
185 if (SecretsKeyHandle != NULL)
186 NtClose(SecretsKeyHandle);
187
188 if (DomainsKeyHandle != NULL)
189 NtClose(DomainsKeyHandle);
190
191 if (AccountsKeyHandle != NULL)
192 NtClose(AccountsKeyHandle);
193
194 if (PolicyKeyHandle != NULL)
195 NtClose(PolicyKeyHandle);
196
197 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
198
199 return Status;
200 }
201
202
203 NTSTATUS
204 LsapInitDatabase(VOID)
205 {
206 NTSTATUS Status;
207
208 TRACE("LsapInitDatabase()\n");
209
210 Status = LsapOpenServiceKey();
211 if (!NT_SUCCESS(Status))
212 {
213 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
214 return Status;
215 }
216
217 if (!LsapIsDatabaseInstalled())
218 {
219 Status = LsapInstallDatabase();
220 if (!NT_SUCCESS(Status))
221 {
222 ERR("Failed to install the LSA database (Status: 0x%08lx)\n", Status);
223 return Status;
224 }
225 }
226
227 TRACE("LsapInitDatabase() done\n");
228
229 return STATUS_SUCCESS;
230 }
231
232
233 LSAPR_HANDLE
234 LsapCreateDbObject(LSAPR_HANDLE ParentHandle,
235 LPWSTR ObjectName,
236 BOOLEAN Open,
237 LSA_DB_OBJECT_TYPE ObjectType,
238 ACCESS_MASK DesiredAccess)
239 {
240 PLSA_DB_OBJECT ParentObject = (PLSA_DB_OBJECT)ParentHandle;
241 PLSA_DB_OBJECT DbObject;
242 OBJECT_ATTRIBUTES ObjectAttributes;
243 UNICODE_STRING KeyName;
244 HANDLE ParentKeyHandle;
245 HANDLE ObjectKeyHandle;
246 NTSTATUS Status;
247
248 if (ParentHandle != NULL)
249 ParentKeyHandle = ParentObject->KeyHandle;
250 else
251 ParentKeyHandle = SecurityKeyHandle;
252
253 RtlInitUnicodeString(&KeyName,
254 ObjectName);
255
256 InitializeObjectAttributes(&ObjectAttributes,
257 &KeyName,
258 OBJ_CASE_INSENSITIVE,
259 ParentKeyHandle,
260 NULL);
261
262 if (Open == TRUE)
263 {
264 Status = NtOpenKey(&ObjectKeyHandle,
265 KEY_ALL_ACCESS,
266 &ObjectAttributes);
267 }
268 else
269 {
270 Status = NtCreateKey(&ObjectKeyHandle,
271 KEY_ALL_ACCESS,
272 &ObjectAttributes,
273 0,
274 NULL,
275 0,
276 NULL);
277 }
278
279 if (!NT_SUCCESS(Status))
280 {
281 return NULL;
282 }
283
284 DbObject = (PLSA_DB_OBJECT)RtlAllocateHeap(RtlGetProcessHeap(),
285 0,
286 sizeof(LSA_DB_OBJECT));
287 if (DbObject == NULL)
288 {
289 NtClose(ObjectKeyHandle);
290 return NULL;
291 }
292
293 DbObject->Signature = LSAP_DB_SIGNATURE;
294 DbObject->RefCount = 0;
295 DbObject->ObjectType = ObjectType;
296 DbObject->Access = DesiredAccess;
297 DbObject->KeyHandle = ObjectKeyHandle;
298 DbObject->ParentObject = ParentObject;
299
300 if (ParentObject != NULL)
301 ParentObject->RefCount++;
302
303 return (LSAPR_HANDLE)DbObject;
304 }
305
306
307 NTSTATUS
308 LsapValidateDbObject(LSAPR_HANDLE Handle,
309 LSA_DB_OBJECT_TYPE ObjectType,
310 ACCESS_MASK GrantedAccess)
311 {
312 PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
313 BOOLEAN bValid = FALSE;
314
315 _SEH2_TRY
316 {
317 if (DbObject->Signature == LSAP_DB_SIGNATURE)
318 {
319 if ((ObjectType == LsaDbIgnoreObject) ||
320 (DbObject->ObjectType == ObjectType))
321 bValid = TRUE;
322 }
323 }
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
325 {
326 bValid = FALSE;
327 }
328 _SEH2_END;
329
330 if (bValid == FALSE)
331 return STATUS_INVALID_HANDLE;
332
333 if (GrantedAccess != 0)
334 {
335 /* FIXME: Check for granted access rights */
336 }
337
338 return STATUS_SUCCESS;
339 }
340
341
342 NTSTATUS
343 LsapCloseDbObject(LSAPR_HANDLE Handle)
344 {
345 PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
346
347 if (DbObject->RefCount != 0)
348 return STATUS_UNSUCCESSFUL;
349
350 if (DbObject->ParentObject != NULL)
351 DbObject->ParentObject->RefCount--;
352
353 if (DbObject->KeyHandle != NULL)
354 NtClose(DbObject->KeyHandle);
355
356 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
357
358 return STATUS_SUCCESS;
359 }
360
361
362 NTSTATUS
363 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
364 LPWSTR AttributeName,
365 LPVOID AttributeData,
366 ULONG AttributeSize)
367 {
368 OBJECT_ATTRIBUTES ObjectAttributes;
369 UNICODE_STRING KeyName;
370 HANDLE AttributeKey;
371 NTSTATUS Status;
372
373 RtlInitUnicodeString(&KeyName,
374 AttributeName);
375
376 InitializeObjectAttributes(&ObjectAttributes,
377 &KeyName,
378 OBJ_CASE_INSENSITIVE,
379 DbObject->KeyHandle,
380 NULL);
381
382 Status = NtCreateKey(&AttributeKey,
383 KEY_SET_VALUE,
384 &ObjectAttributes,
385 0,
386 NULL,
387 REG_OPTION_NON_VOLATILE,
388 NULL);
389 if (!NT_SUCCESS(Status))
390 {
391
392 return Status;
393 }
394
395 Status = RtlpNtSetValueKey(AttributeKey,
396 REG_NONE,
397 AttributeData,
398 AttributeSize);
399
400 NtClose(AttributeKey);
401
402 return Status;
403 }
404
405
406 NTSTATUS
407 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
408 LPWSTR AttributeName,
409 LPVOID AttributeData,
410 PULONG AttributeSize)
411 {
412 OBJECT_ATTRIBUTES ObjectAttributes;
413 UNICODE_STRING KeyName;
414 HANDLE AttributeKey;
415 ULONG ValueSize;
416 NTSTATUS Status;
417
418 RtlInitUnicodeString(&KeyName,
419 AttributeName);
420
421 InitializeObjectAttributes(&ObjectAttributes,
422 &KeyName,
423 OBJ_CASE_INSENSITIVE,
424 DbObject->KeyHandle,
425 NULL);
426
427 Status = NtOpenKey(&AttributeKey,
428 KEY_QUERY_VALUE,
429 &ObjectAttributes);
430 if (!NT_SUCCESS(Status))
431 {
432 return Status;
433 }
434
435 ValueSize = *AttributeSize;
436 Status = RtlpNtQueryValueKey(AttributeKey,
437 NULL,
438 NULL,
439 &ValueSize,
440 0);
441 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
442 {
443 goto Done;
444 }
445
446 if (AttributeData == NULL || *AttributeSize == 0)
447 {
448 *AttributeSize = ValueSize;
449 Status == STATUS_SUCCESS;
450 goto Done;
451 }
452 else if (*AttributeSize < ValueSize)
453 {
454 *AttributeSize = ValueSize;
455 Status == STATUS_BUFFER_OVERFLOW;
456 goto Done;
457 }
458
459 Status = RtlpNtQueryValueKey(AttributeKey,
460 NULL,
461 AttributeData,
462 &ValueSize,
463 0);
464 if (NT_SUCCESS(Status))
465 {
466 *AttributeSize = ValueSize;
467 }
468
469 Done:
470 NtClose(AttributeKey);
471
472 return Status;
473 }
474
475 /* EOF */
476