svn commit: samba r17581 - in branches/SAMBA_4_0/source/lib/ldb/tools: .

abartlet at samba.org abartlet at samba.org
Thu Aug 17 08:49:57 GMT 2006


Author: abartlet
Date: 2006-08-17 08:49:57 +0000 (Thu, 17 Aug 2006)
New Revision: 17581

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

Log:
Add tool to convert AD schema back to OpenLDAP's schema formatting.

Andrew Bartlett

Added:
   branches/SAMBA_4_0/source/lib/ldb/tools/ad2oLschema.c


Changeset:
Added: branches/SAMBA_4_0/source/lib/ldb/tools/ad2oLschema.c
===================================================================
--- branches/SAMBA_4_0/source/lib/ldb/tools/ad2oLschema.c	2006-08-17 08:31:19 UTC (rev 17580)
+++ branches/SAMBA_4_0/source/lib/ldb/tools/ad2oLschema.c	2006-08-17 08:49:57 UTC (rev 17581)
@@ -0,0 +1,324 @@
+/* 
+   ldb database library
+
+   Copyright (C) Andrew Bartlett 2006
+
+     ** NOTE! The following LGPL license applies to the ldb
+     ** library. This does NOT imply that all of Samba is released
+     ** under the LGPL
+   
+   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,
+   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
+*/
+
+/*
+ *  Name: ldb
+ *
+ *  Component: ad2oLschema
+ *
+ *  Description: utility to convert an AD schema into the format required by OpenLDAP
+ *
+ *  Author: Andrew Tridgell
+ */
+
+#include "includes.h"
+#include "ldb/include/includes.h"
+#include "ldb/tools/cmdline.h"
+#include "ldb/tools/convert.h"
+
+struct schema_conv {
+	int count;
+	int skipped;
+	int failures;
+};
+
+static void usage(void)
+{
+	printf("Usage: ad2oLschema <options>\n");
+	printf("\nConvert AD-like LDIF to OpenLDAP schema format\n\n");
+	printf("Options:\n");
+	printf("  -I inputfile     inputfile of mapped OIDs and skipped attributes/ObjectClasses");
+	printf("  -H url           LDB or LDAP server to read schmea from\n");
+	printf("  -O outputfile    outputfile otherwise STDOUT\n");
+	printf("  -o options       pass options like modules to activate\n");
+	printf("              e.g: -o modules:timestamps\n");
+	printf("\n");
+	printf("Converts records from an AD-like LDIF schema into an openLdap formatted schema\n\n");
+	exit(1);
+};
+
+static int fetch_schema(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_result **attrs_res, struct ldb_result **objectclasses_res) 
+{
+	TALLOC_CTX *local_ctx = talloc_new(mem_ctx);
+	struct ldb_dn *basedn, *schemadn;
+	struct ldb_result *res;
+	int ret;
+	const char *rootdse_attrs[] = {"schemaNamingContext", NULL};
+	const char *attrs[] = {
+		"lDAPDisplayName",
+		"mayContain",
+		"mustContain",
+		"systemMayContain",
+		"systemMustContain",
+		"objectClassCategory",
+		"isSingleValued",
+		"attributeID",
+		"attributeSyntax",
+		"description",		
+		"subClassOf",
+		NULL
+	};
+
+	if (!local_ctx) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	
+	basedn = ldb_dn_explode(mem_ctx, "");
+	if (!basedn) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	
+	/* Search for rootdse */
+	ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, rootdse_attrs, &res);
+	if (ret != LDB_SUCCESS) {
+		printf("Search failed: %s\n", ldb_errstring(ldb));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	
+	if (res->count != 1) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+	
+	/* Locate schema */
+	schemadn = ldb_msg_find_attr_as_dn(mem_ctx, res->msgs[0], "schemaNamingContext");
+	if (!schemadn) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	/* Downlaod schema */
+	ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, 
+			 "objectClass=attributeSchema", 
+			 attrs, attrs_res);
+	if (ret != LDB_SUCCESS) {
+		printf("Search failed: %s\n", ldb_errstring(ldb));
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, 
+			 "objectClass=classSchema", 
+			 attrs, objectclasses_res);
+	if (ret != LDB_SUCCESS) {
+		printf("Search failed: %s\n", ldb_errstring(ldb));
+		return ret;
+	}
+
+	talloc_steal(mem_ctx, *attrs_res);
+	talloc_steal(mem_ctx, *objectclasses_res);
+	talloc_free(local_ctx);
+	
+	return LDB_SUCCESS;
+}
+
+static struct schema_conv process_convert(struct ldb_context *ldb, FILE *in, FILE *out) 
+{
+	/* Read list of attributes to skip, OIDs to map */
+	TALLOC_CTX *mem_ctx = talloc_new(ldb);
+	char *line;
+	const char **attrs_skip = NULL;
+	int num_skip = 0;
+	struct oid_map {
+		char *old_oid;
+		char *new_oid;
+	} *oid_map = NULL;
+	int num_maps = 0;
+	struct ldb_result *attrs_res, *objectclasses_res;
+	struct schema_conv ret;
+	int ldb_ret, i;
+
+	ret.count = 0;
+	ret.skipped = 0;
+	ret.failures = 0;
+
+	while ((line = afdgets(fileno(in), mem_ctx, 0))) {
+		if (!*line) {
+			break;
+		}
+		if (isdigit(*line)) {
+			char *p = strchr(line, ':');
+			if (!p) {
+				ret.failures = 1;
+				return ret;
+			}
+			p++;
+			oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_maps + 2);
+			oid_map[num_maps].old_oid = talloc_steal(oid_map, line);
+			oid_map[num_maps].new_oid = p;
+			num_maps++;
+			oid_map[num_maps].old_oid = NULL;
+		} else {
+			attrs_skip = talloc_realloc(mem_ctx, attrs_skip, const char *, num_skip + 2);
+			attrs_skip[num_skip] = talloc_steal(attrs_skip, line);
+		}
+	}
+
+	ldb_ret = fetch_schema(ldb, mem_ctx, &attrs_res, &objectclasses_res);
+	if (ldb_ret != LDB_SUCCESS) {
+		ret.failures = 1;
+		return ret;
+	}
+	
+	for (i=0; i < attrs_res->count; i++) {
+		const char *name = ldb_msg_find_attr_as_string(attrs_res->msgs[i], "lDAPDisplayName", NULL);
+		const char *description = ldb_msg_find_attr_as_string(attrs_res->msgs[i], "description", NULL);
+		const char *oid = ldb_msg_find_attr_as_string(attrs_res->msgs[i], "attributeID", NULL);
+		const char *subClassOf = ldb_msg_find_attr_as_string(attrs_res->msgs[i], "subClassOf", NULL);
+		const char *syntax = ldb_msg_find_attr_as_string(attrs_res->msgs[i], "attributeSyntax", NULL);
+		BOOL single_value = ldb_msg_find_attr_as_bool(attrs_res->msgs[i], "isSingleValued", False);
+		const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax);
+		char *schema_entry = NULL;
+		int j;
+
+		/* We have been asked to skip some attributes/objectClasses */
+		if (in_list(attrs_skip, name, False)) {
+			ret.skipped++;
+			continue;
+		}
+
+		/* We might have been asked to remap this oid, due to a conflict */
+		for (j=0; oid_map[j].old_oid; j++) {
+			if (strcmp(oid, oid_map[j].old_oid) == 0) {
+				oid =  oid_map[j].new_oid;
+				break;
+			}
+		}
+		
+		schema_entry = talloc_asprintf(mem_ctx, 
+					       "attributetype (\n"
+					       "  %s\n", oid);
+		if (!schema_entry) {
+			ret.failures++;
+			break;
+		}
+
+		schema_entry = talloc_asprintf_append(schema_entry, 
+						      "  NAME '%s'\n", name);
+		if (!schema_entry) {
+			ret.failures++;
+			return ret;
+		}
+
+		if (!schema_entry) return ret;
+
+		if (description) {
+			schema_entry = talloc_asprintf_append(schema_entry, 
+							      "  DESC %s\n", description);
+			if (!schema_entry) {
+				ret.failures++;
+				return ret;
+			}
+		}
+
+		if (subClassOf) {
+			schema_entry = talloc_asprintf_append(schema_entry, 
+							      "  SUP %s\n", subClassOf);
+			if (!schema_entry) {
+				ret.failures++;
+				return ret;
+			}
+		}
+			       
+		if (map) {
+			if (map->equality) {
+				schema_entry = talloc_asprintf_append(schema_entry, 
+								      "  EQUALITY %s\n", map->equality);
+				if (!schema_entry) {
+					ret.failures++;
+					return ret;
+				}
+			}
+			if (map->substring) {
+				schema_entry = talloc_asprintf_append(schema_entry, 
+								      "  SUBSTRING %s\n", map->substring);
+				if (!schema_entry) {
+					ret.failures++;
+					return ret;
+				}
+			}
+			schema_entry = talloc_asprintf_append(schema_entry, 
+							      "  SYNTAX %s\n", map->Standard_OID);
+			if (!schema_entry) {
+				ret.failures++;
+				return ret;
+			}
+		}
+
+		if (single_value) {
+			schema_entry = talloc_asprintf_append(schema_entry, 
+							      "  SINGLE-VALUE\n");
+			if (!schema_entry) {
+				ret.failures++;
+				return ret;
+			}
+		}
+		
+		schema_entry = talloc_asprintf_append(schema_entry, 
+						      ")\n\n");
+
+		fprintf(out, "%s", schema_entry);
+	}
+
+	/* Read each element */
+	/* Replace OID if required */
+}
+
+ int main(int argc, const char **argv)
+{
+	TALLOC_CTX *ctx;
+	struct ldb_cmdline *options;
+	FILE *in = stdin;
+	FILE *out = stdout;
+	struct ldb_context *ldb;
+	struct schema_conv ret;
+
+	ldb_global_init();
+
+	ctx = talloc_new(NULL);
+	ldb = ldb_init(ctx);
+
+	options = ldb_cmdline_process(ldb, argc, argv, usage);
+
+	if (options->input) {
+		in = fopen(options->input, "r");
+		if (!in) {
+			perror(options->input);
+			exit(1);
+		}
+	}
+	if (options->output) {
+		out = fopen(options->output, "w");
+		if (!out) {
+			perror(options->output);
+			exit(1);
+		}
+	}
+
+	ret = process_convert(ldb, in, out);
+
+	fclose(in);
+	fclose(out);
+
+	printf("Converted %d records with %d failures\n", ret.count, ret.failures);
+
+	return 0;
+}



More information about the samba-cvs mailing list