Commit f7419e1c authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Sync with HEAD

parent a5cd1dd7
/*
* Copyright 2000, OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "config.h"
#include "debug.h"
#include "LDAPAsynConnection.h"
#include "LDAPAddRequest.h"
#include "LDAPBindRequest.h"
#include "LDAPCompareRequest.h"
#include "LDAPDeleteRequest.h"
#include "LDAPException.h"
#include "LDAPExtRequest.h"
#include "LDAPEntry.h"
#include "LDAPModDNRequest.h"
#include "LDAPModifyRequest.h"
#include "LDAPRequest.h"
#include "LDAPRebind.h"
#include "LDAPRebindAuth.h"
#include "LDAPSearchRequest.h"
using namespace std;
LDAPAsynConnection::LDAPAsynConnection(const string& hostname, int port,
LDAPConstraints *cons ){
DEBUG(LDAP_DEBUG_CONSTRUCT,"LDAPAsynConnection::LDAPAsynConnection()"
<< endl);
DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER,
" host:" << hostname << endl << " port:" << port << endl);
cur_session=0;
m_constr = 0;
this->init(hostname, port);
this->setConstraints(cons);
}
LDAPAsynConnection::~LDAPAsynConnection(){
DEBUG(LDAP_DEBUG_DESTROY,
"LDAPAsynConnection::~LDAPAsynConnection()" << endl);
if (cur_session){
ldap_destroy_cache(cur_session);
}
unbind();
//delete m_constr;
}
void LDAPAsynConnection::init(const string& hostname, int port){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::init" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER,
" hostname:" << hostname << endl
<< " port:" << port << endl);
cur_session=ldap_init(hostname.c_str(),port);
m_host=hostname;
m_port=port;
int opt=3;
ldap_set_option(cur_session, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
ldap_set_option(cur_session, LDAP_OPT_PROTOCOL_VERSION, &opt);
}
int LDAPAsynConnection::start_tls(){
return ldap_start_tls_s( cur_session, NULL, NULL );
}
LDAPMessageQueue* LDAPAsynConnection::bind(const string& dn,
const string& passwd, const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::bind()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, " dn:" << dn << endl
<< " passwd:" << passwd << endl);
LDAPBindRequest *req = new LDAPBindRequest(dn,passwd,this,cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::search(const string& base,int scope,
const string& filter,
const StringList& attrs,
bool attrsOnly,
const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::search()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, " base:" << base << endl
<< " scope:" << scope << endl
<< " filter:" << filter << endl );
LDAPSearchRequest *req = new LDAPSearchRequest(base, scope,filter, attrs,
attrsOnly, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::del(const string& dn,
const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::del()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl);
LDAPDeleteRequest *req = new LDAPDeleteRequest(dn, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::compare(const string& dn,
const LDAPAttribute& attr, const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::compare()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl
<< " attr:" << attr << endl);
LDAPCompareRequest *req = new LDAPCompareRequest(dn, attr, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::add( const LDAPEntry* le,
const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::add()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," entry:" << *le << endl);
LDAPAddRequest *req = new LDAPAddRequest(le, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::modify(const string& dn,
const LDAPModList *mod, const LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::modify()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl);
LDAPModifyRequest *req = new LDAPModifyRequest(dn, mod, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::rename(const string& dn,
const string& newRDN, bool delOldRDN, const string& newParentDN,
const LDAPConstraints *cons ){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::rename()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl
<< " newRDN:" << newRDN << endl
<< " newParentDN:" << newParentDN << endl
<< " delOldRDN:" << delOldRDN << endl);
LDAPModDNRequest *req = new LDAPModDNRequest(dn, newRDN, delOldRDN,
newParentDN, this, cons );
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::extOperation(const string& oid,
const string& value, const LDAPConstraints *cons ){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::extOperation()" << endl);
DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," oid:" << oid << endl);
LDAPExtRequest *req = new LDAPExtRequest(oid, value, this,cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
void LDAPAsynConnection::abandon(LDAPMessageQueue *q){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::abandon()" << endl);
LDAPRequestStack *reqStack=q->getRequestStack();
LDAPRequest *req;
while(! reqStack->empty()){
req=reqStack->top();
if (ldap_abandon_ext(cur_session, req->getMsgID(), 0, 0)
!= LDAP_SUCCESS){
throw LDAPException(this);
}
delete req;
reqStack->pop();
}
}
void LDAPAsynConnection::unbind(){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::unbind()" << endl);
if(cur_session){
LDAPControl** tmpSrvCtrls=m_constr->getSrvCtrlsArray();
LDAPControl** tmpClCtrls=m_constr->getClCtrlsArray();
int err=ldap_unbind_ext(cur_session, tmpSrvCtrls, tmpClCtrls);
cur_session=0;
LDAPControlSet::freeLDAPControlArray(tmpSrvCtrls);
LDAPControlSet::freeLDAPControlArray(tmpClCtrls);
if(err != LDAP_SUCCESS){
throw LDAPException(err);
}
}
}
void LDAPAsynConnection::setConstraints(LDAPConstraints *cons){
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setConstraints()" << endl);
m_constr=cons;
}
const LDAPConstraints* LDAPAsynConnection::getConstraints() const {
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getConstraints()" << endl);
return m_constr;
}
LDAP* LDAPAsynConnection::getSessionHandle() const{
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getSessionHandle()" << endl);
return cur_session;
}
const string& LDAPAsynConnection::getHost() const{
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setHost()" << endl);
return m_host;
}
int LDAPAsynConnection::getPort() const{
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getPort()" << endl);
return m_port;
}
LDAPAsynConnection* LDAPAsynConnection::referralConnect(
const LDAPUrlList& urls, LDAPUrlList::const_iterator& usedUrl,
const LDAPConstraints* cons) const {
DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::referralConnect()" << endl)
LDAPUrlList::const_iterator conUrl;
LDAPAsynConnection* tmpConn=0;
const LDAPRebind* rebind = cons->getReferralRebind();
LDAPRebindAuth* auth = 0;
for(conUrl=urls.begin(); conUrl!=urls.end(); conUrl++){
string host= conUrl->getHost();
int port= conUrl->getPort();
DEBUG(LDAP_DEBUG_TRACE," connecting to: " << host << ":" <<
port << endl);
//Set the new connection's constraints-object ?
tmpConn=new LDAPAsynConnection(host.c_str(),port);
int err=0;
if(rebind){
auth=rebind->getRebindAuth(host, port);
}
if(auth){
string dn = auth->getDN();
string passwd = auth->getPassword();
const char* c_dn=0;
const char* c_passwd=0;
if(dn != ""){
c_dn = dn.c_str();
}
if(passwd != ""){
c_passwd = passwd.c_str();
}
err = ldap_simple_bind_s(tmpConn->getSessionHandle(), c_dn,
c_passwd);
} else {
// Do anonymous bind
err = ldap_simple_bind_s(tmpConn->getSessionHandle(), 0,0);
}
if( err == LDAP_SUCCESS ){
usedUrl=conUrl;
return tmpConn;
}else{
delete tmpConn;
tmpConn=0;
}
auth=0;
}
return 0;
}
int LDAPAsynConnection::enableCache(long timeout, long maxmem){
int retval = ldap_enable_cache(cur_session, timeout, maxmem);
if (!retval)
m_cacheEnabled = true;
return retval;
}
void LDAPAsynConnection::disableCache(){
ldap_disable_cache(cur_session);
m_cacheEnabled = false;
}
void LDAPAsynConnection::uncache_entry(string &dn){
if (m_cacheEnabled){
ldap_uncache_entry(cur_session, dn.c_str());
}
}
void LDAPAsynConnection::flush_cache(){
if (m_cacheEnabled){
ldap_flush_cache(cur_session);
}
}
/*
* Copyright 2000, OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#ifndef LDAP_ASYN_CONNECTION_H
#define LDAP_ASYN_CONNECTION_H
#include<iostream>
#include<string>
#include<ldap.h>
#include<lber.h>
#include <LDAPMessageQueue.h>
#include <LDAPConstraints.h>
#include <LDAPModification.h>
#include <LDAPModList.h>
#include <LDAPUrl.h>
#include <LDAPUrlList.h>
class LDAPEntry;
class LDAPAttribute;
//* Main class for an asynchronous LDAP connection
/**
* This class represents an asynchronous connection to an LDAP-Server. It
* provides the methods for authentication, and all other LDAP-Operations
* (e.g. search, add, delete, etc.)
* All of the LDAP-Operations return a pointer to a LDAPMessageQueue-Object,
* which can be used to obtain the results of that operation.
* A basic example of this class could be like this: <BR>
* 1. Create a new LDAPAsynConnection Object: <BR>
* 2. Use the init-method to initialize the connection <BR>
* 3. Call the bind-method to authenticate to the directory <BR>
* 4. Obtain the bind results from the return LDAPMessageQueue-Object <BR>
* 5. Perform on of the operations on the directory (add, delete, search, ..)
* <BR>
* 6. Use the return LDAPMessageQueue to obtain the results of the operation
* <BR>
* 7. Close the connection (feature not implemented yet :) ) <BR>
*/
class LDAPAsynConnection{
public :
/**
* Constant for the Search-Operation to indicate a Base-Level
* Search
*/
static const int SEARCH_BASE=0;
/**
* Constant for the Search-Operation to indicate a One-Level
* Search
*/
static const int SEARCH_ONE=1;
/**
* Constant for the Search-Operation to indicate a subtree
* Search
*/
static const int SEARCH_SUB=2;
// static const int SEARCH_SUB=LDAP_SCOPE_SUBTREE;
// static const int SEARCH_ONE=LDAP_SCOPE_ONELEVEL;
// static const int SEARCH_SUB=LDAP_SCOPE_SUBTREE;
/** Construtor that initializes a connection to a server
* @param hostname Name (or IP-Adress) of the destination host
* @param port Port the LDAP server is running on
* @param cons Default constraints to use with operations over
* this connection
*/
LDAPAsynConnection(const std::string& hostname=std::string("localhost"),
int port=389, LDAPConstraints *cons=new LDAPConstraints() );
//* Destructor
virtual ~LDAPAsynConnection();
/**
* Initializes a connection to a server.
*
* There actually no
* communication to the server. Just the object is initialized
* (e.g. this method is called within the
* LDAPAsynConnection(char*,int,LDAPConstraints) constructor.)
* @param hostname The Name or IP-Address of the destination
* LDAP-Server
* @param port The Network Port the server is running on
*/
void init(const std::string& hostname, int port);
/**
* Start TLS on this connection. This isn't in the constructor,
* because it could fail (i.e. server doesn't have SSL cert, client
* api wasn't compiled against OpenSSL, etc.). If you need TLS,
* then you should error if this call fails with an error code.
*/
int start_tls();
/** Simple authentication to a LDAP-Server
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* This method does a simple (username, password) bind to the server.
* Other, saver, authentcation methods are provided later
* @param dn the distiguished name to bind as
* @param passwd cleartext password to use
*/
LDAPMessageQueue* bind(const std::string& dn="", const std::string& passwd="",
const LDAPConstraints *cons=0);
/** Performing a search on a directory tree.
*
* Use the search method to perform a search on the LDAP-Directory
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param base The distinguished name of the starting point for the
* search operation
* @param scope The scope of the search. Possible values: <BR>
* LDAPAsynConnection::SEARCH_BASE, <BR>
* LDAPAsynConnection::SEARCH_ONE, <BR>
* LDAPAsynConnection::SEARCH_SUB
* @param filter The std::string representation of a search filter to
* use with this operation
* @param attrsOnly true if only the attributes names (no values)
* should be returned
* @param cons A set of constraints that should be used with this
* request
*/
LDAPMessageQueue* search(const std::string& base="", int scope=0,
const std::string& filter="objectClass=*",
const StringList& attrs=StringList(),
bool attrsOnly=false,
const LDAPConstraints *cons=0);
/** Delete an entry from the directory
*
* This method sends a delete request to the server
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param dn Distinguished name of the entry that should be deleted
* @param cons A set of constraints that should be used with this
* request
*/
LDAPMessageQueue* del(const std::string& dn, const LDAPConstraints *cons=0);
/**
* Perform the COMPARE-operation on an attribute
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param dn Distinguished name of the entry for which the compare
* should be performed
* @param attr An Attribute (one (!) value) to use for the
* compare operation
* @param cons A set of constraints that should be used with this
* request
*/
LDAPMessageQueue* compare(const std::string& dn,
const LDAPAttribute& attr,
const LDAPConstraints *cons=0);
/** Add an entry to the directory
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param le The entry that will be added to the directory
*/
LDAPMessageQueue* add( const LDAPEntry* le,
const LDAPConstraints *const=0);
/** Apply modifications to attributes of an entry
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param dn Distiguished Name of the Entry to modify
* @param modlist A set of modification that should be applied
* to the Entry
* @param cons A set of constraints that should be used with this
* request
*/
LDAPMessageQueue* modify(const std::string& dn,
const LDAPModList *modlist,
const LDAPConstraints *cons=0);
/** modify the DN of an entry
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param dn DN to modify
* @param newRDN The new relative DN for the entry
* @param delOldRDN true=The old RDN will be removed from the
* attributes <BR>
* false=The old RDN will still be present in the
* attributes of the entry
* @param newParentDN The DN of the new parent entry of the entry
* 0 to keep the old one
*/
LDAPMessageQueue* rename(const std::string& dn,
const std::string& newRDN,
bool delOldRDN=false, const std::string& newParentDN="",
const LDAPConstraints* cons=0);
/** Perform a LDAP extended Operation
*
* @throws LDAPException If the Request could not be sent to the
* destination server, a LDAPException-object contains the
* error that occured.
* @param oid The dotted decimal representation of the extended
* Operation that should be performed
* @param value The data asociated with this operation
* @param cons A set of constraints that should be used with this
* request
*/
LDAPMessageQueue* extOperation(const std::string& oid,
const std::string& value="", const LDAPConstraints *cons=0);
/** End an outstanding request
*
* @param q All outstanding request related to this LDAPMessageQueue
* will be abandoned
*/
void abandon(LDAPMessageQueue *q);
/**
* Performs the UNBIND-operation on the destination server
*
* @throws LDAPException in any case of an error
*/
void unbind();
/**
* @returns The C-APIs LDAP-structure that is associated with the
* current connection
*/
LDAP* getSessionHandle() const ;
/**
* @returns The Hostname of the destination server of the
* connection.
*/
const std::string& getHost() const;
/**
* @returns The Port to which this connection is connecting to on
* the remote server.
*/
int getPort() const;
/** Change the default constraints of the connection
*
* @parameter cons cons New LDAPConstraints to use with the connection
*/
void setConstraints(LDAPConstraints *cons);
/** Get the default constraints of the connection
*
* @return Pointer to the LDAPConstraints-Object that is currently
* used with the Connection
*/
const LDAPConstraints* getConstraints() const;
/**
* This method is used internally for automatic referral chasing.
* It tries to bind to a destination server of the URLs of a
* referral.
*
* @throws LDAPException in any case of an error
* @param urls Contains a std::list of LDAP-Urls that indicate the
* destinations of a referral
* @param usedUrl After this method has successfully bind to one of
* the Destination URLs this parameter contains the URLs
* which was contacted.
* @param cons An LDAPConstraints-Object that should be used for
* the new connection. If this object contains a