static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
					   TALLOC_CTX *mem_ctx,
					   struct lsa_policy_state *state,
					   int ldb_flag,
					   struct dom_sid *sid,
					   const struct lsa_RightSet *rights)
{
	struct auth_session_info *session_info =
		dcesrv_call_session_info(dce_call);
	const char *sidstr, *sidndrstr;
	struct ldb_message *msg;
	struct ldb_message_element *el;
	int ret;
	uint32_t i;
	struct lsa_EnumAccountRights r2;
	char *dnstr;

	if (security_session_user_level(session_info, NULL) <
	    SECURITY_ADMINISTRATOR) {
		DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	msg = ldb_msg_new(mem_ctx);
	if (msg == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
	if (sidndrstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	sidstr = dom_sid_string(msg, sid);
	if (sidstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
	if (dnstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
	if (msg->dn == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
		NTSTATUS status;

		r2.in.handle = &state->handle->wire_handle;
		r2.in.sid = sid;
		r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);

		status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
		if (!NT_STATUS_IS_OK(status)) {
			ZERO_STRUCTP(r2.out.rights);
		}
	}

	for (i=0;i<rights->count;i++) {
		bool ok;

		ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
		if (!ok) {
			talloc_free(msg);
			return NT_STATUS_NO_SUCH_PRIVILEGE;
		}

		if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
			uint32_t j;
			for (j=0;j<r2.out.rights->count;j++) {
				if (strcasecmp_m(r2.out.rights->names[j].string,
					       rights->names[i].string) == 0) {
					break;
				}
			}
			if (j != r2.out.rights->count) continue;
		}

		ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
		if (ret != LDB_SUCCESS) {
			talloc_free(msg);
			return NT_STATUS_NO_MEMORY;
		}
	}

	el = ldb_msg_find_element(msg, "privilege");
	if (!el) {
		talloc_free(msg);
		return NT_STATUS_OK;
	}

	el->flags = ldb_flag;

	ret = ldb_modify(state->pdb, msg);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
			talloc_free(msg);
			return NT_STATUS_NO_MEMORY;
		}
		ldb_msg_add_string(msg, "comment", "added via LSA");
		ret = ldb_add(state->pdb, msg);
	}
	if (ret != LDB_SUCCESS) {
		if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
			talloc_free(msg);
			return NT_STATUS_OK;
		}
		DEBUG(3, ("Could not %s attributes from %s: %s",
			  LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
			  ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
		talloc_free(msg);
		return NT_STATUS_UNEXPECTED_IO_ERROR;
	}

	talloc_free(msg);
	return NT_STATUS_OK;
}
static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
					   TALLOC_CTX *mem_ctx,
					   struct lsa_policy_state *state,
					   int ldb_flag,
					   struct dom_sid *sid,
					   const struct lsa_RightSet *rights)
{
	struct auth_session_info *session_info =
		dcesrv_call_session_info(dce_call);
	const char *sidstr, *sidndrstr;
	struct ldb_message *msg;
	struct ldb_message_element *el;
	int ret;
	uint32_t i;
	struct lsa_EnumAccountRights r2;
	char *dnstr;

	if (security_session_user_level(session_info, NULL) <
	    SECURITY_ADMINISTRATOR) {
		DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	msg = ldb_msg_new(mem_ctx);
	if (msg == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
	if (sidndrstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	sidstr = dom_sid_string(msg, sid);
	if (sidstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
	if (dnstr == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
	if (msg->dn == NULL) {
		TALLOC_FREE(msg);
		return NT_STATUS_NO_MEMORY;
	}

	if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
		NTSTATUS status;

		r2.in.handle = &state->handle->wire_handle;
		r2.in.sid = sid;
		r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);

		status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
		if (!NT_STATUS_IS_OK(status)) {
			ZERO_STRUCTP(r2.out.rights);
		}
	}

	for (i=0;i<rights->count;i++) {
		bool ok;

		ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
		if (!ok) {
			talloc_free(msg);
			return NT_STATUS_NO_SUCH_PRIVILEGE;
		}

		if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
			uint32_t j;
			for (j=0;j<r2.out.rights->count;j++) {
				if (strcasecmp_m(r2.out.rights->names[j].string,
					       rights->names[i].string) == 0) {
					break;
				}
			}
			if (j != r2.out.rights->count) continue;
		}

		ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
		if (ret != LDB_SUCCESS) {
			talloc_free(msg);
			return NT_STATUS_NO_MEMORY;
		}
	}

	el = ldb_msg_find_element(msg, "privilege");
	if (!el) {
		talloc_free(msg);
		return NT_STATUS_OK;
	}

	el->flags = ldb_flag;

	ret = ldb_modify(state->pdb, msg);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
			talloc_free(msg);
			return NT_STATUS_NO_MEMORY;
		}
		ldb_msg_add_string(msg, "comment", "added via LSA");
		ret = ldb_add(state->pdb, msg);
	}
	if (ret != LDB_SUCCESS) {
		if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
			talloc_free(msg);
			return NT_STATUS_OK;
		}
		DEBUG(3, ("Could not %s attributes from %s: %s",
			  LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
			  ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
		talloc_free(msg);
		return NT_STATUS_UNEXPECTED_IO_ERROR;
	}

	talloc_free(msg);
	return NT_STATUS_OK;
}