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 Context->TrustedCaller = RequestMsg->ConnectInfo.TrustedCaller; 139 140 if (Context->TrustedCaller) 141 Context->TrustedCaller = LsapIsTrustedClient(ProcessHandle); 142 143 *LogonContext = Context; 144 145 return STATUS_SUCCESS; 146 } 147 148 149 static NTSTATUS 150 LsapHandlePortConnection(PLSA_API_MSG RequestMsg) 151 { 152 PLSAP_LOGON_CONTEXT LogonContext = NULL; 153 HANDLE ConnectionHandle = NULL; 154 BOOLEAN Accept; 155 REMOTE_PORT_VIEW RemotePortView; 156 NTSTATUS Status = STATUS_SUCCESS; 157 158 TRACE("LsapHandlePortConnection(%p)\n", RequestMsg); 159 160 TRACE("Logon Process Name: %s\n", RequestMsg->ConnectInfo.LogonProcessNameBuffer); 161 162 if (RequestMsg->ConnectInfo.CreateContext != FALSE) 163 { 164 Status = LsapCheckLogonProcess(RequestMsg, 165 &LogonContext); 166 167 RequestMsg->ConnectInfo.OperationalMode = 0x43218765; 168 169 RequestMsg->ConnectInfo.Status = Status; 170 } 171 172 if (NT_SUCCESS(Status)) 173 { 174 Accept = TRUE; 175 } 176 else 177 { 178 Accept = FALSE; 179 } 180 181 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); 182 Status = NtAcceptConnectPort(&ConnectionHandle, 183 (PVOID*)LogonContext, 184 &RequestMsg->h, 185 Accept, 186 NULL, 187 &RemotePortView); 188 if (!NT_SUCCESS(Status)) 189 { 190 ERR("NtAcceptConnectPort failed (Status 0x%lx)\n", Status); 191 return Status; 192 } 193 194 if (Accept != FALSE) 195 { 196 if (LogonContext != NULL) 197 { 198 LogonContext->ConnectionHandle = ConnectionHandle; 199 200 InsertHeadList(&LsapLogonContextList, 201 &LogonContext->Entry); 202 } 203 204 Status = NtCompleteConnectPort(ConnectionHandle); 205 if (!NT_SUCCESS(Status)) 206 { 207 ERR("NtCompleteConnectPort failed (Status 0x%lx)\n", Status); 208 return Status; 209 } 210 } 211 212 return Status; 213 } 214 215 216 NTSTATUS WINAPI 217 AuthPortThreadRoutine(PVOID Param) 218 { 219 PLSAP_LOGON_CONTEXT LogonContext; 220 PLSA_API_MSG ReplyMsg = NULL; 221 LSA_API_MSG RequestMsg; 222 NTSTATUS Status; 223 224 TRACE("AuthPortThreadRoutine() called\n"); 225 226 Status = STATUS_SUCCESS; 227 228 for (;;) 229 { 230 TRACE("Reply: %p\n", ReplyMsg); 231 Status = NtReplyWaitReceivePort(AuthPortHandle, 232 (PVOID*)&LogonContext, 233 (PPORT_MESSAGE)ReplyMsg, 234 (PPORT_MESSAGE)&RequestMsg); 235 if (!NT_SUCCESS(Status)) 236 { 237 TRACE("NtReplyWaitReceivePort() failed (Status %lx)\n", Status); 238 break; 239 } 240 241 TRACE("Received message\n"); 242 243 switch (RequestMsg.h.u2.s2.Type) 244 { 245 case LPC_CONNECTION_REQUEST: 246 TRACE("Port connection request\n"); 247 Status = LsapHandlePortConnection(&RequestMsg); 248 ReplyMsg = NULL; 249 break; 250 251 case LPC_PORT_CLOSED: 252 TRACE("Port closed\n"); 253 ReplyMsg = NULL; 254 break; 255 256 case LPC_CLIENT_DIED: 257 TRACE("Client died\n"); 258 ReplyMsg = NULL; 259 break; 260 261 default: 262 TRACE("Received request (ApiNumber: %lu)\n", RequestMsg.ApiNumber); 263 264 switch (RequestMsg.ApiNumber) 265 { 266 case LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE: 267 RequestMsg.Status = LsapCallAuthenticationPackage(&RequestMsg, 268 LogonContext); 269 ReplyMsg = &RequestMsg; 270 break; 271 272 case LSASS_REQUEST_DEREGISTER_LOGON_PROCESS: 273 274 ReplyMsg = &RequestMsg; 275 RequestMsg.Status = STATUS_SUCCESS; 276 NtReplyPort(AuthPortHandle, 277 &ReplyMsg->h); 278 279 LsapDeregisterLogonProcess(&RequestMsg, 280 LogonContext); 281 282 ReplyMsg = NULL; 283 break; 284 285 case LSASS_REQUEST_LOGON_USER: 286 RequestMsg.Status = LsapLogonUser(&RequestMsg, 287 LogonContext); 288 ReplyMsg = &RequestMsg; 289 break; 290 291 case LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE: 292 RequestMsg.Status = LsapLookupAuthenticationPackage(&RequestMsg, 293 LogonContext); 294 ReplyMsg = &RequestMsg; 295 break; 296 297 case LSASS_REQUEST_ENUM_LOGON_SESSIONS: 298 RequestMsg.Status = LsapEnumLogonSessions(&RequestMsg); 299 ReplyMsg = &RequestMsg; 300 break; 301 302 case LSASS_REQUEST_GET_LOGON_SESSION_DATA: 303 RequestMsg.Status = LsapGetLogonSessionData(&RequestMsg); 304 ReplyMsg = &RequestMsg; 305 break; 306 307 case LSASS_REQUEST_POLICY_CHANGE_NOTIFY: 308 RequestMsg.Status = LsapRegisterNotification(&RequestMsg); 309 ReplyMsg = &RequestMsg; 310 break; 311 312 default: 313 RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE; 314 ReplyMsg = &RequestMsg; 315 break; 316 } 317 318 break; 319 } 320 } 321 322 return STATUS_SUCCESS; 323 } 324 325 326 NTSTATUS 327 StartAuthenticationPort(VOID) 328 { 329 OBJECT_ATTRIBUTES ObjectAttributes; 330 UNICODE_STRING PortName; 331 DWORD ThreadId; 332 UNICODE_STRING EventName; 333 HANDLE EventHandle; 334 NTSTATUS Status; 335 336 TRACE("StartAuthenticationPort()\n"); 337 338 /* Initialize the logon context list */ 339 InitializeListHead(&LsapLogonContextList); 340 341 RtlInitUnicodeString(&PortName, 342 L"\\LsaAuthenticationPort"); 343 344 InitializeObjectAttributes(&ObjectAttributes, 345 &PortName, 346 0, 347 NULL, 348 NULL); 349 350 Status = NtCreatePort(&AuthPortHandle, 351 &ObjectAttributes, 352 sizeof(LSA_CONNECTION_INFO), 353 sizeof(LSA_API_MSG), 354 sizeof(LSA_API_MSG) * 32); 355 if (!NT_SUCCESS(Status)) 356 { 357 WARN("NtCreatePort() failed (Status %lx)\n", Status); 358 return Status; 359 } 360 361 RtlInitUnicodeString(&EventName, 362 L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED"); 363 InitializeObjectAttributes(&ObjectAttributes, 364 &EventName, 365 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 366 NULL, 367 NULL); 368 Status = NtOpenEvent(&EventHandle, 369 EVENT_MODIFY_STATE, 370 &ObjectAttributes); 371 if (!NT_SUCCESS(Status)) 372 { 373 TRACE("NtOpenEvent failed (Status 0x%08lx)\n", Status); 374 375 Status = NtCreateEvent(&EventHandle, 376 EVENT_MODIFY_STATE, 377 &ObjectAttributes, 378 NotificationEvent, 379 FALSE); 380 if (!NT_SUCCESS(Status)) 381 { 382 WARN("NtCreateEvent failed (Status 0x%08lx)\n", Status); 383 return Status; 384 } 385 } 386 387 Status = NtSetEvent(EventHandle, NULL); 388 NtClose(EventHandle); 389 if (!NT_SUCCESS(Status)) 390 { 391 WARN("NtSetEvent failed (Status 0x%08lx)\n", Status); 392 return Status; 393 } 394 395 PortThreadHandle = CreateThread(NULL, 396 0x1000, 397 (LPTHREAD_START_ROUTINE)AuthPortThreadRoutine, 398 NULL, 399 0, 400 &ThreadId); 401 402 403 return STATUS_SUCCESS; 404 } 405 406 /* EOF */ 407