diff options
author | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
commit | 7f10bf980edef3ace1522d0c9c082b35e225c950 (patch) | |
tree | d4e9af21de194cca812e754b28f9358a3651f4ce /source4/dsdb/schema/schema_convert_to_ol.c | |
parent | f8f68703da58cf7f61b655b48bbbc45cda647748 (diff) | |
parent | f930f504e1d5e78d2f6f36cab9ce36dbeb34e955 (diff) | |
download | samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.gz samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.bz2 samba-7f10bf980edef3ace1522d0c9c082b35e225c950.zip |
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source4/dsdb/schema/schema_convert_to_ol.c')
-rw-r--r-- | source4/dsdb/schema/schema_convert_to_ol.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/source4/dsdb/schema/schema_convert_to_ol.c b/source4/dsdb/schema/schema_convert_to_ol.c new file mode 100644 index 0000000000..ebcb7ade59 --- /dev/null +++ b/source4/dsdb/schema/schema_convert_to_ol.c @@ -0,0 +1,350 @@ +/* + schema conversion routines + + Copyright (C) Andrew Bartlett 2006-2008 + + 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 3 of the License, or + (at your option) any later version. + + 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "includes.h" +#include "ldb.h" +#include "dsdb/samdb/samdb.h" +#include "system/locale.h" + +#define SEPERATOR "\n " + +struct attr_map { + char *old_attr; + char *new_attr; +}; + +struct oid_map { + char *old_oid; + char *new_oid; +}; + +static char *print_schema_recursive(char *append_to_string, struct dsdb_schema *schema, const char *print_class, + enum dsdb_schema_convert_target target, + const char **attrs_skip, const struct attr_map *attr_map, const struct oid_map *oid_map) +{ + char *out = append_to_string; + const struct dsdb_class *objectclass; + objectclass = dsdb_class_by_lDAPDisplayName(schema, print_class); + if (!objectclass) { + DEBUG(0, ("Cannot find class %s in schema\n", print_class)); + return NULL; + } + + do { + TALLOC_CTX *mem_ctx = talloc_new(append_to_string); + const char *name = objectclass->lDAPDisplayName; + const char *oid = objectclass->governsID_oid; + const char *subClassOf = objectclass->subClassOf; + int objectClassCategory = objectclass->objectClassCategory; + const char **must; + const char **may; + char *schema_entry = NULL; + const char *objectclass_name_as_list[] = { + objectclass->lDAPDisplayName, + NULL + }; + int j; + int attr_idx; + + if (!mem_ctx) { + DEBUG(0, ("Failed to create new talloc context\n")); + return NULL; + } + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + 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; + } + } + + /* 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; + } + } + + may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); + + for (j=0; may && may[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { + may[j] = attr_map[attr_idx].new_attr; + break; + } + } + } + + must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); + + for (j=0; must && must[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { + must[j] = attr_map[attr_idx].new_attr; + break; + } + } + } + + schema_entry = schema_class_description(mem_ctx, target, + SEPERATOR, + oid, + name, + NULL, + subClassOf, + objectClassCategory, + must, + may, + NULL); + if (schema_entry == NULL) { + DEBUG(0, ("failed to generate schema description for %s\n", name)); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_asprintf_append(out, "objectclass %s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + out = talloc_asprintf_append(out, "objectClasses: %s\n", schema_entry); + break; + } + talloc_free(mem_ctx); + } while (0); + + + for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) { + if (ldb_attr_cmp(objectclass->subClassOf, print_class) == 0 + && ldb_attr_cmp(objectclass->lDAPDisplayName, print_class) != 0) { + out = print_schema_recursive(out, schema, objectclass->lDAPDisplayName, + target, attrs_skip, attr_map, oid_map); + } + } + return out; +} + +/* Routine to linearise our internal schema into the format that + OpenLDAP and Fedora DS use for their backend. + + The 'mappings' are of a format like: + +#Standard OpenLDAP attributes +labeledURI +#The memberOf plugin provides this attribute +memberOf +#These conflict with OpenLDAP builtins +attributeTypes:samba4AttributeTypes +2.5.21.5:1.3.6.1.4.1.7165.4.255.7 + +*/ + + +char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str, const char *mappings) +{ + /* Read list of attributes to skip, OIDs to map */ + TALLOC_CTX *mem_ctx = talloc_new(ldb); + char *line; + char *out; + const char **attrs_skip = NULL; + int num_skip = 0; + struct oid_map *oid_map = NULL; + int num_oid_maps = 0; + struct attr_map *attr_map = NULL; + int num_attr_maps = 0; + struct dsdb_attribute *attribute; + struct dsdb_schema *schema; + enum dsdb_schema_convert_target target; + + char *next_line = talloc_strdup(mem_ctx, mappings); + + if (!target_str || strcasecmp(target_str, "openldap") == 0) { + target = TARGET_OPENLDAP; + } else if (strcasecmp(target_str, "fedora-ds") == 0) { + target = TARGET_FEDORA_DS; + } else { + DEBUG(0, ("Invalid target type for schema conversion %s\n", target_str)); + return NULL; + } + + /* The mappings are line-seperated, and specify details such as OIDs to skip etc */ + while (1) { + line = next_line; + next_line = strchr(line, '\n'); + if (!next_line) { + break; + } + next_line[0] = '\0'; + next_line++; + + /* Blank Line */ + if (line[0] == '\0') { + continue; + } + /* Comment */ + if (line[0] == '#') { + continue; + } + + if (isdigit(line[0])) { + char *p = strchr(line, ':'); + if (!p) { + DEBUG(0, ("schema mapping file line has OID but no OID to map to: %s\n", line)); + return NULL; + } + 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_strdup(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_strdup(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_strdup(attrs_skip, line); + num_skip++; + attrs_skip[num_skip] = NULL; + } + } + } + + schema = dsdb_get_schema(ldb); + if (!schema) { + DEBUG(0, ("No schema on ldb to convert!\n")); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_strdup(mem_ctx, ""); + break; + case TARGET_FEDORA_DS: + out = talloc_strdup(mem_ctx, "dn: cn=schema\n"); + break; + } + + for (attribute=schema->attributes; attribute; attribute = attribute->next) { + const char *name = attribute->lDAPDisplayName; + const char *oid = attribute->attributeID_oid; + const char *syntax = attribute->attributeSyntax_oid; + const char *equality = NULL, *substring = NULL; + bool single_value = attribute->isSingleValued; + + char *schema_entry = NULL; + int j; + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + 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; + } + } + + if (attribute->syntax) { + /* We might have been asked to remap this oid, + * due to a conflict, or lack of + * implementation */ + syntax = attribute->syntax->ldap_oid; + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; syntax && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(syntax, oid_map[j].old_oid) == 0) { + syntax = oid_map[j].new_oid; + break; + } + } + + equality = attribute->syntax->equality; + substring = attribute->syntax->substring; + } + + /* 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 = schema_attribute_description(mem_ctx, + target, + SEPERATOR, + oid, + name, + equality, + substring, + syntax, + single_value, + false, + NULL, NULL, + NULL, NULL, + false, false); + + if (schema_entry == NULL) { + DEBUG(0, ("failed to generate attribute description for %s\n", name)); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_asprintf_append(out, "attributetype %s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + out = talloc_asprintf_append(out, "attributeTypes: %s\n", schema_entry); + break; + } + } + + out = print_schema_recursive(out, schema, "top", target, attrs_skip, attr_map, oid_map); + + return out; +} + |