1 /* 2 * PROJECT: Local Security Authority Server DLL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: dll/win32/lsasrv/authport.c 5 * PURPOSE: LsaAuthenticationPort server routines 6 * COPYRIGHT: Copyright 2009 Eric Kohl 7 */ 8 9 #include "lsasrv.h" 10 11 #include <ndk/lpcfuncs.h> 12 13 static LIST_ENTRY LsapLogonContextList; 14 15 static HANDLE PortThreadHandle = NULL; 16 static HANDLE AuthPortHandle = NULL; 17 18 19 /* FUNCTIONS ***************************************************************/ 20 21 static NTSTATUS 22 LsapDeregisterLogonProcess(PLSA_API_MSG RequestMsg, 23 PLSAP_LOGON_CONTEXT LogonContext) 24 { 25 TRACE("LsapDeregisterLogonProcess(%p %p)\n", RequestMsg, LogonContext); 26 27 RemoveHeadList(&LogonContext->Entry); 28 29 NtClose(LogonContext->ClientProcessHandle); 30 NtClose(LogonContext->ConnectionHandle); 31 32 RtlFreeHeap(RtlGetProcessHeap(), 0, LogonContext); 33 34 return STATUS_SUCCESS; 35 } 36 37 38 static 39 BOOL 40 LsapIsTrustedClient( 41 _In_ HANDLE ProcessHandle) 42 { 43 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0}; 44 HANDLE TokenHandle = NULL; 45 PTOKEN_PRIVILEGES Privileges = NULL; 46 ULONG Size, i; 47 BOOL Trusted = FALSE; 48 NTSTATUS Status; 49 50 Status = NtOpenProcessToken(ProcessHandle, 51 TOKEN_QUERY, 52 &TokenHandle); 53 if (!NT_SUCCESS(Status)) 54 goto done; 55 56 Status = NtQueryInformationToken(TokenHandle, 57 TokenPrivileges, 58 NULL, 59 0, 60 &Size); 61 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) 62 goto done; 63 64 Privileges = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); 65 if (Privileges == NULL) 66 goto done; 67 68 Status = NtQueryInformationToken(TokenHandle, 69 TokenPrivileges, 70 Privileges, 71 Size, 72 &Size); 73 if (!NT_SUCCESS(Status)) 74 goto done; 75 76 for (i = 0; i < Privileges->PrivilegeCount; i++) 77 { 78 if (RtlEqualLuid(&Privileges->Privileges[i].Luid, &TcbPrivilege)) 79 { 80 Trusted = TRUE; 81 break; 82 } 83 } 84 85 done: 86 if (Privileges != NULL) 87 RtlFreeHeap(RtlGetProcessHeap(), 0, Privileges); 88 89 if (TokenHandle != NULL) 90 NtClose(TokenHandle); 91 92 return Trusted; 93 } 94 95 96 static NTSTATUS 97 LsapCheckLogonProcess(PLSA_API_MSG RequestMsg, 98 PLSAP_LOGON_CONTEXT *LogonContext) 99 { 100 OBJECT_ATTRIBUTES ObjectAttributes; 101 HANDLE ProcessHandle = NULL; 102 PLSAP_LOGON_CONTEXT Context = NULL; 103 NTSTATUS Status; 104 105 TRACE("LsapCheckLogonProcess(%p)\n", RequestMsg); 106 107 TRACE("Client ID: %p %p\n", RequestMsg->h.ClientId.UniqueProcess, RequestMsg->h.ClientId.UniqueThread); 108 109 InitializeObjectAttributes(&ObjectAttributes, 110 NULL, 111 0, 112 NULL, 113 NULL); 114 115 Status = NtOpenProcess(&ProcessHandle, 116 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, 117 &ObjectAttributes, 118 &RequestMsg->h.ClientId); 119 if (!NT_SUCCESS(Status)) 120 { 121 TRACE("NtOpenProcess() failed (Status %lx)\n", Status); 122 return Status; 123 } 124 125 /* Allocate the logon context */ 126 Context = RtlAllocateHeap(RtlGetProcessHeap(), 127 HEAP_ZERO_MEMORY, 128 sizeof(LSAP_LOGON_CONTEXT)); 129 if (Context == NULL) 130 { 131 NtClose(ProcessHandle); 132 return STATUS_INSUFFICIENT_RESOURCES; 133 } 134 135 TRACE("New LogonContext: %p\n", Context); 136 137 Context->ClientProcessHandle = ProcessHandle; 138 139 switch (RequestMsg->ConnectInfo.TrustedCaller) 140 { 141 case NO: 142 Context->TrustedCaller = FALSE; 143 break; 144 145 case YES: 146 Context->TrustedCaller = TRUE; 147 break; 148 149 case CHECK: 150 default: 151 Context->TrustedCaller = LsapIsTrustedClient(ProcessHandle); 152 break; 153 } 154 155 TRACE("TrustedCaller: %u\n", Context->TrustedCaller); 156 157 *LogonContext = Context; 158 159 return STATUS_SUCCESS; 160 } 161 162 163 static NTSTATUS 164 LsapHandlePortConnection(PLSA_API_MSG RequestMsg) 165 { 166 PLSAP_LOGON_CONTEXT LogonContext = NULL; 167 HANDLE ConnectionHandle = NULL; 168 BOOLEAN Accept; 169 REMOTE_PORT_VIEW RemotePortView; 170 NTSTATUS Status = STATUS_SUCCESS; 171 172 TRACE("LsapHandlePortConnection(%p)\n", RequestMsg); 173 174 TRACE("Logon Process Name: %s\n", RequestMsg->ConnectInfo.LogonProcessNameBuffer); 175 176 if (RequestMsg->ConnectInfo.CreateContext != FALSE) 177 { 178 Status = LsapCheckLogonProcess(RequestMsg, 179 &LogonContext); 180 181 RequestMsg->ConnectInfo.OperationalMode = 0x43218765; 182 183 RequestMsg->ConnectInfo.Status = Status; 184 } 185 186 if (NT_SUCCESS(Status)) 187 { 188 Accept = TRUE; 189 } 190 else 191 { 192 Accept = FALSE; 193 } 194 195 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); 196 Status = NtAcceptConnectPort(&ConnectionHandle, 197 (PVOID*)LogonContext, 198 &RequestMsg->h, 199 Accept, 200 NULL, 201 &RemotePortView); 202 if (!NT_SUCCESS(Status)) 203 { 204 ERR("NtAcceptConnectPort failed (Status 0x%lx)\n", Status); 205 return Status; 206 } 207 208 if (Accept != FALSE) 209 { 210 if (LogonContext != NULL) 211 { 212 LogonContext->ConnectionHandle = ConnectionHandle; 213 214 InsertHeadList(&LsapLogonContextList, 215 &LogonContext->Entry); 216 } 217 218 Status = NtCompleteConnectPort(ConnectionHandle); 219 if (!NT_SUCCESS(Status)) 220 { 221 ERR("NtCompleteConnectPort failed (Status 0x%lx)\n", Status); 222 return Status; 223 } 224 } 225 226 return Status; 227 } 228 229 230 NTSTATUS WINAPI 231 AuthPortThreadRoutine(PVOID Param) 232 { 233 PLSAP_LOGON_CONTEXT LogonContext; 234 PLSA_API_MSG ReplyMsg = NULL; 235 LSA_API_MSG RequestMsg; 236 NTSTATUS Status; 237 238 TRACE("AuthPortThreadRoutine() called\n"); 239 240 Status = STATUS_SUCCESS; 241 242 for (;;) 243 { 244 TRACE("Reply: %p\n", ReplyMsg); 245 Status = NtReplyWaitReceivePort(AuthPortHandle, 246 (PVOID*)&LogonContext, 247 (PPORT_MESSAGE)ReplyMsg, 248 (PPORT_MESSAGE)&RequestMsg); 249 if (!NT_SUCCESS(Status)) 250 { 251 TRACE("NtReplyWaitReceivePort() failed (Status %lx)\n", Status); 252 break; 253 } 254 255 TRACE("Received message\n"); 256 257 switch (RequestMsg.h.u2.s2.Type) 258 { 259 case LPC_CONNECTION_REQUEST: 260 TRACE("Port connection request\n"); 261 Status = LsapHandlePortConnection(&RequestMsg); 262 ReplyMsg = NULL; 263 break; 264 265 case LPC_PORT_CLOSED: 266 TRACE("Port closed\n"); 267 ReplyMsg = NULL; 268 break; 269 270 case LPC_CLIENT_DIED: 271 TRACE("Client died\n"); 272 ReplyMsg = NULL; 273 break; 274 275 default: 276 TRACE("Received request (ApiNumber: %lu)\n", RequestMsg.ApiNumber); 277 278 switch (RequestMsg.ApiNumber) 279 { 280 case LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE: 281 RequestMsg.Status = LsapCallAuthenticationPackage(&RequestMsg, 282 LogonContext); 283 ReplyMsg = &RequestMsg; 284 break; 285 286 case LSASS_REQUEST_DEREGISTER_LOGON_PROCESS: 287 288 ReplyMsg = &RequestMsg; 289 RequestMsg.Status = STATUS_SUCCESS; 290 NtReplyPort(AuthPortHandle, 291 &ReplyMsg->h); 292 293 LsapDeregisterLogonProcess(&RequestMsg, 294 LogonContext); 295 296 ReplyMsg = NULL; 297 break; 298 299 case LSASS_REQUEST_LOGON_USER: 300 RequestMsg.Status = LsapLogonUser(&RequestMsg, 301 LogonContext); 302 ReplyMsg = &RequestMsg; 303 break; 304 305 case LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE: 306 RequestMsg.Status = LsapLookupAuthenticationPackage(&RequestMsg, 307 LogonContext); 308 ReplyMsg = &RequestMsg; 309 break; 310 311 case LSASS_REQUEST_ENUM_LOGON_SESSIONS: 312 RequestMsg.Status = LsapEnumLogonSessions(&RequestMsg); 313 ReplyMsg = &RequestMsg; 314 break; 315 316 case LSASS_REQUEST_GET_LOGON_SESSION_DATA: 317 RequestMsg.Status = LsapGetLogonSessionData(&RequestMsg); 318 ReplyMsg = &RequestMsg; 319 break; 320 321 case LSASS_REQUEST_POLICY_CHANGE_NOTIFY: 322 RequestMsg.Status = LsapRegisterNotification(&RequestMsg); 323 ReplyMsg = &RequestMsg; 324 break; 325 326 default: 327 RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE; 328 ReplyMsg = &RequestMsg; 329 break; 330 } 331 332 break; 333 } 334 } 335 336 return STATUS_SUCCESS; 337 } 338 339 340 NTSTATUS 341 StartAuthenticationPort(VOID) 342 { 343 OBJECT_ATTRIBUTES ObjectAttributes; 344 UNICODE_STRING PortName; 345 DWORD ThreadId; 346 UNICODE_STRING EventName; 347 HANDLE EventHandle; 348 NTSTATUS Status; 349 350 TRACE("StartAuthenticationPort()\n"); 351 352 /* Initialize the logon context list */ 353 InitializeListHead(&LsapLogonContextList); 354 355 RtlInitUnicodeString(&PortName, 356 L"\\LsaAuthenticationPort"); 357 358 InitializeObjectAttributes(&ObjectAttributes, 359 &PortName, 360 0, 361 NULL, 362 NULL); 363 364 Status = NtCreatePort(&AuthPortHandle, 365 &ObjectAttributes, 366 sizeof(LSA_CONNECTION_INFO), 367 sizeof(LSA_API_MSG), 368 sizeof(LSA_API_MSG) * 32); 369 if (!NT_SUCCESS(Status)) 370 { 371 WARN("NtCreatePort() failed (Status %lx)\n", Status); 372 return Status; 373 } 374 375 RtlInitUnicodeString(&EventName, 376 L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED"); 377 InitializeObjectAttributes(&ObjectAttributes, 378 &EventName, 379 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 380 NULL, 381 NULL); 382 Status = NtOpenEvent(&EventHandle, 383 EVENT_MODIFY_STATE, 384 &ObjectAttributes); 385 if (!NT_SUCCESS(Status)) 386 { 387 TRACE("NtOpenEvent failed (Status 0x%08lx)\n", Status); 388 389 Status = NtCreateEvent(&EventHandle, 390 EVENT_MODIFY_STATE, 391 &ObjectAttributes, 392 NotificationEvent, 393 FALSE); 394 if (!NT_SUCCESS(Status)) 395 { 396 WARN("NtCreateEvent failed (Status 0x%08lx)\n", Status); 397 return Status; 398 } 399 } 400 401 Status = NtSetEvent(EventHandle, NULL); 402 NtClose(EventHandle); 403 if (!NT_SUCCESS(Status)) 404 { 405 WARN("NtSetEvent failed (Status 0x%08lx)\n", Status); 406 return Status; 407 } 408 409 PortThreadHandle = CreateThread(NULL, 410 0x1000, 411 (LPTHREAD_START_ROUTINE)AuthPortThreadRoutine, 412 NULL, 413 0, 414 &ThreadId); 415 416 417 return STATUS_SUCCESS; 418 } 419 420 /* EOF */ 421