mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
920 lines
23 KiB
920 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1998 - 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
refresh.c
|
|
|
|
Abstract:
|
|
|
|
This Module implements the delegation tool, which allows for the management
|
|
of access to DS objects
|
|
|
|
Author:
|
|
|
|
Mac McLain (MacM) 10-15-96
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "stdafx.h"
|
|
#include "utils.h"
|
|
#include "dsace.h"
|
|
#include "dsacls.h"
|
|
|
|
|
|
typedef struct _DEFAULT_SD_NODE {
|
|
|
|
PWSTR ObjectClass;
|
|
PSECURITY_DESCRIPTOR DefaultSd;
|
|
struct _DEFAULT_SD_NODE *Next;
|
|
|
|
} DEFAULT_SD_NODE, *PDEFAULT_SD_NODE;
|
|
|
|
typedef struct _DEFAULT_SD_INFO {
|
|
|
|
LDAP *Ldap;
|
|
PWSTR SchemaPath;
|
|
PSID DomainSid;
|
|
PDEFAULT_SD_NODE SdList;
|
|
} DEFAULT_SD_INFO, *PDEFAULT_SD_INFO;
|
|
|
|
#define DSACL_ALL_FILTER L"(ObjectClass=*)"
|
|
#define DSACL_SCHEMA_NC L"schemaNamingContext"
|
|
#define DSACL_OBJECT_CLASS L"objectClass"
|
|
#define DSACL_LDAP_DN L"(ldapDisplayName="
|
|
#define DSACL_LDAP_DN_CLOSE L")"
|
|
#define DSACL_DEFAULT_SD L"defaultSecurityDescriptor"
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
FindDefaultSdForClass(
|
|
IN PWSTR ClassId,
|
|
IN PDEFAULT_SD_INFO SdInfo,
|
|
IN OUT PDEFAULT_SD_NODE *DefaultSdNode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will search the SD_INFO list for an existing entry that matches the current
|
|
class type. If no such entry is found, one will be created from information from the schema
|
|
|
|
Arguments:
|
|
|
|
ClassId - ClassId to find the default SD node for
|
|
SdInfo - Current list of default SDs and associated information
|
|
DefaultSdNode - Where the locted node is returned
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS - Success
|
|
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32Err = ERROR_SUCCESS;
|
|
PWSTR Attributes[] = {
|
|
NULL,
|
|
NULL
|
|
};
|
|
LDAPMessage *Message = NULL, *Entry;
|
|
PWSTR Filter = NULL, SchemaObjectDn = NULL, DefaultSd = NULL, *DefaultSdList = NULL;
|
|
PDEFAULT_SD_NODE Node;
|
|
|
|
*DefaultSdNode = NULL;
|
|
|
|
Node = SdInfo->SdList;
|
|
|
|
while ( Node ) {
|
|
|
|
if ( !_wcsicmp( Node->ObjectClass, ClassId ) ) {
|
|
|
|
*DefaultSdNode = Node;
|
|
break;
|
|
}
|
|
|
|
Node = Node->Next;
|
|
}
|
|
|
|
//
|
|
// If it wasn't found, we'll have to go out and load it out of the Ds.
|
|
//
|
|
if ( !Node ) {
|
|
|
|
Filter = (LPWSTR)LocalAlloc( LMEM_FIXED,
|
|
sizeof( DSACL_LDAP_DN ) - sizeof( WCHAR ) +
|
|
( wcslen( ClassId ) * sizeof( WCHAR ) ) +
|
|
sizeof( DSACL_LDAP_DN_CLOSE ) );
|
|
if ( !Filter ) {
|
|
|
|
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto FindDefaultExit;
|
|
}
|
|
|
|
swprintf( Filter,
|
|
L"%ws%ws%ws",
|
|
DSACL_LDAP_DN,
|
|
ClassId,
|
|
DSACL_LDAP_DN_CLOSE );
|
|
|
|
//
|
|
// Now, do the search
|
|
//
|
|
Win32Err = LdapMapErrorToWin32( ldap_search_s( SdInfo->Ldap,
|
|
SdInfo->SchemaPath,
|
|
LDAP_SCOPE_SUBTREE,
|
|
Filter,
|
|
Attributes,
|
|
0,
|
|
&Message ) );
|
|
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
goto FindDefaultExit;
|
|
}
|
|
|
|
Entry = ldap_first_entry( SdInfo->Ldap, Message );
|
|
|
|
if ( Entry ) {
|
|
|
|
SchemaObjectDn = ldap_get_dn( SdInfo->Ldap, Entry );
|
|
ldap_msgfree( Message );
|
|
|
|
if ( !SchemaObjectDn ) {
|
|
|
|
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto FindDefaultExit;
|
|
|
|
}
|
|
} else {
|
|
|
|
Win32Err = LdapMapErrorToWin32( SdInfo->Ldap->ld_errno );
|
|
goto FindDefaultExit;
|
|
}
|
|
|
|
//
|
|
// Ok, now we can read the default security descriptor
|
|
//
|
|
Attributes[ 0 ] = DSACL_DEFAULT_SD;
|
|
Win32Err = LdapMapErrorToWin32( ldap_search_s( SdInfo->Ldap,
|
|
SchemaObjectDn,
|
|
LDAP_SCOPE_BASE,
|
|
DSACL_ALL_FILTER,
|
|
Attributes,
|
|
0,
|
|
&Message ) );
|
|
Entry = ldap_first_entry( SdInfo->Ldap, Message );
|
|
|
|
if ( Entry ) {
|
|
|
|
//
|
|
// Now, we'll have to get the values
|
|
//
|
|
DefaultSdList = ldap_get_values( SdInfo->Ldap, Entry, Attributes[ 0 ] );
|
|
|
|
if ( DefaultSdList ) {
|
|
|
|
DefaultSd = DefaultSdList[ 0 ];
|
|
|
|
} else {
|
|
|
|
Win32Err = LdapMapErrorToWin32( SdInfo->Ldap->ld_errno );
|
|
goto FindDefaultExit;
|
|
}
|
|
|
|
ldap_msgfree( Message );
|
|
}
|
|
|
|
|
|
//
|
|
// Find a new node and insert it
|
|
//
|
|
Node = (DEFAULT_SD_NODE*)LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
|
|
sizeof( DEFAULT_SD_NODE ) );
|
|
if ( !Node ) {
|
|
|
|
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto FindDefaultExit;
|
|
}
|
|
|
|
|
|
if ( !ConvertStringSDToSDRootDomain( SdInfo->DomainSid,
|
|
DefaultSd,
|
|
SDDL_REVISION,
|
|
&Node->DefaultSd,
|
|
NULL ) ) {
|
|
|
|
|
|
Win32Err = GetLastError();
|
|
}
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Node->ObjectClass =(LPWSTR) LocalAlloc( LMEM_FIXED,
|
|
( wcslen( ClassId ) + 1 ) * sizeof( WCHAR ) );
|
|
|
|
if ( Node->ObjectClass == NULL ) {
|
|
|
|
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
} else {
|
|
|
|
wcscpy( Node->ObjectClass, ClassId );
|
|
|
|
Node->Next = SdInfo->SdList;
|
|
SdInfo->SdList = Node;
|
|
}
|
|
}
|
|
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
LocalFree( Node->DefaultSd );
|
|
LocalFree( Node->ObjectClass );
|
|
LocalFree( Node );
|
|
|
|
} else {
|
|
|
|
*DefaultSdNode = Node;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
FindDefaultExit:
|
|
|
|
LocalFree( Filter );
|
|
|
|
if ( SchemaObjectDn ) {
|
|
|
|
ldap_memfree( SchemaObjectDn );
|
|
}
|
|
|
|
if ( DefaultSdList ) {
|
|
|
|
ldap_value_free( DefaultSdList );
|
|
}
|
|
return( Win32Err );
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
SetDefaultSdForObject(
|
|
IN LDAP *Ldap,
|
|
IN PWSTR ObjectPath,
|
|
IN PDEFAULT_SD_INFO SdInfo,
|
|
IN SECURITY_INFORMATION Protection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine set the default security descriptor on the indicated object
|
|
|
|
Arguments:
|
|
|
|
Ldap - Ldap connect to the server holding the object
|
|
ObjectPath - 1779 style path to the object
|
|
SdInfo - Current list of default SDs and associated information
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS - Success
|
|
ERROR_DS_NAME_TYPE_UNKNOWN - Unable to determine the class id of the object
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32Err = ERROR_SUCCESS;
|
|
PWSTR Attributes[] = {
|
|
DSACL_OBJECT_CLASS,
|
|
NULL
|
|
};
|
|
LDAPMessage *Message = NULL, *Entry;
|
|
PWSTR ClassId = NULL;
|
|
PWSTR *ClassList = NULL;
|
|
ULONG i;
|
|
PDEFAULT_SD_NODE DefaultSdNode = NULL;
|
|
PACTRL_ACCESS NewAccess = NULL;
|
|
PACTRL_AUDIT NewAudit = NULL;
|
|
|
|
//
|
|
// First, get the class id off of the object
|
|
//
|
|
Win32Err = LdapMapErrorToWin32( ldap_search_s( Ldap,
|
|
ObjectPath,
|
|
LDAP_SCOPE_BASE,
|
|
DSACL_ALL_FILTER,
|
|
Attributes,
|
|
0,
|
|
&Message ) );
|
|
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
goto SetDefaultExit;
|
|
}
|
|
|
|
Entry = ldap_first_entry( Ldap, Message );
|
|
|
|
if ( Entry ) {
|
|
|
|
//
|
|
// Now, we'll have to get the values
|
|
//
|
|
ClassList = ldap_get_values( Ldap, Entry, Attributes[ 0 ] );
|
|
|
|
if ( ClassList ) {
|
|
|
|
//
|
|
// Get the class id
|
|
//
|
|
i = 0;
|
|
while ( TRUE ) {
|
|
|
|
if ( ClassList[ i ] ) {
|
|
|
|
i++;
|
|
|
|
} else {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ASSERT( i > 0 );
|
|
if ( i == 0 ) {
|
|
|
|
Win32Err = ERROR_DS_NAME_TYPE_UNKNOWN;
|
|
goto SetDefaultExit;
|
|
}
|
|
ClassId = ClassList[ i - 1 ];
|
|
|
|
} else {
|
|
|
|
Win32Err = LdapMapErrorToWin32( Ldap->ld_errno );
|
|
goto SetDefaultExit;
|
|
}
|
|
|
|
ldap_msgfree( Message );
|
|
Message = NULL;
|
|
}
|
|
|
|
if ( !ClassId ) {
|
|
|
|
Win32Err = ERROR_DS_NAME_TYPE_UNKNOWN;
|
|
goto SetDefaultExit;
|
|
}
|
|
//
|
|
// Now, see if we have a cache entry for that...
|
|
//
|
|
Win32Err = FindDefaultSdForClass( ClassId,
|
|
SdInfo,
|
|
&DefaultSdNode );
|
|
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
goto SetDefaultExit;
|
|
}
|
|
|
|
|
|
//
|
|
// Ok, we have everything we need, so let's go ahead and set it all
|
|
//
|
|
/* Win32Err = ConvertSecurityDescriptorToAccessNamed( ObjectPath,
|
|
SE_DS_OBJECT_ALL,
|
|
DefaultSdNode->DefaultSd,
|
|
&NewAccess,
|
|
&NewAudit,
|
|
NULL,
|
|
NULL );
|
|
*/
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
|
|
Win32Err = WriteObjectSecurity(ObjectPath,
|
|
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION | Protection,
|
|
DefaultSdNode->DefaultSd
|
|
);
|
|
}
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
DisplayMessageEx( 0, MSG_DSACLS_PROCESSED, ObjectPath );
|
|
}
|
|
|
|
|
|
SetDefaultExit:
|
|
|
|
if ( ClassList ) {
|
|
|
|
ldap_value_free( ClassList );
|
|
}
|
|
|
|
if ( Message ) {
|
|
|
|
ldap_msgfree( Message );
|
|
}
|
|
|
|
LocalFree( NewAccess );
|
|
LocalFree( NewAudit );
|
|
|
|
return( Win32Err );
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
SetDefaultSdForObjectAndChildren(
|
|
IN LDAP *Ldap,
|
|
IN PWSTR ObjectPath,
|
|
IN PDEFAULT_SD_INFO SdInfo,
|
|
IN BOOLEAN Propagate,
|
|
IN SECURITY_INFORMATION Protection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will set the security descriptor on the object and potentially all of its
|
|
children to the default security as obtained from the schema
|
|
|
|
Arguments:
|
|
|
|
Ldap - Ldap connect to the server holding the object
|
|
ObjectPath - 1779 style path to the object
|
|
SdInfo - Current list of default SDs and associated information
|
|
Propagate - If TRUE, reset the security on the children as well
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS - Success
|
|
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32Err = ERROR_SUCCESS;
|
|
PWSTR Attributes[] = {
|
|
NULL
|
|
};
|
|
LDAPMessage *Message = NULL, *Entry;
|
|
PWSTR ChildName = NULL;
|
|
PLDAPSearch SearchHandle = NULL;
|
|
ULONG Count;
|
|
|
|
//
|
|
// First, get the class id off of the object
|
|
//
|
|
SearchHandle = ldap_search_init_pageW( Ldap,
|
|
ObjectPath,
|
|
Propagate ? LDAP_SCOPE_SUBTREE : LDAP_SCOPE_BASE,
|
|
DSACL_ALL_FILTER,
|
|
Attributes,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
2000,
|
|
NULL );
|
|
|
|
if ( SearchHandle == NULL ) {
|
|
|
|
Win32Err = LdapMapErrorToWin32( LdapGetLastError( ) );
|
|
|
|
} else {
|
|
|
|
while ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Count = 0;
|
|
|
|
//
|
|
// Get the next page
|
|
//
|
|
Win32Err = ldap_get_next_page_s( Ldap,
|
|
SearchHandle,
|
|
NULL,
|
|
100,
|
|
&Count,
|
|
&Message );
|
|
|
|
if ( Message ) {
|
|
|
|
Entry = ldap_first_entry( Ldap, Message );
|
|
|
|
while ( Entry ) {
|
|
|
|
ChildName = ldap_get_dn( SdInfo->Ldap, Entry );
|
|
|
|
if ( !ChildName ) {
|
|
|
|
Win32Err = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
Win32Err = SetDefaultSdForObject( Ldap,
|
|
ChildName,
|
|
SdInfo,
|
|
Protection);
|
|
|
|
ldap_memfree( ChildName );
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
break;
|
|
}
|
|
|
|
Entry = ldap_next_entry( Ldap, Entry );
|
|
}
|
|
|
|
Win32Err = Ldap->ld_errno;
|
|
ldap_msgfree( Message );
|
|
Message = NULL;
|
|
}
|
|
|
|
if ( Win32Err == LDAP_NO_RESULTS_RETURNED ) {
|
|
|
|
Win32Err = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
ldap_search_abandon_page( Ldap,
|
|
SearchHandle );
|
|
}
|
|
|
|
return( Win32Err );
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
BindToDsObject(
|
|
IN PWSTR ObjectPath,
|
|
OUT PLDAP *Ldap,
|
|
OUT PSID *DomainSid OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will bind to the ldap server on a domain controller that holds the specified
|
|
object path. Optionally, the sid of the domain hosted by that domain controller is returned
|
|
|
|
Arguments:
|
|
|
|
ObjectPath - 1779 style path to the object
|
|
Ldap - Where the ldap connection handle is returned
|
|
DomainSid - Sid of the domain hosted by the domain controller.
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS - Success
|
|
ERROR_PATH_NOT_FOUND - A domain controller for this path could not be located
|
|
ERROR_NOT_ENOUGH_MEMORY - A memory allocation failed
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32Err = ERROR_SUCCESS;
|
|
PWSTR ServerName = NULL;
|
|
PWSTR Separator = NULL;
|
|
PDOMAIN_CONTROLLER_INFO DcInfo = NULL;
|
|
PWSTR Path = NULL;
|
|
HANDLE DsHandle = NULL;
|
|
PDS_NAME_RESULT NameRes = NULL;
|
|
BOOLEAN NamedServer = FALSE;
|
|
UNICODE_STRING ServerNameU;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
LSA_HANDLE LsaHandle;
|
|
PPOLICY_PRIMARY_DOMAIN_INFO PolicyPDI = NULL;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Get a server name
|
|
//
|
|
/* if ( wcslen( ObjectPath ) > 2 && *ObjectPath == L'\\' && *( ObjectPath + 1 ) == L'\\' ) {
|
|
|
|
Separator = wcschr( ObjectPath + 2, L'\\' );
|
|
|
|
if ( Separator ) {
|
|
|
|
*Separator = L'\0';
|
|
Path = Separator + 1;
|
|
}
|
|
|
|
ServerName = ObjectPath + 2;
|
|
NamedServer = TRUE;
|
|
|
|
} else {
|
|
|
|
Path = ObjectPath;
|
|
|
|
Win32Err = DsGetDcName( NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DS_IP_REQUIRED |
|
|
DS_DIRECTORY_SERVICE_REQUIRED,
|
|
&DcInfo );
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
ServerName = DcInfo[ 0 ].DomainControllerName + 2;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Do the bind and crack
|
|
//
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Win32Err = DsBind( ServerName,
|
|
NULL,
|
|
&DsHandle );
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Win32Err = DsCrackNames( DsHandle,
|
|
DS_NAME_NO_FLAGS,
|
|
DS_FQDN_1779_NAME,
|
|
DS_FQDN_1779_NAME,
|
|
1,
|
|
&Path,
|
|
&NameRes );
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
if ( NameRes->cItems != 0 && !NamedServer &&
|
|
NameRes->rItems[ 0 ].status == DS_NAME_ERROR_DOMAIN_ONLY ) {
|
|
|
|
NetApiBufferFree( DcInfo );
|
|
DcInfo = NULL;
|
|
|
|
Win32Err = DsGetDcNameW( NULL,
|
|
NameRes->rItems[ 0 ].pDomain,
|
|
NULL,
|
|
NULL,
|
|
DS_IP_REQUIRED |
|
|
DS_DIRECTORY_SERVICE_REQUIRED,
|
|
&DcInfo );
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
DsUnBindW( &DsHandle );
|
|
DsHandle = NULL;
|
|
|
|
ServerName = DcInfo->DomainControllerName + 2;
|
|
|
|
//Win32Err = DsBind( DcInfo->DomainControllerAddress,
|
|
// NULL,
|
|
// &DsHandle );
|
|
//
|
|
|
|
Win32Err = DsBind( ServerName,
|
|
NULL,
|
|
&DsHandle );
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Win32Err = DsCrackNames( DsHandle,
|
|
DS_NAME_NO_FLAGS,
|
|
DS_FQDN_1779_NAME,
|
|
DS_FQDN_1779_NAME,
|
|
1,
|
|
&Path,
|
|
&NameRes);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
*/
|
|
//
|
|
// Now, do the bind
|
|
//
|
|
|
|
|
|
|
|
*Ldap = ldap_open( g_szServerName,
|
|
LDAP_PORT );
|
|
|
|
if ( *Ldap == NULL ) {
|
|
|
|
Win32Err = ERROR_PATH_NOT_FOUND;
|
|
|
|
} else {
|
|
|
|
Win32Err = LdapMapErrorToWin32( ldap_bind_s( *Ldap,
|
|
NULL,
|
|
NULL,
|
|
LDAP_AUTH_SSPI ) );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// If specified, get the sid for the domain
|
|
//
|
|
if ( DomainSid ) {
|
|
|
|
RtlInitUnicodeString( &ServerNameU, g_szServerName );
|
|
InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
|
|
|
|
//
|
|
// Get the sid of the domain
|
|
//
|
|
Status = LsaOpenPolicy( &ServerNameU,
|
|
&ObjectAttributes,
|
|
POLICY_VIEW_LOCAL_INFORMATION,
|
|
&LsaHandle );
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
Status = LsaQueryInformationPolicy( LsaHandle,
|
|
PolicyPrimaryDomainInformation,
|
|
( PVOID * )&PolicyPDI );
|
|
|
|
if ( NT_SUCCESS( Status ) ) {
|
|
|
|
*DomainSid = (PSID)LocalAlloc( LMEM_FIXED,
|
|
RtlLengthSid( PolicyPDI->Sid ) );
|
|
|
|
if ( *DomainSid == NULL ) {
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
} else {
|
|
|
|
RtlCopySid( RtlLengthSid( PolicyPDI->Sid ), *DomainSid, PolicyPDI->Sid );
|
|
}
|
|
|
|
LsaFreeMemory( PolicyPDI );
|
|
}
|
|
LsaClose( LsaHandle );
|
|
}
|
|
|
|
if ( !NT_SUCCESS( Status ) ) {
|
|
|
|
Win32Err = RtlNtStatusToDosError( Status );
|
|
ldap_unbind( *Ldap );
|
|
*Ldap = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return( Win32Err );
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
SetDefaultSecurityOnObjectTree(
|
|
IN PWSTR ObjectPath,
|
|
IN BOOLEAN Propagate,
|
|
IN SECURITY_INFORMATION Protection
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will set the security descriptor on the object and potentially all of its
|
|
children to the default security as obtained from the schema
|
|
|
|
Arguments:
|
|
|
|
ObjectPath - 1779 style path to the object
|
|
Propagate - If TRUE, reset the security on the children as well
|
|
|
|
Returns:
|
|
|
|
ERROR_SUCCESS - Success
|
|
|
|
--*/
|
|
{
|
|
DWORD Win32Err = ERROR_SUCCESS;
|
|
PWSTR Attributes[] = {
|
|
DSACL_SCHEMA_NC,
|
|
NULL
|
|
};
|
|
LDAPMessage *Message, *Entry;
|
|
PWSTR *PathList = NULL;
|
|
DEFAULT_SD_INFO SdInfo = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
PDEFAULT_SD_NODE CleanupNode;
|
|
|
|
//
|
|
// Bind to the ds object
|
|
//
|
|
Win32Err = BindToDsObject( ObjectPath,
|
|
&SdInfo.Ldap,
|
|
&SdInfo.DomainSid );
|
|
|
|
if ( Win32Err != ERROR_SUCCESS ) {
|
|
|
|
goto SetDefaultExit;
|
|
}
|
|
|
|
//
|
|
// Get the schema path
|
|
//
|
|
|
|
Win32Err = LdapMapErrorToWin32( ldap_search_s( SdInfo.Ldap,
|
|
NULL,
|
|
LDAP_SCOPE_BASE,
|
|
DSACL_ALL_FILTER,
|
|
Attributes,
|
|
0,
|
|
&Message ) );
|
|
|
|
if ( Win32Err == ERROR_SUCCESS ) {
|
|
|
|
Entry = ldap_first_entry( SdInfo.Ldap, Message );
|
|
|
|
if ( Entry ) {
|
|
|
|
//
|
|
// Now, we'll have to get the values
|
|
//
|
|
PathList = ldap_get_values( SdInfo.Ldap, Entry, Attributes[ 0 ] );
|
|
|
|
if ( PathList ) {
|
|
|
|
SdInfo.SchemaPath = PathList[ 0 ];
|
|
|
|
} else {
|
|
|
|
Win32Err = LdapMapErrorToWin32( SdInfo.Ldap->ld_errno );
|
|
}
|
|
|
|
ldap_msgfree( Message );
|
|
}
|
|
}
|
|
|
|
if( SdInfo.Ldap )
|
|
{
|
|
Win32Err = SetDefaultSdForObjectAndChildren( SdInfo.Ldap,
|
|
ObjectPath,
|
|
&SdInfo,
|
|
Propagate,
|
|
Protection);
|
|
}
|
|
|
|
SetDefaultExit:
|
|
|
|
//
|
|
// Unbind from the DS
|
|
//
|
|
if ( SdInfo.Ldap ) {
|
|
|
|
ldap_unbind( SdInfo.Ldap );
|
|
}
|
|
|
|
if ( PathList ) {
|
|
|
|
ldap_value_free( PathList );
|
|
}
|
|
|
|
//
|
|
// Clean up the Default SD Info list
|
|
//
|
|
LocalFree( SdInfo.DomainSid );
|
|
|
|
|
|
while ( SdInfo.SdList ) {
|
|
|
|
CleanupNode = SdInfo.SdList;
|
|
LocalFree( CleanupNode->ObjectClass );
|
|
LocalFree( CleanupNode->DefaultSd );
|
|
SdInfo.SdList = SdInfo.SdList->Next;
|
|
LocalFree( CleanupNode );
|
|
}
|
|
|
|
return( Win32Err );
|
|
}
|
|
|