예제 #1
0
        /// <summary>
        /// Gets the central access policy name of the provided PSObject.
        /// </summary>
        /// <remarks>
        /// Function 'LsaQueryCAPs' is not available in OneCoreUAP and NanoServer.
        /// </remarks>
        /// <param name="instance">
        /// The PSObject for which to obtain the central access policy name.
        /// </param>
        /// <returns>
        /// The central access policy name of the provided PSObject.
        /// </returns>
        public static string GetCentralAccessPolicyName(PSObject instance)
        {
            SecurityIdentifier capId = GetCentralAccessPolicyId(instance);
            if (capId == null)
            {
                return null; // file does not have the scope ace
            }
            int capIdSize = capId.BinaryLength;
            byte[] capIdArray = new byte[capIdSize];
            capId.GetBinaryForm(capIdArray, 0);
            IntPtr caps = IntPtr.Zero;
            IntPtr pCapId = Marshal.AllocHGlobal(capIdSize);

            try
            {
                // Retrieve the CAP by CAPID.
                Marshal.Copy(capIdArray, 0, pCapId, capIdSize);
                IntPtr[] ppCapId = new IntPtr[1];
                ppCapId[0] = pCapId;
                uint capCount = 0;
                uint rs = NativeMethods.LsaQueryCAPs(
                    ppCapId,
                    1,
                    out caps,
                    out capCount);
                if (rs != NativeMethods.STATUS_SUCCESS)
                {
                    throw new Win32Exception((int)rs);
                }
                if (capCount == 0 || caps == IntPtr.Zero)
                {
                    return null;
                }

                // Get the CAP name.
                NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY();
                cap = ClrFacade.PtrToStructure<NativeMethods.CENTRAL_ACCESS_POLICY>(caps);
                // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes.
                return Marshal.PtrToStringUni(cap.Name.Buffer, cap.Name.Length / 2);
            }
            finally
            {
                Marshal.FreeHGlobal(pCapId);
                uint rs = NativeMethods.LsaFreeMemory(caps);
                Dbg.Diagnostics.Assert(rs == NativeMethods.STATUS_SUCCESS,
                    "LsaFreeMemory failed: " + rs.ToString(CultureInfo.CurrentCulture));
            }
        }
예제 #2
0
        /// <summary>
        /// Gets the names and IDs of all central access policies available on the machine.
        /// </summary>
        /// <remarks>
        /// Function 'LsaQueryCAPs' is not available in OneCoreUAP and NanoServer.
        /// </remarks>
        /// <param name="instance">
        /// The PSObject argument is ignored.
        /// </param>
        /// <returns>
        /// The names and IDs of all central access policies available on the machine.
        /// </returns>
        public static string[] GetAllCentralAccessPolicies(PSObject instance)
        {
            IntPtr caps = IntPtr.Zero;

            try
            {
                // Retrieve all CAPs.
                uint capCount = 0;
                uint rs = NativeMethods.LsaQueryCAPs(
                    null,
                    0,
                    out caps,
                    out capCount);
                if (rs != NativeMethods.STATUS_SUCCESS)
                {
                    throw new Win32Exception((int)rs);
                }
                Dbg.Diagnostics.Assert(capCount < 0xFFFF,
                    "Too many central access policies");
                if (capCount == 0 || caps == IntPtr.Zero)
                {
                    return null;
                }

                // Add CAP names and IDs to a string array.
                string[] policies = new string[capCount];
                NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY();
                IntPtr capPtr = caps;
                for (uint capIdx = 0; capIdx < capCount; capIdx++)
                {
                    // Retrieve CAP name.
                    Dbg.Diagnostics.Assert(capPtr != IntPtr.Zero,
                        "Invalid central access policies array");
                    cap = ClrFacade.PtrToStructure<NativeMethods.CENTRAL_ACCESS_POLICY>(capPtr);
                    // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes.
                    policies[capIdx] = "\"" + Marshal.PtrToStringUni(
                        cap.Name.Buffer,
                        cap.Name.Length / 2) + "\"";

                    // Retrieve CAPID.
                    IntPtr pCapId = cap.CAPID;
                    Dbg.Diagnostics.Assert(pCapId != IntPtr.Zero,
                        "Invalid central access policies array");
                    bool ret = NativeMethods.IsValidSid(pCapId);
                    if (!ret)
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                    SecurityIdentifier sid = new SecurityIdentifier(pCapId);
                    policies[capIdx] += " (" + sid.ToString() + ")";

                    capPtr += Marshal.SizeOf(cap);
                }
                return policies;
            }
            finally
            {
                uint rs = NativeMethods.LsaFreeMemory(caps);
                Dbg.Diagnostics.Assert(rs == NativeMethods.STATUS_SUCCESS,
                    "LsaFreeMemory failed: " + rs.ToString(CultureInfo.CurrentCulture));
            }
        }
예제 #3
0
        /// <summary>
        /// Returns a newly allocated SACL with the supplied CAPID in it.
        /// Free the returned SACL by calling Marshal.FreeHGlobal.
        /// </summary>
        /// <remarks>
        /// Function 'LsaQueryCAPs' is not available in OneCoreUAP and NanoServer.
        /// So the parameter "-CentralAccessPolicy" is not supported on OneCore powershell, 
        /// and thus this method won't be hit in OneCore powershell.
        /// </remarks>
        private IntPtr GetSaclWithCapId(string capStr)
        {
            IntPtr pCapId = IntPtr.Zero, pSacl = IntPtr.Zero;
            IntPtr caps = IntPtr.Zero;
            bool ret = true, freeCapId = true;
            uint rs = NativeMethods.STATUS_SUCCESS;

            try
            {
                // Convert the supplied SID from string to binary form.
                ret = NativeMethods.ConvertStringSidToSid(capStr, out pCapId);
                if (!ret)
                {
                    // We may have got a CAP friendly name instead of CAPID.
                    // Enumerate all CAPs on the system and try to find one with 
                    // a matching friendly name.
                    // If we retrieve the CAPID from the LSA, the CAPID need not 
                    // be deallocated separately (but with the entire buffer 
                    // returned by LsaQueryCAPs).
                    freeCapId = false;
                    uint capCount = 0;
                    rs = NativeMethods.LsaQueryCAPs(
                        null,
                        0,
                        out caps,
                        out capCount);
                    if (rs != NativeMethods.STATUS_SUCCESS)
                    {
                        throw new Win32Exception((int)rs);
                    }
                    Dbg.Diagnostics.Assert(capCount < 0xFFFF,
                        "Too many central access policies");
                    if (capCount == 0 || caps == IntPtr.Zero)
                    {
                        return IntPtr.Zero;
                    }

                    // Find the supplied string among available CAP names, use the corresponding CAPID.
                    NativeMethods.CENTRAL_ACCESS_POLICY cap = new NativeMethods.CENTRAL_ACCESS_POLICY();
                    IntPtr capPtr = caps;
                    for (uint capIdx = 0; capIdx < capCount; capIdx++)
                    {
                        Dbg.Diagnostics.Assert(capPtr != IntPtr.Zero,
                            "Invalid central access policies array");
                        cap = ClrFacade.PtrToStructure<NativeMethods.CENTRAL_ACCESS_POLICY>(capPtr);
                        // LSA_UNICODE_STRING is composed of WCHARs, but its length is given in bytes.
                        string capName = Marshal.PtrToStringUni(
                            cap.Name.Buffer,
                            cap.Name.Length / 2);
                        if (capName.Equals(capStr, StringComparison.OrdinalIgnoreCase))
                        {
                            pCapId = cap.CAPID;
                            break;
                        }
                        capPtr += Marshal.SizeOf(cap);
                    }
                }
                if (pCapId == IntPtr.Zero)
                {
                    Exception e = new ArgumentException(UtilsStrings.InvalidCentralAccessPolicyIdentifier);
                    WriteError(new ErrorRecord(
                        e,
                        "SetAcl_CentralAccessPolicy",
                        ErrorCategory.InvalidArgument,
                        AclObject));
                    return IntPtr.Zero;
                }
                ret = NativeMethods.IsValidSid(pCapId);
                if (!ret)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
                uint sidSize = NativeMethods.GetLengthSid(pCapId);

                // Calculate the size of the SACL with one CAPID ACE, align to DWORD.
                uint saclSize = (uint)(Marshal.SizeOf(new NativeMethods.ACL()) +
                    Marshal.SizeOf(new NativeMethods.SYSTEM_AUDIT_ACE()) +
                    sidSize - 1) & 0xFFFFFFFC;
                Dbg.Diagnostics.Assert(saclSize < 0xFFFF,
                    "Acl size must be less than max SD size of 0xFFFF");

                // Allocate and initialize the SACL.
                pSacl = Marshal.AllocHGlobal((int)saclSize);
                ret = NativeMethods.InitializeAcl(
                    pSacl,
                    saclSize,
                    NativeMethods.ACL_REVISION);
                if (!ret)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                // Add CAPID to the SACL.
                rs = NativeMethods.RtlAddScopedPolicyIDAce(
                    pSacl,
                    NativeMethods.ACL_REVISION,
                    NativeMethods.SUB_CONTAINERS_AND_OBJECTS_INHERIT,
                    0,
                    pCapId);
                if (rs != NativeMethods.STATUS_SUCCESS)
                {
                    if (rs == NativeMethods.STATUS_INVALID_PARAMETER)
                    {
                        throw new ArgumentException(UtilsStrings.InvalidCentralAccessPolicyIdentifier);
                    }
                    else
                    {
                        throw new Win32Exception((int)rs);
                    }
                }
            }
            finally
            {
                if (!ret || rs != NativeMethods.STATUS_SUCCESS)
                {
                    Marshal.FreeHGlobal(pSacl);
                    pSacl = IntPtr.Zero;
                }
                rs = NativeMethods.LsaFreeMemory(caps);
                Dbg.Diagnostics.Assert(rs == NativeMethods.STATUS_SUCCESS,
                    "LsaFreeMemory failed: " + rs.ToString(CultureInfo.CurrentCulture));
                if (freeCapId)
                {
                    NativeMethods.LocalFree(pCapId);
                }
            }

            return pSacl;
        }