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