svn commit: samba r16505 - in branches/SOC/mkhl/ldb-map/modules: .

mkhl at samba.org mkhl at samba.org
Sat Jun 24 22:00:53 GMT 2006


Author: mkhl
Date: 2006-06-24 22:00:52 +0000 (Sat, 24 Jun 2006)
New Revision: 16505

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=16505

Log:
Check incoming DN before performing mappings.
Add chunks of searching boilerplate.

Martin

Modified:
   branches/SOC/mkhl/ldb-map/modules/ldb_map.c


Changeset:
Modified: branches/SOC/mkhl/ldb-map/modules/ldb_map.c
===================================================================
--- branches/SOC/mkhl/ldb-map/modules/ldb_map.c	2006-06-24 20:38:38 UTC (rev 16504)
+++ branches/SOC/mkhl/ldb-map/modules/ldb_map.c	2006-06-24 22:00:52 UTC (rev 16505)
@@ -1,25 +1,25 @@
 /* 
-   ldb database library - map backend
+   Mapping ldb module
 
    Copyright (C) Jelmer Vernooij 2005
 
-     ** NOTE! The following LGPL license applies to the ldb
-     ** library. This does NOT imply that all of Samba is released
-     ** under the LGPL
+   * NOTICE: this module is NOT released under the GNU LGPL license as
+   * other ldb code. This module is release under the GNU GPL v2 or
+   * later license.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU 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 free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser 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,
+   This program 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser 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
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
@@ -27,7 +27,7 @@
  *
  *  Component: ldb ldb_map module
  *
- *  Description: ...
+ *  Description: Map portions of data into a different format on a remote partition.
  *
  *  Author: Jelmer Vernooij, Martin Kuehl
  */
@@ -57,7 +57,7 @@
 #define map_oom(module) ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
 
 
-/* Private data */
+/* private data */
 struct map_private {
 	struct ldb_map_context context;
 };
@@ -73,9 +73,11 @@
 }
 
 
-/* Async context data */
+/* async context data */
 struct map_async_context {
 	enum map_step {
+		MAP_SEARCH_LOCAL,
+		MAP_SEARCH_REMOTE,
 		MAP_DO_ADD_REMOTE,
 		MAP_DO_ADD_LOCAL,
 		MAP_SEARCH_SELF_MODIFY,
@@ -87,7 +89,7 @@
 		MAP_SEARCH_SELF_RENAME,
 		MAP_DO_RENAME_REMOTE,
 		MAP_DO_RENAME_FIXUP,
-		MAP_DO_RENAME_LOCAL,
+		MAP_DO_RENAME_LOCAL
 	} step;
 
 	struct ldb_module *module;
@@ -104,6 +106,13 @@
 	struct ldb_async_result *search_res;
 };
 
+/* async context data for searches */
+struct map_async_search_context {
+	struct map_async_context *ac;
+	struct ldb_async_result *local_res;
+	struct ldb_async_result *remote_res;
+};
+
 /* create async context and handle */
 static
 struct ldb_async_handle *
@@ -191,7 +200,7 @@
         return new;
 }
 
-#define MAP_DN_REBASE(dn) dn = ldb_dn_rebase(request, dn, map->local_base_dn, map->remote_base_dn)
+#define MAP_DN_REBASE(dn) dn = ldb_dn_rebase(request, dn, data->local_base_dn, data->remote_base_dn)
 
 /* run request in the remote partition */
 static
@@ -199,7 +208,7 @@
 ldb_next_remote_request(struct ldb_module *module,
 			struct ldb_request *request)
 {
-	struct ldb_map_context *map = map_get_privdat(module);
+	struct ldb_map_context *data = map_get_privdat(module);
         struct ldb_message *msg;
 
         switch (request->operation) {
@@ -315,24 +324,71 @@
 }
 
 
-/* Checking ldb_messages */
+/* Checking ... stuff  */
 
+/* True if dn is below the local baseDN */
 static
-int
-check_msg_is_mapped(struct ldb_module *module,
-		    const struct ldb_message *msg)
+BOOL
+check_dn_local(struct ldb_module *module,
+	       const struct ldb_dn *dn)
 {
 	struct ldb_map_context *data = map_get_privdat(module);
+
+	return ldb_dn_compare_base(module->ldb, data->local_base_dn, dn) == 0;
+}
+
+/* True if attr has an associated mapping that does not ignore it */
+static
+BOOL
+check_attr_mapped(struct ldb_map_context *data,
+		  const char* attr)
+{
 	struct ldb_map_attribute *map;
+
+	map = find_attr_local(data, attr);
+	if (map == NULL)
+		return False;
+	if (map->type == MAP_IGNORE)
+		return False;
+	return True;
+}
+
+/* True if any of attrs is mapped */
+static
+BOOL
+check_attrs_mapped(struct ldb_module *module,
+		   const char * const *attrs)
+{
+	struct ldb_map_context *data = map_get_privdat(module);
+	BOOL ret;
 	int i;
 
+	for (i = 0; attrs[i]; i++) {
+		ret = check_attr_mapped(data, attrs[i]);
+		if (ret)
+			return ret;
+	}
+
+	return False;
+}
+
+/* True if any of the message elements is mapped */
+static
+BOOL
+check_msg_mapped(struct ldb_module *module,
+		 const struct ldb_message *msg)
+{
+	struct ldb_map_context *data = map_get_privdat(module);
+	BOOL ret;
+	int i;
+
 	for (i = 0; i < msg->num_elements; i++) {
-		map = find_attr_local(data, msg->elements[i].name);
-		if (map && map->type != MAP_IGNORE)
-			return 1;
+		ret = check_attr_mapped(data, msg->elements[i].name);
+		if (ret)
+			return ret;
 	}
 
-	return 0;
+	return False;
 }
 
 /* Check whether the given objectClass is contained in the specified
@@ -1340,11 +1396,12 @@
 }
 
 
+/* store single search result in async context */
 static
 int
-get_self_callback(struct ldb_context *ldb,
-		  void *context,
-		  struct ldb_async_result *ares)
+search_self_callback(struct ldb_context *ldb,
+		     void *context,
+		     struct ldb_async_result *ares)
 {
 	struct map_async_context *ac;
 
@@ -1361,7 +1418,8 @@
 		return LDB_SUCCESS;
 	}
 
-	if (ac->remote_dn != NULL) {
+	/* we already have a remote DN */
+	if (ac->remote_dn) {
 		ldb_set_errstring(ldb,
 				  talloc_asprintf(ldb, "Too many results"));
 		talloc_free(ares);
@@ -1369,17 +1427,18 @@
 	}
 
 	ac->search_res = talloc_steal(ac, ares);
-	ac->remote_dn
-		= ldb_dn_explode(ac, ldb_msg_find_string(ares->message,
-							 IS_MAPPED, NULL));
+	ac->remote_dn = ldb_dn_explode(ac,
+				       ldb_msg_find_string(ares->message,
+							   IS_MAPPED, NULL));
 
 	return LDB_SUCCESS;
 }
 
+/* create request that searches for DN */
 static
 struct ldb_request *
-build_self_req(struct map_async_context *ac,
-	       const struct ldb_dn *dn)
+search_self_req(struct map_async_context *ac,
+		const struct ldb_dn *dn)
 {
 	/* attrs[] is returned from this function in
 	   ac->search_req->op.search.attrs, so it must be static, as
@@ -1406,13 +1465,53 @@
 
 	req->controls = NULL;
 	req->async.context = ac;
-	req->async.callback = get_self_callback;
+	req->async.callback = search_self_callback;
 	ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, req);
 
 	return req;
 }
 
+static
+int
+local_search_callback(struct ldb_context *ldb,
+		      void *context,
+		      struct ldb_async_result *ares)
+{
+	struct map_async_search_context *sc;
 
+	if (context == NULL || ares == NULL) {
+		ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context or Result in callback"));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	sc = talloc_get_type(context, struct map_async_search_context);
+
+	switch (ares->type) {
+	case LDB_REPLY_ENTRY:
+		/* we already have a local result */
+		if (sc->local_res != NULL) {
+			ldb_set_errstring(ldb,
+					  talloc_asprintf(ldb,
+							  "Too many results"));
+			talloc_free(ares);
+			return LDB_ERR_OPERATIONS_ERROR;
+		}
+
+		sc->local_res = talloc_steal(sc, ares);
+
+		/* don't return the 'IS_MAPPED' attribute */
+		ldb_msg_remove_attr(ares->message, IS_MAPPED);
+
+		/* XXX: ... */
+		
+	default:
+		talloc_free(ares);
+		ldb_set_errstring(ldb, talloc_asprintf(ldb, "Unexpected result type in search for local record"));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+}
+
+
 /* Handling LDB requests */
 
 /* /\* Search fallback database *\/ */
@@ -1612,6 +1711,73 @@
 /* } */
 
 
+/* Search a record */
+static
+int
+map_search(struct ldb_module *module,
+	   struct ldb_request *req)
+{
+	struct ldb_async_handle *h;
+	struct map_async_context *ac;
+	const char * const *local_attrs;
+	int ret;
+
+	/* do not manipulate our control entries */
+	if (ldb_dn_is_special(req->op.search.base))
+		return ldb_next_request(module, req);
+
+	/* no mapping requested, skip to next module */
+	if (!check_dn_local(module, req->op.search.base))
+		return ldb_next_request(module, req);
+
+	/* no mapping needed, skip to next module */
+	if (req->op.search.attrs
+	    && (!ldb_attr_in_list(req->op.search.attrs, "*"))
+	    && (!check_attrs_mapped(module, req->op.search.attrs)))
+		return ldb_next_request(module, req);
+
+	/* prepare async context and handle */
+	h = map_init_handle(req, module);
+	if (h == NULL)
+		return LDB_ERR_OPERATIONS_ERROR;
+	ac = talloc_get_type(h->private_data, struct map_async_context);
+
+	/* return or own handle to deal with this call */
+	/* req->async.handle = h; */
+
+	/* prepare the local operation */
+	ac->local_req = talloc_zero(ac, struct ldb_request);
+	if (ac->local_req == NULL) {
+		map_oom(module);
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	*(ac->local_req) = *req; /* copy the request */
+
+	/* return or own handle to deal with this call */
+	ac->local_req->async.handle = h;
+
+	ac->local_req->async.context = ac;
+	ac->local_req->async.callback = local_search_callback;
+
+	/* XXX: ... */
+
+	ac->local_req->op.search.attrs = local_attrs;
+
+	ldb_set_timeout_from_prev_req(module->ldb, req, ac->local_req);
+
+	h->state = LDB_ASYNC_INIT;
+	h->status = LDB_SUCCESS;
+
+	ac->step = MAP_SEARCH_LOCAL;
+
+	ret = ldb_next_request(module, ac->local_req);
+	if (ret == LDB_SUCCESS)
+		req->async.handle = ac->local_req->async.handle;
+	return ret;
+}
+
+
 /* Add the local record */
 static
 int
@@ -1644,8 +1810,12 @@
 	if (ldb_dn_is_special(msg->dn))
 		return ldb_next_request(module, req);
 
+	/* no mapping requested, skip to next module */
+	if (!check_dn_local(module, msg->dn))
+		return ldb_next_request(module, req);
+
 	/* no mapping needed, skip to next module */
-	if (!check_msg_is_mapped(module, msg))
+	if (!check_msg_mapped(module, msg))
 		return ldb_next_request(module, req);
 
 	/* prepare async context and handle */
@@ -1797,8 +1967,12 @@
 	if (ldb_dn_is_special(msg->dn))
 		return ldb_next_request(module, req);
 
+	/* no mapping requested, skip to next module */
+	if (!check_dn_local(module, msg->dn))
+		return ldb_next_request(module, req);
+
 	/* no mapping needed, skip to next module */
-	if (!check_msg_is_mapped(module, msg))
+	if (!check_msg_mapped(module, msg))
 		return ldb_next_request(module, req);
 
 	/* prepare async context and handle */
@@ -1860,7 +2034,7 @@
 		return map_modify_do_local(h);
 
 	/* prepare the search operation */
-	ac->search_req = build_self_req(ac, msg->dn);
+	ac->search_req = search_self_req(ac, msg->dn);
 	if (ac->search_req == NULL)
 		return LDB_ERR_OPERATIONS_ERROR;
 
@@ -1951,8 +2125,11 @@
 	if (ldb_dn_is_special(req->op.del.dn))
 		return ldb_next_request(module, req);
 
-	/* TODO: check that DN is under the local baseDN */
 
+	/* no mapping requested, skip to next module */
+	if (!check_dn_local(module, req->op.del.dn))
+		return ldb_next_request(module, req);
+
 	/* prepare async context and handle */
 	h = map_init_handle(req, module);
 	if (h == NULL)
@@ -1963,7 +2140,7 @@
 	req->async.handle = h;
 
 	/* prepare the search operation */
-	ac->search_req = build_self_req(ac, req->op.del.dn);
+	ac->search_req = search_self_req(ac, req->op.del.dn);
 	if (ac->search_req == NULL)
 		return LDB_ERR_OPERATIONS_ERROR;
 
@@ -2104,7 +2281,11 @@
 	if (ldb_dn_is_special(req->op.rename.olddn))
 		return ldb_next_request(module, req);
 
-	/* TODO: check that DN is under the local baseDN */
+	/* no mapping requested, skip to next module */
+	/* TODO: both? either? neither? what to doin each case? */
+	if (!check_dn_local(module, req->op.rename.olddn) ||
+	    !check_dn_local(module, req->op.rename.newdn))
+		return ldb_next_request(module, req);
 
 	/* prepare async context and handle */
 	h = map_init_handle(req, module);
@@ -2116,7 +2297,7 @@
 	req->async.handle = h;
 
 	/* prepare the search operation */
-	ac->search_req = build_self_req(ac, req->op.rename.olddn);
+	ac->search_req = search_self_req(ac, req->op.rename.olddn);
 	if (ac->search_req == NULL)
 		return LDB_ERR_OPERATIONS_ERROR;
 
@@ -2291,7 +2472,7 @@
 	.modify		   = map_modify,
 	.del		   = map_delete,
 	.rename		   = map_rename,
-/* 	.search		   = map_search_bytree, */
+	.search		   = map_search,
 	.async_wait	   = map_async_wait,
 };
 



More information about the samba-cvs mailing list