Leaked source code of windows server 2003
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

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