同様の状況 (MSI からの DCOM セキュリティの構成) に直面して、HKEY_CLASSES_ROOT\AppID{APP-GUID-GOES-HERE} のレジストリ キーの値を変更することで、必要なソリューションを作成することができました。私を正しい道に導いてくれたArnoutの答えに感謝します。
具体的には、LaunchPermission および AccessPermission レジストリ キー値に格納されている DCOM オブジェクトのセキュリティ アクセス許可を編集するメソッドを作成しました。これらはシリアル化されたセキュリティ記述子であり、バイナリ データを に渡すことでアクセスできますRawSecurityDescriptor
。このクラスは、多くの詳細をおいしい .NET 形式で簡素化しますが、Windows ACL に関するすべての論理的な詳細に注意を払う必要があり、.NET を使用してセキュリティ記述子をレジストリに書き戻す必要があります RawSecurityDescriptor.GetBinaryForm
。
私が作成したメソッドは と呼ばれていましたEditOrCreateACE
。このメソッドは、アカウントの既存の ACE を編集するか、新しい ACE を挿入して、アクセス マスクに渡されたフラグが設定されていることを確認します。例としてここに添付します。これは、Windows ACL のことをまだほとんど知らないため、対処方法に関する権威ではありません。
// 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;
}
このコードは決して完璧ではないことに注意してください。これらの ACL のレジストリ キー値全体がレジストリに存在しない場合、合成された ACL は渡されたアカウントへのアクセスのみを許可し、それ以外は何も許可しません。また、適切に処理できていないエラー状態や、詳細を見逃しているエラーがたくさんあると確信しています。繰り返しますが、これは .NET で DCOM ACL を処理する方法の例です。