⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldap_net.cpp

📁 ldap_vcnet ldap_vcnet ldap_vcnet
💻 CPP
字号:
/**************************************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
   PARTICULAR PURPOSE.
   Author: Leon Finker  9/2002
**************************************************************************/

#include "common.h"
#include "ldap_net.h"
#include "helpers.h"
#include <stdio.h>

namespace ldap_net
{
////////////////////////////////////////////////////////////////////////
// LdapAttribute
String* LdapAttribute::get_StringValues()[]
{ 
	CIntPtrStringAnsi ptrAttribname(m_attribname);
	char** vals = ::ldap_get_values(m_ldap, m_start, ptrAttribname);
	ptrAttribname.Free();
	Collections::Specialized::StringCollection* sc = new Collections::Specialized::StringCollection();
	for(int i=0; vals[i] != 0; ++i)
		sc->Add(new String(vals[i]));

	ldap_value_free(vals);

	String* sa[] = new String*[sc->Count];
	sc->CopyTo(sa, 0);
	sc->Clear();
	return sa;
}
/* get_BinaryValues */
Array* LdapAttribute::get_BinaryValues()
{ 
	CIntPtrStringAnsi ptrAttribname(m_attribname);
	berval** vals = ldap_get_values_len(m_ldap, m_start, ptrAttribname);
	ptrAttribname.Free();
	Array* arr[] = new Array*[ldap_count_values_len(vals)];
	for(int i=0; vals[i] != 0; ++i)
	{
		Byte ba[] = new Byte[vals[i]->bv_len];
		Marshal::Copy(IntPtr(vals[i]->bv_val), ba, 0, ba->Length);
		arr[i]=ba;
	}

	ldap_value_free_len(vals);
	return arr;
}
/* MoveNext */
bool LdapAttribute::MoveNext()
{  
	char* attrn;
	if(m_current == 0)
	{
		BerElement* temp;
		attrn = ldap_first_attribute(m_ldap, m_start, &temp);
		m_current = temp;
	}
	else
	{
		attrn = ldap_next_attribute(m_ldap, m_start, m_current);
	}
	if(attrn != 0)
	{
		m_attribname = Marshal::PtrToStringAnsi(attrn);
		ldap_memfree(attrn);
	}
	else
	{
		if(m_current != 0)
			ber_free(m_current, 0);
		
		m_current = 0;
		return false;
	}
	return true;
}

////////////////////////////////////////////////////////////////////////
// LdapEntry

bool LdapEntry::MoveNext()
{
	if(m_current == 0)
		m_current = ldap_first_entry(m_ldap, m_start);
	else
		m_current = ldap_next_entry(m_ldap,m_current);
	if(m_current != 0)
	{
		char* dn = ldap_get_dn(m_ldap, m_current);
		if(dn != 0)
		{
			m_dn = Marshal::PtrToStringAnsi(dn);
			ldap_memfree(dn);
		}
		return true;
	}
	else
		return false;
}

///////////////////////////////////////////////////////////////////////////////
// LDAPModify
// WHAT a f MESS this is!!!
//might have a bug, be carefull
LDAPModify::LDAPModify(const char* dn, ListDictionary * attrvals, long op)
{
	Collections::IDictionaryEnumerator* dicenum = attrvals->GetEnumerator();
	IntPtr ptrMods = Marshal::AllocCoTaskMem((attrvals->Count+1) * sizeof(::LDAPMod*)); //+1 for null
	/*1*/ppMods = (LDAPMod**)ptrMods.ToPointer();
	for(int i=0; i< attrvals->Count; ++i)
		/*2*/ppMods[i] = (::LDAPMod*)Marshal::AllocCoTaskMem(sizeof(::LDAPMod)).ToPointer();

	for(int i=0; dicenum->MoveNext(); ++i)
	{
		String* skey=dynamic_cast<String*>(dicenum->Key);
		if(skey == 0)
			throw new InvalidCastException(S"Invalid type for attribute name, String expected");
		
		ppMods[i]->mod_op = op;
		bool binary=false;
		
		String* svalarr[]= dynamic_cast<String*[]>(dicenum->Value);
		Object* barr[]   = dynamic_cast<Object*[]>(dicenum->Value);
		Byte ba[]		 = dynamic_cast<Byte[]>(dicenum->Value);
		String* sval	 = dynamic_cast<String*>(dicenum->Value);

		int nValsCount = 0;
		if(svalarr != 0)
		{
			binary = false;
			nValsCount = svalarr->Count;
		}
		else if(barr != 0) //check has to be after svalarr
		{
			binary = true;
			nValsCount = barr->Count;
		}
		else if(sval != 0)
		{
			binary = false;
			nValsCount = 1;
		}
		else if(ba != 0)
		{
			binary = true;
			nValsCount = 1;
		}
		else
		{
			if(dicenum->Value != 0)
				throw new InvalidCastException(String::Concat("Expected String, String[], Array of Byte[], or Byte[] for values but got ", dicenum->Value->GetType()->ToString()));
		}
		
		ppMods[i]->mod_op |= LDAP_MOD_BVALUES;
		/*3*/ppMods[i]->mod_type=(char*)Marshal::StringToCoTaskMemAnsi(skey).ToPointer();
		
		/*4*/ppMods[i]->mod_vals.modv_bvals = (berval**)Marshal::AllocCoTaskMem((nValsCount+1) * sizeof(berval*)).ToPointer(); //+1 for null;
		for(int j=0; j < nValsCount; ++j)
		{
			/*5*/ppMods[i]->mod_vals.modv_bvals[j]=(berval*)Marshal::AllocCoTaskMem(sizeof(berval)).ToPointer();
			char* pTemp=0;
			int nLen = 0;
			if(!binary)
			{
				if(sval)
					pTemp = (char*)Marshal::StringToCoTaskMemAnsi(sval).ToPointer();
				else
					pTemp = (char*)Marshal::StringToCoTaskMemAnsi(svalarr[j]).ToPointer();
				nLen = strlen(pTemp);
			}
			else
			{
				Byte baTemp[];
				if(ba != 0)
				{
					baTemp = ba;
					nLen = baTemp->Count;
					pTemp = (char*)Marshal::AllocCoTaskMem(nLen).ToPointer();
					Marshal::Copy(baTemp, 0, IntPtr(pTemp), nLen);
				}
				else
				{
					if(dynamic_cast<Byte[]>(barr[j]) == 0)
						throw new InvalidCastException(String::Concat("Expected Byte[] for values but got ", dicenum->Value->GetType()->ToString()));
					baTemp = (Byte[])barr[j];
					nLen = baTemp->Count;
					pTemp = (char*)Marshal::AllocCoTaskMem(nLen).ToPointer();
					Marshal::Copy(baTemp, 0, IntPtr(pTemp), nLen);
				}
			}
			/*6*/ppMods[i]->mod_vals.modv_bvals[j]->bv_val=pTemp;
			ppMods[i]->mod_vals.modv_bvals[j]->bv_len = nLen;
		}
		ppMods[i]->mod_vals.modv_bvals[nValsCount]=0;//must null terminate for ldap
	}
	ppMods[attrvals->Count] = 0; //need to null terminate for ldap
}

/* ~LDAPModify */
LDAPModify::~LDAPModify()
{
	for(int i=0; ppMods[i] != 0; ++i)
	{
		for(int j=0; ppMods[i]->mod_vals.modv_bvals[j] != 0; ++j)
		{
			/*6*/Marshal::FreeCoTaskMem(IntPtr(ppMods[i]->mod_vals.modv_bvals[j]->bv_val));
			/*5*/Marshal::FreeCoTaskMem(IntPtr(ppMods[i]->mod_vals.modv_bvals[j]));
		}
		
		/*4*/Marshal::FreeCoTaskMem(IntPtr(ppMods[i]->mod_vals.modv_bvals));

		/*3*/Marshal::FreeCoTaskMem(IntPtr(ppMods[i]->mod_type));
		/*2*/Marshal::FreeCoTaskMem(IntPtr(ppMods[i]));
	}
	/*1*/Marshal::FreeCoTaskMem(ppMods);
}

/////////////////////////////////////////////////////////////////////////////////
// LdapClient
LdapClient::LdapClient(String* HostName, UInt32 port, bool prot_ver3, bool ssl)
{
	CIntPtrStringAnsi ptrHost(HostName);
	
#ifdef OPENLDAP_NET
	m_ldap = ::ldap_init(ptrHost, port);	
	//LDAP* temp; //this code is needed for connecting with ssl to AD, because ldap_start_tls_s won't work on win2k
	              //but ldap_start_tls_s should work with windows 2003 and AD
	//ldap_initialize(&temp, (char*)ptr.ToPointer()); //for uri based hostname i.e. ldaps://localhost (ssl)
	//m_ldap = ldap;
#else
	m_ldap = ::ldap_sslinit(ptrHost, port, ssl);	
#endif

	ptrHost.Free();

	if(m_ldap == 0)
		GetLDAPErrorThrow(0);
	if(prot_ver3)
	{
		LDAPINT ver = LDAP_VERSION3;
		LDAPINT nRet = ::ldap_set_option(m_ldap, LDAP_OPT_PROTOCOL_VERSION, &ver);
		//MS specific: nRet = ::ldap_set_option(m_ldap, LDAP_OPT_SERVER_CERTIFICATE, &ServerCertCallback);
		if(nRet != LDAP_SUCCESS)
			GetLDAPErrorThrow(nRet);
	}
#ifdef OPENLDAP_NET
	if(ssl)
	{
		//when using winldap this function is only available on winxp+
		LDAPINT nRet = ::ldap_start_tls_s(m_ldap,0,0);
		if(nRet != LDAP_SUCCESS)
			GetLDAPErrorThrow(nRet);
	}
#endif

}

/* get_DefaultSSLPort */
UInt32 LdapClient::get_DefaultSSLPort() 
{ 
#ifdef OPENLDAP_NET
	return LDAPS_PORT;
#else
	return LDAP_SSL_PORT;
#endif
}

/* ldap_search_s */
Int32 LdapClient::ldap_search_ext_s(String* base, Misc::LDAPSearchScope scope, String* filter, String* attrs[], bool attrsonly, int timeoutsecs, int sizelimit, [Out] LdapResult** res)
{
	CIntPtrStringAnsi ptrBase(base);
	CIntPtrStringAnsi ptrFilter(filter);
	LDAPMessage *msg=0;

	char** pAttrs = 0;
	if(attrs->Count > 0)
	{
		pAttrs = (char**)(Marshal::AllocCoTaskMem((attrs->Count+1) * sizeof(char*)).ToPointer());
		for(int i=0; i<attrs->Count; ++i)
		{
			IntPtr ptr = Marshal::StringToCoTaskMemAnsi(attrs[i]);
			pAttrs[i] = (char*)ptr.ToPointer();
		}
		pAttrs[attrs->Count] = 0;
	}

	//LDAPINT nRet = ::ldap_search_s(m_ldap, ptrBase, scope, ptrFilter, pAttrs, attrsonly, &msg);
#ifdef WINLDAP_NET
	l_timeval time={0};
#elif OPENLDAP_NET
	timeval	  time={0};
#endif
	time.tv_sec = timeoutsecs;
	LDAPINT nRet = ::ldap_search_ext_s(m_ldap, ptrBase, scope, ptrFilter, pAttrs, attrsonly, 0, 0, &time, sizelimit, &msg);
	ptrBase.Free();
	ptrFilter.Free();
	if(attrs->Count > 0)
	{
		for(int i=0; i < attrs->Count; ++i)
		{
			char* p = pAttrs[i];
			Marshal::FreeCoTaskMem(IntPtr(p));
			pAttrs[i]=0;
		}
		Marshal::FreeCoTaskMem(pAttrs);
	}
	if(nRet != LDAP_SUCCESS && nRet != LDAP_PARTIAL_RESULTS && nRet != LDAP_SIZELIMIT_EXCEEDED)
	{
		if(msg)
			ldap_msgfree(msg);
		GetLDAPErrorThrow(nRet);
	}
	LDAPINT nCount = ldap_count_entries(m_ldap, msg);
	*res = new LdapResult(m_ldap, msg);
	if(nRet == LDAP_PARTIAL_RESULTS || nRet == LDAP_SIZELIMIT_EXCEEDED)
		throw new Exceptions::LDAPExceptionPartialResult(nCount);
	return nCount;
}

/* ldap_add_s */
void LdapClient::ldap_add_s(String* dn, ListDictionary * attrvals)
{
#ifdef _DEBUG
	Diagnostics::Debug::Assert(attrvals->Count > 0,"Nothing to add.");
#endif
	CIntPtrStringAnsi ptrDN(dn);
	LDAPModify mod(ptrDN, attrvals, LDAP_MOD_ADD);
	LDAPINT nRet = ::ldap_add_s(m_ldap, ptrDN, mod.ppMods);
	ptrDN.Free();
	if(nRet != LDAP_SUCCESS)
		GetLDAPErrorThrow(nRet);
}

/* ldap_compare_s */
bool LdapClient::ldap_compare_s(String* dn, String* attr, String* val)
{
	CIntPtrStringAnsi ptrDN(dn);
	CIntPtrStringAnsi ptrAttr(attr);
	CIntPtrStringAnsi ptrVal(val);
	LDAPINT nRet = ::ldap_compare_s(m_ldap, ptrDN, ptrAttr, ptrVal);
	ptrDN.Free();
	ptrAttr.Free();
	ptrVal.Free();
	if(nRet != LDAP_COMPARE_TRUE && nRet != LDAP_COMPARE_FALSE)
		GetLDAPErrorThrow(nRet);

	return nRet == LDAP_COMPARE_TRUE;
}

/* ldap_delete_s */
void LdapClient::ldap_delete_s(String* dn)
{
	CIntPtrStringAnsi ptrDN(dn);
	LDAPINT nRet = ::ldap_delete_s(m_ldap, ptrDN);
	ptrDN.Free();
	if(nRet != LDAP_SUCCESS)
		GetLDAPErrorThrow(nRet);
}

/* ldap_modify_passwd */
void LdapClient::ldap_modify_pwd(String* dn, String* newpasswd)
{

	//printf("==========>		Begin Modify user`s password! \n");
	struct berval newpw = { 0, NULL };
	BerElement		*ber = NULL;
	PBERVAL			bv = NULL;
    int				rc = LDAP_SUCCESS;	
	LDAPMessage*	res;
	ULONG			id, code = LDAP_OTHER;

	/*
	* Check input parameter
	*/

	if ( dn == NULL )
		GetLDAPErrorThrow(LDAP_PARAM_ERROR);

	if ( newpasswd == NULL )
		GetLDAPErrorThrow(LDAP_PARAM_ERROR);

	//Data type Conversion (From String to PCHAR)
	CIntPtrStringAnsi ptrDN(dn);
	//CIntPtrStringAnsi ptrNewpasswd(newpasswd);	
	
	CIntPtrStringAnsi ptrPWD(newpasswd);

	//newpw.bv_val = ptrNewpasswd;
	//newpw.bv_len = strlen( newpw.bv_val );

    /*
     * Allocate a BerElement for stuffing in the function IN parameters 
     */
	//The LBER_USE_DER flag (0x01) should always be specified, which causes the element lengths to be encoded in the minimum number of octets.

    ber = ber_alloc_t(LBER_USE_DER);	
    if(ber == NULL)
		GetLDAPErrorThrow(LDAP_NO_MEMORY);
	//#ifdef _DEBUG
	//printf("==========>	Step 01\n");
	//#endif
      
	/* 
	* Build the flow for modify the uses`s password and transfer to ldap server
	*/
	rc = ber_printf( ber,"{");	
	if (rc == LBER_ERROR) 
		GetLDAPErrorThrow(LDAP_ENCODING_ERROR);

	rc =  ber_printf( ber, "ts",LDAP_TAG_EXOP_MODIFY_PASSWD_ID, ptrDN);
	if (rc == LBER_ERROR) 
		GetLDAPErrorThrow(LDAP_ENCODING_ERROR);

	rc = ber_printf( ber, "ts",LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, ptrPWD );	
	if (rc == LBER_ERROR) 
		GetLDAPErrorThrow(LDAP_ENCODING_ERROR);

	rc = ber_printf( ber,"}" );	
	if (rc == LBER_ERROR) 
		GetLDAPErrorThrow(LDAP_ENCODING_ERROR);

	rc = ber_flatten(ber,&bv);	
	if (rc == LBER_ERROR) 
		GetLDAPErrorThrow(LDAP_NO_MEMORY);

	/*
	* Call ldap extended operation RFC3062
	*/
	rc = ldap_extended_operation( m_ldap,LDAP_EXOP_MODIFY_PASSWD,bv,NULL,NULL,&id);
	if( rc != LDAP_SUCCESS )
		GetLDAPErrorThrow(LDAP_OTHER);

	
	rc = ldap_result( m_ldap, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res ); 
	if( rc < 0 )
		GetLDAPErrorThrow(LDAP_NO_RESULTS_RETURNED);

	//printf("The result message is %s\n",res);
	rc = ldap_parse_result( m_ldap,res,&code,NULL,NULL,NULL,NULL, 0 );
	if( rc != LDAP_SUCCESS )
		GetLDAPErrorThrow(LDAP_NO_RESULTS_RETURNED);

	if( code != LDAP_SUCCESS )
		GetLDAPErrorThrow(LDAP_NO_SUCH_OBJECT);

	/*
	*	Realease the resource . Do not make memory leak.
	*/

	ber_free( ber, 1 );
	ber_bvfree(bv);
	ptrPWD.Free();
	ptrDN.Free();
	ldap_msgfree(res);
	//printf("Result: %s | (%d)\n", ldap_err2string( code ), code );
	//printf("==========>		End Modify user`s password! \n");
}

/* ldap_simple_bind_s */
void LdapClient::ldap_simple_bind_s(String* who, String* passwd)
{
	CIntPtrStringAnsi ptrWho(who);
	CIntPtrStringAnsi ptrPasswd(passwd);
	LDAPINT nRet = ::ldap_simple_bind_s(m_ldap, ptrWho, ptrPasswd);
	ptrWho.Free();
	ptrPasswd.Free();
	if(nRet != LDAP_SUCCESS)
		GetLDAPErrorThrow(nRet);
}


/*ldap_modify_s*/
void LdapClient::ldap_bind_s(String* who, String* passwd, Misc::AuthMethod method)
{
	CIntPtrStringAnsi ptrWho(who);
	CIntPtrStringAnsi ptrPasswd(passwd);
	LDAPINT nRet = ::ldap_bind_s(m_ldap, ptrWho, ptrPasswd, method);
	ptrWho.Free();
	ptrPasswd.Free();
	if(nRet != LDAP_SUCCESS)
		GetLDAPErrorThrow(nRet);	
}

/*ldap_modify_s*/
void LdapClient::ldap_modify_s(String* dn, ListDictionary * attrvals, long op)
{
#ifdef _DEBUG
	Diagnostics::Debug::Assert(attrvals->Count > 0,"Nothing to modify.");
#endif
	CIntPtrStringAnsi ptrDN(dn);
	LDAPModify mod(ptrDN, attrvals, op);
	LDAPINT nRet = ::ldap_modify_s(m_ldap, ptrDN, mod.ppMods);
	ptrDN.Free();
	if(nRet != LDAP_SUCCESS)
		GetLDAPErrorThrow(nRet);
}

/*GetLDAPErrorThrow*/
void LdapClient::GetLDAPErrorThrow(LDAPINT nErr)
{
	if(nErr == 0)
		::ldap_get_option(m_ldap, LDAP_OPT_ERROR_NUMBER, &nErr);
	char* pError = ::ldap_err2string(nErr);
	if(pError == 0)
		pError = "unknown error";
	throw new Exceptions::LDAPException(pError);
}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -