8#include "ldapconnection.h"
11#include "kldap_config.h"
14#include "ldap_core_debug.h"
15#include <KLocalizedString>
19static const sasl_callback_t callbacks[] = {{SASL_CB_ECHOPROMPT,
nullptr,
nullptr},
20 {SASL_CB_NOECHOPROMPT,
nullptr,
nullptr},
21 {SASL_CB_GETREALM,
nullptr,
nullptr},
22 {SASL_CB_USER,
nullptr,
nullptr},
23 {SASL_CB_AUTHNAME,
nullptr,
nullptr},
24 {SASL_CB_PASS,
nullptr,
nullptr},
25 {SASL_CB_CANON_USER,
nullptr,
nullptr},
26 {SASL_CB_LIST_END,
nullptr,
nullptr}};
28static bool ldapoperation_sasl_initialized =
false;
35#include "w32-ldap-help.h"
38#ifndef LDAP_OPT_SUCCESS
39#define LDAP_OPT_SUCCESS 0
44using namespace KLDAPCore;
49 LdapConnectionPrivate();
58 sasl_conn_t *mSASLconn;
61LdapConnection::LdapConnectionPrivate::LdapConnectionPrivate()
64 if (!ldapoperation_sasl_initialized) {
65 sasl_client_init(
nullptr);
66 ldapoperation_sasl_initialized =
true;
71 : d(new LdapConnectionPrivate)
77 : d(new LdapConnectionPrivate)
84 : d(new LdapConnectionPrivate)
90LdapConnection::~LdapConnection()
97 d->mServer.setUrl(url);
112 return (
void *)d->mLDAP;
117 return (
void *)d->mSASLconn;
126 return i18n(
"No LDAP Support...");
133 str = sasl_errdetail(d->mSASLconn);
139 return d->mConnectionError;
146 return ldap_get_option(d->mLDAP, option, value);
152 return ldap_set_option(d->mLDAP, option, value);
159 ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err);
167 ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg);
176 qCDebug(LDAP_CORE_LOG) <<
"sizelimit:" << sizelimit;
177 if (
setOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
187 if (
getOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
196 qCDebug(LDAP_CORE_LOG) <<
"timelimit:" << timelimit;
197 if (
setOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
207 if (
getOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
221 int version = d->mServer.version();
222 int timeout = d->mServer.timeout();
224 url = d->mServer.security() == LdapServer::SSL ? QStringLiteral(
"ldaps") : QStringLiteral(
"ldap");
226 url += d->mServer.host();
229 qCDebug(LDAP_CORE_LOG) <<
"ldap url:" << url;
230#if HAVE_LDAP_INITIALIZE
233 d->mLDAP = ldap_init(d->mServer.host().toLatin1().data(), d->mServer.port());
240 if (ret != LDAP_SUCCESS) {
241 d->mConnectionError =
i18n(
"An error occurred during the connection initialization phase.");
245 qCDebug(LDAP_CORE_LOG) <<
"setting version to:" <<
version;
246 if (
setOption(LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
248 d->mConnectionError =
i18n(
"Cannot set protocol version to %1.", version);
253#if defined(LDAP_OPT_TIMEOUT)
254 qCDebug(LDAP_CORE_LOG) <<
"setting timeout to:" << timeout;
257 if (
setOption(LDAP_OPT_TIMEOUT, &timeout) != LDAP_OPT_SUCCESS) {
259 d->mConnectionError =
i18np(
"Cannot set timeout to %1 second.",
"Cannot set timeout to %1 seconds.", timeout);
266 qCDebug(LDAP_CORE_LOG) <<
"setting security to:" << d->mServer.security();
267 if (d->mServer.security() != LdapServer::None) {
268 bool initContext =
false;
269 if (d->mServer.tlsCACertFile().isEmpty() ==
false) {
270 if (
setOption(LDAP_OPT_X_TLS_CACERTFILE, d->mServer.tlsCACertFile().toUtf8().data()) != LDAP_OPT_SUCCESS) {
271 d->mConnectionError =
i18n(
"Could not set CA certificate file.");
277 if (d->mServer.tlsRequireCertificate() != LdapServer::TLSReqCertDefault) {
279 switch (d->mServer.tlsRequireCertificate()) {
280 case LdapServer::TLSReqCertAllow:
281 reqcert = LDAP_OPT_X_TLS_ALLOW;
283 case LdapServer::TLSReqCertDemand:
284 reqcert = LDAP_OPT_X_TLS_DEMAND;
286 case LdapServer::TLSReqCertHard:
287 reqcert = LDAP_OPT_X_TLS_HARD;
289 case LdapServer::TLSReqCertNever:
290 reqcert = LDAP_OPT_X_TLS_NEVER;
292 case LdapServer::TLSReqCertTry:
293 reqcert = LDAP_OPT_X_TLS_TRY;
296 d->mConnectionError =
i18n(
"Invalid TLS require certificate mode.");
300 if (
setOption(LDAP_OPT_X_TLS_REQUIRE_CERT, &reqcert) != LDAP_OPT_SUCCESS) {
301 d->mConnectionError =
i18n(
"Could not set TLS require certificate mode.");
309 if (
setOption(LDAP_OPT_X_TLS_NEWCTX, &isServer) != LDAP_OPT_SUCCESS) {
310 d->mConnectionError =
i18n(
"Could not initialize new TLS context.");
316 if (d->mServer.security() == LdapServer::TLS) {
317 qCDebug(LDAP_CORE_LOG) <<
"start TLS";
319#if HAVE_LDAP_START_TLS_S
320 if ((ret = ldap_start_tls_s(d->mLDAP,
nullptr,
nullptr)) != LDAP_SUCCESS) {
327 d->mConnectionError =
i18n(
"TLS support not available in the LDAP client libraries.");
332 qCDebug(LDAP_CORE_LOG) <<
"setting sizelimit to:" << d->mServer.sizeLimit();
333 if (d->mServer.sizeLimit()) {
337 d->mConnectionError =
i18n(
"Cannot set size limit.");
342 qCDebug(LDAP_CORE_LOG) <<
"setting timelimit to:" << d->mServer.timeLimit();
343 if (d->mServer.timeLimit()) {
347 d->mConnectionError =
i18n(
"Cannot set time limit.");
352 qCDebug(LDAP_CORE_LOG) <<
"initializing SASL client";
353 const int saslresult = sasl_client_new(
"ldap", d->mServer.host().toLatin1().constData(),
nullptr,
nullptr, callbacks, 0, &d->mSASLconn);
354 if (saslresult != SASL_OK) {
355 d->mConnectionError =
i18n(
"Cannot initialize the SASL client.");
356 return KLDAP_SASL_ERROR;
365#if HAVE_LDAP_UNBIND_EXT
366 ldap_unbind_ext(d->mLDAP,
nullptr,
nullptr);
368 ldap_unbind(d->mLDAP);
373 sasl_dispose(&d->mSASLconn);
374 d->mSASLconn =
nullptr;
376 qCDebug(LDAP_CORE_LOG) <<
"connection closed!";
383 qCritical() <<
"No LDAP support...";
389 qCritical() <<
"No LDAP support...";
395 qCritical() <<
"No LDAP support...";
401 qCritical() <<
"No LDAP support...";
407 qCritical() <<
"No LDAP support...";
413 qCritical() <<
"No LDAP support...";
419 qCritical() <<
"No LDAP support...";
425 qCritical() <<
"No LDAP support...";
431 d->mConnectionError =
i18n(
432 "LDAP support not compiled in. Please recompile libkldap with the "
433 "OpenLDAP (or compatible) client libraries, or complain to your "
434 "distribution packagers.");
435 qCritical() <<
"No LDAP support...";
441 qCritical() <<
"No LDAP support...";
This class represents a connection to an LDAP server.
QString ldapErrorString() const
Returns the LDAP error string from the last operation.
const LdapServer & server() const
Returns the connection parameters which was specified with an LDAP Url or a LdapServer structure.
int timeLimit() const
Returns the current time limit.
int connect()
Sets up the connection parameters with creating a handle to the LDAP server.
LdapConnection()
Constructs an LdapConnection object.
QString saslErrorString() const
Returns the SASL error string from the last SASL operation.
int getOption(int option, void *value) const
Gets an option from the connection.
void setUrl(const LdapUrl &url)
Sets the connection parameters via the specified url.
int sizeLimit() const
Returns the current size limit.
int setOption(int option, void *value)
Sets an option in the connection.
QString connectionError() const
Returns a translated error string if connect() failed.
void close()
Closes the LDAP connection.
bool setTimeLimit(int timelimit)
Sets the time limit for the connection.
void setServer(const LdapServer &server)
Sets the connection parameters via the specified server structure.
int ldapErrorCode() const
Returns the LDAP error code from the last operation.
void * saslHandle() const
Returns the opaqe sasl-library specific SASL object.
static QString errorString(int code)
Returns a translated error message from the specified LDAP error code.
void * handle() const
Returns the opaqe client-library specific LDAP object.
bool setSizeLimit(int sizelimit)
Sets the size limit for the connection.
A class that contains LDAP server connection settings.
A special url class for LDAP.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KDB_EXPORT KDbVersionInfo version()
const char * constData() const const
QString fromLocal8Bit(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
QString number(double n, char format, int precision)
QByteArray toLatin1() const const