Author: abartlet Date: 2007-10-31 05:14:31 +0000 (Wed, 31 Oct 2007) New Revision: 25763
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=25763 Log: Handle modifies, in the easy case (add/delete of elements), for the linked attributes. Andrew Bartlett Modified: branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/linked_attributes.c Changeset: Modified: branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/linked_attributes.c =================================================================== --- branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/linked_attributes.c 2007-10-31 04:41:36 UTC (rev 25762) +++ branches/SAMBA_4_0/source/dsdb/samdb/ldb_modules/linked_attributes.c 2007-10-31 05:14:31 UTC (rev 25763) @@ -220,18 +220,168 @@ /* modify */ static int linked_attributes_modify(struct ldb_module *module, struct ldb_request *req) { - return ldb_next_request(module, req); + /* Look over list of modifications */ + /* Find if any are for linked attributes */ + /* Determine the effect of the modification */ + /* Apply the modify to the linked entry */ + + int i, j, ret; + struct linked_attributes_context *ac; + + const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + if (!schema) { + /* without schema, this doesn't make any sense */ + return ldb_next_request(module, req); + } + + if (ldb_dn_is_special(req->op.mod.message->dn)) { + /* do not manipulate our control entries */ + return ldb_next_request(module, req); + } + + + ac = linked_attributes_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* prepare the first operation */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, 1); + if (!ac->down_req) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ac->down_req[0] = talloc(ac->down_req, struct ldb_request); + if (!ac->down_req[0]) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + *(ac->down_req[0]) = *req; /* copy the request */ + + ac->num_requests++; + + /* Run the original request */ + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + + for (i=0; i < req->op.mod.message->num_elements; i++) { + const struct dsdb_attribute *target_attr; + const struct ldb_message_element *el = &req->op.mod.message->elements[i]; + const struct dsdb_attribute *schema_attr + = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + if (!schema_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s is not a valid attribute in schema", req->op.mod.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + /* We have a valid attribute, not find out if it is linked */ + if (schema_attr->linkID == 0) { + continue; + } + + if ((schema_attr->linkID & 1) == 1) { + /* Odd is for the target. Illigal to modify */ + ldb_asprintf_errstring(module->ldb, + "attribute %s must not be modified directly, it is a linked attribute", req->op.mod.message->elements[i].name); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + /* Even link IDs are for the originating attribute */ + + /* Now find the target attribute */ + target_attr = dsdb_attribute_by_linkID(schema, schema_attr->linkID + 1); + if (!target_attr) { + ldb_asprintf_errstring(module->ldb, + "attribute %s does not have valid link target", req->op.mod.message->elements[i].name); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + + if ((el->flags & LDB_FLAG_MOD_MASK) == LDB_FLAG_MOD_REPLACE) { + ldb_asprintf_errstring(module->ldb, + "attribute %s may not be replaced, only added or deleted", req->op.mod.message->elements[i].name); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + /* Prepare the modify (mod element) on the targets */ + + /* For each value being moded, we need to setup the modify */ + for (j=0; j < el->num_values; j++) { + struct ldb_request *new_req; + /* Create the modify request */ + struct ldb_message *new_msg = ldb_msg_new(ac->down_req); + if (!new_msg) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data); + if (!new_msg->dn) { + ldb_asprintf_errstring(module->ldb, + "attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name, + el->values[j].data); + return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; + } + + ret = ldb_msg_add_empty(new_msg, target_attr->lDAPDisplayName, + el->flags & LDB_FLAG_MOD_MASK, NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_msg_add_string(new_msg, target_attr->lDAPDisplayName, + ldb_dn_get_linearized(ac->orig_req->op.add.message->dn)); + if (ret != LDB_SUCCESS) { + return ret; + } + + ret = ldb_build_mod_req(&new_req, module->ldb, ac->down_req, + new_msg, + NULL, + NULL, + NULL); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(new_req, new_msg); + + ldb_set_timeout_from_prev_req(module->ldb, req, new_req); + + /* Now add it to the list */ + ac->down_req = talloc_realloc(ac, ac->down_req, + struct ldb_request *, ac->num_requests + 1); + if (!ac->down_req) { + ldb_oom(ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->down_req[ac->num_requests] = new_req; + ac->num_requests++; + + /* Run the new request */ + ret = ldb_next_request(module, new_req); + if (ret != LDB_SUCCESS) { + return ret; + } + } + } + return ret; } /* delete */ static int linked_attributes_delete(struct ldb_module *module, struct ldb_request *req) { + /* Look up list of linked attributes */ + /* Search to see if any linked attributes are in this entry */ return ldb_next_request(module, req); } /* rename */ static int linked_attributes_rename(struct ldb_module *module, struct ldb_request *req) { + /* Look up list of linked attributes */ + /* Search to see if any linked attributes are in this entry */ return ldb_next_request(module, req); }