File indexing completed on 2024-12-15 04:50:16
0001 /* 0002 This file is part of libkldap. 0003 SPDX-FileCopyrightText: 2004-2006 Szombathelyi György <gyurco@freemail.hu> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "ldapoperation.h" 0009 #include "kldap_config.h" 0010 0011 #include "ldap_core_debug.h" 0012 0013 #include <QElapsedTimer> 0014 0015 #include <cstdlib> 0016 0017 // for struct timeval 0018 #if HAVE_SYS_TIME_H 0019 #include <sys/time.h> 0020 #elif defined(_WIN32) 0021 #include <winsock2.h> 0022 #endif 0023 0024 #include <sasl/sasl.h> 0025 0026 #if LDAP_FOUND 0027 #if !HAVE_WINLDAP_H 0028 #include <lber.h> 0029 #include <ldap.h> 0030 #else 0031 #include "w32-ldap-help.h" 0032 #endif // HAVE_WINLDAP_H 0033 #endif // LDAP_FOUND 0034 0035 #include "ldapdefs.h" 0036 0037 using namespace KLDAPCore; 0038 0039 #if LDAP_FOUND 0040 static void extractControls(LdapControls &ctrls, LDAPControl **pctrls); 0041 #endif // LDAP_FOUND 0042 0043 /* 0044 Returns the difference between msecs and elapsed. If msecs is -1, 0045 however, -1 is returned. 0046 */ 0047 static int kldap_timeout_value(int msecs, int elapsed) 0048 { 0049 if (msecs == -1) { 0050 return -1; 0051 } 0052 0053 int timeout = msecs - elapsed; 0054 return timeout < 0 ? 0 : timeout; 0055 } 0056 0057 class Q_DECL_HIDDEN LdapOperation::LdapOperationPrivate 0058 { 0059 public: 0060 LdapOperationPrivate(); 0061 ~LdapOperationPrivate(); 0062 #if LDAP_FOUND 0063 int processResult(int rescode, LDAPMessage *msg); 0064 int bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async); 0065 #endif 0066 LdapControls mClientCtrls, mServerCtrls, mControls; 0067 LdapObject mObject; 0068 QByteArray mExtOid, mExtData; 0069 QByteArray mServerCred; 0070 QString mMatchedDn; 0071 QList<QByteArray> mReferrals; 0072 0073 LdapConnection *mConnection = nullptr; 0074 }; 0075 0076 LdapOperation::LdapOperation() 0077 : d(new LdapOperationPrivate) 0078 { 0079 d->mConnection = nullptr; 0080 } 0081 0082 LdapOperation::LdapOperation(LdapConnection &conn) 0083 : d(new LdapOperationPrivate) 0084 { 0085 setConnection(conn); 0086 } 0087 0088 LdapOperation::~LdapOperation() = default; 0089 0090 void LdapOperation::setConnection(LdapConnection &conn) 0091 { 0092 d->mConnection = &conn; 0093 } 0094 0095 LdapConnection &LdapOperation::connection() 0096 { 0097 return *d->mConnection; 0098 } 0099 0100 void LdapOperation::setClientControls(const LdapControls &ctrls) 0101 { 0102 d->mClientCtrls = ctrls; 0103 } 0104 0105 void LdapOperation::setServerControls(const LdapControls &ctrls) 0106 { 0107 d->mServerCtrls = ctrls; 0108 } 0109 0110 LdapControls LdapOperation::clientControls() const 0111 { 0112 return d->mClientCtrls; 0113 } 0114 0115 LdapControls LdapOperation::serverControls() const 0116 { 0117 return d->mServerCtrls; 0118 } 0119 0120 LdapObject LdapOperation::object() const 0121 { 0122 return d->mObject; 0123 } 0124 0125 LdapControls LdapOperation::controls() const 0126 { 0127 return d->mControls; 0128 } 0129 0130 QByteArray LdapOperation::extendedOid() const 0131 { 0132 return d->mExtOid; 0133 } 0134 0135 QByteArray LdapOperation::extendedData() const 0136 { 0137 return d->mExtData; 0138 } 0139 0140 QString LdapOperation::matchedDn() const 0141 { 0142 return d->mMatchedDn; 0143 } 0144 0145 QList<QByteArray> LdapOperation::referrals() const 0146 { 0147 return d->mReferrals; 0148 } 0149 0150 QByteArray LdapOperation::serverCred() const 0151 { 0152 return d->mServerCred; 0153 } 0154 0155 LdapOperation::LdapOperationPrivate::LdapOperationPrivate() = default; 0156 0157 LdapOperation::LdapOperationPrivate::~LdapOperationPrivate() = default; 0158 0159 #if LDAP_FOUND 0160 0161 static int kldap_sasl_interact(sasl_interact_t *interact, LdapOperation::SASL_Data *data) 0162 { 0163 if (data->proc) { 0164 for (; interact->id != SASL_CB_LIST_END; interact++) { 0165 switch (interact->id) { 0166 case SASL_CB_GETREALM: 0167 data->creds.fields |= LdapOperation::SASL_Realm; 0168 break; 0169 case SASL_CB_AUTHNAME: 0170 data->creds.fields |= LdapOperation::SASL_Authname; 0171 break; 0172 case SASL_CB_PASS: 0173 data->creds.fields |= LdapOperation::SASL_Password; 0174 break; 0175 case SASL_CB_USER: 0176 data->creds.fields |= LdapOperation::SASL_Authzid; 0177 break; 0178 } 0179 } 0180 int retval; 0181 if ((retval = data->proc(data->creds, data->data))) { 0182 return retval; 0183 } 0184 } 0185 0186 QString value; 0187 0188 while (interact->id != SASL_CB_LIST_END) { 0189 value.clear(); 0190 switch (interact->id) { 0191 case SASL_CB_GETREALM: 0192 value = data->creds.realm; 0193 qCDebug(LDAP_LOG) << "SASL_REALM=" << value; 0194 break; 0195 case SASL_CB_AUTHNAME: 0196 value = data->creds.authname; 0197 qCDebug(LDAP_LOG) << "SASL_AUTHNAME=" << value; 0198 break; 0199 case SASL_CB_PASS: 0200 value = data->creds.password; 0201 qCDebug(LDAP_LOG) << "SASL_PASSWD=[hidden]"; 0202 break; 0203 case SASL_CB_USER: 0204 value = data->creds.authzid; 0205 qCDebug(LDAP_LOG) << "SASL_AUTHZID=" << value; 0206 break; 0207 } 0208 if (value.isEmpty()) { 0209 interact->result = nullptr; 0210 interact->len = 0; 0211 } else { 0212 interact->result = strdup(value.toUtf8().constData()); 0213 interact->len = strlen((const char *)interact->result); 0214 } 0215 interact++; 0216 } 0217 return KLDAP_SUCCESS; 0218 } 0219 0220 int LdapOperation::LdapOperationPrivate::bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async) 0221 { 0222 Q_ASSERT(mConnection); 0223 LDAP *ld = (LDAP *)mConnection->handle(); 0224 LdapServer server; 0225 server = mConnection->server(); 0226 0227 int ret; 0228 0229 if (server.auth() == LdapServer::SASL) { 0230 #if !HAVE_WINLDAP_H 0231 auto saslconn = (sasl_conn_t *)mConnection->saslHandle(); 0232 sasl_interact_t *client_interact = nullptr; 0233 const char *out = nullptr; 0234 uint outlen; 0235 const char *mechusing = nullptr; 0236 struct berval ccred; 0237 struct berval *scred; 0238 int saslresult; 0239 QByteArray sdata = creds; 0240 0241 QString mech = server.mech(); 0242 if (mech.isEmpty()) { 0243 mech = QStringLiteral("DIGEST-MD5"); 0244 } 0245 0246 SASL_Data sasldata; 0247 sasldata.proc = saslproc; 0248 sasldata.data = data; 0249 sasldata.creds.fields = 0; 0250 sasldata.creds.realm = server.realm(); 0251 sasldata.creds.authname = server.user(); 0252 sasldata.creds.authzid = server.bindDn(); 0253 sasldata.creds.password = server.password(); 0254 0255 do { 0256 if (sdata.isEmpty()) { 0257 do { 0258 saslresult = sasl_client_start(saslconn, mech.toLatin1().constData(), &client_interact, &out, &outlen, &mechusing); 0259 0260 if (saslresult == SASL_INTERACT) { 0261 if (kldap_sasl_interact(client_interact, &sasldata) != KLDAP_SUCCESS) { 0262 return KLDAP_SASL_ERROR; 0263 } 0264 } 0265 qCDebug(LDAP_LOG) << "sasl_client_start mech: " << mechusing << " outlen " << outlen << " result: " << saslresult; 0266 } while (saslresult == SASL_INTERACT); 0267 if (saslresult != SASL_CONTINUE && saslresult != SASL_OK) { 0268 return KLDAP_SASL_ERROR; 0269 } 0270 } else { 0271 qCDebug(LDAP_LOG) << "sasl_client_step"; 0272 do { 0273 saslresult = sasl_client_step(saslconn, sdata.data(), sdata.size(), &client_interact, &out, &outlen); 0274 if (saslresult == SASL_INTERACT) { 0275 if (kldap_sasl_interact(client_interact, &sasldata) != KLDAP_SUCCESS) { 0276 return KLDAP_SASL_ERROR; 0277 } 0278 } 0279 } while (saslresult == SASL_INTERACT); 0280 qCDebug(LDAP_LOG) << "sasl_client_step result" << saslresult; 0281 if (saslresult != SASL_CONTINUE && saslresult != SASL_OK) { 0282 return KLDAP_SASL_ERROR; 0283 } 0284 } 0285 0286 ccred.bv_val = (char *)out; 0287 ccred.bv_len = outlen; 0288 0289 if (async) { 0290 qCDebug(LDAP_LOG) << "ldap_sasl_bind"; 0291 int msgid; 0292 ret = ldap_sasl_bind(ld, server.bindDn().toUtf8().constData(), mech.toLatin1().constData(), &ccred, nullptr, nullptr, &msgid); 0293 if (ret == 0) { 0294 ret = msgid; 0295 } 0296 qCDebug(LDAP_LOG) << "ldap_sasl_bind msgid" << ret; 0297 } else { 0298 qCDebug(LDAP_LOG) << "ldap_sasl_bind_s"; 0299 ret = ldap_sasl_bind_s(ld, server.bindDn().toUtf8().constData(), mech.toLatin1().constData(), &ccred, nullptr, nullptr, &scred); 0300 qCDebug(LDAP_LOG) << "ldap_sasl_bind_s ret" << ret; 0301 if (scred) { 0302 sdata = QByteArray(scred->bv_val, scred->bv_len); 0303 } else { 0304 sdata = QByteArray(); 0305 } 0306 } 0307 } while (!async && ret == KLDAP_SASL_BIND_IN_PROGRESS); 0308 #else 0309 qCritical() << "SASL authentication is not available " 0310 << "(re-compile kldap with cyrus-sasl and OpenLDAP development)."; 0311 return KLDAP_SASL_ERROR; 0312 #endif 0313 } else { // simple auth 0314 QByteArray bindname; 0315 QByteArray pass; 0316 struct berval ccred; 0317 if (server.auth() == LdapServer::Simple) { 0318 bindname = server.bindDn().toUtf8(); 0319 pass = server.password().toUtf8(); 0320 } 0321 ccred.bv_val = pass.data(); 0322 ccred.bv_len = pass.size(); 0323 qCDebug(LDAP_LOG) << "binding to server, bindname: " << bindname << " password: *****"; 0324 0325 if (async) { 0326 qCDebug(LDAP_LOG) << "ldap_sasl_bind (simple)"; 0327 #if !HAVE_WINLDAP_H 0328 int msgid = 0; 0329 ret = ldap_sasl_bind(ld, bindname.data(), nullptr, &ccred, nullptr, nullptr, &msgid); 0330 if (ret == 0) { 0331 ret = msgid; 0332 } 0333 #else 0334 ret = ldap_simple_bind(ld, bindname.data(), pass.data()); 0335 #endif 0336 } else { 0337 qCDebug(LDAP_LOG) << "ldap_sasl_bind_s (simple)"; 0338 #if !HAVE_WINLDAP_H 0339 ret = ldap_sasl_bind_s(ld, bindname.data(), nullptr, &ccred, nullptr, nullptr, nullptr); 0340 #else 0341 ret = ldap_simple_bind_s(ld, bindname.data(), pass.data()); 0342 #endif 0343 } 0344 } 0345 return ret; 0346 } 0347 0348 int LdapOperation::LdapOperationPrivate::processResult(int rescode, LDAPMessage *msg) 0349 { 0350 // qCDebug(LDAP_LOG); 0351 int retval; 0352 LDAP *ld = (LDAP *)mConnection->handle(); 0353 0354 qCDebug(LDAP_LOG) << "rescode: " << rescode; 0355 switch (rescode) { 0356 case RES_SEARCH_ENTRY: { 0357 // qCDebug(LDAP_LOG) << "Found search entry"; 0358 mObject.clear(); 0359 LdapAttrMap attrs; 0360 char *name; 0361 struct berval **bvals; 0362 BerElement *entry; 0363 LdapAttrValue values; 0364 0365 char *dn = ldap_get_dn(ld, msg); 0366 mObject.setDn(QString::fromUtf8(dn)); 0367 ldap_memfree(dn); 0368 0369 // iterate over the attributes 0370 name = ldap_first_attribute(ld, msg, &entry); 0371 while (name != nullptr) { 0372 // print the values 0373 bvals = ldap_get_values_len(ld, msg, name); 0374 if (bvals) { 0375 for (int i = 0; bvals[i] != nullptr; i++) { 0376 char *val = bvals[i]->bv_val; 0377 unsigned long len = bvals[i]->bv_len; 0378 values.append(QByteArray(val, len)); 0379 } 0380 ldap_value_free_len(bvals); 0381 } 0382 attrs[QString::fromLatin1(name)] = values; 0383 values.clear(); 0384 ldap_memfree(name); 0385 0386 // next attribute 0387 name = ldap_next_attribute(ld, msg, entry); 0388 } 0389 ber_free(entry, 0); 0390 mObject.setAttributes(attrs); 0391 break; 0392 } 0393 case RES_SEARCH_REFERENCE: 0394 // Will only get this if following references is disabled. ignore it 0395 rescode = 0; 0396 break; 0397 case RES_EXTENDED: { 0398 char *retoid; 0399 struct berval *retdata; 0400 retval = ldap_parse_extended_result(ld, msg, &retoid, &retdata, 0); 0401 if (retval != KLDAP_SUCCESS) { 0402 ldap_msgfree(msg); 0403 return -1; 0404 } 0405 mExtOid = retoid ? QByteArray(retoid) : QByteArray(); 0406 mExtData = retdata ? QByteArray(retdata->bv_val, retdata->bv_len) : QByteArray(); 0407 ldap_memfree(retoid); 0408 ber_bvfree(retdata); 0409 break; 0410 } 0411 case RES_BIND: { 0412 struct berval *servercred = nullptr; 0413 #if !HAVE_WINLDAP_H 0414 // FIXME: Error handling Winldap does not have ldap_parse_sasl_bind_result 0415 retval = ldap_parse_sasl_bind_result(ld, msg, &servercred, 0); 0416 #else 0417 retval = KLDAP_SUCCESS; 0418 #endif 0419 if (retval != KLDAP_SUCCESS && retval != KLDAP_SASL_BIND_IN_PROGRESS) { 0420 qCDebug(LDAP_LOG) << "RES_BIND error: " << retval; 0421 ldap_msgfree(msg); 0422 return -1; 0423 } 0424 qCDebug(LDAP_LOG) << "RES_BIND rescode" << rescode << "retval:" << retval; 0425 if (servercred) { 0426 mServerCred = QByteArray(servercred->bv_val, servercred->bv_len); 0427 ber_bvfree(servercred); 0428 } else { 0429 mServerCred = QByteArray(); 0430 } 0431 break; 0432 } 0433 default: { 0434 LDAPControl **serverctrls = nullptr; 0435 char *matcheddn = nullptr; 0436 char *errmsg = nullptr; 0437 char **referralsp; 0438 int errcodep; 0439 retval = ldap_parse_result(ld, msg, &errcodep, &matcheddn, &errmsg, &referralsp, &serverctrls, 0); 0440 qCDebug(LDAP_LOG) << "rescode" << rescode << "retval:" << retval << "matcheddn:" << matcheddn << "errcode:" << errcodep << "errmsg:" << errmsg; 0441 if (retval != KLDAP_SUCCESS) { 0442 ldap_msgfree(msg); 0443 return -1; 0444 } 0445 mControls.clear(); 0446 if (serverctrls) { 0447 extractControls(mControls, serverctrls); 0448 ldap_controls_free(serverctrls); 0449 } 0450 mReferrals.clear(); 0451 if (referralsp) { 0452 char **tmp = referralsp; 0453 while (*tmp) { 0454 mReferrals.append(QByteArray(*tmp)); 0455 ldap_memfree(*tmp); 0456 tmp++; 0457 } 0458 ldap_memfree((char *)referralsp); 0459 } 0460 mMatchedDn.clear(); 0461 if (matcheddn) { 0462 mMatchedDn = QString::fromUtf8(matcheddn); 0463 ldap_memfree(matcheddn); 0464 } 0465 if (errmsg) { 0466 ldap_memfree(errmsg); 0467 } 0468 } 0469 } 0470 0471 ldap_msgfree(msg); 0472 0473 return rescode; 0474 } 0475 0476 static void addModOp(LDAPMod ***pmods, int mod_type, const QString &attr, const QByteArray *value = nullptr) 0477 { 0478 // qCDebug(LDAP_LOG) << "type:" << mod_type << "attr:" << attr << 0479 // "value:" << QString::fromUtf8(value,value.size()) << 0480 // "size:" << value.size(); 0481 LDAPMod **mods; 0482 0483 mods = *pmods; 0484 0485 uint i = 0; 0486 0487 if (mods == nullptr) { 0488 mods = (LDAPMod **)malloc(2 * sizeof(LDAPMod *)); 0489 mods[0] = (LDAPMod *)malloc(sizeof(LDAPMod)); 0490 mods[1] = nullptr; 0491 memset(mods[0], 0, sizeof(LDAPMod)); 0492 } else { 0493 while (mods[i] != nullptr && (strcmp(attr.toUtf8().constData(), mods[i]->mod_type) != 0 || (mods[i]->mod_op & ~LDAP_MOD_BVALUES) != mod_type)) { 0494 i++; 0495 } 0496 0497 if (mods[i] == nullptr) { 0498 mods = (LDAPMod **)realloc(mods, (i + 2) * sizeof(LDAPMod *)); 0499 if (mods == nullptr) { 0500 qCritical() << "addModOp: realloc"; 0501 return; 0502 } 0503 mods[i + 1] = nullptr; 0504 mods[i] = (LDAPMod *)malloc(sizeof(LDAPMod)); 0505 memset(mods[i], 0, sizeof(LDAPMod)); 0506 } 0507 } 0508 0509 mods[i]->mod_op = mod_type | LDAP_MOD_BVALUES; 0510 if (mods[i]->mod_type == nullptr) { 0511 mods[i]->mod_type = strdup(attr.toUtf8().constData()); 0512 } 0513 0514 *pmods = mods; 0515 0516 if (value == nullptr) { 0517 return; 0518 } 0519 0520 int vallen = value->size(); 0521 BerValue *berval; 0522 berval = (BerValue *)malloc(sizeof(BerValue)); 0523 berval->bv_len = vallen; 0524 if (vallen > 0) { 0525 berval->bv_val = (char *)malloc(vallen); 0526 memcpy(berval->bv_val, value->data(), vallen); 0527 } else { 0528 berval->bv_val = nullptr; 0529 } 0530 0531 if (mods[i]->mod_vals.modv_bvals == nullptr) { 0532 mods[i]->mod_vals.modv_bvals = (BerValue **)malloc(sizeof(BerValue *) * 2); 0533 mods[i]->mod_vals.modv_bvals[0] = berval; 0534 mods[i]->mod_vals.modv_bvals[1] = nullptr; 0535 // qCDebug(LDAP_LOG) << "new bervalue struct" << attr << value; 0536 } else { 0537 uint j = 0; 0538 while (mods[i]->mod_vals.modv_bvals[j] != nullptr) { 0539 j++; 0540 } 0541 mods[i]->mod_vals.modv_bvals = (BerValue **)realloc(mods[i]->mod_vals.modv_bvals, (j + 2) * sizeof(BerValue *)); 0542 if (mods[i]->mod_vals.modv_bvals == nullptr) { 0543 qCritical() << "addModOp: realloc"; 0544 free(berval); 0545 return; 0546 } 0547 mods[i]->mod_vals.modv_bvals[j] = berval; 0548 mods[i]->mod_vals.modv_bvals[j + 1] = nullptr; 0549 qCDebug(LDAP_LOG) << j << ". new bervalue"; 0550 } 0551 } 0552 0553 static void addControlOp(LDAPControl ***pctrls, const QString &oid, const QByteArray &value, bool critical) 0554 { 0555 LDAPControl **ctrls; 0556 auto ctrl = (LDAPControl *)malloc(sizeof(LDAPControl)); 0557 0558 ctrls = *pctrls; 0559 0560 qCDebug(LDAP_LOG) << "oid:'" << oid << "' val: '" << value << "'"; 0561 int vallen = value.size(); 0562 ctrl->ldctl_value.bv_len = vallen; 0563 if (vallen) { 0564 ctrl->ldctl_value.bv_val = (char *)malloc(vallen); 0565 memcpy(ctrl->ldctl_value.bv_val, value.data(), vallen); 0566 } else { 0567 ctrl->ldctl_value.bv_val = nullptr; 0568 } 0569 ctrl->ldctl_iscritical = critical; 0570 ctrl->ldctl_oid = strdup(oid.toUtf8().constData()); 0571 0572 uint i = 0; 0573 0574 if (ctrls == nullptr) { 0575 ctrls = (LDAPControl **)malloc(2 * sizeof(LDAPControl *)); 0576 ctrls[0] = nullptr; 0577 ctrls[1] = nullptr; 0578 } else { 0579 while (ctrls[i] != nullptr) { 0580 i++; 0581 } 0582 ctrls[i + 1] = nullptr; 0583 ctrls = (LDAPControl **)realloc(ctrls, (i + 2) * sizeof(LDAPControl *)); 0584 } 0585 ctrls[i] = ctrl; 0586 *pctrls = ctrls; 0587 } 0588 0589 static void createControls(LDAPControl ***pctrls, const LdapControls &ctrls) 0590 { 0591 for (int i = 0; i < ctrls.count(); ++i) { 0592 addControlOp(pctrls, ctrls[i].oid(), ctrls[i].value(), ctrls[i].critical()); 0593 } 0594 } 0595 0596 static void extractControls(LdapControls &ctrls, LDAPControl **pctrls) 0597 { 0598 LdapControl control; 0599 int i = 0; 0600 0601 while (pctrls[i]) { 0602 LDAPControl *ctrl = pctrls[i]; 0603 control.setOid(QString::fromUtf8(ctrl->ldctl_oid)); 0604 control.setValue(QByteArray(ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len)); 0605 control.setCritical(ctrl->ldctl_iscritical); 0606 ctrls.append(control); 0607 i++; 0608 } 0609 } 0610 0611 int LdapOperation::bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data) 0612 { 0613 return d->bind(creds, saslproc, data, true); 0614 } 0615 0616 int LdapOperation::bind_s(SASL_Callback_Proc *saslproc, void *data) 0617 { 0618 return d->bind(QByteArray(), saslproc, data, false); 0619 } 0620 0621 int LdapOperation::search(const LdapDN &base, LdapUrl::Scope scope, const QString &filter, const QStringList &attributes) 0622 { 0623 Q_ASSERT(d->mConnection); 0624 LDAP *ld = (LDAP *)d->mConnection->handle(); 0625 0626 char **attrs = nullptr; 0627 int msgid; 0628 0629 LDAPControl **serverctrls = nullptr; 0630 LDAPControl **clientctrls = nullptr; 0631 createControls(&serverctrls, d->mServerCtrls); 0632 createControls(&serverctrls, d->mClientCtrls); 0633 0634 int count = attributes.count(); 0635 if (count > 0) { 0636 attrs = static_cast<char **>(malloc((count + 1) * sizeof(char *))); 0637 for (int i = 0; i < count; i++) { 0638 attrs[i] = strdup(attributes.at(i).toUtf8().constData()); 0639 } 0640 attrs[count] = nullptr; 0641 } 0642 0643 int lscope = LDAP_SCOPE_BASE; 0644 switch (scope) { 0645 case LdapUrl::Base: 0646 lscope = LDAP_SCOPE_BASE; 0647 break; 0648 case LdapUrl::One: 0649 lscope = LDAP_SCOPE_ONELEVEL; 0650 break; 0651 case LdapUrl::Sub: 0652 lscope = LDAP_SCOPE_SUBTREE; 0653 break; 0654 } 0655 0656 qCDebug(LDAP_LOG) << "asyncSearch() base=\"" << base.toString() << "\" scope=" << (int)scope << "filter=\"" << filter << "\" attrs=" << attributes; 0657 int retval = ldap_search_ext(ld, 0658 base.toString().toUtf8().data(), 0659 lscope, 0660 filter.isEmpty() ? QByteArray("objectClass=*").data() : filter.toUtf8().data(), 0661 attrs, 0662 0, 0663 serverctrls, 0664 clientctrls, 0665 nullptr, 0666 d->mConnection->sizeLimit(), 0667 &msgid); 0668 0669 ldap_controls_free(serverctrls); 0670 ldap_controls_free(clientctrls); 0671 0672 // free the attributes list again 0673 if (count > 0) { 0674 for (int i = 0; i < count; i++) { 0675 free(attrs[i]); 0676 } 0677 free(attrs); 0678 } 0679 0680 if (retval == 0) { 0681 retval = msgid; 0682 } 0683 return retval; 0684 } 0685 0686 int LdapOperation::add(const LdapObject &object) 0687 { 0688 Q_ASSERT(d->mConnection); 0689 LDAP *ld = (LDAP *)d->mConnection->handle(); 0690 0691 int msgid; 0692 LDAPMod **lmod = nullptr; 0693 0694 LDAPControl **serverctrls = nullptr; 0695 LDAPControl **clientctrls = nullptr; 0696 createControls(&serverctrls, d->mServerCtrls); 0697 createControls(&serverctrls, d->mClientCtrls); 0698 0699 for (LdapAttrMap::ConstIterator it = object.attributes().begin(); it != object.attributes().end(); ++it) { 0700 QString attr = it.key(); 0701 for (LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { 0702 addModOp(&lmod, 0, attr, &(*it2)); 0703 } 0704 } 0705 0706 int retval = ldap_add_ext(ld, object.dn().toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid); 0707 0708 ldap_controls_free(serverctrls); 0709 ldap_controls_free(clientctrls); 0710 ldap_mods_free(lmod, 1); 0711 if (retval == 0) { 0712 retval = msgid; 0713 } 0714 return retval; 0715 } 0716 0717 int LdapOperation::add_s(const LdapObject &object) 0718 { 0719 Q_ASSERT(d->mConnection); 0720 LDAP *ld = (LDAP *)d->mConnection->handle(); 0721 0722 LDAPMod **lmod = nullptr; 0723 0724 LDAPControl **serverctrls = nullptr; 0725 LDAPControl **clientctrls = nullptr; 0726 createControls(&serverctrls, d->mServerCtrls); 0727 createControls(&serverctrls, d->mClientCtrls); 0728 0729 for (LdapAttrMap::ConstIterator it = object.attributes().begin(); it != object.attributes().end(); ++it) { 0730 QString attr = it.key(); 0731 for (LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) { 0732 addModOp(&lmod, 0, attr, &(*it2)); 0733 } 0734 } 0735 0736 int retval = ldap_add_ext_s(ld, object.dn().toString().toUtf8().data(), lmod, serverctrls, clientctrls); 0737 0738 ldap_controls_free(serverctrls); 0739 ldap_controls_free(clientctrls); 0740 ldap_mods_free(lmod, 1); 0741 return retval; 0742 } 0743 0744 int LdapOperation::add(const LdapDN &dn, const ModOps &ops) 0745 { 0746 Q_ASSERT(d->mConnection); 0747 LDAP *ld = (LDAP *)d->mConnection->handle(); 0748 0749 int msgid; 0750 LDAPMod **lmod = nullptr; 0751 0752 LDAPControl **serverctrls = nullptr; 0753 LDAPControl **clientctrls = nullptr; 0754 createControls(&serverctrls, d->mServerCtrls); 0755 createControls(&serverctrls, d->mClientCtrls); 0756 0757 for (int i = 0; i < ops.count(); ++i) { 0758 for (int j = 0; j < ops[i].values.count(); ++j) { 0759 addModOp(&lmod, 0, ops[i].attr, &ops[i].values[j]); 0760 } 0761 } 0762 0763 int retval = ldap_add_ext(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid); 0764 0765 ldap_controls_free(serverctrls); 0766 ldap_controls_free(clientctrls); 0767 ldap_mods_free(lmod, 1); 0768 if (retval == 0) { 0769 retval = msgid; 0770 } 0771 return retval; 0772 } 0773 0774 int LdapOperation::add_s(const LdapDN &dn, const ModOps &ops) 0775 { 0776 Q_ASSERT(d->mConnection); 0777 LDAP *ld = (LDAP *)d->mConnection->handle(); 0778 0779 LDAPMod **lmod = nullptr; 0780 0781 LDAPControl **serverctrls = nullptr; 0782 LDAPControl **clientctrls = nullptr; 0783 createControls(&serverctrls, d->mServerCtrls); 0784 createControls(&serverctrls, d->mClientCtrls); 0785 0786 for (int i = 0; i < ops.count(); ++i) { 0787 for (int j = 0; j < ops[i].values.count(); ++j) { 0788 addModOp(&lmod, 0, ops[i].attr, &ops[i].values[j]); 0789 } 0790 } 0791 qCDebug(LDAP_LOG) << dn.toString(); 0792 int retval = ldap_add_ext_s(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls); 0793 0794 ldap_controls_free(serverctrls); 0795 ldap_controls_free(clientctrls); 0796 ldap_mods_free(lmod, 1); 0797 return retval; 0798 } 0799 0800 int LdapOperation::rename(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold) 0801 { 0802 Q_ASSERT(d->mConnection); 0803 LDAP *ld = (LDAP *)d->mConnection->handle(); 0804 0805 int msgid; 0806 0807 LDAPControl **serverctrls = nullptr; 0808 LDAPControl **clientctrls = nullptr; 0809 createControls(&serverctrls, d->mServerCtrls); 0810 createControls(&serverctrls, d->mClientCtrls); 0811 0812 int retval = ldap_rename(ld, 0813 dn.toString().toUtf8().data(), 0814 newRdn.toUtf8().data(), 0815 newSuperior.isEmpty() ? (char *)nullptr : newSuperior.toUtf8().data(), 0816 deleteold, 0817 serverctrls, 0818 clientctrls, 0819 &msgid); 0820 0821 ldap_controls_free(serverctrls); 0822 ldap_controls_free(clientctrls); 0823 0824 if (retval == 0) { 0825 retval = msgid; 0826 } 0827 return retval; 0828 } 0829 0830 int LdapOperation::rename_s(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold) 0831 { 0832 Q_ASSERT(d->mConnection); 0833 LDAP *ld = (LDAP *)d->mConnection->handle(); 0834 0835 LDAPControl **serverctrls = nullptr; 0836 LDAPControl **clientctrls = nullptr; 0837 createControls(&serverctrls, d->mServerCtrls); 0838 createControls(&serverctrls, d->mClientCtrls); 0839 0840 int retval = ldap_rename_s(ld, 0841 dn.toString().toUtf8().data(), 0842 newRdn.toUtf8().data(), 0843 newSuperior.isEmpty() ? (char *)nullptr : newSuperior.toUtf8().data(), 0844 deleteold, 0845 serverctrls, 0846 clientctrls); 0847 0848 ldap_controls_free(serverctrls); 0849 ldap_controls_free(clientctrls); 0850 0851 return retval; 0852 } 0853 0854 int LdapOperation::del(const LdapDN &dn) 0855 { 0856 Q_ASSERT(d->mConnection); 0857 LDAP *ld = (LDAP *)d->mConnection->handle(); 0858 0859 int msgid; 0860 0861 LDAPControl **serverctrls = nullptr; 0862 LDAPControl **clientctrls = nullptr; 0863 createControls(&serverctrls, d->mServerCtrls); 0864 createControls(&serverctrls, d->mClientCtrls); 0865 0866 int retval = ldap_delete_ext(ld, dn.toString().toUtf8().data(), serverctrls, clientctrls, &msgid); 0867 0868 ldap_controls_free(serverctrls); 0869 ldap_controls_free(clientctrls); 0870 0871 if (retval == 0) { 0872 retval = msgid; 0873 } 0874 return retval; 0875 } 0876 0877 int LdapOperation::del_s(const LdapDN &dn) 0878 { 0879 Q_ASSERT(d->mConnection); 0880 LDAP *ld = (LDAP *)d->mConnection->handle(); 0881 0882 LDAPControl **serverctrls = nullptr; 0883 LDAPControl **clientctrls = nullptr; 0884 createControls(&serverctrls, d->mServerCtrls); 0885 createControls(&serverctrls, d->mClientCtrls); 0886 0887 int retval = ldap_delete_ext_s(ld, dn.toString().toUtf8().data(), serverctrls, clientctrls); 0888 0889 ldap_controls_free(serverctrls); 0890 ldap_controls_free(clientctrls); 0891 0892 return retval; 0893 } 0894 0895 int LdapOperation::modify(const LdapDN &dn, const ModOps &ops) 0896 { 0897 Q_ASSERT(d->mConnection); 0898 LDAP *ld = (LDAP *)d->mConnection->handle(); 0899 0900 int msgid; 0901 LDAPMod **lmod = nullptr; 0902 0903 LDAPControl **serverctrls = nullptr; 0904 LDAPControl **clientctrls = nullptr; 0905 createControls(&serverctrls, d->mServerCtrls); 0906 createControls(&serverctrls, d->mClientCtrls); 0907 0908 for (int i = 0; i < ops.count(); ++i) { 0909 int mtype = 0; 0910 switch (ops[i].type) { 0911 case Mod_None: 0912 mtype = 0; 0913 break; 0914 case Mod_Add: 0915 mtype = LDAP_MOD_ADD; 0916 break; 0917 case Mod_Replace: 0918 mtype = LDAP_MOD_REPLACE; 0919 break; 0920 case Mod_Del: 0921 mtype = LDAP_MOD_DELETE; 0922 break; 0923 } 0924 addModOp(&lmod, mtype, ops[i].attr, nullptr); 0925 for (int j = 0; j < ops[i].values.count(); ++j) { 0926 addModOp(&lmod, mtype, ops[i].attr, &ops[i].values[j]); 0927 } 0928 } 0929 0930 int retval = ldap_modify_ext(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid); 0931 0932 ldap_controls_free(serverctrls); 0933 ldap_controls_free(clientctrls); 0934 ldap_mods_free(lmod, 1); 0935 if (retval == 0) { 0936 retval = msgid; 0937 } 0938 return retval; 0939 } 0940 0941 int LdapOperation::modify_s(const LdapDN &dn, const ModOps &ops) 0942 { 0943 Q_ASSERT(d->mConnection); 0944 LDAP *ld = (LDAP *)d->mConnection->handle(); 0945 0946 LDAPMod **lmod = nullptr; 0947 0948 LDAPControl **serverctrls = nullptr; 0949 LDAPControl **clientctrls = nullptr; 0950 createControls(&serverctrls, d->mServerCtrls); 0951 createControls(&serverctrls, d->mClientCtrls); 0952 0953 for (int i = 0; i < ops.count(); ++i) { 0954 int mtype = 0; 0955 switch (ops[i].type) { 0956 case Mod_None: 0957 mtype = 0; 0958 break; 0959 case Mod_Add: 0960 mtype = LDAP_MOD_ADD; 0961 break; 0962 case Mod_Replace: 0963 mtype = LDAP_MOD_REPLACE; 0964 break; 0965 case Mod_Del: 0966 mtype = LDAP_MOD_DELETE; 0967 break; 0968 } 0969 addModOp(&lmod, mtype, ops[i].attr, nullptr); 0970 for (int j = 0; j < ops[i].values.count(); ++j) { 0971 addModOp(&lmod, mtype, ops[i].attr, &ops[i].values[j]); 0972 } 0973 } 0974 0975 int retval = ldap_modify_ext_s(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls); 0976 0977 ldap_controls_free(serverctrls); 0978 ldap_controls_free(clientctrls); 0979 ldap_mods_free(lmod, 1); 0980 return retval; 0981 } 0982 0983 int LdapOperation::compare(const LdapDN &dn, const QString &attr, const QByteArray &value) 0984 { 0985 Q_ASSERT(d->mConnection); 0986 LDAP *ld = (LDAP *)d->mConnection->handle(); 0987 int msgid; 0988 0989 LDAPControl **serverctrls = nullptr; 0990 LDAPControl **clientctrls = nullptr; 0991 createControls(&serverctrls, d->mServerCtrls); 0992 createControls(&serverctrls, d->mClientCtrls); 0993 0994 int vallen = value.size(); 0995 BerValue *berval; 0996 berval = (BerValue *)malloc(sizeof(BerValue)); 0997 berval->bv_val = (char *)malloc(vallen); 0998 berval->bv_len = vallen; 0999 memcpy(berval->bv_val, value.data(), vallen); 1000 1001 int retval = ldap_compare_ext(ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval, serverctrls, clientctrls, &msgid); 1002 1003 ber_bvfree(berval); 1004 ldap_controls_free(serverctrls); 1005 ldap_controls_free(clientctrls); 1006 1007 if (retval == 0) { 1008 retval = msgid; 1009 } 1010 return retval; 1011 } 1012 1013 int LdapOperation::compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value) 1014 { 1015 Q_ASSERT(d->mConnection); 1016 LDAP *ld = (LDAP *)d->mConnection->handle(); 1017 1018 LDAPControl **serverctrls = nullptr; 1019 LDAPControl **clientctrls = nullptr; 1020 createControls(&serverctrls, d->mServerCtrls); 1021 createControls(&serverctrls, d->mClientCtrls); 1022 1023 int vallen = value.size(); 1024 BerValue *berval; 1025 berval = (BerValue *)malloc(sizeof(BerValue)); 1026 berval->bv_val = (char *)malloc(vallen); 1027 berval->bv_len = vallen; 1028 memcpy(berval->bv_val, value.data(), vallen); 1029 1030 int retval = ldap_compare_ext_s(ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval, serverctrls, clientctrls); 1031 1032 ber_bvfree(berval); 1033 ldap_controls_free(serverctrls); 1034 ldap_controls_free(clientctrls); 1035 1036 return retval; 1037 } 1038 1039 int LdapOperation::exop(const QString &oid, const QByteArray &data) 1040 { 1041 Q_ASSERT(d->mConnection); 1042 #if HAVE_LDAP_EXTENDED_OPERATION 1043 LDAP *ld = (LDAP *)d->mConnection->handle(); 1044 int msgid; 1045 1046 LDAPControl **serverctrls = nullptr; 1047 LDAPControl **clientctrls = nullptr; 1048 createControls(&serverctrls, d->mServerCtrls); 1049 createControls(&serverctrls, d->mClientCtrls); 1050 1051 int vallen = data.size(); 1052 BerValue *berval; 1053 berval = (BerValue *)malloc(sizeof(BerValue)); 1054 berval->bv_val = (char *)malloc(vallen); 1055 berval->bv_len = vallen; 1056 memcpy(berval->bv_val, data.data(), vallen); 1057 1058 int retval = ldap_extended_operation(ld, oid.toUtf8().data(), berval, serverctrls, clientctrls, &msgid); 1059 1060 ber_bvfree(berval); 1061 ldap_controls_free(serverctrls); 1062 ldap_controls_free(clientctrls); 1063 1064 if (retval == 0) { 1065 retval = msgid; 1066 } 1067 return retval; 1068 #else 1069 qCritical() << "Your LDAP client libraries don't support extended operations."; 1070 return -1; 1071 #endif 1072 } 1073 1074 int LdapOperation::exop_s(const QString &oid, const QByteArray &data) 1075 { 1076 #if HAVE_LDAP_EXTENDED_OPERATION_S 1077 Q_ASSERT(d->mConnection); 1078 LDAP *ld = (LDAP *)d->mConnection->handle(); 1079 BerValue *retdata; 1080 char *retoid; 1081 1082 LDAPControl **serverctrls = nullptr; 1083 LDAPControl **clientctrls = nullptr; 1084 createControls(&serverctrls, d->mServerCtrls); 1085 createControls(&serverctrls, d->mClientCtrls); 1086 1087 int vallen = data.size(); 1088 BerValue *berval; 1089 berval = (BerValue *)malloc(sizeof(BerValue)); 1090 berval->bv_val = (char *)malloc(vallen); 1091 berval->bv_len = vallen; 1092 memcpy(berval->bv_val, data.data(), vallen); 1093 1094 int retval = ldap_extended_operation_s(ld, oid.toUtf8().data(), berval, serverctrls, clientctrls, &retoid, &retdata); 1095 1096 ber_bvfree(berval); 1097 ber_bvfree(retdata); 1098 free(retoid); 1099 ldap_controls_free(serverctrls); 1100 ldap_controls_free(clientctrls); 1101 1102 return retval; 1103 #else 1104 qCritical() << "Your LDAP client libraries don't support extended operations."; 1105 return -1; 1106 #endif 1107 } 1108 1109 int LdapOperation::abandon(int id) 1110 { 1111 Q_ASSERT(d->mConnection); 1112 LDAP *ld = (LDAP *)d->mConnection->handle(); 1113 1114 LDAPControl **serverctrls = nullptr; 1115 LDAPControl **clientctrls = nullptr; 1116 createControls(&serverctrls, d->mServerCtrls); 1117 createControls(&serverctrls, d->mClientCtrls); 1118 1119 int retval = ldap_abandon_ext(ld, id, serverctrls, clientctrls); 1120 1121 ldap_controls_free(serverctrls); 1122 ldap_controls_free(clientctrls); 1123 1124 return retval; 1125 } 1126 1127 int LdapOperation::waitForResult(int id, int msecs) 1128 { 1129 Q_ASSERT(d->mConnection); 1130 LDAP *ld = (LDAP *)d->mConnection->handle(); 1131 1132 LDAPMessage *msg; 1133 1134 QElapsedTimer stopWatch; 1135 stopWatch.start(); 1136 int attempt(1); 1137 int timeout(0); 1138 1139 do { 1140 // Calculate the timeout value to use and assign it to a timeval structure 1141 // see man select (2) for details 1142 timeout = kldap_timeout_value(msecs, stopWatch.elapsed()); 1143 qCDebug(LDAP_LOG) << "(" << id << "," << msecs << "): Waiting" << timeout << "msecs for result. Attempt #" << attempt++; 1144 struct timeval tv; 1145 tv.tv_sec = timeout / 1000; 1146 tv.tv_usec = (timeout % 1000) * 1000; 1147 1148 // Wait for a result 1149 int rescode = ldap_result(ld, id, 0, timeout < 0 ? nullptr : &tv, &msg); 1150 if (rescode == -1) { 1151 return -1; 1152 } 1153 // Act on the return code 1154 if (rescode != 0) { 1155 // Some kind of result is available for processing 1156 return d->processResult(rescode, msg); 1157 } 1158 } while (msecs == -1 || stopWatch.elapsed() < msecs); 1159 1160 return 0; // timeout 1161 } 1162 1163 #else 1164 1165 int LdapOperation::bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data) 1166 { 1167 qCritical() << "LDAP support not compiled"; 1168 return -1; 1169 } 1170 1171 int LdapOperation::bind_s(SASL_Callback_Proc *saslproc, void *data) 1172 { 1173 qCritical() << "LDAP support not compiled"; 1174 return -1; 1175 } 1176 1177 int LdapOperation::search(const LdapDN &base, LdapUrl::Scope scope, const QString &filter, const QStringList &attributes) 1178 { 1179 qCritical() << "LDAP support not compiled"; 1180 return -1; 1181 } 1182 1183 int LdapOperation::add(const LdapObject &object) 1184 { 1185 qCritical() << "LDAP support not compiled"; 1186 return -1; 1187 } 1188 1189 int LdapOperation::add_s(const LdapObject &object) 1190 { 1191 qCritical() << "LDAP support not compiled"; 1192 return -1; 1193 } 1194 1195 int LdapOperation::add(const LdapDN &dn, const ModOps &ops) 1196 { 1197 qCritical() << "LDAP support not compiled"; 1198 return -1; 1199 } 1200 1201 int LdapOperation::add_s(const LdapDN &dn, const ModOps &ops) 1202 { 1203 qCritical() << "LDAP support not compiled"; 1204 return -1; 1205 } 1206 1207 int LdapOperation::rename(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold) 1208 { 1209 qCritical() << "LDAP support not compiled"; 1210 return -1; 1211 } 1212 1213 int LdapOperation::rename_s(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold) 1214 { 1215 qCritical() << "LDAP support not compiled"; 1216 return -1; 1217 } 1218 1219 int LdapOperation::del(const LdapDN &dn) 1220 { 1221 qCritical() << "LDAP support not compiled"; 1222 return -1; 1223 } 1224 1225 int LdapOperation::del_s(const LdapDN &dn) 1226 { 1227 qCritical() << "LDAP support not compiled"; 1228 return -1; 1229 } 1230 1231 int LdapOperation::modify(const LdapDN &dn, const ModOps &ops) 1232 { 1233 qCritical() << "LDAP support not compiled"; 1234 return -1; 1235 } 1236 1237 int LdapOperation::modify_s(const LdapDN &dn, const ModOps &ops) 1238 { 1239 qCritical() << "LDAP support not compiled"; 1240 return -1; 1241 } 1242 1243 int LdapOperation::compare(const LdapDN &dn, const QString &attr, const QByteArray &value) 1244 { 1245 qCritical() << "LDAP support not compiled"; 1246 return -1; 1247 } 1248 1249 int LdapOperation::exop(const QString &oid, const QByteArray &data) 1250 { 1251 qCritical() << "LDAP support not compiled"; 1252 return -1; 1253 } 1254 1255 int LdapOperation::compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value) 1256 { 1257 qCritical() << "LDAP support not compiled"; 1258 return -1; 1259 } 1260 1261 int LdapOperation::exop_s(const QString &oid, const QByteArray &data) 1262 { 1263 qCritical() << "LDAP support not compiled"; 1264 return -1; 1265 } 1266 1267 int LdapOperation::waitForResult(int id, int msecs) 1268 { 1269 qCritical() << "LDAP support not compiled"; 1270 return -1; 1271 } 1272 1273 int LdapOperation::abandon(int id) 1274 { 1275 qCritical() << "LDAP support not compiled"; 1276 return -1; 1277 } 1278 1279 #endif