|
|
//----------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: drt.cxx
//
// Contents: Main for OleDs DRT
//
//
// History: 28-Oct-94 KrishnaG, created OleDs DRT
// 28-Oct-94 ChuckC, rewritten.
//
//----------------------------------------------------------------------------
#include "precomp.h"
// Description:
//
// Ldap utilities expect the domain name to be a fully qualified dns name.
// This function takes a flat or dns name as input, and returns the
// fully qualified dns name as output.
//
// Parameters:
//
// pszDomain - caller supplied domain name to be "cracked"
// pfCracked - TRUE if cracking was required, FALSE if the supplied domain
// name was already in the corrrect form.
// ppszDomain - the cracked name if pfCracked is set to TRUE. Caller
// frees this string with NsuFree.
//
DWORD CrackDomainName( IN WCHAR* pszDomain, // domain name from the caller
OUT BOOL* pbCracked, //
OUT WCHAR** ppszDomain) // will point to pszDomain or pszBuffer on success
{ DWORD dwErr = NO_ERROR; PDOMAIN_CONTROLLER_INFOW pDcInfo = NULL;
// Initialize
//
*pbCracked = FALSE; *ppszDomain = NULL;
// NULL domain means "use default" to ldap, so no further processing is
// needed.
//
if (pszDomain == NULL) { return NO_ERROR; }
// If the domain name contains a period, then assume, that it is already
// a fully qualified dns name.
//
if (wcsstr(pszDomain, L".")) { return NO_ERROR; }
// Otherwise, use DsGetDcName to discover the fully qualified domain name
// of the supplied domain
//
dwErr = DsGetDcNameW( NULL, pszDomain, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME, &pDcInfo); NSU_BAIL_ON_ERROR(dwErr);
// If the domain name is not returned, then we have a problem
//
if ((pDcInfo == NULL) || (pDcInfo->DomainName == NULL)) { dwErr = ERROR_NOT_ENOUGH_MEMORY; NSU_BAIL_ON_ERROR(dwErr); }
// Pull out the dns name from the dc info
//
dwErr = NsuStringDupW( ppszDomain, 4 * 1024, // not supporting > 4k chars names
pDcInfo->DomainName); NSU_BAIL_ON_ERROR(dwErr);
*pbCracked = TRUE;
NSU_CLEANUP:
if (pDcInfo) { NetApiBufferFree(pDcInfo); }
return dwErr; }
DWORD LdapOpen( WCHAR *domainName, int portno, HLDAP * phLdapHandle ) { int ldaperr = 0; void *ldapOption; HLDAP hLdapHandle = NULL; DWORD dwError = 0; WCHAR* pszCracked = NULL; BOOL bCracked = FALSE;
// Discover the domain name in the form ldap expects.
//
// If cracking the name fails, then try to connect using the caller
// supplied domain name anyway before failing altogether.
//
dwError = CrackDomainName(domainName, &bCracked, &pszCracked); if (dwError == ERROR_SUCCESS) { if (bCracked) { domainName = pszCracked; } } dwError = ERROR_SUCCESS;
hLdapHandle = ldap_init(domainName, portno );
if (hLdapHandle == NULL ) {
dwError = ERROR_BAD_NETPATH; goto error; }
//
// Now process versioning
//
ldapOption = (void *) LDAP_VERSION3;
ldaperr = ldap_set_option( hLdapHandle, LDAP_OPT_VERSION, &(ldapOption) );
ldapOption = LDAP_OPT_ON;
//
// Ignoring errors for ldap_set_option because we can't force these on
// non-AD directory services (e.g. NDS)
ldaperr = ldap_set_option( hLdapHandle, LDAP_OPT_ENCRYPT, &(ldapOption) );
ldaperr = ldap_set_option( hLdapHandle, LDAP_OPT_SIGN, &(ldapOption) );
ldaperr = ldap_connect(hLdapHandle, NULL);
if (ldaperr) {
dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
goto error; }
//
// Disabled Callback function support and chasing external referrals
// KrishnaG - do I need to support this.
*phLdapHandle = hLdapHandle;
return(dwError);
error:
if (hLdapHandle != NULL) {
ldaperr = ldap_unbind( hLdapHandle );
}
if (pszCracked != NULL) {
NsuFree(&pszCracked);
}
return (dwError); }
DWORD LdapBind( HLDAP hLdapHandle ) { int ldaperr = 0;
ldaperr = ldap_bind_s(hLdapHandle, NULL, NULL, LDAP_AUTH_SSPI);
return (ldaperr); }
DWORD LdapSearchHelper( HLDAP hLdapHandle, WCHAR *base, int scope, WCHAR *filter, WCHAR *attrs[], int attrsonly, struct l_timeval *timeout, LDAPMessage **res ) { int nCount = 0; int j = 0; int ldaperr = 0; DWORD dwError = 0;
if ( timeout == NULL ) { ldaperr = ldap_search_s( hLdapHandle, base, scope, filter, attrs, attrsonly, res ); dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
} else { ldaperr = ldap_search_st( hLdapHandle, base, scope, filter, attrs, attrsonly, timeout, res ); dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
}
//
// Is there an error with checking the no of results
//
return (dwError); }
DWORD LdapSearchS( HLDAP hLdapHandle, WCHAR *base, int scope, WCHAR *filter, WCHAR *attrs[], int attrsonly, LDAPMessage **res ) {
DWORD dwError = 0;
dwError = LdapSearchHelper( hLdapHandle, base, scope, filter, attrs, attrsonly, NULL, res ); //
// Is there a check needed for connection errors
//
return(dwError);
}
DWORD LdapSearchST( HLDAP hLdapHandle, WCHAR *base, int scope, WCHAR *filter, WCHAR *attrs[], int attrsonly, struct l_timeval *timeout, LDAPMessage **res ) { DWORD dwError = 0;
dwError = LdapSearchHelper( hLdapHandle, base, scope, filter, attrs, attrsonly, timeout, res );
return(dwError); }
//
// Completely new functionality - block ported from YihsinS code in ADSI
//
DWORD LdapAbandon( HLDAP hLdapHandle, int msgid ) {
// No error code, 0 if success, -1 otherwise
return ldap_abandon( hLdapHandle, msgid ); }
DWORD LdapResult( HLDAP hLdapHandle, int msgid, int all, struct l_timeval *timeout, LDAPMessage **res, int *restype ) { DWORD dwError = 0; int ldaperr = 0;
*restype = ldap_result( hLdapHandle, msgid, all, timeout, res );
if ( *restype == -1 ) // error
ldaperr = LdapGetLastError();
if (ldaperr) {
if (!ldap_count_entries( hLdapHandle, *res )) {
dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); } }else {
dwError = 0; }
return(dwError);
}
void LdapMsgFree( LDAPMessage *res ) { ldap_msgfree( res ); // Returns the type of message freed which
// is not interesting
}
int LdapResult2Error( HLDAP hLdapHandle, LDAPMessage *res, int freeit ) {
return ldap_result2error( hLdapHandle, res, freeit ); }
DWORD LdapFirstEntry( HLDAP hLdapHandle, LDAPMessage *res, LDAPMessage **pfirst ) { DWORD dwError = 0; int ldaperr = 0;
*pfirst = ldap_first_entry( hLdapHandle, res );
if ( *pfirst == NULL ) { ldaperr = LdapGetLastError();
dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); }
return(dwError); }
DWORD LdapNextEntry( HLDAP hLdapHandle, LDAPMessage *entry, LDAPMessage **pnext ) { DWORD dwError = 0; int ldaperr = 0;
*pnext = ldap_next_entry( hLdapHandle, entry );
if ( *pnext == NULL ) { ldaperr = LdapGetLastError();
dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); }
return(dwError); }
int LdapCountEntries( HLDAP hLdapHandle, LDAPMessage *res ) {
return ldap_count_entries( hLdapHandle, res ); }
DWORD LdapFirstAttribute( HLDAP hLdapHandle, LDAPMessage *entry, void **ptr, WCHAR **pattr ) {
// NOTE: The return value from ldap_first_attribute is static and
// should not be freed
*pattr = ldap_first_attribute( hLdapHandle, entry, (struct berelement **) ptr ); // static data
if ( *pattr == NULL ) { DWORD dwError = 0; int ldaperr = 0;
// Error occurred or end of attributes
ldaperr = LdapGetLastError();
CheckAndSetExtendedError( hLdapHandle, ldaperr);
return(dwError); }
return NO_ERROR;
}
DWORD LdapNextAttribute( HLDAP hLdapHandle, LDAPMessage *entry, void *ptr, WCHAR **pattr ) {
// NOTE: The return value from ldap_next_attribute is static and
// should not be freed
*pattr = ldap_next_attribute( hLdapHandle, entry, (struct berelement *) ptr ); // static data
#if 0 // Ignore the error code here since at the end of the enumeration,
// we will probably get an error code here ( both Andy and umich's
// dll will return errors sometimes. No error returned from NTDS,
// but errors are returned from Exchange server )
if ( *pattr == NULL ) { DWORD hr = NO_ERROR; int ldaperr = 0;
// Error occurred or end of attributes
ldaperr = LdapGetLastError(); dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); return(dwError); } #endif
return S_OK; }
//
// NOTE: LdapGetValues return S_OK if attribute [attr] has no values
// (*[pvalues] =NULL, *[pcount]=0) but all else ok.
//
DWORD LdapGetValues( HLDAP hLdapHandle, LDAPMessage *entry, WCHAR *attr, WCHAR ***pvalues, int *pcount ) { DWORD dwError = 0; int ldaperr = 0;
*pvalues = ldap_get_values( hLdapHandle, entry, attr );
if ( *pvalues == NULL ) {
*pcount=0;
//
// ldap_get_values succeeds if attribute has no values
// but all else ok. (confiremed with anoopa)
//
ldaperr = LdapGetLastError();
if (ldaperr) {
dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); }
//
// KrishnaG if *pvalues is NULL which means I don't get back a
// value - return an ERROR
//
return(ERROR_DS_NO_ATTRIBUTE_OR_VALUE); }
*pcount = ldap_count_values( *pvalues );
return S_OK; }
//
// NOTE: LdapGetValuesLen return S_OK if attribute [attr] has no values
// (*[pvalues] =NULL, *[pcount]=0) but all else ok.
//
DWORD LdapGetValuesLen( HLDAP hLdapHandle, LDAPMessage *entry, WCHAR *attr, struct berval ***pvalues, int *pcount ) { //
// NOTE: this can contain binary data as well as strings,
// strings are ascii, no conversion is done here
//
char *pszAttrA = NULL; DWORD dwError = 0; int ldaperr = 0;
*pvalues = ldap_get_values_len( hLdapHandle, entry, attr );
if ( *pvalues == NULL ){
*pcount=0;
//
// ldap_get_values succeeds if attribute has no values
// but all else ok. (confiremed with anoopa)
//
ldaperr = LdapGetLastError();
if (ldaperr) {
dwError = CheckAndSetExtendedError( hLdapHandle,ldaperr); }
return(ERROR_DS_NO_ATTRIBUTE_OR_VALUE); }
*pcount = ldap_count_values_len( *pvalues );
return S_OK; }
void LdapValueFree( WCHAR **vals ) { ldap_value_free( vals ); }
void LdapValueFreeLen( struct berval **vals ) { ldap_value_free_len( vals ); }
void LdapMemFree( WCHAR *pszString ) { ldap_memfree( pszString ); }
void LdapAttributeFree( WCHAR *pszString ) { // String from ldap_first/next_attribute should not be freed,
// so do nothing here
}
DWORD LdapGetDn( HLDAP hLdapHandle, LDAPMessage *entry, WCHAR **pdn ) { int ldaperr = 0; DWORD dwError = 0;
*pdn = ldap_get_dn( hLdapHandle, entry ); if ( *pdn == NULL ) { // Error occurred
ldaperr = LdapGetLastError();
dwError = CheckAndSetExtendedError( hLdapHandle, ldaperr); return(dwError); }
return(dwError); }
DWORD CheckAndSetExtendedError( HLDAP hLdapHandle, int ldaperr ) {
DWORD dwErr = NO_ERROR;
switch (ldaperr) {
case LDAP_SUCCESS : dwErr = NO_ERROR; break;
case LDAP_OPERATIONS_ERROR : dwErr = ERROR_DS_OPERATIONS_ERROR; break;
case LDAP_PROTOCOL_ERROR : dwErr = ERROR_DS_PROTOCOL_ERROR; break;
case LDAP_TIMELIMIT_EXCEEDED : dwErr = ERROR_DS_TIMELIMIT_EXCEEDED; break;
case LDAP_SIZELIMIT_EXCEEDED : dwErr = ERROR_DS_SIZELIMIT_EXCEEDED; break;
case LDAP_COMPARE_FALSE : dwErr = ERROR_DS_COMPARE_FALSE; break;
case LDAP_COMPARE_TRUE : dwErr = ERROR_DS_COMPARE_TRUE; break;
case LDAP_AUTH_METHOD_NOT_SUPPORTED : dwErr = ERROR_DS_AUTH_METHOD_NOT_SUPPORTED; break;
case LDAP_STRONG_AUTH_REQUIRED : dwErr = ERROR_DS_STRONG_AUTH_REQUIRED; break;
case LDAP_PARTIAL_RESULTS :
//
// Make sure we handle
// partial results.
//
dwErr = ERROR_MORE_DATA; break;
case LDAP_REFERRAL : dwErr = ERROR_DS_REFERRAL; break;
case LDAP_ADMIN_LIMIT_EXCEEDED : dwErr = ERROR_DS_ADMIN_LIMIT_EXCEEDED; break;
case LDAP_UNAVAILABLE_CRIT_EXTENSION : dwErr = ERROR_DS_UNAVAILABLE_CRIT_EXTENSION; break;
case LDAP_CONFIDENTIALITY_REQUIRED : dwErr = ERROR_DS_CONFIDENTIALITY_REQUIRED; break;
case LDAP_NO_SUCH_ATTRIBUTE : dwErr = ERROR_DS_NO_ATTRIBUTE_OR_VALUE; break;
case LDAP_UNDEFINED_TYPE : dwErr = ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED; break;
case LDAP_INAPPROPRIATE_MATCHING : dwErr = ERROR_DS_INAPPROPRIATE_MATCHING; break;
case LDAP_CONSTRAINT_VIOLATION : dwErr = ERROR_DS_CONSTRAINT_VIOLATION; break;
case LDAP_ATTRIBUTE_OR_VALUE_EXISTS : dwErr = ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS; break;
case LDAP_INVALID_SYNTAX : dwErr = ERROR_DS_INVALID_ATTRIBUTE_SYNTAX; break;
case LDAP_NO_SUCH_OBJECT : dwErr = ERROR_DS_NO_SUCH_OBJECT; break;
case LDAP_ALIAS_PROBLEM : dwErr = ERROR_DS_ALIAS_PROBLEM; break;
case LDAP_INVALID_DN_SYNTAX : dwErr = ERROR_DS_INVALID_DN_SYNTAX; break;
case LDAP_IS_LEAF : dwErr = ERROR_DS_IS_LEAF; break;
case LDAP_ALIAS_DEREF_PROBLEM : dwErr = ERROR_DS_ALIAS_DEREF_PROBLEM; break;
case LDAP_INAPPROPRIATE_AUTH : dwErr = ERROR_DS_INAPPROPRIATE_AUTH; break;
case LDAP_INVALID_CREDENTIALS : dwErr = ERROR_LOGON_FAILURE; break;
case LDAP_INSUFFICIENT_RIGHTS : dwErr = ERROR_ACCESS_DENIED; break;
case LDAP_BUSY : dwErr = ERROR_DS_BUSY; break;
case LDAP_UNAVAILABLE : dwErr = ERROR_DS_UNAVAILABLE; break;
case LDAP_UNWILLING_TO_PERFORM : dwErr = ERROR_DS_UNWILLING_TO_PERFORM; break;
case LDAP_LOOP_DETECT : dwErr = ERROR_DS_LOOP_DETECT; break;
case LDAP_NAMING_VIOLATION : dwErr = ERROR_DS_NAMING_VIOLATION; break;
case LDAP_OBJECT_CLASS_VIOLATION : dwErr = ERROR_DS_OBJ_CLASS_VIOLATION; break;
case LDAP_NOT_ALLOWED_ON_NONLEAF : dwErr = ERROR_DS_CANT_ON_NON_LEAF; break;
case LDAP_NOT_ALLOWED_ON_RDN : dwErr = ERROR_DS_CANT_ON_RDN; break;
case LDAP_ALREADY_EXISTS : dwErr = ERROR_OBJECT_ALREADY_EXISTS; break;
case LDAP_NO_OBJECT_CLASS_MODS : dwErr = ERROR_DS_CANT_MOD_OBJ_CLASS; break;
case LDAP_RESULTS_TOO_LARGE : dwErr = ERROR_DS_OBJECT_RESULTS_TOO_LARGE; break;
case LDAP_AFFECTS_MULTIPLE_DSAS : dwErr = ERROR_DS_AFFECTS_MULTIPLE_DSAS; break;
case LDAP_OTHER : dwErr = ERROR_GEN_FAILURE; break;
case LDAP_SERVER_DOWN : dwErr = ERROR_DS_SERVER_DOWN; break;
case LDAP_LOCAL_ERROR : dwErr = ERROR_DS_LOCAL_ERROR; break;
case LDAP_ENCODING_ERROR : dwErr = ERROR_DS_ENCODING_ERROR; break;
case LDAP_DECODING_ERROR : dwErr = ERROR_DS_DECODING_ERROR; break;
case LDAP_TIMEOUT : dwErr = ERROR_TIMEOUT; break;
case LDAP_AUTH_UNKNOWN : dwErr = ERROR_DS_AUTH_UNKNOWN; break;
case LDAP_FILTER_ERROR : dwErr = ERROR_DS_FILTER_UNKNOWN; break;
case LDAP_USER_CANCELLED : dwErr = ERROR_CANCELLED; break;
case LDAP_PARAM_ERROR : dwErr = ERROR_DS_PARAM_ERROR; break;
case LDAP_NO_MEMORY : dwErr = ERROR_NOT_ENOUGH_MEMORY; break;
case LDAP_CONNECT_ERROR : dwErr = ERROR_CONNECTION_REFUSED; break;
case LDAP_NOT_SUPPORTED : dwErr = ERROR_DS_NOT_SUPPORTED; break;
case LDAP_NO_RESULTS_RETURNED : dwErr = ERROR_DS_NO_RESULTS_RETURNED; break;
case LDAP_CONTROL_NOT_FOUND : dwErr = ERROR_DS_CONTROL_NOT_FOUND; break;
case LDAP_MORE_RESULTS_TO_RETURN : dwErr = ERROR_MORE_DATA; break;
case LDAP_CLIENT_LOOP : dwErr = ERROR_DS_CLIENT_LOOP; break;
case LDAP_REFERRAL_LIMIT_EXCEEDED : dwErr = ERROR_DS_REFERRAL_LIMIT_EXCEEDED; break;
default: dwErr = ERROR_DS_BUSY;
}
return(dwErr); }
DWORD LdapAddS( HLDAP hLdapHandle, WCHAR *dn, LDAPModW *attrs[] ) { DWORD dwError = 0; int ldaperr = 0;
ldaperr = ldap_add_s( hLdapHandle, dn, attrs );
dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
return(dwError); }
DWORD LdapModifyS( HLDAP hLdapHandle, WCHAR *dn, LDAPModW *mods[] ) { DWORD dwError = 0; int ldaperr = 0;
ldaperr = ldap_modify_s( hLdapHandle, dn, mods);
dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
return(dwError); }
DWORD LdapDeleteS( HLDAP hLdapHandle, WCHAR *dn ) { DWORD dwError = 0; int ldaperr = 0;
ldaperr = ldap_delete_s( hLdapHandle, dn );
dwError = CheckAndSetExtendedError(hLdapHandle, ldaperr);
return(dwError); }
|