Process Hacker
secedit.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * object security editor
4  *
5  * Copyright (C) 2010 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phgui.h>
24 #include <secedit.h>
25 #include <seceditp.h>
26 
27 static ISecurityInformationVtbl PhSecurityInformation_VTable =
28 {
39 };
40 
41 static PH_INITONCE SecurityEditorInitOnce = PH_INITONCE_INIT;
42 static _CreateSecurityPage CreateSecurityPage_I;
43 static _EditSecurity EditSecurity_I;
44 
46  VOID
47  )
48 {
49  if (PhBeginInitOnce(&SecurityEditorInitOnce))
50  {
51  HMODULE aclui;
52 
53  aclui = LoadLibrary(L"aclui.dll");
54  CreateSecurityPage_I = (PVOID)GetProcAddress(aclui, "CreateSecurityPage");
55  EditSecurity_I = (PVOID)GetProcAddress(aclui, "EditSecurity");
56 
57  PhEndInitOnce(&SecurityEditorInitOnce);
58  }
59 }
60 
73 HPROPSHEETPAGE PhCreateSecurityPage(
74  _In_ PWSTR ObjectName,
75  _In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
76  _In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
77  _In_opt_ PVOID Context,
78  _In_ PPH_ACCESS_ENTRY AccessEntries,
79  _In_ ULONG NumberOfAccessEntries
80  )
81 {
82  ISecurityInformation *info;
83  HPROPSHEETPAGE page;
84 
86 
87  if (!CreateSecurityPage_I)
88  return NULL;
89 
91  ObjectName,
92  GetObjectSecurity,
93  SetObjectSecurity,
94  Context,
95  AccessEntries,
96  NumberOfAccessEntries
97  );
98 
99  page = CreateSecurityPage_I(info);
100 
102 
103  return page;
104 }
105 
120  _In_ HWND hWnd,
121  _In_ PWSTR ObjectName,
122  _In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
123  _In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
124  _In_opt_ PVOID Context,
125  _In_ PPH_ACCESS_ENTRY AccessEntries,
126  _In_ ULONG NumberOfAccessEntries
127  )
128 {
129  ISecurityInformation *info;
130 
132 
133  if (!EditSecurity_I)
134  return;
135 
137  ObjectName,
138  GetObjectSecurity,
139  SetObjectSecurity,
140  Context,
141  AccessEntries,
142  NumberOfAccessEntries
143  );
144 
145  EditSecurity_I(hWnd, info);
146 
148 }
149 
150 ISecurityInformation *PhSecurityInformation_Create(
151  _In_ PWSTR ObjectName,
152  _In_ PPH_GET_OBJECT_SECURITY GetObjectSecurity,
153  _In_ PPH_SET_OBJECT_SECURITY SetObjectSecurity,
154  _In_opt_ PVOID Context,
155  _In_ PPH_ACCESS_ENTRY AccessEntries,
156  _In_ ULONG NumberOfAccessEntries
157  )
158 {
159  PhSecurityInformation *info;
160  ULONG i;
161 
162  info = PhAllocate(sizeof(PhSecurityInformation));
163  info->VTable = &PhSecurityInformation_VTable;
164  info->RefCount = 1;
165 
166  info->ObjectName = PhCreateString(ObjectName);
167  info->GetObjectSecurity = GetObjectSecurity;
168  info->SetObjectSecurity = SetObjectSecurity;
169  info->Context = Context;
170  info->AccessEntries = PhAllocate(sizeof(SI_ACCESS) * NumberOfAccessEntries);
171  info->NumberOfAccessEntries = NumberOfAccessEntries;
172 
173  for (i = 0; i < NumberOfAccessEntries; i++)
174  {
175  memset(&info->AccessEntries[i], 0, sizeof(SI_ACCESS));
176  info->AccessEntries[i].pszName = AccessEntries[i].Name;
177  info->AccessEntries[i].mask = AccessEntries[i].Access;
178 
179  if (AccessEntries[i].General)
180  info->AccessEntries[i].dwFlags |= SI_ACCESS_GENERAL;
181  if (AccessEntries[i].Specific)
182  info->AccessEntries[i].dwFlags |= SI_ACCESS_SPECIFIC;
183  }
184 
185  return (ISecurityInformation *)info;
186 }
187 
188 HRESULT STDMETHODCALLTYPE PhSecurityInformation_QueryInterface(
189  _In_ ISecurityInformation *This,
190  _In_ REFIID Riid,
191  _Out_ PVOID *Object
192  )
193 {
194  if (
195  IsEqualIID(Riid, &IID_IUnknown) ||
196  IsEqualIID(Riid, &IID_ISecurityInformation)
197  )
198  {
200  *Object = This;
201  return S_OK;
202  }
203 
204  *Object = NULL;
205  return E_NOINTERFACE;
206 }
207 
208 ULONG STDMETHODCALLTYPE PhSecurityInformation_AddRef(
209  _In_ ISecurityInformation *This
210  )
211 {
213 
214  this->RefCount++;
215 
216  return this->RefCount;
217 }
218 
219 ULONG STDMETHODCALLTYPE PhSecurityInformation_Release(
220  _In_ ISecurityInformation *This
221  )
222 {
224 
225  this->RefCount--;
226 
227  if (this->RefCount == 0)
228  {
229  if (this->ObjectName) PhDereferenceObject(this->ObjectName);
230  PhFree(this->AccessEntries);
231 
232  PhFree(this);
233 
234  return 0;
235  }
236 
237  return this->RefCount;
238 }
239 
241  _In_ ISecurityInformation *This,
242  _Out_ PSI_OBJECT_INFO ObjectInfo
243  )
244 {
246 
247  memset(ObjectInfo, 0, sizeof(SI_OBJECT_INFO));
248  ObjectInfo->dwFlags =
249  SI_EDIT_AUDITS |
250  SI_EDIT_OWNER |
251  SI_EDIT_PERMS |
252  SI_ADVANCED |
253  SI_NO_ACL_PROTECT |
254  SI_NO_TREE_APPLY;
255  ObjectInfo->hInstance = NULL;
256  ObjectInfo->pszObjectName = this->ObjectName->Buffer;
257 
258  return S_OK;
259 }
260 
261 HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetSecurity(
262  _In_ ISecurityInformation *This,
263  _In_ SECURITY_INFORMATION RequestedInformation,
264  _Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
265  _In_ BOOL Default
266  )
267 {
269  NTSTATUS status;
270  PSECURITY_DESCRIPTOR securityDescriptor;
271  ULONG sdLength;
272  PSECURITY_DESCRIPTOR newSd;
273 
274  status = this->GetObjectSecurity(
275  &securityDescriptor,
276  RequestedInformation,
277  this->Context
278  );
279 
280  if (!NT_SUCCESS(status))
281  return HRESULT_FROM_WIN32(PhNtStatusToDosError(status));
282 
283  sdLength = RtlLengthSecurityDescriptor(securityDescriptor);
284  newSd = LocalAlloc(0, sdLength);
285  memcpy(newSd, securityDescriptor, sdLength);
286  PhFree(securityDescriptor);
287 
288  *SecurityDescriptor = newSd;
289 
290  return S_OK;
291 }
292 
293 HRESULT STDMETHODCALLTYPE PhSecurityInformation_SetSecurity(
294  _In_ ISecurityInformation *This,
295  _In_ SECURITY_INFORMATION SecurityInformation,
296  _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
297  )
298 {
300  NTSTATUS status;
301 
302  status = this->SetObjectSecurity(
303  SecurityDescriptor,
304  SecurityInformation,
305  this->Context
306  );
307 
308  if (!NT_SUCCESS(status))
309  return HRESULT_FROM_WIN32(PhNtStatusToDosError(status));
310 
311  return S_OK;
312 }
313 
314 HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetAccessRights(
315  _In_ ISecurityInformation *This,
316  _In_ const GUID *ObjectType,
317  _In_ ULONG Flags,
318  _Out_ PSI_ACCESS *Access,
319  _Out_ PULONG Accesses,
320  _Out_ PULONG DefaultAccess
321  )
322 {
324 
325  *Access = this->AccessEntries;
326  *Accesses = this->NumberOfAccessEntries;
327  *DefaultAccess = 0;
328 
329  return S_OK;
330 }
331 
332 HRESULT STDMETHODCALLTYPE PhSecurityInformation_MapGeneric(
333  _In_ ISecurityInformation *This,
334  _In_ const GUID *ObjectType,
335  _In_ PUCHAR AceFlags,
336  _Inout_ PACCESS_MASK Mask
337  )
338 {
339  return S_OK;
340 }
341 
342 HRESULT STDMETHODCALLTYPE PhSecurityInformation_GetInheritTypes(
343  _In_ ISecurityInformation *This,
344  _Out_ PSI_INHERIT_TYPE *InheritTypes,
345  _Out_ PULONG InheritTypesCount
346  )
347 {
348  return E_NOTIMPL;
349 }
350 
352  _In_ ISecurityInformation *This,
353  _In_ HWND hwnd,
354  _In_ UINT uMsg,
355  _In_ SI_PAGE_TYPE uPage
356  )
357 {
358  return E_NOTIMPL;
359 }
360 
362  _In_ HANDLE Handle,
363  _In_ SECURITY_INFORMATION SecurityInformation,
364  _Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor
365  )
366 {
367  NTSTATUS status;
368  ULONG bufferSize;
369  PVOID buffer;
370 
371  bufferSize = 0x100;
372  buffer = PhAllocate(bufferSize);
373  // This is required (especially for File objects) because some drivers don't seem to handle QuerySecurity properly.
374  memset(buffer, 0, bufferSize);
375 
377  Handle,
378  SecurityInformation,
379  buffer,
380  bufferSize,
381  &bufferSize
382  );
383 
384  if (status == STATUS_BUFFER_TOO_SMALL)
385  {
386  PhFree(buffer);
387  buffer = PhAllocate(bufferSize);
388  memset(buffer, 0, bufferSize);
389 
391  Handle,
392  SecurityInformation,
393  buffer,
394  bufferSize,
395  &bufferSize
396  );
397  }
398 
399  if (!NT_SUCCESS(status))
400  {
401  PhFree(buffer);
402  return status;
403  }
404 
405  *SecurityDescriptor = (PSECURITY_DESCRIPTOR)buffer;
406 
407  return status;
408 }
409 
424  _Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor,
425  _In_ SECURITY_INFORMATION SecurityInformation,
426  _In_opt_ PVOID Context
427  )
428 {
429  NTSTATUS status;
430  PPH_STD_OBJECT_SECURITY stdObjectSecurity;
431  HANDLE handle;
432 
433  stdObjectSecurity = (PPH_STD_OBJECT_SECURITY)Context;
434 
435  status = stdObjectSecurity->OpenObject(
436  &handle,
437  PhGetAccessForGetSecurity(SecurityInformation),
438  stdObjectSecurity->Context
439  );
440 
441  if (!NT_SUCCESS(status))
442  return status;
443 
444  if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"Service", TRUE))
445  {
446  status = PhGetSeObjectSecurity(handle, SE_SERVICE, SecurityInformation, SecurityDescriptor);
447  CloseServiceHandle(handle);
448  }
449  else if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"File", TRUE))
450  {
451  status = PhpGetObjectSecurityWithTimeout(handle, SecurityInformation, SecurityDescriptor);
452  NtClose(handle);
453  }
454  else
455  {
456  status = PhGetObjectSecurity(handle, SecurityInformation, SecurityDescriptor);
457  NtClose(handle);
458  }
459 
460  return status;
461 }
462 
476  _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
477  _In_ SECURITY_INFORMATION SecurityInformation,
478  _In_opt_ PVOID Context
479  )
480 {
481  NTSTATUS status;
482  PPH_STD_OBJECT_SECURITY stdObjectSecurity;
483  HANDLE handle;
484 
485  stdObjectSecurity = (PPH_STD_OBJECT_SECURITY)Context;
486 
487  status = stdObjectSecurity->OpenObject(
488  &handle,
489  PhGetAccessForSetSecurity(SecurityInformation),
490  stdObjectSecurity->Context
491  );
492 
493  if (!NT_SUCCESS(status))
494  return status;
495 
496  if (PhEqualStringZ(stdObjectSecurity->ObjectType, L"Service", TRUE))
497  {
498  status = PhSetSeObjectSecurity(handle, SE_SERVICE, SecurityInformation, SecurityDescriptor);
499  CloseServiceHandle(handle);
500  }
501  else
502  {
503  status = PhSetObjectSecurity(handle, SecurityInformation, SecurityDescriptor);
504  NtClose(handle);
505  }
506 
507  return status;
508 }
509 
511  _In_ HANDLE Handle,
512  _In_ ULONG ObjectType,
513  _In_ SECURITY_INFORMATION SecurityInformation,
514  _Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor
515  )
516 {
517  ULONG win32Result;
518  PSECURITY_DESCRIPTOR securityDescriptor;
519 
520  win32Result = GetSecurityInfo(
521  Handle,
522  ObjectType,
523  SecurityInformation,
524  NULL,
525  NULL,
526  NULL,
527  NULL,
528  &securityDescriptor
529  );
530 
531  if (win32Result != ERROR_SUCCESS)
532  return NTSTATUS_FROM_WIN32(win32Result);
533 
534  *SecurityDescriptor = PhAllocateCopy(securityDescriptor, RtlLengthSecurityDescriptor(securityDescriptor));
535  LocalFree(securityDescriptor);
536 
537  return STATUS_SUCCESS;
538 }
539 
541  _In_ HANDLE Handle,
542  _In_ ULONG ObjectType,
543  _In_ SECURITY_INFORMATION SecurityInformation,
544  _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
545  )
546 {
547  ULONG win32Result;
548  SECURITY_INFORMATION securityInformation = 0;
549  BOOLEAN present;
550  BOOLEAN defaulted;
551  PSID owner = NULL;
552  PSID group = NULL;
553  PACL dacl = NULL;
554  PACL sacl = NULL;
555 
556  if (SecurityInformation & OWNER_SECURITY_INFORMATION)
557  {
558  if (NT_SUCCESS(RtlGetOwnerSecurityDescriptor(SecurityDescriptor, &owner, &defaulted)))
559  securityInformation |= OWNER_SECURITY_INFORMATION;
560  }
561 
562  if (SecurityInformation & GROUP_SECURITY_INFORMATION)
563  {
564  if (NT_SUCCESS(RtlGetGroupSecurityDescriptor(SecurityDescriptor, &group, &defaulted)))
565  securityInformation |= GROUP_SECURITY_INFORMATION;
566  }
567 
568  if (SecurityInformation & DACL_SECURITY_INFORMATION)
569  {
570  if (NT_SUCCESS(RtlGetDaclSecurityDescriptor(SecurityDescriptor, &present, &dacl, &defaulted)) && present)
571  securityInformation |= DACL_SECURITY_INFORMATION;
572  }
573 
574  if (SecurityInformation & SACL_SECURITY_INFORMATION)
575  {
576  if (NT_SUCCESS(RtlGetSaclSecurityDescriptor(SecurityDescriptor, &present, &sacl, &defaulted)) && present)
577  securityInformation |= SACL_SECURITY_INFORMATION;
578  }
579 
580  win32Result = SetSecurityInfo(
581  Handle,
582  ObjectType,
583  SecurityInformation,
584  owner,
585  group,
586  dacl,
587  sacl
588  );
589 
590  if (win32Result != ERROR_SUCCESS)
591  return NTSTATUS_FROM_WIN32(win32Result);
592 
593  return STATUS_SUCCESS;
594 }