8#include "ldapconnection.h"
9#include "kldap_config.h"
12#include "ldap_core_debug.h"
13#include <KLocalizedString>
17static const sasl_callback_t callbacks[] = {{SASL_CB_ECHOPROMPT,
nullptr,
nullptr},
18 {SASL_CB_NOECHOPROMPT,
nullptr,
nullptr},
19 {SASL_CB_GETREALM,
nullptr,
nullptr},
20 {SASL_CB_USER,
nullptr,
nullptr},
21 {SASL_CB_AUTHNAME,
nullptr,
nullptr},
22 {SASL_CB_PASS,
nullptr,
nullptr},
23 {SASL_CB_CANON_USER,
nullptr,
nullptr},
24 {SASL_CB_LIST_END,
nullptr,
nullptr}};
26static bool ldapoperation_sasl_initialized =
false;
33#include "w32-ldap-help.h"
36#ifndef LDAP_OPT_SUCCESS
37#define LDAP_OPT_SUCCESS 0
42using namespace KLDAPCore;
47 LdapConnectionPrivate();
56 sasl_conn_t *mSASLconn;
59LdapConnection::LdapConnectionPrivate::LdapConnectionPrivate()
62 if (!ldapoperation_sasl_initialized) {
63 sasl_client_init(
nullptr);
64 ldapoperation_sasl_initialized =
true;
69 : d(new LdapConnectionPrivate)
75 : d(new LdapConnectionPrivate)
82 : d(new LdapConnectionPrivate)
88LdapConnection::~LdapConnection()
95 d->mServer.setUrl(url);
110 return (
void *)d->mLDAP;
115 return (
void *)d->mSASLconn;
124 return i18n(
"No LDAP Support...");
131 str = sasl_errdetail(d->mSASLconn);
137 return d->mConnectionError;
144 return ldap_get_option(d->mLDAP, option, value);
150 return ldap_set_option(d->mLDAP, option, value);
157 ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err);
165 ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg);
174 qCDebug(LDAP_LOG) <<
"sizelimit:" << sizelimit;
175 if (
setOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
185 if (
getOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
194 qCDebug(LDAP_LOG) <<
"timelimit:" << timelimit;
195 if (
setOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
205 if (
getOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
219 int version = d->mServer.version();
220 int timeout = d->mServer.timeout();
222 url = d->mServer.security() == LdapServer::SSL ? QStringLiteral(
"ldaps") : QStringLiteral(
"ldap");
224 url += d->mServer.host();
227 qCDebug(LDAP_LOG) <<
"ldap url:" << url;
228#if HAVE_LDAP_INITIALIZE
231 d->mLDAP = ldap_init(d->mServer.host().toLatin1().data(), d->mServer.port());
238 if (ret != LDAP_SUCCESS) {
239 d->mConnectionError =
i18n(
"An error occurred during the connection initialization phase.");
243 qCDebug(LDAP_LOG) <<
"setting version to:" <<
version;
244 if (
setOption(LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
246 d->mConnectionError =
i18n(
"Cannot set protocol version to %1.", version);
251#if defined(LDAP_OPT_TIMEOUT)
252 qCDebug(LDAP_LOG) <<
"setting timeout to:" << timeout;
255 if (
setOption(LDAP_OPT_TIMEOUT, &timeout) != LDAP_OPT_SUCCESS) {
257 d->mConnectionError =
i18np(
"Cannot set timeout to %1 second.",
"Cannot set timeout to %1 seconds.", timeout);
264 qCDebug(LDAP_LOG) <<
"setting security to:" << d->mServer.security();
265 if (d->mServer.security() != LdapServer::None) {
266 bool initContext =
false;
267 if (d->mServer.tlsCACertFile().isEmpty() ==
false) {
268 if (
setOption(LDAP_OPT_X_TLS_CACERTFILE, d->mServer.tlsCACertFile().toUtf8().data()) != LDAP_OPT_SUCCESS) {
269 d->mConnectionError =
i18n(
"Could not set CA certificate file.");
275 if (d->mServer.tlsRequireCertificate() != LdapServer::TLSReqCertDefault) {
277 switch (d->mServer.tlsRequireCertificate()) {
278 case LdapServer::TLSReqCertAllow:
279 reqcert = LDAP_OPT_X_TLS_ALLOW;
281 case LdapServer::TLSReqCertDemand:
282 reqcert = LDAP_OPT_X_TLS_DEMAND;
284 case LdapServer::TLSReqCertHard:
285 reqcert = LDAP_OPT_X_TLS_HARD;
287 case LdapServer::TLSReqCertNever:
288 reqcert = LDAP_OPT_X_TLS_NEVER;
290 case LdapServer::TLSReqCertTry:
291 reqcert = LDAP_OPT_X_TLS_TRY;
294 d->mConnectionError =
i18n(
"Invalid TLS require certificate mode.");
298 if (
setOption(LDAP_OPT_X_TLS_REQUIRE_CERT, &reqcert) != LDAP_OPT_SUCCESS) {
299 d->mConnectionError =
i18n(
"Could not set TLS require certificate mode.");
307 if (
setOption(LDAP_OPT_X_TLS_NEWCTX, &isServer) != LDAP_OPT_SUCCESS) {
308 d->mConnectionError =
i18n(
"Could not initialize new TLS context.");
314 if (d->mServer.security() == LdapServer::TLS) {
315 qCDebug(LDAP_LOG) <<
"start TLS";
317#if HAVE_LDAP_START_TLS_S
318 if ((ret = ldap_start_tls_s(d->mLDAP,
nullptr,
nullptr)) != LDAP_SUCCESS) {
325 d->mConnectionError =
i18n(
"TLS support not available in the LDAP client libraries.");
330 qCDebug(LDAP_LOG) <<
"setting sizelimit to:" << d->mServer.sizeLimit();
331 if (d->mServer.sizeLimit()) {
335 d->mConnectionError =
i18n(
"Cannot set size limit.");
340 qCDebug(LDAP_LOG) <<
"setting timelimit to:" << d->mServer.timeLimit();
341 if (d->mServer.timeLimit()) {
345 d->mConnectionError =
i18n(
"Cannot set time limit.");
350 qCDebug(LDAP_LOG) <<
"initializing SASL client";
351 const int saslresult = sasl_client_new(
"ldap", d->mServer.host().toLatin1().constData(),
nullptr,
nullptr, callbacks, 0, &d->mSASLconn);
352 if (saslresult != SASL_OK) {
353 d->mConnectionError =
i18n(
"Cannot initialize the SASL client.");
354 return KLDAP_SASL_ERROR;
363#if HAVE_LDAP_UNBIND_EXT
364 ldap_unbind_ext(d->mLDAP,
nullptr,
nullptr);
366 ldap_unbind(d->mLDAP);
371 sasl_dispose(&d->mSASLconn);
372 d->mSASLconn =
nullptr;
374 qCDebug(LDAP_LOG) <<
"connection closed!";
381 qCritical() <<
"No LDAP support...";
387 qCritical() <<
"No LDAP support...";
393 qCritical() <<
"No LDAP support...";
399 qCritical() <<
"No LDAP support...";
405 qCritical() <<
"No LDAP support...";
411 qCritical() <<
"No LDAP support...";
417 qCritical() <<
"No LDAP support...";
423 qCritical() <<
"No LDAP support...";
429 d->mConnectionError =
i18n(
430 "LDAP support not compiled in. Please recompile libkldap with the "
431 "OpenLDAP (or compatible) client libraries, or complain to your "
432 "distribution packagers.");
433 qCritical() <<
"No LDAP support...";
439 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