Esempio n. 1
0
static int check_access_on_dn(struct ldb_module *module,
			      TALLOC_CTX *mem_ctx,
			      struct ldb_dn *dn,
			      uint32_t access,
			      struct object_tree *tree)
{
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *acl_res;
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	NTSTATUS status;
	uint32_t access_granted;
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectSid",
		NULL
	};

	ret = ldb_search(ldb, mem_ctx, &acl_res, dn, LDB_SCOPE_BASE, acl_attrs, NULL);
	/* we sould be able to find the parent */
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl: failed to find object %s\n", ldb_dn_get_linearized(dn)));
		return ret;
	}

	ret = get_sd_from_ldb_message(mem_ctx, acl_res->msgs[0], &sd);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}
	ret = get_dom_sid_from_ldb_message(mem_ctx, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	status = sec_access_check_ds(sd, acl_user_token(module),
				     access,
				     &access_granted,
				     tree,
				     sid);
	if (!NT_STATUS_IS_OK(status)) {
		acl_debug(sd,
			  acl_user_token(module),
			  dn,
			  true,
			  10);
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	return LDB_SUCCESS;
}
Esempio n. 2
0
static int acl_check_access_on_attribute(struct ldb_module *module,
					 TALLOC_CTX *mem_ctx,
					 struct security_descriptor *sd,
					 struct dom_sid *rp_sid,
					 uint32_t access,
					 struct dsdb_attribute *attr)
{
	int ret;
	NTSTATUS status;
	uint32_t access_granted;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct security_token *token = acl_user_token(module);
	if (attr) {
		if (!GUID_all_zero(&attr->attributeSecurityGUID)) {
			if (!insert_in_object_tree(tmp_ctx,
						   &attr->attributeSecurityGUID, access,
						   &root, &new_node)) {
				DEBUG(10, ("acl_search: cannot add to object tree securityGUID\n"));
				goto fail;
			}

			if (!insert_in_object_tree(tmp_ctx,
						   &attr->schemaIDGUID, access, &new_node, &new_node)) {
				DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
				goto fail;
			}
		}
		else {
			if (!insert_in_object_tree(tmp_ctx,
						   &attr->schemaIDGUID, access, &root, &new_node)) {
				DEBUG(10, ("acl_search: cannot add to object tree attributeGUID\n"));
				goto fail;
			}
		}
	}
	status = sec_access_check_ds(sd, token,
				     access,
				     &access_granted,
				     root,
				     rp_sid);
	if (!NT_STATUS_IS_OK(status)) {
		ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	else {
		ret = LDB_SUCCESS;
	}
	return ret;
fail:
	return LDB_ERR_OPERATIONS_ERROR;
}
Esempio n. 3
0
static int acl_check_access_on_class(struct ldb_module *module,
				     TALLOC_CTX *mem_ctx,
				     struct security_descriptor *sd,
				     struct dom_sid *rp_sid,
				     uint32_t access,
				     const char *class_name)
{
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	NTSTATUS status;
	uint32_t access_granted;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	struct GUID *guid;
	const struct dsdb_schema *schema = dsdb_get_schema(ldb);
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct security_token *token = acl_user_token(module);
	if (class_name) {
		guid = class_schemaid_guid_by_lDAPDisplayName(schema, class_name);
		if (!guid) {
			DEBUG(10, ("acl_search: cannot find class %s\n",
				   class_name));
			goto fail;
		}
		if (!insert_in_object_tree(tmp_ctx,
					   guid, access,
					   &root, &new_node)) {
			DEBUG(10, ("acl_search: cannot add to object tree guid\n"));
			goto fail;
		}
	}
	status = sec_access_check_ds(sd, token,
				     access,
				     &access_granted,
				     root,
				     rp_sid);
	if (!NT_STATUS_IS_OK(status)) {
		ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	else {
		ret = LDB_SUCCESS;
	}
	return ret;
fail:
	return LDB_ERR_OPERATIONS_ERROR;
}
Esempio n. 4
0
int dsdb_check_access_on_dn_internal(struct ldb_context *ldb,
				     struct ldb_result *acl_res,
				     TALLOC_CTX *mem_ctx,
				     struct security_token *token,
				     struct ldb_dn *dn,
				     uint32_t access_mask,
				     const struct GUID *guid)
{
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	struct object_tree *root = NULL;
	NTSTATUS status;
	uint32_t access_granted;
	int ret;

	ret = dsdb_get_sd_from_ldb_message(ldb, mem_ctx, acl_res->msgs[0], &sd);
	if (ret != LDB_SUCCESS) {
		return ldb_operr(ldb);
	}

	sid = samdb_result_dom_sid(mem_ctx, acl_res->msgs[0], "objectSid");
	if (guid) {
		if (!insert_in_object_tree(mem_ctx, guid, access_mask, NULL,
					   &root)) {
			return ldb_operr(ldb);
		}
	}
	status = sec_access_check_ds(sd, token,
				     access_mask,
				     &access_granted,
				     root,
				     sid);
	if (!NT_STATUS_IS_OK(status)) {
		dsdb_acl_debug(sd,
			       token,
			       dn,
			       true,
			       10);
		ldb_asprintf_errstring(ldb,
				       "dsdb_access: Access check failed on %s",
				       ldb_dn_get_linearized(dn));
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	return LDB_SUCCESS;
}
Esempio n. 5
0
static int acl_rename(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_dn *oldparent = ldb_dn_get_parent(req, req->op.rename.olddn);
	struct ldb_dn *newparent = ldb_dn_get_parent(req, req->op.rename.newdn);
	struct ldb_context *ldb;
	struct security_descriptor *sd = NULL;
	struct dom_sid *sid = NULL;
	struct ldb_result *acl_res;
	const struct GUID *guid;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(req);
	NTSTATUS status;
	uint32_t access_granted;
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectClass",
		"objectSid",
		NULL
	};

	DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}
	if (ldb_dn_is_special(req->op.rename.olddn)) {
		return ldb_next_request(module, req);
	}
	ldb = ldb_module_get_ctx(module);

	/* TODO search to include deleted objects */
	ret = ldb_search(ldb, req, &acl_res, req->op.rename.olddn,
			 LDB_SCOPE_BASE, acl_attrs, NULL);
	/* we sould be able to find the parent */
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl: failed to find object %s\n",
			  ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}

	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	guid = attribute_schemaid_guid_by_lDAPDisplayName(dsdb_get_schema(ldb),
							  "name");
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &new_node, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	};

	ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);

	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}
	ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_ADS_WRITE_PROP,
				     &access_granted,
				     root,
				     sid);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Object %s nas no wp on name\n",
			   ldb_dn_get_linearized(req->op.rename.olddn)));
		acl_debug(sd,
			  acl_user_token(module),
			  req->op.rename.olddn,
			  true,
			  10);
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}

	if (ldb_dn_compare(oldparent, newparent) == 0) {
		/* regular rename, not move, nothing more to do */
		return ldb_next_request(module, req);
	}

	/* What exactly to do in this case? It would fail anyway.. */
	if ((ldb_dn_compare(req->op.rename.newdn, (ldb_get_schema_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_config_basedn(ldb))) == 0) ||
	    (ldb_dn_compare(req->op.rename.newdn, (ldb_get_root_basedn(ldb))) == 0)) {
		DEBUG(10,("acl:moving as an NC\n"));
		return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
	}
	/* new parent should have create child */
	talloc_free(tmp_ctx);
	tmp_ctx = talloc_new(req);
	root = NULL;
	new_node = NULL;
	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!guid) {
		DEBUG(10,("acl:renamed object has no object class\n"));
		return ldb_module_done(req, NULL, NULL,  LDB_ERR_OPERATIONS_ERROR);
	}
	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_CREATE_CHILD,
				   &root, &new_node)) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ret = check_access_on_dn(module, req, newparent, SEC_ADS_CREATE_CHILD, root);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ret;
	}
	/* do we have delete object on the object? */

	status = sec_access_check_ds(sd, acl_user_token(module),
				     SEC_STD_DELETE,
				     &access_granted,
				     NULL,
				     sid);

	if (NT_STATUS_IS_OK(status)) {
		return ldb_next_request(module, req);
	}
	/* what about delete child on the current parent */
	ret = check_access_on_dn(module, req, oldparent, SEC_ADS_DELETE_CHILD, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(10,("acl:access_denied renaming %s", ldb_dn_get_linearized(req->op.rename.olddn)));
		return ldb_module_done(req, NULL, NULL, ret);
	}
	return ldb_next_request(module, req);
}
Esempio n. 6
0
static int acl_modify(struct ldb_module *module, struct ldb_request *req)
{
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	const struct dsdb_schema *schema = dsdb_get_schema(ldb);
	int i;
	bool modify_sd = false;
	const struct GUID *guid;
	uint32_t access_granted;
	struct object_tree *root = NULL;
	struct object_tree *new_node = NULL;
	NTSTATUS status;
	struct ldb_result *acl_res;
	struct security_descriptor *sd;
	struct dom_sid *sid = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(req);
	static const char *acl_attrs[] = {
		"nTSecurityDescriptor",
		"objectClass",
		"objectSid",
		NULL
	};

	/* Don't print this debug statement if elements[0].name is going to be NULL */
	if(req->op.mod.message->num_elements > 0)
	{
		DEBUG(10, ("ldb:acl_modify: %s\n", req->op.mod.message->elements[0].name));
	}
	if (what_is_user(module) == SECURITY_SYSTEM) {
		return ldb_next_request(module, req);
	}
	if (ldb_dn_is_special(req->op.mod.message->dn)) {
		return ldb_next_request(module, req);
	}
	ret = ldb_search(ldb, req, &acl_res, req->op.mod.message->dn,
			 LDB_SCOPE_BASE, acl_attrs, NULL);

	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = get_sd_from_ldb_message(req, acl_res->msgs[0], &sd);
	if (ret != LDB_SUCCESS) {
		DEBUG(10, ("acl_modify: cannot get descriptor\n"));
		return ret;
	}
	/* Theoretically we pass the check if the object has no sd */
	if (!sd) {
		return LDB_SUCCESS;
	}

	guid = get_oc_guid_from_message(module,acl_res->msgs[0]);
	if (!guid) {
		DEBUG(10, ("acl_modify: cannot get guid\n"));
		goto fail;
	}

	ret = get_dom_sid_from_ldb_message(req, acl_res->msgs[0], &sid);
	if (ret != LDB_SUCCESS) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (!insert_in_object_tree(tmp_ctx, guid, SEC_ADS_WRITE_PROP,
				   &root, &new_node)) {
		DEBUG(10, ("acl_modify: cannot add to object tree\n"));
		goto fail;
	}
	for (i=0; i < req->op.mod.message->num_elements; i++){
		const struct dsdb_attribute *attr;
		/* clearTextPassword is not in schema */
		if (strcmp("clearTextPassword", req->op.mod.message->elements[i].name) == 0) {
			attr = dsdb_attribute_by_lDAPDisplayName(schema, "unicodePwd");
		} else {
			attr = dsdb_attribute_by_lDAPDisplayName(schema,
								 req->op.mod.message->elements[i].name);
		}
		if (strcmp("nTSecurityDescriptor", req->op.mod.message->elements[i].name) == 0) {
			modify_sd = true;
		} else {

			if (!attr) {
				DEBUG(10, ("acl_modify: cannot find attribute %s\n",
					   req->op.mod.message->elements[i].name));
				goto fail;
			}
			if (!insert_in_object_tree(tmp_ctx,
						   &attr->attributeSecurityGUID, SEC_ADS_WRITE_PROP,
						   &new_node, &new_node)) {
				DEBUG(10, ("acl_modify: cannot add to object tree securityGUID\n"));
				goto fail;
			}

			if (!insert_in_object_tree(tmp_ctx,
						   &attr->schemaIDGUID, SEC_ADS_WRITE_PROP, &new_node, &new_node)) {
				DEBUG(10, ("acl_modify: cannot add to object tree attributeGUID\n"));
				goto fail;
			}
		}
	}

	if (root->num_of_children > 0) {
		status = sec_access_check_ds(sd, acl_user_token(module),
					     SEC_ADS_WRITE_PROP,
					     &access_granted,
					     root,
					     sid);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(10, ("Object %s nas no write property access\n",
				   ldb_dn_get_linearized(req->op.mod.message->dn)));
			acl_debug(sd,
				  acl_user_token(module),
				  req->op.mod.message->dn,
				  true,
				  10);
			talloc_free(tmp_ctx);
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
	}
	if (modify_sd) {
		status = sec_access_check_ds(sd, acl_user_token(module),
					     SEC_STD_WRITE_DAC,
					     &access_granted,
					     NULL,
					     sid);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(10, ("Object %s nas no write dacl access\n",
				   ldb_dn_get_linearized(req->op.mod.message->dn)));
			acl_debug(sd,
				  acl_user_token(module),
				  req->op.mod.message->dn,
				  true,
				  10);
			talloc_free(tmp_ctx);
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
	}

	talloc_free(tmp_ctx);
	return ldb_next_request(module, req);
fail:
	talloc_free(tmp_ctx);
	return LDB_ERR_OPERATIONS_ERROR;
}