- Introduction
- Developer’s Guide
- Samples
- Reference
Security considerations
The ShellBoost native proxy (“client”) and the ShellBoost .NET server (“server”) communicate using the local-Windows-only RPC “ncalrpc“ protocol.
This ShellBoost RPC channel uses, by default, an endpoint common on both sides but specific to the current user desktop. It means communication is by default only possible between a “client” and the “server” in the same desktop.
However, the RPC server doesn’t enforce security at network level. It means the “server” can serve any RPC client that connects to this endpoint. It also means the user credentials running the “server” may not be the same as the user credentials running the “client”.
Note: The desktop associated with a given process can be determined by the SessionId property of the .NET’s System.Diagnostics.Process standard .NET class.
Client identity
The .NET ShellBoost RPC Server always provides the “client” user identity through the ClientPrincipalName string property of the ShellBoost-provided ShellContext class.
ShellBoost also provides an impersonation feature that allows the .NET Server to behave as the connecting client. This feature is enabled by default, but can be turned off like this, in startup code (config is of ShellConfiguration type):
using (var server = new MyShellFolderServer())
{
var config = new ShellFolderConfiguration();
config.ImpersonateClient = false;
...
server.Start(config);
...
}
Thanks to impersonation turned on by default, the result of calling Environment.UserName or WindowsIdentity.GetCurrent() standard .NET methods should return the same value as ShellContext.Current.ClientPrincipalName, even if the “client” process is calling from a different desktop/session than the “server” one. However if you turn impersonation off, you must only rely on ShellContext.Current.ClientPrincipalName to determine the “client” user identity.
Note: independently from security issues, custom UI (dialog box, windows, windows messages, etc.) is not supported from a “server” running in a desktop to a client “running” in another desktop.
ShellBoost as a Windows Service
A Windows Service is probably going to be running under specific credentials, different as users working with their Windows Shell in their desktop. In this case, the ShellBoost developer can choose to impersonate the client user (run “as” the user, with the user’s credentials), or just identify it. Impersonation is a global setting that must be set or not at application start time. By default, ShellBoost enables client impersonation.
In any cases, even with impersonation disabled, the ShellBoost developer can determine client identity and client process identifier using the ShellContext class.
Here is an extract from the Folder Service sample. The root folder services 5 items that just display diagnostic-type information, for demonstration purposes:
public class RootFolder : RootShellFolder
{
public RootFolder(OverviewShellFolderServer server, ShellItemIdList idList)
: base(idList)
{
Server = server;
}
public OverviewShellFolderServer Server { get; }
public override IEnumerable<ShellItem> EnumItems(SHCONTF options)
{
yield return new SimpleItem(this, "Client Principal Name: " + ShellContext.Current.ClientPrincipalName);
yield return new SimpleItem(this, "Client Process Id: " + ShellContext.Current.ClientProcessId);
yield return new SimpleItem(this, "Client Process: " + Process.GetProcessById(ShellContext.Current.ClientProcessId)?.ProcessName);
// if we impersonate, this will be the same as the client principal name
// otherwise it will be the identity that runs the service process
yield return new SimpleItem(this, "Server Windows Identity: " + WindowsIdentity.GetCurrent()?.Name);
yield return new SimpleItem(this, "Server Process: " + Process.GetCurrentProcess().ProcessName);
}
}
The service’s OnStart() method is coded like this:
protected override void OnStart(string[] args)
{
_server = new OverviewShellFolderServer();
var config = new ShellFolderConfiguration();
config.ImpersonateClient = true; // true is the default
config.NativeDllRegistration = RegistrationMode.User;
_server.Start(config);
}
As you can see below, the service is configured to run as “Local System”.
And this is what we see in our ShellBoost namespace extension:
This information is computed from the ShellBoost.Samples.FolderService.exe, running as “Local System”. Since the user is impersonated, the Service Windows Identity name is the same as the client principal name. We can see the client process is explorer (.exe).
If we change the startup code like this (stop the service, recompile, restart the service, refresh explorer):
config.ImpersonateClient = false;
This is what we see in our ShellBoost namespace extension:
Now, the Service Windows Identity is NT AUTHORITY\SYSTEM (which is “Local Service”). We still have the correct client identity available, though.
Note: custom UI is not supported from Windows Services, since they cannot interact with desktops.