c# .net security permissions dcom
aquí

c# - funcionalidad dcomcnfg programáticamente



.net security (5)

Encontré esta solución funcionando:

public static void SetUp() { SetCOMSercurityAccess("DefaultAccessPermission"); SetCOMSercurityAccess("DefaultLaunchPermission"); } private static void SetCOMSercurityAccess(string regKey) { //This is the magic permission! byte[] binaryform = new string[] { "01","00","04","80","80","00","00","00","90","00","00","00","00","00","00","00","14","00","00","00","02","00","6c","00","04", "00","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","12","00","00","00","00","00", "24","00","0b","00","00","00","01","05","00","00","00","00","00","05","15","00","00","00","a3","53","d8","c8","94","bd","63", "84","88","bf","fa","cf","a7","2b","00","00","00","00","18","00","1f","00","00","00","01","02","00","00","00","00","00","05", "20","00","00","00","20","02","00","00","00","00","14","00","1f","00","00","00","01","01","00","00","00","00","00","05","04", "00","00","00","01","02","00","00","00","00","00","05","20","00","00","00","20","02","00","00","01","02","00","00","00","00", "00","05","20","00","00","00","20","02","00","00" }.Select(o=> Convert.ToByte(o,16)).ToArray(); Registry.SetValue("HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Ole", regKey, binaryform, RegistryValueKind.Binary); }

En caso de que ayude a otros ...

Puedo encontrar todo tipo de cosas sobre cómo programar para DCOM, pero prácticamente nada sobre cómo configurar / verificar la seguridad mediante programación.

No estoy intentando recrear dcomcnfg, pero si supiera cómo reproducir toda la funcionalidad de dcomcnfg en C # (preferred, o VB.net), entonces mi objetivo está a la vista.

Parece que no puedo encontrar ningún buen recurso sobre esto, ninguna API de código abierto o incluso ejemplos rápidos de cómo hacer cada paso. Incluso aquí DCOM o dcomcnfg arroja pocos resultados y ninguno realmente acerca de cómo establecer / verificar / enumerar la seguridad.

Si alguien tiene algunos consejos para una API abierta o algunos ejemplos, lo agradecería.


Esta información se almacena en HKCR/AppID/{Your-AppID}/LaunchPermission y AccessPermission . Estos son valores REG_BINARY que contienen descripciones de seguridad serializadas. No tengo idea de si hay algo que brinde un acceso conveniente a los de .NET ...

Más información en MSDN .


No pude encontrar ninguna forma .NET de hacer esto: puede usar la utilidad de línea de comandos MS DCOMPerm que es parte del SDK o descargar desde aquí (o aquí desde esta publicación )

(No utilizo ninguno de los enlaces anteriores para dcomperm.exe, utilizo un archivo compilado para mí por un compañero de trabajo ...)


Frente a circunstancias similares (configuración de seguridad DCOM desde una MSI) logré crear una solución que hace lo que quiero alterando los valores clave de registro en HKEY_CLASSES_ROOT / AppID {APP-GUID-GOES-HERE}. Gracias a la respuesta de Arnout por ponerme en el camino correcto.

En específico, creé un método para editar los permisos de seguridad para objetos DCOM, que se almacenan en los valores de clave de registro LaunchPermission y AccessPermission. Estos son descriptores de seguridad serializados, a los que se puede acceder pasando los datos binarios a través de RawSecurityDescriptor . Esta clase simplifica muchos de los detalles en una deliciosa forma de .NET-y, pero aún debe atender todos los detalles lógicos con respecto a la ACL de Windows, y debe asegurarse de volver a escribir el descriptor de seguridad en el registro utilizando RawSecurityDescriptor.GetBinaryForm .

El método que creé se llamaba EditOrCreateACE . Este método editará una ACE existente para una cuenta, o insertará una nueva, y se asegurará de que la máscara de acceso tenga los indicadores pasados ​​establecidos. Lo adjunto aquí como un ejemplo , esto de ninguna manera es una autoridad sobre cómo lidiar con él, ya que sé muy poco de cosas de Windows ACL todavía:

// These are constants for the access mask on LaunchPermission. // I''m unsure of the exact constants for AccessPermission private const int COM_RIGHTS_EXECUTE = 1; private const int COM_RIGHTS_EXECUTE_LOCAL = 2; private const int COM_RIGHTS_EXECUTE_REMOTE = 4; private const int COM_RIGHTS_ACTIVATE_LOCAL = 8; private const int COM_RIGHTS_ACTIVATE_REMOTE = 16; void EditOrCreateACE(string keyname, string valuename, string accountname, int mask) { // Get security descriptor from registry byte[] keyval = (byte[]) Registry.GetValue(keyname, valuename, new byte[] { }); RawSecurityDescriptor sd; if (keyval.Length > 0) { sd = new RawSecurityDescriptor(keyval, 0); } else { sd = InitializeEmptySecurityDescriptor(); } RawAcl acl = sd.DiscretionaryAcl; CommonAce accountACE = null; // Look for the account in the ACL int i = 0; foreach (GenericAce ace in acl) { if (ace.AceType == AceType.AccessAllowed) { CommonAce c_ace = ace as CommonAce; NTAccount account = c_ace.SecurityIdentifier.Translate(typeof(NTAccount)) as NTAccount; if (account.Value.Contains(accountname)) { accountACE = c_ace; } i++; } } // If no ACE found for the given account, insert a new one at the end // of the ACL, otherwise just set the mask if (accountACE == null) { SecurityIdentifier ns_account = (new NTAccount(accountname)).Translate(typeof(SecurityIdentifier)) as SecurityIdentifier; CommonAce ns = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed, mask, ns_account, false, null); acl.InsertAce(acl.Count, ns); } else { accountACE.AccessMask |= mask; } // Write security descriptor back to registry byte[] binarySd = new byte[sd.BinaryLength]; sd.GetBinaryForm(binarySd, 0); Registry.SetValue(keyname, valuename, binarySd); } private static RawSecurityDescriptor InitializeEmptySecurityDescriptor() { var localSystem = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); var new_sd = new RawSecurityDescriptor(ControlFlags.DiscretionaryAclPresent, localSystem, localSystem, null, new RawAcl(GenericAcl.AclRevision, 1)); return new_sd; }

Tenga en cuenta que este código no es perfecto. Si falta todo el valor de la clave de registro para estas ACL en el registro, la ACL que se sintetiza SÓLO otorgará acceso a la cuenta pasada y nada más. También estoy seguro de que hay muchas condiciones de error que no he manejado correctamente y detalles que he pasado por alto. De nuevo, es un ejemplo de cómo lidiar con DCOM ACL en .NET.


La respuesta publicada por Daniel fue HUGELY útil. ¡Muchas gracias, Daniel!

Un problema con la documentación de Microsoft es que indican que los valores del registro contienen una ACL en forma binaria. Entonces, por ejemplo, si estuviera tratando de establecer el acceso predeterminado de la máquina (en lugar de por proceso), estaría accediendo a la clave de registro HKEY_LOCAL_MACHINE / SOFTWARE / Microsoft / Ole / DefaultAccessPermission. Sin embargo, en mis intentos iniciales de acceder a esta clave utilizando la clase System.Security.AccessControl.RawACL fallaron.

Como indica el código de Daniel, el valor no es realmente una ACL, pero en realidad es un SecurityDescriptor con la ACL.

Por lo tanto, aunque sé que esta publicación es antigua, voy a publicar mi solución para verificar y establecer la configuración de seguridad y agregar NetworkService para el acceso local predeterminado. Por supuesto, podrías tomar esto y hacerlo mejor, estoy seguro, pero para empezar solo necesitarías cambiar la llave y la máscara de acceso.

static class ComACLRights{ public const int COM_RIGHTS_EXECUTE= 1; public const int COM_RIGHTS_EXECUTE_LOCAL = 2; public const int COM_RIGHTS_EXECUTE_REMOTE = 4; public const int COM_RIGHTS_ACTIVATE_LOCAL = 8; public const int COM_RIGHTS_ACTIVATE_REMOTE = 16; } class Program { static void Main(string[] args) { var value = Registry.GetValue("HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Ole", "DefaultAccessPermission", null); RawSecurityDescriptor sd; RawAcl acl; if (value == null) { System.Console.WriteLine("Default Access Permission key has not been created yet"); sd = new RawSecurityDescriptor(""); }else{ sd = new RawSecurityDescriptor(value as byte[], 0); } acl = sd.DiscretionaryAcl; bool found = false; foreach (CommonAce ca in acl) { if (ca.SecurityIdentifier.IsWellKnown(WellKnownSidType.NetworkServiceSid)) { //ensure local access is set ca.AccessMask |= ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL; //set local access. Always set execute found = true; break; } } if(!found){ //Network Service was not found. Add it to the ACL SecurityIdentifier si = new SecurityIdentifier( WellKnownSidType.NetworkServiceSid, null); CommonAce ca = new CommonAce( AceFlags.None, AceQualifier.AccessAllowed, ComACLRights.COM_RIGHTS_EXECUTE | ComACLRights.COM_RIGHTS_EXECUTE_LOCAL | ComACLRights.COM_RIGHTS_ACTIVATE_LOCAL, si, false, null); acl.InsertAce(acl.Count, ca); } //re-set the ACL sd.DiscretionaryAcl = acl; byte[] binaryform = new byte[sd.BinaryLength]; sd.GetBinaryForm(binaryform, 0); Registry.SetValue("HKEY_LOCAL_MACHINE//SOFTWARE//Microsoft//Ole", "DefaultAccessPermission", binaryform, RegistryValueKind.Binary); } }