const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element, struct ldb_request *parent) { const struct dsdb_class *last_class = NULL; unsigned int i; for (i = 0; i < element->num_values; i++){ const struct dsdb_class *tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &element->values[i]); if(tmp_class == NULL) { continue; } if(tmp_class->objectClassCategory > 1) { continue; } if (!last_class) { last_class = tmp_class; } else { if (tmp_class->subClass_order > last_class->subClass_order) last_class = tmp_class; } } return last_class; }
static int acl_childClasses(struct ldb_module *module, struct ldb_message *sd_msg, struct ldb_message *msg, const char *attrName) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; int i, j, ret; /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { return LDB_SUCCESS; } /* Must remove any existing attribute, or else confusion reins */ ldb_msg_remove_attr(msg, attrName); ret = ldb_msg_add_empty(msg, attrName, 0, &allowedClasses); if (ret != LDB_SUCCESS) { return ret; } oc_el = ldb_msg_find_element(sd_msg, "objectClass"); for (i=0; oc_el && i < oc_el->num_values; i++) { sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { /* We don't know this class? what is going on? */ continue; } for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { ldb_msg_add_string(msg, attrName, sclass->possibleInferiors[j]); } } if (allowedClasses->num_values > 1) { qsort(allowedClasses->values, allowedClasses->num_values, sizeof(*allowedClasses->values), (comparison_fn_t)data_blob_cmp); for (i=1 ; i < allowedClasses->num_values; i++) { struct ldb_val *val1 = &allowedClasses->values[i-1]; struct ldb_val *val2 = &allowedClasses->values[i]; if (data_blob_cmp(val1, val2) == 0) { memmove(val1, val2, (allowedClasses->num_values - i) * sizeof(struct ldb_val)); allowedClasses->num_values--; i--; } } } return LDB_SUCCESS; }
static int acl_childClassesEffective(struct ldb_module *module, struct ldb_message *sd_msg, struct ldb_message *msg, struct acl_context *ac) { struct ldb_message_element *oc_el; struct ldb_message_element *allowedClasses = NULL; struct ldb_context *ldb = ldb_module_get_ctx(module); const struct dsdb_schema *schema = dsdb_get_schema(ldb); const struct dsdb_class *sclass; struct security_descriptor *sd; struct dom_sid *sid = NULL; int i, j, ret; if (ac->user_type == SECURITY_SYSTEM) { return acl_childClasses(module, sd_msg, msg, "allowedChildClassesEffective"); } /* If we don't have a schema yet, we can't do anything... */ if (schema == NULL) { return LDB_SUCCESS; } /* Must remove any existing attribute, or else confusion reins */ ldb_msg_remove_attr(msg, "allowedChildClassesEffective"); oc_el = ldb_msg_find_element(sd_msg, "objectClass"); ret = get_sd_from_ldb_message(msg, sd_msg, &sd); if (ret != LDB_SUCCESS) { return ret; } ret = get_dom_sid_from_ldb_message(msg, sd_msg, &sid); if (ret != LDB_SUCCESS) { return ret; } for (i=0; oc_el && i < oc_el->num_values; i++) { sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]); if (!sclass) { /* We don't know this class? what is going on? */ continue; } for (j=0; sclass->possibleInferiors && sclass->possibleInferiors[j]; j++) { ret = acl_check_access_on_class(module, msg, sd, sid, SEC_ADS_CREATE_CHILD, sclass->possibleInferiors[j]); if (ret == LDB_SUCCESS) { ldb_msg_add_string(msg, "allowedChildClassesEffective", sclass->possibleInferiors[j]); } } } allowedClasses = ldb_msg_find_element(msg, "allowedChildClassesEffective"); if (!allowedClasses) { return LDB_SUCCESS; } if (allowedClasses->num_values > 1) { qsort(allowedClasses->values, allowedClasses->num_values, sizeof(*allowedClasses->values), (comparison_fn_t)data_blob_cmp); for (i=1 ; i < allowedClasses->num_values; i++) { struct ldb_val *val1 = &allowedClasses->values[i-1]; struct ldb_val *val2 = &allowedClasses->values[i]; if (data_blob_cmp(val1, val2) == 0) { memmove(val1, val2, (allowedClasses->num_values - i) * sizeof( struct ldb_val)); allowedClasses->num_values--; i--; } } } return LDB_SUCCESS; }