CreateFile不返回所需的特权

时间:2018-06-28 06:59:55

标签: windows winapi

尝试从Windows Server上运行的Win32应用程序在Samba上打开文件时,函数CreateFiles返回无效的句柄,错误代码为0x522(ERROR_PRIVILEGE_NOT_HELD),有一种方法可以查询缺少该特权的系统特定文件?

我模拟了登录的用户(应为管理员)后启用了一些安全特权:SE_SECURITY_NAME,SE_BACKUP_NAME和SE_RESTORE_NAME,但这不起作用。

我只需要对该文件具有读特权,并且我将以下选项提交给CreateFile:

 hSrcFile = CreateFile (sourcePath, READ_CONTROL | ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS, NULL);

其他一些可能不是很有用的信息:

  • 登录用户可以使用任何随机应用程序打开文件,例如 记事本。
  • 如果该进程在samba文件夹中创建一个新文件,则它也可以 毫无问题地打开它,问题似乎已经影响了文件 在程序启动之前创建。

有什么建议吗?谢谢

编辑1

要配置SE_SECURITY_NAME标志,我使用OpenProcessToken来获取Process令牌,然后使用this function from MSDN来启用特权。

我还尝试以登录身份以admin身份使用LogonUser中的令牌来设置特权,但是在这种情况下,MSDN funtion似乎失败,错误为ACCESS_DENIED。用DuplicateToken(和SecurityDelegation标志)复制令牌后,做同样的事情也不起作用。

在设置SE_SECURITY_NAME时,我已经验证了AdjustTokenPrivileges的返回值,并且该函数不会失败。我可以调用CreateFile来打开没有标志ACCESS_SYSTEM_SECURITY的文件,但是然后我不能使用文件句柄来调用GetFileInformationByHandleEx,因为该函数失败并显示ACCESS DENIED,不确定是否与ACCESS_SYSTEM_SECURITY相关是否。

编辑2

我正在执行以下步骤来启用SE_SECURITY_NAME,然后使用CreateFile:

  • 使用OpenProcessToken(标志TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY)获取进程令牌,然后使用SE_SECURITY_NAME,SE_BACKUP_NAME和SE_RESTORE_NAME调用AdjustTokenPrivileges。 (使用LookupPrivilegeValue获得正确的LUID之后)。该函数返回的错误代码为0x0。

  • 使用OpenThreadToken(标志TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY)获取线程令牌,并使用SE_SECURITY_NAME,SE_BACKUP_NAME和SE_RESTORE_NAME调用AdjustTokenPrivileges。 (使用LookupPrivilegeValue获得正确的LUID之后)。该函数返回的错误代码为0x0。

  • 使用CreateFile(pathTofile, READ_CONTROL | ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTIC,NULL)调用CreateFile,该函数将返回0x522:特权未获得。 pathToFile的格式类似于“ \ 192.168.0.0 \ folder \ file.txt”

希望这可以澄清流程,启用特权的代码为:

bStatus = LookupPrivilegeValue (NULL, privilegeStr, &luid);
if (!bStatus)
{
    dwStatus = GetLastError();
   // do stuff
}

ZeroMemory (&tp, sizeof (tp));
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

/* Adjust Token privileges */
bStatus = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
    &oldtp, &dwSize);
dwStatus = GetLastError();
if (!bStatus || dwStatus != ERROR_SUCCESS )
{
    //do stuff, print error etc.
}

其中privilegeStr例如是SE_SECURITY_NAME

编辑3

为了希望提供一个能使问题重现的代码示例,从而为它提供一个可能的解决方案,我准备了以下丑陋的代码片段:

HANDLE hToken;
bStatus = OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
    TOKEN_QUERY, TRUE, &hToken);

LUID luid;
LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid);

TOKEN_PRIVILEGES    tp = { 0, };
TOKEN_PRIVILEGES    oldtp = { 0, };
DWORD               dwSize = sizeof(TOKEN_PRIVILEGES);

ZeroMemory(&tp, sizeof(tp));
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

/* Adjust Token privileges */
bStatus = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
    &oldtp, &dwSize);
dwStatus = GetLastError();
if (!bStatus || dwStatus != ERROR_SUCCESS)
{
    //Print error.
}

PRIVILEGE_SET privSet;
ZeroMemory(&privSet, sizeof(PRIVILEGE_SET));

privSet.PrivilegeCount = 1;
privSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
privSet.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
privSet.Privilege[0].Luid = luid;

BOOL bResult;
PrivilegeCheck(hToken, &privSet, &bResult);

fprintf(stderr,"Status bool: %d, attr value:0x%x, error code: 0x%x\n", 
    bResult,
    privSet.Privilege[0].Attributes,
    GetLastError());

hSrcFile = CreateFile (sourcePath, READ_CONTROL | ACCESS_SYSTEM_SECURITY, 0, NULL, OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS, NULL);

if( hSrcFile == INVALID_HANDLE_VALUE )
{
    fprintf(stderr,"CreateFile error 0x%x\n", GetLastError());
}

输出为Status bool:1, attr value:0x80000002, error code: 0x0,后跟CreateFile error 0x522

此示例是否确认启用了SE_SECURITY_NAME,但CreateFile仍然失败?还有什么需要的吗?另外:

  • 我可以使用ACCESS_SYSTEM_SECURITY
  • 打开本地磁盘上的任何其他随机文件
  • 无法访问的文件位于SAMBA上,如我的问题的第一行所述,这与必须配置这些属性的方式有关吗?看起来是这样,但不知道如何。

0 个答案:

没有答案