1 /* 2 * PROJECT: Local Security Authority Server DLL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/lsasrv/session.c 5 * PURPOSE: Logon session management routines 6 * COPYRIGHT: Copyright 2013 Eric Kohl 7 */ 8 9 #include "lsasrv.h" 10 11 typedef struct _LSAP_LOGON_SESSION 12 { 13 LIST_ENTRY Entry; 14 LUID LogonId; 15 ULONG LogonType; 16 ULONG Session; 17 LARGE_INTEGER LogonTime; 18 PSID Sid; 19 UNICODE_STRING UserName; 20 UNICODE_STRING LogonDomain; 21 UNICODE_STRING AuthenticationPackage; 22 UNICODE_STRING LogonServer; 23 UNICODE_STRING DnsDomainName; 24 UNICODE_STRING Upn; 25 } LSAP_LOGON_SESSION, *PLSAP_LOGON_SESSION; 26 27 28 /* GLOBALS *****************************************************************/ 29 30 LIST_ENTRY SessionListHead; 31 ULONG SessionCount; 32 33 /* FUNCTIONS ***************************************************************/ 34 35 VOID 36 LsapInitLogonSessions(VOID) 37 { 38 InitializeListHead(&SessionListHead); 39 SessionCount = 0; 40 } 41 42 43 static 44 PLSAP_LOGON_SESSION 45 LsapGetLogonSession(IN PLUID LogonId) 46 { 47 PLIST_ENTRY SessionEntry; 48 PLSAP_LOGON_SESSION CurrentSession; 49 50 SessionEntry = SessionListHead.Flink; 51 while (SessionEntry != &SessionListHead) 52 { 53 CurrentSession = CONTAINING_RECORD(SessionEntry, 54 LSAP_LOGON_SESSION, 55 Entry); 56 if (RtlEqualLuid(&CurrentSession->LogonId, LogonId)) 57 return CurrentSession; 58 59 SessionEntry = SessionEntry->Flink; 60 } 61 62 return NULL; 63 } 64 65 66 NTSTATUS 67 LsapSetLogonSessionData( 68 _In_ PLUID LogonId, 69 _In_ ULONG LogonType, 70 _In_ PUNICODE_STRING UserName, 71 _In_ PUNICODE_STRING LogonDomain, 72 _In_ PSID Sid) 73 { 74 PLSAP_LOGON_SESSION Session; 75 ULONG Length; 76 77 TRACE("LsapSetLogonSessionData(%p)\n", LogonId); 78 79 Session = LsapGetLogonSession(LogonId); 80 if (Session == NULL) 81 return STATUS_NO_SUCH_LOGON_SESSION; 82 83 TRACE("LogonType %lu\n", LogonType); 84 Session->LogonType = LogonType; 85 86 TRACE("UserName %wZ\n", UserName); 87 Session->UserName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, UserName->MaximumLength); 88 if (Session->UserName.Buffer == NULL) 89 return STATUS_INSUFFICIENT_RESOURCES; 90 91 Session->UserName.Length = UserName->Length; 92 Session->UserName.MaximumLength = UserName->MaximumLength; 93 RtlCopyMemory(Session->UserName.Buffer, UserName->Buffer, UserName->MaximumLength); 94 95 TRACE("LogonDomain %wZ\n", LogonDomain); 96 Session->LogonDomain.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, LogonDomain->MaximumLength); 97 if (Session->LogonDomain.Buffer == NULL) 98 return STATUS_INSUFFICIENT_RESOURCES; 99 100 Session->LogonDomain.Length = LogonDomain->Length; 101 Session->LogonDomain.MaximumLength = LogonDomain->MaximumLength; 102 RtlCopyMemory(Session->LogonDomain.Buffer, LogonDomain->Buffer, LogonDomain->MaximumLength); 103 104 Length = RtlLengthSid(Sid); 105 Session->Sid = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length); 106 if (Session->UserName.Buffer == NULL) 107 return STATUS_INSUFFICIENT_RESOURCES; 108 109 RtlCopyMemory(Session->Sid, Sid, Length); 110 111 return STATUS_SUCCESS; 112 } 113 114 115 NTSTATUS 116 NTAPI 117 LsapCreateLogonSession(IN PLUID LogonId) 118 { 119 PLSAP_LOGON_SESSION Session; 120 NTSTATUS Status; 121 122 TRACE("LsapCreateLogonSession(%p)\n", LogonId); 123 124 /* Fail, if a session already exists */ 125 if (LsapGetLogonSession(LogonId) != NULL) 126 return STATUS_LOGON_SESSION_COLLISION; 127 128 /* Allocate a new session entry */ 129 Session = RtlAllocateHeap(RtlGetProcessHeap(), 130 HEAP_ZERO_MEMORY, 131 sizeof(LSAP_LOGON_SESSION)); 132 if (Session == NULL) 133 return STATUS_INSUFFICIENT_RESOURCES; 134 135 /* Initialize the session entry */ 136 RtlCopyLuid(&Session->LogonId, LogonId); 137 138 TRACE("LsapCreateLogonSession(<0x%lx,0x%lx>)\n", 139 LogonId->HighPart, LogonId->LowPart); 140 141 /* Tell ntoskrnl to create a new logon session */ 142 Status = LsapRmCreateLogonSession(LogonId); 143 if (!NT_SUCCESS(Status)) 144 { 145 RtlFreeHeap(RtlGetProcessHeap(), 0, Session); 146 return Status; 147 } 148 149 /* Insert the new session into the session list */ 150 InsertHeadList(&SessionListHead, &Session->Entry); 151 SessionCount++; 152 153 return STATUS_SUCCESS; 154 } 155 156 157 NTSTATUS 158 NTAPI 159 LsapDeleteLogonSession(IN PLUID LogonId) 160 { 161 PLSAP_LOGON_SESSION Session; 162 NTSTATUS Status; 163 164 TRACE("LsapDeleteLogonSession(%p)\n", LogonId); 165 166 /* Fail, if the session does not exist */ 167 Session = LsapGetLogonSession(LogonId); 168 if (Session == NULL) 169 return STATUS_NO_SUCH_LOGON_SESSION; 170 171 TRACE("LsapDeleteLogonSession(<0x%lx,0x%lx>)\n", 172 LogonId->HighPart, LogonId->LowPart); 173 174 /* Tell ntoskrnl to delete the logon session */ 175 Status = LsapRmDeleteLogonSession(LogonId); 176 if (!NT_SUCCESS(Status)) 177 return Status; 178 179 /* Remove the session entry from the list */ 180 RemoveEntryList(&Session->Entry); 181 SessionCount--; 182 183 /* Free the session data */ 184 if (Session->Sid != NULL) 185 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Sid); 186 187 if (Session->UserName.Buffer != NULL) 188 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName.Buffer); 189 190 if (Session->LogonDomain.Buffer != NULL) 191 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonDomain.Buffer); 192 193 if (Session->AuthenticationPackage.Buffer != NULL) 194 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->AuthenticationPackage.Buffer); 195 196 if (Session->LogonServer.Buffer != NULL) 197 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonServer.Buffer); 198 199 if (Session->DnsDomainName.Buffer != NULL) 200 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->DnsDomainName.Buffer); 201 202 if (Session->Upn.Buffer != NULL) 203 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Upn.Buffer); 204 205 /* Free the session entry */ 206 RtlFreeHeap(RtlGetProcessHeap(), 0, Session); 207 208 return STATUS_SUCCESS; 209 } 210 211 212 NTSTATUS 213 NTAPI 214 LsapAddCredential( 215 _In_ PLUID LogonId, 216 _In_ ULONG AuthenticationPackage, 217 _In_ PLSA_STRING PrimaryKeyValue, 218 _In_ PLSA_STRING Credential) 219 { 220 221 return STATUS_SUCCESS; 222 } 223 224 225 NTSTATUS 226 NTAPI 227 LsapGetCredentials( 228 _In_ PLUID LogonId, 229 _In_ ULONG AuthenticationPackage, 230 _Inout_ PULONG QueryContext, 231 _In_ BOOLEAN RetrieveAllCredentials, 232 _Inout_ PLSA_STRING PrimaryKeyValue, 233 _Out_ PULONG PrimaryKeyLength, 234 _Out_ PLSA_STRING Credentials) 235 { 236 237 return STATUS_SUCCESS; 238 } 239 240 241 NTSTATUS 242 NTAPI 243 LsapDeleteCredential( 244 _In_ PLUID LogonId, 245 _In_ ULONG AuthenticationPackage, 246 _In_ PLSA_STRING PrimaryKeyValue) 247 { 248 249 return STATUS_SUCCESS; 250 } 251 252 253 NTSTATUS 254 LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg) 255 { 256 OBJECT_ATTRIBUTES ObjectAttributes; 257 HANDLE ProcessHandle = NULL; 258 PLIST_ENTRY SessionEntry; 259 PLSAP_LOGON_SESSION CurrentSession; 260 PLUID SessionList; 261 ULONG i, Length; 262 SIZE_T MemSize; 263 PVOID ClientBaseAddress = NULL; 264 NTSTATUS Status; 265 266 TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg); 267 268 Length = SessionCount * sizeof(LUID); 269 SessionList = RtlAllocateHeap(RtlGetProcessHeap(), 270 HEAP_ZERO_MEMORY, 271 Length); 272 if (SessionList == NULL) 273 return STATUS_INSUFFICIENT_RESOURCES; 274 275 i = 0; 276 SessionEntry = SessionListHead.Flink; 277 while (SessionEntry != &SessionListHead) 278 { 279 CurrentSession = CONTAINING_RECORD(SessionEntry, 280 LSAP_LOGON_SESSION, 281 Entry); 282 283 RtlCopyLuid(&SessionList[i], 284 &CurrentSession->LogonId); 285 286 SessionEntry = SessionEntry->Flink; 287 i++; 288 } 289 290 InitializeObjectAttributes(&ObjectAttributes, 291 NULL, 292 0, 293 NULL, 294 NULL); 295 296 Status = NtOpenProcess(&ProcessHandle, 297 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 298 &ObjectAttributes, 299 &RequestMsg->h.ClientId); 300 if (!NT_SUCCESS(Status)) 301 { 302 TRACE("NtOpenProcess() failed (Status %lx)\n", Status); 303 goto done; 304 } 305 306 TRACE("Length: %lu\n", Length); 307 308 MemSize = Length; 309 Status = NtAllocateVirtualMemory(ProcessHandle, 310 &ClientBaseAddress, 311 0, 312 &MemSize, 313 MEM_COMMIT, 314 PAGE_READWRITE); 315 if (!NT_SUCCESS(Status)) 316 { 317 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status); 318 goto done; 319 } 320 321 TRACE("MemSize: %lu\n", MemSize); 322 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress); 323 324 Status = NtWriteVirtualMemory(ProcessHandle, 325 ClientBaseAddress, 326 SessionList, 327 Length, 328 NULL); 329 if (!NT_SUCCESS(Status)) 330 { 331 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status); 332 goto done; 333 } 334 335 RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount; 336 RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress; 337 338 done: 339 if (ProcessHandle != NULL) 340 NtClose(ProcessHandle); 341 342 if (SessionList != NULL) 343 RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList); 344 345 return Status; 346 } 347 348 349 NTSTATUS 350 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg) 351 { 352 OBJECT_ATTRIBUTES ObjectAttributes; 353 HANDLE ProcessHandle = NULL; 354 PLSAP_LOGON_SESSION Session; 355 PSECURITY_LOGON_SESSION_DATA LocalSessionData; 356 PVOID ClientBaseAddress = NULL; 357 ULONG TotalLength, SidLength = 0; 358 SIZE_T MemSize; 359 PUCHAR Ptr; 360 NTSTATUS Status; 361 362 TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg); 363 364 TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart); 365 Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId); 366 if (Session == NULL) 367 return STATUS_NO_SUCH_LOGON_SESSION; 368 369 /* Calculate the required buffer size */ 370 TotalLength = sizeof(SECURITY_LOGON_SESSION_DATA) + 371 Session->UserName.MaximumLength + 372 Session->LogonDomain.MaximumLength + 373 Session->AuthenticationPackage.MaximumLength + 374 Session->LogonServer.MaximumLength + 375 Session->DnsDomainName.MaximumLength + 376 Session->Upn.MaximumLength; 377 if (Session->Sid != NULL) 378 { 379 SidLength = RtlLengthSid(Session->Sid); 380 TotalLength += SidLength; 381 } 382 TRACE("TotalLength: %lu\n", TotalLength); 383 384 /* Allocate the buffer */ 385 LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(), 386 HEAP_ZERO_MEMORY, 387 TotalLength); 388 if (LocalSessionData == NULL) 389 return STATUS_INSUFFICIENT_RESOURCES; 390 391 Ptr = (PUCHAR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA)); 392 TRACE("LocalSessionData: %p Ptr: %p\n", LocalSessionData, Ptr); 393 394 LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA); 395 396 /* Copy the LogonId */ 397 RtlCopyLuid(&LocalSessionData->LogonId, 398 &RequestMsg->GetLogonSessionData.Request.LogonId); 399 400 /* Copy the UserName string*/ 401 LocalSessionData->UserName.Length = Session->UserName.Length; 402 LocalSessionData->UserName.MaximumLength = Session->UserName.MaximumLength; 403 404 if (Session->UserName.MaximumLength != 0) 405 { 406 RtlCopyMemory(Ptr, Session->UserName.Buffer, Session->UserName.MaximumLength); 407 LocalSessionData->UserName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 408 409 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->UserName.MaximumLength); 410 } 411 412 /* Copy the LogonDomain string */ 413 LocalSessionData->LogonDomain.Length = Session->LogonDomain.Length; 414 LocalSessionData->LogonDomain.MaximumLength = Session->LogonDomain.MaximumLength; 415 if (Session->LogonDomain.MaximumLength != 0) 416 { 417 RtlCopyMemory(Ptr, Session->LogonDomain.Buffer, Session->LogonDomain.MaximumLength); 418 LocalSessionData->LogonDomain.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 419 420 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonDomain.MaximumLength); 421 } 422 423 /* Copy the AuthenticationPackage string */ 424 LocalSessionData->AuthenticationPackage.Length = Session->AuthenticationPackage.Length; 425 LocalSessionData->AuthenticationPackage.MaximumLength = Session->AuthenticationPackage.MaximumLength; 426 if (Session->AuthenticationPackage.MaximumLength != 0) 427 { 428 RtlCopyMemory(Ptr, Session->AuthenticationPackage.Buffer, Session->AuthenticationPackage.MaximumLength); 429 LocalSessionData->AuthenticationPackage.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 430 431 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->AuthenticationPackage.MaximumLength); 432 } 433 434 LocalSessionData->LogonType = Session->LogonType; 435 LocalSessionData->Session = 0; 436 437 /* Sid */ 438 if (Session->Sid != NULL) 439 { 440 RtlCopyMemory(Ptr, Session->Sid, SidLength); 441 LocalSessionData->Sid = (PSID)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 442 443 Ptr = (PUCHAR)((ULONG_PTR)Ptr + SidLength); 444 } 445 446 /* LogonTime */ 447 LocalSessionData->LogonTime.QuadPart = Session->LogonTime.QuadPart; 448 449 /* Copy the LogonServer string */ 450 LocalSessionData->LogonServer.Length = Session->LogonServer.Length; 451 LocalSessionData->LogonServer.MaximumLength = Session->LogonServer.MaximumLength; 452 if (Session->LogonServer.MaximumLength != 0) 453 { 454 RtlCopyMemory(Ptr, Session->LogonServer.Buffer, Session->LogonServer.MaximumLength); 455 LocalSessionData->LogonServer.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 456 457 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonServer.MaximumLength); 458 } 459 460 /* Copy the DnsDomainName string */ 461 LocalSessionData->DnsDomainName.Length = Session->DnsDomainName.Length; 462 LocalSessionData->DnsDomainName.MaximumLength = Session->DnsDomainName.MaximumLength; 463 if (Session->DnsDomainName.MaximumLength != 0) 464 { 465 RtlCopyMemory(Ptr, Session->DnsDomainName.Buffer, Session->DnsDomainName.MaximumLength); 466 LocalSessionData->DnsDomainName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 467 468 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->DnsDomainName.MaximumLength); 469 } 470 471 /* Copy the Upn string */ 472 LocalSessionData->Upn.Length = Session->Upn.Length; 473 LocalSessionData->Upn.MaximumLength = Session->Upn.MaximumLength; 474 if (Session->Upn.MaximumLength != 0) 475 { 476 RtlCopyMemory(Ptr, Session->Upn.Buffer, Session->Upn.MaximumLength); 477 LocalSessionData->Upn.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData); 478 479 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->Upn.MaximumLength); 480 } 481 482 483 InitializeObjectAttributes(&ObjectAttributes, 484 NULL, 485 0, 486 NULL, 487 NULL); 488 489 Status = NtOpenProcess(&ProcessHandle, 490 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, 491 &ObjectAttributes, 492 &RequestMsg->h.ClientId); 493 if (!NT_SUCCESS(Status)) 494 { 495 TRACE("NtOpenProcess() failed (Status %lx)\n", Status); 496 goto done; 497 } 498 499 MemSize = TotalLength; 500 Status = NtAllocateVirtualMemory(ProcessHandle, 501 &ClientBaseAddress, 502 0, 503 &MemSize, 504 MEM_COMMIT, 505 PAGE_READWRITE); 506 if (!NT_SUCCESS(Status)) 507 { 508 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status); 509 goto done; 510 } 511 512 TRACE("MemSize: %lu\n", MemSize); 513 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress); 514 515 Status = NtWriteVirtualMemory(ProcessHandle, 516 ClientBaseAddress, 517 LocalSessionData, 518 TotalLength, 519 NULL); 520 if (!NT_SUCCESS(Status)) 521 { 522 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status); 523 goto done; 524 } 525 526 RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress; 527 528 done: 529 if (ProcessHandle != NULL) 530 NtClose(ProcessHandle); 531 532 if (LocalSessionData != NULL) 533 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData); 534 535 return Status; 536 } 537 538 /* EOF */ 539