2010-06-29 4 views
6

estoy usando el siguiente código en un intento de permitir programáticamente el NetworkService cuenta para tener acceso a una clave:Intento de establecer permisos en un KeyContainer en C# está teniendo ningún efecto

var RSA = new RSACryptoServiceProvider(
    new CspParameters() { 
    KeyContainerName = "MyEncryptionKey", 
    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore 
}); 

RSA.CspKeyContainerInfo.CryptoKeySecurity.AddAccessRule(
    new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), 
    CryptoKeyRights.GenericAll, 
    AccessControlType.Allow 
) 
); 

Este código se ejecuta sin error, pero no tiene ningún efecto sobre los permisos del contenedor de claves.

Sin embargo, el uso de la herramienta de línea de comandos aspnet_regiis a hacer lo mismo, funciona perfectamente:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService" 

estoy corriendo con derechos de administrador completos - si no corro con esos derechos, entonces es una excepción arrojado. También me estoy ejecutando como el usuario que inicialmente creó la clave.

el contenedor de claves siempre tiene las siguientes reglas de acceso:

S-1-5-18   -> LocalSystem 
S-1-5-32-544  -> Administrators 
S-1-5-5-0-135377 -> MyUser 

Con aspnet_regiis, el SID, S-1-5-20 se añade a esta lista. No puedo afectarlo desde el código.

He intentado crear el identificador de seguridad del sid en formato de cadena, así como usar SetAccessRule en lugar de AddAccessRule.

¿Alguna idea de cómo afectar realmente a esta lista de ACL desde el código?

Respuesta

10

Parece que no llamas a Persist. Los cambios que realice en CryptoKeySecurity realmente no se guardan de inmediato. Debe usar uno de los métodos Persist(...) para guardar realmente los cambios.

NativeObjectSecurity.Persist Method (String, AccessControlSections)

parece que estos API siguen un enfoque bastante complicado a modificación. Primero debe crear un CspParameters, aplicar los cambios necesarios y luego crear el proveedor a partir de esos parámetros. La construcción invoca una actualización del contenedor.

var params = new CspParameters 
{ 
    KeyContainerName = "MyEncryptionKey", 
    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore  
}; 

params.CryptoKeySecurity.AddAccessRule(
    new System.Security.AccessControl.CryptoKeyAccessRule(
    new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), 
    CryptoKeyRights.GenericAll, 
    AccessControlType.Allow 
) 
); 

var RSA = new RSACryptoServiceProvider(params); 
+0

Lamentablemente todos los métodos de Persist están protegidos. –

+0

Parece que necesita modificar la seguridad antes de crear el proveedor utilizando CspParameters. Los CspParameters, cuando se pasan al RSACryptoServiceProvider, invocan una persistencia. Una forma muy extraña de construir una API, pero de acuerdo con la documentación, parece ser así como funciona. Respuesta actualizada para reflejar – jrista

+4

Eso me puso en el camino correcto. La propiedad CryptoKeySecurity como se usa arriba es nula, por lo que arroja. Puede crear uno nuevo, pero anula todos los permisos que ya existían (este fue el primer efecto real que tuvo, por lo que ahora estoy bloqueado fuera de mi almacén de claves principal;). Pero ... si obtiene la clave del almacén de claves, cree un nuevo CspParamters copiando los valores de RSA.CspKeyContainerInfo (incluyendo nombre y tipo de proveedor, nombre del contenedor y CryptoKeySecurity), luego puede modificarlo, crear otro RSA objeto clave utilizando los parámetros csp, y listo, todo hecho. simples ...? –

Cuestiones relacionadas