[ADVAPI32] Sync cred.c with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / win32 / advapi32 / misc / logon.c
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 DECLSPEC_HOTPATCH
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 DECLSPEC_HOTPATCH
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 /*
226 * @implemented
227 */
228 BOOL
229 WINAPI
230 LogonUserA(
231 _In_ LPSTR lpszUsername,
232 _In_opt_ LPSTR lpszDomain,
233 _In_opt_ LPSTR lpszPassword,
234 _In_ DWORD dwLogonType,
235 _In_ DWORD dwLogonProvider,
236 _Out_opt_ PHANDLE phToken)
237 {
238 return LogonUserExA(lpszUsername,
239 lpszDomain,
240 lpszPassword,
241 dwLogonType,
242 dwLogonProvider,
243 phToken,
244 NULL,
245 NULL,
246 NULL,
247 NULL);
248 }
249
250
251 /*
252 * @implemented
253 */
254 BOOL
255 WINAPI
256 LogonUserExA(
257 _In_ LPSTR lpszUsername,
258 _In_opt_ LPSTR lpszDomain,
259 _In_opt_ LPSTR lpszPassword,
260 _In_ DWORD dwLogonType,
261 _In_ DWORD dwLogonProvider,
262 _Out_opt_ PHANDLE phToken,
263 _Out_opt_ PSID *ppLogonSid,
264 _Out_opt_ PVOID *ppProfileBuffer,
265 _Out_opt_ LPDWORD pdwProfileLength,
266 _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
267 {
268 UNICODE_STRING UserName;
269 UNICODE_STRING Domain;
270 UNICODE_STRING Password;
271 BOOL ret = FALSE;
272
273 UserName.Buffer = NULL;
274 Domain.Buffer = NULL;
275 Password.Buffer = NULL;
276
277 if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
278 {
279 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
280 goto UsernameDone;
281 }
282
283 if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
284 {
285 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
286 goto DomainDone;
287 }
288
289 if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
290 {
291 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
292 goto PasswordDone;
293 }
294
295 ret = LogonUserExW(UserName.Buffer,
296 Domain.Buffer,
297 Password.Buffer,
298 dwLogonType,
299 dwLogonProvider,
300 phToken,
301 ppLogonSid,
302 ppProfileBuffer,
303 pdwProfileLength,
304 pQuotaLimits);
305
306 if (Password.Buffer != NULL)
307 RtlFreeUnicodeString(&Password);
308
309 PasswordDone:
310 if (Domain.Buffer != NULL)
311 RtlFreeUnicodeString(&Domain);
312
313 DomainDone:
314 if (UserName.Buffer != NULL)
315 RtlFreeUnicodeString(&UserName);
316
317 UsernameDone:
318 return ret;
319 }
320
321
322 /*
323 * @implemented
324 */
325 BOOL
326 WINAPI
327 LogonUserW(
328 _In_ LPWSTR lpszUsername,
329 _In_opt_ LPWSTR lpszDomain,
330 _In_opt_ LPWSTR lpszPassword,
331 _In_ DWORD dwLogonType,
332 _In_ DWORD dwLogonProvider,
333 _Out_opt_ PHANDLE phToken)
334 {
335 return LogonUserExW(lpszUsername,
336 lpszDomain,
337 lpszPassword,
338 dwLogonType,
339 dwLogonProvider,
340 phToken,
341 NULL,
342 NULL,
343 NULL,
344 NULL);
345 }
346
347
348 /*
349 * @implemented
350 */
351 BOOL
352 WINAPI
353 LogonUserExW(
354 _In_ LPWSTR lpszUsername,
355 _In_opt_ LPWSTR lpszDomain,
356 _In_opt_ LPWSTR lpszPassword,
357 _In_ DWORD dwLogonType,
358 _In_ DWORD dwLogonProvider,
359 _Out_opt_ PHANDLE phToken,
360 _Out_opt_ PSID *ppLogonSid,
361 _Out_opt_ PVOID *ppProfileBuffer,
362 _Out_opt_ LPDWORD pdwProfileLength,
363 _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
364 {
365 SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
366 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
367 PSID LogonSid = NULL;
368 PSID LocalSid = NULL;
369 LSA_STRING OriginName;
370 UNICODE_STRING DomainName;
371 UNICODE_STRING UserName;
372 UNICODE_STRING Password;
373 PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
374 ULONG AuthInfoLength;
375 ULONG_PTR Ptr;
376 TOKEN_SOURCE TokenSource;
377 PTOKEN_GROUPS TokenGroups = NULL;
378 PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
379 ULONG ProfileBufferLength = 0;
380 LUID Luid = {0, 0};
381 LUID LogonId = {0, 0};
382 HANDLE TokenHandle = NULL;
383 QUOTA_LIMITS QuotaLimits;
384 SECURITY_LOGON_TYPE LogonType;
385 NTSTATUS SubStatus = STATUS_SUCCESS;
386 NTSTATUS Status;
387
388 *phToken = NULL;
389
390 switch (dwLogonType)
391 {
392 case LOGON32_LOGON_INTERACTIVE:
393 LogonType = Interactive;
394 break;
395
396 case LOGON32_LOGON_NETWORK:
397 LogonType = Network;
398 break;
399
400 case LOGON32_LOGON_BATCH:
401 LogonType = Batch;
402 break;
403
404 case LOGON32_LOGON_SERVICE:
405 LogonType = Service;
406 break;
407
408 default:
409 ERR("Invalid logon type: %ul\n", dwLogonType);
410 Status = STATUS_INVALID_PARAMETER;
411 goto done;
412 }
413
414 if (LsaHandle == NULL)
415 {
416 Status = OpenLogonLsaHandle();
417 if (!NT_SUCCESS(Status))
418 goto done;
419 }
420
421 RtlInitAnsiString((PANSI_STRING)&OriginName,
422 "Advapi32 Logon");
423
424 RtlInitUnicodeString(&DomainName,
425 lpszDomain);
426
427 RtlInitUnicodeString(&UserName,
428 lpszUsername);
429
430 RtlInitUnicodeString(&Password,
431 lpszPassword);
432
433 AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
434 DomainName.MaximumLength +
435 UserName.MaximumLength +
436 Password.MaximumLength;
437
438 AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
439 HEAP_ZERO_MEMORY,
440 AuthInfoLength);
441 if (AuthInfo == NULL)
442 {
443 Status = STATUS_INSUFFICIENT_RESOURCES;
444 goto done;
445 }
446
447 AuthInfo->MessageType = MsV1_0InteractiveLogon;
448
449 Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
450
451 AuthInfo->LogonDomainName.Length = DomainName.Length;
452 AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
453 AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
454 if (DomainName.MaximumLength > 0)
455 {
456 RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
457 DomainName.Buffer,
458 DomainName.MaximumLength);
459
460 Ptr += DomainName.MaximumLength;
461 }
462
463 AuthInfo->UserName.Length = UserName.Length;
464 AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
465 AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
466 if (UserName.MaximumLength > 0)
467 RtlCopyMemory(AuthInfo->UserName.Buffer,
468 UserName.Buffer,
469 UserName.MaximumLength);
470
471 Ptr += UserName.MaximumLength;
472
473 AuthInfo->Password.Length = Password.Length;
474 AuthInfo->Password.MaximumLength = Password.MaximumLength;
475 AuthInfo->Password.Buffer = (PWCHAR)Ptr;
476 if (Password.MaximumLength > 0)
477 RtlCopyMemory(AuthInfo->Password.Buffer,
478 Password.Buffer,
479 Password.MaximumLength);
480
481 /* Create the Logon SID*/
482 AllocateLocallyUniqueId(&LogonId);
483 Status = RtlAllocateAndInitializeSid(&SystemAuthority,
484 SECURITY_LOGON_IDS_RID_COUNT,
485 SECURITY_LOGON_IDS_RID,
486 LogonId.HighPart,
487 LogonId.LowPart,
488 SECURITY_NULL_RID,
489 SECURITY_NULL_RID,
490 SECURITY_NULL_RID,
491 SECURITY_NULL_RID,
492 SECURITY_NULL_RID,
493 &LogonSid);
494 if (!NT_SUCCESS(Status))
495 goto done;
496
497 /* Create the Local SID*/
498 Status = RtlAllocateAndInitializeSid(&LocalAuthority,
499 1,
500 SECURITY_LOCAL_RID,
501 SECURITY_NULL_RID,
502 SECURITY_NULL_RID,
503 SECURITY_NULL_RID,
504 SECURITY_NULL_RID,
505 SECURITY_NULL_RID,
506 SECURITY_NULL_RID,
507 SECURITY_NULL_RID,
508 &LocalSid);
509 if (!NT_SUCCESS(Status))
510 goto done;
511
512 /* Allocate and set the token groups */
513 TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
514 HEAP_ZERO_MEMORY,
515 sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
516 if (TokenGroups == NULL)
517 {
518 Status = STATUS_INSUFFICIENT_RESOURCES;
519 goto done;
520 }
521
522 TokenGroups->GroupCount = 2;
523 TokenGroups->Groups[0].Sid = LogonSid;
524 TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
525 SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
526 TokenGroups->Groups[1].Sid = LocalSid;
527 TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
528 SE_GROUP_ENABLED_BY_DEFAULT;
529
530 /* Set the token source */
531 strncpy(TokenSource.SourceName, "Advapi ", sizeof(TokenSource.SourceName));
532 AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
533
534 Status = LsaLogonUser(LsaHandle,
535 &OriginName,
536 LogonType,
537 AuthenticationPackage,
538 (PVOID)AuthInfo,
539 AuthInfoLength,
540 TokenGroups,
541 &TokenSource,
542 (PVOID*)&ProfileBuffer,
543 &ProfileBufferLength,
544 &Luid,
545 &TokenHandle,
546 &QuotaLimits,
547 &SubStatus);
548 if (!NT_SUCCESS(Status))
549 {
550 ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
551 goto done;
552 }
553
554 if (ProfileBuffer != NULL)
555 {
556 TRACE("ProfileBuffer: %p\n", ProfileBuffer);
557 TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
558
559 TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
560 TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
561
562 TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
563 TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
564 }
565
566 TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
567
568 if (TokenHandle != NULL)
569 {
570 TRACE("TokenHandle: %p\n", TokenHandle);
571 }
572
573 *phToken = TokenHandle;
574
575 /* FIXME: return ppLogonSid, ppProfileBuffer, pdwProfileLength and pQuotaLimits */
576
577 done:
578 if (ProfileBuffer != NULL)
579 LsaFreeReturnBuffer(ProfileBuffer);
580
581 if (!NT_SUCCESS(Status))
582 {
583 if (TokenHandle != NULL)
584 CloseHandle(TokenHandle);
585 }
586
587 if (TokenGroups != NULL)
588 RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
589
590 if (LocalSid != NULL)
591 RtlFreeSid(LocalSid);
592
593 if (LogonSid != NULL)
594 RtlFreeSid(LogonSid);
595
596 if (AuthInfo != NULL)
597 RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
598
599 if (!NT_SUCCESS(Status))
600 {
601 SetLastError(RtlNtStatusToDosError(Status));
602 return FALSE;
603 }
604
605 return TRUE;
606 }
607
608 /* EOF */