[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 /* 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 */