842 lines
24 KiB
C++
842 lines
24 KiB
C++
|
//-----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Copyright (C) 1998, Microsoft Corporation
|
||
|
//
|
||
|
// File: dfsacl.c
|
||
|
|
||
|
// Contents: Functions to add/remove entries from ACL list(s).
|
||
|
//
|
||
|
// History: Nov 6, 1998 JHarper created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#define UNICODE
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <winldap.h>
|
||
|
#include <ntldap.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <dsgetdc.h>
|
||
|
#include <lm.h>
|
||
|
#include <sddl.h>
|
||
|
#include <dfsstr.h>
|
||
|
#include <dfsmrshl.h>
|
||
|
#include <marshal.hxx>
|
||
|
#include <lmdfs.h>
|
||
|
#include <dfspriv.h>
|
||
|
#include <csites.hxx>
|
||
|
#include <dfsm.hxx>
|
||
|
#include <recon.hxx>
|
||
|
|
||
|
#include "dfsacl.hxx"
|
||
|
#include "struct.hxx"
|
||
|
|
||
|
DWORD
|
||
|
ReadDSObjSecDesc(
|
||
|
PLDAP pLDAP,
|
||
|
PWSTR pwszObject,
|
||
|
SECURITY_INFORMATION SeInfo,
|
||
|
PSECURITY_DESCRIPTOR *ppSD,
|
||
|
PULONG pcSDSize);
|
||
|
|
||
|
DWORD
|
||
|
DfsGetObjSecurity(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR pwszObjectName,
|
||
|
LPWSTR *pwszStringSD);
|
||
|
|
||
|
DWORD
|
||
|
DfsStampSD(
|
||
|
PWSTR pwszObject,
|
||
|
ULONG cSDSize,
|
||
|
SECURITY_INFORMATION SeInfo,
|
||
|
PSECURITY_DESCRIPTOR pSD,
|
||
|
PLDAP pLDAP);
|
||
|
|
||
|
DWORD
|
||
|
DfsAddAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszStringSD,
|
||
|
LPWSTR wszwszStringSid);
|
||
|
|
||
|
DWORD
|
||
|
DfsRemoveAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszStringSD,
|
||
|
LPWSTR wszwszStringSid);
|
||
|
|
||
|
BOOL
|
||
|
DfsFindSid(
|
||
|
LPWSTR DcName,
|
||
|
LPWSTR Name,
|
||
|
PSID *Sid);
|
||
|
|
||
|
BOOLEAN
|
||
|
DfsSidInAce(
|
||
|
LPWSTR wszAce,
|
||
|
LPWSTR wszStringSid);
|
||
|
|
||
|
#define ACTRL_SD_PROP_NAME L"nTSecurityDescriptor"
|
||
|
|
||
|
//
|
||
|
// Name of the attribute holding the ACL/ACE list
|
||
|
//
|
||
|
|
||
|
#define ACTRL_SD_PROP_NAME L"nTSecurityDescriptor"
|
||
|
|
||
|
//
|
||
|
// The sddl description of the ACE we will be adding
|
||
|
//
|
||
|
LPWSTR wszAce = L"(A;;RPWP;;;";
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsAddMachineAce
|
||
|
//
|
||
|
// Synopsis: Adds an ACE representing this machine to the ACL list of the
|
||
|
// object.
|
||
|
//
|
||
|
// Arguments: [pldap] -- The open LDAP connection
|
||
|
// [wszDcName] -- The DC whose DS we are to use.
|
||
|
// [wszObjectName] -- The fully-qualified name of the DS object
|
||
|
// [wszRootName] -- The name of the machine/root we want to add
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- The object is reachable
|
||
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsAddMachineAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszDcName,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszRootName)
|
||
|
{
|
||
|
ULONG dwErr = ERROR_SUCCESS;
|
||
|
PSID Sid;
|
||
|
BOOL Result;
|
||
|
ULONG i;
|
||
|
WCHAR wszNewSD[MAX_PATH];
|
||
|
LPWSTR wszStringSD = NULL;
|
||
|
LPWSTR wszStringSid = NULL;
|
||
|
LPWSTR wszNewRootName = NULL;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsAddMachineAce(%ws,%ws)\r\n", wszObjectName, wszRootName);
|
||
|
//
|
||
|
// Get Security Descriptor on the FtDfs object
|
||
|
//
|
||
|
dwErr = DfsGetObjSecurity(pldap, wszObjectName, &wszStringSD);
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"ACL=[%ws]\r\n", wszStringSD);
|
||
|
wszNewRootName = (LPWSTR)malloc((wcslen(wszRootName) + 2) * sizeof(WCHAR));
|
||
|
if (wszNewRootName != NULL) {
|
||
|
wcscpy(wszNewRootName, wszRootName);
|
||
|
for (i = 0; wszNewRootName[i] != L'\0'; i++) {
|
||
|
if (wszNewRootName[i] == L'.') {
|
||
|
wszNewRootName[i] = L'\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
wcscat(wszNewRootName, L"$");
|
||
|
//
|
||
|
// Get SID representing root machine
|
||
|
//
|
||
|
Result = DfsFindSid(wszDcName,wszNewRootName, &Sid);
|
||
|
if (Result == TRUE) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Got SID for %ws\r\n", wszRootName);
|
||
|
//
|
||
|
// Convert the machine SID to a string
|
||
|
//
|
||
|
Result = ConvertSidToStringSid(Sid, &wszStringSid);
|
||
|
if (Result == TRUE) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Sid=[%ws]\r\n", wszStringSid);
|
||
|
//
|
||
|
// Now update the ACL list on the FtDfs object
|
||
|
//
|
||
|
DfsAddAce(
|
||
|
pldap,
|
||
|
wszObjectName,
|
||
|
wszStringSD,
|
||
|
wszStringSid);
|
||
|
LocalFree(wszStringSid);
|
||
|
}
|
||
|
} else {
|
||
|
dwErr = ERROR_OBJECT_NOT_FOUND;
|
||
|
}
|
||
|
free(wszNewRootName);
|
||
|
} else {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
LocalFree(wszStringSD);
|
||
|
}
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsAddMachineAce returning %d\r\n", dwErr);
|
||
|
return dwErr;
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsRemoveMachineAce
|
||
|
//
|
||
|
// Synopsis: Removes an ACE representing this machine from the ACL list of the
|
||
|
// object.
|
||
|
//
|
||
|
// Arguments: [pldap] -- The open LDAP connection
|
||
|
// [wszDcName] -- The DC whose DS we are to use.
|
||
|
// [wszObjectName] -- The fully-qualified name of the DS object
|
||
|
// [wszRootName] -- The name of the machine/root we want to remove
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- The object is reachable
|
||
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsRemoveMachineAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszDcName,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszRootName)
|
||
|
{
|
||
|
ULONG dwErr = ERROR_SUCCESS;
|
||
|
PSID Sid;
|
||
|
BOOL Result;
|
||
|
WCHAR wszNewSD[MAX_PATH];
|
||
|
LPWSTR wszStringSD = NULL;
|
||
|
LPWSTR wszStringSid = NULL;
|
||
|
LPWSTR wszNewRootName = NULL;
|
||
|
ULONG i;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRemoveMachineAce(DC=%ws,DN=\"%ws\",Root=%ws)\r\n",
|
||
|
wszDcName,
|
||
|
wszObjectName,
|
||
|
wszRootName);
|
||
|
//
|
||
|
// Get Security Descriptor on the FtDfs object
|
||
|
//
|
||
|
dwErr = DfsGetObjSecurity(pldap, wszObjectName, &wszStringSD);
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"ACL=[%ws]\r\n", wszStringSD);
|
||
|
wszNewRootName = (LPWSTR)malloc((wcslen(wszRootName) + 2) * sizeof(WCHAR));
|
||
|
if (wszNewRootName != NULL) {
|
||
|
wcscpy(wszNewRootName, wszRootName);
|
||
|
for (i = 0; wszNewRootName[i] != L'\0'; i++) {
|
||
|
if (wszNewRootName[i] == L'.') {
|
||
|
wszNewRootName[i] = L'\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
wcscat(wszNewRootName, L"$");
|
||
|
//
|
||
|
// Get SID representing root machine
|
||
|
//
|
||
|
Result = DfsFindSid(wszDcName,wszNewRootName, &Sid);
|
||
|
if (Result == TRUE) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Got SID for %ws\r\n", wszRootName);
|
||
|
//
|
||
|
// Convert the machine SID to a string
|
||
|
//
|
||
|
Result = ConvertSidToStringSid(Sid, &wszStringSid);
|
||
|
if (Result == TRUE) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Sid=[%ws]\r\n", wszStringSid);
|
||
|
//
|
||
|
// Now update the ACL list on the FtDfs object
|
||
|
//
|
||
|
DfsRemoveAce(
|
||
|
pldap,
|
||
|
wszObjectName,
|
||
|
wszStringSD,
|
||
|
wszStringSid);
|
||
|
LocalFree(wszStringSid);
|
||
|
}
|
||
|
} else {
|
||
|
dwErr = ERROR_OBJECT_NOT_FOUND;
|
||
|
}
|
||
|
free(wszNewRootName);
|
||
|
} else {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
LocalFree(wszStringSD);
|
||
|
}
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRemoveMachineAce exit %d\r\n", dwErr);
|
||
|
return dwErr;
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: ReadDSObjSecDesc
|
||
|
//
|
||
|
// Synopsis: Reads the security descriptor from the specied object via
|
||
|
// the open ldap connection
|
||
|
//
|
||
|
// Arguments: [pLDAP] -- The open LDAP connection
|
||
|
// [pwszDSObj] -- The DSObject to get the security
|
||
|
// descriptor for
|
||
|
// [SeInfo] -- Parts of the security descriptor to
|
||
|
// read.
|
||
|
// [ppSD] -- Where the security descriptor is
|
||
|
// returned
|
||
|
// [pcSDSize -- Size of the security descriptor
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- The object is reachable
|
||
|
// ERROR_NOT_ENOUGH_MEMORY A memory allocation failed
|
||
|
//
|
||
|
// Notes: The returned security descriptor must be freed with LocalFree
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
ReadDSObjSecDesc(
|
||
|
PLDAP pLDAP,
|
||
|
PWSTR pwszObject,
|
||
|
SECURITY_INFORMATION SeInfo,
|
||
|
PSECURITY_DESCRIPTOR *ppSD,
|
||
|
PULONG pcSDSize)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
PLDAPMessage pMsg = NULL;
|
||
|
PWSTR rgAttribs[2];
|
||
|
BYTE berValue[8];
|
||
|
|
||
|
LDAPControl SeInfoControl =
|
||
|
{
|
||
|
LDAP_SERVER_SD_FLAGS_OID_W,
|
||
|
{
|
||
|
5, (PCHAR)berValue
|
||
|
},
|
||
|
TRUE
|
||
|
};
|
||
|
|
||
|
PLDAPControl ServerControls[2] =
|
||
|
{
|
||
|
&SeInfoControl,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"ReadDSObjSecDesc(%ws)\r\n", pwszObject);
|
||
|
|
||
|
berValue[0] = 0x30;
|
||
|
berValue[1] = 0x03;
|
||
|
berValue[2] = 0x02;
|
||
|
berValue[3] = 0x01;
|
||
|
berValue[4] = (BYTE)((ULONG)SeInfo & 0xF);
|
||
|
|
||
|
|
||
|
rgAttribs[0] = ACTRL_SD_PROP_NAME;
|
||
|
rgAttribs[1] = NULL;
|
||
|
|
||
|
dwErr = ldap_search_ext_s(
|
||
|
pLDAP,
|
||
|
pwszObject,
|
||
|
LDAP_SCOPE_BASE,
|
||
|
L"(objectClass=*)",
|
||
|
rgAttribs,
|
||
|
0,
|
||
|
(PLDAPControl *)&ServerControls,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
10000,
|
||
|
&pMsg);
|
||
|
|
||
|
dwErr = LdapMapErrorToWin32( dwErr );
|
||
|
if(dwErr == ERROR_SUCCESS) {
|
||
|
|
||
|
LDAPMessage *pEntry = NULL;
|
||
|
PWSTR *ppwszValues = NULL;
|
||
|
PLDAP_BERVAL *pSize = NULL;
|
||
|
|
||
|
pEntry = ldap_first_entry(pLDAP, pMsg);
|
||
|
if(pEntry != NULL) {
|
||
|
//
|
||
|
// Now, we'll have to get the values
|
||
|
//
|
||
|
ppwszValues = ldap_get_values(pLDAP, pEntry, rgAttribs[0]);
|
||
|
if(ppwszValues != NULL) {
|
||
|
pSize = ldap_get_values_len(pLDAP, pMsg, rgAttribs[0]);
|
||
|
if(pSize != NULL) {
|
||
|
//
|
||
|
// Allocate the security descriptor to return
|
||
|
//
|
||
|
*ppSD = (PSECURITY_DESCRIPTOR)malloc((*pSize)->bv_len);
|
||
|
if(*ppSD != NULL) {
|
||
|
memcpy(*ppSD, (PBYTE)(*pSize)->bv_val, (*pSize)->bv_len);
|
||
|
*pcSDSize = (*pSize)->bv_len;
|
||
|
} else {
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
ldap_value_free_len(pSize);
|
||
|
} else {
|
||
|
dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
|
||
|
}
|
||
|
ldap_value_free(ppwszValues);
|
||
|
} else {
|
||
|
dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
|
||
|
}
|
||
|
} else {
|
||
|
dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
|
||
|
}
|
||
|
ldap_msgfree(pMsg);
|
||
|
|
||
|
}
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"ReadDSObjSecDesc returning %d\r\n", dwErr);
|
||
|
return(dwErr);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsGetObjSecurity
|
||
|
//
|
||
|
// Synopsis: Gets the ACL list of an object in sddl stringized form
|
||
|
//
|
||
|
// Arguments: [pldap] -- The open LDAP connection
|
||
|
// [wszObjectName] -- The fully-qualified name of the DS object
|
||
|
// [pwszStringSD] -- Pointer to pointer to SD in string form (sddl)
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- The object is reachable
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsGetObjSecurity(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR pwszObjectName,
|
||
|
LPWSTR *pwszStringSD)
|
||
|
{
|
||
|
DWORD dwErr;
|
||
|
WCHAR wszObjectName[ MAX_PATH ];
|
||
|
SECURITY_INFORMATION si;
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
ULONG cSDSize;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsGetObjSecurity(%ws)\r\n", pwszObjectName);
|
||
|
|
||
|
si = DACL_SECURITY_INFORMATION;
|
||
|
|
||
|
dwErr = ReadDSObjSecDesc(
|
||
|
pldap,
|
||
|
pwszObjectName,
|
||
|
si,
|
||
|
&pSD,
|
||
|
&cSDSize);
|
||
|
|
||
|
if (dwErr == ERROR_SUCCESS) {
|
||
|
if (!ConvertSecurityDescriptorToStringSecurityDescriptor(
|
||
|
pSD,
|
||
|
SDDL_REVISION_1,
|
||
|
DACL_SECURITY_INFORMATION,
|
||
|
pwszStringSD,
|
||
|
NULL)
|
||
|
) {
|
||
|
dwErr = GetLastError();
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"ConvertSecurityDescriptorToStringSecurityDescriptor FAILED %d:\r\n", dwErr);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return(dwErr);
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsFindSid
|
||
|
//
|
||
|
// Synopsis: Gets the SID for a name
|
||
|
//
|
||
|
// [DcName] -- The DC to remote to
|
||
|
// [Name] -- The Name of the object
|
||
|
// [Sid] -- Pointer to pointer to returned SID, which must be freed
|
||
|
// using LocalFree
|
||
|
//
|
||
|
// Returns: TRUE or FALSE
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOL
|
||
|
DfsFindSid(
|
||
|
LPWSTR DcName,
|
||
|
LPWSTR Name,
|
||
|
PSID *Sid
|
||
|
)
|
||
|
{
|
||
|
DWORD SidLength = 0;
|
||
|
WCHAR DomainName[256];
|
||
|
DWORD DomainNameLength = 256;
|
||
|
SID_NAME_USE Use;
|
||
|
BOOL Result;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsFindSid(%ws,%ws)\r\n", DcName,Name);
|
||
|
|
||
|
Result = LookupAccountName(
|
||
|
DcName,
|
||
|
Name,
|
||
|
(PSID)NULL,
|
||
|
&SidLength,
|
||
|
DomainName,
|
||
|
&DomainNameLength,
|
||
|
&Use);
|
||
|
|
||
|
if ( !Result && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ) {
|
||
|
|
||
|
*Sid = LocalAlloc( 0, SidLength );
|
||
|
|
||
|
Result = LookupAccountName(
|
||
|
NULL,
|
||
|
Name,
|
||
|
*Sid,
|
||
|
&SidLength,
|
||
|
DomainName,
|
||
|
&DomainNameLength,
|
||
|
&Use);
|
||
|
|
||
|
}
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsFindSid returning %s\r\n", Result == TRUE ? "TRUE" : "FALSE");
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsAddAce
|
||
|
//
|
||
|
// Synopsis: Adds a string ACE to a string version of an objects SD
|
||
|
// object. This is a string manipulation routine.
|
||
|
//
|
||
|
// Arguments: [pldap] -- The open LDAP connection
|
||
|
// [wszObjectName] -- The fully-qualified name of the DS object
|
||
|
// [wszStringSD] -- String version of SD
|
||
|
// [wszStringSid] -- String version of SID to add
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- ACE was added
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsAddAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszStringSD,
|
||
|
LPWSTR wszStringSid)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
LPWSTR wszNewStringSD = NULL;
|
||
|
SECURITY_INFORMATION si;
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
BOOL Result;
|
||
|
ULONG Size = 0;
|
||
|
ULONG cSDSize = 0;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsAddAce(%ws)\r\n", wszObjectName);
|
||
|
|
||
|
Size = wcslen(wszStringSD) * sizeof(WCHAR) +
|
||
|
wcslen(wszAce) * sizeof(WCHAR) +
|
||
|
wcslen(wszStringSid) * sizeof(WCHAR) +
|
||
|
wcslen(L")") * sizeof(WCHAR) +
|
||
|
sizeof(WCHAR);
|
||
|
|
||
|
wszNewStringSD = (LPWSTR)malloc(Size);
|
||
|
|
||
|
if (wszNewStringSD != NULL) {
|
||
|
wcscpy(wszNewStringSD,wszStringSD);
|
||
|
wcscat(wszNewStringSD,wszAce);
|
||
|
wcscat(wszNewStringSD,wszStringSid);
|
||
|
wcscat(wszNewStringSD,L")");
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"NewSD=[%ws]\r\n", wszNewStringSD);
|
||
|
Result = ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||
|
wszNewStringSD,
|
||
|
SDDL_REVISION_1,
|
||
|
&pSD,
|
||
|
&cSDSize);
|
||
|
if (Result == TRUE) {
|
||
|
si = DACL_SECURITY_INFORMATION;
|
||
|
dwErr = DfsStampSD(
|
||
|
wszObjectName,
|
||
|
cSDSize,
|
||
|
si,
|
||
|
pSD,
|
||
|
pldap);
|
||
|
LocalFree(pSD);
|
||
|
} else {
|
||
|
dwErr = GetLastError();
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Convert returned %d\r\n", dwErr);
|
||
|
}
|
||
|
free(wszNewStringSD);
|
||
|
} else {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsAddAce returning %d\r\n", dwErr);
|
||
|
return(dwErr);
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsRemoveAce
|
||
|
//
|
||
|
// Synopsis: Finds and removes a string ACE from the string SD of an
|
||
|
// object. This is a string manipulation routine.
|
||
|
//
|
||
|
// Arguments: [pldap] -- The open LDAP connection
|
||
|
// [wszObjectName] -- The fully-qualified name of the DS object
|
||
|
// [wszStringSD] -- String version of SD
|
||
|
// [wszStringSid] -- String version of SID to remove
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- ACE was removed or was not present
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsRemoveAce(
|
||
|
LDAP *pldap,
|
||
|
LPWSTR wszObjectName,
|
||
|
LPWSTR wszStringSD,
|
||
|
LPWSTR wszStringSid)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
LPWSTR wszNewStringSD = NULL;
|
||
|
SECURITY_INFORMATION si;
|
||
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
||
|
BOOL Result;
|
||
|
ULONG Size = 0;
|
||
|
ULONG cSDSize = 0;
|
||
|
BOOLEAN fCopying;
|
||
|
ULONG s1, s2;
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRemoveAce(%ws)\r\n", wszObjectName);
|
||
|
|
||
|
Size = wcslen(wszStringSD) * sizeof(WCHAR) + sizeof(WCHAR);
|
||
|
|
||
|
wszNewStringSD = (LPWSTR)malloc(Size);
|
||
|
|
||
|
if (wszNewStringSD != NULL) {
|
||
|
|
||
|
RtlZeroMemory(wszNewStringSD, Size);
|
||
|
|
||
|
//
|
||
|
// We have to find the ACEs containing this SID, and remove them.
|
||
|
//
|
||
|
|
||
|
fCopying = TRUE;
|
||
|
for (s1 = s2 = 0; wszStringSD[s1]; s1++) {
|
||
|
|
||
|
//
|
||
|
// If this is the start of an ACE that has this SID, stop copying
|
||
|
//
|
||
|
if (wszStringSD[s1] == L'(' && DfsSidInAce(&wszStringSD[s1],wszStringSid) == TRUE) {
|
||
|
fCopying = FALSE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If this is the end of SID we are not copying, start copying again
|
||
|
//
|
||
|
if (wszStringSD[s1] == L')' && fCopying == FALSE) {
|
||
|
fCopying = TRUE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we are copying, do so.
|
||
|
//
|
||
|
if (fCopying == TRUE)
|
||
|
wszNewStringSD[s2++] = wszStringSD[s1];
|
||
|
}
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"NewSD=[%ws]\r\n", wszNewStringSD);
|
||
|
Result = ConvertStringSecurityDescriptorToSecurityDescriptor(
|
||
|
wszNewStringSD,
|
||
|
SDDL_REVISION_1,
|
||
|
&pSD,
|
||
|
&cSDSize);
|
||
|
if (Result == TRUE) {
|
||
|
si = DACL_SECURITY_INFORMATION;
|
||
|
dwErr = DfsStampSD(
|
||
|
wszObjectName,
|
||
|
cSDSize,
|
||
|
si,
|
||
|
pSD,
|
||
|
pldap);
|
||
|
LocalFree(pSD);
|
||
|
} else {
|
||
|
dwErr = GetLastError();
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"Convert returned %d\r\n", dwErr);
|
||
|
}
|
||
|
free(wszNewStringSD);
|
||
|
} else {
|
||
|
dwErr = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsRemoveAce returning %d\r\n", dwErr);
|
||
|
return(dwErr);
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsSidInAce
|
||
|
//
|
||
|
// Synopsis: Scans an ACE to see if the string SID is in it.
|
||
|
//
|
||
|
// Arguments: [wszAce] -- ACE to scan
|
||
|
// [wszStringSid] -- SID to scan for
|
||
|
//
|
||
|
// Returns: TRUE -- SID is in this ACE
|
||
|
// FALSE -- SID is not in this ACE
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
BOOLEAN
|
||
|
DfsSidInAce(
|
||
|
LPWSTR wszAce,
|
||
|
LPWSTR wszStringSid)
|
||
|
{
|
||
|
ULONG i;
|
||
|
ULONG SidLen = wcslen(wszStringSid);
|
||
|
ULONG AceLen;
|
||
|
WCHAR Oldcp;
|
||
|
|
||
|
for (AceLen = 0; wszAce[AceLen] && wszAce[AceLen] != L')'; AceLen++)
|
||
|
/* NOTHING */;
|
||
|
|
||
|
Oldcp = wszAce[AceLen];
|
||
|
wszAce[AceLen] = L'\0';
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsSidInAce(%ws),%ws)\r\n", wszAce, wszStringSid);
|
||
|
wszAce[AceLen] = Oldcp;
|
||
|
|
||
|
if (SidLen > AceLen || wszAce[0] != L'(') {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsSidInAce returning FALSE(1)\r\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i <= (AceLen - SidLen); i++) {
|
||
|
|
||
|
if (wszAce[i] == wszStringSid[0] && wcsncmp(&wszAce[i],wszStringSid,SidLen) == 0) {
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsSidInAce returning TRUE\r\n");
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsSidInAce returning FALSE(2)\r\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: DfsStampSD
|
||
|
//
|
||
|
// Synopsis: Actually stamps the security descriptor on the object.
|
||
|
//
|
||
|
// Arguments: [pwszObject] -- The object to stamp the SD on
|
||
|
// [cSDSize] -- The size of the security descriptor
|
||
|
// [SeInfo] -- SecurityInformation about the security
|
||
|
// descriptor
|
||
|
// [pSD] -- The SD to stamp
|
||
|
// [pLDAP] -- The LDAP connection to use
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- Success
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
DfsStampSD(
|
||
|
PWSTR pwszObject,
|
||
|
ULONG cSDSize,
|
||
|
SECURITY_INFORMATION SeInfo,
|
||
|
PSECURITY_DESCRIPTOR pSD,
|
||
|
PLDAP pLDAP)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
PLDAPMod rgMods[2];
|
||
|
PLDAP_BERVAL pBVals[2];
|
||
|
LDAPMod Mod;
|
||
|
LDAP_BERVAL BVal;
|
||
|
BYTE ControlBuffer[ 5 ];
|
||
|
|
||
|
LDAPControl SeInfoControl =
|
||
|
{
|
||
|
LDAP_SERVER_SD_FLAGS_OID_W,
|
||
|
{
|
||
|
5, (PCHAR) &ControlBuffer
|
||
|
},
|
||
|
TRUE
|
||
|
};
|
||
|
|
||
|
PLDAPControl ServerControls[2] =
|
||
|
{
|
||
|
&SeInfoControl,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsStampSD(%ws,%d)\r\n", pwszObject, cSDSize);
|
||
|
|
||
|
ASSERT(*(PULONG)pSD > 0xF );
|
||
|
|
||
|
ControlBuffer[0] = 0x30;
|
||
|
ControlBuffer[1] = 0x3;
|
||
|
ControlBuffer[2] = 0x02; // Denotes an integer;
|
||
|
ControlBuffer[3] = 0x01; // Size
|
||
|
ControlBuffer[4] = (BYTE)((ULONG)SeInfo & 0xF);
|
||
|
|
||
|
ASSERT(IsValidSecurityDescriptor( pSD ) );
|
||
|
|
||
|
rgMods[0] = &Mod;
|
||
|
rgMods[1] = NULL;
|
||
|
|
||
|
pBVals[0] = &BVal;
|
||
|
pBVals[1] = NULL;
|
||
|
|
||
|
BVal.bv_len = cSDSize;
|
||
|
BVal.bv_val = (PCHAR)pSD;
|
||
|
|
||
|
Mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
|
||
|
Mod.mod_type = ACTRL_SD_PROP_NAME;
|
||
|
Mod.mod_values = (PWSTR *)pBVals;
|
||
|
|
||
|
//
|
||
|
// Now, we'll do the write...
|
||
|
//
|
||
|
dwErr = ldap_modify_ext_s(pLDAP,
|
||
|
pwszObject,
|
||
|
rgMods,
|
||
|
(PLDAPControl *)&ServerControls,
|
||
|
NULL);
|
||
|
|
||
|
dwErr = LdapMapErrorToWin32(dwErr);
|
||
|
|
||
|
if (fSwDebug != 0)
|
||
|
MyPrintf(L"DfsStampSD returning %d\r\n", dwErr);
|
||
|
|
||
|
return(dwErr);
|
||
|
}
|