none
How to use ICertAdminD2::GetCASecurity RRS feed

  • Question

  • Greetings,

    I have a project in which I need to programmatically report the permissions set on a ADCS enterprise CA.  I've been able to determine that the method GetCASecurity from the ICertADminD2 interface should be able to get what I need, however, I have a few questions:

    1. What Namespace(s) do I need to be using in order to be able to leverage the ICertAdminD2 interface?

    2. The MSDN documentation indicates that the return value from the GetCASecurity method is a pointer to data of type "CERTTRANSBLOB" is anyone familiar with working with that particular data structure?  I need to somehow obtain a list of security groups from it.

    Thanks in advance!

    Monday, March 2, 2015 4:49 PM

Answers

  • Windows 2008 R2.

    I was finally able to figure it out!  I had to implement some methods included in the CommonObjectSecurity interface.  The only other sticking point was determining which hex values mapped to each CA privilege.  Most implementations I came across used an enumeration, but I opted to create a small class to handle it.

    Here's what I did:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using CERTADMINLib;
    
    namespace getCAPermissions
    {
        public class ProxySecurity : CommonObjectSecurity
        {
            public ProxySecurity(bool isContainer)
                : base(isContainer)
            {
            }
    
            public override AccessRule AccessRuleFactory(IdentityReference identityReference, 
                                                         int accessMask, bool isInherited, 
                                                         InheritanceFlags inheritanceFlags, 
                                                         PropagationFlags propagationFlags, 
                                                         AccessControlType type)
            {
                return new ProxyAccessRule(identityReference, accessMask, type);
            }
    
            public override Type AccessRuleType
            {
                get { return typeof(ProxyAccessRule); }
            }
    
            public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
            {
                throw new NotImplementedException();
            }
    
            public override Type AuditRuleType
            {
                get { throw new NotImplementedException(); }
            }
    
            public override Type AccessRightType
            {
                //get { return typeof(ProxyRightsEnum); }
                get { return typeof(int); }
            }
        }
    
        public class ProxyAccessRule : AccessRule
        {
            public ProxyAccessRule(IdentityReference identity,
                                   int accessMask,
                                   AccessControlType accessType)
                : base(identity, accessMask, false, InheritanceFlags.None, PropagationFlags.None, accessType)
            {
            }
    
            public int AccessRights { get { return AccessMask; } }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                if (args.Length != 1)
                {
                    Console.WriteLine("Usage: getCAPermissions.exe [CA Config parameter]");
                    return;
                }
                CCertAdmin certAdmin = new CCertAdmin();
                byte[] security;
    
                try
                {
                    //byte[] security = certAdmin.GetConfigEntry(@"DCCA.mikeslab.com\MIKESLAB Issuing CA", "", "Security");
                    security = certAdmin.GetConfigEntry(args[0], "", "Security");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString() + Environment.NewLine + "Usage: getCAPermissions.exe [CA Config parameter]");
                    return;
                }
    
                ProxySecurity CASecurity = new ProxySecurity(false);
                CASecurity.SetSecurityDescriptorBinaryForm(security, AccessControlSections.All);
                AuthorizationRuleCollection coll = CASecurity.GetAccessRules(true, false, typeof(NTAccount));
                int rights;
                PrivilegedUserOrGroup pg;
                foreach (AuthorizationRule rule in coll)
                {
                    ProxyAccessRule accRule = rule as ProxyAccessRule;
                    rights = accRule.AccessRights;
                    pg = new PrivilegedUserOrGroup(rule.IdentityReference.Value, rights, accRule.AccessControlType.ToString());
                    foreach (string right in pg.rightsList)
                    {
                        Console.WriteLine("Name: " + pg.n + "   Right: " + right + "   Type:" + pg.type);
                    }
                    //Console.WriteLine("User or Group: \"{0}\"     Permissions: {1}     Access Type: {2}", rule.IdentityReference.Value, rights.ToString(), accRule.AccessControlType.ToString());
                }
            }
        }
    
        class PrivilegedUserOrGroup
        {
            public string n;
            public List<string> rightsList;
            public string type;
    
            public PrivilegedUserOrGroup(string name, int accessRights, string accessType)
            {
                n = name;
                type = accessType;
                rightsList = getRights(accessRights);
            }
    
            private List<string> getRights(int rights)
            {
                string noRights = "No Rights";
                string ca = "Manage CA";
                string certs = "Issue and Manage Certificates";
                string read = "Read";
                string req = "Request Certificates";
    
                List<string> result = new List<string>();
    
                switch (rights)
                {
                    case 0x000:
                        result.Add(noRights);
                        break;
                    case 0x001:
                        result.Add(ca);
                        break;
                    case 0x002:
                        result.Add(certs);
                        break;
                    case 0x003:
                        result.Add(ca);
                        result.Add(certs);
                        break;
                    case 0x100:
                        result.Add(read);
                        break;
                    case 0x101:
                        result.Add(ca);
                        result.Add(read);
                        break;
                    case 0x102:
                        result.Add(certs);
                        result.Add(read);
                        break;
                    case 0x103:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(read);
                        break;
                    case 0x200:
                        result.Add(req);
                        break;
                    case 0x201:
                        result.Add(ca);
                        result.Add(req);
                        break;
                    case 0x202:
                        result.Add(certs);
                        result.Add(req);
                        break;
                    case 0x203:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(req);
                        break;
                    case 0x300:
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x301:
                        result.Add(ca);
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x302:
                        result.Add(certs);
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x303:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(read);
                        result.Add(req);
                        break;
                    default:
                        result.Add("ERROR");
                        break;
                }
    
                return result;
            }
        }
    
    }
    

    • Marked as answer by Mike Bruno Thursday, March 5, 2015 1:29 PM
    Thursday, March 5, 2015 1:28 PM

All replies

  • Hi Mike, thank you for your question. A member of the protocol documentation team will respond to you soon.

    Josh Curry (jcurry) | Escalation Engineer | Open Specifications Support Team

    Monday, March 2, 2015 9:16 PM
    Moderator
  • Hi Mike:

    I will help you with this issue and will be in touch as soon as I have an answer.


    Regards, Obaid Farooqi

    Tuesday, March 3, 2015 10:10 PM
    Owner
  • Thank you!
    Wednesday, March 4, 2015 2:22 PM
  • Hi Mike:

    Which platform you are developing on? Windows or non-Windows?


    Regards, Obaid Farooqi

    Wednesday, March 4, 2015 6:27 PM
    Owner
  • Windows 2008 R2.

    I was finally able to figure it out!  I had to implement some methods included in the CommonObjectSecurity interface.  The only other sticking point was determining which hex values mapped to each CA privilege.  Most implementations I came across used an enumeration, but I opted to create a small class to handle it.

    Here's what I did:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using CERTADMINLib;
    
    namespace getCAPermissions
    {
        public class ProxySecurity : CommonObjectSecurity
        {
            public ProxySecurity(bool isContainer)
                : base(isContainer)
            {
            }
    
            public override AccessRule AccessRuleFactory(IdentityReference identityReference, 
                                                         int accessMask, bool isInherited, 
                                                         InheritanceFlags inheritanceFlags, 
                                                         PropagationFlags propagationFlags, 
                                                         AccessControlType type)
            {
                return new ProxyAccessRule(identityReference, accessMask, type);
            }
    
            public override Type AccessRuleType
            {
                get { return typeof(ProxyAccessRule); }
            }
    
            public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
            {
                throw new NotImplementedException();
            }
    
            public override Type AuditRuleType
            {
                get { throw new NotImplementedException(); }
            }
    
            public override Type AccessRightType
            {
                //get { return typeof(ProxyRightsEnum); }
                get { return typeof(int); }
            }
        }
    
        public class ProxyAccessRule : AccessRule
        {
            public ProxyAccessRule(IdentityReference identity,
                                   int accessMask,
                                   AccessControlType accessType)
                : base(identity, accessMask, false, InheritanceFlags.None, PropagationFlags.None, accessType)
            {
            }
    
            public int AccessRights { get { return AccessMask; } }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                if (args.Length != 1)
                {
                    Console.WriteLine("Usage: getCAPermissions.exe [CA Config parameter]");
                    return;
                }
                CCertAdmin certAdmin = new CCertAdmin();
                byte[] security;
    
                try
                {
                    //byte[] security = certAdmin.GetConfigEntry(@"DCCA.mikeslab.com\MIKESLAB Issuing CA", "", "Security");
                    security = certAdmin.GetConfigEntry(args[0], "", "Security");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString() + Environment.NewLine + "Usage: getCAPermissions.exe [CA Config parameter]");
                    return;
                }
    
                ProxySecurity CASecurity = new ProxySecurity(false);
                CASecurity.SetSecurityDescriptorBinaryForm(security, AccessControlSections.All);
                AuthorizationRuleCollection coll = CASecurity.GetAccessRules(true, false, typeof(NTAccount));
                int rights;
                PrivilegedUserOrGroup pg;
                foreach (AuthorizationRule rule in coll)
                {
                    ProxyAccessRule accRule = rule as ProxyAccessRule;
                    rights = accRule.AccessRights;
                    pg = new PrivilegedUserOrGroup(rule.IdentityReference.Value, rights, accRule.AccessControlType.ToString());
                    foreach (string right in pg.rightsList)
                    {
                        Console.WriteLine("Name: " + pg.n + "   Right: " + right + "   Type:" + pg.type);
                    }
                    //Console.WriteLine("User or Group: \"{0}\"     Permissions: {1}     Access Type: {2}", rule.IdentityReference.Value, rights.ToString(), accRule.AccessControlType.ToString());
                }
            }
        }
    
        class PrivilegedUserOrGroup
        {
            public string n;
            public List<string> rightsList;
            public string type;
    
            public PrivilegedUserOrGroup(string name, int accessRights, string accessType)
            {
                n = name;
                type = accessType;
                rightsList = getRights(accessRights);
            }
    
            private List<string> getRights(int rights)
            {
                string noRights = "No Rights";
                string ca = "Manage CA";
                string certs = "Issue and Manage Certificates";
                string read = "Read";
                string req = "Request Certificates";
    
                List<string> result = new List<string>();
    
                switch (rights)
                {
                    case 0x000:
                        result.Add(noRights);
                        break;
                    case 0x001:
                        result.Add(ca);
                        break;
                    case 0x002:
                        result.Add(certs);
                        break;
                    case 0x003:
                        result.Add(ca);
                        result.Add(certs);
                        break;
                    case 0x100:
                        result.Add(read);
                        break;
                    case 0x101:
                        result.Add(ca);
                        result.Add(read);
                        break;
                    case 0x102:
                        result.Add(certs);
                        result.Add(read);
                        break;
                    case 0x103:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(read);
                        break;
                    case 0x200:
                        result.Add(req);
                        break;
                    case 0x201:
                        result.Add(ca);
                        result.Add(req);
                        break;
                    case 0x202:
                        result.Add(certs);
                        result.Add(req);
                        break;
                    case 0x203:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(req);
                        break;
                    case 0x300:
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x301:
                        result.Add(ca);
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x302:
                        result.Add(certs);
                        result.Add(read);
                        result.Add(req);
                        break;
                    case 0x303:
                        result.Add(ca);
                        result.Add(certs);
                        result.Add(read);
                        result.Add(req);
                        break;
                    default:
                        result.Add("ERROR");
                        break;
                }
    
                return result;
            }
        }
    
    }
    

    • Marked as answer by Mike Bruno Thursday, March 5, 2015 1:29 PM
    Thursday, March 5, 2015 1:28 PM
  • Hi Mark:

    Glad to see that you figured it out.

    I see that you use a Windows API and that is the right approach if you are developing on Windows.

    Your original question was about a DCOM interface described in MS-CSRA open specification. This forum is dedicated to supporting issues related to open specifications that can be found at http://microsoft.com/openspecifications by clicking on "Documentation Library" button.

    If you have a question on a Managed Windows API, you have a better chance of getting an answer if you post it on forums related to C# development or a .net forum.

    Please feel free to post here if you have a question/comment on any of the open specifications.


    Regards, Obaid Farooqi

    Thursday, March 5, 2015 4:04 PM
    Owner