xref: /reactos/dll/win32/advapi32/misc/logon.c (revision 321bcc05)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS system libraries
4  * FILE:        lib/advapi32/misc/logon.c
5  * PURPOSE:     Logon functions
6  * PROGRAMMER:  Eric Kohl
7  */
8 
9 #include <advapi32.h>
10 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
11 
12 /* GLOBALS *****************************************************************/
13 
14 HANDLE LsaHandle = NULL;
15 ULONG AuthenticationPackage = 0;
16 
17 /* FUNCTIONS ***************************************************************/
18 
19 static
20 NTSTATUS
21 OpenLogonLsaHandle(VOID)
22 {
23     LSA_STRING LogonProcessName;
24     LSA_STRING PackageName;
25     LSA_OPERATIONAL_MODE SecurityMode = 0;
26     NTSTATUS Status;
27 
28     RtlInitAnsiString((PANSI_STRING)&LogonProcessName,
29                       "User32LogonProcess");
30 
31     Status = LsaRegisterLogonProcess(&LogonProcessName,
32                                      &LsaHandle,
33                                      &SecurityMode);
34     if (!NT_SUCCESS(Status))
35     {
36         TRACE("LsaRegisterLogonProcess failed (Status 0x%08lx)\n", Status);
37         goto done;
38     }
39 
40     RtlInitAnsiString((PANSI_STRING)&PackageName,
41                       MSV1_0_PACKAGE_NAME);
42 
43     Status = LsaLookupAuthenticationPackage(LsaHandle,
44                                             &PackageName,
45                                             &AuthenticationPackage);
46     if (!NT_SUCCESS(Status))
47     {
48         TRACE("LsaLookupAuthenticationPackage failed (Status 0x%08lx)\n", Status);
49         goto done;
50     }
51 
52     TRACE("AuthenticationPackage: 0x%08lx\n", AuthenticationPackage);
53 
54 done:
55     if (!NT_SUCCESS(Status))
56     {
57         if (LsaHandle != NULL)
58         {
59             Status = LsaDeregisterLogonProcess(LsaHandle);
60             if (!NT_SUCCESS(Status))
61             {
62                 TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
63             }
64         }
65     }
66 
67     return Status;
68 }
69 
70 
71 NTSTATUS
72 CloseLogonLsaHandle(VOID)
73 {
74     NTSTATUS Status = STATUS_SUCCESS;
75 
76     if (LsaHandle != NULL)
77     {
78         Status = LsaDeregisterLogonProcess(LsaHandle);
79         if (!NT_SUCCESS(Status))
80         {
81             TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
82         }
83     }
84 
85     return Status;
86 }
87 
88 
89 /*
90  * @implemented
91  */
92 BOOL WINAPI
93 CreateProcessAsUserA(HANDLE hToken,
94                      LPCSTR lpApplicationName,
95                      LPSTR lpCommandLine,
96                      LPSECURITY_ATTRIBUTES lpProcessAttributes,
97                      LPSECURITY_ATTRIBUTES lpThreadAttributes,
98                      BOOL bInheritHandles,
99                      DWORD dwCreationFlags,
100                      LPVOID lpEnvironment,
101                      LPCSTR lpCurrentDirectory,
102                      LPSTARTUPINFOA lpStartupInfo,
103                      LPPROCESS_INFORMATION lpProcessInformation)
104 {
105     PROCESS_ACCESS_TOKEN AccessToken;
106     NTSTATUS Status;
107 
108     TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
109         debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
110         dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
111 
112     /* Create the process with a suspended main thread */
113     if (!CreateProcessA(lpApplicationName,
114                         lpCommandLine,
115                         lpProcessAttributes,
116                         lpThreadAttributes,
117                         bInheritHandles,
118                         dwCreationFlags | CREATE_SUSPENDED,
119                         lpEnvironment,
120                         lpCurrentDirectory,
121                         lpStartupInfo,
122                         lpProcessInformation))
123     {
124         ERR("CreateProcessA failed! GLE: %d\n", GetLastError());
125         return FALSE;
126     }
127 
128     if (hToken != NULL)
129     {
130         AccessToken.Token = hToken;
131         AccessToken.Thread = NULL;
132 
133         /* Set the new process token */
134         Status = NtSetInformationProcess(lpProcessInformation->hProcess,
135                                          ProcessAccessToken,
136                                          (PVOID)&AccessToken,
137                                          sizeof(AccessToken));
138         if (!NT_SUCCESS (Status))
139         {
140             ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
141             TerminateProcess(lpProcessInformation->hProcess, Status);
142             SetLastError(RtlNtStatusToDosError(Status));
143             return FALSE;
144         }
145     }
146 
147     /* Resume the main thread */
148     if (!(dwCreationFlags & CREATE_SUSPENDED))
149     {
150         ResumeThread(lpProcessInformation->hThread);
151     }
152 
153     return TRUE;
154 }
155 
156 
157 /*
158  * @implemented
159  */
160 BOOL WINAPI
161 CreateProcessAsUserW(HANDLE hToken,
162                      LPCWSTR lpApplicationName,
163                      LPWSTR lpCommandLine,
164                      LPSECURITY_ATTRIBUTES lpProcessAttributes,
165                      LPSECURITY_ATTRIBUTES lpThreadAttributes,
166                      BOOL bInheritHandles,
167                      DWORD dwCreationFlags,
168                      LPVOID lpEnvironment,
169                      LPCWSTR lpCurrentDirectory,
170                      LPSTARTUPINFOW lpStartupInfo,
171                      LPPROCESS_INFORMATION lpProcessInformation)
172 {
173     PROCESS_ACCESS_TOKEN AccessToken;
174     NTSTATUS Status;
175 
176     TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_w(lpApplicationName),
177         debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
178         dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
179 
180     /* Create the process with a suspended main thread */
181     if (!CreateProcessW(lpApplicationName,
182                         lpCommandLine,
183                         lpProcessAttributes,
184                         lpThreadAttributes,
185                         bInheritHandles,
186                         dwCreationFlags | CREATE_SUSPENDED,
187                         lpEnvironment,
188                         lpCurrentDirectory,
189                         lpStartupInfo,
190                         lpProcessInformation))
191     {
192         ERR("CreateProcessW failed! GLE: %d\n", GetLastError());
193         return FALSE;
194     }
195 
196     if (hToken != NULL)
197     {
198         AccessToken.Token = hToken;
199         AccessToken.Thread = NULL;
200 
201         /* Set the new process token */
202         Status = NtSetInformationProcess(lpProcessInformation->hProcess,
203                                          ProcessAccessToken,
204                                          (PVOID)&AccessToken,
205                                          sizeof(AccessToken));
206         if (!NT_SUCCESS (Status))
207         {
208             ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
209             TerminateProcess(lpProcessInformation->hProcess, Status);
210             SetLastError(RtlNtStatusToDosError(Status));
211             return FALSE;
212         }
213     }
214 
215     /* Resume the main thread */
216     if (!(dwCreationFlags & CREATE_SUSPENDED))
217     {
218         ResumeThread(lpProcessInformation->hThread);
219     }
220 
221     return TRUE;
222 }
223 
224 /*
225  * @implemented
226  */
227 BOOL WINAPI
228 LogonUserA(LPSTR lpszUsername,
229            LPSTR lpszDomain,
230            LPSTR lpszPassword,
231            DWORD dwLogonType,
232            DWORD dwLogonProvider,
233            PHANDLE phToken)
234 {
235     UNICODE_STRING UserName;
236     UNICODE_STRING Domain;
237     UNICODE_STRING Password;
238     BOOL ret = FALSE;
239 
240     UserName.Buffer = NULL;
241     Domain.Buffer = NULL;
242     Password.Buffer = NULL;
243 
244     if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
245     {
246         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
247         goto UsernameDone;
248     }
249 
250     if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
251     {
252         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
253         goto DomainDone;
254     }
255 
256     if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
257     {
258         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
259         goto PasswordDone;
260     }
261 
262     ret = LogonUserW(UserName.Buffer,
263                      Domain.Buffer,
264                      Password.Buffer,
265                      dwLogonType,
266                      dwLogonProvider,
267                      phToken);
268 
269     if (Password.Buffer != NULL)
270         RtlFreeUnicodeString(&Password);
271 
272 PasswordDone:
273     if (Domain.Buffer != NULL)
274         RtlFreeUnicodeString(&Domain);
275 
276 DomainDone:
277     if (UserName.Buffer != NULL)
278         RtlFreeUnicodeString(&UserName);
279 
280 UsernameDone:
281     return ret;
282 }
283 
284 
285 /*
286  * @implemented
287  */
288 BOOL WINAPI
289 LogonUserW(LPWSTR lpszUsername,
290            LPWSTR lpszDomain,
291            LPWSTR lpszPassword,
292            DWORD dwLogonType,
293            DWORD dwLogonProvider,
294            PHANDLE phToken)
295 {
296     SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
297     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
298     PSID LogonSid = NULL;
299     PSID LocalSid = NULL;
300     LSA_STRING OriginName;
301     UNICODE_STRING DomainName;
302     UNICODE_STRING UserName;
303     UNICODE_STRING Password;
304     PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
305     ULONG AuthInfoLength;
306     ULONG_PTR Ptr;
307     TOKEN_SOURCE TokenSource;
308     PTOKEN_GROUPS TokenGroups = NULL;
309     PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
310     ULONG ProfileBufferLength = 0;
311     LUID Luid = {0, 0};
312     LUID LogonId = {0, 0};
313     HANDLE TokenHandle = NULL;
314     QUOTA_LIMITS QuotaLimits;
315     SECURITY_LOGON_TYPE LogonType;
316     NTSTATUS SubStatus = STATUS_SUCCESS;
317     NTSTATUS Status;
318 
319     *phToken = NULL;
320 
321     switch (dwLogonType)
322     {
323         case LOGON32_LOGON_INTERACTIVE:
324             LogonType = Interactive;
325             break;
326 
327         case LOGON32_LOGON_NETWORK:
328             LogonType = Network;
329             break;
330 
331         case LOGON32_LOGON_BATCH:
332             LogonType = Batch;
333             break;
334 
335         case LOGON32_LOGON_SERVICE:
336             LogonType = Service;
337             break;
338 
339        default:
340             ERR("Invalid logon type: %ul\n", dwLogonType);
341             Status = STATUS_INVALID_PARAMETER;
342             goto done;
343     }
344 
345     if (LsaHandle == NULL)
346     {
347         Status = OpenLogonLsaHandle();
348         if (!NT_SUCCESS(Status))
349             goto done;
350     }
351 
352     RtlInitAnsiString((PANSI_STRING)&OriginName,
353                       "Advapi32 Logon");
354 
355     RtlInitUnicodeString(&DomainName,
356                          lpszDomain);
357 
358     RtlInitUnicodeString(&UserName,
359                          lpszUsername);
360 
361     RtlInitUnicodeString(&Password,
362                          lpszPassword);
363 
364     AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
365                      DomainName.MaximumLength +
366                      UserName.MaximumLength +
367                      Password.MaximumLength;
368 
369     AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
370                                HEAP_ZERO_MEMORY,
371                                AuthInfoLength);
372     if (AuthInfo == NULL)
373     {
374         Status = STATUS_INSUFFICIENT_RESOURCES;
375         goto done;
376     }
377 
378     AuthInfo->MessageType = MsV1_0InteractiveLogon;
379 
380     Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
381 
382     AuthInfo->LogonDomainName.Length = DomainName.Length;
383     AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
384     AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
385     if (DomainName.MaximumLength > 0)
386     {
387         RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
388                       DomainName.Buffer,
389                       DomainName.MaximumLength);
390 
391         Ptr += DomainName.MaximumLength;
392     }
393 
394     AuthInfo->UserName.Length = UserName.Length;
395     AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
396     AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
397     if (UserName.MaximumLength > 0)
398         RtlCopyMemory(AuthInfo->UserName.Buffer,
399                       UserName.Buffer,
400                       UserName.MaximumLength);
401 
402     Ptr += UserName.MaximumLength;
403 
404     AuthInfo->Password.Length = Password.Length;
405     AuthInfo->Password.MaximumLength = Password.MaximumLength;
406     AuthInfo->Password.Buffer = (PWCHAR)Ptr;
407     if (Password.MaximumLength > 0)
408         RtlCopyMemory(AuthInfo->Password.Buffer,
409                       Password.Buffer,
410                       Password.MaximumLength);
411 
412     /* Create the Logon SID*/
413     AllocateLocallyUniqueId(&LogonId);
414     Status = RtlAllocateAndInitializeSid(&SystemAuthority,
415                                          SECURITY_LOGON_IDS_RID_COUNT,
416                                          SECURITY_LOGON_IDS_RID,
417                                          LogonId.HighPart,
418                                          LogonId.LowPart,
419                                          SECURITY_NULL_RID,
420                                          SECURITY_NULL_RID,
421                                          SECURITY_NULL_RID,
422                                          SECURITY_NULL_RID,
423                                          SECURITY_NULL_RID,
424                                          &LogonSid);
425     if (!NT_SUCCESS(Status))
426         goto done;
427 
428     /* Create the Local SID*/
429     Status = RtlAllocateAndInitializeSid(&LocalAuthority,
430                                          1,
431                                          SECURITY_LOCAL_RID,
432                                          SECURITY_NULL_RID,
433                                          SECURITY_NULL_RID,
434                                          SECURITY_NULL_RID,
435                                          SECURITY_NULL_RID,
436                                          SECURITY_NULL_RID,
437                                          SECURITY_NULL_RID,
438                                          SECURITY_NULL_RID,
439                                          &LocalSid);
440     if (!NT_SUCCESS(Status))
441         goto done;
442 
443     /* Allocate and set the token groups */
444     TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
445                                   HEAP_ZERO_MEMORY,
446                                   sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
447     if (TokenGroups == NULL)
448     {
449         Status = STATUS_INSUFFICIENT_RESOURCES;
450         goto done;
451     }
452 
453     TokenGroups->GroupCount = 2;
454     TokenGroups->Groups[0].Sid = LogonSid;
455     TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
456                                         SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
457     TokenGroups->Groups[1].Sid = LocalSid;
458     TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
459                                         SE_GROUP_ENABLED_BY_DEFAULT;
460 
461     /* Set the token source */
462     strncpy(TokenSource.SourceName, "Advapi  ", sizeof(TokenSource.SourceName));
463     AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
464 
465     Status = LsaLogonUser(LsaHandle,
466                           &OriginName,
467                           LogonType,
468                           AuthenticationPackage,
469                           (PVOID)AuthInfo,
470                           AuthInfoLength,
471                           TokenGroups,
472                           &TokenSource,
473                           (PVOID*)&ProfileBuffer,
474                           &ProfileBufferLength,
475                           &Luid,
476                           &TokenHandle,
477                           &QuotaLimits,
478                           &SubStatus);
479     if (!NT_SUCCESS(Status))
480     {
481         ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
482         goto done;
483     }
484 
485     if (ProfileBuffer != NULL)
486     {
487         TRACE("ProfileBuffer: %p\n", ProfileBuffer);
488         TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
489 
490         TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
491         TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
492 
493         TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
494         TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
495     }
496 
497     TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
498 
499     if (TokenHandle != NULL)
500     {
501         TRACE("TokenHandle: %p\n", TokenHandle);
502     }
503 
504     *phToken = TokenHandle;
505 
506 done:
507     if (ProfileBuffer != NULL)
508         LsaFreeReturnBuffer(ProfileBuffer);
509 
510     if (!NT_SUCCESS(Status))
511     {
512         if (TokenHandle != NULL)
513             CloseHandle(TokenHandle);
514     }
515 
516     if (TokenGroups != NULL)
517         RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
518 
519     if (LocalSid != NULL)
520         RtlFreeSid(LocalSid);
521 
522     if (LogonSid != NULL)
523         RtlFreeSid(LogonSid);
524 
525     if (AuthInfo != NULL)
526         RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
527 
528     if (!NT_SUCCESS(Status))
529     {
530         SetLastError(RtlNtStatusToDosError(Status));
531         return FALSE;
532     }
533 
534     return TRUE;
535 }
536 
537 /* EOF */
538