From 0c6fe80059cd554fead2ce632be0050a6e6e949c Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Wed, 20 Sep 2017 00:16:24 -0400 Subject: [PATCH] InteropMessage can only be called by the same user that runs the service --- TGServerService/Administration.cs | 259 ++++++++++++++++-------------- 1 file changed, 140 insertions(+), 119 deletions(-) diff --git a/TGServerService/Administration.cs b/TGServerService/Administration.cs index bc9f171782..1040501497 100644 --- a/TGServerService/Administration.cs +++ b/TGServerService/Administration.cs @@ -6,132 +6,153 @@ using TGServiceInterface; namespace TGServerService { - //note this only works with MACHINE LOCAL groups and admins for now - //if someone wants AD shit, code it yourself - partial class TGStationServer : ServiceAuthorizationManager, ITGAdministration - { - SecurityIdentifier TheDroidsWereLookingFor; - object authLock = new object(); - string LastSeenUser = null; + //note this only works with MACHINE LOCAL groups and admins for now + //if someone wants AD shit, code it yourself + partial class TGStationServer : ServiceAuthorizationManager, ITGAdministration + { + SecurityIdentifier TheDroidsWereLookingFor; + object authLock = new object(); + string LastSeenUser = null; - /// - public string GetCurrentAuthorizedGroup() - { - try - { - if (TheDroidsWereLookingFor == null) - return "ADMIN"; + readonly SecurityIdentifier ServiceSID = UserPrincipal.Current.Sid; - var pc = new PrincipalContext(ContextType.Machine); - return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name; - } - catch - { - return null; - } - } + /// + public string GetCurrentAuthorizedGroup() + { + try + { + if (TheDroidsWereLookingFor == null) + return "ADMIN"; - /// - public string SetAuthorizedGroup(string groupName) - { - if(groupName == null) - { - TheDroidsWereLookingFor = null; - var config = Properties.Settings.Default; - config.AuthorizedGroupSID = null; - config.Save(); - return "ADMIN"; - } - return FindTheDroidsWereLookingFor(groupName); - } + var pc = new PrincipalContext(ContextType.Machine); + return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name; + } + catch + { + return null; + } + } - string FindTheDroidsWereLookingFor(string search = null) - { - //find the group that is authorized to use the tools - var pc = new PrincipalContext(ContextType.Machine); - var config = Properties.Settings.Default; - var groupName = search ?? config.AuthorizedGroupSID; - if (String.IsNullOrWhiteSpace(groupName)) - return null; - var gp = GroupPrincipal.FindByIdentity(pc, search != null ? IdentityType.Name : IdentityType.Sid, groupName); - if (gp == null) - { - if (search != null) - //try again with all types - gp = GroupPrincipal.FindByIdentity(pc, search); - if (gp == null) - return null; - } - TheDroidsWereLookingFor = gp.Sid; - if (search != null) - { - config.AuthorizedGroupSID = TheDroidsWereLookingFor.Value; - config.Save(); - } - return gp.Name; - } + /// + public string SetAuthorizedGroup(string groupName) + { + if (groupName == null) + { + TheDroidsWereLookingFor = null; + var config = Properties.Settings.Default; + config.AuthorizedGroupSID = null; + config.Save(); + return "ADMIN"; + } + return FindTheDroidsWereLookingFor(groupName); + } - //This function checks for authorization whenever an API call is made - //This does NOT validate the windows account, that is done when the user connects internally - protected override bool CheckAccessCore(OperationContext operationContext) - { - if (operationContext.EndpointDispatcher.ContractName == typeof(ITGConnectivity).Name) //always allow connectivity checks - return true; + string FindTheDroidsWereLookingFor(string search = null) + { + //find the group that is authorized to use the tools + var pc = new PrincipalContext(ContextType.Machine); + var config = Properties.Settings.Default; + var groupName = search ?? config.AuthorizedGroupSID; + if (String.IsNullOrWhiteSpace(groupName)) + return null; + var gp = GroupPrincipal.FindByIdentity(pc, search != null ? IdentityType.Name : IdentityType.Sid, groupName); + if (gp == null) + { + if (search != null) + //try again with all types + gp = GroupPrincipal.FindByIdentity(pc, search); + if (gp == null) + return null; + } + TheDroidsWereLookingFor = gp.Sid; + if (search != null) + { + config.AuthorizedGroupSID = TheDroidsWereLookingFor.Value; + config.Save(); + } + return gp.Name; + } - var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity; - var wp = new WindowsPrincipal(windowsIdent); - //first allow admins - var authSuccess = wp.IsInRole(WindowsBuiltInRole.Administrator); + static UserPrincipal WindowsIdentityToUserPrincipal(WindowsIdentity windowsIdent, out PrincipalContext pc) + { + pc = new PrincipalContext(ContextType.Machine); + var up = UserPrincipal.FindByIdentity(pc, IdentityType.Sid, windowsIdent.User.Value); + //tiny bit of ad support here just cause i was debugging at work + //if up is null check it on a domain + if (up == null) + try + { + up = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), IdentityType.Sid, windowsIdent.User.Value); + } + catch { } + return up; + } - //if we're not an admin, check that we aren't trying to access the admin interface - if (!authSuccess && operationContext.EndpointDispatcher.ContractName != typeof(ITGAdministration).Name && TheDroidsWereLookingFor != null) - { - var pc = new PrincipalContext(ContextType.Machine); - var up = UserPrincipal.FindByIdentity(pc, IdentityType.Sid, windowsIdent.User.Value); - //tiny bit of ad support here just cause i was debugging at work - //if up is null check it on a domain - if (up == null) - try - { - up = UserPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain), IdentityType.Sid, windowsIdent.User.Value); - } - catch { } - if (up != null) - { - var gp = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value); - if (gp != null) - { - //and allow those in the authorized group - authSuccess = up.IsMemberOf(gp); - } - } - } - lock (authLock) - { - var user = operationContext.ServiceSecurityContext.WindowsIdentity.Name; - if (LastSeenUser != user) { - LastSeenUser = user; - TGServerService.WriteAccess(user, authSuccess); - } - } - return authSuccess; - } + //This function checks for authorization whenever an API call is made + //This does NOT validate the windows account, that is done when the user connects internally + protected override bool CheckAccessCore(OperationContext operationContext) + { + if (operationContext.EndpointDispatcher.ContractName == typeof(ITGConnectivity).Name) //always allow connectivity checks + return true; - /// - public ushort RemoteAccessPort() - { - return Properties.Settings.Default.RemoteAccessPort; - } + var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity; + var wp = new WindowsPrincipal(windowsIdent); - /// - public string SetRemoteAccessPort(ushort port) - { - if (port == 0) - return "Cannot bind to port 0"; - var Config = Properties.Settings.Default; - Config.RemoteAccessPort = port; - Config.Save(); - return null; - } - } + bool authSuccess; + var isInterop = operationContext.EndpointDispatcher.ContractName == typeof(ITGInterop).Name; + if (isInterop) + { + //only DD is allowed to use Interop + //make sure it's from the same windows account + var up = WindowsIdentityToUserPrincipal(windowsIdent, out PrincipalContext pc); + authSuccess = up.Sid != ServiceSID; + } + else + //first allow admins + authSuccess = wp.IsInRole(WindowsBuiltInRole.Administrator); + + //if we're not an admin, check that we aren't trying to access the admin interface + if (!authSuccess && operationContext.EndpointDispatcher.ContractName != typeof(ITGAdministration).Name && TheDroidsWereLookingFor != null) + { + var up = WindowsIdentityToUserPrincipal(windowsIdent, out PrincipalContext pc); + if (up != null) + { + var gp = GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value); + if (gp != null) + { + //and allow those in the authorized group + authSuccess = up.IsMemberOf(gp); + } + } + } + if (!isInterop) + lock (authLock) + { + var user = operationContext.ServiceSecurityContext.WindowsIdentity.Name; + if (LastSeenUser != user) + { + LastSeenUser = user; + TGServerService.WriteAccess(user, authSuccess); + } + } + return authSuccess; + } + + /// + public ushort RemoteAccessPort() + { + return Properties.Settings.Default.RemoteAccessPort; + } + + /// + public string SetRemoteAccessPort(ushort port) + { + if (port == 0) + return "Cannot bind to port 0"; + var Config = Properties.Settings.Default; + Config.RemoteAccessPort = port; + Config.Save(); + return null; + } + } }