| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Activation
- {
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.Runtime;
- using System.Runtime.InteropServices;
- using System.Security;
- using System.Security.AccessControl;
- using System.Security.Permissions;
- using System.Security.Principal;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.ComIntegration;
- using System.Text;
- unsafe static class Utility
- {
- const string WindowsServiceAccountFormat = "NT Service\\{0}";
- internal static Uri FormatListenerEndpoint(string serviceName, string listenerEndPoint)
- {
- UriBuilder builder = new UriBuilder(Uri.UriSchemeNetPipe, serviceName);
- builder.Path = string.Format(CultureInfo.InvariantCulture, "/{0}/", listenerEndPoint);
- return builder.Uri;
- }
- static SafeCloseHandle OpenCurrentProcessForWrite()
- {
- int processId = Process.GetCurrentProcess().Id;
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- SafeCloseHandle process = ListenerUnsafeNativeMethods.OpenProcess(ListenerUnsafeNativeMethods.PROCESS_QUERY_INFORMATION | ListenerUnsafeNativeMethods.WRITE_DAC | ListenerUnsafeNativeMethods.READ_CONTROL, false, processId);
- if (process.IsInvalid)
- {
- Exception exception = new Win32Exception();
- process.SetHandleAsInvalid();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
- }
- return process;
- }
- static SafeCloseHandle OpenProcessForQuery(int pid)
- {
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- SafeCloseHandle process = ListenerUnsafeNativeMethods.OpenProcess(ListenerUnsafeNativeMethods.PROCESS_QUERY_INFORMATION, false, pid);
- if (process.IsInvalid)
- {
- Exception exception = new Win32Exception();
- process.SetHandleAsInvalid();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
- }
- return process;
- }
- static SafeCloseHandle GetProcessToken(SafeCloseHandle process, int requiredAccess)
- {
- SafeCloseHandle processToken;
- bool success = ListenerUnsafeNativeMethods.OpenProcessToken(process, requiredAccess, out processToken);
- int error = Marshal.GetLastWin32Error();
- if (!success)
- {
- System.ServiceModel.Diagnostics.Utility.CloseInvalidOutSafeHandle(processToken);
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- return processToken;
- }
- static int GetTokenInformationLength(SafeCloseHandle token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS tic)
- {
- int lengthNeeded;
- bool success = ListenerUnsafeNativeMethods.GetTokenInformation(token, tic, null, 0, out lengthNeeded);
- if (!success)
- {
- int error = Marshal.GetLastWin32Error();
- if (error != ListenerUnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- }
- return lengthNeeded;
- }
- static void GetTokenInformation(SafeCloseHandle token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS tic, byte[] tokenInformation)
- {
- int lengthNeeded;
- if (!ListenerUnsafeNativeMethods.GetTokenInformation(token, tic, tokenInformation, tokenInformation.Length, out lengthNeeded))
- {
- int error = Marshal.GetLastWin32Error();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- }
- static SafeServiceHandle OpenSCManager()
- {
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- SafeServiceHandle scManager = ListenerUnsafeNativeMethods.OpenSCManager(null, null, ListenerUnsafeNativeMethods.SC_MANAGER_CONNECT);
- if (scManager.IsInvalid)
- {
- Exception exception = new Win32Exception();
- scManager.SetHandleAsInvalid();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
- }
- return scManager;
- }
- static SafeServiceHandle OpenService(SafeServiceHandle scManager, string serviceName, int purpose)
- {
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- SafeServiceHandle service = ListenerUnsafeNativeMethods.OpenService(scManager, serviceName, purpose);
- if (service.IsInvalid)
- {
- Exception exception = new Win32Exception();
- service.SetHandleAsInvalid();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
- }
- return service;
- }
- internal static void AddRightGrantedToAccounts(List<SecurityIdentifier> accounts, int right, bool onProcess)
- {
- SafeCloseHandle process = OpenCurrentProcessForWrite();
- try
- {
- if (onProcess)
- {
- EditKernelObjectSecurity(process, accounts, null, right, true);
- }
- else
- {
- SafeCloseHandle token = GetProcessToken(process, ListenerUnsafeNativeMethods.TOKEN_QUERY | ListenerUnsafeNativeMethods.WRITE_DAC | ListenerUnsafeNativeMethods.READ_CONTROL);
- try
- {
- EditKernelObjectSecurity(token, accounts, null, right, true);
- }
- finally
- {
- token.Close();
- }
- }
- }
- finally
- {
- process.Close();
- }
- }
- internal static void AddRightGrantedToAccount(SecurityIdentifier account, int right)
- {
- SafeCloseHandle process = OpenCurrentProcessForWrite();
- try
- {
- EditKernelObjectSecurity(process, null, account, right, true);
- }
- finally
- {
- process.Close();
- }
- }
- internal static void RemoveRightGrantedToAccount(SecurityIdentifier account, int right)
- {
- SafeCloseHandle process = OpenCurrentProcessForWrite();
- try
- {
- EditKernelObjectSecurity(process, null, account, right, false);
- }
- finally
- {
- process.Close();
- }
- }
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- internal static void KeepOnlyPrivilegeInProcess(string privilege)
- {
- SafeCloseHandle process = OpenCurrentProcessForWrite();
- try
- {
- SafeCloseHandle token = GetProcessToken(process, ListenerUnsafeNativeMethods.TOKEN_QUERY | ListenerUnsafeNativeMethods.TOKEN_ADJUST_PRIVILEGES | ListenerUnsafeNativeMethods.READ_CONTROL);
- try
- {
- LUID luid;
- bool success = ListenerUnsafeNativeMethods.LookupPrivilegeValue(IntPtr.Zero, privilege, &luid);
- if (!success)
- {
- int error = Marshal.GetLastWin32Error();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- int length = GetTokenInformationLength(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenPrivileges);
- byte[] tokenInformation = new byte[length];
- fixed (byte* pTokenPrivileges = tokenInformation)
- {
- GetTokenInformation(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenPrivileges,
- tokenInformation);
- ListenerUnsafeNativeMethods.TOKEN_PRIVILEGES* pTP = (ListenerUnsafeNativeMethods.TOKEN_PRIVILEGES*)pTokenPrivileges;
- LUID_AND_ATTRIBUTES* pLuidAndAttributes = (LUID_AND_ATTRIBUTES*)(&(pTP->Privileges));
- int privilegeCount = 0;
- for (int i = 0; i < pTP->PrivilegeCount; i++)
- {
- if (!pLuidAndAttributes[i].Luid.Equals(luid))
- {
- pLuidAndAttributes[privilegeCount].Attributes = PrivilegeAttribute.SE_PRIVILEGE_REMOVED;
- pLuidAndAttributes[privilegeCount].Luid = pLuidAndAttributes[i].Luid;
- privilegeCount++;
- }
- }
- pTP->PrivilegeCount = privilegeCount;
- success = ListenerUnsafeNativeMethods.AdjustTokenPrivileges(token, false, pTP, tokenInformation.Length, IntPtr.Zero, IntPtr.Zero);
- int error = Marshal.GetLastWin32Error();
- if (!success || error != UnsafeNativeMethods.ERROR_SUCCESS)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- }
- }
- finally
- {
- token.Close();
- }
- }
- finally
- {
- process.Close();
- }
- }
- // Do not use this method unless you understand the consequnces of lack of synchronization
- static void EditKernelObjectSecurity(SafeCloseHandle kernelObject, List<SecurityIdentifier> accounts, SecurityIdentifier account, int right, bool add)
- {
- // take the SECURITY_DESCRIPTOR from the kernelObject
- int lpnLengthNeeded;
- bool success = ListenerUnsafeNativeMethods.GetKernelObjectSecurity(kernelObject, ListenerUnsafeNativeMethods.DACL_SECURITY_INFORMATION, null, 0, out lpnLengthNeeded);
- if (!success)
- {
- int errorCode = Marshal.GetLastWin32Error();
- if (errorCode != ListenerUnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode));
- }
- }
- byte[] pSecurityDescriptor = new byte[lpnLengthNeeded];
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- success = ListenerUnsafeNativeMethods.GetKernelObjectSecurity(kernelObject, ListenerUnsafeNativeMethods.DACL_SECURITY_INFORMATION, pSecurityDescriptor, pSecurityDescriptor.Length, out lpnLengthNeeded);
- if (!success)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception());
- }
- CommonSecurityDescriptor securityDescriptor = new CommonSecurityDescriptor(false, false, pSecurityDescriptor, 0);
- DiscretionaryAcl dacl = securityDescriptor.DiscretionaryAcl;
- // add ACEs to the SECURITY_DESCRIPTOR of the kernelObject
- if (account != null)
- {
- EditDacl(dacl, account, right, add);
- }
- else if (accounts != null)
- {
- foreach (SecurityIdentifier accountInList in accounts)
- {
- EditDacl(dacl, accountInList, right, add);
- }
- }
- lpnLengthNeeded = securityDescriptor.BinaryLength;
- pSecurityDescriptor = new byte[lpnLengthNeeded];
- securityDescriptor.GetBinaryForm(pSecurityDescriptor, 0);
- // set the SECURITY_DESCRIPTOR on the kernelObject
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- success = ListenerUnsafeNativeMethods.SetKernelObjectSecurity(kernelObject, ListenerUnsafeNativeMethods.DACL_SECURITY_INFORMATION, pSecurityDescriptor);
- if (!success)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception());
- }
- }
- static void EditDacl(DiscretionaryAcl dacl, SecurityIdentifier account, int right, bool add)
- {
- if (add)
- {
- dacl.AddAccess(AccessControlType.Allow, account, right, InheritanceFlags.None, PropagationFlags.None);
- }
- else
- {
- dacl.RemoveAccess(AccessControlType.Allow, account, right, InheritanceFlags.None, PropagationFlags.None);
- }
- }
- internal static SecurityIdentifier GetWindowsServiceSid(string name)
- {
- Fx.Assert(OSEnvironmentHelper.IsVistaOrGreater, "This method can be called only on Vista or greater.");
- string accountName = string.Format(CultureInfo.InvariantCulture, WindowsServiceAccountFormat, name);
- byte[] sid = null;
- uint cbSid = 0;
- uint cchReferencedDomainName = 0;
- short peUse;
- int error = UnsafeNativeMethods.ERROR_SUCCESS;
- if (!ListenerUnsafeNativeMethods.LookupAccountName(null, accountName, sid, ref cbSid,
- null, ref cchReferencedDomainName, out peUse))
- {
- error = Marshal.GetLastWin32Error();
- if (error != ListenerUnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- }
- sid = new byte[cbSid];
- StringBuilder referencedDomainName = new StringBuilder((int)cchReferencedDomainName);
- if (!ListenerUnsafeNativeMethods.LookupAccountName(null, accountName, sid, ref cbSid,
- referencedDomainName, ref cchReferencedDomainName, out peUse))
- {
- error = Marshal.GetLastWin32Error();
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error));
- }
- return new SecurityIdentifier(sid, 0);
- }
- internal static int GetPidForService(string serviceName)
- {
- return GetStatusForService(serviceName).dwProcessId;
- }
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- internal static SecurityIdentifier GetLogonSidForPid(int pid)
- {
- SafeCloseHandle process = OpenProcessForQuery(pid);
- try
- {
- SafeCloseHandle token = GetProcessToken(process, ListenerUnsafeNativeMethods.TOKEN_QUERY);
- try
- {
- int length = GetTokenInformationLength(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenGroups);
- byte[] tokenInformation = new byte[length];
- fixed (byte* pTokenInformation = tokenInformation)
- {
- GetTokenInformation(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenGroups, tokenInformation);
- ListenerUnsafeNativeMethods.TOKEN_GROUPS* ptg = (ListenerUnsafeNativeMethods.TOKEN_GROUPS*)pTokenInformation;
- ListenerUnsafeNativeMethods.SID_AND_ATTRIBUTES* sids = (ListenerUnsafeNativeMethods.SID_AND_ATTRIBUTES*)(&(ptg->Groups));
- for (int i = 0; i < ptg->GroupCount; i++)
- {
- if ((sids[i].Attributes & ListenerUnsafeNativeMethods.SidAttribute.SE_GROUP_LOGON_ID) == ListenerUnsafeNativeMethods.SidAttribute.SE_GROUP_LOGON_ID)
- {
- return new SecurityIdentifier(sids[i].Sid);
- }
- }
- }
- return new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
- }
- finally
- {
- token.Close();
- }
- }
- finally
- {
- process.Close();
- }
- }
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- internal static SecurityIdentifier GetUserSidForPid(int pid)
- {
- SafeCloseHandle process = OpenProcessForQuery(pid);
- try
- {
- SafeCloseHandle token = GetProcessToken(process, ListenerUnsafeNativeMethods.TOKEN_QUERY);
- try
- {
- int length = GetTokenInformationLength(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenUser);
- byte[] tokenInformation = new byte[length];
- fixed (byte* pTokenInformation = tokenInformation)
- {
- GetTokenInformation(token, ListenerUnsafeNativeMethods.TOKEN_INFORMATION_CLASS.TokenUser, tokenInformation);
- ListenerUnsafeNativeMethods.TOKEN_USER* ptg = (ListenerUnsafeNativeMethods.TOKEN_USER*)pTokenInformation;
- ListenerUnsafeNativeMethods.SID_AND_ATTRIBUTES* sids = (ListenerUnsafeNativeMethods.SID_AND_ATTRIBUTES*)(&(ptg->User));
- return new SecurityIdentifier(sids->Sid);
- }
- }
- finally
- {
- token.Close();
- }
- }
- finally
- {
- process.Close();
- }
- }
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- static ListenerUnsafeNativeMethods.SERVICE_STATUS_PROCESS GetStatusForService(string serviceName)
- {
- SafeServiceHandle scManager = OpenSCManager();
- try
- {
- SafeServiceHandle service = OpenService(scManager, serviceName, ListenerUnsafeNativeMethods.SERVICE_QUERY_STATUS);
- try
- {
- int lpnLengthNeeded;
- bool success = ListenerUnsafeNativeMethods.QueryServiceStatusEx(service, ListenerUnsafeNativeMethods.SC_STATUS_PROCESS_INFO, null, 0, out lpnLengthNeeded);
- if (!success)
- {
- int errorCode = Marshal.GetLastWin32Error();
- if (errorCode != ListenerUnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(errorCode));
- }
- }
- byte[] serviceStatusProcess = new byte[lpnLengthNeeded];
- #pragma warning suppress 56523 // [....], Win32Exception ctor calls Marshal.GetLastWin32Error()
- success = ListenerUnsafeNativeMethods.QueryServiceStatusEx(service, ListenerUnsafeNativeMethods.SC_STATUS_PROCESS_INFO, serviceStatusProcess, serviceStatusProcess.Length, out lpnLengthNeeded);
- if (!success)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception());
- }
- fixed (byte* pServiceStatusProcess = serviceStatusProcess)
- {
- return (ListenerUnsafeNativeMethods.SERVICE_STATUS_PROCESS)Marshal.PtrToStructure((IntPtr)pServiceStatusProcess, typeof(ListenerUnsafeNativeMethods.SERVICE_STATUS_PROCESS));
- }
- }
- finally
- {
- service.Close();
- }
- }
- finally
- {
- scManager.Close();
- }
- }
- }
- }
|