2010-06-29 8 views
6

Sto utilizzando il seguente codice nel tentativo di consentire programatically il NetworkService account per avere accesso a una chiave:Tentativo di impostare le autorizzazioni per un KeyContainer in C# sta avendo alcun effetto

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 
) 
); 

Questo codice viene eseguito senza errore, ma non ha alcun effetto sulle autorizzazioni del contenitore chiave.

Tuttavia, utilizzando lo strumento a riga di comando aspnet_regiis a fare la stessa cosa, funziona perfettamente:

aspnet_regiis -pa "MyEncryptionKey" "NetworkService" 

Io corro con pieni diritti di amministratore - se non corro con questi diritti, allora è un'eccezione gettato. Sono anche in esecuzione come utente che inizialmente ha creato la chiave.

Il contenitore di chiavi ha sempre le seguenti regole di accesso:

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

Con aspnet_regiis, il SID, S-1-5-20 viene aggiunto a questa lista. Non posso influenzarlo dal codice.

Ho provato a creare l'identificatore di sicurezza dal formato di stringa Sid, oltre a utilizzare SetAccessRule anziché AddAccessRule.

Qualche idea su come modificare effettivamente questo elenco ACL dal codice?

risposta

10

Sembra che non si chiami Persist. Le modifiche apportate a CryptoKeySecurity non vengono effettivamente salvate immediatamente. È necessario utilizzare uno dei metodi Persist(...) per salvare effettivamente le modifiche.

NativeObjectSecurity.Persist Method (String, AccessControlSections)

Sembra questi API seguono un approccio piuttosto complicata a modifiche. Devi prima creare un CspParameters, applicare le modifiche necessarie, quindi costruire il fornitore da quei parametri. La costruzione richiama un aggiornamento sul contenitore.

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

Purtroppo tutti i metodi Persist sono protetti. –

+0

Sembra che sia necessario modificare la sicurezza prima di creare il provider utilizzando CspParameters. CspParameters, quando viene passato a RSACryptoServiceProvider, richiama un persist. Modo MOLTO strano per costruire un'API, ma secondo la documentazione, sembra essere come funziona. Risposta aggiornata per riflettere. – jrista

+4

Questo mi ha fatto sulla buona strada. La proprietà CryptoKeySecurity come sopra utilizzata è nullo, quindi genera. Puoi crearne uno nuovo, ma cancella tutti i permessi già esistenti (questo era il primo effetto effettivo che aveva, quindi ora sono bloccato fuori dal mio keystore principale;). Ma ... se si ottiene la chiave dal keystore, quindi creare un nuovo CspParamters copiando i valori da RSA.CspKeyContainerInfo (incluso nome del provider e tipo, nome del contenitore e CryptoKeySecurity), quindi è possibile modificarlo, creare un altro RSA oggetto chiave usando i cspparameters e voilà, tutto fatto. simples ...? –