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;
+}

Reply via email to