pldap.h

Go to the documentation of this file.
00001 /*
00002  * pldap.h
00003  *
00004  * Lightweight Directory Access Protocol interface class.
00005  *
00006  * Portable Windows Library
00007  *
00008  * Copyright (c) 1993-2003 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Log: pldap.h,v $
00027  * Revision 1.13  2007/07/22 23:54:38  rjongbloed
00028  * Fixed MSVC compiler warning.
00029  *
00030  * Revision 1.12  2007/07/20 21:44:03  shorne
00031  * Removed virtual on PLDAPSchema::SchemaName
00032  *
00033  * Revision 1.11  2007/07/19 15:05:25  shorne
00034  * Added Factory loaded LDAP schemas
00035  *
00036  * Revision 1.10  2006/01/16 19:52:05  dsandras
00037  * Applied patch from Brian Lu <brian lu sun com> to allow compilation on
00038  * Solaris using SUN's LDAP. Thanks!!
00039  *
00040  * Revision 1.9  2004/05/24 12:02:49  csoutheren
00041  * Add function to permit setting a limit on the number of results returned
00042  * from an LDAP query. Change the default number of results to unlimited,
00043  * rather than MAX_INT which apparently is clamped to some arbitrary low value.
00044  * Thanks to Damien Sandras
00045  *
00046  * Revision 1.8  2004/02/20 16:28:27  ykiryanov
00047  * if'd LDAP code to enable non-LDAP builds
00048  *
00049  * Revision 1.7  2003/06/05 23:17:07  rjongbloed
00050  * Added functions to get and set LDAP operation timeout.
00051  *
00052  * Revision 1.6  2003/06/05 05:29:30  rjongbloed
00053  * Fixed LDAP bind authentication methods, thanks Ravelli Rossano
00054  *
00055  * Revision 1.5  2003/04/07 12:00:04  robertj
00056  * Fixed search function returning an error if can't find anything for filter.
00057  *
00058  * Revision 1.4  2003/04/01 07:05:29  robertj
00059  * Added ability to specify host:port in opening an LDAP server
00060  *
00061  * Revision 1.3  2003/03/31 09:02:43  robertj
00062  * Added missing return for error number.
00063  *
00064  * Revision 1.2  2003/03/31 03:32:41  robertj
00065  * Major addition of functionality.
00066  *
00067  * Revision 1.1  2003/03/28 01:15:44  robertj
00068  * OpenLDAP support.
00069  *
00070  *
00071  */
00072 
00073 #ifndef _PLDAP_H
00074 #define _PLDAP_H
00075 
00076 #ifdef P_USE_PRAGMA
00077 #pragma interface
00078 #endif
00079 
00080 #if P_LDAP
00081 
00082 #include <ptlib/sockets.h>
00083 #include <ptlib/pluginmgr.h>
00084 #include <map>
00085 #include <list>
00086 
00087 struct ldap;
00088 struct ldapmsg;
00089 struct ldapmod;
00090 struct berval;
00091 
00092 class PLDAPStructBase;
00093 
00094 
00097 class PLDAPSession : public PObject
00098 {
00099   PCLASSINFO(PLDAPSession, PObject);
00100   public:
00103     PLDAPSession(
00104       const PString & defaultBaseDN = PString::Empty()
00105     );
00106 
00109     ~PLDAPSession();
00110 
00117     BOOL Open(
00118       const PString & server,
00119       WORD port = 0
00120     );
00121 
00124     BOOL Close();
00125 
00128     BOOL IsOpen() const { return ldapContext != NULL; }
00129 
00132     BOOL SetOption(
00133       int optcode,
00134       int value
00135     );
00136 
00139     BOOL SetOption(
00140       int optcode,
00141       void * value
00142     );
00143 
00144     enum AuthenticationMethod {
00145       AuthSimple,
00146       AuthSASL,
00147       AuthKerberos,
00148 #ifdef SOLARIS
00149       NumAuthenticationMethod1,
00150       NumAuthenticationMethod2
00151 #else
00152       NumAuthenticationMethod
00153 #endif
00154     };
00155 
00158     BOOL Bind(
00159       const PString & who = PString::Empty(),
00160       const PString & passwd = PString::Empty(),
00161       AuthenticationMethod authMethod = AuthSimple
00162     );
00163 
00164     class ModAttrib : public PObject {
00165         PCLASSINFO(ModAttrib, PObject);
00166       public:
00167         enum Operation {
00168           Add,
00169           Replace,
00170           Delete,
00171           NumOperations
00172         };
00173 
00174       protected:
00175         ModAttrib(
00176           const PString & name,
00177           Operation op = NumOperations
00178         );
00179 
00180       public:
00181         const PString & GetName() const { return name; }
00182 
00183         Operation GetOperation() const { return op; }
00184 
00185         void SetLDAPMod(
00186           struct ldapmod & mod,
00187           Operation defaultOp
00188         );
00189 
00190       protected:
00191         virtual BOOL IsBinary() const = 0;
00192         virtual void SetLDAPModVars(struct ldapmod & mod) = 0;
00193 
00194         PString   name;
00195         Operation op;
00196     };
00197 
00198     class StringModAttrib : public ModAttrib {
00199         PCLASSINFO(StringModAttrib, ModAttrib);
00200       public:
00201         StringModAttrib(
00202           const PString & name,
00203           Operation op = NumOperations
00204         );
00205         StringModAttrib(
00206           const PString & name,
00207           const PString & value,
00208           Operation op = NumOperations
00209         );
00210         StringModAttrib(
00211           const PString & name,
00212           const PStringList & values,
00213           Operation op = NumOperations
00214         );
00215         void SetValue(
00216           const PString & value
00217         );
00218         void AddValue(
00219           const PString & value
00220         );
00221       protected:
00222         virtual BOOL IsBinary() const;
00223         virtual void SetLDAPModVars(struct ldapmod & mod);
00224 
00225         PStringList values;
00226         PBaseArray<char *> pointers;
00227     };
00228 
00229     class BinaryModAttrib : public ModAttrib {
00230         PCLASSINFO(BinaryModAttrib, ModAttrib);
00231       public:
00232         BinaryModAttrib(
00233           const PString & name,
00234           Operation op = Add
00235         );
00236         BinaryModAttrib(
00237           const PString & name,
00238           const PBYTEArray & value,
00239           Operation op = Add
00240         );
00241         BinaryModAttrib(
00242           const PString & name,
00243           const PList<PBYTEArray> & values,
00244           Operation op = Add
00245         );
00246         void SetValue(
00247           const PBYTEArray & value
00248         );
00249         void AddValue(
00250           const PBYTEArray & value
00251         );
00252       protected:
00253         virtual BOOL IsBinary() const;
00254         virtual void SetLDAPModVars(struct ldapmod & mod);
00255 
00256         PList<PBYTEArray> values;
00257         PBaseArray<struct berval *> pointers;
00258         PBYTEArray bervals;
00259     };
00260 
00263     BOOL Add(
00264       const PString & dn,
00265       const PList<ModAttrib> & attributes
00266     );
00267 
00270     BOOL Add(
00271       const PString & dn,
00272       const PStringToString & attributes
00273     );
00274 
00278     BOOL Add(
00279       const PString & dn,
00280       const PStringArray & attributes
00281     );
00282 
00286     BOOL Add(
00287       const PString & dn,
00288       const PLDAPStructBase & data
00289     );
00290 
00293     BOOL Modify(
00294       const PString & dn,
00295       const PList<ModAttrib> & attributes
00296     );
00297 
00300     BOOL Modify(
00301       const PString & dn,
00302       const PStringToString & attributes
00303     );
00304 
00308     BOOL Modify(
00309       const PString & dn,
00310       const PStringArray & attributes
00311     );
00312 
00316     BOOL Modify(
00317       const PString & dn,
00318       const PLDAPStructBase & data
00319     );
00320 
00323     BOOL Delete(
00324       const PString & dn
00325     );
00326 
00327 
00328     enum SearchScope {
00329       ScopeBaseOnly,
00330       ScopeSingleLevel,
00331       ScopeSubTree,
00332       NumSearchScope
00333     };
00334 
00335     class SearchContext {
00336       public:
00337         SearchContext();
00338         ~SearchContext();
00339 
00340         BOOL IsCompleted() const { return completed; }
00341 
00342       private:
00343         int              msgid;
00344         struct ldapmsg * result;
00345         struct ldapmsg * message;
00346         BOOL             found;
00347         BOOL             completed;
00348 
00349       friend class PLDAPSession;
00350     };
00351 
00354     BOOL Search(
00355       SearchContext & context,
00356       const PString & filter,
00357       const PStringArray & attributes = PStringList(),
00358       const PString & base = PString::Empty(),
00359       SearchScope scope = ScopeSubTree
00360     );
00361 
00364     BOOL GetSearchResult(
00365       SearchContext & context,
00366       PStringToString & data
00367     );
00368 
00371     BOOL GetSearchResult(
00372       SearchContext & context,
00373       const PString & attribute,
00374       PString & data
00375     );
00376 
00379     BOOL GetSearchResult(
00380       SearchContext & context,
00381       const PString & attribute,
00382       PStringArray & data
00383     );
00384 
00387     BOOL GetSearchResult(
00388       SearchContext & context,
00389       const PString & attribute,
00390       PArray<PBYTEArray> & data
00391     );
00392 
00395     BOOL GetSearchResult(
00396       SearchContext & context,
00397       PLDAPStructBase & data
00398     );
00399 
00402     PString GetSearchResultDN(
00403       SearchContext & context
00404     );
00405 
00408     BOOL GetNextSearchResult(
00409       SearchContext & context
00410     );
00411 
00416     PList<PStringToString> Search(
00417       const PString & filter,
00418       const PStringArray & attributes = PStringList(),
00419       const PString & base = PString::Empty(),
00420       SearchScope scope = ScopeSubTree
00421     );
00422 
00423 
00426     void SetBaseDN(
00427       const PString & dn
00428     ) { defaultBaseDN = dn; }
00429 
00432     const PString & GetBaseDN() const { return defaultBaseDN; }
00433 
00436     int GetErrorNumber() const { return errorNumber; }
00437 
00440     PString GetErrorText() const;
00441 
00444     struct ldap * GetOpenLDAP() const { return ldapContext; }
00445 
00448     const PTimeInterval & GetTimeout() const { return timeout; }
00449 
00452     void SetTimeout(
00453       const PTimeInterval & t
00454     ) { timeout = t; }
00455 
00458      void SetSearchLimit(
00459       const unsigned s
00460     ) { searchLimit = s; }
00461 
00462   protected:
00463     struct ldap * ldapContext;
00464     int           errorNumber;
00465     unsigned      protocolVersion;
00466     PString       defaultBaseDN;
00467     unsigned      searchLimit;
00468     PTimeInterval timeout;
00469     PString       multipleValueSeparator;
00470 };
00471 
00472 
00473 
00474 class PLDAPStructBase;
00475 
00476 class PLDAPAttributeBase : public PObject
00477 {
00478     PCLASSINFO(PLDAPAttributeBase, PObject);
00479   public:
00480     PLDAPAttributeBase(const char * name, void * pointer, PINDEX size);
00481 
00482     const char * GetName() const { return name; }
00483     BOOL IsBinary() const { return pointer != NULL; }
00484 
00485     virtual void Copy(const PLDAPAttributeBase & other) = 0;
00486 
00487     virtual PString ToString() const;
00488     virtual void FromString(const PString & str);
00489     virtual PBYTEArray ToBinary() const;
00490     virtual void FromBinary(const PArray<PBYTEArray> & data);
00491 
00492   protected:
00493     const char * name;
00494     void       * pointer;
00495     PINDEX       size;
00496 };
00497 
00498 
00499 class PLDAPStructBase : public PObject {
00500     PCLASSINFO(PLDAPStructBase, PObject);
00501   protected:
00502     PLDAPStructBase();
00503     PLDAPStructBase & operator=(const PLDAPStructBase &);
00504     PLDAPStructBase & operator=(const PStringArray & array);
00505     PLDAPStructBase & operator=(const PStringToString & dict);
00506   private:
00507     PLDAPStructBase(const PLDAPStructBase &) { }
00508 
00509   public:
00510     void PrintOn(ostream & strm) const;
00511 
00512     PINDEX GetNumAttributes() const { return attributes.GetSize(); }
00513     PLDAPAttributeBase & GetAttribute(PINDEX idx) const { return attributes.GetDataAt(idx); }
00514     PLDAPAttributeBase * GetAttribute(const char * name) const { return attributes.GetAt(name); }
00515 
00516     void AddAttribute(PLDAPAttributeBase * var);
00517     static PLDAPStructBase & GetInitialiser() { return *PAssertNULL(initialiserInstance); }
00518 
00519   protected:
00520     void EndConstructor();
00521 
00522     PDictionary<PString, PLDAPAttributeBase> attributes;
00523 
00524     PLDAPStructBase        * initialiserStack;
00525     static PMutex            initialiserMutex;
00526     static PLDAPStructBase * initialiserInstance;
00527 };
00528 
00530 
00531 class PLDAPSchema : public PObject
00532 {
00533   public:
00534     PLDAPSchema();
00535 
00536     enum AttributeType {
00537         AttibuteUnknown = -1,
00538         AttributeString,
00539         AttributeBinary,
00540         AttributeNumeric
00541     };
00542 
00543     class Attribute
00544     {
00545     public:
00546         Attribute() : m_type(AttibuteUnknown) { }
00547         Attribute(const PString & name, AttributeType type);
00548         PString       m_name;
00549         AttributeType m_type;
00550     };
00551 
00552     typedef std::list<Attribute> attributeList;
00553 
00554     static PLDAPSchema * CreateSchema(const PString & schemaname, PPluginManager * pluginMgr = NULL);
00555     static PStringList GetSchemaNames(PPluginManager * pluginMgr = NULL);
00556     static PStringList GetSchemaFriendlyNames(const PString & schema, PPluginManager * pluginMgr = NULL);
00557 
00558     void OnReceivedAttribute(const PString & attribute, const PString & value);
00559 
00560     void OnSendSchema(PList<PLDAPSession::ModAttrib> & attributes,
00561         PLDAPSession::ModAttrib::Operation op=PLDAPSession::ModAttrib::Add);
00562 
00563     void LoadSchema();
00564 
00565     PStringList SchemaName() { return PStringList(); }
00566     virtual void AttributeList(attributeList & /*attrib*/) {};
00567 
00568 
00569     PStringList GetAttributeList();
00570     BOOL Exists(const PString & attribute);
00571 
00572     BOOL SetAttribute(const PString & attribute, const PString & value);
00573     BOOL SetAttribute(const PString & attribute, const PBYTEArray & value);
00574 
00575     BOOL GetAttribute(const PString & attribute, PString & value);
00576     BOOL GetAttribute(const PString & attribute, PBYTEArray & value);
00577 
00578     AttributeType GetAttributeType(const PString & attribute);
00579 
00580 
00581   protected:
00582     typedef std::map<PString,PString> ldapAttributes;
00583     typedef std::map<PString,PBYTEArray> ldapBinAttributes;
00584 
00585 
00586     attributeList           attributelist;
00587     ldapAttributes          attributes;
00588     ldapBinAttributes       binattributes;   
00589 };
00590 
00591 
00592 template <class className> class LDAPPluginServiceDescriptor : public PDevicePluginServiceDescriptor
00593 {
00594   public:
00595     virtual PObject *   CreateInstance(int /*userData*/) const { return new className; }
00596     virtual PStringList GetDeviceNames(int /*userData*/) const { return className::SchemaName(); } 
00597 };
00598 
00599 #define LDAP_Schema(name)    \
00600 static LDAPPluginServiceDescriptor<##name##_schema> ##name##_schema_descriptor; \
00601 PCREATE_PLUGIN(##name##_schema, PLDAPSchema, &##name##_schema_descriptor); \
00602 PWLIB_STATIC_LOAD_PLUGIN(##name##_schema, PLDAPSchema); \
00603 
00605 
00606 #define PLDAP_STRUCT_BEGIN(name) \
00607   class name : public PLDAPStructBase { \
00608     public: name() { EndConstructor(); } \
00609     public: name(const name & other) { EndConstructor(); operator=(other); } \
00610     public: name(const PStringArray & array) { EndConstructor(); operator=(array); } \
00611     public: name(const PStringToString & dict) { EndConstructor(); operator=(dict); } \
00612     public: name & operator=(const name & other) { PLDAPStructBase::operator=(other); return *this; } \
00613     public: name & operator=(const PStringArray & array) { PLDAPStructBase::operator=(array); return *this; } \
00614     public: name & operator=(const PStringToString & dict) { PLDAPStructBase::operator=(dict); return *this; } \
00615     PLDAP_ATTR_INIT(name, PString, objectClass, #name);
00616 
00617 #define PLDAP_ATTRIBUTE(base, type, attribute, pointer, init) \
00618     public: type attribute; \
00619     private: struct PLDAPAttr_##attribute : public PLDAPAttributeBase { \
00620       PLDAPAttr_##attribute() \
00621         : PLDAPAttributeBase(#attribute, pointer, sizeof(type)), \
00622           instance(((base &)base::GetInitialiser()).attribute) \
00623         { init } \
00624       virtual void PrintOn (ostream & s) const { s << instance; } \
00625       virtual void ReadFrom(istream & s)       { s >> instance; } \
00626       virtual void Copy(const PLDAPAttributeBase & other) \
00627                     { instance = ((PLDAPAttr_##attribute &)other).instance; } \
00628       type & instance; \
00629     } pldapvar_##attribute
00630 
00631 #define PLDAP_ATTR_SIMP(base, type, attribute) \
00632         PLDAP_ATTRIBUTE(base, type, attribute, NULL, ;)
00633 
00634 #define PLDAP_ATTR_INIT(base, type, attribute, init) \
00635         PLDAP_ATTRIBUTE(base, type, attribute, NULL, instance = init;)
00636 
00637 #define PLDAP_BINATTRIB(base, type, attribute) \
00638         PLDAP_ATTRIBUTE(base, type, attribute, &((base &)base::GetInitialiser()).attribute, ;)
00639 
00640 #define PLDAP_STRUCT_END() \
00641   };
00642 
00643 #endif // P_LDAP
00644 
00645 #endif // _PLDAP_H
00646 
00647 
00648 // End of file ////////////////////////////////////////////////////////////////

Generated on Fri Mar 7 06:25:02 2008 for PTLib by  doxygen 1.5.1