需要首先获取特定用户的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.\n", 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.\n");
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.\n");
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\n", 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\n"), GetLastError());
goto Cleanup;
} // Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
_tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
goto Cleanup;
} if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION))
{
_tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
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\n"),
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\n"));
} 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。

win32 - 将文件的访问权限给特定的用户的更多相关文章

  1. UNIX环境编程学习笔记(8)——文件I/O之校验当前登录用户对文件的访问权限

    lienhua342014-09-03 通过前面一篇随笔(文件访问权限与进程访问控制),我们知道内核校验文件的访问权限使用的是进程的有效用户 ID 和有效组 ID.但有时我们需要知道当前登录用户对某个 ...

  2. python判断文件的访问权限

    os.access(file, mode)判断文件的访问权限file为文件mode为操作模式,有这么几种:os.F_OK: 检查文件是否存在;os.R_OK: 检查文件是否可读;os.W_OK: 检查 ...

  3. 【C# IO 操作】C#修改文件或文件夹的权限,为指定用户、用户组添加完全控制权限

    代码实现 在C盘添加一个文件夹,并在文件夹内部,新建一个文本文件,如图所示: 该文件夹下,新建一个文本文件,如图所示: 为文件添加完全控制权限: /// <summary> /// 为文件 ...

  4. C#修改文件或文件夹的权限,为指定用户、用户组添加完全控制权限

    C#修改文件或文件夹的权限,为指定用户.用户组添加完全控制权限 public void SetFileRole(string foldPath) { DirectorySecurity fsec = ...

  5. 关于heritrix安装配置时出现”必须限制口令文件读取访问权限”的解决方法

    转载:http://www.floatinglife.cn/关于heritrix安装配置时出现必须限制口令文件读取访问 最近开始写一个RSS聚合程序,需要爬虫支持,于是就整来heritrix,没想到, ...

  6. Windows Server 2012下手动配置IIS的文件夹访问权限

    当新建一个website的时候,一般情况下IIS对相应的物理文件夹的访问权限是不够的. 针对匿名认证(anonymous authentication)需要: 打开文件夹properties-> ...

  7. chmod - 改变文件的访问权限

    总揽 chmod [options] mode file... POSIX 选项: [-R] GNU 选项 (最短方式): [-cfvR] [--reference=rfile] [--help] [ ...

  8. Linux中文件夹访问权限不足

    经常操作Linux服务器,远程访问会遇到403问题,本篇讲述nginx下文件权限的修改. 1.命令修改该文件夹的权限 chmod -R 755 /usr/local/....   文件夹的路径 2.修 ...

  9. DACL原理.控制文件的访问权限(文件,注册表.目录.等任何带有安全属性的对象.)

    目录 一丶简介 1.DACL是什么. 2.如何创建一个自己控制的文件. 3.SDDL是个什么鬼. 二丶 编写SDDL 控制的文件 一丶简介 1.DACL是什么. DACL称为自主访问的控制列表.是应用 ...

  10. Linux的文件/目录访问权限

    一直以为对这个概念非常懂,但这次还是犯了眼高手低的毛病. 配置服务器遇到了一个问题,对某个WEB目录(例如"/bin"),有两个用户要对其进行读写操作: 首先apache服务器要对 ...

随机推荐

  1. [转帖]一次ORA-3136的处理

    https://oracleblog.org/working-case/deal-with-ora3136/ 最近收到一个告警,用户说数据库无法连接,但是从监控上看,oracle的后台进程已经侦听进程 ...

  2. [转帖]What is Pstate

    https://www.jianshu.com/p/342480d917e3 When someone refers to a P-state, generally only the frequenc ...

  3. [转帖]gcc与makefile常用操作(绝对常用,也绝对够用)

    makefile与gcc常用操作 一.温故知新 1.可执行程序的生成过程 2.gcc的常用操作 二.make操作 三.编写Makefile文件时常用操作 注意:在Makefile文件中 空格和缩进是完 ...

  4. [转帖]Linux make: g++: Command not found

    https://www.cnblogs.com/kerrycode/p/4748606.html Linux使用make命令时遇到"make: g++: Command not found& ...

  5. [转帖]/etc/passwd文件 各个字段详解

    转载自:https://www.sohu.com/a/320177323_505901 /etc/passwd文件: 系统用户配置文件,存储了系统中所有用户的基本信息,并且所有用户都可以对此文件执行读 ...

  6. 分析fastcache和freecache(一)

    分析fastcache和freecache(一) fastcache和freecache是两个比较简单的缓存实现,下面分析一下各自的实现,并学习一下其实现中比较好的方式. fastcache 概述 f ...

  7. VScode中下载了插件但是无法找到SSH Target连接服务器的解决方法(CANNOT find SSH Target in remote explorer)

    VSCode版本vscode version:(version 1.82) 已下载扩展installed extensions: Remote - SSH v0.106.4 Remote - SSH: ...

  8. 像elementui一样封装自定义按钮

    <template> <div> <button @click.prevent="coverHandler" class="btn-btn& ...

  9. 【解决了一个小问题】terraform apply 的时候出现访问 localhost 出错

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 有这样一段 terraform 的部署脚本: provid ...

  10. 【K哥爬虫普法】倒计时21天!事关爬虫er们能否平安回家过年!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...