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 
27 using namespace std;
28 
LDAPAsynConnection(const string & url,int port,LDAPConstraints * cons)29 LDAPAsynConnection::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 
~LDAPAsynConnection()46 LDAPAsynConnection::~LDAPAsynConnection(){
47 	unbind();
48 	delete m_constr;
49 }
50 
init(const string & hostname,int port)51 void 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 
initialize(const std::string & uri)73 void 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 
start_tls()86 void 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 
bind(const string & dn,const string & passwd,const LDAPConstraints * cons)93 LDAPMessageQueue* 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 
saslBind(const std::string & mech,const std::string & cred,const LDAPConstraints * cons)108 LDAPMessageQueue* 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 
saslInteractiveBind(const std::string & mech,int flags,SaslInteractionHandler * sih,const LDAPConstraints * cons)124 LDAPMessageQueue* 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 
search(const string & base,int scope,const string & filter,const StringList & attrs,bool attrsOnly,const LDAPConstraints * cons)143 LDAPMessageQueue* 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 
del(const string & dn,const LDAPConstraints * cons)163 LDAPMessageQueue* 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 
compare(const string & dn,const LDAPAttribute & attr,const LDAPConstraints * cons)177 LDAPMessageQueue* 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 
add(const LDAPEntry * le,const LDAPConstraints * cons)192 LDAPMessageQueue* 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 
modify(const string & dn,const LDAPModList * mod,const LDAPConstraints * cons)206 LDAPMessageQueue* 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 
rename(const string & dn,const string & newRDN,bool delOldRDN,const string & newParentDN,const LDAPConstraints * cons)220 LDAPMessageQueue* 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 
extOperation(const string & oid,const string & value,const LDAPConstraints * cons)240 LDAPMessageQueue* 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 
abandon(LDAPMessageQueue * q)255 void 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 
unbind()270 void 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 
setConstraints(LDAPConstraints * cons)285 void LDAPAsynConnection::setConstraints(LDAPConstraints *cons){
286     DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setConstraints()" << endl);
287 	delete m_constr;
288     m_constr=cons;
289 }
290 
getConstraints() const291 const LDAPConstraints* LDAPAsynConnection::getConstraints() const {
292     DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getConstraints()" << endl);
293     return m_constr;
294 }
295 
getTlsOptions() const296 TlsOptions LDAPAsynConnection::getTlsOptions() const {
297     return TlsOptions( cur_session );
298 }
299 
getSessionHandle() const300 LDAP* LDAPAsynConnection::getSessionHandle() const{
301     DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getSessionHandle()" << endl);
302     return cur_session;
303 }
304 
getHost() const305 const string& LDAPAsynConnection::getHost() const{
306     DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::setHost()" << endl);
307     return m_uri.getHost();
308 }
309 
getPort() const310 int LDAPAsynConnection::getPort() const{
311     DEBUG(LDAP_DEBUG_TRACE,"LDAPAsynConnection::getPort()" << endl);
312     return m_uri.getPort();
313 }
314 
referralConnect(const LDAPUrlList & urls,LDAPUrlList::const_iterator & usedUrl,const LDAPConstraints * cons) const315 LDAPAsynConnection* 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