From 152a99bbd15b4ac8f1378011dbd08336dc2fcff6 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Tue, 19 Sep 2017 22:44:34 -0400 Subject: [PATCH 1/4] Rename ITGServiceBridge to ITGInterop --- TGServerService/Interop.cs | 2 +- TGServiceInterface/{ServiceBridge.cs => Interop.cs} | 4 ++-- TGServiceInterface/Server.cs | 2 +- TGServiceInterface/TGServiceInterface.csproj | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename TGServiceInterface/{ServiceBridge.cs => Interop.cs} (93%) diff --git a/TGServerService/Interop.cs b/TGServerService/Interop.cs index 121a762479..f176a8a374 100644 --- a/TGServerService/Interop.cs +++ b/TGServerService/Interop.cs @@ -11,7 +11,7 @@ using TGServiceInterface; namespace TGServerService { //handles talking between the world and us - partial class TGStationServer : ITGServiceBridge + partial class TGStationServer : ITGInterop { object topicLock = new object(); diff --git a/TGServiceInterface/ServiceBridge.cs b/TGServiceInterface/Interop.cs similarity index 93% rename from TGServiceInterface/ServiceBridge.cs rename to TGServiceInterface/Interop.cs index 764250ea36..fa5581f70b 100644 --- a/TGServiceInterface/ServiceBridge.cs +++ b/TGServiceInterface/Interop.cs @@ -10,7 +10,7 @@ namespace TGServiceInterface /// Used by DD to access the interop API with call()() /// [ServiceContract] - public interface ITGServiceBridge + public interface ITGInterop { /// /// Called from /world/ExportService(command) @@ -36,7 +36,7 @@ namespace TGServiceInterface { try { - ChannelFactory channel = null; + ChannelFactory channel = null; try { Server.GetComponentAndChannel(out channel).InteropMessage(String.Join(" ", args)); diff --git a/TGServiceInterface/Server.cs b/TGServiceInterface/Server.cs index 888f216561..0d735c161c 100644 --- a/TGServiceInterface/Server.cs +++ b/TGServiceInterface/Server.cs @@ -10,7 +10,7 @@ namespace TGServiceInterface /// /// List of types that can be used with GetComponen /// - public static readonly IList ValidInterfaces = new List { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGSService), typeof(ITGConnectivity), typeof(ITGAdministration), typeof(ITGServiceBridge) }; + public static readonly IList ValidInterfaces = new List { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGSService), typeof(ITGConnectivity), typeof(ITGAdministration), typeof(ITGInterop) }; /// /// Base name of the communication pipe diff --git a/TGServiceInterface/TGServiceInterface.csproj b/TGServiceInterface/TGServiceInterface.csproj index 6851600e9c..864ffc9a7b 100644 --- a/TGServiceInterface/TGServiceInterface.csproj +++ b/TGServiceInterface/TGServiceInterface.csproj @@ -57,7 +57,7 @@ - + From 0c6fe80059cd554fead2ce632be0050a6e6e949c Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Wed, 20 Sep 2017 00:16:24 -0400 Subject: [PATCH 2/4] 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; + } + } } From 13b5bae9a2aca9af4efb8937216967505a88a8b0 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Wed, 20 Sep 2017 10:01:24 -0400 Subject: [PATCH 3/4] TIL that WindowsIdentity DOES contain the Sid. It just has a cryptic ass name --- TGServerService/Administration.cs | 91 ++++++++++--------------------- 1 file changed, 30 insertions(+), 61 deletions(-) diff --git a/TGServerService/Administration.cs b/TGServerService/Administration.cs index 1040501497..2de29f907e 100644 --- a/TGServerService/Administration.cs +++ b/TGServerService/Administration.cs @@ -14,7 +14,7 @@ namespace TGServerService object authLock = new object(); string LastSeenUser = null; - readonly SecurityIdentifier ServiceSID = UserPrincipal.Current.Sid; + readonly SecurityIdentifier ServiceSID = WindowsIdentity.GetCurrent().User; /// public string GetCurrentAuthorizedGroup() @@ -73,70 +73,39 @@ namespace TGServerService return gp.Name; } - 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; - } + //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) + { + var contract = operationContext.EndpointDispatcher.ContractName; - //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; + if (contract == typeof(ITGConnectivity).Name) //always allow connectivity checks + return true; - var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity; - var wp = new WindowsPrincipal(windowsIdent); + var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity; - 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 (contract == typeof(ITGInterop).Name) //only allow the same user the service is running as to use interop, because that's what DD is running as + return windowsIdent.User == ServiceSID; - //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; - } + var wp = new WindowsPrincipal(windowsIdent); + //first allow admins + var 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) + authSuccess = wp.IsInRole(new SecurityIdentifier(Properties.Settings.Default.AuthorizedGroupSID)); + + lock (authLock) + { + var user = windowsIdent.Name; + if (LastSeenUser != user) + { + LastSeenUser = user; + TGServerService.WriteAccess(user, authSuccess); + } + } + return authSuccess; + } /// public ushort RemoteAccessPort() From ab1047db3657afab02292a5e95b359a6b0f1ac16 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Wed, 20 Sep 2017 10:15:34 -0400 Subject: [PATCH 4/4] TABS --- TGServerService/Administration.cs | 154 +++++++++++++++--------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/TGServerService/Administration.cs b/TGServerService/Administration.cs index 2de29f907e..80caa90f7b 100644 --- a/TGServerService/Administration.cs +++ b/TGServerService/Administration.cs @@ -6,72 +6,72 @@ 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; - readonly SecurityIdentifier ServiceSID = WindowsIdentity.GetCurrent().User; + readonly SecurityIdentifier ServiceSID = WindowsIdentity.GetCurrent().User; - /// - public string GetCurrentAuthorizedGroup() - { - try - { - if (TheDroidsWereLookingFor == null) - return "ADMIN"; + /// + public string GetCurrentAuthorizedGroup() + { + try + { + if (TheDroidsWereLookingFor == null) + return "ADMIN"; - var pc = new PrincipalContext(ContextType.Machine); - return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name; - } - catch - { - return null; - } - } + var pc = new PrincipalContext(ContextType.Machine); + return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name; + } + catch + { + return null; + } + } - /// - 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); - } + /// + 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); + } - 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; - } + 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; + } //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 @@ -107,21 +107,21 @@ namespace TGServerService return authSuccess; } - /// - public ushort RemoteAccessPort() - { - return Properties.Settings.Default.RemoteAccessPort; - } + /// + 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; - } - } + /// + 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; + } + } }