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