// $OpenLDAP$
/*
* Copyright 2000-2021 The 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 "LDAPExtRequest.h"
#include "LDAPEntry.h"
#include "LDAPModDNRequest.h"
#include "LDAPModifyRequest.h"
#include "LDAPRequest.h"
#include "LDAPRebind.h"
#include "LDAPRebindAuth.h"
#include "LDAPSearchRequest.h"
#include <lber.h>
#include <sstream>
using namespace std;
LDAPAsynConnection::LDAPAsynConnection(const string& url, int port,
LDAPConstraints *cons ){
DEBUG(LDAP_DEBUG_CONSTRUCT,"LDAPAsynConnection::LDAPAsynConnection()"
<< endl);
DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER,
" URL:" << url << endl << " port:" << port << endl);
cur_session=0;
m_constr = 0;
// Is this an LDAP URI?
if ( url.find("://") == std::string::npos ) {
this->init(url, port);
} else {
this->initialize(url);
}
this->setConstraints(cons);
}
LDAPAsynConnection::~LDAPAsynConnection(){
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);
unbind();
m_uri.setScheme("ldap");
m_uri.setHost(hostname);
m_uri.setPort(port);
const char *ldapuri = m_uri.getURLString().c_str();
int ret = ldap_initialize(&cur_session, ldapuri);
if ( ret != LDAP_SUCCESS ) {
throw LDAPException( ret );
}
int opt=3;
ldap_set_option(cur_session, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
ldap_set_option(cur_session, LDAP_OPT_PROTOCOL_VERSION, &opt);
}
void LDAPAsynConnection::initialize(const std::string& uri){
unbind();
m_uri.setURLString(uri);
int ret = ldap_initialize(&cur_session, m_uri.getURLString().c_str());
if ( ret != LDAP_SUCCESS ) {
throw LDAPException( ret );
}
int opt=3;
ldap_set_option(cur_session, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
ldap_set_option(cur_session, LDAP_OPT_PROTOCOL_VERSION, &opt);
}
void LDAPAsynConnection::start_tls(){
int ret = ldap_start_tls_s( cur_session, NULL, NULL );
if( ret != LDAP_SUCCESS ) {
throw LDAPException(this);
}
}
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::saslBind(const std::string &mech,
const std::string &cred,
const LDAPConstraints *cons)
{
DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::saslBind()" << endl);
LDAPSaslBindRequest *req = new LDAPSaslBindRequest(mech, cred, this, cons);
try{
LDAPMessageQueue *ret = req->sendRequest();
return ret;
}catch(LDAPException e){
delete req;
throw;
}
}
LDAPMessageQueue* LDAPAsynConnection::saslInteractiveBind(
const std::string &mech,
int flags,
SaslInteractionHandler *sih,
const LDAPConstraints *cons)
{
DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::saslInteractiveBind"
<< std::endl);
LDAPSaslInteractiveBind *req =
new LDAPSaslInteractiveBind(mech, flags, sih, 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);
delete m_constr;
m_constr=cons;
}
const LDAPConstraints* LDAPAsynConnection::getConstraints() const {
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getConstraints()" << endl);
return m_constr;
}
TlsOptions LDAPAsynConnection::getTlsOptions() const {
return TlsOptions( cur_session );
}
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_uri.getHost();
}
int LDAPAsynConnection::getPort() const{
DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getPort()" << endl);
return m_uri.getPort();
}
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;
struct berval c_passwd = { 0, 0 };
if(dn != ""){
c_dn = dn.c_str();
}
if(passwd != ""){
c_passwd.bv_val = const_cast<char*>(passwd.c_str());
c_passwd.bv_len = passwd.size();
}
err = ldap_sasl_bind_s(tmpConn->getSessionHandle(), c_dn,
LDAP_SASL_SIMPLE, &c_passwd, NULL, NULL, NULL);
} else {
// Do anonymous bind
err = ldap_sasl_bind_s(tmpConn->getSessionHandle(),NULL,
LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL);
}
if( err == LDAP_SUCCESS ){
usedUrl=conUrl;
return tmpConn;
}else{
delete tmpConn;
tmpConn=0;
}
auth=0;
}
return 0;
}