diff --git a/source/lib/ldb-samba/ldif_handlers.c b/source/lib/ldb-samba/ldif_handlers.c index 5c29d001c26..fb9ac8f8da3 100644 --- a/source/lib/ldb-samba/ldif_handlers.c +++ b/source/lib/ldb-samba/ldif_handlers.c @@ -26,7 +26,9 @@ #include "dsdb/samdb/samdb.h" #include "librpc/gen_ndr/ndr_security.h" #include "librpc/gen_ndr/ndr_misc.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" #include "libcli/security/security.h" +#include "param/param.h" /* convert a ldif formatted objectSid to a NDR formatted blob @@ -371,10 +373,178 @@ static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx return ret; } +/* + convert a ldif formatted prefixMap to a NDR formatted blob +*/ +static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct prefixMapBlob *blob; + enum ndr_err_code ndr_err; + char *string, *line, *p, *oid; + + blob = talloc_zero(mem_ctx, struct prefixMapBlob); + if (blob == NULL) { + return -1; + } + + string = (const char *)in->data; + + line = string; + while (line && line[0]) { + p=strchr(line, ';'); + if (p) { + p[0] = '\0'; + } else { + p=strchr(string, '\n'); + if (p) { + p[0] = '\0'; + } + } + + blob->ctr.dsdb.mappings = talloc_realloc(blob, + blob->ctr.dsdb.mappings, + struct drsuapi_DsReplicaOIDMapping, + blob->ctr.dsdb.num_mappings+1); + if (!blob->ctr.dsdb.mappings) { + return -1; + } + + blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(p, &oid, 10); + + if (oid[0] != ':') { + return -1; + } + + /* we know there must be at least ":" */ + oid++; + + blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid + = talloc_strdup(blob->ctr.dsdb.mappings, oid); + + blob->ctr.dsdb.num_mappings++; + + if (p) { + line = p++; + } else { + line = NULL; + } + } + + ndr_err = ndr_push_struct_blob(out, mem_ctx, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + blob, + (ndr_push_flags_fn_t)ndr_push_prefixMapBlob); + talloc_free(blob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return -1; + } + return 0; +} + +/* + convert a NDR formatted blob to a ldif formatted prefixMap +*/ +static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + struct prefixMapBlob *blob; + enum ndr_err_code ndr_err; + uint32_t i; + + blob = talloc(mem_ctx, struct prefixMapBlob); + if (blob == NULL) { + return -1; + } + ndr_err = ndr_pull_struct_blob(in, blob, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + blob, + (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(blob); + return -1; + } + if (blob->version != PREFIX_MAP_VERSION_DSDB) { + return -1; + } + out->data = talloc_strdup(mem_ctx, ""); + if (out->data == NULL) { + return -1; + } + + for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { + if (i > 0) { + out->data = talloc_asprintf_append(out->data, ";"); + } + out->data = talloc_asprintf_append(out->data, "%u: %s", + blob->ctr.dsdb.mappings[i].id_prefix, + blob->ctr.dsdb.mappings[i].oid.oid); + if (out->data == NULL) { + return -1; + } + } + + talloc_free(blob); + out->length = strlen((const char *)out->data); + return 0; +} + +static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v) +{ + if (v->length < 4) { + return true; + } + + if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) { + return false; + } + + return true; +} + +/* + canonicalise a prefixMap +*/ +static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *in, struct ldb_val *out) +{ + if (ldif_comparision_prefixMap_isString(in)) { + return ldif_read_prefixMap(ldb, mem_ctx, in, out); + } + return ldb_handler_copy(ldb, mem_ctx, in, out); +} + +static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx, + const struct ldb_val *v1, + const struct ldb_val *v2) +{ + + int ret, ret1, ret2; + struct ldb_val v1_canon, v2_canon; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + + /* I could try and bail if tmp_ctx was NULL, but what return + * value would I use? + * + * It seems easier to continue on the NULL context + */ + ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon); + ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon); + + if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) { + ret = data_blob_cmp(&v1_canon, &v2_canon); + } else { + ret = data_blob_cmp(v1, v2); + } + talloc_free(tmp_ctx); + return ret; +} + #define LDB_SYNTAX_SAMBA_SID "LDB_SYNTAX_SAMBA_SID" #define LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR "LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR" #define LDB_SYNTAX_SAMBA_GUID "LDB_SYNTAX_SAMBA_GUID" #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY" +#define LDB_SYNTAX_SAMBA_PREFIX_MAP "LDB_SYNTAX_SAMBA_PREFIX_MAP" static const struct ldb_schema_syntax samba_syntaxes[] = { { @@ -401,6 +571,12 @@ static const struct ldb_schema_syntax samba_syntaxes[] = { .ldif_write_fn = ldb_handler_copy, .canonicalise_fn= ldif_canonicalise_objectCategory, .comparison_fn = ldif_comparison_objectCategory + },{ + .name = LDB_SYNTAX_SAMBA_PREFIX_MAP, + .ldif_read_fn = ldif_read_prefixMap, + .ldif_write_fn = ldif_write_prefixMap, + .canonicalise_fn= ldif_canonicalise_prefixMap, + .comparison_fn = ldif_comparison_prefixMap } }; @@ -435,6 +611,7 @@ static const struct { { "masteredBy", LDB_SYNTAX_DN }, { "msDs-masteredBy", LDB_SYNTAX_DN }, { "fSMORoleOwner", LDB_SYNTAX_DN }, + { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP } }; /* diff --git a/source/script/installmisc.sh b/source/script/installmisc.sh index 4707aafdbd2..5f7e11f0837 100755 --- a/source/script/installmisc.sh +++ b/source/script/installmisc.sh @@ -25,6 +25,7 @@ cp setup/*.reg $SETUPDIR || exit 1 cp setup/*.zone $SETUPDIR || exit 1 cp setup/*.conf $SETUPDIR || exit 1 cp setup/*.php $SETUPDIR || exit 1 +cp setup/*.txt $SETUPDIR || exit 1 cp setup/provision.smb.conf.dc $SETUPDIR || exit 1 cp setup/provision.smb.conf.member $SETUPDIR || exit 1 cp setup/provision.smb.conf.standalone $SETUPDIR || exit 1 diff --git a/source/scripting/python/samba/provision.py b/source/scripting/python/samba/provision.py index 4a9def8aa9c..71c1ac31878 100644 --- a/source/scripting/python/samba/provision.py +++ b/source/scripting/python/samba/provision.py @@ -797,13 +797,17 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "EXTENSIBLEOBJECT": "# no objectClass: extensibleObject for local ldb" }) message("Modifying schema container") + + prefixmap = open(setup_path("prefixMap.txt"), 'r').read() + setup_modify_ldif(samdb, setup_path("provision_schema_basedn_modify.ldif"), { "SCHEMADN": names.schemadn, "NETBIOSNAME": names.netbiosname, "DEFAULTSITE": names.sitename, "CONFIGDN": names.configdn, - "SERVERDN": names.serverdn + "SERVERDN": names.serverdn, + "PREFIXMAP_B64": b64encode(prefixmap) }) message("Setting up sam.ldb Samba4 schema") @@ -1389,12 +1393,16 @@ def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename): schema_data = open(setup_path("schema.ldif"), 'r').read() schema_data += open(setup_path("schema_samba4.ldif"), 'r').read() schema_data = substitute_var(schema_data, {"SCHEMADN": schemadn}) + prefixmap = open(setup_path("prefixMap.txt"), 'r').read() + prefixmap = b64encode(prefixmap) + head_data = open(setup_path("provision_schema_basedn_modify.ldif"), 'r').read() head_data = substitute_var(head_data, { "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, "CONFIGDN": configdn, - "DEFAULTSITE":sitename + "DEFAULTSITE":sitename, + "PREFIXMAP_B64":prefixmap }) samdb.attach_schema_from_ldif(head_data, schema_data) diff --git a/source/setup/prefixMap.txt b/source/setup/prefixMap.txt new file mode 100644 index 00000000000..34a913c990d --- /dev/null +++ b/source/setup/prefixMap.txt @@ -0,0 +1,34 @@ +0: 2.5.4 +1: 2.5.6 +2: 1.2.840.113556.1.2 +3: 1.2.840.113556.1.3 +4: 2.16.840.1.101.2.2.1 +5: 2.16.840.1.101.2.2.3 +6: 2.16.840.1.101.2.1.5 +7: 2.16.840.1.101.2.1.4 +8: 2.5.5 +9: 1.2.840.113556.1.4 +10: 1.2.840.113556.1.5 +19: 0.9.2342.19200300.100 +20: 2.16.840.1.113730.3 +21: 0.9.2342.19200300.100.1 +22: 2.16.840.1.113730.3.1 +23: 1.2.840.113556.1.5.7000 +24: 2.5.21 +25: 2.5.18 +26: 2.5.20 +11: 1.2.840.113556.1.4.260 +12: 1.2.840.113556.1.5.56 +13: 1.2.840.113556.1.4.262 +14: 1.2.840.113556.1.5.57 +15: 1.2.840.113556.1.4.263 +16: 1.2.840.113556.1.5.58 +17: 1.2.840.113556.1.5.73 +18: 1.2.840.113556.1.4.305 +27: 1.3.6.1.4.1.1466.101.119 +28: 2.16.840.1.113730.3.2 +29: 1.3.6.1.4.1.250.1 +30: 1.2.840.113549.1.9 +31: 0.9.2342.19200300.100.4 +32: 1.3.6.1.4.1.7165.4.1 +33: 1.3.6.1.4.1.7165.4.2 diff --git a/source/setup/provision_schema_basedn_modify.ldif b/source/setup/provision_schema_basedn_modify.ldif index 4e8267a303e..d6c458904eb 100644 --- a/source/setup/provision_schema_basedn_modify.ldif +++ b/source/setup/provision_schema_basedn_modify.ldif @@ -10,19 +10,5 @@ replace: objectVersion objectVersion: 30 - replace: prefixMap -prefixMap:: QkRTRAAAAAAiAAAAAAACACIAAAAAAAAAAgAAAAQAAgABAAAAAgAAAAgAAgACAAAACA - AAAAwAAgADAAAACAAAABAAAgAEAAAACAAAABQAAgAFAAAACAAAABgAAgAGAAAACAAAABwAAgAHAAA - ACAAAACAAAgAIAAAAAgAAACQAAgAJAAAACAAAACgAAgAKAAAACAAAACwAAgATAAAACAAAADAAAgAU - AAAACAAAADQAAgAVAAAACQAAADgAAgAWAAAACQAAADwAAgAXAAAACgAAAEAAAgAYAAAAAgAAAEQAA - gAZAAAAAgAAAEgAAgAaAAAAAgAAAEwAAgALAAAACgAAAFAAAgAMAAAACQAAAFQAAgANAAAACgAAAF - gAAgAOAAAACQAAAFwAAgAPAAAACgAAAGAAAgAQAAAACQAAAGQAAgARAAAACQAAAGgAAgASAAAACgA - AAGwAAgAbAAAACQAAAHAAAgAcAAAACQAAAHQAAgAdAAAACAAAAHgAAgAeAAAACAAAAHwAAgAfAAAA - CQAAAIAAAgAgAAAACQAAAIQAAgAhAAAACQAAAIgAAgACAAAAVQQAAAIAAABVBgAACAAAACqGSIb3F - AECCAAAACqGSIb3FAEDCAAAAGCGSAFlAgIBCAAAAGCGSAFlAgIDCAAAAGCGSAFlAgEFCAAAAGCGSA - FlAgEEAgAAAFUFAAAIAAAAKoZIhvcUAQQIAAAAKoZIhvcUAQUIAAAACZImiZPyLGQIAAAAYIZIAYb - 4QgMJAAAACZImiZPyLGQBAAAACQAAAGCGSAGG+EIDAQAAAAoAAAAqhkiG9xQBBbZYAAACAAAAVRUA - AAIAAABVEgAAAgAAAFUUAAAKAAAAKoZIhvcUAQSCBAAACQAAACqGSIb3FAEFOAAAAAoAAAAqhkiG9 - xQBBIIGAAAJAAAAKoZIhvcUAQU5AAAACgAAACqGSIb3FAEEggcAAAkAAAAqhkiG9xQBBToAAAAJAA - AAKoZIhvcUAQVJAAAACgAAACqGSIb3FAEEgjEAAAkAAAArBgEEAYs6ZXcAAAAJAAAAYIZIAYb4QgM - CAAAACAAAACsGAQQBgXoBCAAAACqGSIb3DQEJCQAAAAmSJomT8ixkBAAAAAkAAAArBgEEAbd9BAEA - AAAJAAAAKwYBBAG3fQQC +prefixMap:: ${PREFIXMAP_B64} +