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