• win32


    需要首先获取特定用户的SID。

    这是一些步骤,

    1. 验证输入参数。
    2. 为可能足够大的SID和域名创建缓冲区。
    3. 在循环中,调用LookupAccountName以检索提供的帐户名的SID。如果SID的缓冲区或域名的缓冲区不够大,则分别cbSid或中返回所需的缓冲区大小cchDomainName,并在下一次调用之前分配一个新的缓冲区LookupAccountName请注意,当lpSystemName参数设置为NULL时,将在本地系统上检索信息 
    4. 释放分配给域名缓冲区的内存。

    然后将SID传递给SetEntriesInAclA函数,


    SetEntriesInAcl函数通过将新的访问控制或审核控制信息合并到现有ACL结构中来创建新的访问控制列表(ACL)。

    这是传递给SetEntriesInAcl的结构参数,

     ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
        ea.grfAccessPermissions = GENERIC_ALL;  //权限设置
        ea.grfAccessMode = SET_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
        ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
        ea.Trustee.TrusteeType = TRUSTEE_IS_USER; //特定的对象
        ea.Trustee.ptstrName = (LPTSTR)sid; //特定用户的sid
    
        // Create a new ACL that contains the new ACEs.
        dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);

    完整代码:

    #pragma comment(lib, "advapi32.lib")
    
    #include <windows.h>
    #include <stdio.h>
    #include <aclapi.h>
    #include <tchar.h>
    #include <mq.h.>
    
    HRESULT GetSid(
        LPCWSTR wszAccName,
        PSID* ppSid
    )
    {
    
        // Validate the input parameters.  
        if (wszAccName == NULL || ppSid == NULL)
        {
            return MQ_ERROR_INVALID_PARAMETER;
        }
    
        // Create buffers that may be large enough.  
        // If a buffer is too small, the count parameter will be set to the size needed.  
        const DWORD INITIAL_SIZE = 32;
        DWORD cbSid = 0;
        DWORD dwSidBufferSize = INITIAL_SIZE;
        DWORD cchDomainName = 0;
        DWORD dwDomainBufferSize = INITIAL_SIZE;
        WCHAR* wszDomainName = NULL;
        SID_NAME_USE eSidType;
        DWORD dwErrorCode = 0;
        HRESULT hr = MQ_OK;
    
        // Create buffers for the SID and the domain name.  
        *ppSid = (PSID) new BYTE[dwSidBufferSize];
        if (*ppSid == NULL)
        {
            return MQ_ERROR_INSUFFICIENT_RESOURCES;
        }
        memset(*ppSid, 0, dwSidBufferSize);
        wszDomainName = new WCHAR[dwDomainBufferSize];
        if (wszDomainName == NULL)
        {
            return MQ_ERROR_INSUFFICIENT_RESOURCES;
        }
        memset(wszDomainName, 0, dwDomainBufferSize * sizeof(WCHAR));
    
        // Obtain the SID for the account name passed.  
        for (; ; )
        {
    
            // Set the count variables to the buffer sizes and retrieve the SID.  
            cbSid = dwSidBufferSize;
            cchDomainName = dwDomainBufferSize;
            if (LookupAccountNameW(
                NULL,            // Computer name. NULL for the local computer  
                wszAccName,
                *ppSid,          // Pointer to the SID buffer. Use NULL to get the size needed,  
                &cbSid,          // Size of the SID buffer needed.  
                wszDomainName,   // wszDomainName,  
                &cchDomainName,
                &eSidType
            ))
            {
                if (IsValidSid(*ppSid) == FALSE)
                {
                    wprintf(L"The SID for %s is invalid.
    ", wszAccName);
                    dwErrorCode = MQ_ERROR;
                }
                break;
            }
            dwErrorCode = GetLastError();
    
            // Check if one of the buffers was too small.  
            if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
            {
                if (cbSid > dwSidBufferSize)
                {
    
                    // Reallocate memory for the SID buffer.  
                    wprintf(L"The SID buffer was too small. It will be reallocated.
    ");
                    FreeSid(*ppSid);
                    *ppSid = (PSID) new BYTE[cbSid];
                    if (*ppSid == NULL)
                    {
                        return MQ_ERROR_INSUFFICIENT_RESOURCES;
                    }
                    memset(*ppSid, 0, cbSid);
                    dwSidBufferSize = cbSid;
                }
                if (cchDomainName > dwDomainBufferSize)
                {
    
                    // Reallocate memory for the domain name buffer.  
                    wprintf(L"The domain name buffer was too small. It will be reallocated.
    ");
                    delete[] wszDomainName;
                    wszDomainName = new WCHAR[cchDomainName];
                    if (wszDomainName == NULL)
                    {
                        return MQ_ERROR_INSUFFICIENT_RESOURCES;
                    }
                    memset(wszDomainName, 0, cchDomainName * sizeof(WCHAR));
                    dwDomainBufferSize = cchDomainName;
                }
            }
            else
            {
                wprintf(L"LookupAccountNameW failed. GetLastError returned: %d
    ", dwErrorCode);
                hr = HRESULT_FROM_WIN32(dwErrorCode);
                break;
            }
        }
    
        delete[] wszDomainName;
        return hr;
    }
    
    void main()
    {
        PSID sid;
        GetSid(L"strive", &sid);
        DWORD dwRes, dwDisposition;
        PACL pACL = NULL;
        PSECURITY_DESCRIPTOR pSD = NULL;
        EXPLICIT_ACCESS ea;
        SECURITY_ATTRIBUTES sa;
        HANDLE lRes = NULL;
        // Initialize an EXPLICIT_ACCESS structure for an ACE.
        // The ACE will allow Everyone read access to the key.
        ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
        ea.grfAccessPermissions = GENERIC_ALL;
        ea.grfAccessMode = SET_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
        ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
        ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
        ea.Trustee.ptstrName = (LPTSTR)sid;
    
        // Create a new ACL that contains the new ACEs.
        dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);
        if (ERROR_SUCCESS != dwRes)
        {
            _tprintf(_T("SetEntriesInAcl Error %u
    "), GetLastError());
            goto Cleanup;
        }
    
        // Initialize a security descriptor.  
        pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
            SECURITY_DESCRIPTOR_MIN_LENGTH);
        if (NULL == pSD)
        {
            _tprintf(_T("LocalAlloc Error %u
    "), GetLastError());
            goto Cleanup;
        }
    
        if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION))
        {
            _tprintf(_T("InitializeSecurityDescriptor Error %u
    "),
                GetLastError());
            goto Cleanup;
        }
    
        // Add the ACL to the security descriptor. 
        if (!SetSecurityDescriptorDacl(pSD,
            TRUE,     // bDaclPresent flag   
            pACL,
            FALSE))   // not a default DACL 
        {
            _tprintf(_T("SetSecurityDescriptorDacl Error %u
    "),
                GetLastError());
            goto Cleanup;
        }
    
        // Initialize a security attributes structure.
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.lpSecurityDescriptor = pSD;
        sa.bInheritHandle = FALSE;
    
        // Use the security attributes to set the security descriptor 
        // when you create a key.
        lRes =  CreateFile(_T("D:\File.txt"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
            &sa, OPEN_ALWAYS, 0, NULL);
        if (lRes != NULL)
        {
            _tprintf(_T("Create file success
    "));
        }
       
    Cleanup:
    
        if (pACL)
            LocalFree(pACL);
        if (pSD)
            LocalFree(pSD);
        if (lRes)
           CloseHandle(lRes);
        return;
    
    }

    结果: 创建了一个文本,我们可以检查文本的属性来验证是否成功。

    文档参考: 在C ++中为新对象创建安全描述符

                        C-C++ Code Example: Creating a Security Descriptor

    拓展:

    我们可以使用SetNamedSecurityInfo函数,将访问权限限制为特定的用户帐户和/或组。 不过如果具有足够权限的合适用户帐户运行您的应用程序(或与此相关的任何应用程序),或者您的应用程序(或其他应用程序)冒充了该帐户,则它将能够访问该文件。

    案例参考: 使用C ++制作具有仅用户可以查看和编辑的权限的文件

    关于ACL和ACE的详细介绍: 关于Windows安全权限的学习(三)

    部分内容(防止丢失):

    一个安全描述符包含以下安全信息:

    • 两个安全标识符(Security identifiers),简称为SID,分别是OwnerSid和GroupSid. 所谓SID就是每次当我们创建一个用户或一个组的时候,系统会分配给改用户或组一个唯一SID,当你重新安装系统后,也会得到一个唯一的SID。SID是唯一的,不随用户的删除而分配到另外的用户使用。
      请记住,SID永远都是唯一的SIF是由计算机名、当前时间、当前用户态线程的CPU耗费时间的总和三个参数决定以保证它的唯一性。
        例:   S-1-5-21-1763234323-3212657521-1234321321-500
    • 一个DACL(Discretionary Access Control List),其指出了允许和拒绝某用户或用户组的存取控制列表。 当一个进程需要访问安全对象,系统就会检查DACL来决定进程的访问权。如果一个对象没有DACL,那么就是说这个对象是任何人都可以拥有完全的访问权限。
    • 一个SACL(System Access Control List),其指出了在该对象上的一组存取方式(如,读、写、运行等)的存取控制权限细节的列表。
    • 还有其自身的一些控制位。SECURITY_DESCRIPTOR_CONTROL

              DACL和SACL构成了整个存取控制列表Access Control List,简称ACL,ACL中的每一项,我们叫做ACE(Access Control Entry),ACL中的每一个ACE。

  • 相关阅读:
    我的第一篇博客,简单介绍MarkDown的语法。
    js实现网页pdf打印
    spring与hibernate整合入门-----示例一:各自为政【第一天】
    思考记录
    hibernate入门---Hibernate查询方式(for循环、构造器、对象数组等)【第三天,相当于总结整合】
    hibernate入门---uuid.hex生成方式【依据机器标识等自生】【第二天】
    hibernate入门-------实例、increment生成方式【实例自增-避免使用】【第二天】
    Hibernate入门----几种主键ID生成方式及示例【第二天】
    bat入门-----attrib隐藏文件【第一天】
    bat入门-----依据ping状态判断ip【第一天】
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14173054.html
Copyright © 2020-2023  润新知