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.
344 lines
12 KiB
344 lines
12 KiB
#include "stdafx.h"
|
|
|
|
#include "exchange.hpp"
|
|
|
|
#include "common.hpp"
|
|
#include "err.hpp"
|
|
#include "ErrDct.hpp"
|
|
#include "UString.hpp"
|
|
|
|
#include "sidcache.hpp"
|
|
#include "sd.hpp"
|
|
#include "SecObj.hpp"
|
|
#include "exldap.h"
|
|
|
|
#include "Mcs.h"
|
|
#include "folders.h"
|
|
#include "treg.hpp"
|
|
|
|
using namespace nsFolders;
|
|
|
|
extern TErrorDct err;
|
|
|
|
#define NOT_PT_ERROR(x) ( PROP_TYPE(x.ulPropTag) != PT_ERROR )
|
|
|
|
#define LDAP_PortNumber_DN_Part L"/cn=Protocols/cn=LDAP"
|
|
#define ATT_OBJ_CLASS L"Obj-Class"
|
|
#define ATT_DIST_NAME L"Obj-Dist-Name"
|
|
#define ATT_LDAP_PORT L"Port-Number"
|
|
#define LDAP_USE_SITE_VALUES L"Use-Site-Values"
|
|
|
|
|
|
TGlobalDirectory::TGlobalDirectory()
|
|
{
|
|
m_stat = NULL;
|
|
}
|
|
|
|
TGlobalDirectory::~TGlobalDirectory()
|
|
{
|
|
}
|
|
|
|
#define NDX_SID 3
|
|
#define NDX_SD 4
|
|
|
|
void
|
|
TGlobalDirectory::GetSiteNameForServer(
|
|
WCHAR const * server, // in - name of exchange server to use
|
|
CLdapEnum * e, // in - LDAP connection to use for query
|
|
WCHAR * siteName // out- distinguished name of exchange site for server
|
|
)
|
|
{
|
|
WCHAR * atts[6] = { L"distinguishedName", L"rdn",NULL };
|
|
WCHAR query[200];
|
|
DWORD rc;
|
|
WCHAR ** values = NULL;
|
|
siteName[0] = 0;
|
|
|
|
swprintf(query,L"(&(objectClass=computer)(rdn=%ls))",server);
|
|
rc = e->Open(query,L"",2,100,3,atts);
|
|
// there should be only one server with this name
|
|
if (! rc )
|
|
rc = e->Next(&values);
|
|
if (! rc )
|
|
{
|
|
if ( !UStrICmp(values[1],server) )
|
|
{
|
|
WCHAR serverPrefix[LEN_Path];
|
|
_snwprintf(serverPrefix,DIM(serverPrefix),L"cn=%ls,cn=Servers,cn=Configuration,",values[1]);
|
|
serverPrefix[DIM(serverPrefix) - 1] = L'\0';
|
|
if ( ! UStrICmp(values[0],serverPrefix,UStrLen(serverPrefix)) )
|
|
{
|
|
UStrCpy(siteName,values[0] + UStrLen(serverPrefix),LEN_Path);
|
|
}
|
|
else
|
|
{
|
|
err.MsgWrite(ErrE,DCT_MSG_GENERIC_S,values[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err.MsgWrite(ErrE,DCT_MSG_LDAP_CALL_FAILED_SD,server,ERROR_NOT_FOUND);
|
|
}
|
|
e->FreeData(values);
|
|
}
|
|
else
|
|
{
|
|
err.SysMsgWrite(ErrE,e->m_connection.LdapMapErrorToWin32(rc),DCT_MSG_LDAP_CALL_FAILED_SD,server,rc);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
TGlobalDirectory::DoLdapTranslation(
|
|
WCHAR * server,
|
|
WCHAR * domain,
|
|
WCHAR * user,
|
|
WCHAR * password,
|
|
SecurityTranslatorArgs * args,
|
|
WCHAR * basept,
|
|
WCHAR * query
|
|
)
|
|
{
|
|
CLdapEnum e;
|
|
WCHAR * atts[6] = { L"distinguishedName", L"rdn", L"cn", L"Assoc-NT-Account",L"NT-Security-Descriptor",NULL };
|
|
WCHAR ** values = NULL;
|
|
DWORD ldapPort, sslPort;
|
|
GetLDAPPort(&ldapPort, &sslPort);
|
|
ULONG pageSize = 100;
|
|
WCHAR basepoint[LEN_Path] = L"";
|
|
|
|
e.m_connection.SetCredentials(domain,user,password);
|
|
|
|
BOOL sslEnabled = FALSE;
|
|
SetLastError(0);
|
|
// try SSL port first
|
|
DWORD rc = e.InitSSLConnection(server,&sslEnabled,sslPort);
|
|
|
|
if (rc || sslEnabled == FALSE)
|
|
{
|
|
WCHAR* serverName = (server == NULL) ? L"" : server;
|
|
if (rc == 0)
|
|
err.MsgWrite(ErrW, DCT_MSG_CANNOT_ESTABLISH_SSL_CONNECTION_WITH_EXCHANGE_SERVER_WITHOUT_RC_SD, serverName, sslPort);
|
|
else
|
|
err.SysMsgWrite(ErrW, rc, DCT_MSG_CANNOT_ESTABLISH_SSL_CONNECTION_WITH_EXCHANGE_SERVER_WITH_RC_SDD, serverName, sslPort,rc);
|
|
err.MsgWrite(ErrI, DCT_MSG_USE_REGULAR_PORT_DS, ldapPort, serverName);
|
|
rc = e.InitConnection(server, ldapPort);
|
|
}
|
|
|
|
BOOL anychange = FALSE;
|
|
BOOL verbose = args->LogVerbose();
|
|
BOOL bUseMapFile = args->UsingMapFile();
|
|
|
|
|
|
if (! rc )
|
|
{
|
|
if ( ! basept )
|
|
{
|
|
GetSiteNameForServer(server,&e,basepoint);
|
|
}
|
|
else
|
|
{
|
|
// use the user-specified basepoint
|
|
safecopy(basepoint,basept);
|
|
}
|
|
if ( query )
|
|
{
|
|
rc = e.Open(query,basepoint,2,pageSize,5,atts);
|
|
}
|
|
else
|
|
{
|
|
rc = e.Open(L"(objectClass=*)",basepoint,2,pageSize,5,atts);
|
|
}
|
|
if ( ! rc )
|
|
{
|
|
do
|
|
{
|
|
rc = e.Next(&values);
|
|
anychange = FALSE;
|
|
if (! rc )
|
|
{
|
|
if ( args->Cache()->IsCancelled() )
|
|
{
|
|
err.MsgWrite(0,DCT_MSG_OPERATION_ABORTED);
|
|
return FALSE;
|
|
}
|
|
if ( m_stat )
|
|
{
|
|
m_stat->DisplayPath(values[0]);
|
|
m_stat->IncrementExamined(mailbox);
|
|
}
|
|
|
|
// update the Assoc-NT-Account, if any
|
|
if ( values[NDX_SID] && *values[NDX_SID] )
|
|
{
|
|
// convert the SID to a binary value and look it up in the cache
|
|
BYTE pSid[500];
|
|
|
|
if ( e.m_connection.StringToBytes(values[NDX_SID],pSid) )
|
|
{
|
|
|
|
// check if the sid is one we need to change
|
|
//TRACE (_T("DisplayName = %s "),pUserProperties[0].Value.lpszW);
|
|
PSID newSid = 0;
|
|
TAcctNode * node;
|
|
|
|
if ( IsValidSid(pSid) )
|
|
{
|
|
if (!bUseMapFile)
|
|
node = args->Cache()->Lookup(pSid);
|
|
else
|
|
node = args->Cache()->LookupWODomain(pSid);
|
|
if ( m_stat )
|
|
{
|
|
m_stat->IncrementOwnerExamined();
|
|
if ( verbose )
|
|
err.MsgWrite(0,DCT_MSG_EXAMINED_S,values[0]);
|
|
}
|
|
if ( node == (TAcctNode*)-1 && m_stat )
|
|
m_stat->IncrementOwnerNoTarget();
|
|
|
|
if ( node && (node != (TAcctNode *)-1) && node->IsValidOnTgt() )
|
|
{
|
|
if (!bUseMapFile)
|
|
newSid = args->Cache()->GetTgtSid(node);
|
|
else
|
|
newSid = args->Cache()->GetTgtSidWODomain(node);
|
|
}
|
|
else
|
|
{
|
|
newSid = NULL;
|
|
m_stat->IncrementOwnerNoTarget();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newSid = NULL;
|
|
}
|
|
if ( newSid )
|
|
{
|
|
//TRACE (_T("needs to be translated\n"));
|
|
MCSASSERT ( IsValidSid(newSid) );
|
|
WCHAR newSidStr[1000];
|
|
|
|
if ( e.m_connection.BytesToString((BYTE*)newSid,newSidStr,GetLengthSid(newSid)) )
|
|
{
|
|
if ( !args->NoChange() )
|
|
{
|
|
rc = e.m_connection.UpdateSimpleStringValue(values[0],atts[NDX_SID],newSidStr);
|
|
|
|
if ( rc )
|
|
{
|
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_UPDATE_ACCOUNT_FAILED_D, rc);
|
|
}
|
|
else
|
|
anychange = TRUE;
|
|
}
|
|
if ( anychange && m_stat )
|
|
{
|
|
m_stat->IncrementOwnerChange(node,mailbox,NULL);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// this variable determines whether we should continue mailbox translation
|
|
DWORD dwContinueRC = ERROR_SUCCESS;
|
|
|
|
// Update the NT-Security-Descriptor, if any
|
|
// however, we do not try to roll back if anything wrong happens in this part
|
|
if ( values[NDX_SD] && *values[NDX_SD] )
|
|
{
|
|
// convert the SID to a binary value and look it up in the cache
|
|
BYTE * pSD = new BYTE[UStrLen(values[NDX_SD])];
|
|
if (!pSD)
|
|
dwContinueRC = ERROR_OUTOFMEMORY;
|
|
|
|
if ( dwContinueRC == ERROR_SUCCESS && e.m_connection.StringToBytes(values[NDX_SD],pSD) )
|
|
{
|
|
TMapiSD tMailbox((SECURITY_DESCRIPTOR *)pSD);
|
|
if ( tMailbox.HasSecurity() )
|
|
{
|
|
TSD * pSD = tMailbox.GetSecurity();
|
|
|
|
bool changes = tMailbox.ResolveSDInternal(args->Cache(),m_stat,verbose,args->TranslationMode(),mailbox, bUseMapFile);
|
|
|
|
if ( changes )
|
|
{
|
|
SECURITY_DESCRIPTOR * pRelSD = (SECURITY_DESCRIPTOR *)pSD->MakeRelSD();
|
|
if (pRelSD == NULL)
|
|
dwContinueRC = ERROR_OUTOFMEMORY;
|
|
|
|
if ( dwContinueRC == ERROR_SUCCESS && ! args->NoChange() )
|
|
{
|
|
DWORD dwSDLength = GetSecurityDescriptorLength(pRelSD);
|
|
|
|
WCHAR * pSDString = new WCHAR[1 + dwSDLength * 2];
|
|
if (!pSDString)
|
|
dwContinueRC = ERROR_OUTOFMEMORY;
|
|
|
|
if ( dwContinueRC == ERROR_SUCCESS && e.m_connection.BytesToString((BYTE*)pRelSD,pSDString,dwSDLength) )
|
|
{
|
|
rc = e.m_connection.UpdateSimpleStringValue(values[0],atts[NDX_SD],pSDString);
|
|
if ( rc )
|
|
{
|
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_RECIP_SD_WRITE_FAILED_SD,values[0],rc);
|
|
if ( rc == ERROR_INVALID_PARAMETER )
|
|
{
|
|
// this error occurs when the security descriptor is too large
|
|
// don't abort in this case
|
|
rc = 0;
|
|
}
|
|
}
|
|
else
|
|
anychange = TRUE;
|
|
|
|
}
|
|
delete [] pSDString;
|
|
}
|
|
|
|
if (pRelSD)
|
|
free(pRelSD);
|
|
}
|
|
}
|
|
}
|
|
delete [] pSD;
|
|
}
|
|
|
|
if ( anychange && m_stat )
|
|
{
|
|
m_stat->IncrementChanged(mailbox);
|
|
err.MsgWrite(0, DCT_MSG_MAILBOX_HAS_BEEN_UPDATED_S, values[0]);
|
|
}
|
|
|
|
if (dwContinueRC != ERROR_SUCCESS)
|
|
{
|
|
if (anychange)
|
|
err.SysMsgWrite(ErrE,dwContinueRC,DCT_MSG_MAILBOX_TRANSLATION_ABORTED_WITH_UPDATE_SD,values[0],dwContinueRC);
|
|
else
|
|
err.SysMsgWrite(ErrE,dwContinueRC,DCT_MSG_MAILBOX_TRANSLATION_ABORTED_SD,values[0],dwContinueRC);
|
|
e.FreeData(values);
|
|
return FALSE;
|
|
}
|
|
|
|
e.FreeData(values);
|
|
|
|
}
|
|
|
|
} while ( ! rc );
|
|
}
|
|
if ( rc && (rc != LDAP_COMPARE_FALSE) && (rc != ERROR_NOT_FOUND) )
|
|
{
|
|
err.SysMsgWrite(ErrE,e.m_connection.LdapMapErrorToWin32(rc),DCT_MSG_LDAP_CALL_FAILED_SD,server,rc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
err.SysMsgWrite(ErrE,rc,DCT_MSG_CANNOT_CONNECT_TO_EXCHANGE_SERVER_SSD,server,domain,user,rc);
|
|
}
|
|
|
|
return rc;
|
|
}
|