InteropMessage can only be called by the same user that runs the service

This commit is contained in:
Cyberboss
2017-09-20 00:16:24 -04:00
parent 152a99bbd1
commit 0c6fe80059
+140 -119
View File
@@ -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;
/// <inheritdoc />
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;
}
}
/// <inheritdoc />
public string GetCurrentAuthorizedGroup()
{
try
{
if (TheDroidsWereLookingFor == null)
return "ADMIN";
/// <inheritdoc />
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;
}
/// <inheritdoc />
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;
/// <inheritdoc />
public ushort RemoteAccessPort()
{
return Properties.Settings.Default.RemoteAccessPort;
}
var windowsIdent = operationContext.ServiceSecurityContext.WindowsIdentity;
var wp = new WindowsPrincipal(windowsIdent);
/// <inheritdoc />
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;
}
/// <inheritdoc />
public ushort RemoteAccessPort()
{
return Properties.Settings.Default.RemoteAccessPort;
}
/// <inheritdoc />
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;
}
}
}