C++ GetNamedSecurityInfo在写入远程Windows共享文件夹的所有者时返回错误\u访问\u拒绝(5)

C++ GetNamedSecurityInfo在写入远程Windows共享文件夹的所有者时返回错误\u访问\u拒绝(5),c++,winapi,active-directory,access-denied,C++,Winapi,Active Directory,Access Denied,我是一名域管理员,我想以API(例如C++)编程的方式在我的域的某个服务器上拥有一些共享文件夹的所有权。我做了一些阅读工作,发现默认情况下,域管理员位于成员计算机的本地管理员组中,并且本地管理员用户可以获得所有权。我只是以这种方式编写了一些代码,但在使用GetNamedSecurityInfo获取所有者sid时仍然遇到错误\u ACCESS\u DENIED?问题出在哪里 有趣的是:当我将GetNamedSecurityInfo的secound参数从SE_FILE_对象更改为SE_LMSHARE

我是一名域管理员,我想以API(例如C++)编程的方式在我的域的某个服务器上拥有一些共享文件夹的所有权。我做了一些阅读工作,发现默认情况下,域管理员位于成员计算机的本地管理员组中,并且本地管理员用户可以获得所有权。我只是以这种方式编写了一些代码,但在使用GetNamedSecurityInfo获取所有者sid时仍然遇到错误\u ACCESS\u DENIED?问题出在哪里

有趣的是:当我将GetNamedSecurityInfo的secound参数从SE_FILE_对象更改为SE_LMSHARE时,它会成功(也设置了一个)。但我在文件夹属性的“安全”选项卡中没有看到所有者发生更改。我知道“共享”权限与“安全”权限不同。“共享”权限甚至没有所有者。那么,当通过seu LMSHARE参数调用GetNamedSecurityInfo时,我得到了什么所有者

这是我用于获取文件夹“strFileName”所有权的函数,在服务器“strServerName”上,所有者更改为的只是名为“strDomainName”“strUserName”“strPassword”的域管理员帐户,原始所有者保留在“poriginId”中。 我在GetNamedSecurityInfo调用(也是Set调用)中得到了错误代码5。我还编写了一个模拟方法“logOnByUserPassword”,它似乎不起作用,我将它粘贴到下面

HANDLE ADPermissionSearch::getAccessTokenByCredential(CString strDomainName、CString strUserName、CString strPassword) {

}

int ADPermissionSearch::takeOwnership(CString strServerName、CString strFileName、CString strDomainName、CString strUserName、CString strPassword、u out PSID和poriginId) {

}

BOOL ADDirectorySearch::logOnByUserPassword(CString strDomainName、CString strUserName、CString strPassword) {


}

本地管理员需要接受通常的Windows安全检查,但有一个例外:无论权限如何,他们始终可以拥有受保护对象的所有权。这确保管理员始终能够重新获得控制权

但是,您并不是试图获取所有权,而是试图读取当前所有者,并且您不一定拥有这样做的权限

您的代码不清楚您为什么要读取所有者。你好像什么都没做。可能会完全删除对GetNamedSecurityInfo的调用

更新

目的是编写一个程序来检查每个共享上的DACL。因此,它需要保存当前所有者、获取所有权、读取DACL并恢复所有者。但在取得所有权之前,无法读取当前所有者

我认为这种行为是故意的。最初的意图是管理员能够获得所有权,但不会对对象的所有者隐瞒他们拥有所有权的事实,尽管有办法解决这个问题。例如,对于文件,您可以通过启用备份权限、调用BackupRead并解析输出(一系列WIN32_STREAM_ID结构,每个结构后跟数据)来读取完整的安全描述符(包括所有者)。我不知道有没有更简单的方法

有关股份的信息存储在注册表中的以下位置:

SYSTEM\CurrentControlSet\Services\LanmanServer\Shares


安全信息似乎存储在
security
子项中,以共享名命名。这个二进制值似乎是一个安全描述符,因此您可以使用它读取所有者。您还可以从此安全描述符读取所有其他安全信息,因此根本不需要更改所有者。

在GetNamedSecurityInfo之后,我有一个SetNamedSecurityInfo调用。SetNamedSecurityInfo函数使我通过参数传递的帐户成为所有者。这是在收购方法中。我只是想知道如何让Windows相信我是本地管理员帐户,并允许我接受所有者?我为此编写了logOnByUserPassword方法,但不知道它是对还是错?是的,但如果
GetNamedSecurityInfo
失败(即使您是管理员也可能失败),您永远不会调用
SetNamedSecurityInfo
。哦。。。我知道哪里不对。你的意思是我只能带着主人,而不能看。我想解释一下我的全部功能,让你们知道我为什么这么做:我写这个软件是为了读取所有共享文件夹的DACL。但有时文件夹甚至禁止域管理员阅读它。因此,我使用此“获取所有权”方法获取所有文件夹的DACL,但我不想在使用该软件后更改域或服务器。以下步骤:1)将所有者设置为域管理员2)将读取权限设置为域管理员3)读取文件夹的安全描述符(然后读取DACL)4)恢复原始权限5)恢复原始所有者。因此,在恢复之前,我需要先通过GetNamedSecurityInfo获取所有者。如何解决这个问题?谢谢你干得好!我还有几个问题。您似乎有两种解决方法:1)通过调用BackupRead获得SD。2) 从注册表项获取SD。对于1)我注意到函数需要一个句柄,那么如何获取远程共享文件夹的句柄呢?2) 我一直认为共享文件夹有两个SDs,一个是共享文件夹,一个是NTFS文件夹(我不知道这种理解是否正确,但我已经编写了两个函数来获取SDs,它似乎可以工作)。我不知道哪个是安全注册表项?
CString strUPNUserName = strUserName + _T("@") + strDomainName;

HANDLE hToken;
BOOL bResult;
//bResult = LogonUser(strUserName, strDomainName, strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
//  &hToken);
if (strDomainName != _T(""))
{
    bResult = LogonUser(strUPNUserName, _T(""), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
else
{
    bResult = LogonUser(strUserName, _T("."), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
if (bResult == FALSE)
{
    MyMessageBox_Error(_T("getAccessTokenByCredential Error."), _T("Error"));
    return FALSE;
}
else
{
    return hToken;
}
CString strUNCFileName = _T("\\\\") + strServerName + _T("\\") + strFileName;
_bstr_t bstrUNCFileName = _bstr_t(strUNCFileName);
PSID pSIDAdmin = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
HANDLE hToken = NULL;
DWORD dwRes;

// Create a SID for the BUILTIN\Administrators group.
if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &pSIDAdmin))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// If the preceding call failed because access was denied,
// enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for
// the Administrators group, take ownership of the object, and
// disable the privilege. Then try again to set the object's DACL.

// Open a handle to the access token for the calling process.
/*
if (!OpenProcessToken(GetCurrentProcess(),
                      TOKEN_ADJUST_PRIVILEGES,
                      &hToken))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}
*/
if ((hToken = getAccessTokenByCredential(strDomainName, strUserName, strPassword)) == NULL)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Enable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!setPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Get the original owner in the object's security descriptor.
dwRes = GetNamedSecurityInfo(
    bstrUNCFileName,             // name of the object
    SE_FILE_OBJECT,                  // type of object
    OWNER_SECURITY_INFORMATION,  // change only the object's owner
    &pOriginSID,                 // SID of Administrator group
    NULL,
    NULL,
    NULL,
    NULL);
if (dwRes != ERROR_SUCCESS)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Set the owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
            bstrUNCFileName,             // name of the object
            SE_FILE_OBJECT,                  // type of object
            OWNER_SECURITY_INFORMATION,  // change only the object's owner
            pSIDAdmin,                   // SID of Administrator group
            NULL,
            NULL,
            NULL);
if (dwRes != ERROR_SUCCESS)
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

// Disable the SE_TAKE_OWNERSHIP_NAME privilege.
if (!setPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
    if (pSIDAdmin)
        FreeSid(pSIDAdmin);
    if (hToken)
        CloseHandle(hToken);
    MyMessageBox_Error(_T("takeOwnership"));
    return 0;
}

return 1;
CString strUPNUserName = strUserName + _T("@") + strDomainName;

HANDLE hToken;
BOOL bResult;
//bResult = LogonUser(strUserName, strDomainName, strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT,
//  &hToken);
if (strDomainName != _T(""))
{
    bResult = LogonUser(strUPNUserName, _T(""), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
else
{
    bResult = LogonUser(strUserName, _T("."), strPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, 
        &hToken);
}
if (bResult == FALSE)
{
    MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
    return FALSE;
}
else
{
    bResult = ImpersonateLoggedOnUser(hToken);
    if (bResult == FALSE)
    {
        MyMessageBox_Error(_T("logOnByUserPassword Error."), _T("Error"));
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}