#include "TLDAPServer.h"
#include "TLDAPResult.h"
#include "TLDAPEntry.h"
#include "TLDAPAttribute.h"
#include "TObjString.h"
#include "TList.h"
#include "TError.h"
ClassImp(TLDAPServer)
TLDAPServer::TLDAPServer(const char *host, Int_t port, const char *binddn,
const char *password, Int_t version)
{
fLd = 0;
fIsConnected = kFALSE;
fBinddn = binddn;
fPassword = password;
fLd = ldap_init(host, port);
if (!fLd) {
Error("TLDAPServer", "error in ldap_init function");
} else {
if (ldap_set_option(fLd, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS ) {
Error("Bind", "Could not set protocol version!");
return;
}
Bind( );
}
}
TLDAPServer::TLDAPServer(const TLDAPServer& lds) :
TObject(lds),
fLd(lds.fLd),
fBinddn(lds.fBinddn),
fPassword(lds.fPassword),
fIsConnected(lds.fIsConnected)
{
}
TLDAPServer& TLDAPServer::operator=(const TLDAPServer& lds)
{
if(this!=&lds) {
TObject::operator=(lds);
fLd=lds.fLd;
fBinddn=lds.fBinddn;
fPassword=lds.fPassword;
fIsConnected=lds.fIsConnected;
} return *this;
}
TLDAPServer::~TLDAPServer()
{
Unbind();
}
Int_t TLDAPServer::Bind()
{
if (!IsConnected()) {
Int_t result = ldap_simple_bind_s(fLd, fBinddn.Data(), fPassword.Data());
if (result != LDAP_SUCCESS) {
ldap_unbind(fLd);
fIsConnected = kFALSE;
switch (result) {
case LDAP_INVALID_CREDENTIALS:
Error("Bind", "invalid password");
break;
case LDAP_INAPPROPRIATE_AUTH:
Error("Bind", "entry has no password to check");
break;
default :
Error("Bind", "%s", ldap_err2string(result));
break;
}
} else {
fIsConnected = kTRUE;
}
return result;
}
return 0;
}
void TLDAPServer::Unbind()
{
if (IsConnected()) {
ldap_unbind(fLd);
fIsConnected = kFALSE;
}
}
const char *TLDAPServer::GetNamingContexts()
{
TList *attrs = new TList;
attrs->SetOwner();
attrs->AddLast(new TObjString("namingContexts"));
const char *namingcontexts = 0;
TLDAPResult *result = Search("", LDAP_SCOPE_BASE, 0, attrs, 0);
if (result) {
TLDAPEntry *entry = result->GetNext();
if (entry) {
TLDAPAttribute *attribute = entry->GetAttribute();
if (attribute)
namingcontexts = attribute->GetValue();
delete entry;
}
delete result;
}
delete attrs;
return namingcontexts;
}
const char *TLDAPServer::GetSubschemaSubentry()
{
TList *attrs = new TList;
attrs->SetOwner();
attrs->AddLast(new TObjString("subschemaSubentry"));
const char *subschema = 0;
TLDAPResult *result = Search("", LDAP_SCOPE_BASE, 0, attrs, 0);
if (result) {
TLDAPEntry *entry = result->GetNext();
if (entry) {
TLDAPAttribute *attribute = entry->GetAttribute();
if (attribute)
subschema = attribute->GetValue();
delete entry;
}
delete result;
}
delete attrs;
return subschema;
}
TLDAPResult *TLDAPServer::GetObjectClasses()
{
const char *subschema = GetSubschemaSubentry();
TList *attrs = new TList;
attrs->SetOwner();
attrs->AddLast(new TObjString("objectClasses"));
TLDAPResult *result = Search(subschema, LDAP_SCOPE_BASE, 0, attrs, 0);
delete attrs;
return result;
}
TLDAPResult *TLDAPServer::GetAttributeTypes()
{
const char *subschema = GetSubschemaSubentry();
TList *attrs = new TList;
attrs->SetOwner();
attrs->AddLast(new TObjString("attributeTypes"));
TLDAPResult *result = Search(subschema, LDAP_SCOPE_BASE, 0, attrs, 0);
delete attrs;
return result;
}
TLDAPResult *TLDAPServer::Search(const char *base, Int_t scope,
const char *filter, TList *attrs,
Bool_t attrsonly)
{
Bind();
Int_t errcode;
TLDAPResult *result = 0;
if (IsConnected()) {
LDAPMessage *searchresult;
char **attrslist = 0;
if (attrs) {
Int_t n = attrs->GetSize();
attrslist = new char* [n + 1];
for (Int_t i = 0; i < n; i++)
attrslist[i] = (char*) ((TObjString*)attrs->At(i))->GetName();
attrslist[n] = 0;
}
if (filter == 0)
filter = "(objectClass=*)";
errcode = ldap_search_s(fLd, base, scope, filter, attrslist,
attrsonly, &searchresult);
delete [] attrslist;
if (errcode == LDAP_SUCCESS) {
result = new TLDAPResult(fLd, searchresult);
} else {
ldap_msgfree(searchresult);
Error("Search", "%s", ldap_err2string(errcode));
}
} else {
errcode = LDAP_SERVER_DOWN;
Error("Search", "%s", "server is not connected");
}
return result;
}
Int_t TLDAPServer::AddEntry(TLDAPEntry &entry)
{
Bind();
Int_t errcode;
if (IsConnected()) {
LDAPMod **ms = entry.GetMods(0);
errcode = ldap_add_s(fLd, entry.GetDn(), ms);
TLDAPServer::DeleteMods(ms);
if (errcode != LDAP_SUCCESS)
Error("AddEntry", "%s", ldap_err2string(errcode));
} else {
errcode = LDAP_SERVER_DOWN;
Error("AddEntry", "server is not connected");
}
return errcode;
}
Int_t TLDAPServer::ModifyEntry(TLDAPEntry &entry, Int_t mode)
{
Bind();
Int_t errcode;
if (IsConnected()) {
LDAPMod **ms = entry.GetMods(mode);
errcode = ldap_modify_s(fLd, entry.GetDn(), ms);
TLDAPServer::DeleteMods(ms);
if (errcode != LDAP_SUCCESS)
Error("ModifyEntry", "%s", ldap_err2string(errcode));
} else {
errcode = LDAP_SERVER_DOWN;
Error("ModifyEntry", "server is not connected");
}
return errcode;
}
Int_t TLDAPServer::DeleteEntry(const char *dn)
{
Bind();
Int_t errcode;
if (IsConnected()) {
errcode = ldap_delete_s(fLd, dn);
if (errcode != LDAP_SUCCESS)
Error("DeleteEntry", "%s", ldap_err2string(errcode));
} else {
errcode = LDAP_SERVER_DOWN;
Error("DeleteEntry", "server is not connected");
}
return errcode;
}
Int_t TLDAPServer::RenameEntry(const char *dn, const char *newrdn, Bool_t removeattr)
{
Int_t errcode;
if (IsConnected()) {
errcode = ldap_modrdn2_s(fLd, dn, newrdn, removeattr);
if (errcode != LDAP_SUCCESS)
Error( "RenameEntry", "%s", ldap_err2string(errcode));
} else {
errcode = LDAP_SERVER_DOWN;
Error("RenameEntry", "server is not connected");
}
return errcode;
}
void TLDAPServer::DeleteMods(LDAPMod **mods)
{
#if 1
ldap_mods_free(mods, 1);
#else
Int_t i = 0;
LDAPMod *mod;
while ((mod = mods[i++]) != 0) {
if (mod->mod_op & LDAP_MOD_BVALUES) {
ber_bvecfree(mod->mod_bvalues);
} else {
Int_t j = 0;
char *c;
while ((c = mod->mod_values[j++]) != 0)
delete c;
}
delete mod->mod_type;
delete mod;
}
delete mods;
#endif
}