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
PipeSend(HANDLE CommPipe,COMM_DHCP_REPLY * Reply)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 */
CreateDhcpPipeSecurity(PSECURITY_DESCRIPTOR * SecurityDescriptor)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
PipeThreadProc(LPVOID Parameter)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
PipeInit(HANDLE hStopEvent)422 HANDLE PipeInit(HANDLE hStopEvent)
423 {
424 return CreateThread( NULL, 0, PipeThreadProc, (LPVOID)hStopEvent, 0, NULL);
425 }
426