1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: subsys/system/dhcp/pipe.c 5 * PURPOSE: DHCP client pipe 6 * PROGRAMMER: arty 7 */ 8 9 #include <rosdhcp.h> 10 11 #define NDEBUG 12 #include <reactos/debug.h> 13 14 #define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DHCP_REQ) 15 #define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DHCP_REPLY) 16 #define COMM_PIPE_DEFAULT_TIMEOUT 1000 17 18 DWORD PipeSend( HANDLE CommPipe, COMM_DHCP_REPLY *Reply ) { 19 DWORD Written = 0; 20 OVERLAPPED Overlapped = {0}; 21 BOOL Success = 22 WriteFile( CommPipe, 23 Reply, 24 sizeof(*Reply), 25 &Written, 26 &Overlapped); 27 if (!Success) 28 { 29 WaitForSingleObject(CommPipe, INFINITE); 30 Success = GetOverlappedResult(CommPipe, 31 &Overlapped, 32 &Written, 33 TRUE); 34 } 35 36 return Success ? Written : -1; 37 } 38 39 /** 40 * @brief 41 * Creates a security descriptor for the DHCP pipe 42 * service. 43 * 44 * @param[out] SecurityDescriptor 45 * A pointer to an allocated security descriptor 46 * for the DHCP pipe. 47 * 48 * @return 49 * ERROR_SUCCESS is returned if the function has 50 * successfully created the descriptor otherwise 51 * a Win32 error code is returned. 52 * 53 * @remarks 54 * Both admins and local system are given full power 55 * over the DHCP pipe whereas authenticated users 56 * and network operators can only read over this pipe. 57 * They can also execute it. 58 */ 59 DWORD CreateDhcpPipeSecurity( PSECURITY_DESCRIPTOR *SecurityDescriptor ) { 60 DWORD ErrCode; 61 PACL Dacl; 62 ULONG DaclSize, RelSDSize = 0; 63 PSECURITY_DESCRIPTOR AbsSD = NULL, RelSD = NULL; 64 PSID AuthenticatedUsersSid = NULL, NetworkOpsSid = NULL, AdminsSid = NULL, SystemSid = NULL; 65 static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; 66 67 if (!AllocateAndInitializeSid(&NtAuthority, 68 1, 69 SECURITY_AUTHENTICATED_USER_RID, 70 0, 0, 0, 0, 0, 0, 0, 71 &AuthenticatedUsersSid)) 72 { 73 DPRINT1("CreateDhcpPipeSecurity(): Failed to create Authenticated Users SID (error code %d)\n", GetLastError()); 74 return GetLastError(); 75 } 76 77 if (!AllocateAndInitializeSid(&NtAuthority, 78 2, 79 SECURITY_BUILTIN_DOMAIN_RID, 80 DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS, 81 0, 0, 0, 0, 0, 0, 82 &NetworkOpsSid)) 83 { 84 DPRINT1("CreateDhcpPipeSecurity(): Failed to create Network Ops SID (error code %d)\n", GetLastError()); 85 ErrCode = GetLastError(); 86 goto Quit; 87 } 88 89 if (!AllocateAndInitializeSid(&NtAuthority, 90 2, 91 SECURITY_BUILTIN_DOMAIN_RID, 92 DOMAIN_ALIAS_RID_ADMINS, 93 0, 0, 0, 0, 0, 0, 94 &AdminsSid)) 95 { 96 DPRINT1("CreateDhcpPipeSecurity(): Failed to create Admins SID (error code %d)\n", GetLastError()); 97 ErrCode = GetLastError(); 98 goto Quit; 99 } 100 101 if (!AllocateAndInitializeSid(&NtAuthority, 102 1, 103 SECURITY_LOCAL_SYSTEM_RID, 104 0, 0, 0, 0, 0, 0, 0, 105 &SystemSid)) 106 { 107 DPRINT1("CreateDhcpPipeSecurity(): Failed to create Local System SID (error code %d)\n", GetLastError()); 108 ErrCode = GetLastError(); 109 goto Quit; 110 } 111 112 AbsSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SECURITY_DESCRIPTOR)); 113 if (!AbsSD) 114 { 115 DPRINT1("CreateDhcpPipeSecurity(): Failed to allocate absolute security descriptor!\n"); 116 ErrCode = ERROR_OUTOFMEMORY; 117 goto Quit; 118 } 119 120 if (!InitializeSecurityDescriptor(AbsSD, SECURITY_DESCRIPTOR_REVISION)) 121 { 122 DPRINT1("CreateDhcpPipeSecurity(): Failed to initialize absolute security descriptor (error code %d)\n", GetLastError()); 123 ErrCode = GetLastError(); 124 goto Quit; 125 } 126 127 DaclSize = sizeof(ACL) + 128 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AuthenticatedUsersSid) + 129 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(NetworkOpsSid) + 130 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(AdminsSid) + 131 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(SystemSid); 132 133 Dacl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize); 134 if (!Dacl) 135 { 136 DPRINT1("CreateDhcpPipeSecurity(): Failed to allocate DACL!\n"); 137 ErrCode = ERROR_OUTOFMEMORY; 138 goto Quit; 139 } 140 141 if (!InitializeAcl(Dacl, DaclSize, ACL_REVISION)) 142 { 143 DPRINT1("CreateDhcpPipeSecurity(): Failed to initialize DACL (error code %d)\n", GetLastError()); 144 ErrCode = GetLastError(); 145 goto Quit; 146 } 147 148 if (!AddAccessAllowedAce(Dacl, 149 ACL_REVISION, 150 GENERIC_READ | GENERIC_EXECUTE, 151 AuthenticatedUsersSid)) 152 { 153 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up ACE for Authenticated Users SID (error code %d)\n", GetLastError()); 154 ErrCode = GetLastError(); 155 goto Quit; 156 } 157 158 if (!AddAccessAllowedAce(Dacl, 159 ACL_REVISION, 160 GENERIC_READ | GENERIC_EXECUTE, 161 NetworkOpsSid)) 162 { 163 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up ACE for Network Ops SID (error code %d)\n", GetLastError()); 164 ErrCode = GetLastError(); 165 goto Quit; 166 } 167 168 if (!AddAccessAllowedAce(Dacl, 169 ACL_REVISION, 170 GENERIC_ALL, 171 AdminsSid)) 172 { 173 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up ACE for Admins SID (error code %d)\n", GetLastError()); 174 ErrCode = GetLastError(); 175 goto Quit; 176 } 177 178 if (!AddAccessAllowedAce(Dacl, 179 ACL_REVISION, 180 GENERIC_ALL, 181 SystemSid)) 182 { 183 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up ACE for Local System SID (error code %d)\n", GetLastError()); 184 ErrCode = GetLastError(); 185 goto Quit; 186 } 187 188 if (!SetSecurityDescriptorDacl(AbsSD, TRUE, Dacl, FALSE)) 189 { 190 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up DACL to absolute security descriptor (error code %d)\n", GetLastError()); 191 ErrCode = GetLastError(); 192 goto Quit; 193 } 194 195 if (!SetSecurityDescriptorOwner(AbsSD, AdminsSid, FALSE)) 196 { 197 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up owner to absolute security descriptor (error code %d)\n", GetLastError()); 198 ErrCode = GetLastError(); 199 goto Quit; 200 } 201 202 if (!SetSecurityDescriptorGroup(AbsSD, SystemSid, FALSE)) 203 { 204 DPRINT1("CreateDhcpPipeSecurity(): Failed to set up group to absolute security descriptor (error code %d)\n", GetLastError()); 205 ErrCode = GetLastError(); 206 goto Quit; 207 } 208 209 if (!MakeSelfRelativeSD(AbsSD, NULL, &RelSDSize) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 210 { 211 DPRINT1("CreateDhcpPipeSecurity(): Unexpected error code (error code %d -- must be ERROR_INSUFFICIENT_BUFFER)\n", GetLastError()); 212 ErrCode = GetLastError(); 213 goto Quit; 214 } 215 216 RelSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, RelSDSize); 217 if (RelSD == NULL) 218 { 219 DPRINT1("CreateDhcpPipeSecurity(): Failed to allocate relative SD!\n"); 220 ErrCode = ERROR_OUTOFMEMORY; 221 goto Quit; 222 } 223 224 if (!MakeSelfRelativeSD(AbsSD, RelSD, &RelSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 225 { 226 DPRINT1("CreateDhcpPipeSecurity(): Failed to allocate relative SD, buffer too smal (expected size %lu)\n", RelSDSize); 227 ErrCode = ERROR_INSUFFICIENT_BUFFER; 228 goto Quit; 229 } 230 231 *SecurityDescriptor = RelSD; 232 ErrCode = ERROR_SUCCESS; 233 234 Quit: 235 if (ErrCode != ERROR_SUCCESS) 236 { 237 if (RelSD) 238 { 239 HeapFree(GetProcessHeap(), 0, RelSD); 240 } 241 } 242 243 if (AuthenticatedUsersSid) 244 { 245 FreeSid(AuthenticatedUsersSid); 246 } 247 248 if (NetworkOpsSid) 249 { 250 FreeSid(NetworkOpsSid); 251 } 252 253 if (AdminsSid) 254 { 255 FreeSid(AdminsSid); 256 } 257 258 if (SystemSid) 259 { 260 FreeSid(SystemSid); 261 } 262 263 if (Dacl) 264 { 265 HeapFree(GetProcessHeap(), 0, Dacl); 266 } 267 268 if (AbsSD) 269 { 270 HeapFree(GetProcessHeap(), 0, AbsSD); 271 } 272 273 return ErrCode; 274 } 275 276 DWORD WINAPI PipeThreadProc( LPVOID Parameter ) { 277 DWORD BytesRead; 278 COMM_DHCP_REQ Req; 279 COMM_DHCP_REPLY Reply; 280 BOOL Result, Connected; 281 HANDLE Events[2]; 282 HANDLE CommPipe; 283 OVERLAPPED Overlapped = {0}; 284 DWORD dwError; 285 SECURITY_ATTRIBUTES SecurityAttributes; 286 PSECURITY_DESCRIPTOR DhcpPipeSD = NULL; 287 288 DPRINT("PipeThreadProc(%p)\n", Parameter); 289 290 dwError = CreateDhcpPipeSecurity(&DhcpPipeSD); 291 if (dwError != ERROR_SUCCESS) 292 { 293 DbgPrint("DHCP: Could not create security descriptor for pipe\n"); 294 return FALSE; 295 } 296 297 SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); 298 SecurityAttributes.lpSecurityDescriptor = DhcpPipeSD; 299 SecurityAttributes.bInheritHandle = FALSE; 300 301 CommPipe = CreateNamedPipeW 302 ( DHCP_PIPE_NAME, 303 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, 304 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 305 1, 306 COMM_PIPE_OUTPUT_BUFFER, 307 COMM_PIPE_INPUT_BUFFER, 308 COMM_PIPE_DEFAULT_TIMEOUT, 309 &SecurityAttributes ); 310 HeapFree(GetProcessHeap(), 0, DhcpPipeSD); 311 if (CommPipe == INVALID_HANDLE_VALUE) 312 { 313 DbgPrint("DHCP: Could not create named pipe\n"); 314 return FALSE; 315 } 316 317 Events[0] = (HANDLE)Parameter; 318 Events[1] = CommPipe; 319 320 while( TRUE ) 321 { 322 Connected = ConnectNamedPipe(CommPipe, &Overlapped); 323 if (!Connected) 324 { 325 dwError = GetLastError(); 326 if (dwError == ERROR_IO_PENDING) 327 { 328 dwError = WaitForMultipleObjects(2, Events, FALSE, INFINITE); 329 DPRINT("WaitForMultipleObjects() returned %lu\n", dwError); 330 if (dwError == WAIT_OBJECT_0 + 1) 331 { 332 Connected = GetOverlappedResult(CommPipe, 333 &Overlapped, 334 &BytesRead, 335 TRUE); 336 } 337 else if (dwError == WAIT_OBJECT_0) 338 { 339 CancelIo(CommPipe); 340 CloseHandle(CommPipe); 341 CommPipe = INVALID_HANDLE_VALUE; 342 break; 343 } 344 } 345 } 346 347 if (!Connected) { 348 DbgPrint("DHCP: Could not connect named pipe\n"); 349 CloseHandle( CommPipe ); 350 CommPipe = INVALID_HANDLE_VALUE; 351 break; 352 } 353 354 Result = ReadFile(CommPipe, &Req, sizeof(Req), &BytesRead, &Overlapped); 355 if (!Result) 356 { 357 dwError = GetLastError(); 358 if (dwError == ERROR_IO_PENDING) 359 { 360 dwError = WaitForMultipleObjects(2, Events, FALSE, INFINITE); 361 DPRINT("WaitForMultipleObjects() returned %lu\n", dwError); 362 if (dwError == WAIT_OBJECT_0 + 1) 363 { 364 Result = GetOverlappedResult(CommPipe, 365 &Overlapped, 366 &BytesRead, 367 TRUE); 368 } 369 else if (dwError == WAIT_OBJECT_0) 370 { 371 CancelIo(CommPipe); 372 DisconnectNamedPipe( CommPipe ); 373 CloseHandle(CommPipe); 374 CommPipe = INVALID_HANDLE_VALUE; 375 break; 376 } 377 } 378 } 379 380 if( Result ) { 381 switch( Req.Type ) { 382 case DhcpReqQueryHWInfo: 383 DSQueryHWInfo( PipeSend, CommPipe, &Req ); 384 break; 385 386 case DhcpReqLeaseIpAddress: 387 DSLeaseIpAddress( PipeSend, CommPipe, &Req ); 388 break; 389 390 case DhcpReqReleaseIpAddress: 391 DSReleaseIpAddressLease( PipeSend, CommPipe, &Req ); 392 break; 393 394 case DhcpReqRenewIpAddress: 395 DSRenewIpAddressLease( PipeSend, CommPipe, &Req ); 396 break; 397 398 case DhcpReqStaticRefreshParams: 399 DSStaticRefreshParams( PipeSend, CommPipe, &Req ); 400 break; 401 402 case DhcpReqGetAdapterInfo: 403 DSGetAdapterInfo( PipeSend, CommPipe, &Req ); 404 break; 405 406 default: 407 DPRINT1("Unrecognized request type %d\n", Req.Type); 408 ZeroMemory( &Reply, sizeof( COMM_DHCP_REPLY ) ); 409 Reply.Reply = 0; 410 PipeSend(CommPipe, &Reply ); 411 break; 412 } 413 } 414 DisconnectNamedPipe( CommPipe ); 415 } 416 417 DPRINT("Pipe thread stopped!\n"); 418 419 return TRUE; 420 } 421 422 HANDLE PipeInit(HANDLE hStopEvent) 423 { 424 return CreateThread( NULL, 0, PipeThreadProc, (LPVOID)hStopEvent, 0, NULL); 425 } 426