Module: sip-router
Branch: janakj/ldap
Commit: 8c44d53bd22595f85a6192e265403e00b5f7506d
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8c44d53…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Mon May 19 15:18:02 2008 +0000
- todo list updated
---
modules/db_ldap/todo.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/modules/db_ldap/todo.txt b/modules/db_ldap/todo.txt
index 3778b74..8a82bde 100644
--- a/modules/db_ldap/todo.txt
+++ b/modules/db_ldap/todo.txt
@@ -92,7 +92,7 @@ X Support for Syntax Specification in the Config File
The module should issue an warning when the incremented/decremented field
value overflows/underflows.
-* Support for Older LDAP Libraries
+X Support for Older LDAP Libraries
Older versions of the openldap client library might not contain
LDAP_SCOPE_CHILDREN. We need to handle this case in a graceful manner and
Module: sip-router
Branch: janakj/ldap
Commit: f8cc26095162a16db0b9fdb15e02111bf1372855
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f8cc260…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Mon May 19 15:17:03 2008 +0000
- LD_SCOPE_CHILDREN compiled conditionally, it requires a recent version
of openldap library and is disabled by default
- convenience scope aliases sub and one added
---
modules/db_ldap/Makefile | 5 +++++
modules/db_ldap/ld_config.c | 6 +++++-
modules/db_ldap/ldap.cfg | 8 ++++----
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/modules/db_ldap/Makefile b/modules/db_ldap/Makefile
index 839692c..f7b0507 100644
--- a/modules/db_ldap/Makefile
+++ b/modules/db_ldap/Makefile
@@ -7,6 +7,11 @@ auto_gen=
NAME=ldap.so
#DEFS += -DLD_TEST
+
+# Uncomment this if you have a recent version of libldap with
+# LD_SCOPE_CHILDREN defined
+#DEFS += -DHAVE_SCOPE_CHILDREN
+
LIBS=-L$(LOCALBASE)/lib -L /usr/lib -lldap
include ../../Makefile.modules
diff --git a/modules/db_ldap/ld_config.c b/modules/db_ldap/ld_config.c
index 0b8a781..ecfcefc 100644
--- a/modules/db_ldap/ld_config.c
+++ b/modules/db_ldap/ld_config.c
@@ -537,7 +537,7 @@ static int parse_search_scope(token_t* token)
r = lookup_token(token_scope, &t.val);
if (!r) {
- ERR("ldap:%s:%d:%d: Invalid option value '%.*s'\n",
+ ERR("ldap:%s:%d:%d: Unsupported option value '%.*s'\n",
pstate.file, t.start.line, t.start.col,
t.val.len, ZSW(t.val.s));
return -1;
@@ -921,8 +921,12 @@ char* ld_find_attr_name(enum ld_syntax* syntax, struct ld_config* cfg, char* fld
static struct parser_tab token_scope[] = {
{STR_STATIC_INIT("base"), {.ival = LDAP_SCOPE_BASE}},
{STR_STATIC_INIT("onelevel"), {.ival = LDAP_SCOPE_ONELEVEL}},
+ {STR_STATIC_INIT("one"), {.ival = LDAP_SCOPE_ONELEVEL}},
{STR_STATIC_INIT("subtree"), {.ival = LDAP_SCOPE_SUBTREE}},
+ {STR_STATIC_INIT("sub"), {.ival = LDAP_SCOPE_SUBTREE}},
+#if defined HAVE_SCOPE_CHILDREN
{STR_STATIC_INIT("children"), {.ival = LDAP_SCOPE_CHILDREN}},
+#endif
{STR_NULL}
};
diff --git a/modules/db_ldap/ldap.cfg b/modules/db_ldap/ldap.cfg
index 16fe984..1f134b2 100644
--- a/modules/db_ldap/ldap.cfg
+++ b/modules/db_ldap/ldap.cfg
@@ -25,8 +25,8 @@
# credentials should start.
base = "ou=Digest Credentials,dc=iptel,dc=org"
-# We search all the children but not the ou object itself.
-scope = children
+# We search the whole subtree.
+scope = subtree
# For digest credentials we are only interested in objects with objectClass
# 'digestAuthCredentials', objects of all other types are ignored.
@@ -51,7 +51,7 @@ field_map = flags : (BitString) serFlags
# in the subtree with the following root:
base = "ou=Domains,dc=iptel,dc=org"
-scope = children
+scope = subtree
# We are only interested in serDomain objects when looking up information
# about virtual domains.
@@ -67,7 +67,7 @@ field_map = flags : (BitString) serFlags
#
[domain_attrs]
base = "ou=Domains, dc=iptel,dc=org"
-scope = children
+scope = subtree
filter = "(objectClass=serDomainAttr)"
Module: sip-router
Branch: janakj/ldap
Commit: a6ffc5036a87502e47a67ba928ff55d66201ccdd
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=a6ffc50…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Wed May 14 17:07:43 2008 +0000
- full support for all db api field types in LDAP search filters
(they will be converted according to the syntax specified in
the config file)
- todo list updated
---
modules/db_ldap/ld_cmd.c | 206 +-----------------
modules/db_ldap/ld_config.h | 13 +-
modules/db_ldap/ld_fld.c | 524 +++++++++++++++++++++++++++++++++++++++++-
modules/db_ldap/ld_fld.h | 13 +
modules/db_ldap/todo.txt | 21 ++-
5 files changed, 547 insertions(+), 230 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=a6f…
Module: sip-router
Branch: janakj/ldap
Commit: 5cede19dc92e67081f6d0ecbc7629c940f5f6915
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5cede19…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Tue May 13 14:35:59 2008 +0000
- example SER LDAP schema
---
modules/db_ldap/ser.schema | 259 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 259 insertions(+), 0 deletions(-)
diff --git a/modules/db_ldap/ser.schema b/modules/db_ldap/ser.schema
new file mode 100644
index 0000000..2c25c6d
--- /dev/null
+++ b/modules/db_ldap/ser.schema
@@ -0,0 +1,259 @@
+#
+# $Id$
+#
+# This is the default LDAP schema of SER for OpenLDAP.
+# Written by Jan Janak <jan(a)iptel.org>.
+#
+
+#
+# The root OID of IANA private enterprise numbers
+#
+objectIdentifier ianaPrivate 1.3.6.1.4.1
+
+#
+# The root OID of many LDAPv3 attributes
+#
+objectIdentifier ldap3OID ianaPrivate:1466
+
+#
+# The root OID assigned by the IANA to iptel.org
+#
+objectIdentifier iptelorg ianaPrivate:24960
+
+#
+# SER related objects and attributes
+#
+objectIdentifier ser iptelorg:0
+objectIdentifier serLDAP ser:1
+objectIdentifier serAttributeType serLDAP:0
+objectIdentifier serObjectClass serLDAP:1
+
+#
+# Convenience macros for commonly used syntax OIDs
+#
+objectIdentifier ldapSyntax ldap3OID:115.121.1
+objectIdentifier stringSyntax ldapSyntax:15
+objectIdentifier octetStringSyntax ldapSyntax:40
+objectIdentifier bitStringSyntax ldapSyntax:6
+objectIdentifier intSyntax ldapSyntax:27
+objectIdentifier numericStringSyntax ldapSyntax:36
+objectIdentifier binarySyntax ldapSyntax:5
+objectIdentifier boolSyntax ldapSyntax:7
+
+#
+# This is the parent attribute type for various UID attributes of SER, such
+# as serUID and serDID.
+#
+attributeType ( serAttributeType:0
+ NAME 'serUUID'
+ DESC 'SER Universally Unique Identifier'
+ SYNTAX stringSyntax
+ SINGLE-VALUE
+ )
+
+#
+# serUID attribute stores universally unique identifiers of SER users, the
+# identifier is an opaque string by default.
+#
+attributeType ( serAttributeType:1 NAME 'serUID'
+ DESC 'SER User Identifier'
+ SUP serUUID
+ )
+
+#
+# serDID attributes contain universally unique identifiers of virtual SER
+# domains. They are used to group a bunch of domain names together in a
+# single virtual domain.
+#
+attributeType ( serAttributeType:2 NAME 'serDID'
+ DESC 'SER Domain Identifier'
+ SUP serUUID
+ )
+
+#
+# digesetUsername attribute contains the value of username field from
+# digest authentication credentials as specified in RFC2617. This attribute,
+# together with digestRealm, is used by SER during digest authentication to
+# lookup credentaials of a particular user.
+#
+attributeType ( serAttributeType:3 NAME 'digestUsername'
+ DESC 'SIP Digest Authentication username'
+ SYNTAX stringSyntax
+ EQUALITY caseIgnoreMatch
+ SINGLE-VALUE
+ )
+
+#
+# digestRealm attribute contains the value of realm field from digest
+# authentication credentials as specified in RFC2617. This attribute,
+# together with digestUsername, is used by SER during digest authentication
+# to lookup credentials of a particular user.
+#
+attributeType ( serAttributeType:4 NAME 'digestRealm'
+ DESC 'SIP Digest Authentication realm attribute'
+ SYNTAX stringSyntax
+ EQUALITY caseIgnoreMatch
+ SINGLE-VALUE
+ )
+
+#
+# digestPassword attribute contains the plain-text password for digest
+# authentication (see RFC2617)
+#
+attributeType ( serAttributeType:5 NAME 'digestPassword'
+ DESC 'SIP Digest Authentication password'
+ SYNTAX octetStringSyntax
+ EQUALITY octetStringMatch
+ SINGLE-VALUE
+ )
+
+#
+# The attribute serFlags contains various SER and SERWeb related flags,
+# the flags are used to mark entries as deleted or disabled, they are
+# used to mark entries that are exclusively for SER or SERWeb, and so on.
+# The maximum length of the bit string fields is 32 bits, the most
+# significant bits of values longer than 32 will be ignored.
+#
+attributeType ( serAttributeType:6 NAME 'serFlags'
+ DESC 'SER flags'
+ SYNTAX bitStringSyntax
+ EQUALITY bitStringMatch
+ SINGLE-VALUE
+ )
+
+#
+# This attribute contains the HA1 string as defined in RFC2617. The
+# string is an MD5 hash of digest username, realm, and password.
+# See RFC2617 for more details. SER is using either HA1 or plain-text
+# password (depending on configuration) when verifying digest credentials.
+#
+attributeType ( serAttributeType:7 NAME 'digestHA1'
+ DESC 'Digest Authentication HA1 String'
+ SYNTAX octetStringSyntax
+ EQUALITY octetStringMatch
+ SINGLE-VALUE
+ )
+
+#
+# This attribute contains the HA1 string as defined in RFC2617. This is
+# similar to digestHA1 attribute, except that the MD5 hash in digestHA1b
+# also includes a domain part in username, so the username is of form
+# user@domain. This is sometimes needed when authenticating user agents
+# that put user@domain into the digest username field.
+#
+attributeType ( serAttributeType:8 NAME 'digestHA1b'
+ DESC 'Digest Authentication HA1 String (includes domain in username)'
+ SYNTAX octetStringSyntax
+ EQUALITY octetStringMatch
+ SINGLE-VALUE
+ )
+
+#
+# This attribute stores a domain name within a virtual domain handled
+# by a SER server. SER users this value to determine whether the SIP
+# requests are to/from one of its virtual domains.
+#
+attributeType ( serAttributeType:9 NAME 'serDomain'
+ DESC 'Domain Name'
+ SYNTAX stringSyntax
+ EQUALITY caseIgnoreMatch
+ SINGLE-VALUE
+ )
+
+#
+# SER attributes is a generic mechanism for storing configuration data.
+# This attribute contains the name of an SER attribute.
+#
+attributeType ( serAttributeType:10 NAME 'serAttrName'
+ DESC 'SER Attribute Name'
+ SYNTAX stringSyntax
+ EQUALITY caseExactMatch
+ SINGLE-VALUE
+ )
+
+#
+# SER attributes is a generic mechanism for storing configuration data.
+# This attribute contains SER attribute type. There are two types of
+# SER attributes: integer and string.
+#
+attributeType ( serAttributeType:11 NAME 'serAttrType'
+ DESC 'SER Attribute Type'
+ SYNTAX intSyntax
+ SINGLE-VALUE
+ )
+
+#
+# SER attributes is a generic mechanism for storing configuration data.
+# This attribute contains the value (as string) of a SER attribute.
+#
+attributeType ( serAttributeType:12 NAME 'serAttrValue'
+ DESC 'SER Attribute Value'
+ SYNTAX stringSyntax
+ EQUALITY caseExactMatch
+ SINGLE-VALUE
+ )
+
+#
+# digestAuthCredentials objects are used by SER to perform digest
+# authentication as defined in RFC3261 and RFC2617. Every object must
+# contain a username, a realm, and a UID of the user who owns the
+# credentials. In addition to that the object can contains either
+# password in plain-text format, or the HA1 string, or both. Which of
+# them will be used by SER depends on the configuration.
+#
+# This is an analogy to 'credentials' table found in SER relational
+# database schema.
+#
+objectClass ( serObjectClass:0 NAME 'digestAuthCredentials'
+ DESC 'Credentials for SIP Digest Authentication'
+ MUST ( digestUsername $ digestRealm $ serUID $ serFlags )
+ MAY ( serDID $ digestPassword $ digestHA1 $ digestHA1b )
+ )
+
+#
+# serDomain objects are used to store the information about virtual
+# domains supported by a SER server. The purpose of the object is
+# to map domain names (which appear in SIP messages) to universally
+# unique domain identifiers and vice versa.
+#
+# This is an analogy to 'domain' table found in SER relational database
+# schema.
+#
+objectClass ( serObjectClass:1 NAME 'serDomain'
+ DESC 'SER Virtual Domains'
+ MUST ( serDID $ serDomain $ serFlags )
+ )
+
+#
+# This is an abstract class that can be used as a base for other classes
+# storing SER uri/user/domain/global attributes. An object storing SER
+# attributes must contain serAttrName, serAttrType, serAttrValue, and
+# serFlags attributes.
+#
+objectClass ( serObjectClass:2 NAME 'serAttrAbstract'
+ ABSTRACT
+ MUST ( serAttrName $ serAttrType $ serAttrValue $ serFlags )
+ )
+
+#
+# An auxiliary class that can be used to extend other objects in an LDAP
+# directory with the possibility to store SER attributes.
+#
+objectClass ( serObjectClass:3 NAME 'serAttr'
+ AUXILIARY
+ SUP serAttrAbstract
+ )
+
+#
+# This class is used to store domain level attributes. Domain level
+# attributes are attributes used to store configuration information related
+# to a virtual domain (i.e. common configuration for all users/URIs within
+# that virtual domain), such as digest authentication realm or default
+# language.
+#
+objectClass ( serObjectClass:4 NAME 'serDomainAttr'
+ DESC 'SER Domain Attributes'
+ SUP serAttrAbstract
+ MUST ( serDID )
+ )
+
Module: sip-router
Branch: janakj/ldap
Commit: 0d793e63a790508e71854d00a4e861c9366d6337
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0d793e6…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Tue May 13 12:35:12 2008 +0000
- todo list updated
---
modules/db_ldap/todo.txt | 14 +++++++++++++-
1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/modules/db_ldap/todo.txt b/modules/db_ldap/todo.txt
index 14fb139..7f78010 100644
--- a/modules/db_ldap/todo.txt
+++ b/modules/db_ldap/todo.txt
@@ -27,7 +27,7 @@
operators, only <= and >=. Currently the ldap driver simply uses <= instead
of < and >= instead of >. We need a better implementation of this.
-* Implement Support For Other Than str Parameters
+X Implement Support For Other Than str Parameters
* Escape Values of Parameters Injected Into the Search Filter
@@ -66,3 +66,15 @@
We should eliminate the use of all functions that are marked as deprecated
in the header field and remove LDAP_DEPRECATED define from all files.
+
+X Support for Bool Attribute Types
+
+ The module should be able to convert boolean attributes from the LDAP result
+ into int fields.
+
+X Support for Syntax Specification in the Config File
+
+ There is no easy or portable way of retrieving syntaxes of attributes from
+ the LDAP server, so it might be necessary to specify the syntax of
+ attributes in the configuration file so that the module knows how to convert
+ DB API fields into attribute values in command parameters.
Module: sip-router
Branch: janakj/ldap
Commit: 5055f48ce7f0a00ed9a5ecdb63732b84fb9a3457
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=5055f48…
Author: Jan Janak <jan(a)iptel.org>
Committer: Jan Janak <jan(a)iptel.org>
Date: Mon May 12 16:13:10 2008 +0000
- Support for generalized time attributes
- Support for double/float fields
- Support for bitmap fields
- todo list items augmented with more info
---
modules/db_ldap/ld_fld.c | 113 ++++++++++++++++++++++++++++++++++++-----
modules/db_ldap/standards.txt | 2 +
modules/db_ldap/todo.txt | 77 ++++++++++++++++++++++++----
3 files changed, 168 insertions(+), 24 deletions(-)
diff --git a/modules/db_ldap/ld_fld.c b/modules/db_ldap/ld_fld.c
index b886d85..f9d2c95 100644
--- a/modules/db_ldap/ld_fld.c
+++ b/modules/db_ldap/ld_fld.c
@@ -36,6 +36,10 @@
#define LDAP_DEPRECATED 1
+#define _XOPEN_SOURCE 4 /* bsd */
+#define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
+#define _SVID_SOURCE 1 /* timegm */
+
#include "ld_fld.h"
#include "../../db/db_drv.h"
@@ -43,8 +47,12 @@
#include "../../dprint.h"
#include "../../ut.h"
+#include <stdlib.h>
+#include <strings.h>
#include <stdint.h>
#include <string.h>
+#include <time.h> /* strptime, XOPEN issue must be >= 4 */
+
/** Frees memory used by a ld_fld structure.
* This function frees all memory used by a ld_fld structure
@@ -127,11 +135,63 @@ static inline int ldap_bit2db_int(int* dst, str* src)
}
+/* Convert time_t structure to Generalized Time */
+static inline int db_datetime2ldap_gentime(str* dst, time_t src)
+{
+ /*
+ struct tm* t;
+
+ t = gmtime(&_time);
+ return strftime(result, res_len, "%Y%m%d%H%M%S", t);
+ */
+ return -1;
+}
+
+
+static inline int ldap_gentime2db_datetime(time_t* dst, str* src)
+{
+ struct tm time;
+
+ if (src->len < 12) return -1;
+
+ /* It is necessary to zero tm structure first */
+ memset(&time, '\0', sizeof(struct tm));
+ strptime(src->s, "%Y%m%d%H%M%S", &time);
+
+ /* Daylight saving information got lost in the database
+ * so let timegm to guess it. This eliminates the bug when
+ * contacts reloaded from the database have different time
+ * of expiration by one hour when daylight saving is used
+ */
+ time.tm_isdst = -1;
+#ifdef HAVE_TIMEGM
+ *dst = timegm(&time);
+#else
+ *dst = _timegm(&time);
+#endif /* HAVE_TIMEGM */
+ return 0;
+}
+
+
+static inline int ldap_str2db_double(double* dst, char* src)
+{
+ *dst = atof(src);
+ return 0;
+}
+
+
+static inline int ldap_str2db_float(float* dst, char* src)
+{
+ *dst = (float)atof(src);
+ return 0;
+}
+
+
int ld_ldap2fld(db_fld_t* fld, LDAP* ldap, LDAPMessage* msg)
{
int i;
struct ld_fld* lfld;
- str tmp;
+ str v;
if (fld == NULL || msg == NULL) return 0;
for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
@@ -151,32 +211,57 @@ int ld_ldap2fld(db_fld_t* fld, LDAP* ldap, LDAPMessage* msg)
return -1;
}
+ v.s = lfld->values[0]->bv_val;
+ v.len = lfld->values[0]->bv_len;
+
switch(fld[i].type) {
case DB_CSTR:
- fld[i].v.cstr = lfld->values[0]->bv_val;
+ fld[i].v.cstr = v.s;
break;
case DB_STR:
case DB_BLOB:
- fld[i].v.lstr.s = lfld->values[0]->bv_val;
- fld[i].v.lstr.len = lfld->values[0]->bv_len;
+ fld[i].v.lstr.s = v.s;
+ fld[i].v.lstr.len = v.len;
break;
case DB_INT:
case DB_BITMAP:
- tmp.s = lfld->values[0]->bv_val;
- tmp.len = lfld->values[0]->bv_len;
+ if (v.s[0] == '\'' &&
+ v.s[v.len - 1] == 'B' &&
+ v.s[v.len - 2] == '\'') {
+
+ v.s++;
+ v.len -= 3;
+ return ldap_bit2db_int(&fld[i].v.int4, &v);
+ } else {
+ return ldap_int2db_int(&fld[i].v.int4, &v);
+ }
+ break;
+ case DB_DATETIME:
+ if (ldap_gentime2db_datetime(&fld[i].v.time, &v) != 0) {
+ ERR("ldap: Error while converting LDAP time value '%.*s'\n",
+ v.len, ZSW(v.s));
+ return -1;
+ }
+ break;
- if (tmp.s[0] == '\'' &&
- tmp.s[tmp.len - 1] == 'B' &&
- tmp.s[tmp.len - 2] == '\'') {
+ case DB_FLOAT:
+ /* We know that the ldap library zero-terminated v.s */
+ if (ldap_str2db_float(&fld[i].v.flt, v.s) != 0) {
+ ERR("ldap: Error while converting '%.*s' to float\n",
+ v.len, ZSW(v.s));
+ return -1;
+ }
+ break;
- tmp.s++;
- tmp.len -= 3;
- return ldap_bit2db_int(&fld[i].v.int4, &tmp);
- } else {
- return ldap_int2db_int(&fld[i].v.int4, &tmp);
+ case DB_DOUBLE:
+ /* We know that the ldap library zero-terminated v.s */
+ if (ldap_str2db_double(&fld[i].v.dbl, v.s) != 0) {
+ ERR("ldap: Error while converting '%.*s' to double\n",
+ v.len, ZSW(v.s));
+ return -1;
}
break;
diff --git a/modules/db_ldap/standards.txt b/modules/db_ldap/standards.txt
index 77d9d2c..e24244d 100644
--- a/modules/db_ldap/standards.txt
+++ b/modules/db_ldap/standards.txt
@@ -23,3 +23,5 @@ RFC4530: LDAP entryUUID Operational Attribute
directory. Such identifiers can be used to identify the object even
when the dn of the object changes. Unfortunately the entryUUID attribute
cannot by modified by the user and thus it is not directly usable for us.
+
+RFC2252 LDAPv3: Attribute Syntax Definitions
diff --git a/modules/db_ldap/todo.txt b/modules/db_ldap/todo.txt
index 7e9c544..14fb139 100644
--- a/modules/db_ldap/todo.txt
+++ b/modules/db_ldap/todo.txt
@@ -1,11 +1,68 @@
-* Support for authentication
-* Support for SSL
-* Copy all data from the configuration structures into db api structures
- (right now we only store pointers)
-* Implement < and > operators properly
-* Implement support for other than str parameters
-* Escape values of parameters injected into the search filter
-* Proper handling of NULL values
-* use the asynchronous functions of the api instead of synchronous
-* Support for multi-value attributes (they should be broken up into rows)
+* Authentication Support
+
+ The driver supports no authentication method at the moment, we should
+ include support for simple authentication at least, but better SASL.
+ This will take a change in the URI parser because the one provided
+ by libldap (which we use to parse the URI right now) does not support
+ embedded usernames and passwords in the URI.
+* TLS/SSL Support
+
+ The driver should support encrypted connections to LDAP servers and some
+ level of certificate validation. Currently there are no options or
+ parameters to configure SSL/TLS certificates and keys to use.
+
+* Copy Data from Config Data Structure
+
+ The driver maintains an internal data structure that gets initialized
+ from the supplied configuration file. The structure contains things like
+ search filters and field mapping tables. The LDAP specific extension
+ structures make a shallow copy of strings from the configuration
+ data structure, they should rather copy the whole string so that they
+ do not depend on the config structure.
+
+* Implement Support For < And > Operators
+
+ The LDAP search filter syntax (RFC4515) does not support < and >
+ operators, only <= and >=. Currently the ldap driver simply uses <= instead
+ of < and >= instead of >. We need a better implementation of this.
+
+* Implement Support For Other Than str Parameters
+
+* Escape Values of Parameters Injected Into the Search Filter
+
+ see RFC4515 for description of escaping.
+
+* Proper handling of NULL Values in Parameter.
+
+ Is it correct that parameters with NULL values are represented as
+ paramName= in the filter?
+
+* Use Asynchronous API Functions Instead of Synchronous
+
+ This would be useful when we have support for multiple database drivers
+ within one database context, then we could initiate multiple searches
+ simultaneously without being blocked waiting for the result.
+
+* Support For Multi-Value Attributes
+
+ The module should support multi-value attributes. Objects containing
+ attributes with multi-values should be returned as multiple records,
+ each record containing one value of the multi-value attribute. Currently
+ the module will report an error if it encounters a multi-value attribute.
+
+* Support For Time Zones in Generalized Times
+
+ The time conversion functions ignore time zones in GeneralizedTime
+ attributes, this should be fixed.
+
+* Handle Fractions of Seconds in Generalized Time
+
+ There is no need to account fractions of seconds because we store time
+ internally as time_t, but the parses should be able to skip fractions
+ of seconds gracefully.
+
+* Eliminate Use of All libldap Functions Marked as Deprecated
+
+ We should eliminate the use of all functions that are marked as deprecated
+ in the header field and remove LDAP_DEPRECATED define from all files.