968 lines
24 KiB
C++
968 lines
24 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows NT Security
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1998
|
||
|
//
|
||
|
// File: dsctx.cpp
|
||
|
//
|
||
|
// Contents: Implementation of CDsObjectContext and NT Marta DS object
|
||
|
// Functions
|
||
|
//
|
||
|
// History: 3-31-1999 kirtd Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
#include <aclpch.hxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <dsctx.h>
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::CDsObjectContext, public
|
||
|
//
|
||
|
// Synopsis: Constructor
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CDsObjectContext::CDsObjectContext ()
|
||
|
{
|
||
|
m_cRefs = 1;
|
||
|
memset( &m_LdapUrlComponents, 0, sizeof( m_LdapUrlComponents ) );
|
||
|
m_pBinding = NULL;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::~CDsObjectContext, public
|
||
|
//
|
||
|
// Synopsis: Destructor
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
CDsObjectContext::~CDsObjectContext ()
|
||
|
{
|
||
|
LdapFreeBindings( m_pBinding );
|
||
|
LdapFreeUrlComponents( &m_LdapUrlComponents );
|
||
|
|
||
|
assert( m_cRefs == 0 );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::InitializeByName, public
|
||
|
//
|
||
|
// Synopsis: initialize the context given the name of the lanman share
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::InitializeByName (LPCWSTR pObjectName, ACCESS_MASK AccessMask)
|
||
|
{
|
||
|
DWORD Result = ERROR_SUCCESS;
|
||
|
LPWSTR pwszName = NULL;
|
||
|
ULONG len = wcslen( pObjectName );
|
||
|
ULONG i, j;
|
||
|
|
||
|
if ( _wcsnicmp( pObjectName, LDAP_SCHEME_U, wcslen( LDAP_SCHEME_U ) ) != 0 )
|
||
|
{
|
||
|
pwszName = new WCHAR [ len + wcslen( LDAP_SCHEME_UC ) + 2 ];
|
||
|
|
||
|
if ( pwszName != NULL )
|
||
|
{
|
||
|
wcscpy( pwszName, LDAP_SCHEME_UC );
|
||
|
wcscat( pwszName, L"/" );
|
||
|
wcscat( pwszName, pObjectName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pwszName = new WCHAR [ len + 1 ];
|
||
|
|
||
|
if ( pwszName != NULL )
|
||
|
{
|
||
|
wcscpy( pwszName, pObjectName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
for (i = j = 0; i <= len; i++, j++)
|
||
|
{
|
||
|
if (L'\\' == pwszName[i])
|
||
|
{
|
||
|
if (L'/' != pwszName[i+1])
|
||
|
{
|
||
|
pwszName[j++] = pwszName[i++];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
pwszName[j] = pwszName[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
if ( LdapCrackUrl( pwszName, &m_LdapUrlComponents ) == FALSE )
|
||
|
{
|
||
|
Result = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
if ( LdapGetBindings(
|
||
|
m_LdapUrlComponents.pwszHost,
|
||
|
m_LdapUrlComponents.Port,
|
||
|
0,
|
||
|
0,
|
||
|
&m_pBinding
|
||
|
) == FALSE )
|
||
|
{
|
||
|
Result = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pwszName != pObjectName )
|
||
|
{
|
||
|
delete pwszName;
|
||
|
}
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::AddRef, public
|
||
|
//
|
||
|
// Synopsis: add a reference to the context
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::AddRef ()
|
||
|
{
|
||
|
m_cRefs += 1;
|
||
|
return( m_cRefs );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::Release, public
|
||
|
//
|
||
|
// Synopsis: release a reference to the context
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::Release ()
|
||
|
{
|
||
|
m_cRefs -= 1;
|
||
|
|
||
|
if ( m_cRefs == 0 )
|
||
|
{
|
||
|
delete this;
|
||
|
return( 0 );
|
||
|
}
|
||
|
|
||
|
return( m_cRefs );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::GetDsObjectProperties, public
|
||
|
//
|
||
|
// Synopsis: get properties about the context
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::GetDsObjectProperties (
|
||
|
PMARTA_OBJECT_PROPERTIES pObjectProperties
|
||
|
)
|
||
|
{
|
||
|
if ( pObjectProperties->cbSize < sizeof( MARTA_OBJECT_PROPERTIES ) )
|
||
|
{
|
||
|
return( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
assert( pObjectProperties->dwFlags == 0 );
|
||
|
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::GetDsObjectRights, public
|
||
|
//
|
||
|
// Synopsis: get the DsObject security descriptor
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::GetDsObjectRights (
|
||
|
SECURITY_INFORMATION SecurityInfo,
|
||
|
PSECURITY_DESCRIPTOR* ppSecurityDescriptor
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
|
||
|
Result = MartaReadDSObjSecDesc(
|
||
|
m_pBinding,
|
||
|
m_LdapUrlComponents.pwszDN,
|
||
|
SecurityInfo,
|
||
|
ppSecurityDescriptor
|
||
|
);
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::SetDsObjectRights, public
|
||
|
//
|
||
|
// Synopsis: set the window security descriptor
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::SetDsObjectRights (
|
||
|
SECURITY_INFORMATION SecurityInfo,
|
||
|
PSECURITY_DESCRIPTOR pSecurityDescriptor
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
PISECURITY_DESCRIPTOR pisd = NULL;
|
||
|
DWORD cb = 0;
|
||
|
PSECURITY_DESCRIPTOR psd = NULL;
|
||
|
|
||
|
pisd = (PISECURITY_DESCRIPTOR)pSecurityDescriptor;
|
||
|
|
||
|
if ( pisd->Control & SE_SELF_RELATIVE )
|
||
|
{
|
||
|
cb = GetSecurityDescriptorLength( pSecurityDescriptor );
|
||
|
psd = pSecurityDescriptor;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( MakeSelfRelativeSD(
|
||
|
pSecurityDescriptor,
|
||
|
NULL,
|
||
|
&cb
|
||
|
) == FALSE )
|
||
|
{
|
||
|
if ( cb > 0 )
|
||
|
{
|
||
|
psd = new BYTE [ cb ];
|
||
|
if ( psd != NULL )
|
||
|
{
|
||
|
if ( MakeSelfRelativeSD(
|
||
|
pSecurityDescriptor,
|
||
|
psd,
|
||
|
&cb
|
||
|
) == FALSE )
|
||
|
{
|
||
|
delete psd;
|
||
|
return( GetLastError() );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return( ERROR_OUTOFMEMORY );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return( GetLastError() );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
assert( FALSE && "Should not get here!" );
|
||
|
return( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
assert( psd != NULL );
|
||
|
|
||
|
Result = MartaStampSD(
|
||
|
m_LdapUrlComponents.pwszDN,
|
||
|
cb,
|
||
|
SecurityInfo,
|
||
|
psd,
|
||
|
m_pBinding
|
||
|
);
|
||
|
|
||
|
if ( psd != pSecurityDescriptor )
|
||
|
{
|
||
|
delete psd;
|
||
|
}
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsObjectContext::GetDsObjectGuid, public
|
||
|
//
|
||
|
// Synopsis: get the object GUID
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
CDsObjectContext::GetDsObjectGuid (GUID* pGuid)
|
||
|
{
|
||
|
return( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Functions from Ds.h which dispatch unto the CDsObjectContext class
|
||
|
//
|
||
|
|
||
|
DWORD
|
||
|
MartaAddRefDsObjectContext(
|
||
|
IN MARTA_CONTEXT Context
|
||
|
)
|
||
|
{
|
||
|
return( ( (CDsObjectContext *)Context )->AddRef() );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaCloseDsObjectContext(
|
||
|
IN MARTA_CONTEXT Context
|
||
|
)
|
||
|
{
|
||
|
return( ( (CDsObjectContext *)Context )->Release() );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaGetDsObjectProperties(
|
||
|
IN MARTA_CONTEXT Context,
|
||
|
IN OUT PMARTA_OBJECT_PROPERTIES pProperties
|
||
|
)
|
||
|
{
|
||
|
return( ( (CDsObjectContext *)Context )->GetDsObjectProperties( pProperties ) );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaGetDsObjectTypeProperties(
|
||
|
IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
|
||
|
)
|
||
|
{
|
||
|
if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
|
||
|
{
|
||
|
return( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
assert( pProperties->dwFlags == 0 );
|
||
|
|
||
|
pProperties->dwFlags = MARTA_OBJECT_TYPE_INHERITANCE_MODEL_PRESENT_FLAG;
|
||
|
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaGetDsObjectRights(
|
||
|
IN MARTA_CONTEXT Context,
|
||
|
IN SECURITY_INFORMATION SecurityInfo,
|
||
|
OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
|
||
|
)
|
||
|
{
|
||
|
return( ( (CDsObjectContext *)Context )->GetDsObjectRights(
|
||
|
SecurityInfo,
|
||
|
ppSecurityDescriptor
|
||
|
) );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaOpenDsObjectNamedObject(
|
||
|
IN LPCWSTR pObjectName,
|
||
|
IN ACCESS_MASK AccessMask,
|
||
|
OUT PMARTA_CONTEXT pContext
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
CDsObjectContext* pDsObjectContext;
|
||
|
|
||
|
pDsObjectContext = new CDsObjectContext;
|
||
|
if ( pDsObjectContext == NULL )
|
||
|
{
|
||
|
return( ERROR_OUTOFMEMORY );
|
||
|
}
|
||
|
|
||
|
Result = pDsObjectContext->InitializeByName( pObjectName, AccessMask );
|
||
|
if ( Result != ERROR_SUCCESS )
|
||
|
{
|
||
|
pDsObjectContext->Release();
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
*pContext = pDsObjectContext;
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaSetDsObjectRights(
|
||
|
IN MARTA_CONTEXT Context,
|
||
|
IN SECURITY_INFORMATION SecurityInfo,
|
||
|
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
|
||
|
)
|
||
|
{
|
||
|
return( ( (CDsObjectContext *)Context )->SetDsObjectRights(
|
||
|
SecurityInfo,
|
||
|
pSecurityDescriptor
|
||
|
) );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaConvertDsObjectNameToGuid(
|
||
|
IN LPCWSTR pObjectName,
|
||
|
OUT GUID* pGuid
|
||
|
)
|
||
|
{
|
||
|
DWORD Result = ERROR_SUCCESS;
|
||
|
LPWSTR pwszName = NULL;
|
||
|
LDAP_URL_COMPONENTS LdapUrlComponents;
|
||
|
DS_NAME_RESULTW* pnameresult;
|
||
|
HANDLE hDs = NULL;
|
||
|
WCHAR GuidString[ MAX_PATH ];
|
||
|
|
||
|
memset( &LdapUrlComponents, 0, sizeof( LdapUrlComponents ) );
|
||
|
|
||
|
if ( _wcsnicmp( pObjectName, LDAP_SCHEME_U, wcslen( LDAP_SCHEME_U ) ) != 0 )
|
||
|
{
|
||
|
pwszName = new WCHAR [ wcslen( pObjectName ) +
|
||
|
wcslen( LDAP_SCHEME_U ) + 2 ];
|
||
|
|
||
|
if ( pwszName != NULL )
|
||
|
{
|
||
|
wcscpy( pwszName, LDAP_SCHEME_U );
|
||
|
wcscat( pwszName, L"/" );
|
||
|
wcscat( pwszName, pObjectName );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pwszName = (LPWSTR)pObjectName;
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
if ( LdapCrackUrl( pwszName, &LdapUrlComponents ) == FALSE )
|
||
|
{
|
||
|
Result = GetLastError();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
Result = DsBindW( LdapUrlComponents.pwszHost, NULL, &hDs );
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
Result = DsCrackNamesW(
|
||
|
hDs,
|
||
|
DS_NAME_NO_FLAGS,
|
||
|
DS_FQDN_1779_NAME,
|
||
|
DS_UNIQUE_ID_NAME,
|
||
|
1,
|
||
|
&LdapUrlComponents.pwszDN,
|
||
|
&pnameresult
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
if ( ( pnameresult->cItems > 0 ) &&
|
||
|
( pnameresult->rItems[0].status == ERROR_SUCCESS ) )
|
||
|
{
|
||
|
Result = IIDFromString( pnameresult->rItems[0].pName, pGuid );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
DsFreeNameResultW( pnameresult );
|
||
|
}
|
||
|
|
||
|
if ( hDs != NULL )
|
||
|
{
|
||
|
DsUnBindW( &hDs );
|
||
|
}
|
||
|
|
||
|
LdapFreeUrlComponents( &LdapUrlComponents );
|
||
|
|
||
|
if ( pwszName != pObjectName )
|
||
|
{
|
||
|
delete pwszName;
|
||
|
}
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaConvertGuidToDsName(
|
||
|
IN GUID Guid,
|
||
|
OUT LPWSTR * ppObjectName
|
||
|
)
|
||
|
{
|
||
|
DWORD Result;
|
||
|
HANDLE hDs = NULL;
|
||
|
WCHAR GuidString[ MAX_PATH ];
|
||
|
DS_NAME_RESULTW* pnameresult = NULL;
|
||
|
LPWSTR pObjectName = NULL;
|
||
|
|
||
|
if ( StringFromGUID2( Guid, GuidString, MAX_PATH ) == 0 )
|
||
|
{
|
||
|
return( ERROR_INVALID_PARAMETER );
|
||
|
}
|
||
|
|
||
|
Result = DsBindW( NULL, NULL, &hDs );
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
Result = DsCrackNamesW(
|
||
|
hDs,
|
||
|
DS_NAME_NO_FLAGS,
|
||
|
DS_UNIQUE_ID_NAME,
|
||
|
DS_FQDN_1779_NAME,
|
||
|
1,
|
||
|
(LPCWSTR *)&GuidString,
|
||
|
&pnameresult
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ( Result == ERROR_SUCCESS )
|
||
|
{
|
||
|
if ( ( pnameresult->cItems > 0 ) &&
|
||
|
( pnameresult->rItems[0].status == ERROR_SUCCESS ) )
|
||
|
{
|
||
|
pObjectName = (LPWSTR)LocalAlloc(
|
||
|
LPTR,
|
||
|
( wcslen( pnameresult->rItems[0].pName )
|
||
|
+ 1 ) * sizeof( WCHAR )
|
||
|
);
|
||
|
|
||
|
if ( pObjectName != NULL )
|
||
|
{
|
||
|
wcscpy( pObjectName, pnameresult->rItems[0].pName );
|
||
|
*ppObjectName = pObjectName;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_OUTOFMEMORY;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
DsFreeNameResultW( pnameresult );
|
||
|
}
|
||
|
|
||
|
if ( hDs != NULL )
|
||
|
{
|
||
|
DsUnBindW( &hDs );
|
||
|
}
|
||
|
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MartaReadDSObjSecDesc
|
||
|
//
|
||
|
// Synopsis: Reads the security descriptor from the specied object via
|
||
|
// the open ldap connection
|
||
|
//
|
||
|
// Arguments: [IN pLDAP] -- The open LDAP connection
|
||
|
// [IN SeInfo] -- Parts of the security descriptor to
|
||
|
// read.
|
||
|
// [IN pwszDSObj] -- The DSObject to get the security
|
||
|
// descriptor for
|
||
|
// [OUT ppSD] -- Where the security descriptor is
|
||
|
// returned
|
||
|
//
|
||
|
// 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
|
||
|
MartaReadDSObjSecDesc(IN PLDAP pLDAP,
|
||
|
IN LPWSTR pwszObject,
|
||
|
IN SECURITY_INFORMATION SeInfo,
|
||
|
OUT PSECURITY_DESCRIPTOR *ppSD)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
PLDAPMessage pMessage = NULL;
|
||
|
LPWSTR rgAttribs[2];
|
||
|
BYTE berValue[8];
|
||
|
|
||
|
//
|
||
|
// JohnsonA The BER encoding is current hardcoded. Change this to use
|
||
|
// AndyHe's BER_printf package once it's done.
|
||
|
//
|
||
|
|
||
|
berValue[0] = 0x30;
|
||
|
berValue[1] = 0x03;
|
||
|
berValue[2] = 0x02;
|
||
|
berValue[3] = 0x01;
|
||
|
berValue[4] = (BYTE)((ULONG)SeInfo & 0xF);
|
||
|
|
||
|
LDAPControlW SeInfoControl =
|
||
|
{
|
||
|
LDAP_SERVER_SD_FLAGS_OID_W,
|
||
|
{
|
||
|
5, (PCHAR)berValue
|
||
|
},
|
||
|
TRUE
|
||
|
};
|
||
|
|
||
|
PLDAPControlW ServerControls[2] =
|
||
|
{
|
||
|
&SeInfoControl,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
rgAttribs[0] = SD_PROP_NAME;
|
||
|
rgAttribs[1] = NULL;
|
||
|
|
||
|
|
||
|
|
||
|
if(dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
dwErr = ldap_search_ext_sW(pLDAP,
|
||
|
pwszObject,
|
||
|
LDAP_SCOPE_BASE,
|
||
|
L"(objectClass=*)",
|
||
|
rgAttribs,
|
||
|
0,
|
||
|
(PLDAPControlW *)&ServerControls,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
10000,
|
||
|
&pMessage);
|
||
|
|
||
|
dwErr = LdapMapErrorToWin32( dwErr );
|
||
|
}
|
||
|
|
||
|
if(dwErr == ERROR_SUCCESS)
|
||
|
{
|
||
|
LDAPMessage *pEntry = NULL;
|
||
|
|
||
|
pEntry = ldap_first_entry(pLDAP,pMessage);
|
||
|
|
||
|
if(pEntry == NULL)
|
||
|
{
|
||
|
dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
|
||
|
if (ERROR_SUCCESS == dwErr)
|
||
|
dwErr = ERROR_ACCESS_DENIED;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PLDAP_BERVAL *pSize = ldap_get_values_lenW(pLDAP,
|
||
|
pMessage,
|
||
|
rgAttribs[0]);
|
||
|
if(pSize == NULL)
|
||
|
{
|
||
|
dwErr = LdapMapErrorToWin32( pLDAP->ld_errno );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Allocate the security descriptor to return
|
||
|
//
|
||
|
*ppSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, (*pSize)->bv_len);
|
||
|
if(*ppSD == NULL)
|
||
|
{
|
||
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(*ppSD, (PBYTE)(*pSize)->bv_val, (*pSize)->bv_len);
|
||
|
}
|
||
|
ldap_value_free_len(pSize);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pMessage != NULL )
|
||
|
{
|
||
|
ldap_msgfree(pMessage);
|
||
|
}
|
||
|
|
||
|
return(dwErr);
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MartaStampSD
|
||
|
//
|
||
|
// Synopsis: Actually stamps the security descriptor on the object.
|
||
|
//
|
||
|
// Arguments: [IN pwszObject] -- The object to stamp the SD on
|
||
|
// [IN cSDSize] -- The size of the security descriptor
|
||
|
// [IN SeInfo] -- SecurityInformation about the security
|
||
|
// descriptor
|
||
|
// [IN pSD] -- The SD to stamp
|
||
|
// [IN pLDAP] -- The LDAP connection to use
|
||
|
//
|
||
|
// Returns: ERROR_SUCCESS -- Success
|
||
|
// ERROR_NOT_ENOUGH_MEMORY -- A memory allocation failed
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
DWORD
|
||
|
MartaStampSD(IN LPWSTR pwszObject,
|
||
|
IN ULONG cSDSize,
|
||
|
IN SECURITY_INFORMATION SeInfo,
|
||
|
IN PSECURITY_DESCRIPTOR pSD,
|
||
|
IN PLDAP pLDAP)
|
||
|
{
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
|
||
|
//
|
||
|
// Now, we'll do the write. The security descriptor
|
||
|
// we got passed in better not be in the old Ds format,
|
||
|
// where the leading 4 bytes are the SECURITY_INFORMATION, which we'll skip
|
||
|
// and replace with control information
|
||
|
//
|
||
|
|
||
|
assert(*(PULONG)pSD > 0xF );
|
||
|
|
||
|
PLDAPModW rgMods[2];
|
||
|
PLDAP_BERVAL pBVals[2];
|
||
|
LDAPModW Mod;
|
||
|
LDAP_BERVAL BVal;
|
||
|
BYTE ControlBuffer[ 5 ];
|
||
|
|
||
|
LDAPControlW SeInfoControl =
|
||
|
{
|
||
|
LDAP_SERVER_SD_FLAGS_OID_W,
|
||
|
{
|
||
|
5, (PCHAR) &ControlBuffer
|
||
|
},
|
||
|
TRUE
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// !!! Hardcoded for now. Use Andyhe's BER_printf once it's done.
|
||
|
//
|
||
|
|
||
|
ControlBuffer[0] = 0x30;
|
||
|
ControlBuffer[1] = 0x3;
|
||
|
ControlBuffer[2] = 0x02; // Denotes an integer;
|
||
|
ControlBuffer[3] = 0x01; // Size
|
||
|
ControlBuffer[4] = (BYTE)((ULONG)SeInfo & 0xF);
|
||
|
|
||
|
PLDAPControlW ServerControls[2] =
|
||
|
{
|
||
|
&SeInfoControl,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
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 = SD_PROP_NAME;
|
||
|
Mod.mod_values = (LPWSTR *)pBVals;
|
||
|
|
||
|
//
|
||
|
// Now, we'll do the write...
|
||
|
//
|
||
|
|
||
|
dwErr = ldap_modify_ext_sW(pLDAP,
|
||
|
pwszObject,
|
||
|
rgMods,
|
||
|
(PLDAPControlW *)&ServerControls,
|
||
|
NULL);
|
||
|
|
||
|
dwErr = LdapMapErrorToWin32(dwErr);
|
||
|
|
||
|
return(dwErr);
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MartaGetDsParentName(
|
||
|
IN LPWSTR ObjectName,
|
||
|
OUT LPWSTR *pParentName
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given the name of a DS object return the name of its parent. The routine
|
||
|
allocates memory required to hold the parent name.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ObjectName - Name of the DS object.
|
||
|
|
||
|
pParentName - To return the pointer to the allocated parent name.
|
||
|
In case of the root of the tree, we return NULL parent with ERROR_SUCCESS.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
ERROR_SUCCESS in case of success.
|
||
|
ERROR_* otherwise
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
LPCWSTR pKey = NULL;
|
||
|
LPCWSTR pVal = NULL;
|
||
|
DWORD ccKey = 0;
|
||
|
DWORD ccDN = 0;
|
||
|
DWORD ccVal = 0;
|
||
|
DWORD Size = 0;
|
||
|
DWORD dwErr = ERROR_SUCCESS;
|
||
|
LPCWSTR pDN = (LPWSTR) ObjectName;
|
||
|
|
||
|
ccDN = wcslen(pDN);
|
||
|
*pParentName = NULL;
|
||
|
|
||
|
//
|
||
|
// The input is empty. There is no parent. Just return.
|
||
|
//
|
||
|
|
||
|
if (0 == ccDN)
|
||
|
{
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Do the first pass to get to the next level. At the end of this call,
|
||
|
// pDN will point to the next ','. One more call to DsGetRdnW will
|
||
|
// return the right result in pKey.
|
||
|
// Input:
|
||
|
// pDN = "CN=Kedar, DC=NTDEV, DC=Microsoft, DC=com"
|
||
|
// Output:
|
||
|
// pDN = ", DC=NTDEV, DC=Microsoft, DC=com"
|
||
|
//
|
||
|
|
||
|
dwErr = DsGetRdnW(
|
||
|
&pDN,
|
||
|
&ccDN,
|
||
|
&pKey,
|
||
|
&ccKey,
|
||
|
&pVal,
|
||
|
&ccVal
|
||
|
);
|
||
|
|
||
|
if (ERROR_SUCCESS != dwErr)
|
||
|
{
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This is TRUE when the Object does not have any parent.
|
||
|
//
|
||
|
|
||
|
if (0 == ccDN)
|
||
|
{
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Input:
|
||
|
// pDN = ", DC=NTDEV, DC=Microsoft, DC=com"
|
||
|
// Output:
|
||
|
// pKey = "DC=NTDEV, DC=Microsoft, DC=com"
|
||
|
//
|
||
|
|
||
|
dwErr = DsGetRdnW(
|
||
|
&pDN,
|
||
|
&ccDN,
|
||
|
&pKey,
|
||
|
&ccKey,
|
||
|
&pVal,
|
||
|
&ccVal
|
||
|
);
|
||
|
|
||
|
if (ERROR_SUCCESS != dwErr)
|
||
|
{
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We have to distinguish between LDAP://ServerName/ObjectName and
|
||
|
// ObjectName.
|
||
|
//
|
||
|
|
||
|
if (!_wcsnicmp(ObjectName, LDAP_SCHEME_U, wcslen(LDAP_SCHEME_U)) != 0 )
|
||
|
{
|
||
|
ULONG HostSize;
|
||
|
|
||
|
//
|
||
|
// Compute the size of string required to hold "LDAP//ServerName/" in
|
||
|
// HostSize.
|
||
|
//
|
||
|
|
||
|
pDN = ObjectName + sizeof("ldap://");
|
||
|
pDN = wcschr(pDN, L'/');
|
||
|
|
||
|
if (NULL == pDN)
|
||
|
{
|
||
|
return ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
HostSize = (ULONG) (pDN - ObjectName + 1);
|
||
|
|
||
|
Size = (1 + wcslen(pKey) + HostSize) * sizeof(WCHAR);
|
||
|
|
||
|
*pParentName = (LPWSTR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Size);
|
||
|
|
||
|
if (NULL == *pParentName)
|
||
|
{
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the name of the parent into allocated memeory.
|
||
|
//
|
||
|
|
||
|
wcsncpy(*pParentName, ObjectName, HostSize);
|
||
|
wcscpy((*pParentName) + HostSize, pKey);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Size = (1 + wcslen(pKey)) * sizeof(WCHAR);
|
||
|
|
||
|
*pParentName = (LPWSTR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, Size);
|
||
|
|
||
|
if (NULL == *pParentName)
|
||
|
{
|
||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the name of the parent into allocated memeory.
|
||
|
//
|
||
|
|
||
|
wcscpy(*pParentName, pKey);
|
||
|
}
|
||
|
|
||
|
|
||
|
return ERROR_SUCCESS;
|
||
|
}
|