diff options
Diffstat (limited to 'source4/utils')
-rw-r--r-- | source4/utils/ad2oLschema.1.xml | 87 | ||||
-rw-r--r-- | source4/utils/ad2oLschema.c | 798 | ||||
-rw-r--r-- | source4/utils/config.mk | 28 | ||||
-rw-r--r-- | source4/utils/oLschema2ldif.1.xml | 79 | ||||
-rw-r--r-- | source4/utils/oLschema2ldif.c | 603 | ||||
-rw-r--r-- | source4/utils/schema_convert.c | 173 | ||||
-rw-r--r-- | source4/utils/schema_convert.h | 10 |
7 files changed, 1778 insertions, 0 deletions
diff --git a/source4/utils/ad2oLschema.1.xml b/source4/utils/ad2oLschema.1.xml new file mode 100644 index 0000000000..6ae8996477 --- /dev/null +++ b/source4/utils/ad2oLschema.1.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> +<refentry id="ad2oLschema.1"> + +<refmeta> + <refentrytitle>ad2oLschema</refentrytitle> + <manvolnum>1</manvolnum> +</refmeta> + + +<refnamediv> + <refname>ad2oLschema</refname> + <refpurpose>Converts AC-like LDAP schemas to OpenLDAP + compatible schema files</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>ad2oLschema</command> + <arg choice="opt">-I INPUT-FILE</arg> + <arg choice="opt">-O OUTPUT-FILE</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1> + <title>DESCRIPTION</title> + + <para>ad2oLschema is a simple tool that converts AD-like LDIF + schema files into OpenLDAP schema files.</para> +</refsect1> + + +<refsect1> + <title>OPTIONS</title> + + <variablelist> + <varlistentry> + <term>-H url</term> + <listitem><para>URL to an LDB or LDAP server with an AD schema to read. </para></listitem> + </varlistentry> + + <varlistentry> + <term>-I input-file</term> <listitem><para>AD schema + to read. If neither this nor -H is specified, the + schema file will be read from standard input. + </para></listitem> + </varlistentry> + + <varlistentry> + <term>-O output-file</term> + <listitem><para>File to write OpenLDAP version of schema to. + </para></listitem> + </varlistentry> + </variablelist> +</refsect1> + +<refsect1> + <title>VERSION</title> + + <para>This man page is correct for version 4.0 of the Samba suite.</para> +</refsect1> + +<refsect1> + <title>SEE ALSO</title> + + <para>ldb(7), ldbmodify, ldbdel, ldif(5)</para> + +</refsect1> + +<refsect1> + <title>AUTHOR</title> + + <para> ldb was written by + <ulink url="http://samba.org/~tridge/">Andrew Tridgell</ulink>. + ad2oLschema was written by <ulink + url="http://samba.org/~abartlet/">Andrew Bartlett</ulink>. + </para> + + <para> +If you wish to report a problem or make a suggestion then please see +the <ulink url="http://ldb.samba.org/"/> web site for +current contact and maintainer information. + </para> + +</refsect1> + +</refentry> diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c new file mode 100644 index 0000000000..879b1a7213 --- /dev/null +++ b/source4/utils/ad2oLschema.c @@ -0,0 +1,798 @@ +/* + 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Name: ldb + * + * Component: ad2oLschema + * + * Description: utility to convert an AD schema into the format required by OpenLDAP + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb_includes.h" +#include "system/locale.h" +#include "lib/ldb/tools/cmdline.h" +#include "utils/schema_convert.h" +#include "param/param.h" +#include "lib/cmdline/popt_common.h" +#include "dsdb/samdb/samdb.h" + +struct schema_conv { + int count; + int skipped; + int failures; +}; + +enum convert_target { + TARGET_OPENLDAP, + TARGET_FEDORA_DS +}; + + +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_attrs_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, + TALLOC_CTX *mem_ctx, + struct ldb_result **attrs_res) +{ + int ret; + + /* Downlaod schema */ + ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, + "objectClass=attributeSchema", + NULL, attrs_res); + if (ret != LDB_SUCCESS) { + printf("Search failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + return ret; +} + +static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn, + TALLOC_CTX *mem_ctx, + struct ldb_result *search_from, + struct ldb_result *res_list) +{ + int i; + int ret = 0; + for (i=0; i < search_from->count; i++) { + struct ldb_result *res; + const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i], + "lDAPDisplayname", NULL); + + ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, + schemadn, LDB_SCOPE_SUBTREE, NULL, + "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", + name, name); + if (ret != LDB_SUCCESS) { + printf("Search failed: %s\n", ldb_errstring(ldb)); + return ret; + } + + res_list->msgs = talloc_realloc(res_list, res_list->msgs, + struct ldb_message *, res_list->count + 2); + if (!res_list->msgs) { + return LDB_ERR_OPERATIONS_ERROR; + } + res_list->msgs[res_list->count] = talloc_move(res_list, + &search_from->msgs[i]); + res_list->count++; + res_list->msgs[res_list->count] = NULL; + + if (res->count > 0) { + ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list); + } + if (ret != LDB_SUCCESS) { + return ret; + } + } + return ret; +} + +static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, + TALLOC_CTX *mem_ctx, + struct ldb_result **objectclasses_res) +{ + TALLOC_CTX *local_ctx = talloc_new(mem_ctx); + struct ldb_result *top_res, *ret_res; + int ret; + if (!local_ctx) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Downlaod 'top' */ + ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE, + "(&(objectClass=classSchema)(lDAPDisplayName=top))", + NULL, &top_res); + if (ret != LDB_SUCCESS) { + printf("Search failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + talloc_steal(local_ctx, top_res); + + if (top_res->count != 1) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret_res = talloc_zero(local_ctx, struct ldb_result); + if (!ret_res) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res); + + if (ret != LDB_SUCCESS) { + printf("Search failed: %s\n", ldb_errstring(ldb)); + return LDB_ERR_OPERATIONS_ERROR; + } + + *objectclasses_res = talloc_move(mem_ctx, &ret_res); + return ret; +} + +static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + struct ldb_result **schema_res) +{ + const char *rootdse_attrs[] = {"schemaNamingContext", NULL}; + struct ldb_dn *schemadn; + struct ldb_dn *basedn = ldb_dn_new(mem_ctx, ldb, NULL); + struct ldb_result *rootdse_res; + int ldb_ret; + + if (!basedn) { + return NULL; + } + + /* Search for rootdse */ + ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, rootdse_attrs, &rootdse_res); + if (ldb_ret != LDB_SUCCESS) { + ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, + "(&(objectClass=dMD)(cn=Schema))", + NULL, schema_res); + if (ldb_ret) { + printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb)); + return NULL; + } + + talloc_steal(mem_ctx, *schema_res); + + if ((*schema_res)->count != 1) { + printf("Failed to find rootDSE"); + return NULL; + } + + schemadn = talloc_steal(mem_ctx, (*schema_res)->msgs[0]->dn); + return schemadn; + + } + + talloc_steal(mem_ctx, rootdse_res); + + if (rootdse_res->count != 1) { + printf("Failed to find rootDSE"); + return NULL; + } + + /* Locate schema */ + schemadn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, rootdse_res->msgs[0], "schemaNamingContext"); + if (!schemadn) { + return NULL; + } + + ldb_ret = ldb_search(ldb, schemadn, LDB_SCOPE_BASE, + "(&(objectClass=dMD)(cn=Schema))", + NULL, schema_res); + if (ldb_ret) { + printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb)); + return NULL; + } + + talloc_steal(mem_ctx, *schema_res); + + if ((*schema_res)->count != 1) { + printf("Failed to find rootDSE"); + return NULL; + } + talloc_free(rootdse_res); + return schemadn; +} + +static bool merge_attr_list(TALLOC_CTX *mem_ctx, + struct ldb_message_element *attrs, struct ldb_message_element *new_attrs) +{ + struct ldb_val *values; + if (!new_attrs) { + return true; + } + + values = talloc_realloc(mem_ctx, + attrs->values, struct ldb_val, attrs->num_values + new_attrs->num_values); + + attrs->values = values; + + memcpy(&attrs->values[attrs->num_values], new_attrs->values, sizeof(*new_attrs->values) * new_attrs->num_values); + attrs->num_values = attrs->num_values + new_attrs->num_values; + + /* Add sort and unique implementation here */ + + return true; +} + +static bool find_aux_classes(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_dn *schema_dn, + struct ldb_message_element *aux_class, struct ldb_message_element *must, + struct ldb_message_element *sys_must, struct ldb_message_element *may, + struct ldb_message_element *sys_may) +{ + int i, ret; + struct ldb_message *msg; + struct ldb_result *res; + + for (i=0; aux_class && i < aux_class->num_values; i++) { + ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, + schema_dn, LDB_SCOPE_SUBTREE, NULL, + "(&(objectClass=classSchema)(lDAPDisplayName=%s))", + aux_class->values[i].data); + if (ret != LDB_SUCCESS) { + return false; + } + + msg = res->msgs[0]; + + if (!merge_attr_list(mem_ctx, must, ldb_msg_find_element(msg, "mustContain"))) { + return false; + } + if (!merge_attr_list(mem_ctx, sys_must, ldb_msg_find_element(msg, "systemMustContain"))) { + return false; + } + if (!merge_attr_list(mem_ctx, may, ldb_msg_find_element(msg, "mayContain"))) { + return false; + } + if (!merge_attr_list(mem_ctx, sys_may, ldb_msg_find_element(msg, "systemMayContain"))) { + return false; + } + + + if (res->count == 0) { + return false; + } + + if (!find_aux_classes(mem_ctx, ldb, schema_dn, + ldb_msg_find_element(msg, "auxiliaryClass"), must, sys_must, may, sys_may)) { + return false; + } + if (!find_aux_classes(mem_ctx, ldb, schema_dn, + ldb_msg_find_element(msg, "systemAuxiliaryClass"), must, sys_must, may, sys_may)) { + return false; + } + } + return true; +} + + +#define IF_NULL_FAIL_RET(x) do { \ + if (!x) { \ + ret.failures++; \ + return ret; \ + } \ + } while (0) + + +static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_target target, 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_oid_maps = 0; + struct attr_map { + char *old_attr; + char *new_attr; + } *attr_map = NULL; + int num_attr_maps = 0; + struct ldb_result *schema_res, *attrs_res, *objectclasses_res; + struct ldb_dn *schemadn; + struct schema_conv ret; + struct dsdb_schema *schema; + char *error_string; + + int ldb_ret, i; + + ret.count = 0; + ret.skipped = 0; + ret.failures = 0; + + while ((line = afdgets(fileno(in), mem_ctx, 0))) { + /* Blank Line */ + if (line[0] == '\0') { + continue; + } + /* Comment */ + if (line[0] == '#') { + continue; + } + if (isdigit(line[0])) { + char *p = strchr(line, ':'); + IF_NULL_FAIL_RET(p); + p[0] = '\0'; + p++; + oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_oid_maps + 2); + trim_string(line, " ", " "); + oid_map[num_oid_maps].old_oid = talloc_move(oid_map, &line); + trim_string(p, " ", " "); + oid_map[num_oid_maps].new_oid = p; + num_oid_maps++; + oid_map[num_oid_maps].old_oid = NULL; + } else { + char *p = strchr(line, ':'); + if (p) { + /* remap attribute/objectClass */ + p[0] = '\0'; + p++; + attr_map = talloc_realloc(mem_ctx, attr_map, struct attr_map, num_attr_maps + 2); + trim_string(line, " ", " "); + attr_map[num_attr_maps].old_attr = talloc_move(attr_map, &line); + trim_string(p, " ", " "); + attr_map[num_attr_maps].new_attr = p; + num_attr_maps++; + attr_map[num_attr_maps].old_attr = NULL; + } else { + /* skip attribute/objectClass */ + attrs_skip = talloc_realloc(mem_ctx, attrs_skip, const char *, num_skip + 2); + trim_string(line, " ", " "); + attrs_skip[num_skip] = talloc_move(attrs_skip, &line); + num_skip++; + attrs_skip[num_skip] = NULL; + } + } + } + + schemadn = find_schema_dn(ldb, mem_ctx, &schema_res); + if (!schemadn) { + printf("Failed to find schema DN: %s\n", ldb_errstring(ldb)); + ret.failures = 1; + return ret; + } + + ldb_ret = fetch_attrs_schema(ldb, schemadn, mem_ctx, &attrs_res); + if (ldb_ret != LDB_SUCCESS) { + printf("Failed to fetch attribute schema: %s\n", ldb_errstring(ldb)); + ret.failures = 1; + return ret; + } + + + ldb_ret = fetch_objectclass_schema(ldb, schemadn, mem_ctx, &objectclasses_res); + if (ldb_ret != LDB_SUCCESS) { + printf("Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb)); + ret.failures = 1; + return ret; + } + + ldb_ret = dsdb_schema_from_ldb_results(mem_ctx, ldb, + lp_iconv_convenience(cmdline_lp_ctx), + schema_res, attrs_res, objectclasses_res, &schema, &error_string); + if (ldb_ret != LDB_SUCCESS) { + printf("Failed to load schema: %s\n", error_string); + ret.failures = 1; + return ret; + } + + switch (target) { + case TARGET_OPENLDAP: + break; + case TARGET_FEDORA_DS: + fprintf(out, "dn: cn=schema\n"); + break; + } + + for (i=0; i < attrs_res->count; i++) { + struct ldb_message *msg = attrs_res->msgs[i]; + + const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); + const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); + const char *oid = ldb_msg_find_attr_as_string(msg, "attributeID", NULL); + const char *syntax = ldb_msg_find_attr_as_string(msg, "attributeSyntax", NULL); + bool single_value = ldb_msg_find_attr_as_bool(msg, "isSingleValued", false); + const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax); + char *schema_entry = NULL; + int j; + + if (!name) { + printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); + ret.failures++; + continue; + } + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + ret.skipped++; + continue; + } + + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; oid && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(oid, oid_map[j].old_oid) == 0) { + oid = oid_map[j].new_oid; + break; + } + } + + switch (target) { + case TARGET_OPENLDAP: + schema_entry = talloc_asprintf(mem_ctx, + "attributetype (\n" + " %s\n", oid); + break; + case TARGET_FEDORA_DS: + schema_entry = talloc_asprintf(mem_ctx, + "attributeTypes: (\n" + " %s\n", oid); + break; + } + IF_NULL_FAIL_RET(schema_entry); + + /* We might have been asked to remap this name, due to a conflict */ + for (j=0; name && attr_map && attr_map[j].old_attr; j++) { + if (strcasecmp(name, attr_map[j].old_attr) == 0) { + name = attr_map[j].new_attr; + break; + } + } + + schema_entry = talloc_asprintf_append(schema_entry, + " NAME '%s'\n", name); + IF_NULL_FAIL_RET(schema_entry); + + if (description) { + schema_entry = talloc_asprintf_append(schema_entry, + " DESC %s\n", description); + IF_NULL_FAIL_RET(schema_entry); + } + + if (map) { + const char *syntax_oid; + if (map->equality) { + schema_entry = talloc_asprintf_append(schema_entry, + " EQUALITY %s\n", map->equality); + IF_NULL_FAIL_RET(schema_entry); + } + if (map->substring) { + schema_entry = talloc_asprintf_append(schema_entry, + " SUBSTR %s\n", map->substring); + IF_NULL_FAIL_RET(schema_entry); + } + syntax_oid = map->Standard_OID; + /* We might have been asked to remap this oid, + * due to a conflict, or lack of + * implementation */ + for (j=0; syntax_oid && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(syntax_oid, oid_map[j].old_oid) == 0) { + syntax_oid = oid_map[j].new_oid; + break; + } + } + schema_entry = talloc_asprintf_append(schema_entry, + " SYNTAX %s\n", syntax_oid); + IF_NULL_FAIL_RET(schema_entry); + } + + if (single_value) { + schema_entry = talloc_asprintf_append(schema_entry, + " SINGLE-VALUE\n"); + IF_NULL_FAIL_RET(schema_entry); + } + + schema_entry = talloc_asprintf_append(schema_entry, + " )"); + + switch (target) { + case TARGET_OPENLDAP: + fprintf(out, "%s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + fprintf(out, "%s\n", schema_entry); + break; + } + ret.count++; + } + + for (i=0; i < objectclasses_res->count; i++) { + struct ldb_message *msg = objectclasses_res->msgs[i]; + const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); + const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); + const char *oid = ldb_msg_find_attr_as_string(msg, "governsID", NULL); + const char *subClassOf = ldb_msg_find_attr_as_string(msg, "subClassOf", NULL); + int objectClassCategory = ldb_msg_find_attr_as_int(msg, "objectClassCategory", 0); + struct ldb_message_element *must = ldb_msg_find_element(msg, "mustContain"); + struct ldb_message_element *sys_must = ldb_msg_find_element(msg, "systemMustContain"); + struct ldb_message_element *may = ldb_msg_find_element(msg, "mayContain"); + struct ldb_message_element *sys_may = ldb_msg_find_element(msg, "systemMayContain"); + struct ldb_message_element *aux_class = ldb_msg_find_element(msg, "auxiliaryClass"); + struct ldb_message_element *sys_aux_class = ldb_msg_find_element(msg, "systemAuxiliaryClass"); + char *schema_entry = NULL; + int j; + + if (!name) { + printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); + ret.failures++; + continue; + } + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + ret.skipped++; + continue; + } + + if (must == NULL) { + must = talloc_zero(mem_ctx, struct ldb_message_element); + } + + if (may == NULL) { + may = talloc_zero(mem_ctx, struct ldb_message_element); + } + + if (sys_must == NULL) { + sys_must = talloc_zero(mem_ctx, struct ldb_message_element); + } + + if (sys_may == NULL) { + sys_may = talloc_zero(mem_ctx, struct ldb_message_element); + } + + if (!find_aux_classes(mem_ctx, ldb, schemadn, aux_class, must, sys_must, may, sys_may)) { + ret.failures++; + continue; + } + + if (!find_aux_classes(mem_ctx, ldb, schemadn, sys_aux_class, must, sys_must, may, sys_may)) { + ret.failures++; + continue; + } + + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(oid, oid_map[j].old_oid) == 0) { + oid = oid_map[j].new_oid; + break; + } + } + + switch (target) { + case TARGET_OPENLDAP: + schema_entry = talloc_asprintf(mem_ctx, + "objectclass (\n" + " %s\n", oid); + break; + case TARGET_FEDORA_DS: + schema_entry = talloc_asprintf(mem_ctx, + "objectClasses: (\n" + " %s\n", oid); + break; + } + IF_NULL_FAIL_RET(schema_entry); + if (!schema_entry) { + ret.failures++; + break; + } + + /* We might have been asked to remap this name, due to a conflict */ + for (j=0; name && attr_map && attr_map[j].old_attr; j++) { + if (strcasecmp(name, attr_map[j].old_attr) == 0) { + name = attr_map[j].new_attr; + break; + } + } + + schema_entry = talloc_asprintf_append(schema_entry, + " NAME '%s'\n", name); + IF_NULL_FAIL_RET(schema_entry); + + if (!schema_entry) return ret; + + if (description) { + schema_entry = talloc_asprintf_append(schema_entry, + " DESC %s\n", description); + IF_NULL_FAIL_RET(schema_entry); + } + + if (subClassOf) { + schema_entry = talloc_asprintf_append(schema_entry, + " SUP %s\n", subClassOf); + IF_NULL_FAIL_RET(schema_entry); + } + + switch (objectClassCategory) { + case 1: + schema_entry = talloc_asprintf_append(schema_entry, + " STRUCTURAL\n"); + IF_NULL_FAIL_RET(schema_entry); + break; + case 2: + schema_entry = talloc_asprintf_append(schema_entry, + " ABSTRACT\n"); + IF_NULL_FAIL_RET(schema_entry); + break; + case 3: + schema_entry = talloc_asprintf_append(schema_entry, + " AUXILIARY\n"); + IF_NULL_FAIL_RET(schema_entry); + break; + } + +#define APPEND_ATTRS(attributes) \ + do { \ + int k; \ + for (k=0; attributes && k < attributes->num_values; k++) { \ + int attr_idx; \ + const char *attr_name = (const char *)attributes->values[k].data; \ + /* We might have been asked to remap this name, due to a conflict */ \ + for (attr_idx=0; attr_name && attr_map && attr_map[attr_idx].old_attr; attr_idx++) { \ + if (strcasecmp(attr_name, attr_map[attr_idx].old_attr) == 0) { \ + attr_name = attr_map[attr_idx].new_attr; \ + break; \ + } \ + } \ + \ + schema_entry = talloc_asprintf_append(schema_entry, \ + " %s", \ + attr_name); \ + IF_NULL_FAIL_RET(schema_entry); \ + if (k != (attributes->num_values - 1)) { \ + schema_entry = talloc_asprintf_append(schema_entry, \ + " $"); \ + IF_NULL_FAIL_RET(schema_entry); \ + if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \ + schema_entry = talloc_asprintf_append(schema_entry, \ + "\n "); \ + IF_NULL_FAIL_RET(schema_entry); \ + } \ + } \ + } \ + } while (0) + + if ((must && must->values) || (sys_must && sys_must->values)) { + schema_entry = talloc_asprintf_append(schema_entry, + " MUST ("); + IF_NULL_FAIL_RET(schema_entry); + + APPEND_ATTRS(must); + if (must && must->values && sys_must && sys_must->values) { + schema_entry = talloc_asprintf_append(schema_entry, \ + " $"); \ + } + APPEND_ATTRS(sys_must); + + schema_entry = talloc_asprintf_append(schema_entry, + " )\n"); + IF_NULL_FAIL_RET(schema_entry); + } + + if ((may && may->values) || (sys_may && sys_may->values)) { + schema_entry = talloc_asprintf_append(schema_entry, + " MAY ("); + IF_NULL_FAIL_RET(schema_entry); + + APPEND_ATTRS(may); + if (may && may->values && sys_may && sys_may->values) { + schema_entry = talloc_asprintf_append(schema_entry, \ + " $"); \ + } + APPEND_ATTRS(sys_may); + + schema_entry = talloc_asprintf_append(schema_entry, + " )\n"); + IF_NULL_FAIL_RET(schema_entry); + } + + schema_entry = talloc_asprintf_append(schema_entry, + " )"); + + switch (target) { + case TARGET_OPENLDAP: + fprintf(out, "%s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + fprintf(out, "%s\n", schema_entry); + break; + } + ret.count++; + } + + return ret; +} + + 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; + const char *target_str; + enum convert_target target; + + ctx = talloc_new(NULL); + ldb = ldb_init(ctx, NULL); + + 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); + } + } + + target_str = lp_parm_string(cmdline_lp_ctx, NULL, "convert", "target"); + + if (!target_str || strcasecmp(target_str, "openldap") == 0) { + target = TARGET_OPENLDAP; + } else if (strcasecmp(target_str, "fedora-ds") == 0) { + target = TARGET_FEDORA_DS; + } else { + printf("Unsupported target: %s\n", target_str); + exit(1); + } + + ret = process_convert(ldb, target, in, out); + + fclose(in); + fclose(out); + + printf("Converted %d records (skipped %d) with %d failures\n", ret.count, ret.skipped, ret.failures); + + return 0; +} diff --git a/source4/utils/config.mk b/source4/utils/config.mk index d47b36ea7c..61565807d2 100644 --- a/source4/utils/config.mk +++ b/source4/utils/config.mk @@ -94,3 +94,31 @@ PRIVATE_DEPENDENCIES = \ ################################# testparm_OBJ_FILES = $(utilssrcdir)/testparm.o + +################################################ +# Start BINARY oLschema2ldif +[BINARY::oLschema2ldif] +INSTALLDIR = BINDIR +PRIVATE_DEPENDENCIES = \ + LIBLDB_CMDLINE +# End BINARY oLschema2ldif +################################################ + + +oLschema2ldif_OBJ_FILES = $(addprefix $(utilssrcdir)/, schema_convert.o oLschema2ldif.o) + +MANPAGES += $(utilssrcdir)/man/oLschema2ldif.1 + +################################################ +# Start BINARY ad2oLschema +[BINARY::ad2oLschema] +INSTALLDIR = BINDIR +PRIVATE_DEPENDENCIES = \ + LIBLDB_CMDLINE SAMDB +# End BINARY ad2oLschema +################################################ + +ad2oLschema_OBJ_FILES = $(addprefix $(utilssrcdir)/, schema_convert.o ad2oLschema.o) + +MANPAGES += $(utilssrcdir)/man/ad2oLschema.1 + diff --git a/source4/utils/oLschema2ldif.1.xml b/source4/utils/oLschema2ldif.1.xml new file mode 100644 index 0000000000..b1e681be4e --- /dev/null +++ b/source4/utils/oLschema2ldif.1.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"> +<refentry id="oLschema2ldif.1"> + +<refmeta> + <refentrytitle>oLschema2ldif</refentrytitle> + <manvolnum>1</manvolnum> +</refmeta> + + +<refnamediv> + <refname>oLschema2ldif</refname> + <refpurpose>Converts LDAP schema's to LDB-compatible LDIF</refpurpose> +</refnamediv> + +<refsynopsisdiv> + <cmdsynopsis> + <command>oLschema2ldif</command> + <arg choice="opt">-I INPUT-FILE</arg> + <arg choice="opt">-O OUTPUT-FILE</arg> + </cmdsynopsis> +</refsynopsisdiv> + +<refsect1> + <title>DESCRIPTION</title> + + <para>oLschema2ldif is a simple tool that converts standard OpenLDAP schema files to a LDIF format that is understood by LDB.</para> +</refsect1> + + +<refsect1> + <title>OPTIONS</title> + + <variablelist> + <varlistentry> + <term>-I input-file</term> + <listitem><para>OpenLDAP schema to read. If none are specified, +the schema file will be read from standard input. + </para></listitem> + </varlistentry> + + <varlistentry> + <term>-O output-file</term> + <listitem><para>File to write ldif version of schema to. + </para></listitem> + </varlistentry> + </variablelist> +</refsect1> + +<refsect1> + <title>VERSION</title> + + <para>This man page is correct for version 4.0 of the Samba suite.</para> +</refsect1> + +<refsect1> + <title>SEE ALSO</title> + + <para>ldb(7), ldbmodify, ldbdel, ldif(5)</para> + +</refsect1> + +<refsect1> + <title>AUTHOR</title> + + <para> ldb was written by + <ulink url="http://samba.org/~tridge/">Andrew Tridgell</ulink>. + oLschema2ldif was written by <ulink url="mailto:idra@samba.org">Simo Sorce</ulink>. + </para> + + <para> +If you wish to report a problem or make a suggestion then please see +the <ulink url="http://ldb.samba.org/"/> web site for +current contact and maintainer information. + </para> + +</refsect1> + +</refentry> diff --git a/source4/utils/oLschema2ldif.c b/source4/utils/oLschema2ldif.c new file mode 100644 index 0000000000..b501b75529 --- /dev/null +++ b/source4/utils/oLschema2ldif.c @@ -0,0 +1,603 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +/* + * Name: ldb + * + * Component: oLschema2ldif + * + * Description: utility to convert an OpenLDAP schema into AD LDIF + * + * Author: Simo Sorce + */ + +#include "ldb_includes.h" +#include "tools/cmdline.h" +#include "utils/schema_convert.h" + +#define SCHEMA_UNKNOWN 0 +#define SCHEMA_NAME 1 +#define SCHEMA_SUP 2 +#define SCHEMA_STRUCTURAL 3 +#define SCHEMA_ABSTRACT 4 +#define SCHEMA_AUXILIARY 5 +#define SCHEMA_MUST 6 +#define SCHEMA_MAY 7 +#define SCHEMA_SINGLE_VALUE 8 +#define SCHEMA_EQUALITY 9 +#define SCHEMA_ORDERING 10 +#define SCHEMA_SUBSTR 11 +#define SCHEMA_SYNTAX 12 +#define SCHEMA_DESC 13 + +struct schema_conv { + int count; + int failures; +}; + +struct schema_token { + int type; + char *value; +}; + +struct ldb_context *ldb_ctx; +struct ldb_dn *basedn; + +static int check_braces(const char *string) +{ + int b; + char *c; + + b = 0; + if ((c = strchr(string, '(')) == NULL) { + return -1; + } + b++; + c++; + while (b) { + c = strpbrk(c, "()"); + if (c == NULL) return 1; + if (*c == '(') b++; + if (*c == ')') b--; + c++; + } + return 0; +} + +static char *skip_spaces(char *string) { + return (string + strspn(string, " \t\n")); +} + +static int add_multi_string(struct ldb_message *msg, const char *attr, char *values) +{ + char *c; + char *s; + int n; + + c = skip_spaces(values); + while (*c) { + n = strcspn(c, " \t$"); + s = talloc_strndup(msg, c, n); + if (ldb_msg_add_string(msg, attr, s) != 0) { + return -1; + } + c += n; + c += strspn(c, " \t$"); + } + + return 0; +} + +#define MSG_ADD_STRING(a, v) do { if (ldb_msg_add_string(msg, a, v) != 0) goto failed; } while(0) +#define MSG_ADD_M_STRING(a, v) do { if (add_multi_string(msg, a, v) != 0) goto failed; } while(0) + +static char *get_def_value(TALLOC_CTX *ctx, char **string) +{ + char *c = *string; + char *value; + int n; + + if (*c == '\'') { + c++; + n = strcspn(c, "\'"); + value = talloc_strndup(ctx, c, n); + c += n; + c++; /* skip closing \' */ + } else { + n = strcspn(c, " \t\n"); + value = talloc_strndup(ctx, c, n); + c += n; + } + *string = c; + + return value; +} + +static struct schema_token *get_next_schema_token(TALLOC_CTX *ctx, char **string) +{ + char *c = skip_spaces(*string); + char *type; + struct schema_token *token; + int n; + + token = talloc(ctx, struct schema_token); + + n = strcspn(c, " \t\n"); + type = talloc_strndup(token, c, n); + c += n; + c = skip_spaces(c); + + if (strcasecmp("NAME", type) == 0) { + talloc_free(type); + token->type = SCHEMA_NAME; + /* we do not support aliases so we get only the first name given and skip others */ + if (*c == '(') { + char *s = strchr(c, ')'); + if (s == NULL) return NULL; + s = skip_spaces(s); + *string = s; + + c++; + c = skip_spaces(c); + } + + token->value = get_def_value(ctx, &c); + + if (*string < c) { /* single name */ + c = skip_spaces(c); + *string = c; + } + return token; + } + if (strcasecmp("SUP", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SUP; + + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("STRUCTURAL", type) == 0) { + talloc_free(type); + token->type = SCHEMA_STRUCTURAL; + *string = c; + return token; + } + + if (strcasecmp("ABSTRACT", type) == 0) { + talloc_free(type); + token->type = SCHEMA_ABSTRACT; + *string = c; + return token; + } + + if (strcasecmp("AUXILIARY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_AUXILIARY; + *string = c; + return token; + } + + if (strcasecmp("MUST", type) == 0) { + talloc_free(type); + token->type = SCHEMA_MUST; + + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("MAY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_MAY; + + if (*c == '(') { + c++; + n = strcspn(c, ")"); + token->value = talloc_strndup(ctx, c, n); + c += n; + c++; + } else { + token->value = get_def_value(ctx, &c); + } + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SINGLE-VALUE", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SINGLE_VALUE; + *string = c; + return token; + } + + if (strcasecmp("EQUALITY", type) == 0) { + talloc_free(type); + token->type = SCHEMA_EQUALITY; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("ORDERING", type) == 0) { + talloc_free(type); + token->type = SCHEMA_ORDERING; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SUBSTR", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SUBSTR; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("SYNTAX", type) == 0) { + talloc_free(type); + token->type = SCHEMA_SYNTAX; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + if (strcasecmp("DESC", type) == 0) { + talloc_free(type); + token->type = SCHEMA_DESC; + + token->value = get_def_value(ctx, &c); + + c = skip_spaces(c); + *string = c; + return token; + } + + token->type = SCHEMA_UNKNOWN; + token->value = type; + if (*c == ')') { + *string = c; + return token; + } + if (*c == '\'') { + c = strchr(++c, '\''); + c++; + } else { + c += strcspn(c, " \t\n"); + } + c = skip_spaces(c); + *string = c; + + return token; +} + +static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry) +{ + TALLOC_CTX *ctx; + struct ldb_message *msg; + struct schema_token *token; + char *c, *s; + int n; + + ctx = talloc_new(mem_ctx); + msg = ldb_msg_new(ctx); + + ldb_msg_add_string(msg, "objectClass", "top"); + + c = talloc_strdup(ctx, entry); + if (!c) return NULL; + + c = skip_spaces(c); + + switch (*c) { + case 'a': + if (strncmp(c, "attributetype", 13) == 0) { + c += 13; + MSG_ADD_STRING("objectClass", "attributeSchema"); + break; + } + goto failed; + case 'o': + if (strncmp(c, "objectclass", 11) == 0) { + c += 11; + MSG_ADD_STRING("objectClass", "classSchema"); + break; + } + goto failed; + default: + goto failed; + } + + c = strchr(c, '('); + if (c == NULL) goto failed; + c++; + + c = skip_spaces(c); + + /* get attributeID */ + n = strcspn(c, " \t"); + s = talloc_strndup(msg, c, n); + MSG_ADD_STRING("attributeID", s); + c += n; + c = skip_spaces(c); + + while (*c != ')') { + token = get_next_schema_token(msg, &c); + if (!token) goto failed; + + switch (token->type) { + case SCHEMA_NAME: + MSG_ADD_STRING("cn", token->value); + MSG_ADD_STRING("name", token->value); + MSG_ADD_STRING("lDAPDisplayName", token->value); + msg->dn = ldb_dn_copy(msg, basedn); + ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Schema,CN=Configuration", token->value); + break; + + case SCHEMA_SUP: + MSG_ADD_M_STRING("subClassOf", token->value); + break; + + case SCHEMA_STRUCTURAL: + MSG_ADD_STRING("objectClassCategory", "1"); + break; + + case SCHEMA_ABSTRACT: + MSG_ADD_STRING("objectClassCategory", "2"); + break; + + case SCHEMA_AUXILIARY: + MSG_ADD_STRING("objectClassCategory", "3"); + break; + + case SCHEMA_MUST: + MSG_ADD_M_STRING("mustContain", token->value); + break; + + case SCHEMA_MAY: + MSG_ADD_M_STRING("mayContain", token->value); + break; + + case SCHEMA_SINGLE_VALUE: + MSG_ADD_STRING("isSingleValued", "TRUE"); + break; + + case SCHEMA_EQUALITY: + /* TODO */ + break; + + case SCHEMA_ORDERING: + /* TODO */ + break; + + case SCHEMA_SUBSTR: + /* TODO */ + break; + + case SCHEMA_SYNTAX: + { + const struct syntax_map *map = + find_syntax_map_by_standard_oid(token->value); + if (!map) { + break; + } + MSG_ADD_STRING("attributeSyntax", map->AD_OID); + break; + } + case SCHEMA_DESC: + MSG_ADD_STRING("description", token->value); + break; + + default: + fprintf(stderr, "Unknown Definition: %s\n", token->value); + } + } + + talloc_steal(mem_ctx, msg); + talloc_free(ctx); + return msg; + +failed: + talloc_free(ctx); + return NULL; +} + +static struct schema_conv process_file(FILE *in, FILE *out) +{ + TALLOC_CTX *ctx; + struct schema_conv ret; + char *entry; + int c, t, line; + struct ldb_ldif ldif; + + ldif.changetype = LDB_CHANGETYPE_NONE; + + ctx = talloc_new(NULL); + + ret.count = 0; + ret.failures = 0; + line = 0; + + while ((c = fgetc(in)) != EOF) { + line++; + /* fprintf(stderr, "Parsing line %d\n", line); */ + if (c == '#') { + do { + c = fgetc(in); + } while (c != EOF && c != '\n'); + continue; + } + if (c == '\n') { + continue; + } + + t = 0; + entry = talloc_array(ctx, char, 1024); + if (entry == NULL) exit(-1); + + do { + if (c == '\n') { + entry[t] = '\0'; + if (check_braces(entry) == 0) { + ret.count++; + ldif.msg = process_entry(ctx, entry); + if (ldif.msg == NULL) { + ret.failures++; + fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line); + break; + } + ldb_ldif_write_file(ldb_ctx, out, &ldif); + break; + } + line++; + } else { + entry[t] = c; + t++; + } + if ((t % 1023) == 0) { + entry = talloc_realloc(ctx, entry, char, t + 1024); + if (entry == NULL) exit(-1); + } + } while ((c = fgetc(in)) != EOF); + + if (c != '\n') { + entry[t] = '\0'; + if (check_braces(entry) == 0) { + ret.count++; + ldif.msg = process_entry(ctx, entry); + if (ldif.msg == NULL) { + ret.failures++; + fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line); + break; + } + ldb_ldif_write_file(ldb_ctx, out, &ldif); + } else { + fprintf(stderr, "malformed entry on line %d\n", line); + ret.failures++; + } + } + + if (c == EOF) break; + } + + return ret; +} + +static void usage(void) +{ + printf("Usage: oLschema2ldif -H NONE <options>\n"); + printf("\nConvert OpenLDAP schema to AD-like LDIF format\n\n"); + printf("Options:\n"); + printf(" -I inputfile inputfile of OpenLDAP style schema otherwise STDIN\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 openLdap formatted schema to an ldif schema\n\n"); + exit(1); +} + + int main(int argc, const char **argv) +{ + TALLOC_CTX *ctx; + struct schema_conv ret; + struct ldb_cmdline *options; + FILE *in = stdin; + FILE *out = stdout; + ctx = talloc_new(NULL); + ldb_ctx = ldb_init(ctx, NULL); + + setenv("LDB_URL", "NONE", 1); + options = ldb_cmdline_process(ldb_ctx, argc, argv, usage); + + if (options->basedn == NULL) { + perror("Base DN not specified"); + exit(1); + } else { + basedn = ldb_dn_new(ctx, ldb_ctx, options->basedn); + if ( ! ldb_dn_validate(basedn)) { + perror("Malformed Base DN"); + exit(1); + } + } + + 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_file(in, out); + + fclose(in); + fclose(out); + + printf("Converted %d records with %d failures\n", ret.count, ret.failures); + + return 0; +} diff --git a/source4/utils/schema_convert.c b/source4/utils/schema_convert.c new file mode 100644 index 0000000000..a5d38451d4 --- /dev/null +++ b/source4/utils/schema_convert.c @@ -0,0 +1,173 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + ** 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "schema_convert.h" +#include "ldb_includes.h" + +/* Shared map for converting syntax between formats */ +static const struct syntax_map syntax_map[] = { + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.12", + .AD_OID = "2.5.5.1", + .equality = "distinguishedNameMatch", + .comment = "Object(DS-DN) == a DN" + }, +#if 0 + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.38", + .AD_OID = "2.5.5.2", + .equality = "objectIdentifierMatch", + .comment = "OID String" + }, +#else + { + .Standard_OID = "1.2.840.113556.1.4.905", + .AD_OID = "2.5.5.2", + .equality = "caseIgnoreMatch", + .comment = "OID as a Case Insensitive String" + }, +#endif + { + .Standard_OID = "1.2.840.113556.1.4.905", + .AD_OID = "2.5.5.4", + .equality = "caseIgnoreMatch", + .substring = "caseIgnoreSubstringsMatch", + .comment = "Case Insensitive String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", + .AD_OID = "2.5.5.5", + .equality = "caseExactIA5Match", + .comment = "Printable String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.36", + .AD_OID = "2.5.5.6", + .equality = "numericStringMatch", + .substring = "numericStringSubstringsMatch", + .comment = "Numeric String" + }, + { + .Standard_OID = "1.2.840.113556.1.4.903", + .AD_OID = "2.5.5.7", + .equality = "distinguishedNameMatch", + .comment = "OctetString: Binary+DN" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.7", + .AD_OID = "2.5.5.8", + .equality = "booleanMatch", + .comment = "Boolean" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.27", + .AD_OID = "2.5.5.9", + .equality = "integerMatch", + .comment = "Integer" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", + .AD_OID = "2.5.5.10", + .equality = "octetStringMatch", + .comment = "Octet String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.24", + .AD_OID = "2.5.5.11", + .equality = "generalizedTimeMatch", + .comment = "Generalized Time" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.53", + .AD_OID = "2.5.5.11", + .equality = "generalizedTimeMatch", + .comment = "UTC Time" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.15", + .AD_OID = "2.5.5.12", + .equality = "caseIgnoreMatch", + .substring = "caseIgnoreSubstringsMatch", + .comment = "Directory String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.43", + .AD_OID = "2.5.5.13", + .comment = "Presentation Address" + }, + { + .Standard_OID = "Not Found Yet", + .AD_OID = "2.5.5.14", + .equality = "distinguishedNameMatch", + .comment = "OctetString: String+DN" + }, + { + .Standard_OID = "1.2.840.113556.1.4.907", + .AD_OID = "2.5.5.15", + .equality = "octetStringMatch", + .comment = "NT Security Descriptor" + }, + { + .Standard_OID = "1.2.840.113556.1.4.906", + .AD_OID = "2.5.5.16", + .equality = "integerMatch", + .comment = "Large Integer" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", + .AD_OID = "2.5.5.17", + .equality = "octetStringMatch", + .comment = "Octet String - Security Identifier (SID)" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", + .AD_OID = "2.5.5.5", + .equality = "caseExactIA5Match", + .comment = "IA5 String" + }, + { .Standard_OID = NULL + } +}; + + +const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid) +{ + int i; + for (i=0; syntax_map[i].Standard_OID; i++) { + if (strcasecmp(ad_oid, syntax_map[i].AD_OID) == 0) { + return &syntax_map[i]; + } + } + return NULL; +} + +const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid) +{ + int i; + for (i=0; syntax_map[i].Standard_OID; i++) { + if (strcasecmp(standard_oid, syntax_map[i].Standard_OID) == 0) { + return &syntax_map[i]; + } + } + return NULL; +} diff --git a/source4/utils/schema_convert.h b/source4/utils/schema_convert.h new file mode 100644 index 0000000000..de379343a6 --- /dev/null +++ b/source4/utils/schema_convert.h @@ -0,0 +1,10 @@ +struct syntax_map { + const char *Standard_OID; + const char *AD_OID; + const char *equality; + const char *substring; + const char *comment; +}; + +const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid); +const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid); |