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