struct ldb_context *ldb;
const struct dsdb_schema *schema;
const struct dsdb_class *objectclass;
- struct ldb_dn *nc_root;
struct ldb_control *as_system;
+ struct ldb_message_element *el;
+ unsigned int instanceType = 0;
if (ldb_dn_is_special(req->op.add.message->dn)) {
return ldb_next_request(module, req);
return ldb_oom(ldb);
}
- /* Creating an NC. There is probably something we should do here,
- * but we will establish that later */
-
- ret = dsdb_find_nc_root(ldb, req, req->op.add.message->dn, &nc_root);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- if (ldb_dn_compare(nc_root, req->op.add.message->dn) == 0) {
- talloc_free(nc_root);
- return ldb_next_request(module, req);
- }
- talloc_free(nc_root);
-
schema = dsdb_get_schema(ldb, req);
if (!schema) {
return ldb_operr(ldb);
objectclass = dsdb_get_structural_oc_from_msg(schema, req->op.add.message);
if (!objectclass) {
ldb_asprintf_errstring(ldb_module_get_ctx(module),
- "acl: unable to find or validate structrual objectClass on %s\n",
+ "acl: unable to find or validate structural objectClass on %s\n",
ldb_dn_get_linearized(req->op.add.message->dn));
return ldb_module_done(req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
}
+ el = ldb_msg_find_element(req->op.add.message, "instanceType");
+ if ((el != NULL) && (el->num_values != 1)) {
+ ldb_set_errstring(ldb, "acl: the 'instanceType' attribute is single-valued!");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
+ "instanceType", 0);
+ if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
+ static const char *no_attrs[] = { NULL };
+ struct ldb_result *partition_res;
+ struct ldb_dn *partitions_dn;
+
+ partitions_dn = samdb_partitions_dn(ldb, req);
+ if (!partitions_dn) {
+ ldb_set_errstring(ldb, "acl: CN=partitions dn could not be generated!");
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ ret = dsdb_module_search(module, req, &partition_res,
+ partitions_dn, LDB_SCOPE_ONELEVEL,
+ no_attrs,
+ DSDB_FLAG_NEXT_MODULE |
+ DSDB_FLAG_AS_SYSTEM |
+ DSDB_SEARCH_ONE_ONLY |
+ DSDB_SEARCH_SHOW_RECYCLED,
+ req,
+ "(&(nCName=%s)(objectClass=crossRef))",
+ ldb_dn_get_linearized(req->op.add.message->dn));
+
+ if (ret == LDB_SUCCESS) {
+ /* Check that we can write to the crossRef object MS-ADTS 3.1.1.5.2.8.2 */
+ ret = dsdb_module_check_access_on_dn(module, req, partition_res->msgs[0]->dn,
+ SEC_ADS_WRITE_PROP,
+ &objectclass->schemaIDGUID, req);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "acl: ACL check failed on crossRef object %s: %s\n",
+ ldb_dn_get_linearized(partition_res->msgs[0]->dn),
+ ldb_errstring(ldb));
+ return ret;
+ }
+
+ /*
+ * TODO: Remaining checks, like if we are
+ * the naming master etc need to be handled
+ * in the instanceType module
+ */
+ return ldb_next_request(module, req);
+ }
+
+ /* Check that we can create a crossRef object MS-ADTS 3.1.1.5.2.8.2 */
+ ret = dsdb_module_check_access_on_dn(module, req, partitions_dn,
+ SEC_ADS_CREATE_CHILD,
+ &objectclass->schemaIDGUID, req);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT &&
+ ldb_request_get_control(req, LDB_CONTROL_RELAX_OID))
+ {
+ /* Allow provision bootstrap */
+ ret = LDB_SUCCESS;
+ }
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "acl: ACL check failed on CN=Partitions crossRef container %s: %s\n",
+ ldb_dn_get_linearized(partitions_dn), ldb_errstring(ldb));
+ return ret;
+ }
+
+ /*
+ * TODO: Remaining checks, like if we are the naming
+ * master and adding the crossRef object need to be
+ * handled in the instanceType module
+ */
+ return ldb_next_request(module, req);
+ }
+
ret = dsdb_module_check_access_on_dn(module, req, parent,
SEC_ADS_CREATE_CHILD,
&objectclass->schemaIDGUID, req);
if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb_module_get_ctx(module),
+ "acl: unable to find or validate structrual objectClass on %s\n",
+ ldb_dn_get_linearized(req->op.add.message->dn));
return ret;
}
return ldb_next_request(module, req);