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