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