1// $OpenLDAP$ 2/* 3 * Copyright 2000-2021 The OpenLDAP Foundation, All Rights Reserved. 4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file 5 */ 6 7 8#include "config.h" 9#include "debug.h" 10#include "LDAPAsynConnection.h" 11 12#include "LDAPAddRequest.h" 13#include "LDAPBindRequest.h" 14#include "LDAPCompareRequest.h" 15#include "LDAPDeleteRequest.h" 16#include "LDAPExtRequest.h" 17#include "LDAPEntry.h" 18#include "LDAPModDNRequest.h" 19#include "LDAPModifyRequest.h" 20#include "LDAPRequest.h" 21#include "LDAPRebind.h" 22#include "LDAPRebindAuth.h" 23#include "LDAPSearchRequest.h" 24#include <lber.h> 25#include <sstream> 26 27using namespace std; 28 29LDAPAsynConnection::LDAPAsynConnection(const string& url, int port, 30 LDAPConstraints *cons ){ 31 DEBUG(LDAP_DEBUG_CONSTRUCT,"LDAPAsynConnection::LDAPAsynConnection()" 32 << endl); 33 DEBUG(LDAP_DEBUG_CONSTRUCT | LDAP_DEBUG_PARAMETER, 34 " URL:" << url << endl << " port:" << port << endl); 35 cur_session=0; 36 m_constr = 0; 37 // Is this an LDAP URI? 38 if ( url.find("://") == std::string::npos ) { 39 this->init(url, port); 40 } else { 41 this->initialize(url); 42 } 43 this->setConstraints(cons); 44} 45 46LDAPAsynConnection::~LDAPAsynConnection(){ 47 unbind(); 48 delete m_constr; 49} 50 51void LDAPAsynConnection::init(const string& hostname, int port){ 52 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::init" << endl); 53 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, 54 " hostname:" << hostname << endl 55 << " port:" << port << endl); 56 57 unbind(); 58 59 m_uri.setScheme("ldap"); 60 m_uri.setHost(hostname); 61 m_uri.setPort(port); 62 63 const char *ldapuri = m_uri.getURLString().c_str(); 64 int ret = ldap_initialize(&cur_session, ldapuri); 65 if ( ret != LDAP_SUCCESS ) { 66 throw LDAPException( ret ); 67 } 68 int opt=3; 69 ldap_set_option(cur_session, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 70 ldap_set_option(cur_session, LDAP_OPT_PROTOCOL_VERSION, &opt); 71} 72 73void LDAPAsynConnection::initialize(const std::string& uri){ 74 unbind(); 75 76 m_uri.setURLString(uri); 77 int ret = ldap_initialize(&cur_session, m_uri.getURLString().c_str()); 78 if ( ret != LDAP_SUCCESS ) { 79 throw LDAPException( ret ); 80 } 81 int opt=3; 82 ldap_set_option(cur_session, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); 83 ldap_set_option(cur_session, LDAP_OPT_PROTOCOL_VERSION, &opt); 84} 85 86void LDAPAsynConnection::start_tls(){ 87 int ret = ldap_start_tls_s( cur_session, NULL, NULL ); 88 if( ret != LDAP_SUCCESS ) { 89 throw LDAPException(this); 90 } 91} 92 93LDAPMessageQueue* LDAPAsynConnection::bind(const string& dn, 94 const string& passwd, const LDAPConstraints *cons){ 95 DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::bind()" << endl); 96 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, " dn:" << dn << endl 97 << " passwd:" << passwd << endl); 98 LDAPBindRequest *req = new LDAPBindRequest(dn,passwd,this,cons); 99 try{ 100 LDAPMessageQueue *ret = req->sendRequest(); 101 return ret; 102 }catch(LDAPException e){ 103 delete req; 104 throw; 105 } 106} 107 108LDAPMessageQueue* LDAPAsynConnection::saslBind(const std::string &mech, 109 const std::string &cred, 110 const LDAPConstraints *cons) 111{ 112 DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::saslBind()" << endl); 113 LDAPSaslBindRequest *req = new LDAPSaslBindRequest(mech, cred, this, cons); 114 try{ 115 LDAPMessageQueue *ret = req->sendRequest(); 116 return ret; 117 }catch(LDAPException e){ 118 delete req; 119 throw; 120 } 121 122} 123 124LDAPMessageQueue* LDAPAsynConnection::saslInteractiveBind( 125 const std::string &mech, 126 int flags, 127 SaslInteractionHandler *sih, 128 const LDAPConstraints *cons) 129{ 130 DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::saslInteractiveBind" 131 << std::endl); 132 LDAPSaslInteractiveBind *req = 133 new LDAPSaslInteractiveBind(mech, flags, sih, this, cons); 134 try { 135 LDAPMessageQueue *ret = req->sendRequest(); 136 return ret; 137 }catch(LDAPException e){ 138 delete req; 139 throw; 140 } 141} 142 143LDAPMessageQueue* LDAPAsynConnection::search(const string& base,int scope, 144 const string& filter, 145 const StringList& attrs, 146 bool attrsOnly, 147 const LDAPConstraints *cons){ 148 DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::search()" << endl); 149 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER, " base:" << base << endl 150 << " scope:" << scope << endl 151 << " filter:" << filter << endl ); 152 LDAPSearchRequest *req = new LDAPSearchRequest(base, scope,filter, attrs, 153 attrsOnly, this, cons); 154 try{ 155 LDAPMessageQueue *ret = req->sendRequest(); 156 return ret; 157 }catch(LDAPException e){ 158 delete req; 159 throw; 160 } 161} 162 163LDAPMessageQueue* LDAPAsynConnection::del(const string& dn, 164 const LDAPConstraints *cons){ 165 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::del()" << endl); 166 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl); 167 LDAPDeleteRequest *req = new LDAPDeleteRequest(dn, this, cons); 168 try{ 169 LDAPMessageQueue *ret = req->sendRequest(); 170 return ret; 171 }catch(LDAPException e){ 172 delete req; 173 throw; 174 } 175} 176 177LDAPMessageQueue* LDAPAsynConnection::compare(const string& dn, 178 const LDAPAttribute& attr, const LDAPConstraints *cons){ 179 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::compare()" << endl); 180 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl 181 << " attr:" << attr << endl); 182 LDAPCompareRequest *req = new LDAPCompareRequest(dn, attr, this, cons); 183 try{ 184 LDAPMessageQueue *ret = req->sendRequest(); 185 return ret; 186 }catch(LDAPException e){ 187 delete req; 188 throw; 189 } 190} 191 192LDAPMessageQueue* LDAPAsynConnection::add( const LDAPEntry* le, 193 const LDAPConstraints *cons){ 194 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::add()" << endl); 195 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," entry:" << *le << endl); 196 LDAPAddRequest *req = new LDAPAddRequest(le, this, cons); 197 try{ 198 LDAPMessageQueue *ret = req->sendRequest(); 199 return ret; 200 }catch(LDAPException e){ 201 delete req; 202 throw; 203 } 204} 205 206LDAPMessageQueue* LDAPAsynConnection::modify(const string& dn, 207 const LDAPModList *mod, const LDAPConstraints *cons){ 208 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::modify()" << endl); 209 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl); 210 LDAPModifyRequest *req = new LDAPModifyRequest(dn, mod, this, cons); 211 try{ 212 LDAPMessageQueue *ret = req->sendRequest(); 213 return ret; 214 }catch(LDAPException e){ 215 delete req; 216 throw; 217 } 218} 219 220LDAPMessageQueue* LDAPAsynConnection::rename(const string& dn, 221 const string& newRDN, bool delOldRDN, const string& newParentDN, 222 const LDAPConstraints *cons ){ 223 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::rename()" << endl); 224 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," dn:" << dn << endl 225 << " newRDN:" << newRDN << endl 226 << " newParentDN:" << newParentDN << endl 227 << " delOldRDN:" << delOldRDN << endl); 228 LDAPModDNRequest *req = new LDAPModDNRequest(dn, newRDN, delOldRDN, 229 newParentDN, this, cons ); 230 try{ 231 LDAPMessageQueue *ret = req->sendRequest(); 232 return ret; 233 }catch(LDAPException e){ 234 delete req; 235 throw; 236 } 237} 238 239 240LDAPMessageQueue* LDAPAsynConnection::extOperation(const string& oid, 241 const string& value, const LDAPConstraints *cons ){ 242 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::extOperation()" << endl); 243 DEBUG(LDAP_DEBUG_TRACE | LDAP_DEBUG_PARAMETER," oid:" << oid << endl); 244 LDAPExtRequest *req = new LDAPExtRequest(oid, value, this,cons); 245 try{ 246 LDAPMessageQueue *ret = req->sendRequest(); 247 return ret; 248 }catch(LDAPException e){ 249 delete req; 250 throw; 251 } 252} 253 254 255void LDAPAsynConnection::abandon(LDAPMessageQueue *q){ 256 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::abandon()" << endl); 257 LDAPRequestStack *reqStack=q->getRequestStack(); 258 LDAPRequest *req; 259 while(! reqStack->empty()){ 260 req=reqStack->top(); 261 if (ldap_abandon_ext(cur_session, req->getMsgID(), 0, 0) 262 != LDAP_SUCCESS){ 263 throw LDAPException(this); 264 } 265 delete req; 266 reqStack->pop(); 267 } 268} 269 270void LDAPAsynConnection::unbind(){ 271 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::unbind()" << endl); 272 if(cur_session){ 273 LDAPControl** tmpSrvCtrls=m_constr->getSrvCtrlsArray(); 274 LDAPControl** tmpClCtrls=m_constr->getClCtrlsArray(); 275 int err=ldap_unbind_ext(cur_session, tmpSrvCtrls, tmpClCtrls); 276 cur_session=0; 277 LDAPControlSet::freeLDAPControlArray(tmpSrvCtrls); 278 LDAPControlSet::freeLDAPControlArray(tmpClCtrls); 279 if(err != LDAP_SUCCESS){ 280 throw LDAPException(err); 281 } 282 } 283} 284 285void LDAPAsynConnection::setConstraints(LDAPConstraints *cons){ 286 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setConstraints()" << endl); 287 delete m_constr; 288 m_constr=cons; 289} 290 291const LDAPConstraints* LDAPAsynConnection::getConstraints() const { 292 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getConstraints()" << endl); 293 return m_constr; 294} 295 296TlsOptions LDAPAsynConnection::getTlsOptions() const { 297 return TlsOptions( cur_session ); 298} 299 300LDAP* LDAPAsynConnection::getSessionHandle() const{ 301 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getSessionHandle()" << endl); 302 return cur_session; 303} 304 305const string& LDAPAsynConnection::getHost() const{ 306 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setHost()" << endl); 307 return m_uri.getHost(); 308} 309 310int LDAPAsynConnection::getPort() const{ 311 DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getPort()" << endl); 312 return m_uri.getPort(); 313} 314 315LDAPAsynConnection* LDAPAsynConnection::referralConnect( 316 const LDAPUrlList& urls, LDAPUrlList::const_iterator& usedUrl, 317 const LDAPConstraints* cons) const { 318 DEBUG(LDAP_DEBUG_TRACE, "LDAPAsynConnection::referralConnect()" << endl) 319 LDAPUrlList::const_iterator conUrl; 320 LDAPAsynConnection* tmpConn=0; 321 const LDAPRebind* rebind = cons->getReferralRebind(); 322 LDAPRebindAuth* auth = 0; 323 324 for(conUrl=urls.begin(); conUrl!=urls.end(); conUrl++){ 325 string host= conUrl->getHost(); 326 int port= conUrl->getPort(); 327 DEBUG(LDAP_DEBUG_TRACE," connecting to: " << host << ":" << 328 port << endl); 329 //Set the new connection's constraints-object ? 330 tmpConn=new LDAPAsynConnection(host.c_str(),port); 331 int err=0; 332 333 if(rebind){ 334 auth=rebind->getRebindAuth(host, port); 335 } 336 if(auth){ 337 string dn = auth->getDN(); 338 string passwd = auth->getPassword(); 339 const char* c_dn=0; 340 struct berval c_passwd = { 0, 0 }; 341 if(dn != ""){ 342 c_dn = dn.c_str(); 343 } 344 if(passwd != ""){ 345 c_passwd.bv_val = const_cast<char*>(passwd.c_str()); 346 c_passwd.bv_len = passwd.size(); 347 } 348 err = ldap_sasl_bind_s(tmpConn->getSessionHandle(), c_dn, 349 LDAP_SASL_SIMPLE, &c_passwd, NULL, NULL, NULL); 350 } else { 351 // Do anonymous bind 352 err = ldap_sasl_bind_s(tmpConn->getSessionHandle(),NULL, 353 LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL); 354 } 355 if( err == LDAP_SUCCESS ){ 356 usedUrl=conUrl; 357 return tmpConn; 358 }else{ 359 delete tmpConn; 360 tmpConn=0; 361 } 362 auth=0; 363 } 364 return 0; 365} 366 367