c7b770c7131864f2f918b8a1e08538b08d2dec56
[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 LsapCreateDatabaseKeys(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 Done:
184 if (SecretsKeyHandle != NULL)
185 NtClose(SecretsKeyHandle);
186
187 if (DomainsKeyHandle != NULL)
188 NtClose(DomainsKeyHandle);
189
190 if (AccountsKeyHandle != NULL)
191 NtClose(AccountsKeyHandle);
192
193 if (PolicyKeyHandle != NULL)
194 NtClose(PolicyKeyHandle);
195
196 TRACE("LsapInstallDatabase() done (Status: 0x%08lx)\n", Status);
197
198 return Status;
199 }
200
201
202 static NTSTATUS
203 LsapCreateDatabaseObjects(VOID)
204 {
205 PLSA_DB_OBJECT PolicyObject;
206 NTSTATUS Status;
207
208 /* Open the 'Policy' object */
209 Status = LsapOpenDbObject(NULL,
210 L"Policy",
211 LsaDbPolicyObject,
212 0,
213 &PolicyObject);
214 if (!NT_SUCCESS(Status))
215 return Status;
216
217 LsapSetObjectAttribute(PolicyObject,
218 L"PolPrDmN",
219 NULL,
220 0);
221
222 LsapSetObjectAttribute(PolicyObject,
223 L"PolPrDmS",
224 NULL,
225 0);
226
227 LsapSetObjectAttribute(PolicyObject,
228 L"PolAcDmN",
229 NULL,
230 0);
231
232 LsapSetObjectAttribute(PolicyObject,
233 L"PolAcDmS",
234 NULL,
235 0);
236
237 /* Close the 'Policy' object */
238 LsapCloseDbObject(PolicyObject);
239
240 return STATUS_SUCCESS;
241 }
242
243
244 static NTSTATUS
245 LsapUpdateDatabase(VOID)
246 {
247 return STATUS_SUCCESS;
248 }
249
250
251 NTSTATUS
252 LsapInitDatabase(VOID)
253 {
254 NTSTATUS Status;
255
256 TRACE("LsapInitDatabase()\n");
257
258 Status = LsapOpenServiceKey();
259 if (!NT_SUCCESS(Status))
260 {
261 ERR("Failed to open the service key (Status: 0x%08lx)\n", Status);
262 return Status;
263 }
264
265 if (!LsapIsDatabaseInstalled())
266 {
267 Status = LsapCreateDatabaseKeys();
268 if (!NT_SUCCESS(Status))
269 {
270 ERR("Failed to create the LSA database keys (Status: 0x%08lx)\n", Status);
271 return Status;
272 }
273
274 Status = LsapCreateDatabaseObjects();
275 if (!NT_SUCCESS(Status))
276 {
277 ERR("Failed to create the LSA database objects (Status: 0x%08lx)\n", Status);
278 return Status;
279 }
280 }
281 else
282 {
283 Status = LsapUpdateDatabase();
284 if (!NT_SUCCESS(Status))
285 {
286 ERR("Failed to update the LSA database (Status: 0x%08lx)\n", Status);
287 return Status;
288 }
289 }
290
291 TRACE("LsapInitDatabase() done\n");
292
293 return STATUS_SUCCESS;
294 }
295
296
297 NTSTATUS
298 LsapCreateDbObject(IN PLSA_DB_OBJECT ParentObject,
299 IN LPWSTR ObjectName,
300 IN LSA_DB_OBJECT_TYPE ObjectType,
301 IN ACCESS_MASK DesiredAccess,
302 OUT PLSA_DB_OBJECT *DbObject)
303 {
304 PLSA_DB_OBJECT NewObject;
305 OBJECT_ATTRIBUTES ObjectAttributes;
306 UNICODE_STRING KeyName;
307 HANDLE ParentKeyHandle;
308 HANDLE ObjectKeyHandle;
309 NTSTATUS Status;
310
311 if (DbObject == NULL)
312 return STATUS_INVALID_PARAMETER;
313
314 if (ParentObject == NULL)
315 ParentKeyHandle = SecurityKeyHandle;
316 else
317 ParentKeyHandle = ParentObject->KeyHandle;
318
319 RtlInitUnicodeString(&KeyName,
320 ObjectName);
321
322 InitializeObjectAttributes(&ObjectAttributes,
323 &KeyName,
324 OBJ_CASE_INSENSITIVE,
325 ParentKeyHandle,
326 NULL);
327
328 Status = NtCreateKey(&ObjectKeyHandle,
329 KEY_ALL_ACCESS,
330 &ObjectAttributes,
331 0,
332 NULL,
333 0,
334 NULL);
335 if (!NT_SUCCESS(Status))
336 {
337 return Status;
338 }
339
340 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
341 0,
342 sizeof(LSA_DB_OBJECT));
343 if (NewObject == NULL)
344 {
345 NtClose(ObjectKeyHandle);
346 return STATUS_NO_MEMORY;
347 }
348
349 NewObject->Signature = LSAP_DB_SIGNATURE;
350 NewObject->RefCount = 1;
351 NewObject->ObjectType = ObjectType;
352 NewObject->Access = DesiredAccess;
353 NewObject->KeyHandle = ObjectKeyHandle;
354 NewObject->ParentObject = ParentObject;
355
356 if (ParentObject != NULL)
357 ParentObject->RefCount++;
358
359 *DbObject = NewObject;
360
361 return STATUS_SUCCESS;
362 }
363
364
365 NTSTATUS
366 LsapOpenDbObject(IN PLSA_DB_OBJECT ParentObject,
367 IN LPWSTR ObjectName,
368 IN LSA_DB_OBJECT_TYPE ObjectType,
369 IN ACCESS_MASK DesiredAccess,
370 OUT PLSA_DB_OBJECT *DbObject)
371 {
372 PLSA_DB_OBJECT NewObject;
373 OBJECT_ATTRIBUTES ObjectAttributes;
374 UNICODE_STRING KeyName;
375 HANDLE ParentKeyHandle;
376 HANDLE ObjectKeyHandle;
377 NTSTATUS Status;
378
379 if (DbObject == NULL)
380 return STATUS_INVALID_PARAMETER;
381
382 if (ParentObject == NULL)
383 ParentKeyHandle = SecurityKeyHandle;
384 else
385 ParentKeyHandle = ParentObject->KeyHandle;
386
387 RtlInitUnicodeString(&KeyName,
388 ObjectName);
389
390 InitializeObjectAttributes(&ObjectAttributes,
391 &KeyName,
392 OBJ_CASE_INSENSITIVE,
393 ParentKeyHandle,
394 NULL);
395
396 Status = NtOpenKey(&ObjectKeyHandle,
397 KEY_ALL_ACCESS,
398 &ObjectAttributes);
399 if (!NT_SUCCESS(Status))
400 {
401 return Status;
402 }
403
404 NewObject = RtlAllocateHeap(RtlGetProcessHeap(),
405 0,
406 sizeof(LSA_DB_OBJECT));
407 if (NewObject == NULL)
408 {
409 NtClose(ObjectKeyHandle);
410 return STATUS_NO_MEMORY;
411 }
412
413 NewObject->Signature = LSAP_DB_SIGNATURE;
414 NewObject->RefCount = 1;
415 NewObject->ObjectType = ObjectType;
416 NewObject->Access = DesiredAccess;
417 NewObject->KeyHandle = ObjectKeyHandle;
418 NewObject->ParentObject = ParentObject;
419
420 if (ParentObject != NULL)
421 ParentObject->RefCount++;
422
423 *DbObject = NewObject;
424
425 return STATUS_SUCCESS;
426 }
427
428
429 NTSTATUS
430 LsapValidateDbObject(LSAPR_HANDLE Handle,
431 LSA_DB_OBJECT_TYPE ObjectType,
432 ACCESS_MASK DesiredAccess,
433 PLSA_DB_OBJECT *DbObject)
434 {
435 PLSA_DB_OBJECT LocalObject = (PLSA_DB_OBJECT)Handle;
436 BOOLEAN bValid = FALSE;
437
438 _SEH2_TRY
439 {
440 if (LocalObject->Signature == LSAP_DB_SIGNATURE)
441 {
442 if ((ObjectType == LsaDbIgnoreObject) ||
443 (LocalObject->ObjectType == ObjectType))
444 bValid = TRUE;
445 }
446 }
447 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
448 {
449 bValid = FALSE;
450 }
451 _SEH2_END;
452
453 if (bValid == FALSE)
454 return STATUS_INVALID_HANDLE;
455
456 if (DesiredAccess != 0)
457 {
458 /* Check for granted access rights */
459 if ((LocalObject->Access & DesiredAccess) != DesiredAccess)
460 {
461 ERR("LsapValidateDbObject access check failed %08lx %08lx\n",
462 LocalObject->Access, DesiredAccess);
463 return STATUS_ACCESS_DENIED;
464 }
465 }
466
467 if (DbObject != NULL)
468 *DbObject = LocalObject;
469
470 return STATUS_SUCCESS;
471 }
472
473
474 NTSTATUS
475 LsapCloseDbObject(PLSA_DB_OBJECT DbObject)
476 {
477 PLSA_DB_OBJECT ParentObject = NULL;
478 NTSTATUS Status = STATUS_SUCCESS;
479
480 DbObject->RefCount--;
481
482 if (DbObject->RefCount > 0)
483 return STATUS_SUCCESS;
484
485 if (DbObject->KeyHandle != NULL)
486 NtClose(DbObject->KeyHandle);
487
488 if (DbObject->ParentObject != NULL)
489 ParentObject = DbObject->ParentObject;
490
491 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
492
493 if (ParentObject != NULL)
494 {
495 ParentObject->RefCount--;
496
497 if (ParentObject->RefCount == 0)
498 Status = LsapCloseDbObject(ParentObject);
499 }
500
501 return Status;
502 }
503
504
505 NTSTATUS
506 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
507 LPWSTR AttributeName,
508 LPVOID AttributeData,
509 ULONG AttributeSize)
510 {
511 OBJECT_ATTRIBUTES ObjectAttributes;
512 UNICODE_STRING KeyName;
513 HANDLE AttributeKey;
514 NTSTATUS Status;
515
516 RtlInitUnicodeString(&KeyName,
517 AttributeName);
518
519 InitializeObjectAttributes(&ObjectAttributes,
520 &KeyName,
521 OBJ_CASE_INSENSITIVE,
522 DbObject->KeyHandle,
523 NULL);
524
525 Status = NtCreateKey(&AttributeKey,
526 KEY_SET_VALUE,
527 &ObjectAttributes,
528 0,
529 NULL,
530 REG_OPTION_NON_VOLATILE,
531 NULL);
532 if (!NT_SUCCESS(Status))
533 {
534
535 return Status;
536 }
537
538 Status = RtlpNtSetValueKey(AttributeKey,
539 REG_NONE,
540 AttributeData,
541 AttributeSize);
542
543 NtClose(AttributeKey);
544
545 return Status;
546 }
547
548
549 NTSTATUS
550 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
551 LPWSTR AttributeName,
552 LPVOID AttributeData,
553 PULONG AttributeSize)
554 {
555 OBJECT_ATTRIBUTES ObjectAttributes;
556 UNICODE_STRING KeyName;
557 HANDLE AttributeKey;
558 ULONG ValueSize;
559 NTSTATUS Status;
560
561 RtlInitUnicodeString(&KeyName,
562 AttributeName);
563
564 InitializeObjectAttributes(&ObjectAttributes,
565 &KeyName,
566 OBJ_CASE_INSENSITIVE,
567 DbObject->KeyHandle,
568 NULL);
569
570 Status = NtOpenKey(&AttributeKey,
571 KEY_QUERY_VALUE,
572 &ObjectAttributes);
573 if (!NT_SUCCESS(Status))
574 {
575 return Status;
576 }
577
578 ValueSize = *AttributeSize;
579 Status = RtlpNtQueryValueKey(AttributeKey,
580 NULL,
581 NULL,
582 &ValueSize,
583 0);
584 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
585 {
586 goto Done;
587 }
588
589 if (AttributeData == NULL || *AttributeSize == 0)
590 {
591 *AttributeSize = ValueSize;
592 Status = STATUS_SUCCESS;
593 goto Done;
594 }
595 else if (*AttributeSize < ValueSize)
596 {
597 *AttributeSize = ValueSize;
598 Status = STATUS_BUFFER_OVERFLOW;
599 goto Done;
600 }
601
602 Status = RtlpNtQueryValueKey(AttributeKey,
603 NULL,
604 AttributeData,
605 &ValueSize,
606 0);
607 if (NT_SUCCESS(Status))
608 {
609 *AttributeSize = ValueSize;
610 }
611
612 Done:
613 NtClose(AttributeKey);
614
615 return Status;
616 }
617
618 /* EOF */
619