54

I'm having an issue with a COM based client-server setup. The COM server is written in C# (.NET 4.0) and runs as a (registered) local server.

Depending on which application connects to the server, other clients will receive a Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)

The underlying issue is explained here (in the section COM is integrity aware). The way I understand it, it is being caused by the fact that an elevated application creates the server with a higher integrity level. When another non-elevated application then connects, it is not allowed to connect to the same instance. The same happens when a non-elevated application creates the process, followed an elevated application connecting.

I've tried to implement the solution described on the page: modifying the registry to set a security descriptor that should allow all clients to connect. There is a code sample in C++, but this does effectively the same thing in .NET:

// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);

RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
    key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}

using (key)
{
    key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}

However, this does not have the desired effect. When the second client tries to create an instance of the object in question, Windows tries to launch a separate instance of my COM Server, but the server prevents two instances from running as the same user. Given the permissions I've set, I would not expect a second instance to launch in the first place.

Since one of the client applications is running in Medium IL and the other in High IL, I also experimented with variants on the mandatory label, like:

O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)

I've also tried setting the ROTFlags registry key to 0x1 (ROTFLAGS_ALLOWANYCLIENT) as suggested on the page, still no change in behavior.

I've established that the LaunchPermission registry value is being used in some way. I cannot discover where it's being read using Process Monitor, but when I use the dcomcnfg.exe tool to set the same key, I can force the server to fail loading by denying launch permissions.

I would like to point out that my server process does not need elevation. How do I make both elevated and non-elevated processes capable of connecting to a single server instance?

Roger Rowland
  • 24,701
  • 11
  • 69
  • 106
Thorarin
  • 43,849
  • 11
  • 70
  • 108
  • 2
    Is the server registered in the registry? – tyranid Aug 21 '12 at 18:42
  • 1
    @tyranid: Yes, and it has an AppID. I've updated my code to write a registry key instead, because the MSDN solution mentions using this solution. – Thorarin Aug 23 '12 at 12:28
  • 1
    I guess it is a stupid question but have you tried setting AccessPermission? http://msdn.microsoft.com/en-us/library/windows/desktop/ms688679%28v=vs.85%29.aspx – tyranid Aug 23 '12 at 21:21
  • 1
    @tyranid: Setting it to what? The MSDN page only mentions needing LaunchPermissions to get around this particular issue? – Thorarin Aug 24 '12 at 11:07
  • 1
    Well setting it to a similar security descriptor, I doubt it would make a difference but certainly when used in services exposing COM servers it is important to determine access for lower privileged clients. Tbh what is your registration mode? Do you _need_ to only create a single instance of the server executable? – tyranid Aug 24 '12 at 14:31
  • 1
    @tyranid: Activate as Activator, if that's what you're referring to. And yes, I need a single instance. I could theoretically make things work with two instances if these instances were to communicate with each other, but it would make it a whole lot more complicated. I tried also setting Access Permissions, but this has no effect. – Thorarin Aug 24 '12 at 15:28
  • 5
    (outside the box question) Is COM a requirement? I've had similar situations before. I chickened-out and made a wrapper (COM+/WCF) and called the wrapper. – tgolisch Aug 29 '12 at 16:52
  • @tgolisch: There are additional functional requirements that effectively make COM a requirement. I would have preferred not using COM myself :) – Thorarin Sep 04 '12 at 15:41
  • 3
    "The same happens when a non-elevated application creates the process, followed [by] an elevated application connecting." This scenario shouldn't fall foul of integrity control... are you sure there isn't some other issue in play? How does the app fail in this scenario? – Chris Dickson Sep 09 '12 at 15:19
  • How is the COM server declared? Is it Singleton? – playerone May 05 '13 at 04:07
  • Try this article, not sure if threading is applicable but might give you some food for thought: http://stackoverflow.com/questions/2092523/how-to-mark-net-objects-exposed-to-com-interop-as-single-threaded – Rots May 09 '13 at 05:42

2 Answers2

1

According to Windows Vista Security Model Analysis you will need to use shared objects such as a named pipe to go between the different IL. Also, the shared object should have an IL equivalent to your lowest IL being used.

0

you have to Set Debug option to Any cpu in VS.

Prakash
  • 23
  • 3