diff options
author | Andrew Bartlett <abartlet@samba.org> | 2009-09-23 21:14:37 -0700 |
---|---|---|
committer | Matthias Dieter Wallnöfer <mwallnoefer@yahoo.de> | 2009-11-15 14:26:40 +0100 |
commit | 2c7294bd8faad339d090ee7a7d8d1bb44c9837fc (patch) | |
tree | 4356b3cb9823c6cbea8b64464858c72e08ee7e8f /source4/dsdb/samdb/ldb_modules | |
parent | da3d471d10a822713fea937b3e1951bdbdc7dc83 (diff) | |
download | samba-2c7294bd8faad339d090ee7a7d8d1bb44c9837fc.tar.gz samba-2c7294bd8faad339d090ee7a7d8d1bb44c9837fc.tar.bz2 samba-2c7294bd8faad339d090ee7a7d8d1bb44c9837fc.zip |
s4:SAMLDB module - Add support for required and generated schema attributes
This missing support found by Microsoft test suite at AD interop event.
Patch by Andrew Bartlett
Enhancements by Matthias Dieter Wallnöfer
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 292 |
1 files changed, 285 insertions, 7 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 0f314b241a..390950bb75 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -97,6 +97,9 @@ struct samldb_ctx { /* all the async steps necessary to complete the operation */ struct samldb_step *steps; struct samldb_step *curstep; + + /* If someone set an ares to forward controls and response back to the caller */ + struct ldb_reply *ares; }; static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module, @@ -161,9 +164,14 @@ static int samldb_next_step(struct samldb_ctx *ac) return ac->curstep->fn(ac); } - /* it is an error if the last step does not properly - * return to the upper module by itself */ - return LDB_ERR_OPERATIONS_ERROR; + /* we exit the samldb module here */ + /* If someone set an ares to forward controls and response back to the caller, use them */ + if (ac->ares) { + return ldb_module_done(ac->req, ac->ares->controls, + ac->ares->response, LDB_SUCCESS); + } else { + return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS); + } } /* @@ -868,6 +876,152 @@ static int samldb_notice_sid(struct samldb_ctx *ac) } /* + * samldb_set_defaultObjectCategory_callback (async) + */ + +static int samldb_set_defaultObjectCategory_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct samldb_ctx *ac; + int ret; + + ac = talloc_get_type(req->context, struct samldb_ctx); + ldb = ldb_module_get_ctx(ac->module); + + if (!ares) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + if (ares->type != LDB_REPLY_DONE) { + ldb_set_errstring(ldb, + "Invalid reply type!\n"); + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + + ret = samldb_next_step(ac); + +done: + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + + return LDB_SUCCESS; +} + +static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac) +{ + int ret; + if (ac->dn) { + struct ldb_request *req; + struct ldb_context *ldb; + struct ldb_message *msg = ldb_msg_new(ac); + + msg->dn = ac->dn; + + ldb_msg_add_empty(msg, "defaultObjectCategory", LDB_FLAG_MOD_REPLACE, NULL); + + ldb_msg_add_steal_string(msg, "defaultObjectCategory", ldb_dn_alloc_linearized(msg, ac->dn)); + + ldb = ldb_module_get_ctx(ac->module); + + ret = ldb_build_mod_req(&req, ldb, ac, + msg, NULL, + ac, samldb_set_defaultObjectCategory_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(ac->module, req); + } + + ret = samldb_next_step(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + return ret; +} + +/* + * samldb_find_for_defaultObjectCategory (async) + */ + +static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req, + struct ldb_reply *ares) +{ + struct samldb_ctx *ac; + int ret; + + ac = talloc_get_type(req->context, struct samldb_ctx); + + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + ac->dn = talloc_steal(ac, ares->message->dn); + break; + case LDB_REPLY_REFERRAL: + /* this should not happen */ + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + + case LDB_REPLY_DONE: + /* found or not found, go on */ + talloc_free(ares); + ret = samldb_next_step(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + break; + } + + return LDB_SUCCESS; +} + +static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac) +{ + struct ldb_context *ldb; + struct ldb_request *req; + int ret; + const char *no_attrs[] = { NULL }; + + ldb = ldb_module_get_ctx(ac->module); + + ac->dn = NULL; + + if (ldb_msg_find_element(ac->msg, "defaultObjectCategory") == NULL) { + ret = ldb_build_search_req(&req, ldb, ac, + ac->msg->dn, LDB_SCOPE_BASE, + "objectClass=classSchema", no_attrs, + NULL, + ac, samldb_find_for_defaultObjectCategory_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + return ldb_next_request(ac->module, req); + } + + ret = samldb_next_step(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + return ret; + +} + + + +/* * samldb_add_entry (async) */ @@ -876,6 +1030,7 @@ static int samldb_add_entry_callback(struct ldb_request *req, { struct ldb_context *ldb; struct samldb_ctx *ac; + int ret; ac = talloc_get_type(req->context, struct samldb_ctx); ldb = ldb_module_get_ctx(ac->module); @@ -895,9 +1050,14 @@ static int samldb_add_entry_callback(struct ldb_request *req, LDB_ERR_OPERATIONS_ERROR); } - /* we exit the samldb module here */ - return ldb_module_done(ac->req, ares->controls, - ares->response, LDB_SUCCESS); + /* The caller may wish to get controls back from the add */ + ac->ares = talloc_steal(ac, ares); + + ret = samldb_next_step(ac); + if (ret != LDB_SUCCESS) { + return ldb_module_done(ac->req, NULL, NULL, ret); + } + return ret; } static int samldb_add_entry(struct samldb_ctx *ac) @@ -975,8 +1135,102 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type) ret = samdb_find_or_add_attribute(ldb, ac->msg, "groupType", "-2147483646"); if (ret != LDB_SUCCESS) return ret; + } else if (strcmp(ac->type, "classSchema") == 0) { + const struct ldb_val *rdn_value; + + ret = samdb_find_or_add_attribute(ldb, ac->msg, + "rdnAttId", "cn"); + if (ret != LDB_SUCCESS) return ret; + + rdn_value = ldb_dn_get_rdn_val(ac->msg->dn); + if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) { + /* the RDN has prefix "CN" */ + ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName", + samdb_cn_to_lDAPDisplayName(ac, + (const char *) rdn_value->data)); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return ret; + } + } + + if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) { + enum ndr_err_code ndr_err; + struct ldb_val guid_value; + struct GUID guid; + /* a new GUID */ + guid = GUID_random(); + /* generated NDR encoded values */ + ndr_err = ndr_push_struct_blob(&guid_value, ac->msg, + NULL, + &guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return ret; + } + } + + ret = samldb_add_step(ac, samldb_add_entry); + if (ret != LDB_SUCCESS) return ret; + + ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory); + if (ret != LDB_SUCCESS) return ret; + + ret = samldb_add_step(ac, samldb_set_defaultObjectCategory); + if (ret != LDB_SUCCESS) return ret; + + return samldb_first_step(ac); + } else if (strcmp(ac->type, "attributeSchema") == 0) { + const struct ldb_val *rdn_value; + rdn_value = ldb_dn_get_rdn_val(ac->msg->dn); + if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) { + /* the RDN has prefix "CN" */ + ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName", + samdb_cn_to_lDAPDisplayName(ac, + (const char *) rdn_value->data)); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return ret; + } + } + + ret = samdb_find_or_add_attribute(ldb, ac->msg, + "isSingleValued", "FALSE"); + if (ret != LDB_SUCCESS) return ret; + + if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) { + enum ndr_err_code ndr_err; + struct ldb_val guid_value; + struct GUID guid; + /* a new GUID */ + guid = GUID_random(); + /* generated NDR encoded values */ + ndr_err = ndr_push_struct_blob(&guid_value, ac->msg, + NULL, + &guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL); + if (ret != LDB_SUCCESS) { + ldb_oom(ldb); + return ret; + } + } + + ret = samldb_add_step(ac, samldb_add_entry); + if (ret != LDB_SUCCESS) return ret; + + return samldb_first_step(ac); } else { - /* we should only have "user" and "group" */ ldb_asprintf_errstring(ldb, "Invalid entry type!\n"); return LDB_ERR_OPERATIONS_ERROR; @@ -1952,6 +2206,30 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return samldb_fill_foreignSecurityPrincipal_object(ac); } + if (samdb_find_attribute(ldb, ac->msg, + "objectclass", "classSchema") != NULL) { + + ret = samldb_check_rdn(module, ac->req->op.add.message->dn); + if (ret != LDB_SUCCESS) { + talloc_free(ac); + return ret; + } + + return samldb_fill_object(ac, "classSchema"); + } + + if (samdb_find_attribute(ldb, ac->msg, + "objectclass", "attributeSchema") != NULL) { + + ret = samldb_check_rdn(module, ac->req->op.add.message->dn); + if (ret != LDB_SUCCESS) { + talloc_free(ac); + return ret; + } + + return samldb_fill_object(ac, "attributeSchema"); + } + talloc_free(ac); /* nothing matched, go on */ |