xref: /reactos/dll/win32/advapi32/misc/logon.c (revision 527f2f90)
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     /* Create the process with a suspended main thread */
109     if (!CreateProcessA(lpApplicationName,
110                         lpCommandLine,
111                         lpProcessAttributes,
112                         lpThreadAttributes,
113                         bInheritHandles,
114                         dwCreationFlags | CREATE_SUSPENDED,
115                         lpEnvironment,
116                         lpCurrentDirectory,
117                         lpStartupInfo,
118                         lpProcessInformation))
119     {
120         return FALSE;
121     }
122 
123     AccessToken.Token = hToken;
124     AccessToken.Thread = NULL;
125 
126     /* Set the new process token */
127     Status = NtSetInformationProcess(lpProcessInformation->hProcess,
128                                      ProcessAccessToken,
129                                      (PVOID)&AccessToken,
130                                      sizeof(AccessToken));
131     if (!NT_SUCCESS (Status))
132     {
133         SetLastError(RtlNtStatusToDosError(Status));
134         return FALSE;
135     }
136 
137     /* Resume the main thread */
138     if (!(dwCreationFlags & CREATE_SUSPENDED))
139     {
140         ResumeThread(lpProcessInformation->hThread);
141     }
142 
143     return TRUE;
144 }
145 
146 
147 /*
148  * @implemented
149  */
150 BOOL WINAPI
151 CreateProcessAsUserW(HANDLE hToken,
152                      LPCWSTR lpApplicationName,
153                      LPWSTR lpCommandLine,
154                      LPSECURITY_ATTRIBUTES lpProcessAttributes,
155                      LPSECURITY_ATTRIBUTES lpThreadAttributes,
156                      BOOL bInheritHandles,
157                      DWORD dwCreationFlags,
158                      LPVOID lpEnvironment,
159                      LPCWSTR lpCurrentDirectory,
160                      LPSTARTUPINFOW lpStartupInfo,
161                      LPPROCESS_INFORMATION lpProcessInformation)
162 {
163     PROCESS_ACCESS_TOKEN AccessToken;
164     NTSTATUS Status;
165 
166     /* Create the process with a suspended main thread */
167     if (!CreateProcessW(lpApplicationName,
168                         lpCommandLine,
169                         lpProcessAttributes,
170                         lpThreadAttributes,
171                         bInheritHandles,
172                         dwCreationFlags | CREATE_SUSPENDED,
173                         lpEnvironment,
174                         lpCurrentDirectory,
175                         lpStartupInfo,
176                         lpProcessInformation))
177     {
178         return FALSE;
179     }
180 
181     AccessToken.Token = hToken;
182     AccessToken.Thread = NULL;
183 
184     /* Set the new process token */
185     Status = NtSetInformationProcess(lpProcessInformation->hProcess,
186                                      ProcessAccessToken,
187                                      (PVOID)&AccessToken,
188                                      sizeof(AccessToken));
189     if (!NT_SUCCESS (Status))
190     {
191         SetLastError(RtlNtStatusToDosError(Status));
192         return FALSE;
193     }
194 
195     /* Resume the main thread */
196     if (!(dwCreationFlags & CREATE_SUSPENDED))
197     {
198         ResumeThread(lpProcessInformation->hThread);
199     }
200 
201     return TRUE;
202 }
203 
204 /*
205  * @unimplemented
206  */
207 BOOL WINAPI
208 CreateProcessWithLogonW(LPCWSTR lpUsername,
209                         LPCWSTR lpDomain,
210                         LPCWSTR lpPassword,
211                         DWORD dwLogonFlags,
212                         LPCWSTR lpApplicationName,
213                         LPWSTR lpCommandLine,
214                         DWORD dwCreationFlags,
215                         LPVOID lpEnvironment,
216                         LPCWSTR lpCurrentDirectory,
217                         LPSTARTUPINFOW lpStartupInfo,
218                         LPPROCESS_INFORMATION lpProcessInformation)
219 {
220     FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain),
221     debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName),
222     debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
223     lpStartupInfo, lpProcessInformation);
224 
225     return FALSE;
226 }
227 
228 /*
229  * @implemented
230  */
231 BOOL WINAPI
232 LogonUserA(LPSTR lpszUsername,
233            LPSTR lpszDomain,
234            LPSTR lpszPassword,
235            DWORD dwLogonType,
236            DWORD dwLogonProvider,
237            PHANDLE phToken)
238 {
239     UNICODE_STRING UserName;
240     UNICODE_STRING Domain;
241     UNICODE_STRING Password;
242     BOOL ret = FALSE;
243 
244     UserName.Buffer = NULL;
245     Domain.Buffer = NULL;
246     Password.Buffer = NULL;
247 
248     if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
249     {
250         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
251         goto UsernameDone;
252     }
253 
254     if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
255     {
256         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
257         goto DomainDone;
258     }
259 
260     if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
261     {
262         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
263         goto PasswordDone;
264     }
265 
266     ret = LogonUserW(UserName.Buffer,
267                      Domain.Buffer,
268                      Password.Buffer,
269                      dwLogonType,
270                      dwLogonProvider,
271                      phToken);
272 
273     if (Password.Buffer != NULL)
274         RtlFreeUnicodeString(&Password);
275 
276 PasswordDone:
277     if (Domain.Buffer != NULL)
278         RtlFreeUnicodeString(&Domain);
279 
280 DomainDone:
281     if (UserName.Buffer != NULL)
282         RtlFreeUnicodeString(&UserName);
283 
284 UsernameDone:
285     return ret;
286 }
287 
288 
289 /*
290  * @implemented
291  */
292 BOOL WINAPI
293 LogonUserW(LPWSTR lpszUsername,
294            LPWSTR lpszDomain,
295            LPWSTR lpszPassword,
296            DWORD dwLogonType,
297            DWORD dwLogonProvider,
298            PHANDLE phToken)
299 {
300     SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
301     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
302     PSID LogonSid = NULL;
303     PSID LocalSid = NULL;
304     LSA_STRING OriginName;
305     UNICODE_STRING DomainName;
306     UNICODE_STRING UserName;
307     UNICODE_STRING Password;
308     PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
309     ULONG AuthInfoLength;
310     ULONG_PTR Ptr;
311     TOKEN_SOURCE TokenSource;
312     PTOKEN_GROUPS TokenGroups = NULL;
313     PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
314     ULONG ProfileBufferLength = 0;
315     LUID Luid = {0, 0};
316     LUID LogonId = {0, 0};
317     HANDLE TokenHandle = NULL;
318     QUOTA_LIMITS QuotaLimits;
319     SECURITY_LOGON_TYPE LogonType;
320     NTSTATUS SubStatus = STATUS_SUCCESS;
321     NTSTATUS Status;
322 
323     *phToken = NULL;
324 
325     switch (dwLogonType)
326     {
327         case LOGON32_LOGON_INTERACTIVE:
328             LogonType = Interactive;
329             break;
330 
331         case LOGON32_LOGON_NETWORK:
332             LogonType = Network;
333             break;
334 
335         case LOGON32_LOGON_BATCH:
336             LogonType = Batch;
337             break;
338 
339         case LOGON32_LOGON_SERVICE:
340             LogonType = Service;
341             break;
342 
343        default:
344             ERR("Invalid logon type: %ul\n", dwLogonType);
345             Status = STATUS_INVALID_PARAMETER;
346             goto done;
347     }
348 
349     if (LsaHandle == NULL)
350     {
351         Status = OpenLogonLsaHandle();
352         if (!NT_SUCCESS(Status))
353             goto done;
354     }
355 
356     RtlInitAnsiString((PANSI_STRING)&OriginName,
357                       "Advapi32 Logon");
358 
359     RtlInitUnicodeString(&DomainName,
360                          lpszDomain);
361 
362     RtlInitUnicodeString(&UserName,
363                          lpszUsername);
364 
365     RtlInitUnicodeString(&Password,
366                          lpszPassword);
367 
368     AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
369                      DomainName.MaximumLength +
370                      UserName.MaximumLength +
371                      Password.MaximumLength;
372 
373     AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
374                                HEAP_ZERO_MEMORY,
375                                AuthInfoLength);
376     if (AuthInfo == NULL)
377     {
378         Status = STATUS_INSUFFICIENT_RESOURCES;
379         goto done;
380     }
381 
382     AuthInfo->MessageType = MsV1_0InteractiveLogon;
383 
384     Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
385 
386     AuthInfo->LogonDomainName.Length = DomainName.Length;
387     AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
388     AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
389     if (DomainName.MaximumLength > 0)
390     {
391         RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
392                       DomainName.Buffer,
393                       DomainName.MaximumLength);
394 
395         Ptr += DomainName.MaximumLength;
396     }
397 
398     AuthInfo->UserName.Length = UserName.Length;
399     AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
400     AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
401     if (UserName.MaximumLength > 0)
402         RtlCopyMemory(AuthInfo->UserName.Buffer,
403                       UserName.Buffer,
404                       UserName.MaximumLength);
405 
406     Ptr += UserName.MaximumLength;
407 
408     AuthInfo->Password.Length = Password.Length;
409     AuthInfo->Password.MaximumLength = Password.MaximumLength;
410     AuthInfo->Password.Buffer = (PWCHAR)Ptr;
411     if (Password.MaximumLength > 0)
412         RtlCopyMemory(AuthInfo->Password.Buffer,
413                       Password.Buffer,
414                       Password.MaximumLength);
415 
416     /* Create the Logon SID*/
417     AllocateLocallyUniqueId(&LogonId);
418     Status = RtlAllocateAndInitializeSid(&SystemAuthority,
419                                          SECURITY_LOGON_IDS_RID_COUNT,
420                                          SECURITY_LOGON_IDS_RID,
421                                          LogonId.HighPart,
422                                          LogonId.LowPart,
423                                          SECURITY_NULL_RID,
424                                          SECURITY_NULL_RID,
425                                          SECURITY_NULL_RID,
426                                          SECURITY_NULL_RID,
427                                          SECURITY_NULL_RID,
428                                          &LogonSid);
429     if (!NT_SUCCESS(Status))
430         goto done;
431 
432     /* Create the Local SID*/
433     Status = RtlAllocateAndInitializeSid(&LocalAuthority,
434                                          1,
435                                          SECURITY_LOCAL_RID,
436                                          SECURITY_NULL_RID,
437                                          SECURITY_NULL_RID,
438                                          SECURITY_NULL_RID,
439                                          SECURITY_NULL_RID,
440                                          SECURITY_NULL_RID,
441                                          SECURITY_NULL_RID,
442                                          SECURITY_NULL_RID,
443                                          &LocalSid);
444     if (!NT_SUCCESS(Status))
445         goto done;
446 
447     /* Allocate and set the token groups */
448     TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
449                                   HEAP_ZERO_MEMORY,
450                                   sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
451     if (TokenGroups == NULL)
452     {
453         Status = STATUS_INSUFFICIENT_RESOURCES;
454         goto done;
455     }
456 
457     TokenGroups->GroupCount = 2;
458     TokenGroups->Groups[0].Sid = LogonSid;
459     TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
460                                         SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
461     TokenGroups->Groups[1].Sid = LocalSid;
462     TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
463                                         SE_GROUP_ENABLED_BY_DEFAULT;
464 
465     /* Set the token source */
466     strcpy(TokenSource.SourceName, "LogonUser");
467     AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
468 
469     Status = LsaLogonUser(LsaHandle,
470                           &OriginName,
471                           LogonType,
472                           AuthenticationPackage,
473                           (PVOID)AuthInfo,
474                           AuthInfoLength,
475                           TokenGroups,
476                           &TokenSource,
477                           (PVOID*)&ProfileBuffer,
478                           &ProfileBufferLength,
479                           &Luid,
480                           &TokenHandle,
481                           &QuotaLimits,
482                           &SubStatus);
483     if (!NT_SUCCESS(Status))
484     {
485         ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
486         goto done;
487     }
488 
489     if (ProfileBuffer != NULL)
490     {
491         TRACE("ProfileBuffer: %p\n", ProfileBuffer);
492         TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
493 
494         TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
495         TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
496 
497         TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
498         TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
499     }
500 
501     TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
502 
503     if (TokenHandle != NULL)
504     {
505         TRACE("TokenHandle: %p\n", TokenHandle);
506     }
507 
508     *phToken = TokenHandle;
509 
510 done:
511     if (ProfileBuffer != NULL)
512         LsaFreeReturnBuffer(ProfileBuffer);
513 
514     if (!NT_SUCCESS(Status))
515     {
516         if (TokenHandle != NULL)
517             CloseHandle(TokenHandle);
518     }
519 
520     if (TokenGroups != NULL)
521         RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
522 
523     if (LocalSid != NULL)
524         RtlFreeSid(LocalSid);
525 
526     if (LogonSid != NULL)
527         RtlFreeSid(LogonSid);
528 
529     if (AuthInfo != NULL)
530         RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
531 
532     if (!NT_SUCCESS(Status))
533     {
534         SetLastError(RtlNtStatusToDosError(Status));
535         return FALSE;
536     }
537 
538     return TRUE;
539 }
540 
541 /* EOF */
542