[LSASRV] - Correctly set return values in LsapGetObjectAttribute
[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 DbObject = NULL;
206
207 /* Open the 'Policy' object */
208 DbObject = (PLSA_DB_OBJECT)LsapCreateDbObject(NULL,
209 L"Policy",
210 TRUE,
211 LsaDbPolicyObject,
212 0);
213 if (DbObject != NULL)
214 {
215 LsapSetObjectAttribute(DbObject,
216 L"PolPrDmN",
217 NULL,
218 0);
219
220 LsapSetObjectAttribute(DbObject,
221 L"PolPrDmS",
222 NULL,
223 0);
224
225 LsapSetObjectAttribute(DbObject,
226 L"PolAcDmN",
227 NULL,
228 0);
229
230 LsapSetObjectAttribute(DbObject,
231 L"PolAcDmS",
232 NULL,
233 0);
234
235
236 /* Close the 'Policy' object */
237 LsapCloseDbObject((LSAPR_HANDLE)DbObject);
238 }
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 LSAPR_HANDLE
298 LsapCreateDbObject(LSAPR_HANDLE ParentHandle,
299 LPWSTR ObjectName,
300 BOOLEAN Open,
301 LSA_DB_OBJECT_TYPE ObjectType,
302 ACCESS_MASK DesiredAccess)
303 {
304 PLSA_DB_OBJECT ParentObject = (PLSA_DB_OBJECT)ParentHandle;
305 PLSA_DB_OBJECT DbObject;
306 OBJECT_ATTRIBUTES ObjectAttributes;
307 UNICODE_STRING KeyName;
308 HANDLE ParentKeyHandle;
309 HANDLE ObjectKeyHandle;
310 NTSTATUS Status;
311
312 if (ParentHandle != NULL)
313 ParentKeyHandle = ParentObject->KeyHandle;
314 else
315 ParentKeyHandle = SecurityKeyHandle;
316
317 RtlInitUnicodeString(&KeyName,
318 ObjectName);
319
320 InitializeObjectAttributes(&ObjectAttributes,
321 &KeyName,
322 OBJ_CASE_INSENSITIVE,
323 ParentKeyHandle,
324 NULL);
325
326 if (Open == TRUE)
327 {
328 Status = NtOpenKey(&ObjectKeyHandle,
329 KEY_ALL_ACCESS,
330 &ObjectAttributes);
331 }
332 else
333 {
334 Status = NtCreateKey(&ObjectKeyHandle,
335 KEY_ALL_ACCESS,
336 &ObjectAttributes,
337 0,
338 NULL,
339 0,
340 NULL);
341 }
342
343 if (!NT_SUCCESS(Status))
344 {
345 return NULL;
346 }
347
348 DbObject = (PLSA_DB_OBJECT)RtlAllocateHeap(RtlGetProcessHeap(),
349 0,
350 sizeof(LSA_DB_OBJECT));
351 if (DbObject == NULL)
352 {
353 NtClose(ObjectKeyHandle);
354 return NULL;
355 }
356
357 DbObject->Signature = LSAP_DB_SIGNATURE;
358 DbObject->RefCount = 0;
359 DbObject->ObjectType = ObjectType;
360 DbObject->Access = DesiredAccess;
361 DbObject->KeyHandle = ObjectKeyHandle;
362 DbObject->ParentObject = ParentObject;
363
364 if (ParentObject != NULL)
365 ParentObject->RefCount++;
366
367 return (LSAPR_HANDLE)DbObject;
368 }
369
370
371 NTSTATUS
372 LsapValidateDbObject(LSAPR_HANDLE Handle,
373 LSA_DB_OBJECT_TYPE ObjectType,
374 ACCESS_MASK GrantedAccess)
375 {
376 PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
377 BOOLEAN bValid = FALSE;
378
379 _SEH2_TRY
380 {
381 if (DbObject->Signature == LSAP_DB_SIGNATURE)
382 {
383 if ((ObjectType == LsaDbIgnoreObject) ||
384 (DbObject->ObjectType == ObjectType))
385 bValid = TRUE;
386 }
387 }
388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
389 {
390 bValid = FALSE;
391 }
392 _SEH2_END;
393
394 if (bValid == FALSE)
395 return STATUS_INVALID_HANDLE;
396
397 if (GrantedAccess != 0)
398 {
399 /* FIXME: Check for granted access rights */
400 }
401
402 return STATUS_SUCCESS;
403 }
404
405
406 NTSTATUS
407 LsapCloseDbObject(LSAPR_HANDLE Handle)
408 {
409 PLSA_DB_OBJECT DbObject = (PLSA_DB_OBJECT)Handle;
410
411 if (DbObject->RefCount != 0)
412 return STATUS_UNSUCCESSFUL;
413
414 if (DbObject->ParentObject != NULL)
415 DbObject->ParentObject->RefCount--;
416
417 if (DbObject->KeyHandle != NULL)
418 NtClose(DbObject->KeyHandle);
419
420 RtlFreeHeap(RtlGetProcessHeap(), 0, DbObject);
421
422 return STATUS_SUCCESS;
423 }
424
425
426 NTSTATUS
427 LsapSetObjectAttribute(PLSA_DB_OBJECT DbObject,
428 LPWSTR AttributeName,
429 LPVOID AttributeData,
430 ULONG AttributeSize)
431 {
432 OBJECT_ATTRIBUTES ObjectAttributes;
433 UNICODE_STRING KeyName;
434 HANDLE AttributeKey;
435 NTSTATUS Status;
436
437 RtlInitUnicodeString(&KeyName,
438 AttributeName);
439
440 InitializeObjectAttributes(&ObjectAttributes,
441 &KeyName,
442 OBJ_CASE_INSENSITIVE,
443 DbObject->KeyHandle,
444 NULL);
445
446 Status = NtCreateKey(&AttributeKey,
447 KEY_SET_VALUE,
448 &ObjectAttributes,
449 0,
450 NULL,
451 REG_OPTION_NON_VOLATILE,
452 NULL);
453 if (!NT_SUCCESS(Status))
454 {
455
456 return Status;
457 }
458
459 Status = RtlpNtSetValueKey(AttributeKey,
460 REG_NONE,
461 AttributeData,
462 AttributeSize);
463
464 NtClose(AttributeKey);
465
466 return Status;
467 }
468
469
470 NTSTATUS
471 LsapGetObjectAttribute(PLSA_DB_OBJECT DbObject,
472 LPWSTR AttributeName,
473 LPVOID AttributeData,
474 PULONG AttributeSize)
475 {
476 OBJECT_ATTRIBUTES ObjectAttributes;
477 UNICODE_STRING KeyName;
478 HANDLE AttributeKey;
479 ULONG ValueSize;
480 NTSTATUS Status;
481
482 RtlInitUnicodeString(&KeyName,
483 AttributeName);
484
485 InitializeObjectAttributes(&ObjectAttributes,
486 &KeyName,
487 OBJ_CASE_INSENSITIVE,
488 DbObject->KeyHandle,
489 NULL);
490
491 Status = NtOpenKey(&AttributeKey,
492 KEY_QUERY_VALUE,
493 &ObjectAttributes);
494 if (!NT_SUCCESS(Status))
495 {
496 return Status;
497 }
498
499 ValueSize = *AttributeSize;
500 Status = RtlpNtQueryValueKey(AttributeKey,
501 NULL,
502 NULL,
503 &ValueSize,
504 0);
505 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
506 {
507 goto Done;
508 }
509
510 if (AttributeData == NULL || *AttributeSize == 0)
511 {
512 *AttributeSize = ValueSize;
513 Status = STATUS_SUCCESS;
514 goto Done;
515 }
516 else if (*AttributeSize < ValueSize)
517 {
518 *AttributeSize = ValueSize;
519 Status = STATUS_BUFFER_OVERFLOW;
520 goto Done;
521 }
522
523 Status = RtlpNtQueryValueKey(AttributeKey,
524 NULL,
525 AttributeData,
526 &ValueSize,
527 0);
528 if (NT_SUCCESS(Status))
529 {
530 *AttributeSize = ValueSize;
531 }
532
533 Done:
534 NtClose(AttributeKey);
535
536 return Status;
537 }
538
539 /* EOF */
540