在写远程Windows共享文件夹的所有者时,GetNamedSecurityInfo返回ERROR_ACCESS_DENIED(5) [英] GetNamedSecurityInfo returns ERROR_ACCESS_DENIED(5) when writting owner of a remote Windows shared folder

查看:2220
本文介绍了在写远程Windows共享文件夹的所有者时,GetNamedSecurityInfo返回ERROR_ACCESS_DENIED(5)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是域管理员,并且希望在API(例如C ++)中以程序方式获取域的某些服务器上的某些共享文件夹的所有权。我做了一些阅读工作,发现域管理员在成员计算机的本地管理员组中默认情况下,本地管理员用户可以取得所有权。我只是以这种方式wrtie一些代码,但仍然遇到ERROR_ACCESS_DENIED当获取所有者sid使用GetNamedSecurityInfo?问题在哪里?

I'm a Domain Admin and I want to take ownership of some shared folders on some server of my domain programmatically in API(for example C++). I did some reading work and found that a Domain Admin is in the member machine's Local Admins group by default, and the Local Admins users can take ownership anyway. I just wrtie some code in this way but still encountered ERROR_ACCESS_DENIED when getting the owner sid using GetNamedSecurityInfo? Where's the problem?

有趣的是:当我将GetNamedSecurityInfo的secound参数从SE_FILE_OBJECT改为SE_LMSHARE时,它会成功(也设置一个)。但我没有看到所有者更改在文件夹的属性的安全选项卡。我知道一个共享权限是不同的安全一。一个共享权限即使没有所有者。那么我通过SE_LMSHARE参数调用GetNamedSecurityInfo时获得什么所有者?

Something interesting is: When I changed the GetNamedSecurityInfo's secound argument from SE_FILE_OBJECT to SE_LMSHARE, it would succeed(also set one). But I didn't see the owner changed in the "Security" tab of folder's properties. I know a "share" permission is different with "security" one. a "share" permission even don't have a owner. So what owner did I get when calling GetNamedSecurityInfo by the SE_LMSHARE argument?

这里是我为服务器strServerName的文件夹strFileName所有者更改为只是称为strDomainNamestrUserNamestrPassword的域管理帐户,在pOriginSID中保留原始所有者。
我在GetNamedSecurityInfo调用中得到错误代码5(也是Set one)。我也写了一个模拟方法logOnByUserPassword,这似乎不工作,我粘贴它下面。

Here's the function i use for Taking ownership for the folder "strFileName", on server "strServerName", the owner changed to is just the Domain Admin account known as "strDomainName" "strUserName" "strPassword", orginal owner is reserved in "pOriginSID". I got error code 5 in the GetNamedSecurityInfo call (also the Set one). I also write a impersonation method "logOnByUserPassword" which seems not to work, i paste it below.

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

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

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;
}

}

int ADPermissionSearch :: takeOwnership(CString strServerName,CString strFileName,CString strDomainName,CString strUserName,CString strPassword,__out PSID& pOriginSID)
{

int ADPermissionSearch::takeOwnership(CString strServerName, CString strFileName, CString strDomainName, CString strUserName, CString strPassword, __out PSID &pOriginSID) {

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;

}

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

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

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;
    }
}

}

推荐答案

本地管理员受到通常的Windows安全检查,但有一个例外:他们可以始终获取受保护对象的所有权,而不管权限。这可以确保管理员始终能够重新获得控制权。

Local admins are subject to the usual Windows security checks with one exception: they can always take ownership of a secured object regardless of the permissions. This ensures that admins are always able to regain control.

但是,您并未尝试取得所有权,而是尝试读取当前所有者,而不一定是有权限这样做。

However, you are not trying to take ownership, you are trying to read the current owner and you don't necessarily have permission to do that.

您的代码不清楚为什么要尝试读取所有者。你似乎没有做任何事情。或许可以完全取消对GetNamedSecurityInfo的调用。

It's not clear from your code why you are trying to read the owner. You don't seem to do anything with it. Maybe remove the call to GetNamedSecurityInfo altogether.

更新

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

The intention is to write a program that checks the DACLs on every share. So it needs to save the current owner, take ownership, read the DACLs and restore the owner. But the current owner cannot be read until ownership has been taken.

我认为这种行为是设计的。最初的意图是,管理员能够取得所有权,但不隐藏事实,他们从一个对象的所有者,虽然有方法。例如,对于文件,可以通过启用备份特权,调用BackupRead并解析输出(WIN32_STREAM_ID结构序列,后跟数据)来读取完整的安全描述符(包括所有者)。我不知道是否有更简单的方法。

I think this behaviour is by design. The original intention was that admins were able to take ownership, but not hide the fact that they had from the owner of an object, though there are ways around this. For example, for files you can read the complete security descriptor (including the owner) by enabling the backup privilege, calling BackupRead and parsing the output (a sequence of WIN32_STREAM_ID structures each followed by data). I don't know if there's a simpler way.

有关股份的信息存储在注册表中:

Information about shares is stored in the registry under:

SYSTEM\CurrentControlSet\Services\LanmanServer\Shares

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

The security info seems to be stored in the Security subkey, in a value named after the share. This binary value seems to be a security descriptor so you can read the owner with GetSecurityDescriptorOwner. You can also read all the other security info from this security descriptor, so you shouldn't need to change the owner at all.

这篇关于在写远程Windows共享文件夹的所有者时,GetNamedSecurityInfo返回ERROR_ACCESS_DENIED(5)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆