/* * pldap.h * * Lightweight Directory Access Protocol interface class. * * Portable Windows Library * * Copyright (c) 1993-2003 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): ______________________________________. * * $Log: pldap.h,v $ * Revision 1.10 2006/01/16 19:52:05 dsandras * Applied patch from Brian Lu <brian lu sun com> to allow compilation on * Solaris using SUN's LDAP. Thanks!! * * Revision 1.9 2004/05/24 12:02:49 csoutheren * Add function to permit setting a limit on the number of results returned * from an LDAP query. Change the default number of results to unlimited, * rather than MAX_INT which apparently is clamped to some arbitrary low value. * Thanks to Damien Sandras * * Revision 1.8 2004/02/20 16:28:27 ykiryanov * if'd LDAP code to enable non-LDAP builds * * Revision 1.7 2003/06/05 23:17:07 rjongbloed * Added functions to get and set LDAP operation timeout. * * Revision 1.6 2003/06/05 05:29:30 rjongbloed * Fixed LDAP bind authentication methods, thanks Ravelli Rossano * * Revision 1.5 2003/04/07 12:00:04 robertj * Fixed search function returning an error if can't find anything for filter. * * Revision 1.4 2003/04/01 07:05:29 robertj * Added ability to specify host:port in opening an LDAP server * * Revision 1.3 2003/03/31 09:02:43 robertj * Added missing return for error number. * * Revision 1.2 2003/03/31 03:32:41 robertj * Major addition of functionality. * * Revision 1.1 2003/03/28 01:15:44 robertj * OpenLDAP support. * * */ #ifndef _PLDAP_H #define _PLDAP_H #ifdef P_USE_PRAGMA #pragma interface #endif #if P_LDAP #include <ptlib/sockets.h> struct ldap; struct ldapmsg; struct ldapmod; struct berval; class PLDAPStructBase; /**This class will create an LDAP client to access a remote LDAP server. */ class PLDAPSession : public PObject { PCLASSINFO(PLDAPSession, PObject); public: /**Create a LDAP client. */ PLDAPSession( const PString & defaultBaseDN = PString::Empty() ); /**Close the sesison on destruction */ ~PLDAPSession(); /**Open the LDAP session to the specified server. The server name string is of the form hostip[:port] where hostip is a host name or IP address and the :port is an optional port number. If not present then the port variable is used. If that is also zero then the default port of 369 is used. */ BOOL Open( const PString & server, WORD port = 0 ); /**Close the LDAP session */ BOOL Close(); /**Determine of session is open. */ BOOL IsOpen() const { return ldapContext != NULL; } /**Set LDAP option parameter (OpenLDAp specific values) */ BOOL SetOption( int optcode, int value ); /**Set LDAP option parameter (OpenLDAP specific values) */ BOOL SetOption( int optcode, void * value ); enum AuthenticationMethod { AuthSimple, AuthSASL, AuthKerberos, #ifdef SOLARIS NumAuthenticationMethod1, NumAuthenticationMethod2 #else NumAuthenticationMethod #endif }; /**Bind to the remote LDAP server. */ BOOL Bind( const PString & who = PString::Empty(), const PString & passwd = PString::Empty(), AuthenticationMethod authMethod = AuthSimple ); class ModAttrib : public PObject { PCLASSINFO(ModAttrib, PObject); public: enum Operation { Add, Replace, Delete, NumOperations }; protected: ModAttrib( const PString & name, Operation op = NumOperations ); public: const PString & GetName() const { return name; } Operation GetOperation() const { return op; } void SetLDAPMod( struct ldapmod & mod, Operation defaultOp ); protected: virtual BOOL IsBinary() const = 0; virtual void SetLDAPModVars(struct ldapmod & mod) = 0; PString name; Operation op; }; class StringModAttrib : public ModAttrib { PCLASSINFO(StringModAttrib, ModAttrib); public: StringModAttrib( const PString & name, Operation op = NumOperations ); StringModAttrib( const PString & name, const PString & value, Operation op = NumOperations ); StringModAttrib( const PString & name, const PStringList & values, Operation op = NumOperations ); void SetValue( const PString & value ); void AddValue( const PString & value ); protected: virtual BOOL IsBinary() const; virtual void SetLDAPModVars(struct ldapmod & mod); PStringList values; PBaseArray<char *> pointers; }; class BinaryModAttrib : public ModAttrib { PCLASSINFO(BinaryModAttrib, ModAttrib); public: BinaryModAttrib( const PString & name, Operation op = Add ); BinaryModAttrib( const PString & name, const PBYTEArray & value, Operation op = Add ); BinaryModAttrib( const PString & name, const PList<PBYTEArray> & values, Operation op = Add ); void SetValue( const PBYTEArray & value ); void AddValue( const PBYTEArray & value ); protected: virtual BOOL IsBinary() const; virtual void SetLDAPModVars(struct ldapmod & mod); PList<PBYTEArray> values; PBaseArray<struct berval *> pointers; PBYTEArray bervals; }; /**Add a new distringuished name to LDAP dirctory. */ BOOL Add( const PString & dn, const PList<ModAttrib> & attributes ); /**Add a new distringuished name to LDAP dirctory. */ BOOL Add( const PString & dn, const PStringToString & attributes ); /**Add a new distringuished name to LDAP dirctory. The attributes list is a string array of the form attr=value */ BOOL Add( const PString & dn, const PStringArray & attributes ); /**Add a new distringuished name to LDAP dirctory. The attributes list is a string array of the form attr=value */ BOOL Add( const PString & dn, const PLDAPStructBase & data ); /**Modify an existing distringuished name to LDAP dirctory. */ BOOL Modify( const PString & dn, const PList<ModAttrib> & attributes ); /**Add a new distringuished name to LDAP dirctory. */ BOOL Modify( const PString & dn, const PStringToString & attributes ); /**Add a new distringuished name to LDAP dirctory. The attributes list is a string array of the form attr=value */ BOOL Modify( const PString & dn, const PStringArray & attributes ); /**Add a new distringuished name to LDAP dirctory. The attributes list is a string array of the form attr=value */ BOOL Modify( const PString & dn, const PLDAPStructBase & data ); /**Delete the distinguished name from LDAP directory. */ BOOL Delete( const PString & dn ); enum SearchScope { ScopeBaseOnly, ScopeSingleLevel, ScopeSubTree, NumSearchScope }; class SearchContext { public: SearchContext(); ~SearchContext(); BOOL IsCompleted() const { return completed; } private: int msgid; struct ldapmsg * result; struct ldapmsg * message; BOOL found; BOOL completed; friend class PLDAPSession; }; /**Start search for specified information. */ BOOL Search( SearchContext & context, const PString & filter, const PStringArray & attributes = PStringList(), const PString & base = PString::Empty(), SearchScope scope = ScopeSubTree ); /**Get the current search result entry. */ BOOL GetSearchResult( SearchContext & context, PStringToString & data ); /**Get an attribute of the current search result entry. */ BOOL GetSearchResult( SearchContext & context, const PString & attribute, PString & data ); /**Get an attribute of the current search result entry. */ BOOL GetSearchResult( SearchContext & context, const PString & attribute, PStringArray & data ); /**Get an attribute of the current search result entry. */ BOOL GetSearchResult( SearchContext & context, const PString & attribute, PArray<PBYTEArray> & data ); /**Get all attributes of the current search result entry. */ BOOL GetSearchResult( SearchContext & context, PLDAPStructBase & data ); /**Get the current search result distinguished name entry. */ PString GetSearchResultDN( SearchContext & context ); /**Get the next search result. */ BOOL GetNextSearchResult( SearchContext & context ); /**Search for specified information, returning all matches. This can be used for simple LDAP databases where all attributes are represented by a string. */ PList<PStringToString> Search( const PString & filter, const PStringArray & attributes = PStringList(), const PString & base = PString::Empty(), SearchScope scope = ScopeSubTree ); /**Set the default base DN for use if not specified for searches. */ void SetBaseDN( const PString & dn ) { defaultBaseDN = dn; } /**Set the default base DN for use if not specified for searches. */ const PString & GetBaseDN() const { return defaultBaseDN; } /**Get the last OpenLDAP error code. */ int GetErrorNumber() const { return errorNumber; } /**Get the last OpenLDAP error as text string. */ PString GetErrorText() const; /**Get the OpenLDAP context structure. */ struct ldap * GetOpenLDAP() const { return ldapContext; } /**Get the timeout for LDAP operations. */ const PTimeInterval & GetTimeout() const { return timeout; } /**Set the timeout for LDAP operations. */ void SetTimeout( const PTimeInterval & t ) { timeout = t; } /**Set a limit on the number of results to return */ void SetSearchLimit( const unsigned s ) { searchLimit = s; } protected: struct ldap * ldapContext; int errorNumber; unsigned protocolVersion; PString defaultBaseDN; unsigned searchLimit; PTimeInterval timeout; PString multipleValueSeparator; }; class PLDAPStructBase; class PLDAPAttributeBase : public PObject { PCLASSINFO(PLDAPAttributeBase, PObject); public: PLDAPAttributeBase(const char * name, void * pointer, PINDEX size); const char * GetName() const { return name; } BOOL IsBinary() const { return pointer != NULL; } virtual void Copy(const PLDAPAttributeBase & other) = 0; virtual PString ToString() const; virtual void FromString(const PString & str); virtual PBYTEArray ToBinary() const; virtual void FromBinary(const PArray<PBYTEArray> & data); protected: const char * name; void * pointer; PINDEX size; }; class PLDAPStructBase : public PObject { PCLASSINFO(PLDAPStructBase, PObject); protected: PLDAPStructBase(); PLDAPStructBase & operator=(const PLDAPStructBase &); PLDAPStructBase & operator=(const PStringArray & array); PLDAPStructBase & operator=(const PStringToString & dict); private: PLDAPStructBase(const PLDAPStructBase &) { } public: void PrintOn(ostream & strm) const; PINDEX GetNumAttributes() const { return attributes.GetSize(); } PLDAPAttributeBase & GetAttribute(PINDEX idx) const { return attributes.GetDataAt(idx); } PLDAPAttributeBase * GetAttribute(const char * name) const { return attributes.GetAt(name); } void AddAttribute(PLDAPAttributeBase * var); static PLDAPStructBase & GetInitialiser() { return *PAssertNULL(initialiserInstance); } protected: void EndConstructor(); PDictionary<PString, PLDAPAttributeBase> attributes; PLDAPStructBase * initialiserStack; static PMutex initialiserMutex; static PLDAPStructBase * initialiserInstance; }; #define PLDAP_STRUCT_BEGIN(name) \ class name : public PLDAPStructBase { \ public: name() { EndConstructor(); } \ public: name(const name & other) { EndConstructor(); operator=(other); } \ public: name(const PStringArray & array) { EndConstructor(); operator=(array); } \ public: name(const PStringToString & dict) { EndConstructor(); operator=(dict); } \ public: name & operator=(const name & other) { PLDAPStructBase::operator=(other); return *this; } \ public: name & operator=(const PStringArray & array) { PLDAPStructBase::operator=(array); return *this; } \ public: name & operator=(const PStringToString & dict) { PLDAPStructBase::operator=(dict); return *this; } \ PLDAP_ATTR_INIT(name, PString, objectClass, #name); #define PLDAP_ATTRIBUTE(base, type, attribute, pointer, init) \ public: type attribute; \ private: struct PLDAPAttr_##attribute : public PLDAPAttributeBase { \ PLDAPAttr_##attribute() \ : PLDAPAttributeBase(#attribute, pointer, sizeof(type)), \ instance(((base &)base::GetInitialiser()).attribute) \ { init } \ virtual void PrintOn (ostream & s) const { s << instance; } \ virtual void ReadFrom(istream & s) { s >> instance; } \ virtual void Copy(const PLDAPAttributeBase & other) \ { instance = ((PLDAPAttr_##attribute &)other).instance; } \ type & instance; \ } pldapvar_##attribute #define PLDAP_ATTR_SIMP(base, type, attribute) \ PLDAP_ATTRIBUTE(base, type, attribute, NULL, ;) #define PLDAP_ATTR_INIT(base, type, attribute, init) \ PLDAP_ATTRIBUTE(base, type, attribute, NULL, instance = init;) #define PLDAP_BINATTRIB(base, type, attribute) \ PLDAP_ATTRIBUTE(base, type, attribute, &((base &)base::GetInitialiser()).attribute, ;) #define PLDAP_STRUCT_END() \ }; #endif // P_LDAP #endif // _PLDAP_H // End of file ////////////////////////////////////////////////////////////////