diff --git a/TGCommandLine/AdminCommands.cs b/TGCommandLine/AdminCommands.cs index 51a6c6a6fc..83d6eb4575 100644 --- a/TGCommandLine/AdminCommands.cs +++ b/TGCommandLine/AdminCommands.cs @@ -45,7 +45,7 @@ namespace TGCommandLine public override string GetHelpText() { - return "Search for and set the windows group allowed to use the service"; + return "Set the windows group allowed to use the service"; } public override string GetArgumentString() @@ -62,7 +62,7 @@ namespace TGCommandLine } else { - OutputProc("Search failed to find a group named: " + parameters[0]); + OutputProc("Failed to find a group named: " + parameters[0]); return ExitCode.ServerError; } } diff --git a/TGCommandLine/Program.cs b/TGCommandLine/Program.cs index b788f2bd39..0fcbd4d2f8 100644 --- a/TGCommandLine/Program.cs +++ b/TGCommandLine/Program.cs @@ -16,6 +16,13 @@ namespace TGCommandLine Console.WriteLine("Unable to connect to service: " + res); return ExitCode.ConnectionError; } + + if (!Server.Authenticate()) + { + Console.WriteLine("Authentication error! Username/password/windows identity is not authorized!"); + return ExitCode.ConnectionError; + } + try { return new CLICommand().DoRun(argsAsList); diff --git a/TGControlPanel/Program.cs b/TGControlPanel/Program.cs index 6fc61dc39d..6cab0b7326 100644 --- a/TGControlPanel/Program.cs +++ b/TGControlPanel/Program.cs @@ -24,6 +24,11 @@ namespace TGControlPanel MessageBox.Show("Unable to connect to service! Error: " + res); return; } + if (!Server.Authenticate()) + { + MessageBox.Show("Authentication error! Username/password/windows identity is not authorized!"); + return; + } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Main()); diff --git a/TGServerService/Administration.cs b/TGServerService/Administration.cs index 2e8cc2737c..d9b770306f 100644 --- a/TGServerService/Administration.cs +++ b/TGServerService/Administration.cs @@ -8,6 +8,8 @@ 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; @@ -17,7 +19,11 @@ namespace TGServerService { try { - return TheDroidsWereLookingFor != null ? TheDroidsWereLookingFor.Translate(typeof(GroupPrincipal)).ToString() : "ADMIN"; + if (TheDroidsWereLookingFor == null) + return "ADMIN"; + + var pc = new PrincipalContext(ContextType.Machine); + return GroupPrincipal.FindByIdentity(pc, IdentityType.Sid, TheDroidsWereLookingFor.Value).Name; } catch { @@ -32,7 +38,7 @@ namespace TGServerService { TheDroidsWereLookingFor = null; var config = Properties.Settings.Default; - config.AuthorizedGroupName = null; + config.AuthorizedGroupSID = null; config.Save(); return "ADMIN"; } @@ -44,33 +50,62 @@ namespace TGServerService //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.AuthorizedGroupName; + 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) - return 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.AuthorizedGroupName = TheDroidsWereLookingFor.Value; + 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 protected override bool CheckAccessCore(OperationContext operationContext) { if (operationContext.EndpointDispatcher.ContractName == typeof(ITGConnectivity).Name) //always allow connectivity checks return true; var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity; + var wp = new WindowsPrincipal(windowsIdent); //first allow admins - var authSuccess = new WindowsPrincipal(windowsIdent).IsInRole(WindowsBuiltInRole.Administrator); + 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) - //and allow those in the authorized group - authSuccess = (TheDroidsWereLookingFor != null || windowsIdent.Groups.Contains(TheDroidsWereLookingFor)); + 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); + } + } + } var actions = new List(); try diff --git a/TGServerService/App.config b/TGServerService/App.config index 601eff041c..152806066e 100644 --- a/TGServerService/App.config +++ b/TGServerService/App.config @@ -67,7 +67,7 @@ localhost - + diff --git a/TGServerService/Properties/Settings.Designer.cs b/TGServerService/Properties/Settings.Designer.cs index 6bbfbe6e30..0cdb11a2cc 100644 --- a/TGServerService/Properties/Settings.Designer.cs +++ b/TGServerService/Properties/Settings.Designer.cs @@ -254,12 +254,12 @@ namespace TGServerService.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("")] - public string AuthorizedGroupName { + public string AuthorizedGroupSID { get { - return ((string)(this["AuthorizedGroupName"])); + return ((string)(this["AuthorizedGroupSID"])); } set { - this["AuthorizedGroupName"] = value; + this["AuthorizedGroupSID"] = value; } } } diff --git a/TGServerService/Properties/Settings.settings b/TGServerService/Properties/Settings.settings index ee0d0945b7..c0a4589eb8 100644 --- a/TGServerService/Properties/Settings.settings +++ b/TGServerService/Properties/Settings.settings @@ -59,7 +59,7 @@ localhost - + diff --git a/TGServiceInterface/Administration.cs b/TGServiceInterface/Administration.cs index 6e222e2954..483e8dfb03 100644 --- a/TGServiceInterface/Administration.cs +++ b/TGServiceInterface/Administration.cs @@ -18,8 +18,8 @@ namespace TGServiceInterface /// /// Searches the windows machine for the group named , sets it as the authorized group if it's found /// - /// The name of the group to search for or null to clear the setting - /// The full name of the group that is now authorized on success, null on failure, "ADMIN" on clearing + /// The name of the windows group to search for or null to clear the setting + /// The name of the windows group that is now authorized to use the service on success, null on failure, "ADMIN" on clearing [OperationContract] string SetAuthorizedGroup(string groupName); }