migrate substitution keywords to SVN
[reactos.git] / reactos / lib / samlib / samlib.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * PURPOSE: SAM interface library
24 * FILE: lib/samlib/samlib.c
25 * PROGRAMER: Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <windows.h>
31 #include <string.h>
32
33 #include <samlib.h>
34
35
36 #define NDEBUG
37 #include "debug.h"
38
39
40 /* GLOBALS *******************************************************************/
41
42
43 /* FUNCTIONS *****************************************************************/
44
45
46 static BOOL
47 CreateBuiltinAliases (HKEY hAliasesKey)
48 {
49 return TRUE;
50 }
51
52
53 static BOOL
54 CreateBuiltinGroups (HKEY hGroupsKey)
55 {
56 return TRUE;
57 }
58
59
60 static BOOL
61 CreateBuiltinUsers (HKEY hUsersKey)
62 {
63 return TRUE;
64 }
65
66
67 BOOL STDCALL
68 SamInitializeSAM (VOID)
69 {
70 DWORD dwDisposition;
71 HKEY hSamKey;
72 HKEY hDomainsKey;
73 HKEY hAccountKey;
74 HKEY hBuiltinKey;
75 HKEY hAliasesKey;
76 HKEY hGroupsKey;
77 HKEY hUsersKey;
78
79 DPRINT("SamInitializeSAM() called\n");
80
81 if (RegCreateKeyExW (HKEY_LOCAL_MACHINE,
82 L"SAM\\SAM",
83 0,
84 NULL,
85 REG_OPTION_NON_VOLATILE,
86 KEY_ALL_ACCESS,
87 NULL,
88 &hSamKey,
89 &dwDisposition))
90 {
91 DPRINT1 ("Failed to create 'Sam' key! (Error %lu)\n", GetLastError());
92 return FALSE;
93 }
94
95 if (RegCreateKeyExW (hSamKey,
96 L"Domains",
97 0,
98 NULL,
99 REG_OPTION_NON_VOLATILE,
100 KEY_ALL_ACCESS,
101 NULL,
102 &hDomainsKey,
103 &dwDisposition))
104 {
105 DPRINT1 ("Failed to create 'Domains' key! (Error %lu)\n", GetLastError());
106 RegCloseKey (hSamKey);
107 return FALSE;
108 }
109
110 RegCloseKey (hSamKey);
111
112 /* Create the 'Domains\\Account' key */
113 if (RegCreateKeyExW (hDomainsKey,
114 L"Account",
115 0,
116 NULL,
117 REG_OPTION_NON_VOLATILE,
118 KEY_ALL_ACCESS,
119 NULL,
120 &hAccountKey,
121 &dwDisposition))
122 {
123 DPRINT1 ("Failed to create 'Domains\\Account' key! (Error %lu)\n", GetLastError());
124 RegCloseKey (hDomainsKey);
125 return FALSE;
126 }
127
128
129 /* Create the 'Account\Aliases' key */
130 if (RegCreateKeyExW (hAccountKey,
131 L"Aliases",
132 0,
133 NULL,
134 REG_OPTION_NON_VOLATILE,
135 KEY_ALL_ACCESS,
136 NULL,
137 &hAliasesKey,
138 &dwDisposition))
139 {
140 DPRINT1 ("Failed to create 'Account\\Aliases' key! (Error %lu)\n", GetLastError());
141 RegCloseKey (hAccountKey);
142 RegCloseKey (hDomainsKey);
143 return FALSE;
144 }
145
146 RegCloseKey (hAliasesKey);
147
148
149 /* Create the 'Account\Groups' key */
150 if (RegCreateKeyExW (hAccountKey,
151 L"Groups",
152 0,
153 NULL,
154 REG_OPTION_NON_VOLATILE,
155 KEY_ALL_ACCESS,
156 NULL,
157 &hGroupsKey,
158 &dwDisposition))
159 {
160 DPRINT1 ("Failed to create 'Account\\Groups' key! (Error %lu)\n", GetLastError());
161 RegCloseKey (hAccountKey);
162 RegCloseKey (hDomainsKey);
163 return FALSE;
164 }
165
166 RegCloseKey (hGroupsKey);
167
168
169 /* Create the 'Account\Users' key */
170 if (RegCreateKeyExW (hAccountKey,
171 L"Users",
172 0,
173 NULL,
174 REG_OPTION_NON_VOLATILE,
175 KEY_ALL_ACCESS,
176 NULL,
177 &hUsersKey,
178 &dwDisposition))
179 {
180 DPRINT1 ("Failed to create 'Account\\Users' key! (Error %lu)\n", GetLastError());
181 RegCloseKey (hAccountKey);
182 RegCloseKey (hDomainsKey);
183 return FALSE;
184 }
185
186 RegCloseKey (hUsersKey);
187
188 RegCloseKey (hAccountKey);
189
190
191 /* Create the 'Domains\\Builtin' */
192 if (RegCreateKeyExW (hDomainsKey,
193 L"Builtin",
194 0,
195 NULL,
196 REG_OPTION_NON_VOLATILE,
197 KEY_ALL_ACCESS,
198 NULL,
199 &hBuiltinKey,
200 &dwDisposition))
201 {
202 DPRINT1 ("Failed to create Builtin key! (Error %lu)\n", GetLastError());
203 RegCloseKey (hDomainsKey);
204 return FALSE;
205 }
206
207
208 /* Create the 'Builtin\Aliases' key */
209 if (RegCreateKeyExW (hBuiltinKey,
210 L"Aliases",
211 0,
212 NULL,
213 REG_OPTION_NON_VOLATILE,
214 KEY_ALL_ACCESS,
215 NULL,
216 &hAliasesKey,
217 &dwDisposition))
218 {
219 DPRINT1 ("Failed to create 'Builtin\\Aliases' key! (Error %lu)\n", GetLastError());
220 RegCloseKey (hBuiltinKey);
221 RegCloseKey (hDomainsKey);
222 return FALSE;
223 }
224
225 /* Create builtin aliases */
226 if (!CreateBuiltinAliases (hAliasesKey))
227 {
228 DPRINT1 ("Failed to create builtin aliases!\n");
229 RegCloseKey (hAliasesKey);
230 RegCloseKey (hBuiltinKey);
231 RegCloseKey (hDomainsKey);
232 return FALSE;
233 }
234
235 RegCloseKey (hAliasesKey);
236
237
238 /* Create the 'Builtin\Groups' key */
239 if (RegCreateKeyExW (hBuiltinKey,
240 L"Groups",
241 0,
242 NULL,
243 REG_OPTION_NON_VOLATILE,
244 KEY_ALL_ACCESS,
245 NULL,
246 &hGroupsKey,
247 &dwDisposition))
248 {
249 DPRINT1 ("Failed to create 'Builtin\\Groups' key! (Error %lu)\n", GetLastError());
250 RegCloseKey (hBuiltinKey);
251 RegCloseKey (hDomainsKey);
252 return FALSE;
253 }
254
255 /* Create builtin groups */
256 if (!CreateBuiltinGroups (hGroupsKey))
257 {
258 DPRINT1 ("Failed to create builtin groups!\n");
259 RegCloseKey (hGroupsKey);
260 RegCloseKey (hBuiltinKey);
261 RegCloseKey (hDomainsKey);
262 return FALSE;
263 }
264
265 RegCloseKey (hGroupsKey);
266
267
268 /* Create the 'Builtin\Users' key */
269 if (RegCreateKeyExW (hBuiltinKey,
270 L"Users",
271 0,
272 NULL,
273 REG_OPTION_NON_VOLATILE,
274 KEY_ALL_ACCESS,
275 NULL,
276 &hUsersKey,
277 &dwDisposition))
278 {
279 DPRINT1 ("Failed to create 'Builtin\\Users' key! (Error %lu)\n", GetLastError());
280 RegCloseKey (hBuiltinKey);
281 RegCloseKey (hDomainsKey);
282 return FALSE;
283 }
284
285 /* Create builtin users */
286 if (!CreateBuiltinUsers (hUsersKey))
287 {
288 DPRINT1 ("Failed to create builtin users!\n");
289 RegCloseKey (hUsersKey);
290 RegCloseKey (hBuiltinKey);
291 RegCloseKey (hDomainsKey);
292 return FALSE;
293 }
294
295 RegCloseKey (hUsersKey);
296
297 RegCloseKey (hBuiltinKey);
298
299 RegCloseKey (hDomainsKey);
300
301 DPRINT ("SamInitializeSAM() done\n");
302
303 return TRUE;
304 }
305
306
307 BOOL STDCALL
308 SamGetDomainSid (PSID *Sid)
309 {
310 DPRINT ("SamGetDomainSid() called\n");
311
312 return FALSE;
313 }
314
315
316 BOOL STDCALL
317 SamSetDomainSid (PSID Sid)
318 {
319 HKEY hAccountKey;
320
321 DPRINT ("SamSetDomainSid() called\n");
322
323 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
324 L"SAM\\SAM\\Domains\\Account",
325 0,
326 KEY_ALL_ACCESS,
327 &hAccountKey))
328 {
329 DPRINT1 ("Failed to open the Account key! (Error %lu)\n", GetLastError());
330 return FALSE;
331 }
332
333 if (RegSetValueExW (hAccountKey,
334 L"Sid",
335 0,
336 REG_BINARY,
337 (LPBYTE)Sid,
338 RtlLengthSid (Sid)))
339 {
340 DPRINT1 ("Failed to set Domain-SID value! (Error %lu)\n", GetLastError());
341 RegCloseKey (hAccountKey);
342 return FALSE;
343 }
344
345 RegCloseKey (hAccountKey);
346
347 DPRINT ("SamSetDomainSid() called\n");
348
349 return TRUE;
350 }
351
352
353 /*
354 * ERROR_USER_EXISTS
355 */
356 BOOL STDCALL
357 SamCreateUser (PWSTR UserName,
358 PWSTR UserPassword,
359 PSID UserSid)
360 {
361 DWORD dwDisposition;
362 HKEY hUsersKey;
363 HKEY hUserKey;
364
365 DPRINT ("SamCreateUser() called\n");
366
367 /* FIXME: Check whether the SID is a real user sid */
368
369 /* Open the Users key */
370 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
371 L"SAM\\SAM\\Domains\\Account\\Users",
372 0,
373 KEY_ALL_ACCESS,
374 &hUsersKey))
375 {
376 DPRINT1 ("Failed to open Account key! (Error %lu)\n", GetLastError());
377 return FALSE;
378 }
379
380 /* Create user name key */
381 if (RegCreateKeyExW (hUsersKey,
382 UserName,
383 0,
384 NULL,
385 REG_OPTION_NON_VOLATILE,
386 KEY_ALL_ACCESS,
387 NULL,
388 &hUserKey,
389 &dwDisposition))
390 {
391 DPRINT1 ("Failed to create/open the user key! (Error %lu)\n", GetLastError());
392 RegCloseKey (hUsersKey);
393 return FALSE;
394 }
395
396 RegCloseKey (hUsersKey);
397
398 if (dwDisposition == REG_OPENED_EXISTING_KEY)
399 {
400 DPRINT1 ("User already exists!\n");
401 RegCloseKey (hUserKey);
402 SetLastError (ERROR_USER_EXISTS);
403 return FALSE;
404 }
405
406
407 /* Set 'Name' value */
408 if (RegSetValueExW (hUserKey,
409 L"Name",
410 0,
411 REG_SZ,
412 (LPBYTE)UserName,
413 (wcslen (UserName) + 1) * sizeof (WCHAR)))
414 {
415 DPRINT1 ("Failed to set the user name value! (Error %lu)\n", GetLastError());
416 RegCloseKey (hUserKey);
417 return FALSE;
418 }
419
420 /* Set 'Password' value */
421 if (RegSetValueExW (hUserKey,
422 L"Password",
423 0,
424 REG_SZ,
425 (LPBYTE)UserPassword,
426 (wcslen (UserPassword) + 1) * sizeof (WCHAR)))
427 {
428 DPRINT1 ("Failed to set the user name value! (Error %lu)\n", GetLastError());
429 RegCloseKey (hUserKey);
430 return FALSE;
431 }
432
433 /* Set 'Sid' value */
434 if (RegSetValueExW (hUserKey,
435 L"Sid",
436 0,
437 REG_BINARY,
438 (LPBYTE)UserSid,
439 RtlLengthSid (UserSid)))
440 {
441 DPRINT1 ("Failed to set the user SID value! (Error %lu)\n", GetLastError());
442 RegCloseKey (hUserKey);
443 return FALSE;
444 }
445
446 RegCloseKey (hUserKey);
447
448 DPRINT ("SamCreateUser() done\n");
449
450 return TRUE;
451 }
452
453
454 /*
455 * ERROR_WRONG_PASSWORD
456 * ERROR_NO_SUCH_USER
457 */
458 BOOL STDCALL
459 SamCheckUserPassword (PWSTR UserName,
460 PWSTR UserPassword)
461 {
462 WCHAR szPassword[256];
463 DWORD dwLength;
464 HKEY hUsersKey;
465 HKEY hUserKey;
466
467 DPRINT ("SamCheckUserPassword() called\n");
468
469 /* Open the Users key */
470 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
471 L"SAM\\SAM\\Domains\\Account\\Users",
472 0,
473 KEY_READ,
474 &hUsersKey))
475 {
476 DPRINT1 ("Failed to open Users key! (Error %lu)\n", GetLastError());
477 return FALSE;
478 }
479
480 /* Open the user key */
481 if (RegOpenKeyExW (hUsersKey,
482 UserName,
483 0,
484 KEY_READ,
485 &hUserKey))
486 {
487 if (GetLastError () == ERROR_FILE_NOT_FOUND)
488 {
489 DPRINT1 ("Invalid user name!\n");
490 SetLastError (ERROR_NO_SUCH_USER);
491 }
492 else
493 {
494 DPRINT1 ("Failed to open user key! (Error %lu)\n", GetLastError());
495 }
496
497 RegCloseKey (hUsersKey);
498 return FALSE;
499 }
500
501 RegCloseKey (hUsersKey);
502
503 /* Get the password */
504 dwLength = 256 * sizeof(WCHAR);
505 if (RegQueryValueExW (hUserKey,
506 L"Password",
507 NULL,
508 NULL,
509 (LPBYTE)szPassword,
510 &dwLength))
511 {
512 DPRINT1 ("Failed to read the password! (Error %lu)\n", GetLastError());
513 RegCloseKey (hUserKey);
514 return FALSE;
515 }
516
517 RegCloseKey (hUserKey);
518
519 /* Compare passwords */
520 if ((wcslen (szPassword) != wcslen (UserPassword)) ||
521 (wcscmp (szPassword, UserPassword) != 0))
522 {
523 DPRINT1 ("Wrong password!\n");
524 SetLastError (ERROR_WRONG_PASSWORD);
525 return FALSE;
526 }
527
528 DPRINT ("SamCheckUserPassword() done\n");
529
530 return TRUE;
531 }
532
533
534 BOOL STDCALL
535 SamGetUserSid (PWSTR UserName,
536 PSID *Sid)
537 {
538 PSID lpSid;
539 DWORD dwLength;
540 HKEY hUsersKey;
541 HKEY hUserKey;
542
543 DPRINT ("SamGetUserSid() called\n");
544
545 if (Sid != NULL)
546 *Sid = NULL;
547
548 /* Open the Users key */
549 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
550 L"SAM\\SAM\\Domains\\Account\\Users",
551 0,
552 KEY_READ,
553 &hUsersKey))
554 {
555 DPRINT1 ("Failed to open Users key! (Error %lu)\n", GetLastError());
556 return FALSE;
557 }
558
559 /* Open the user key */
560 if (RegOpenKeyExW (hUserKey,
561 UserName,
562 0,
563 KEY_READ,
564 &hUserKey))
565 {
566 if (GetLastError () == ERROR_FILE_NOT_FOUND)
567 {
568 DPRINT1 ("Invalid user name!\n");
569 SetLastError (ERROR_NO_SUCH_USER);
570 }
571 else
572 {
573 DPRINT1 ("Failed to open user key! (Error %lu)\n", GetLastError());
574 }
575
576 RegCloseKey (hUsersKey);
577 return FALSE;
578 }
579
580 RegCloseKey (hUsersKey);
581
582 /* Get SID size */
583 dwLength = 0;
584 if (RegQueryValueExW (hUserKey,
585 L"Sid",
586 NULL,
587 NULL,
588 NULL,
589 &dwLength))
590 {
591 DPRINT1 ("Failed to read the SID size! (Error %lu)\n", GetLastError());
592 RegCloseKey (hUserKey);
593 return FALSE;
594 }
595
596 /* Allocate sid buffer */
597 DPRINT ("Required SID buffer size: %lu\n", dwLength);
598 lpSid = (PSID)RtlAllocateHeap (RtlGetProcessHeap (),
599 0,
600 dwLength);
601 if (lpSid == NULL)
602 {
603 DPRINT1 ("Failed to allocate SID buffer!\n");
604 RegCloseKey (hUserKey);
605 return FALSE;
606 }
607
608 /* Read sid */
609 if (RegQueryValueExW (hUserKey,
610 L"Sid",
611 NULL,
612 NULL,
613 (LPBYTE)lpSid,
614 &dwLength))
615 {
616 DPRINT1 ("Failed to read the SID! (Error %lu)\n", GetLastError());
617 RtlFreeHeap (RtlGetProcessHeap (),
618 0,
619 lpSid);
620 RegCloseKey (hUserKey);
621 return FALSE;
622 }
623
624 RegCloseKey (hUserKey);
625
626 *Sid = lpSid;
627
628 DPRINT ("SamGetUserSid() done\n");
629
630 return TRUE;
631 }
632
633 /* EOF */