r19725: sync samba3's ldb with samba4
authorStefan Metzmacher <metze@samba.org>
Wed, 15 Nov 2006 17:34:20 +0000 (17:34 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:15:50 +0000 (12:15 -0500)
metze
(This used to be commit 207643e9c9c75546f38a09f12ea0b574b08086c5)

31 files changed:
source3/lib/ldb/Makefile.in
source3/lib/ldb/common/ldb.c
source3/lib/ldb/common/ldb_dn.c
source3/lib/ldb/common/ldb_match.c
source3/lib/ldb/common/ldb_modules.c
source3/lib/ldb/common/ldb_msg.c
source3/lib/ldb/config.mk
source3/lib/ldb/include/ldb.h
source3/lib/ldb/include/ldb_private.h
source3/lib/ldb/ldb.pc.in
source3/lib/ldb/ldb_ildap/ldb_ildap.c
source3/lib/ldb/ldb_ldap/ldb_ldap.c
source3/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source3/lib/ldb/ldb_tdb/ldb_search.c
source3/lib/ldb/modules/asq.c
source3/lib/ldb/modules/ldb_map.c
source3/lib/ldb/modules/ldb_map_inbound.c
source3/lib/ldb/modules/ldb_map_outbound.c
source3/lib/ldb/modules/ldb_map_private.h
source3/lib/ldb/modules/paged_results.c
source3/lib/ldb/modules/rdn_name.c
source3/lib/ldb/modules/sort.c
source3/lib/ldb/nssldb/README.txt [new file with mode: 0644]
source3/lib/ldb/nssldb/ldb-grp.c [new file with mode: 0644]
source3/lib/ldb/nssldb/ldb-nss.c [new file with mode: 0644]
source3/lib/ldb/nssldb/ldb-nss.h [new file with mode: 0644]
source3/lib/ldb/nssldb/ldb-pwd.c [new file with mode: 0644]
source3/lib/ldb/samba/ldif_handlers.c
source3/lib/ldb/standalone.sh [new file with mode: 0755]
source3/lib/ldb/tests/test-sqlite3.sh
source3/lib/ldb/tools/cmdline.c

index c27ecf68c80fb2547d62bdc14342f449fcaba1dc..a091b4832ebe87f83f652076a7dfe390e73df7a5 100644 (file)
@@ -18,7 +18,7 @@ SLAPD = @SLAPD@
 EXTRA_OBJ=@EXTRA_OBJ@
 TESTS=test-tdb.sh @TESTS@
 
-CFLAGS=-I$(srcdir)/include -Iinclude -I$(srcdir) -I$(srcdir)/.. \
+CFLAGS=-g -I$(srcdir)/include -Iinclude -I$(srcdir) -I$(srcdir)/.. \
        @POPT_CFLAGS@ -I@tallocdir@ -I@tdbdir@/include -I@libreplacedir@ \
        -DLIBDIR=\"$(libdir)\" -DSHLIBEXT=\"@SHLIBEXT@\" -DUSE_MMAP=1 @CFLAGS@
 
@@ -41,6 +41,10 @@ MODULES_OBJ=$(MODDIR)/operational.o $(MODDIR)/rdn_name.o \
           $(MODDIR)/objectclass.o \
           $(MODDIR)/paged_results.o $(MODDIR)/sort.o $(MODDIR)/asq.o
 
+NSSDIR=nssldb
+NSS_OBJ= $(NSSDIR)/ldb-nss.o $(NSSDIR)/ldb-pwd.o $(NSSDIR)/ldb-grp.o
+NSS_LIB = lib/libnss_ldb.so.2
+
 OBJS = $(MODULES_OBJ) $(COMMON_OBJ) $(LDB_TDB_OBJ) @TDBOBJ@ @TALLOCOBJ@ @POPTOBJ@ @LIBREPLACEOBJ@ $(EXTRA_OBJ) 
 
 LDB_LIB = lib/libldb.a
@@ -53,6 +57,13 @@ EXAMPLES = examples/ldbreader examples/ldifreader
 
 DIRS = lib bin common ldb_tdb ldb_ldap ldb_sqlite3 modules tools examples
 
+default: all
+
+nss: nssdir all $(NSS_LIB)
+
+nssdir:
+       @mkdir -p $(NSSDIR)
+
 all: showflags dirs $(OBJS) $(LDB_LIB) $(BINS) $(EXAMPLES) manpages
 
 showflags:
@@ -72,6 +83,9 @@ lib/libldb.a: $(OBJS)
        ar -rv $@ $(OBJS)
        @-ranlib $@
 
+lib/libnss_ldb.so.2: $(NSS_OBJ) $(LIBS)
+       $(CC) -shared -Wl,-soname,libnss_ldb.so.2 -o lib/libnss_ldb.so.2 $(NSS_OBJ) $(OBJS) $(LIB_FLAGS)
+
 bin/ldbadd: tools/ldbadd.o tools/cmdline.o $(LIBS)
        $(CC) -o bin/ldbadd tools/ldbadd.o tools/cmdline.o $(LIB_FLAGS)
 
@@ -112,7 +126,7 @@ doxygen:
 
 clean:
        rm -f *.o */*.o *.gcov */*.gc?? tdbtest.ldb*
-       rm -f $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB)
+       rm -f $(BINS) $(TDB_OBJ) $(TALLOC_OBJ) $(LDB_LIB) $(NSS_LIB)
        rm -f man/*.1 man/*.3 man/*.html
        rm -f $(EXAMPLES)
        rm -rf apidocs/
index 7648abf795e27bfa7e73f64603ff061a556cee1b..9e0ee6ebca96bea13fe5cf705ee0f847b869402a 100644 (file)
@@ -522,7 +522,7 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
   Use talloc_free to free the ldb_message returned in 'res', if successful
 
 */
-static int ldb_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+int ldb_search_default_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
 {
        struct ldb_result *res;
        int n;
@@ -532,12 +532,13 @@ static int ldb_search_callback(struct ldb_context *ldb, void *context, struct ld
                return LDB_ERR_OPERATIONS_ERROR;
        }       
 
-       res = *((struct ldb_result **)context);
+       res = talloc_get_type(context, struct ldb_result);
 
        if (!res || !ares) {
+               ldb_set_errstring(ldb, "NULL res or ares in callback");
                goto error;
        }
-       
+
        switch (ares->type) {
        case LDB_REPLY_ENTRY:
                res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
@@ -564,19 +565,17 @@ static int ldb_search_callback(struct ldb_context *ldb, void *context, struct ld
 
                res->refs[n] = talloc_move(res->refs, &ares->referral);
                res->refs[n + 1] = NULL;
+       case LDB_REPLY_EXTENDED:
        case LDB_REPLY_DONE:
-               /* Should do something here to detect if this never
-                * happens */
+               /* TODO: we should really support controls on entries and referrals too! */
+               res->controls = talloc_move(res, &ares->controls);
                break;          
        }
-       talloc_steal(res, ares->controls);
        talloc_free(ares);
        return LDB_SUCCESS;
 
 error:
        talloc_free(ares);
-       talloc_free(res);
-       *((struct ldb_result **)context) = NULL;
        return LDB_ERR_OPERATIONS_ERROR;
 }
 
@@ -752,16 +751,19 @@ int ldb_search(struct ldb_context *ldb,
               enum ldb_scope scope,
               const char *expression,
               const char * const *attrs, 
-              struct ldb_result **res)
+              struct ldb_result **_res)
 {
        struct ldb_request *req;
        int ret;
+       struct ldb_result *res;
+
+       *_res = NULL;
 
-       *res = talloc_zero(ldb, struct ldb_result);
-       if (! *res) {
+       res = talloc_zero(ldb, struct ldb_result);
+       if (!res) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
-       
+
        ret = ldb_build_search_req(&req, ldb, ldb,
                                        base?base:ldb_get_default_basedn(ldb),
                                        scope,
@@ -769,7 +771,7 @@ int ldb_search(struct ldb_context *ldb,
                                        attrs,
                                        NULL,
                                        res,
-                                       ldb_search_callback);
+                                       ldb_search_default_callback);
 
        if (ret != LDB_SUCCESS) goto done;
 
@@ -785,10 +787,10 @@ int ldb_search(struct ldb_context *ldb,
 
 done:
        if (ret != LDB_SUCCESS) {
-               talloc_free(*res);
-               *res = NULL;
+               talloc_free(res);
        }
 
+       *_res = res;
        return ret;
 }
 
index e937a2b7fc40cbe10f8c4cfccc800e3203a025a7..48f471bf6fdf86a1d8a1b439ff7db02a01c36bd6 100644 (file)
 
 #define LDB_SPECIAL "@SPECIAL"
 
+/**
+   internal ldb exploded dn structures
+*/
+struct ldb_dn_component {
+       char *name;  
+       struct ldb_val value;
+};
+
+struct ldb_dn {
+       int comp_num;
+       struct ldb_dn_component *components;
+};
+
 int ldb_dn_is_special(const struct ldb_dn *dn)
 {
        if (dn == NULL || dn->comp_num != 1) return 0;
@@ -688,6 +701,26 @@ static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_d
        return dst;
 }
 
+/* Copy a DN but replace the old with the new base DN. */
+struct ldb_dn *ldb_dn_copy_rebase(void *mem_ctx, const struct ldb_dn *old, const struct ldb_dn *old_base, const struct ldb_dn *new_base)
+{
+       struct ldb_dn *new_dn;
+       int i, offset;
+
+       /* Perhaps we don't need to rebase at all? */
+       if (!old_base || !new_base) {
+               return ldb_dn_copy(mem_ctx, old);
+       }
+
+       offset = old->comp_num - old_base->comp_num;
+       new_dn = ldb_dn_copy_partial(mem_ctx, new_base, offset + new_base->comp_num);
+       for (i = 0; i < offset; i++) {
+               new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &(old->components[i]));
+       }
+
+       return new_dn;
+}
+
 /* copy specified number of elements of a dn into a new one
    element are copied from top level up to the unique rdn
    num_el may be greater than dn->comp_num (see ldb_dn_make_child)
@@ -799,15 +832,6 @@ failed:
 
 }
 
-struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component,
-                                               const struct ldb_dn *base)
-{
-       if (component == NULL) return NULL;
-
-       return ldb_dn_build_child(mem_ctx, component->name, 
-                                 (char *)component->value.data, base);
-}
-
 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2)
 {
        int i;
@@ -872,28 +896,6 @@ struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, c
        return dn;
 }
 
-struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn)
-{
-       struct ldb_dn_component *rdn;
-
-       if (dn == NULL) return NULL;
-
-       if (dn->comp_num < 1) {
-               return NULL;
-       }
-
-       rdn = talloc(mem_ctx, struct ldb_dn_component);
-       if (rdn == NULL) return NULL;
-
-       *rdn = ldb_dn_copy_component(mem_ctx, &dn->components[0]);
-       if (rdn->name == NULL) {
-               talloc_free(rdn);
-               return NULL;
-       }
-
-       return rdn;
-}
-
 /* Create a 'canonical name' string from a DN:
 
    ie dc=samba,dc=org -> samba.org/
@@ -962,3 +964,58 @@ char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
 char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
        return ldb_dn_canonical(mem_ctx, dn, 1);
 }
+
+int ldb_dn_get_comp_num(const struct ldb_dn *dn)
+{
+       return dn->comp_num;
+}
+
+const char *ldb_dn_get_component_name(const struct ldb_dn *dn, unsigned int num)
+{
+       if (num >= dn->comp_num) return NULL;
+       return dn->components[num].name;
+}
+
+const struct ldb_val *ldb_dn_get_component_val(const struct ldb_dn *dn, unsigned int num)
+{
+       if (num >= dn->comp_num) return NULL;
+       return &dn->components[num].value;
+}
+
+const char *ldb_dn_get_rdn_name(const struct ldb_dn *dn) {
+       if (dn->comp_num == 0) return NULL;
+       return dn->components[0].name;
+}
+
+const struct ldb_val *ldb_dn_get_rdn_val(const struct ldb_dn *dn) {
+       if (dn->comp_num == 0) return NULL;
+       return &dn->components[0].value;
+}
+
+int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
+{
+       char *n;
+       struct ldb_val v;
+
+       if (num >= dn->comp_num) {
+               return LDB_ERR_OTHER;
+       }
+
+       n = talloc_strdup(dn, name);
+       if ( ! n) {
+               return LDB_ERR_OTHER;
+       }
+
+       v.length = val.length;
+       v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
+       if ( ! v.data) {
+               return LDB_ERR_OTHER;
+       }
+
+       talloc_free(dn->components[num].name);
+       talloc_free(dn->components[num].value.data);
+       dn->components[num].name = n;
+       dn->components[num].value = v;
+
+       return LDB_SUCCESS;
+}
index 1fd12da7f3917c8b4172b1fdf055795c60874051..0cd220ad60706d9d6baf855d1afdc3087ec7b7e6 100644 (file)
@@ -58,7 +58,7 @@ static int ldb_match_scope(struct ldb_context *ldb,
                break;
 
        case LDB_SCOPE_ONELEVEL:
-               if (dn->comp_num == (base->comp_num + 1)) {
+               if (ldb_dn_get_comp_num(dn) == (ldb_dn_get_comp_num(base) + 1)) {
                        if (ldb_dn_compare_base(ldb, base, dn) == 0) {
                                ret = 1;
                        }
index 8bcafa36a8b8d0a845627e8787ec8c8e6eb34547..a6997b324a19acb228dd3a3bad28b24ecd11088b 100644 (file)
@@ -159,6 +159,7 @@ static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
                ldb_objectclass_init,   \
                ldb_paged_results_init, \
                ldb_sort_init,          \
+               ldb_asq_init,           \
                NULL                    \
        }
 #endif
@@ -205,17 +206,26 @@ int ldb_try_load_dso(struct ldb_context *ldb, const char *name)
        char *path;
        void *handle;
        int (*init_fn) (void);
+       char *modulesdir;
 
 #ifdef HAVE_DLOPEN
+       if (getenv("LD_LDB_MODULE_PATH") != NULL) {
+               modulesdir = talloc_strdup(ldb, getenv("LD_LDB_MODULE_PATH"));
+       } else {
 #ifdef _SAMBA_BUILD_
-       path = talloc_asprintf(ldb, "%s/ldb/%s.%s", dyn_MODULESDIR, name, dyn_SHLIBEXT);
+               modulesdir = talloc_asprintf(ldb, "%s/ldb", dyn_MODULESDIR);
 #else
-       path = talloc_asprintf(ldb, "%s/%s.%s", MODULESDIR, name, SHLIBEXT);
+               modulesdir = talloc_strdup(ldb, MODULESDIR);
 #endif
+       }
+
+       path = talloc_asprintf(ldb, "%s/%s.%s", modulesdir, name, SHLIBEXT);
+
+       talloc_free(modulesdir);
 
        ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s\n", name, path);
 
-       handle = dlopen(path, 0);
+       handle = dlopen(path, RTLD_NOW);
        if (handle == NULL) {
                ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s\n", name, path, dlerror());
                return -1;
index 46ab721e2e9d43274c2845cdc6db0e6615387019..9cb4cf5ed04edf6a47d6e90f248db425c6c7a9b3 100644 (file)
@@ -119,10 +119,10 @@ struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
 /*
   add an empty element to a message
 */
-int ldb_msg_add_empty(struct ldb_message *msg,
-                     const char *attr_name,
-                     int flags,
-                     struct ldb_message_element **return_el)
+int ldb_msg_add_empty( struct ldb_message *msg,
+                       const char *attr_name,
+                       int flags,
+                       struct ldb_message_element **return_el)
 {
        struct ldb_message_element *els;
 
index 4e3ba273d6a618149de83e399126f29dbbd5487f..cd80adf7213c4d2efc56c168f796eda50fa53aef 100644 (file)
@@ -167,7 +167,9 @@ OBJ_FILES = \
                common/ldb_controls.o \
                common/qsort.o
 PUBLIC_DEPENDENCIES = \
-               LIBTALLOC
+               LIBTALLOC \
+               DYNCONFIG \
+                                                                                                                                               SOCKET_WRAPPER
 MANPAGE = man/ldb.3
 PUBLIC_HEADERS = include/ldb.h include/ldb_errors.h
 #
index 2c332b2f9d4dff0fca6528e0352e35f4aa04535a..17a2ec75569bb06dc98eb83edbcb66f95a5429ef 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) Andrew Tridgell  2004
    Copyright (C) Stefan Metzmacher  2004
-   Copyright (C) Simo Sorce  2005
+   Copyright (C) Simo Sorce  2005-2006
 
      ** NOTE! The following LGPL license applies to the ldb
      ** library. This does NOT imply that all of Samba is released
@@ -86,18 +86,9 @@ struct ldb_val {
 #endif
 /*! \endcond */
 
-/**
-   internal ldb exploded dn structures
-*/
-struct ldb_dn_component {
-       char *name;  
-       struct ldb_val value;
-};
-
-struct ldb_dn {
-       int comp_num;
-       struct ldb_dn_component *components;
-};
+/* opaque ldb_dn structures, see ldb_dn.c for internals */
+struct ldb_dn_component;
+struct ldb_dn;
 
 /**
  There are a number of flags that are used with ldap_modify() in
@@ -193,12 +184,6 @@ enum ldb_scope {LDB_SCOPE_DEFAULT=-1,
 
 struct ldb_context;
 
-/*
-  the fuction type for the callback used in traversing the database
-*/
-typedef int (*ldb_traverse_fn)(struct ldb_context *, const struct ldb_message *);
-
-
 /* debugging uses one of the following levels */
 enum ldb_debug_level {LDB_DEBUG_FATAL, LDB_DEBUG_ERROR, 
                      LDB_DEBUG_WARNING, LDB_DEBUG_TRACE};
@@ -333,22 +318,25 @@ char *ldb_binary_encode_string(void *mem_ctx, const char *string);
 typedef int (*ldb_attr_handler_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, struct ldb_val *);
 typedef int (*ldb_attr_comparison_t)(struct ldb_context *, void *mem_ctx, const struct ldb_val *, const struct ldb_val *);
 
+/*
+  attribute handler structure
+
+  attr                 -> The attribute name
+  flags                        -> LDB_ATTR_FLAG_*
+  ldif_read_fn         -> convert from ldif to binary format
+  ldif_write_fn                -> convert from binary to ldif format
+  canonicalise_fn      -> canonicalise a value, for use by indexing and dn construction
+  comparison_fn                -> compare two values
+*/
+
 struct ldb_attrib_handler {
-       const char *attr;
 
-       /* LDB_ATTR_FLAG_* */
+       const char *attr;
        unsigned flags;
 
-       /* convert from ldif to binary format */
        ldb_attr_handler_t ldif_read_fn;
-
-       /* convert from binary to ldif format */
        ldb_attr_handler_t ldif_write_fn;
-       
-       /* canonicalise a value, for use by indexing and dn construction */
        ldb_attr_handler_t canonicalise_fn;
-
-       /* compare two values */
        ldb_attr_comparison_t comparison_fn;
 };
 
@@ -839,6 +827,145 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co
 */
 const struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb);
 
+
+/**
+  The Default iasync search callback function 
+
+  \param ldb the context associated with the database (from ldb_init())
+  \param context the callback context
+  \param ares a single reply from the async core
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+
+  \note this function expects the context to always be an struct ldb_result pointer
+  AND a talloc context, this function will steal on the context each message
+  from the ares reply passed on by the async core so that in the end all the
+  messages will be in the context (ldb_result)  memory tree.
+  Freeing the passed context (ldb_result tree) will free all the resources
+  (the request need to be freed separately and the result doe not depend on the
+  request that can be freed as sson as the search request is finished)
+*/
+
+int ldb_search_default_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares);
+
+/**
+  Helper function to build a search request
+
+  \param ret_req the request structure is returned here (talloced on mem_ctx)
+  \param ldb the context associated with the database (from ldb_init())
+  \param mem_ctx a talloc emmory context (used as parent of ret_req)
+  \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one)
+  \param scope the search scope for the query
+  \param expression the search expression to use for this query
+  \param attrs the search attributes for the query (pass NULL if none required)
+  \param controls an array of controls
+  \param context the callback function context
+  \param the callback function to handle the async replies
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_search_req(struct ldb_request **ret_req,
+                       struct ldb_context *ldb,
+                       void *mem_ctx,
+                       const struct ldb_dn *base,
+                       enum ldb_scope scope,
+                       const char *expression,
+                       const char * const *attrs,
+                       struct ldb_control **controls,
+                       void *context,
+                       ldb_request_callback_t callback);
+
+/**
+  Helper function to build an add request
+
+  \param ret_req the request structure is returned here (talloced on mem_ctx)
+  \param ldb the context associated with the database (from ldb_init())
+  \param mem_ctx a talloc emmory context (used as parent of ret_req)
+  \param message contains the entry to be added 
+  \param controls an array of controls
+  \param context the callback function context
+  \param the callback function to handle the async replies
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_add_req(struct ldb_request **ret_req,
+                       struct ldb_context *ldb,
+                       void *mem_ctx,
+                       const struct ldb_message *message,
+                       struct ldb_control **controls,
+                       void *context,
+                       ldb_request_callback_t callback);
+
+/**
+  Helper function to build a modify request
+
+  \param ret_req the request structure is returned here (talloced on mem_ctx)
+  \param ldb the context associated with the database (from ldb_init())
+  \param mem_ctx a talloc emmory context (used as parent of ret_req)
+  \param message contains the entry to be modified
+  \param controls an array of controls
+  \param context the callback function context
+  \param the callback function to handle the async replies
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_mod_req(struct ldb_request **ret_req,
+                       struct ldb_context *ldb,
+                       void *mem_ctx,
+                       const struct ldb_message *message,
+                       struct ldb_control **controls,
+                       void *context,
+                       ldb_request_callback_t callback);
+
+/**
+  Helper function to build a delete request
+
+  \param ret_req the request structure is returned here (talloced on mem_ctx)
+  \param ldb the context associated with the database (from ldb_init())
+  \param mem_ctx a talloc emmory context (used as parent of ret_req)
+  \param dn the DN to be deleted
+  \param controls an array of controls
+  \param context the callback function context
+  \param the callback function to handle the async replies
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_del_req(struct ldb_request **ret_req,
+                       struct ldb_context *ldb,
+                       void *mem_ctx,
+                       const struct ldb_dn *dn,
+                       struct ldb_control **controls,
+                       void *context,
+                       ldb_request_callback_t callback);
+
+/**
+  Helper function to build a rename request
+
+  \param ret_req the request structure is returned here (talloced on mem_ctx)
+  \param ldb the context associated with the database (from ldb_init())
+  \param mem_ctx a talloc emmory context (used as parent of ret_req)
+  \param olddn the old DN
+  \param newdn the new DN
+  \param controls an array of controls
+  \param context the callback function context
+  \param the callback function to handle the async replies
+
+  \return result code (LDB_SUCCESS on success, or a failure code)
+*/
+
+int ldb_build_rename_req(struct ldb_request **ret_req,
+                       struct ldb_context *ldb,
+                       void *mem_ctx,
+                       const struct ldb_dn *olddn,
+                       const struct ldb_dn *newdn,
+                       struct ldb_control **controls,
+                       void *context,
+                       ldb_request_callback_t callback);
+
 /**
   Search the database
 
@@ -846,7 +973,7 @@ const struct ldb_dn *ldb_get_default_basedn(struct ldb_context *ldb);
   records that match an LDAP-like search expression
 
   \param ldb the context associated with the database (from ldb_init())
-  \param base the Base Distinguished Name for the query (pass NULL for root DN)
+  \param base the Base Distinguished Name for the query (use ldb_dn_new() for an empty one)
   \param scope the search scope for the query
   \param expression the search expression to use for this query
   \param attrs the search attributes for the query (pass NULL if none required)
@@ -1156,18 +1283,25 @@ struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, void *mem_ctx, const str
 struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, void *mem_ctx, const char *dn);
 struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el);
 struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn);
+struct ldb_dn *ldb_dn_copy_rebase(void *mem_ctx, const struct ldb_dn *old, const struct ldb_dn *old_base, const struct ldb_dn *new_base);
 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn);
 struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
                                                               const char *val);
 struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
                                                 const char * value,
                                                 const struct ldb_dn *base);
-struct ldb_dn *ldb_dn_make_child(void *mem_ctx,
-                                const struct ldb_dn_component *component,
-                                const struct ldb_dn *base);
 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2);
 struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...) PRINTF_ATTRIBUTE(3,4);
-struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn);
+char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn);
+char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn);
+int ldb_dn_get_comp_num(const struct ldb_dn *dn);
+const char *ldb_dn_get_component_name(const struct ldb_dn *dn, unsigned int num);
+const struct ldb_val *ldb_dn_get_component_val(const struct ldb_dn *dn, unsigned int num);
+const char *ldb_dn_get_rdn_name(const struct ldb_dn *dn);
+const struct ldb_val *ldb_dn_get_rdn_val(const struct ldb_dn *dn);
+int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val);
+
+
 
 /* useful functions for ldb_message structure manipulation */
 int ldb_dn_cmp(struct ldb_context *ldb, const char *dn1, const char *dn2);
@@ -1228,9 +1362,9 @@ struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
    add a new empty element to a ldb_message
 */
 int ldb_msg_add_empty(struct ldb_message *msg,
-                     const char *attr_name,
-                     int flags,
-                     struct ldb_message_element **return_el);
+               const char *attr_name,
+               int flags,
+               struct ldb_message_element **return_el);
 
 /**
    add a element to a ldb_message
@@ -1239,9 +1373,9 @@ int ldb_msg_add(struct ldb_message *msg,
                const struct ldb_message_element *el, 
                int flags);
 int ldb_msg_add_value(struct ldb_message *msg, 
-                     const char *attr_name,
-                     const struct ldb_val *val,
-                     struct ldb_message_element **return_el);
+               const char *attr_name,
+               const struct ldb_val *val,
+               struct ldb_message_element **return_el);
 int ldb_msg_add_steal_value(struct ldb_message *msg, 
                      const char *attr_name,
                      struct ldb_val *val);
@@ -1407,9 +1541,6 @@ char *ldb_timestring(void *mem_ctx, time_t t);
 */
 time_t ldb_string_to_time(const char *s);
 
-char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn);
-char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn);
-
 
 void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp);
 #endif
index 3cacd5e292479f663054518e6362890d1c28739f..3902bb2fc28f275669c9c01def3e05efe43a1372 100644 (file)
@@ -170,6 +170,7 @@ int ldb_operational_init(void);
 int ldb_paged_results_init(void);
 int ldb_rdn_name_init(void);
 int ldb_schema_init(void);
+int ldb_asq_init(void);
 int ldb_sort_init(void);
 int ldb_ldap_init(void);
 int ldb_ildap_init(void);
index 8b0536e21e5126f33e75d39ec75c99f56347b117..815d663a7c89dc09d6a95b54a670316c5d5b7bae 100644 (file)
@@ -7,6 +7,9 @@ modulesdir=@modulesdir@
 Name: ldb
 Description: An LDAP-like embedded database
 Version: 4.0
-Libs: @LIBS@ -L${libdir} -lldb
+Requires.private: tdb
+Requires: talloc
+Libs: -L${libdir} -lldb
 Cflags: -I${includedir} @CFLAGS@
 Modulesdir: ${modulesdir}
+URL: http://ldb.samba.org/
index 3843d2b82508f7c13fe325de23e203b9af044817..51ae031cf93f384f4be0e067bc6558d74a5a0504 100644 (file)
@@ -49,6 +49,7 @@
 #include "libcli/ldap/ldap.h"
 #include "libcli/ldap/ldap_client.h"
 #include "auth/auth.h"
+#include "auth/credentials/credentials.h"
 
 struct ildb_private {
        struct ldap_connection *ldap;
@@ -639,8 +640,8 @@ static int ildb_rename(struct ldb_module *module, struct ldb_request *req)
 
        msg->r.ModifyDNRequest.newrdn = 
                talloc_asprintf(msg, "%s=%s",
-                               req->op.rename.newdn->components[0].name,
-                               ldb_dn_escape_value(msg, req->op.rename.newdn->components[0].value));
+                               ldb_dn_get_rdn_name(req->op.rename.newdn),
+                               ldb_dn_escape_value(msg, *ldb_dn_get_rdn_val(req->op.rename.newdn)));
        if (msg->r.ModifyDNRequest.newrdn == NULL) {
                talloc_free(msg);
                return LDB_ERR_OPERATIONS_ERROR;
index a17e80cde02cedd6aa9138a9612a9910f8fa191f..cdc1a500f80bb5f3c625a6ba81461d905ef56fa9 100644 (file)
@@ -463,8 +463,8 @@ static int lldb_rename(struct ldb_module *module, struct ldb_request *req)
        }
 
        newrdn = talloc_asprintf(lldb_ac, "%s=%s",
-                                req->op.rename.newdn->components[0].name,
-                                ldb_dn_escape_value(lldb, req->op.rename.newdn->components[0].value));
+                                ldb_dn_get_rdn_name(req->op.rename.newdn),
+                                ldb_dn_escape_value(lldb, *(ldb_dn_get_rdn_val(req->op.rename.newdn))));
        if (!newrdn) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
index 8dd25db1d6c628db4948e5d9578579dd447e7d13..4f9b0f6370f38cac96cee17e59abdf4cf8ae7cc0 100644 (file)
@@ -2,7 +2,7 @@
    ldb database library
    
    Copyright (C) Derrell Lipman  2005
-   Copyright (C) Simo Sorce 2005
+   Copyright (C) Simo Sorce 2005-2006
    
    ** NOTE! The following LGPL license applies to the ldb
    ** library. This does NOT imply that all of Samba is released
@@ -57,9 +57,9 @@ struct lsql_context {
        int (*callback)(struct ldb_context *, void *, struct ldb_reply *);
 };
 
-static struct ldb_handle *init_handle(struct lsqlite3_private *lsqlite3, struct ldb_module *module,
-                                           void *context,
-                                           int (*callback)(struct ldb_context *, void *, struct ldb_reply *))
+static struct ldb_handle *init_handle(struct lsqlite3_private *lsqlite3,
+                                       struct ldb_module *module,
+                                       struct ldb_request *req)
 {
        struct lsql_context *ac;
        struct ldb_handle *h;
@@ -85,8 +85,8 @@ static struct ldb_handle *init_handle(struct lsqlite3_private *lsqlite3, struct
        h->status = LDB_SUCCESS;
 
        ac->module = module;
-       ac->context = context;
-       ac->callback = callback;
+       ac->context = req->context;
+       ac->callback = req->callback;
 
        return h;
 }
@@ -370,6 +370,7 @@ static char *parsetree_to_sql(struct ldb_module *module,
                } else if (strcasecmp(t->u.equality.attr, "dn") == 0) {
                        /* DN query is a special ldb case */
                        char *cdn = ldb_dn_linearize_casefold(module->ldb,
+                                                             mem_ctx,
                                                              ldb_dn_explode(module->ldb,
                                                              (const char *)value.data));
 
@@ -828,7 +829,7 @@ static long long lsqlite3_get_eid(struct ldb_module *module, const struct ldb_dn
                return -1;
        }
 
-       cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, dn));
+       cdn = ldb_dn_linearize(local_ctx, ldb_dn_casefold(module->ldb, local_ctx, dn));
        if (!cdn) goto done;
 
        eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, local_ctx, cdn);
@@ -842,53 +843,8 @@ done:
  * Interface functions referenced by lsqlite3_ops
  */
 
-static int lsql_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
-{
-       struct ldb_result *res = NULL;
-       
-       if (!context) {
-               ldb_set_errstring(ldb, "NULL Context in callback");
-               goto error;
-       }       
-
-       res = *((struct ldb_result **)context);
-
-       if (!res || !ares) {
-               goto error;
-       }
-
-       if (ares->type == LDB_REPLY_ENTRY) {
-               res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
-               if (! res->msgs) {
-                       goto error;
-               }
-
-               res->msgs[res->count + 1] = NULL;
-
-               res->msgs[res->count] = talloc_move(res->msgs, &ares->message);
-               res->count++;
-       } else {
-               ldb_debug(ldb, LDB_DEBUG_ERROR, "unrecognized async reply in ltdb_search_sync_callback!\n");
-               goto error;
-       }
-
-       talloc_free(ares);
-       return LDB_SUCCESS;
-
-error:
-       if (ares) talloc_free(ares);
-       if (res) talloc_free(res);
-       if (context) *((struct ldb_result **)context) = NULL;
-       return LDB_ERR_OPERATIONS_ERROR;
-}
-
 /* search for matching records, by tree */
-int lsql_search_async(struct ldb_module *module, const struct ldb_dn *base,
-                     enum ldb_scope scope, struct ldb_parse_tree *tree,
-                     const char * const *attrs,
-                     void *context,
-                     int (*callback)(struct ldb_context *, void *, struct ldb_reply *),
-                     struct ldb_handle **handle)
+int lsql_search(struct ldb_module *module, struct ldb_request *req)
 {
        struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
        struct lsql_context *lsql_ac;
@@ -898,32 +854,29 @@ int lsql_search_async(struct ldb_module *module, const struct ldb_dn *base,
        char *query = NULL;
         int ret;
 
-       *handle = init_handle(lsqlite3, module, context, callback);
-       if (*handle == NULL) {
-               talloc_free(*handle);
+       req->handle = init_handle(lsqlite3, module, req);
+       if (req->handle == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_context);
+       lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
 
-       if (base) {
-               norm_basedn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, base));
+       if ((req->op.search.base == NULL || req->op.search.base->comp_num == 0) &&
+           (req->op.search.scope == LDB_SCOPE_BASE || req->op.search.scope == LDB_SCOPE_ONELEVEL))
+               return LDB_ERR_OPERATIONS_ERROR;
+
+       if (req->op.search.base) {
+               norm_basedn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, lsql_ac, req->op.search.base));
                if (norm_basedn == NULL) {
                        ret = LDB_ERR_INVALID_DN_SYNTAX;
                        goto failed;
                }
        } else norm_basedn = talloc_strdup(lsql_ac, "");
 
-       if (*norm_basedn == '\0' &&
-               (scope == LDB_SCOPE_BASE || scope == LDB_SCOPE_ONELEVEL)) {
-                       ret = LDB_ERR_UNWILLING_TO_PERFORM;
-                       goto failed;
-               }
-
         /* Convert filter into a series of SQL conditions (constraints) */
-       sqlfilter = parsetree_to_sql(module, lsql_ac, tree);
+       sqlfilter = parsetree_to_sql(module, lsql_ac, req->op.search.tree);
         
-        switch(scope) {
+        switch(req->op.search.scope) {
         case LDB_SCOPE_DEFAULT:
         case LDB_SCOPE_SUBTREE:
                if (*norm_basedn != '\0') {
@@ -1033,12 +986,12 @@ int lsql_search_async(struct ldb_module *module, const struct ldb_dn *base,
        / * */
 
        lsql_ac->current_eid = 0;
-       lsql_ac->attrs = attrs;
+       lsql_ac->attrs = req->op.search.attrs;
        lsql_ac->ares = NULL;
 
-       (*handle)->state = LDB_ASYNC_PENDING;
+       req->handle->state = LDB_ASYNC_PENDING;
 
-       ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, *handle, &errmsg);
+       ret = sqlite3_exec(lsqlite3->sqlite, query, lsqlite3_search_callback, req->handle, &errmsg);
        if (ret != SQLITE_OK) {
                if (errmsg) {
                        ldb_set_errstring(module->ldb, errmsg);
@@ -1053,70 +1006,39 @@ int lsql_search_async(struct ldb_module *module, const struct ldb_dn *base,
                if (lsql_ac->ares->message == NULL)
                        goto failed;
                        
-               (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, lsql_ac->ares);
-               if ((*handle)->status != LDB_SUCCESS)
+               req->handle->status = lsql_ac->callback(module->ldb, lsql_ac->context, lsql_ac->ares);
+               if (req->handle->status != LDB_SUCCESS)
                        goto failed;
        }
 
-       (*handle)->state = LDB_ASYNC_DONE;
+       req->handle->state = LDB_ASYNC_DONE;
 
        return LDB_SUCCESS;
 
 failed:
-        talloc_free(*handle);
        return LDB_ERR_OPERATIONS_ERROR;
 }
 
-static int lsql_search_bytree(struct ldb_module * module, const struct ldb_dn* base,
-                             enum ldb_scope scope, struct ldb_parse_tree * tree,
-                             const char * const * attrs, struct ldb_result ** res)
-{
-       struct ldb_handle *handle;
-       int ret;
-
-       *res = talloc_zero(module, struct ldb_result);
-       if (! *res) {
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       ret = lsql_search_async(module, base, scope, tree, attrs,
-                               res, &lsql_search_sync_callback,
-                               &handle);
-
-       if (ret == LDB_SUCCESS) {
-               ret = ldb_wait(handle, LDB_WAIT_ALL);
-               talloc_free(handle);
-       }
-
-       if (ret != LDB_SUCCESS) {
-               talloc_free(*res);
-       }
-
-       return ret;
-}
-
 /* add a record */
-static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
-                         void *context,
-                         int (*callback)(struct ldb_context *, void *, struct ldb_reply *),
-                         struct ldb_handle **handle)
+static int lsql_add(struct ldb_module *module, struct ldb_request *req)
 {
        struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
        struct lsql_context *lsql_ac;
+       struct ldb_message *msg = req->op.add.message;
         long long eid;
        char *dn, *ndn;
        char *errmsg;
        char *query;
        int i;
-       int ret = LDB_ERR_OPERATIONS_ERROR;
+       int ret = LDB_SUCCESS;
 
-       *handle = init_handle(lsqlite3, module, context, callback);
-       if (*handle == NULL) {
-               goto failed;
+       req->handle = init_handle(lsqlite3, module, req);
+       if (req->handle == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_context);
-       (*handle)->state = LDB_ASYNC_DONE;
-       (*handle)->status = LDB_SUCCESS;
+       lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
+       req->handle->state = LDB_ASYNC_DONE;
+       req->handle->status = LDB_SUCCESS;
 
         /* See if this is an ltdb special */
        if (ldb_dn_is_special(msg->dn)) {
@@ -1126,26 +1048,28 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
 #warning "insert subclasses into object class tree"
                        ret = LDB_ERR_UNWILLING_TO_PERFORM;
-                       goto failed;
+                       goto done;
                }
 
 /*
                c = ldb_dn_explode(local_ctx, "@INDEXLIST");
                if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
 #warning "should we handle indexes somehow ?"
-                       goto failed;
+                       ret = LDB_ERR_UNWILLING_TO_PERFORM;
+                       goto done;
                }
 */
-                /* Others are implicitly ignored */
-                return LDB_SUCCESS;
+                /* Others return an error */
+               ret = LDB_ERR_UNWILLING_TO_PERFORM;
+               goto done;
        }
 
        /* create linearized and normalized dns */
        dn = ldb_dn_linearize(lsql_ac, msg->dn);
-       ndn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, msg->dn));
+       ndn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, lsql_ac, msg->dn));
        if (dn == NULL || ndn == NULL) {
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        query = lsqlite3_tprintf(lsql_ac,
@@ -1156,7 +1080,7 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                                dn, ndn);
        if (query == NULL) {
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg);
@@ -1166,13 +1090,13 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                        free(errmsg);
                }
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        eid = lsqlite3_get_eid_ndn(lsqlite3->sqlite, lsql_ac, ndn);
        if (eid == -1) {
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        for (i = 0; i < msg->num_elements; i++) {
@@ -1185,7 +1109,7 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                attr = ldb_attr_casefold(lsql_ac, el->name);
                if (attr == NULL) {
                        ret = LDB_ERR_OTHER;
-                       goto failed;
+                       goto done;
                }
 
                h = ldb_attrib_handler(module->ldb, el->name);
@@ -1199,7 +1123,7 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                        h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
                        if (value.data == NULL) {
                                ret = LDB_ERR_OTHER;
-                               goto failed;
+                               goto done;
                        }
 
                        insert = lsqlite3_tprintf(lsql_ac,
@@ -1211,7 +1135,7 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                                        el->values[j].data, value.data);
                        if (insert == NULL) {
                                ret = LDB_ERR_OTHER;
-                               goto failed;
+                               goto done;
                        }
 
                        ret = sqlite3_exec(lsqlite3->sqlite, insert, NULL, NULL, &errmsg);
@@ -1221,58 +1145,38 @@ static int lsql_add_async(struct ldb_module *module, struct ldb_message *msg,
                                        free(errmsg);
                                }
                                ret = LDB_ERR_OTHER;
-                               goto failed;
+                               goto done;
                        }
                }
        }
 
-       if (lsql_ac->callback)
-               (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+       if (lsql_ac->callback) {
+               req->handle->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+       }
        
-        return LDB_SUCCESS;
-
-failed:
-       talloc_free(*handle);
-       return ret;
-}
-
-static int lsql_add(struct ldb_module *module, const struct ldb_message *msg)
-{
-       struct ldb_handle *handle;
-       int ret;
-
-       ret = lsql_add_async(module, msg, NULL, NULL, &handle);
-
-       if (ret != LDB_SUCCESS)
-               return ret;
-
-       ret = ldb_wait(handle, LDB_WAIT_ALL);
-
-       talloc_free(handle);
+done:
+       req->handle->state = LDB_ASYNC_DONE;
        return ret;
 }
 
-
 /* modify a record */
-static int lsql_modify_async(struct ldb_module *module, const struct ldb_message *msg,
-                            void *context,
-                            int (*callback)(struct ldb_context *, void *, struct ldb_reply *),
-                            struct ldb_handle **handle)
+static int lsql_modify(struct ldb_module *module, struct ldb_request *req)
 {
        struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
        struct lsql_context *lsql_ac;
+       struct ldb_message *msg = req->op.mod.message;
         long long eid;
        char *errmsg;
        int i;
-       int ret = LDB_ERR_OPERATIONS_ERROR;
+       int ret = LDB_SUCCESS;
 
-       *handle = init_handle(lsqlite3, module, context, callback);
-       if (*handle == NULL) {
-               goto failed;
+       req->handle = init_handle(lsqlite3, module, req);
+       if (req->handle == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_context);
-       (*handle)->state = LDB_ASYNC_DONE;
-       (*handle)->status = LDB_SUCCESS;
+       lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
+       req->handle->state = LDB_ASYNC_DONE;
+       req->handle->status = LDB_SUCCESS;
 
         /* See if this is an ltdb special */
        if (ldb_dn_is_special(msg->dn)) {
@@ -1282,17 +1186,18 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                if (ldb_dn_compare(module->ldb, msg->dn, c) == 0) {
 #warning "modify subclasses into object class tree"
                        ret = LDB_ERR_UNWILLING_TO_PERFORM;
-                       goto failed;
+                       goto done;
                }
 
-                /* Others are implicitly ignored */
-                return LDB_SUCCESS;
+                /* Others return an error */
+               ret = LDB_ERR_UNWILLING_TO_PERFORM;
+                goto done;
        }
 
        eid = lsqlite3_get_eid(module, msg->dn);
        if (eid == -1) {
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        for (i = 0; i < msg->num_elements; i++) {
@@ -1307,7 +1212,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                attr = ldb_attr_casefold(lsql_ac, el->name);
                if (attr == NULL) {
                        ret = LDB_ERR_OTHER;
-                       goto failed;
+                       goto done;
                }
 
                h = ldb_attrib_handler(module->ldb, el->name);
@@ -1324,7 +1229,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                                eid, attr);
                        if (mod == NULL) {
                                ret = LDB_ERR_OTHER;
-                               goto failed;
+                               goto done;
                        }
 
                        ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg);
@@ -1334,7 +1239,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                        free(errmsg);
                                }
                                ret = LDB_ERR_OTHER;
-                               goto failed;
+                               goto done;
                         }
 
                        /* MISSING break is INTENTIONAL */
@@ -1349,7 +1254,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
                                if (value.data == NULL) {
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
 
                                mod = lsqlite3_tprintf(lsql_ac,
@@ -1362,7 +1267,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
 
                                if (mod == NULL) {
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
 
                                ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg);
@@ -1372,7 +1277,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                                free(errmsg);
                                        }
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
                        }
 
@@ -1388,7 +1293,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                                        eid, attr);
                                if (mod == NULL) {
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
 
                                ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg);
@@ -1398,7 +1303,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                                free(errmsg);
                                        }
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
                        }
 
@@ -1410,7 +1315,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                h->canonicalise_fn(module->ldb, lsql_ac, &(el->values[j]), &value);
                                if (value.data == NULL) {
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
 
                                mod = lsqlite3_tprintf(lsql_ac,
@@ -1422,7 +1327,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
 
                                if (mod == NULL) {
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
 
                                ret = sqlite3_exec(lsqlite3->sqlite, mod, NULL, NULL, &errmsg);
@@ -1432,7 +1337,7 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                                                free(errmsg);
                                        }
                                        ret = LDB_ERR_OTHER;
-                                       goto failed;
+                                       goto done;
                                }
                        }
 
@@ -1440,57 +1345,37 @@ static int lsql_modify_async(struct ldb_module *module, const struct ldb_message
                }
        }
 
-       if (lsql_ac->callback)
-               (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+       if (lsql_ac->callback) {
+               req->handle->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
+       }
        
-        return LDB_SUCCESS;
-
-failed:
-       talloc_free(*handle);
-       return ret;
-}
-
-static int lsql_modify(struct ldb_module *module, const struct ldb_message *msg)
-{
-       struct ldb_handle *handle;
-       int ret;
-
-       ret = lsql_modify_async(module, msg, NULL, NULL, &handle);
-
-       if (ret != LDB_SUCCESS)
-               return ret;
-
-       ret = ldb_wait(handle, LDB_WAIT_ALL);
-
-       talloc_free(handle);
+done:
+       req->handle->state = LDB_ASYNC_DONE;
        return ret;
 }
 
 /* delete a record */
-static int lsql_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
-                            void *context,
-                            int (*callback)(struct ldb_context *, void *, struct ldb_reply *),
-                            struct ldb_handle **handle)
+static int lsql_delete(struct ldb_module *module, struct ldb_request *req)
 {
        struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
        struct lsql_context *lsql_ac;
         long long eid;
        char *errmsg;
        char *query;
-       int ret = LDB_ERR_OPERATIONS_ERROR;
+       int ret = LDB_SUCCESS;
 
 
-       *handle = init_handle(lsqlite3, module, context, callback);
-       if (*handle == NULL) {
-               goto failed;
+       req->handle = init_handle(lsqlite3, module, req);
+       if (req->handle == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_context);
-       (*handle)->state = LDB_ASYNC_DONE;
-       (*handle)->status = LDB_SUCCESS;
+       lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
+       req->handle->state = LDB_ASYNC_DONE;
+       req->handle->status = LDB_SUCCESS;
 
-       eid = lsqlite3_get_eid(module, dn);
+       eid = lsqlite3_get_eid(module, req->op.del.dn);
        if (eid == -1) {
-               goto failed;
+               goto done;
        }
 
        query = lsqlite3_tprintf(lsql_ac,
@@ -1501,7 +1386,7 @@ static int lsql_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
                                eid, eid);
        if (query == NULL) {
                ret = LDB_ERR_OTHER;
-               goto failed;
+               goto done;
        }
 
        ret = sqlite3_exec(lsqlite3->sqlite, query, NULL, NULL, &errmsg);
@@ -1510,68 +1395,43 @@ static int lsql_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
                        ldb_set_errstring(module->ldb, errmsg);
                        free(errmsg);
                }
-               ret = LDB_ERR_OPERATIONS_ERROR;
-               goto failed;
+               req->handle->status = LDB_ERR_OPERATIONS_ERROR;
+               goto done;
        }
 
-       if (lsql_ac->callback)
-               (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
-       
-        return LDB_SUCCESS;
-
-failed:
-       talloc_free(*handle);
-       return ret;
-}
-
-static int lsql_delete(struct ldb_module *module, const struct ldb_dn *dn)
-{
-       struct ldb_handle *handle;
-       int ret;
-
-       /* ignore ltdb specials */
-       if (ldb_dn_is_special(dn)) {
-               return LDB_SUCCESS;
+       if (lsql_ac->callback) {
+               ret = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
        }
-
-       ret = lsql_delete_async(module, dn, NULL, NULL, &handle);
-
-       if (ret != LDB_SUCCESS)
-               return ret;
-
-       ret = ldb_wait(handle, LDB_WAIT_ALL);
-
-       talloc_free(handle);
+       
+done:
+       req->handle->state = LDB_ASYNC_DONE;
        return ret;
 }
 
 /* rename a record */
-static int lsql_rename_async(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn,
-                            void *context,
-                            int (*callback)(struct ldb_context *, void *, struct ldb_reply *),
-                            struct ldb_handle **handle)
+static int lsql_rename(struct ldb_module *module, struct ldb_request *req)
 {
        struct lsqlite3_private *lsqlite3 = talloc_get_type(module->private_data, struct lsqlite3_private);
        struct lsql_context *lsql_ac;
        char *new_dn, *new_cdn, *old_cdn;
        char *errmsg;
        char *query;
-       int ret = LDB_ERR_OPERATIONS_ERROR;
+       int ret = LDB_SUCCESS;
 
-       *handle = init_handle(lsqlite3, module, context, callback);
-       if (*handle == NULL) {
-               goto failed;
+       req->handle = init_handle(lsqlite3, module, req);
+       if (req->handle == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       lsql_ac = talloc_get_type((*handle)->private_data, struct lsql_context);
-       (*handle)->state = LDB_ASYNC_DONE;
-       (*handle)->status = LDB_SUCCESS;
+       lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);
+       req->handle->state = LDB_ASYNC_DONE;
+       req->handle->status = LDB_SUCCESS;
 
        /* create linearized and normalized dns */
-       old_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, olddn));
-       new_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, newdn));
-       new_dn = ldb_dn_linearize(lsql_ac, newdn);
+       old_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, lsql_ac, req->op.rename.olddn));
+       new_cdn = ldb_dn_linearize(lsql_ac, ldb_dn_casefold(module->ldb, lsql_ac, req->op.rename.newdn));
+       new_dn = ldb_dn_linearize(lsql_ac, req->op.rename.newdn);
        if (old_cdn == NULL || new_cdn == NULL || new_dn == NULL) {
-               goto failed;
+               goto done;
        }
 
        /* build the SQL query */
@@ -1580,7 +1440,7 @@ static int lsql_rename_async(struct ldb_module *module, const struct ldb_dn *old
                                 "WHERE norm_dn = '%q';",
                                 new_dn, new_cdn, old_cdn);
        if (query == NULL) {
-               goto failed;
+               goto done;
        }
 
        /* execute */
@@ -1591,38 +1451,15 @@ static int lsql_rename_async(struct ldb_module *module, const struct ldb_dn *old
                        free(errmsg);
                }
                ret = LDB_ERR_OPERATIONS_ERROR;
-               goto failed;
+               goto done;
        }
 
-       if (lsql_ac->callback)
-               (*handle)->status = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
-       
-        return LDB_SUCCESS;
-
-failed:
-       talloc_free(*handle);
-       return ret;
-}
-
-static int lsql_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
-{
-       struct ldb_handle *handle;
-       int ret;
-
-       /* ignore ltdb specials */
-       if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
-               return LDB_SUCCESS;
+       if (lsql_ac->callback) {
+               ret = lsql_ac->callback(module->ldb, lsql_ac->context, NULL);
        }
 
-
-       ret = lsql_rename_async(module, olddn, newdn, NULL, NULL, &handle);
-
-       if (ret != LDB_SUCCESS)
-               return ret;
-
-       ret = ldb_wait(handle, LDB_WAIT_ALL);
-
-       talloc_free(handle);
+done:
+       req->handle->state = LDB_ASYNC_DONE;
        return ret;
 }
 
@@ -1687,6 +1524,41 @@ static int lsql_del_trans(struct ldb_module *module)
        return -1;
 }
 
+static int destructor(struct lsqlite3_private *lsqlite3)
+{        
+       if (lsqlite3->sqlite) {
+               sqlite3_close(lsqlite3->sqlite);
+       }
+       return 0;
+}
+
+static int lsql_request(struct ldb_module *module, struct ldb_request *req)
+{
+       return LDB_ERR_OPERATIONS_ERROR;
+}
+
+static int lsql_wait(struct ldb_handle *handle, enum ldb_wait_type type)
+{
+       return handle->status;
+}
+
+/*
+ * Table of operations for the sqlite3 backend
+ */
+static const struct ldb_module_ops lsqlite3_ops = {
+       .name              = "sqlite",
+       .search            = lsql_search,
+       .add               = lsql_add,
+        .modify            = lsql_modify,
+        .del               = lsql_delete,
+        .rename            = lsql_rename,
+       .request           = lsql_request,
+       .start_transaction = lsql_start_trans,
+       .end_transaction   = lsql_end_trans,
+       .del_transaction   = lsql_del_trans,
+       .wait              = lsql_wait,
+};
+
 /*
  * Static functions
  */
@@ -1796,12 +1668,12 @@ static int initialize(struct lsqlite3_private *lsqlite3,
                 "    ('TOP', '0001');");
         
         /* Skip protocol indicator of url  */
-        if (strncmp(url, "sqlite://", 9) != 0) {
+        if (strncmp(url, "sqlite3://", 10) != 0) {
                 return SQLITE_MISUSE;
         }
         
         /* Update pointer to just after the protocol indicator */
-        url += 9;
+        url += 10;
         
         /* Try to open the (possibly empty/non-existent) database */
         if ((ret = sqlite3_open(url, &lsqlite3->sqlite)) != SQLITE_OK) {
@@ -1959,112 +1831,6 @@ failed:
        return -1;
 }
 
-static int destructor(struct lsqlite3_private *lsqlite3)
-{        
-       if (lsqlite3->sqlite) {
-               sqlite3_close(lsqlite3->sqlite);
-       }
-       return 0;
-}
-
-static int lsql_wait(struct ldb_handle *handle, enum ldb_wait_type type)
-{
-       return handle->status;
-}
-
-static int lsql_request(struct ldb_module *module, struct ldb_request *req)
-{
-       /* check for oustanding critical controls and return an error if found */
-
-       if (req->controls != NULL) {
-               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_sqlite3 backend!\n");
-       }
-
-       if (check_critical_controls(req->controls)) {
-               return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
-       }
-       
-       switch (req->operation) {
-
-       case LDB_SEARCH:
-               return lsql_search_bytree(module,
-                                         req->op.search.base,
-                                         req->op.search.scope, 
-                                         req->op.search.tree, 
-                                         req->op.search.attrs, 
-                                         &req->op.search.res);
-
-       case LDB_ADD:
-               return lsql_add(module, req->op.add.message);
-
-       case LDB_MODIFY:
-               return lsql_modify(module, req->op.mod.message);
-
-       case LDB_DELETE:
-               return lsql_delete(module, req->op.del.dn);
-
-       case LDB_RENAME:
-               return lsql_rename(module,
-                                       req->op.rename.olddn,
-                                       req->op.rename.newdn);
-
-       case LDB_SEARCH:
-               return lsql_search_async(module,
-                                       req->op.search.base,
-                                       req->op.search.scope, 
-                                       req->op.search.tree, 
-                                       req->op.search.attrs,
-                                       req->context,
-                                       req->callback,
-                                       &req->handle);
-/*
-       case LDB_ADD:
-               return lsql_add_async(module,
-                                       req->op.add.message,
-                                       req->context,
-                                       req->callback,
-                                       &req->handle);
-
-       case LDB_MODIFY:
-               return lsql_modify_async(module,
-                                       req->op.mod.message,
-                                       req->context,
-                                       req->callback,
-                                       &req->handle);
-*/
-       case LDB_DELETE:
-               return lsql_delete_async(module,
-                                       req->op.del.dn,
-                                       req->context,
-                                       req->callback,
-                                       &req->handle);
-
-       case LDB_RENAME:
-               return lsql_rename_async(module,
-                                       req->op.rename.olddn,
-                                       req->op.rename.newdn,
-                                       req->context,
-                                       req->callback,
-                                       &req->handle);
-
-       default:
-               return LDB_ERR_OPERATIONS_ERROR;
-
-       }
-}
-
-/*
- * Table of operations for the sqlite3 backend
- */
-static const struct ldb_module_ops lsqlite3_ops = {
-       .name              = "sqlite",
-       .request           = lsql_request,
-       .start_transaction = lsql_start_trans,
-       .end_transaction   = lsql_end_trans,
-       .del_transaction   = lsql_del_trans,
-       .wait              = lsql_wait,
-};
-
 /*
  * connect to the database
  */
index 4b76c437b6435cceb526abd64f51c85d30427484..884eccd36227eb23b51000b0db7cc9e9fb7eabaa 100644 (file)
@@ -464,7 +464,7 @@ int ltdb_search(struct ldb_module *module, struct ldb_request *req)
        struct ldb_reply *ares;
        int ret;
 
-       if ((req->op.search.base == NULL || req->op.search.base->comp_num == 0) &&
+       if ((req->op.search.base == NULL || ldb_dn_get_comp_num(req->op.search.base) == 0) &&
            (req->op.search.scope == LDB_SCOPE_BASE || req->op.search.scope == LDB_SCOPE_ONELEVEL))
                return LDB_ERR_OPERATIONS_ERROR;
 
index 354bbf2bc87210bb04d28ada9fe2cd0806d763c1..2fed6aac50a8a79190cb4f662128d482ef46c40c 100644 (file)
@@ -454,8 +454,7 @@ static int asq_init(struct ldb_module *module)
 
        ret = ldb_request(module->ldb, req);
        if (ret != LDB_SUCCESS) {
-               ldb_debug(module->ldb, LDB_DEBUG_ERROR, "asq: Unable to register control with rootdse!\n");
-               return LDB_ERR_OTHER;
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "asq: Unable to register control with rootdse!\n");
        }
 
        return ldb_next_init(module);
index 1cdeeeb2934729ea41c34a1066f2ff0195ad11d6..32e64f3eb2cf1fd8c15f95cc2905acaf1ac2fda4 100644 (file)
@@ -181,60 +181,16 @@ BOOL map_check_local_db(struct ldb_module *module)
        return True;
 }
 
-/* WARK: verbatim copy from ldb_dn.c */
-static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
-{
-       struct ldb_dn_component dst;
-
-       memset(&dst, 0, sizeof(dst));
-
-       if (src == NULL) {
-               return dst;
-       }
-
-       dst.value = ldb_val_dup(mem_ctx, &(src->value));
-       if (dst.value.data == NULL) {
-               return dst;
-       }
-
-       dst.name = talloc_strdup(mem_ctx, src->name);
-       if (dst.name == NULL) {
-               talloc_free(dst.value.data);
-       }
-
-       return dst;
-}
-
-/* Copy a DN but replace the old with the new base DN. */
-static struct ldb_dn *ldb_dn_rebase(void *mem_ctx, const struct ldb_dn *old, const struct ldb_dn *old_base, const struct ldb_dn *new_base)
-{
-       struct ldb_dn *new;
-       int i, offset;
-
-       /* Perhaps we don't need to rebase at all? */
-       if (!old_base || !new_base) {
-               return ldb_dn_copy(mem_ctx, old);
-       }
-
-       offset = old->comp_num - old_base->comp_num;
-       new = ldb_dn_copy_partial(mem_ctx, new_base, offset + new_base->comp_num);
-       for (i = 0; i < offset; i++) {
-               new->components[i] = ldb_dn_copy_component(new->components, &(old->components[i]));
-       }
-
-       return new;
-}
-
 /* Copy a DN with the base DN of the local partition. */
 static struct ldb_dn *ldb_dn_rebase_local(void *mem_ctx, const struct ldb_map_context *data, const struct ldb_dn *dn)
 {
-       return ldb_dn_rebase(mem_ctx, dn, data->remote_base_dn, data->local_base_dn);
+       return ldb_dn_copy_rebase(mem_ctx, dn, data->remote_base_dn, data->local_base_dn);
 }
 
 /* Copy a DN with the base DN of the remote partition. */
 static struct ldb_dn *ldb_dn_rebase_remote(void *mem_ctx, const struct ldb_map_context *data, const struct ldb_dn *dn)
 {
-       return ldb_dn_rebase(mem_ctx, dn, data->local_base_dn, data->remote_base_dn);
+       return ldb_dn_copy_rebase(mem_ctx, dn, data->local_base_dn, data->remote_base_dn);
 }
 
 /* Run a request and make sure it targets the remote partition. */
@@ -460,23 +416,23 @@ int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attr
  * ================== */
 
 /* Map an ldb value into the remote partition. */
-struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val)
+struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val)
 {
        if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_local)) {
-               return map->u.convert.convert_local(module, mem_ctx, &val);
+               return map->u.convert.convert_local(module, mem_ctx, val);
        }
 
-       return ldb_val_dup(mem_ctx, &val);
+       return ldb_val_dup(mem_ctx, val);
 }
 
 /* Map an ldb value back into the local partition. */
-struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val)
+struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val)
 {
        if (map && (map->type == MAP_CONVERT) && (map->u.convert.convert_remote)) {
-               return map->u.convert.convert_remote(module, mem_ctx, &val);
+               return map->u.convert.convert_remote(module, mem_ctx, val);
        }
 
-       return ldb_val_dup(mem_ctx, &val);
+       return ldb_val_dup(mem_ctx, val);
 }
 
 
@@ -500,10 +456,11 @@ struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, const
 {
        const struct ldb_map_context *data = map_get_context(module);
        struct ldb_dn *newdn;
-       struct ldb_dn_component *old, *new;
        const struct ldb_map_attribute *map;
        enum ldb_map_attr_type map_type;
-       int i;
+       const char *name;
+       struct ldb_val value;
+       int i, ret;
 
        if (dn == NULL) {
                return NULL;
@@ -516,10 +473,8 @@ struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, const
        }
 
        /* For each RDN, map the component name and possibly the value */
-       for (i = 0; i < newdn->comp_num; i++) {
-               old = &dn->components[i];
-               new = &newdn->components[i];
-               map = map_attr_find_local(data, old->name);
+       for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
+               map = map_attr_find_local(data, ldb_dn_get_component_name(dn, i));
 
                /* Unknown attribute - leave this RDN as is and hope the best... */
                if (map == NULL) {
@@ -533,21 +488,30 @@ struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, const
                case MAP_GENERATE:
                        ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                  "MAP_IGNORE/MAP_GENERATE attribute '%s' "
-                                 "used in DN!\n", old->name);
+                                 "used in DN!\n", ldb_dn_get_component_name(dn, i));
                        goto failed;
 
                case MAP_CONVERT:
                        if (map->u.convert.convert_local == NULL) {
                                ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                          "'convert_local' not set for attribute '%s' "
-                                         "used in DN!\n", old->name);
+                                         "used in DN!\n", ldb_dn_get_component_name(dn, i));
                                goto failed;
                        }
                        /* fall through */
                case MAP_KEEP:
                case MAP_RENAME:
-                       new->name = discard_const_p(char, map_attr_map_local(newdn->components, map, old->name));
-                       new->value = ldb_val_map_local(module, newdn->components, map, old->value);
+                       name = map_attr_map_local(newdn, map, ldb_dn_get_component_name(dn, i));
+                       if (name == NULL) goto failed;
+
+                       value = ldb_val_map_local(module, newdn, map, ldb_dn_get_component_val(dn, i));
+                       if (value.data == NULL) goto failed;
+
+                       ret = ldb_dn_set_component(newdn, i, name, value);
+                       if (ret != LDB_SUCCESS) {
+                               goto failed;
+                       }
+
                        break;
                }
        }
@@ -564,10 +528,11 @@ struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const
 {
        const struct ldb_map_context *data = map_get_context(module);
        struct ldb_dn *newdn;
-       struct ldb_dn_component *old, *new;
        const struct ldb_map_attribute *map;
        enum ldb_map_attr_type map_type;
-       int i;
+       const char *name;
+       struct ldb_val value;
+       int i, ret;
 
        if (dn == NULL) {
                return NULL;
@@ -580,10 +545,8 @@ struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const
        }
 
        /* For each RDN, map the component name and possibly the value */
-       for (i = 0; i < newdn->comp_num; i++) {
-               old = &dn->components[i];
-               new = &newdn->components[i];
-               map = map_attr_find_remote(data, old->name);
+       for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
+               map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i));
 
                /* Unknown attribute - leave this RDN as is and hope the best... */
                if (map == NULL) {
@@ -597,21 +560,30 @@ struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const
                case MAP_GENERATE:
                        ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                  "MAP_IGNORE/MAP_GENERATE attribute '%s' "
-                                 "used in DN!\n", old->name);
+                                 "used in DN!\n", ldb_dn_get_component_name(dn, i));
                        goto failed;
 
                case MAP_CONVERT:
                        if (map->u.convert.convert_remote == NULL) {
                                ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
                                          "'convert_remote' not set for attribute '%s' "
-                                         "used in DN!\n", old->name);
+                                         "used in DN!\n", ldb_dn_get_component_name(dn, i));
                                goto failed;
                        }
                        /* fall through */
                case MAP_KEEP:
                case MAP_RENAME:
-                       new->name = discard_const_p(char, map_attr_map_remote(newdn->components, map, old->name));
-                       new->value = ldb_val_map_remote(module, newdn->components, map, old->value);
+                       name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
+                       if (name == NULL) goto failed;
+
+                       value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i));
+                       if (value.data == NULL) goto failed;
+
+                       ret = ldb_dn_set_component(newdn, i, name, value);
+                       if (ret != LDB_SUCCESS) {
+                               goto failed;
+                       }
+
                        break;
                }
        }
@@ -1296,13 +1268,13 @@ static int map_init_maps(struct ldb_module *module, struct ldb_map_context *data
 }
 
 /* Copy the list of provided module operations. */
-struct ldb_module_ops ldb_map_get_ops(void)
+_PUBLIC_ struct ldb_module_ops ldb_map_get_ops(void)
 {
        return map_ops;
 }
 
 /* Initialize global private data. */
-int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, 
+_PUBLIC_ int ldb_map_init(struct ldb_module *module, const struct ldb_map_attribute *attrs, 
                 const struct ldb_map_objectclass *ocls,
                 const char * const *wildcard_attributes,
                 const char *name)
index b83a17e502c41a641247ad9d76ae9d285c0882f7..38454b2b1168c36fe4173f2f256a99cc6ea572fc 100644 (file)
@@ -56,7 +56,7 @@ static struct ldb_message_element *ldb_msg_el_map_local(struct ldb_module *modul
        el->name = map_attr_map_local(el, map, old->name);
 
        for (i = 0; i < el->num_values; i++) {
-               el->values[i] = ldb_val_map_local(module, el->values, map, old->values[i]);
+               el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
        }
 
        return el;
index ff3b5c3aa2b26c2aa778a3f805d6e0851e88f50c..dc213f36d183953bc8e222ab9eece98f85d92dbc 100644 (file)
@@ -195,6 +195,7 @@ static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_ele
                if (ldb_msg_add_empty(msg, el->name, 0, &old) != 0) {
                        return -1;
                }
+               talloc_free(old->name);
        }
 
        /* copy new element */
@@ -234,7 +235,7 @@ static struct ldb_message_element *ldb_msg_el_map_remote(struct ldb_module *modu
        el->name = map_attr_map_remote(el, map, old->name);
 
        for (i = 0; i < el->num_values; i++) {
-               el->values[i] = ldb_val_map_remote(module, el->values, map, old->values[i]);
+               el->values[i] = ldb_val_map_remote(module, el->values, map, &old->values[i]);
        }
 
        return el;
@@ -728,21 +729,21 @@ int map_subtree_collect_remote_simple(struct ldb_module *module, void *mem_ctx,
                                *new = NULL;
                                return 0;
                        }
-                       *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, *tree->u.substring.chunks[i]);
+                       *(*new)->u.substring.chunks[i] = ldb_val_map_local(module, *new, map, tree->u.substring.chunks[i]);
                        (*new)->u.substring.chunks[i+1] = NULL;
                }
                break;
        }
        case LDB_OP_EQUALITY:
-               (*new)->u.equality.value = ldb_val_map_local(module, *new, map, tree->u.equality.value);
+               (*new)->u.equality.value = ldb_val_map_local(module, *new, map, &tree->u.equality.value);
                break;
        case LDB_OP_LESS:
        case LDB_OP_GREATER:
        case LDB_OP_APPROX:
-               (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, tree->u.comparison.value);
+               (*new)->u.comparison.value = ldb_val_map_local(module, *new, map, &tree->u.comparison.value);
                break;
        case LDB_OP_EXTENDED:
-               (*new)->u.extended.value = ldb_val_map_local(module, *new, map, tree->u.extended.value);
+               (*new)->u.extended.value = ldb_val_map_local(module, *new, map, &tree->u.extended.value);
                (*new)->u.extended.rule_id = talloc_strdup(*new, tree->u.extended.rule_id);
                break;
        default:                        /* unknown kind of simple subtree */
index 7fb2745179cce72395fc9e251b9a0d4f39e9af65..ae53ebbdd48e8bc5dbf4cbe67f683f0e223b6d5c 100644 (file)
@@ -77,8 +77,8 @@ const char *map_attr_map_local(void *mem_ctx, const struct ldb_map_attribute *ma
 const char *map_attr_map_remote(void *mem_ctx, const struct ldb_map_attribute *map, const char *attr);
 int map_attrs_merge(struct ldb_module *module, void *mem_ctx, const char ***attrs, const char * const *more_attrs);
 
-struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val);
-struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, struct ldb_val val);
+struct ldb_val ldb_val_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val);
+struct ldb_val ldb_val_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_val *val);
 
 struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_dn *dn);
 struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_dn *dn);
index 3ab575ef6b04484c41bcd520ebd299cac3ecfcaa..c4b1ecf26b35d2e3021d5f9e29c6cd8e037e93ff 100644 (file)
@@ -544,9 +544,7 @@ static int paged_request_init(struct ldb_module *module)
 
        ret = ldb_request(module->ldb, req);
        if (ret != LDB_SUCCESS) {
-               ldb_debug(module->ldb, LDB_DEBUG_ERROR, "paged_request: Unable to register control with rootdse!\n");
-               talloc_free(req);
-               return LDB_ERR_OTHER;
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "paged_request: Unable to register control with rootdse!\n");
        }
 
        talloc_free(req);
index 510a43dbc941cc6635da081b0687ed4090157de8..bab5f6a014901feef45a10b7e5d45bc8f42309c3 100644 (file)
@@ -58,7 +58,8 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
        struct ldb_request *down_req;
        struct ldb_message *msg;
        struct ldb_message_element *attribute;
-       struct ldb_dn_component *rdn;
+       const char *rdn_name;
+       struct ldb_val rdn_val;
        int i, ret;
 
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
@@ -80,43 +81,45 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       rdn = ldb_dn_get_rdn(msg, msg->dn);
-       if (rdn == NULL) {
+       rdn_name = ldb_dn_get_rdn_name(msg->dn);
+       if (rdn_name == NULL) {
                talloc_free(down_req);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        
+       rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(msg->dn));
+       
        /* Perhaps someone above us tried to set this? */
        if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
                attribute->num_values = 0;
        }
 
-       if (ldb_msg_add_value(msg, "name", &rdn->value, NULL) != 0) {
+       if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
                talloc_free(down_req);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       attribute = rdn_name_find_attribute(msg, rdn->name);
+       attribute = rdn_name_find_attribute(msg, rdn_name);
 
        if (!attribute) {
-               if (ldb_msg_add_value(msg, rdn->name, &rdn->value, NULL) != 0) {
+               if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
                        talloc_free(down_req);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
        } else {
-               const struct ldb_attrib_handler *handler = ldb_attrib_handler(module->ldb, rdn->name);
+               const struct ldb_attrib_handler *handler = ldb_attrib_handler(module->ldb, rdn_name);
 
                for (i = 0; i < attribute->num_values; i++) {
-                       if (handler->comparison_fn(module->ldb, msg, &rdn->value, &attribute->values[i]) == 0) {
+                       if (handler->comparison_fn(module->ldb, msg, &rdn_val, &attribute->values[i]) == 0) {
                                /* overwrite so it matches in case */
-                               attribute->values[i] = rdn->value;
+                               attribute->values[i] = rdn_val;
                                break;
                        }
                }
                if (i == attribute->num_values) {
                        ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, 
-                                     "RDN mismatch on %s: %s", 
-                                     ldb_dn_linearize(msg, msg->dn), rdn->name);
+                                     "RDN mismatch on %s: %s (%s)", 
+                                     ldb_dn_linearize(msg, msg->dn), rdn_name, rdn_val.data);
                        talloc_free(down_req);
                        return LDB_ERR_OPERATIONS_ERROR;
                }
@@ -190,16 +193,12 @@ static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
 static int rdn_name_rename_do_mod(struct ldb_handle *h) {
 
        struct rename_context *ac;
-       struct ldb_dn_component *rdn;
+       const char *rdn_name;
+       struct ldb_val rdn_val;
        struct ldb_message *msg;
 
        ac = talloc_get_type(h->private_data, struct rename_context);
 
-       rdn = ldb_dn_get_rdn(ac, ac->orig_req->op.rename.newdn);
-       if (rdn == NULL) {
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-       
        ac->mod_req = talloc_zero(ac, struct ldb_request);
 
        ac->mod_req->operation = LDB_MODIFY;
@@ -213,16 +212,23 @@ static int rdn_name_rename_do_mod(struct ldb_handle *h) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       if (ldb_msg_add_empty(msg, rdn->name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
+       rdn_name = ldb_dn_get_rdn_name(ac->orig_req->op.rename.newdn);
+       if (rdn_name == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->orig_req->op.rename.newdn));
+       
+       if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
-       if (ldb_msg_add_value(msg, rdn->name, &rdn->value, NULL) != 0) {
+       if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
        if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
-       if (ldb_msg_add_value(msg, "name", &rdn->value, NULL) != 0) {
+       if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
index 3a0598c5289c40dd5aece7ae74bc3f9e8455ede1..4fa03f8bfa34c4b1435fbadfa9ea532e570e52b8 100644 (file)
@@ -423,9 +423,7 @@ static int server_sort_init(struct ldb_module *module)
 
        ret = ldb_request(module->ldb, req);
        if (ret != LDB_SUCCESS) {
-               ldb_debug(module->ldb, LDB_DEBUG_ERROR, "server_sort: Unable to register control with rootdse!\n");
-               talloc_free(req);
-               return LDB_ERR_OTHER;
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "server_sort: Unable to register control with rootdse!\n");
        }
 
        talloc_free(req);
diff --git a/source3/lib/ldb/nssldb/README.txt b/source3/lib/ldb/nssldb/README.txt
new file mode 100644 (file)
index 0000000..ddba62b
--- /dev/null
@@ -0,0 +1,34 @@
+
+This test code requires a tdb that is configured for to use the asq module.
+You can do that adding the following record to a tdb:
+
+dn: @MODULES
+@LIST: asq
+
+Other modules can be used as well (like rdn_name for example)
+
+The uidNumber 0 and the gidNumber 0 are considered invalid.
+
+The user records should contain the followin attributes:
+uid (required)                 the user name
+userPassword (optional)                the user password (if not present "LDB" is
+                               returned in the password field)
+uidNumber (required)           the user uid
+gidNumber (required)           the user primary gid
+gecos (optional)               the GECOS
+homeDirectory (required)       the home directory
+loginShell (required)          the login shell
+memberOf (required)            all the groups the user is member of should
+                               be reported here using their DNs. The
+                               primary group as well.
+
+The group accounts should contain the following attributes:
+cn (required)                  the group name
+uesrPassword (optional)                the group password (if not present "LDB" is
+                               returned in the password field)
+gidNumber (required)           the group gid
+member (optional)              the DNs of the member users, also the ones
+                               that have this group as primary
+
+
+SSS
diff --git a/source3/lib/ldb/nssldb/ldb-grp.c b/source3/lib/ldb/nssldb/ldb-grp.c
new file mode 100644 (file)
index 0000000..f33ec65
--- /dev/null
@@ -0,0 +1,427 @@
+/* 
+   LDB nsswitch module
+
+   Copyright (C) Simo Sorce 2006
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "ldb-nss.h"
+
+extern struct _ldb_nss_context *_ldb_nss_ctx;
+
+const char *_ldb_nss_gr_attrs[] = {
+       "cn",
+       "userPassword",
+       "gidNumber",
+       NULL
+};
+
+const char *_ldb_nss_mem_attrs[] = {
+       "uid",
+       NULL
+};
+
+#define _NSS_LDB_ENOMEM(amem) \
+       do { \
+               if ( ! amem) { \
+                       errno = ENOMEM; \
+                       talloc_free(memctx); \
+                       return NSS_STATUS_UNAVAIL; \
+               } \
+       } while(0)
+
+/* This setgrent, getgrent, endgrent is not very efficient */
+
+NSS_STATUS _nss_ldb_setgrent(void)
+{
+       int ret;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       _ldb_nss_ctx->gr_cur = 0;
+       if (_ldb_nss_ctx->gr_res != NULL) {
+               talloc_free(_ldb_nss_ctx->gr_res);
+               _ldb_nss_ctx->gr_res = NULL;
+       }
+
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        _LDB_NSS_GRENT_FILTER,
+                        _ldb_nss_gr_attrs,
+                        &_ldb_nss_ctx->gr_res);
+       if (ret != LDB_SUCCESS) {
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_endgrent(void)
+{
+       int ret;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       _ldb_nss_ctx->gr_cur = 0;
+       if (_ldb_nss_ctx->gr_res) {
+               talloc_free(_ldb_nss_ctx->gr_res);
+               _ldb_nss_ctx->gr_res = NULL;
+       }
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop)
+{
+       int ret;
+       struct ldb_result *res;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       *errnop = 0;
+
+       if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) {
+               /* already returned all entries */
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result);
+       if ( ! res) {
+               errno = *errnop = ENOMEM;
+               _ldb_nss_ctx->gr_cur++; /* skip this entry */
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       ret = _ldb_nss_group_request(&res,
+                               _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, 
+                               _ldb_nss_mem_attrs,
+                               "member");
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               *errnop = errno;
+               talloc_free(res);
+               _ldb_nss_ctx->gr_cur++; /* skip this entry */
+               return ret;
+       }
+
+       ret = _ldb_nss_fill_group(result_buf,
+                               buffer,
+                               buflen,
+                               errnop,
+                               _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur],
+                               res);
+
+       talloc_free(res);
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               if (ret != NSS_STATUS_TRYAGAIN) {
+                       _ldb_nss_ctx->gr_cur++; /* skip this entry */
+               }
+               return ret;
+       }
+
+       /* this entry is ok, increment counter to nex entry */
+       _ldb_nss_ctx->gr_cur++;
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
+{
+       int ret;
+       char *filter;
+       TALLOC_CTX *ctx;
+       struct ldb_result *gr_res;
+       struct ldb_result *mem_res;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       ctx = talloc_new(_ldb_nss_ctx->ldb);
+       if ( ! ctx) {
+               *errnop = errno = ENOMEM;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* build the filter for this uid */
+       filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name);
+       if (filter == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOMEM;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* search the entry */
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        filter,
+                        _ldb_nss_gr_attrs,
+                        &gr_res);
+       if (ret != LDB_SUCCESS) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       talloc_steal(ctx, gr_res);
+
+       /* if none found return */
+       if (gr_res->count == 0) {
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_NOTFOUND;
+               goto done;
+       }
+
+       if (gr_res->count != 1) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       mem_res = talloc_zero(ctx, struct ldb_result);
+       if ( ! mem_res) {
+               errno = *errnop = ENOMEM;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       ret = _ldb_nss_group_request(&mem_res,
+                                       gr_res->msgs[0]->dn,
+                                       _ldb_nss_mem_attrs,
+                                       "member");
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               *errnop = errno;
+               goto done;
+       }
+
+       ret = _ldb_nss_fill_group(result_buf,
+                               buffer,
+                               buflen,
+                               errnop,
+                               gr_res->msgs[0],
+                               mem_res);
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               goto done;
+       }
+
+       ret = NSS_STATUS_SUCCESS;
+done:
+       talloc_free(ctx);
+       return ret;
+}
+
+NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
+{
+       int ret;
+       char *filter;
+       TALLOC_CTX *ctx;
+       struct ldb_result *gr_res;
+       struct ldb_result *mem_res;
+
+       if (gid == 0) { /* we don't serve root gid by policy */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       ctx = talloc_new(_ldb_nss_ctx->ldb);
+       if ( ! ctx) {
+               *errnop = errno = ENOMEM;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* build the filter for this uid */
+       filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid);
+       if (filter == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOMEM;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* search the entry */
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        filter,
+                        _ldb_nss_gr_attrs,
+                        &gr_res);
+       if (ret != LDB_SUCCESS) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       talloc_steal(ctx, gr_res);
+
+       /* if none found return */
+       if (gr_res->count == 0) {
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_NOTFOUND;
+               goto done;
+       }
+
+       if (gr_res->count != 1) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       mem_res = talloc_zero(ctx, struct ldb_result);
+       if ( ! mem_res) {
+               errno = *errnop = ENOMEM;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       ret = _ldb_nss_group_request(&mem_res,
+                                       gr_res->msgs[0]->dn,
+                                       _ldb_nss_mem_attrs,
+                                       "member");
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               *errnop = errno;
+               goto done;
+       }
+
+       ret = _ldb_nss_fill_group(result_buf,
+                               buffer,
+                               buflen,
+                               errnop,
+                               gr_res->msgs[0],
+                               mem_res);
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               goto done;
+       }
+
+       ret = NSS_STATUS_SUCCESS;
+done:
+       talloc_free(ctx);
+       return ret;
+}
+
+NSS_STATUS _nss_ldb_initgroups_dyn(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop)
+{
+       int ret;
+       char *filter;
+       const char * attrs[] = { "uidNumber", "gidNumber", NULL };
+       struct ldb_result *uid_res;
+       struct ldb_result *mem_res;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
+       if ( ! mem_res) {
+               errno = *errnop = ENOMEM;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* build the filter for this name */
+       filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
+       if (filter == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* search the entry */
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        filter,
+                        attrs,
+                        &uid_res);
+       if (ret != LDB_SUCCESS) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       talloc_steal(mem_res, uid_res);
+
+       /* if none found return */
+       if (uid_res->count == 0) {
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_NOTFOUND;
+               goto done;
+       }
+
+       if (uid_res->count != 1) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       ret = _ldb_nss_group_request(&mem_res,
+                                       uid_res->msgs[0]->dn,
+                                       attrs,
+                                       "memberOf");
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               *errnop = errno;
+               goto done;
+       }
+
+       ret = _ldb_nss_fill_initgr(group,
+                               limit,
+                               start,
+                               size,
+                               groups,
+                               errnop,
+                               mem_res);
+
+       if (ret != NSS_STATUS_SUCCESS) {
+               goto done;
+       }
+
+       ret = NSS_STATUS_SUCCESS;
+
+done:
+       talloc_free(mem_res);
+       return ret;
+}
diff --git a/source3/lib/ldb/nssldb/ldb-nss.c b/source3/lib/ldb/nssldb/ldb-nss.c
new file mode 100644 (file)
index 0000000..614f6e1
--- /dev/null
@@ -0,0 +1,402 @@
+/* 
+   LDB nsswitch module
+
+   Copyright (C) Simo Sorce 2006
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "ldb-nss.h"
+
+struct _ldb_nss_context *_ldb_nss_ctx = NULL;
+
+NSS_STATUS _ldb_nss_init(void)
+{
+       int ret;
+
+       pid_t mypid = getpid();
+
+       if (_ldb_nss_ctx != NULL) {
+               if (_ldb_nss_ctx->pid == mypid) {
+                       /* already initialized */
+                       return NSS_STATUS_SUCCESS;
+               } else {
+                       /* we are in a forked child now, reinitialize */
+                       talloc_free(_ldb_nss_ctx);
+                       _ldb_nss_ctx = NULL;
+               }
+       }
+               
+       _ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid);
+       if (_ldb_nss_ctx == NULL) {
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       _ldb_nss_ctx->pid = mypid;
+
+       ret = ldb_global_init();
+       if (ret != 0) {
+               goto failed;
+       }
+
+       _ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx);
+       if (_ldb_nss_ctx->ldb == NULL) {
+               goto failed;
+       }
+
+       ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
+       if (ret != LDB_SUCCESS) {
+               goto failed;
+       }
+
+       _ldb_nss_ctx->base = ldb_dn_explode(_ldb_nss_ctx, _LDB_NSS_BASEDN);
+       if (_ldb_nss_ctx->base == NULL) {
+               goto failed;
+       }
+
+       _ldb_nss_ctx->pw_cur = 0;
+       _ldb_nss_ctx->pw_res = NULL;
+       _ldb_nss_ctx->gr_cur = 0;
+       _ldb_nss_ctx->gr_res = NULL;
+
+       return NSS_STATUS_SUCCESS;
+
+failed:
+       /* talloc_free(_ldb_nss_ctx); */
+       _ldb_nss_ctx = NULL;
+       return NSS_STATUS_UNAVAIL;
+}
+
+NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
+                               char *buffer,
+                               int buflen,
+                               int *errnop,
+                               struct ldb_message *msg)
+{
+       int len;
+       int bufpos;
+       const char *tmp;
+
+       bufpos = 0;
+
+       /* get username */
+       tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
+       if (tmp == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->pw_name = &buffer[bufpos];
+       bufpos += len;
+
+       /* get userPassword */
+       tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
+       if (tmp == NULL) {
+               tmp = "LDB";
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->pw_passwd = &buffer[bufpos];
+       bufpos += len;
+
+       /* this backend never serves an uid 0 user */
+       result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
+       if (result->pw_uid == 0) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
+       if (result->pw_gid == 0) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* get gecos */
+       tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
+       if (tmp == NULL) {
+               tmp = "";
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->pw_gecos = &buffer[bufpos];
+       bufpos += len;
+
+       /* get homeDirectory */
+       tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
+       if (tmp == NULL) {
+               tmp = "";
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->pw_dir = &buffer[bufpos];
+       bufpos += len;
+
+       /* get shell */
+       tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
+       if (tmp == NULL) {
+               tmp = "";
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->pw_shell = &buffer[bufpos];
+       bufpos += len;
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _ldb_nss_fill_group(struct group *result,
+                               char *buffer,
+                               int buflen,
+                               int *errnop,
+                               struct ldb_message *group,
+                               struct ldb_result *members)
+{
+       const char *tmp;
+       size_t len;
+       size_t bufpos;
+       size_t lsize;
+       int i;
+
+       bufpos = 0;
+
+       /* get group name */
+       tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
+       if (tmp == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->gr_name = &buffer[bufpos];
+       bufpos += len;
+
+       /* get userPassword */
+       tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
+       if (tmp == NULL) {
+               tmp = "LDB";
+       }
+       len = strlen(tmp)+1;
+       if (bufpos + len > buflen) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       }
+       memcpy(&buffer[bufpos], tmp, len);
+       result->gr_passwd = &buffer[bufpos];
+       bufpos += len;
+
+       result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
+       if (result->gr_gid == 0) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* check if there is enough memory for the list of pointers */
+       lsize = (members->count + 1) * sizeof(char *);
+
+       /* align buffer on pointer boundary */
+       bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
+       if ((buflen - bufpos) < lsize) {
+               /* buffer too small */
+               *errnop = errno = EAGAIN;
+               return NSS_STATUS_TRYAGAIN;
+       } 
+
+       result->gr_mem = (char **)&buffer[bufpos];
+       bufpos += lsize;
+
+       for (i = 0; i < members->count; i++) {
+               tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
+               if (tmp == NULL) {
+                       /* this is a fatal error */
+                       *errnop = errno = ENOENT;
+                       return NSS_STATUS_UNAVAIL;
+               }
+               len = strlen(tmp)+1;
+               if (bufpos + len > buflen) {
+                       /* buffer too small */
+                       *errnop = errno = EAGAIN;
+                       return NSS_STATUS_TRYAGAIN;
+               }
+               memcpy(&buffer[bufpos], tmp, len);
+               result->gr_mem[i] = &buffer[bufpos];
+               bufpos += len;
+       }
+
+       result->gr_mem[i] = NULL;
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
+                               long int limit,
+                               long int *start,
+                               long int *size,
+                               gid_t **groups,
+                               int *errnop,
+                               struct ldb_result *grlist)
+{
+       NSS_STATUS ret;
+       int i;
+
+       for (i = 0; i < grlist->count; i++) {
+
+               if (limit && (*start > limit)) {
+                       /* TODO: warn no all groups were reported */
+                       *errnop = 0;
+                       ret = NSS_STATUS_SUCCESS;
+                       goto done;
+               }
+
+               if (*start == *size) {
+                       /* buffer full, enlarge it */
+                       long int gs;
+                       gid_t *gm;
+
+                       gs = (*size) + 32;
+                       if (limit && (gs > limit)) {
+                               gs = limit;
+                       }
+
+                       gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
+                       if ( ! gm) {
+                               *errnop = ENOMEM;
+                               ret = NSS_STATUS_UNAVAIL;
+                               goto done;
+                       }
+
+                       *groups = gm;
+                       *size = gs;
+               }
+
+               (*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
+               if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
+                       /* skip root group or primary group */
+                       continue;
+               }
+               (*start)++;
+
+       }
+
+       *errnop = 0;
+       ret = NSS_STATUS_SUCCESS;
+done:
+       return ret;
+}
+
+#define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
+
+NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
+                                       struct ldb_dn *group_dn,
+                                       const char * const *attrs,
+                                       const char *mattr)
+{
+       struct ldb_control **ctrls;
+       struct ldb_control *ctrl;
+       struct ldb_asq_control *asqc;
+       struct ldb_request *req;
+       int ret;
+       struct ldb_result *res = *_res;
+
+       ctrls = talloc_array(res, struct ldb_control *, 2);
+       _LDB_NSS_ALLOC_CHECK(ctrls);
+
+       ctrl = talloc(ctrls, struct ldb_control);
+       _LDB_NSS_ALLOC_CHECK(ctrl);
+
+       asqc = talloc(ctrl, struct ldb_asq_control);
+       _LDB_NSS_ALLOC_CHECK(asqc);
+
+       asqc->source_attribute = talloc_strdup(asqc, mattr);
+       _LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
+
+       asqc->request = 1;
+       asqc->src_attr_len = strlen(asqc->source_attribute);
+       ctrl->oid = LDB_CONTROL_ASQ_OID;
+       ctrl->critical = 1;
+       ctrl->data = asqc;
+       ctrls[0] = ctrl;
+       ctrls[1] = NULL;
+
+       ret = ldb_build_search_req(
+                               &req,
+                               _ldb_nss_ctx->ldb,
+                               res,
+                               group_dn,
+                               LDB_SCOPE_BASE,
+                               "(objectClass=*)",
+                               attrs,
+                               ctrls,
+                               res,
+                               ldb_search_default_callback);
+       
+       if (ret != LDB_SUCCESS) {
+               errno = ENOENT;
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
+
+       ret = ldb_request(_ldb_nss_ctx->ldb, req);
+
+       if (ret == LDB_SUCCESS) {
+               ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+       } else {
+               talloc_free(req);
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       talloc_free(req);
+       return NSS_STATUS_SUCCESS;
+}
+
diff --git a/source3/lib/ldb/nssldb/ldb-nss.h b/source3/lib/ldb/nssldb/ldb-nss.h
new file mode 100644 (file)
index 0000000..c780a21
--- /dev/null
@@ -0,0 +1,86 @@
+/* 
+   LDB nsswitch module
+
+   Copyright (C) Simo Sorce 2006
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef _LDB_NSS
+#define _LDB_NSS
+
+#include "includes.h"
+#include "ldb/include/includes.h"
+
+#include <nss.h>
+#include <pwd.h>
+#include <grp.h>
+
+#define _LDB_NSS_URL "etc/users.ldb"
+#define _LDB_NSS_BASEDN "CN=Users,CN=System"
+#define _LDB_NSS_PWENT_FILTER "(&(objectClass=posixAccount)(!(uidNumber=0))(!(gidNumber=0)))"
+#define _LDB_NSS_PWUID_FILTER "(&(objectClass=posixAccount)(uidNumber=%d)(!(gidNumber=0)))"
+#define _LDB_NSS_PWNAM_FILTER "(&(objectClass=posixAccount)(uid=%s)(!(uidNumber=0))(!(gidNumber=0)))"
+
+#define _LDB_NSS_GRENT_FILTER "(&(objectClass=posixGroup)(!(gidNumber=0)))"
+#define _LDB_NSS_GRGID_FILTER "(&(objectClass=posixGroup)(gidNumber=%d)))"
+#define _LDB_NSS_GRNAM_FILTER "(&(objectClass=posixGroup)(cn=%s)(!(gidNumber=0)))"
+
+typedef enum nss_status NSS_STATUS;
+
+struct _ldb_nss_context {
+
+       pid_t pid;
+
+       struct ldb_context *ldb;
+       const struct ldb_dn *base;
+
+       int pw_cur;
+       struct ldb_result *pw_res;
+
+       int gr_cur;
+       struct ldb_result *gr_res;
+};
+       
+NSS_STATUS _ldb_nss_init(void);
+
+NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
+                               char *buffer,
+                               int buflen,
+                               int *errnop,
+                               struct ldb_message *msg);
+
+NSS_STATUS _ldb_nss_fill_group(struct group *result,
+                               char *buffer,
+                               int buflen,
+                               int *errnop,
+                               struct ldb_message *group,
+                               struct ldb_result *members);
+
+NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
+                               long int limit,
+                               long int *start,
+                               long int *size,
+                               gid_t **groups,
+                               int *errnop,
+                               struct ldb_result *grlist);
+
+NSS_STATUS _ldb_nss_group_request(struct ldb_result **res,
+                                       struct ldb_dn *group_dn,
+                                       const char * const *attrs,
+                                       const char *mattr);
+
+#endif /* _LDB_NSS */
diff --git a/source3/lib/ldb/nssldb/ldb-pwd.c b/source3/lib/ldb/nssldb/ldb-pwd.c
new file mode 100644 (file)
index 0000000..e4bafdc
--- /dev/null
@@ -0,0 +1,241 @@
+/* 
+   LDB nsswitch module
+
+   Copyright (C) Simo Sorce 2006
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "ldb-nss.h"
+
+extern struct _ldb_nss_context *_ldb_nss_ctx;
+
+const char *_ldb_nss_pw_attrs[] = {
+       "uid",
+       "userPassword",
+       "uidNumber",
+       "gidNumber",
+       "gecos",
+       "homeDirectory",
+       "loginShell",
+       NULL
+};
+
+NSS_STATUS _nss_ldb_setpwent(void)
+{
+       int ret;
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       _ldb_nss_ctx->pw_cur = 0;
+       if (_ldb_nss_ctx->pw_res != NULL) {
+               talloc_free(_ldb_nss_ctx->pw_res);
+               _ldb_nss_ctx->pw_res = NULL;
+       }
+
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        _LDB_NSS_PWENT_FILTER,
+                        _ldb_nss_pw_attrs,
+                        &_ldb_nss_ctx->pw_res);
+       if (ret != LDB_SUCCESS) {
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_endpwent(void)
+{
+       int ret;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       _ldb_nss_ctx->pw_cur = 0;
+       if (_ldb_nss_ctx->pw_res) {
+               talloc_free(_ldb_nss_ctx->pw_res);
+               _ldb_nss_ctx->pw_res = NULL;
+       }
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_getpwent_r(struct passwd *result_buf,
+                               char *buffer,
+                               int buflen,
+                               int *errnop)
+{
+       int ret;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       *errnop = 0;
+
+       if (_ldb_nss_ctx->pw_cur >= _ldb_nss_ctx->pw_res->count) {
+               /* already returned all entries */
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       ret = _ldb_nss_fill_passwd(result_buf,
+                                  buffer,
+                                  buflen,
+                                  errnop,
+                                  _ldb_nss_ctx->pw_res->msgs[_ldb_nss_ctx->pw_cur]);
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       _ldb_nss_ctx->pw_cur++;
+
+       return NSS_STATUS_SUCCESS;
+}
+
+NSS_STATUS _nss_ldb_getpwuid_r(uid_t uid, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop)
+{
+       int ret;
+       char *filter;
+       struct ldb_result *res;
+
+       if (uid == 0) { /* we don't serve root uid by policy */
+               *errnop = errno = ENOENT;
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       /* build the filter for this uid */
+       filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWUID_FILTER, uid);
+       if (filter == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOMEM;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* search the entry */
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        filter,
+                        _ldb_nss_pw_attrs,
+                        &res);
+       if (ret != LDB_SUCCESS) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* if none found return */
+       if (res->count == 0) {
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_NOTFOUND;
+               goto done;
+       }
+
+       if (res->count != 1) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* fill in the passwd struct */
+       ret = _ldb_nss_fill_passwd(result_buf,
+                                  buffer,
+                                  buflen,
+                                  errnop,
+                                  res->msgs[0]);
+
+done:
+       talloc_free(filter);
+       talloc_free(res);
+       return ret;
+}
+
+NSS_STATUS _nss_ldb_getpwnam_r(const char *name, struct passwd *result_buf, char *buffer, size_t buflen, int *errnop)
+{
+       int ret;
+       char *filter;
+       struct ldb_result *res;
+
+       ret = _ldb_nss_init();
+       if (ret != NSS_STATUS_SUCCESS) {
+               return ret;
+       }
+
+       /* build the filter for this name */
+       filter = talloc_asprintf(_ldb_nss_ctx, _LDB_NSS_PWNAM_FILTER, name);
+       if (filter == NULL) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* search the entry */
+       ret = ldb_search(_ldb_nss_ctx->ldb,
+                        _ldb_nss_ctx->base,
+                        LDB_SCOPE_SUBTREE,
+                        filter,
+                        _ldb_nss_pw_attrs,
+                        &res);
+       if (ret != LDB_SUCCESS) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* if none found return */
+       if (res->count == 0) {
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_NOTFOUND;
+               goto done;
+       }
+
+       if (res->count != 1) {
+               /* this is a fatal error */
+               *errnop = errno = ENOENT;
+               ret = NSS_STATUS_UNAVAIL;
+               goto done;
+       }
+
+       /* fill in the passwd struct */
+       ret = _ldb_nss_fill_passwd(result_buf,
+                                  buffer,
+                                  buflen,
+                                  errnop,
+                                  res->msgs[0]);
+
+done:
+       talloc_free(filter);
+       talloc_free(res);
+       return ret;
+}
+
index 46eac2295d6a52c5ec74e0b5ddddb7e6947a1922..8abfb872382d4ff94987b861b4436e955e17d9e9 100644 (file)
@@ -80,10 +80,12 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
 
 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
 {
-       /* see if the input if null-terninated */
-       if (v->data[v->length] != '\0') return False;
-       
+       if (v->length < 3) {
+               return False;
+       }
+
        if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
+       
        return True;
 }
 
@@ -179,11 +181,11 @@ static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
        struct GUID guid;
        NTSTATUS status;
 
-       /* see if the input if null-terninated */
-       if (v->data[v->length] != '\0') return False;
-
        if (v->length < 33) return False;
 
+       /* see if the input if null-terninated (safety check for the below) */
+       if (v->data[v->length] != '\0') return False;
+
        status = GUID_from_string((const char *)v->data, &guid);
        if (!NT_STATUS_IS_OK(status)) {
                return False;
@@ -301,9 +303,9 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
        dn1 = ldb_dn_explode(mem_ctx, (char *)in->data);
        if (dn1 == NULL) {
                oc1 = talloc_strndup(mem_ctx, (char *)in->data, in->length);
-       } else if (dn1->comp_num >= 1 && strcasecmp(dn1->components[0].name, "cn") == 0) {
-               oc1 = talloc_strndup(mem_ctx, (char *)dn1->components[0].value.data, 
-                                    dn1->components[0].value.length);
+       } else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
+               const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
+               oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
        } else {
                return -1;
        }
@@ -326,9 +328,9 @@ static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx
        dn1 = ldb_dn_explode(mem_ctx, (char *)v1->data);
        if (dn1 == NULL) {
                oc1 = talloc_strndup(mem_ctx, (char *)v1->data, v1->length);
-       } else if (dn1->comp_num >= 1 && strcasecmp(dn1->components[0].name, "cn") == 0) {
-               oc1 = talloc_strndup(mem_ctx, (char *)dn1->components[0].value.data, 
-                                    dn1->components[0].value.length);
+       } else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
+               const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
+               oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
        } else {
                oc1 = NULL;
        }
@@ -336,9 +338,9 @@ static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx
        dn2 = ldb_dn_explode(mem_ctx, (char *)v2->data);
        if (dn2 == NULL) {
                oc2 = talloc_strndup(mem_ctx, (char *)v2->data, v2->length);
-       } else if (dn2->comp_num >= 2 && strcasecmp(dn2->components[0].name, "cn") == 0) {
-               oc2 = talloc_strndup(mem_ctx, (char *)dn2->components[0].value.data, 
-                                    dn2->components[0].value.length);
+       } else if (ldb_dn_get_comp_num(dn2) >= 2 && strcasecmp(ldb_dn_get_rdn_name(dn2), "cn") == 0) {
+               const struct ldb_val *val = ldb_dn_get_rdn_val(dn2);
+               oc2 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
        } else {
                oc2 = NULL;
        }
diff --git a/source3/lib/ldb/standalone.sh b/source3/lib/ldb/standalone.sh
new file mode 100755 (executable)
index 0000000..fa1b9ba
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+cd ../replace
+make clean
+
+cd ../talloc
+make clean
+
+cd ../tdb
+make clean
+
+cd ../ldb
+make clean
+
+./autogen.sh
+
+rm -fr build
+mkdir build
+cd build
+
+../configure $*
+make dirs
+make all
+
+cd ..
index a51ae637dc863e4c0a7d0f07102d833e62f9e566..0cef318d98a5748817343fac2c7adc20e6b633fb 100755 (executable)
@@ -1,20 +1,23 @@
 #!/bin/sh
 
 
-LDB_URL="sqlite://sqltest.ldb"
+LDB_URL="sqlite3://sqltest.ldb"
 export LDB_URL
 
-PATH=bin:$PATH
-export PATH
-
 rm -f sqltest.ldb
 
 if [ -z "$LDBDIR" ]; then
-    LDBDIR="."
+    LDBDIR=`dirname $0`/..
     export LDBDIR
 fi
 
-. $LDBDIR/tests/test-generic.sh
+PATH=bin:$PATH
+export PATH
+
+LDB_SPECIALS=0
+export LDB_SPECIALS
+
+$LDBDIR/tests/test-generic.sh
 
 #. $LDBDIR/tests/test-extended.sh
 
index 09bb99c096fafb50d75cc8bcdba294513fa57c27..928519f3bbd6c43feb95c2e6bf7fbabba584438b 100644 (file)
@@ -29,6 +29,7 @@
 #if (_SAMBA_BUILD_ >= 4)
 #include "lib/cmdline/popt_common.h"
 #include "lib/ldb/samba/ldif_handlers.h"
+#include "auth/gensec/gensec.h"
 #include "auth/auth.h"
 #include "db_wrap.h"
 #endif