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