am newbie to both WCF and Named pipes.
I need a way to securely communicate between a UI application and Windows Service on the same machine. Here's what I need: - Client UI application needs to send (push) various message types to the Windows Service. - Client UI app needs will receive various message types from the service (pushed or pulled).
(message here is simply a structured serialized data).
Now all this exchange should happen only under authorized user account (which might be different from service account). So I was thinking of ACLing a named pipe for both the service and user account.
However, the named pipe supports streams only. I have multiple types of messag开发者_如何学Ces that need to be exchanged over the named pipe, which means I need to define them and serialize/deserialize them.
To circumvent this, I thought of using WCF (for serialization and RPC support) over named pipes. Also host WCF service in the Windows service.
Question 1) Is this a good approach ? I hesitate in using http or tcp below WCF as communication must remain within the machine.
Question 2) If and how can I ACL the named pipe that WCF would use ? Is this something that I can control ? I feel ACLing the name pipe with specific SIDs provides me better security as opposed to implementing an authentication scheme between client and server.
Thanks for any pointers, suggestions! Sameer
1) I think this is a good approach. Your thinking is spot on.
2) As you seem to have already discovered, my blog post here shows you one way to set the ACL on the pipe created by the WCF NetNamedPipe binding. It involves using reflection to fill in the gap in the Microsoft's implementation, which was obviosuly intended originally to support a direct mechanism for setting the ACL, but didn't get finished properly.
Derive a AclSecuredNamedPipeBinding
from CustomBinding
and a corresponding AclSecuredNamedPipeTransportBindingElement
from NamedPipeTransportBindingElement
. The binding element has a list of of SecurityIdentifier
:
internal List<SecurityIdentifier> AllowedUsers { get { return _allowedUsers; } }
private List<SecurityIdentifier> _allowedUsers = new List<SecurityIdentifier>();
The BuildChannelListener<TChannel>(BindingContext)
-method is overridden to set the private property AllowedUsers
:
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
private static Type namedPipeChannelListenerType
= Type.GetType("System.ServiceModel.Channels.NamedPipeChannelListener, System.ServiceModel", false);
IChannelListener<TChannel> listener = base.BuildChannelListener<TChannel>(context);
PropertyInfo p = namedPipeChannelListenerType.GetProperty(
"AllowedUsers", BindingFlags.Instance|BindingFlags.NonPublic);
p.SetValue(listener, _allowedUsers, null);
return listener;
}
If you go this route, be sure also to patch the "squatting vulnerability" as explained in a later post.
Came across these posts which is very helpful: Exploring the WCF Named Pipe Binding - Part 3 - Chris Dickson's Blog
I tried what is suggested in above "Chris Disson's blog" but after running service code in admin privilege, got below exception. "There is an issue with StudentService Some or all identity references could not be translated." here is my code which host the service
AclSecuredNamedPipeBinding binding = new AclSecuredNamedPipeBinding();
SecurityIdentifier allowedGroup = (SecurityIdentifier)(new
NTAccount("NPServiceUsers").Translate(typeof(SecurityIdentifier)));
binding.AddUserOrGroup(allowedGroup);
studentServiceHost = new ServiceHost(typeof(StudentService.StudentService));
Uri httpBaseAddress = new
Uri("net.pipe://localhost/ServiceHost/ServiceHost");
studentServiceHost.AddServiceEndpoint(
typeof(StudentService.IStudentService),binding, httpBaseAddress);
studentServiceHost.Open();
then I tried by changing nTAccount from "NPServiceUsers" to "Administrators" then I got below exception.
"There is an issue with StudentService Object reference not set to an instance of an object."
studentService is class which implemented the IStudentService interface.
public class StudentService : IStudentService
{
public void DoWork()
{
}
}
精彩评论