From: Bob Campbell Date: Tue, 7 Feb 2017 22:40:32 +0000 (+1300) Subject: samldb: Allow automatic generation of mAPIIDs X-Git-Tag: talloc-2.1.9~194 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec11d65bef7aaea155fb40e87a74210166eca7dd;p=thirdparty%2Fsamba.git samldb: Allow automatic generation of mAPIIDs This allows us to conform to MS-ADTS 3.1.1.2.3.2, where the OID 1.2.840.113556.1.2.49 can be specified as the mAPIID of a new attribute in the schema in order to automatically assign it an unused mAPIID. Signed-off-by: Bob Campbell Reviewed-by: Garming Sam Reviewed-by: Andrew Bartlett --- diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 755e2ed4fc9..ea43ccc78f6 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -439,8 +439,120 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac) } } -/* sAMAccountName handling */ +static int samldb_check_mapiid_used(struct samldb_ctx *ac, + struct dsdb_schema *schema, + struct ldb_dn *schema_dn, + struct ldb_context *ldb, + int32_t mapiid, + bool *found) +{ + int ret; + struct ldb_result *ldb_res; + + ret = dsdb_module_search(ac->module, ac, + &ldb_res, + schema_dn, LDB_SCOPE_ONELEVEL, NULL, + DSDB_FLAG_NEXT_MODULE, + ac->req, + "(mAPIID=%d)", mapiid); + if (ret != LDB_SUCCESS) { + ldb_debug_set(ldb, LDB_DEBUG_ERROR, + __location__": Searching for mAPIID=%d failed - %s\n", + mapiid, + ldb_errstring(ldb)); + return ldb_operr(ldb); + } + + *found = (ldb_res->count != 0); + talloc_free(ldb_res); + + return LDB_SUCCESS; +} + +static int samldb_generate_next_mapiid(struct samldb_ctx *ac, + struct dsdb_schema *schema, + int32_t *next_mapiid) +{ + int ret; + struct ldb_context *ldb; + struct ldb_dn *schema_dn; + bool mapiid_used = true; + + /* Windows' generation seems to start about here */ + *next_mapiid = 60000; + + ldb = ldb_module_get_ctx(ac->module); + schema_dn = ldb_get_schema_basedn(ldb); + while (mapiid_used) { + *next_mapiid += 1; + ret = samldb_check_mapiid_used(ac, schema, + schema_dn, ldb, + *next_mapiid, &mapiid_used); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + return LDB_SUCCESS; +} + +static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) +{ + int ret; + bool ok; + struct ldb_message_element *el; + const char *enc_str; + struct ldb_context *ldb; + struct ldb_dn *schema_dn; + struct dsdb_schema *schema; + int32_t new_mapiid = 0; + + /* + * The mAPIID of a new attribute should be automatically generated + * if a specific OID is put as the mAPIID, as according to + * [MS-ADTS] 3.1.1.2.3.2. + */ + + ldb = ldb_module_get_ctx(ac->module); + schema = dsdb_get_schema(ldb, ac); + schema_dn = ldb_get_schema_basedn(ldb); + + el = dsdb_get_single_valued_attr(ac->msg, "mAPIID", + ac->req->operation); + if (el == NULL) { + return LDB_SUCCESS; + } + + enc_str = ldb_binary_encode(ac, el->values[0]); + if (enc_str == NULL) { + return ldb_module_oom(ac->module); + } + + ok = (strcmp(enc_str, "1.2.840.113556.1.2.49") == 0); + if (ok) { + ret = samldb_generate_next_mapiid(ac, schema, + &new_mapiid); + if (ret != LDB_SUCCESS) { + return ret; + } + + ldb_msg_remove_element(ac->msg, el); + ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, + "mAPIID", new_mapiid); + return ret; + } + + schema_dn = ldb_get_schema_basedn(ldb_module_get_ctx(ac->module)); + ret = samldb_unique_attr_check(ac, "mAPIID", NULL, schema_dn); + if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) { + return LDB_ERR_UNWILLING_TO_PERFORM; + } else { + return ret; + } +} + +/* sAMAccountName handling */ static int samldb_generate_sAMAccountName(struct ldb_context *ldb, struct ldb_message *msg) { @@ -3398,6 +3510,11 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) if (ret != LDB_SUCCESS) { return ret; } + + ret = samldb_schema_add_handle_mapiid(ac); + if (ret != LDB_SUCCESS) { + return ret; + } } ret = samldb_schema_ldapdisplayname_valid_check(ac);