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