static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
				 struct lsa_CreateSecret *r)
{
	struct auth_session_info *session_info =
		dcesrv_call_session_info(dce_call);
	struct dcesrv_handle *policy_handle;
	struct lsa_policy_state *policy_state;
	struct lsa_secret_state *secret_state;
	struct dcesrv_handle *handle;
	struct ldb_message **msgs, *msg;
	const char *attrs[] = {
		NULL
	};

	const char *name;

	int ret;

	DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
	ZERO_STRUCTP(r->out.sec_handle);

	switch (security_session_user_level(session_info, NULL))
	{
	case SECURITY_SYSTEM:
	case SECURITY_ADMINISTRATOR:
		break;
	default:
		/* Users and annonymous are not allowed create secrets */
		return NT_STATUS_ACCESS_DENIED;
	}

	policy_state = policy_handle->data;

	if (!r->in.name.string) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	secret_state = talloc(mem_ctx, struct lsa_secret_state);
	NT_STATUS_HAVE_NO_MEMORY(secret_state);
	secret_state->policy = policy_state;

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

	if (strncmp("G$", r->in.name.string, 2) == 0) {
		const char *name2;

		secret_state->global = true;

		name = &r->in.name.string[2];
		if (strlen(name) == 0) {
			return NT_STATUS_INVALID_PARAMETER;
		}

		name2 = talloc_asprintf(mem_ctx, "%s Secret",
					ldb_binary_encode_string(mem_ctx, name));
		NT_STATUS_HAVE_NO_MEMORY(name2);

		/*
		 * We need to connect to the database as system, as this is
		 * one of the rare RPC calls that must read the secrets
		 * (and this is denied otherwise)
		 *
		 * We also save the current remote session details so they can
		 * used by the audit logging module. This allows the audit
		 * logging to report the remote users details, rather than the
		 * system users details.
		 */
		secret_state->sam_ldb =
			dcesrv_samdb_connect_as_system(secret_state, dce_call);
		NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);

		/* search for the secret record */
		ret = gendb_search(secret_state->sam_ldb,
				   mem_ctx, policy_state->system_dn, &msgs, attrs,
				   "(&(cn=%s)(objectclass=secret))",
				   name2);
		if (ret > 0) {
			return NT_STATUS_OBJECT_NAME_COLLISION;
		}

		if (ret < 0) {
			DEBUG(0,("Failure searching for CN=%s: %s\n",
				 name2, ldb_errstring(secret_state->sam_ldb)));
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
		NT_STATUS_HAVE_NO_MEMORY(msg->dn);
		if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
			return NT_STATUS_NO_MEMORY;
		}

		ret = ldb_msg_add_string(msg, "cn", name2);
		if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
	} else {
		secret_state->global = false;

		name = r->in.name.string;
		if (strlen(name) == 0) {
			return NT_STATUS_INVALID_PARAMETER;
		}

		secret_state->sam_ldb = secrets_db_connect(secret_state,
					dce_call->conn->dce_ctx->lp_ctx);
		NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);

		/* search for the secret record */
		ret = gendb_search(secret_state->sam_ldb, mem_ctx,
				   ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
				   &msgs, attrs,
				   "(&(cn=%s)(objectclass=secret))",
				   ldb_binary_encode_string(mem_ctx, name));
		if (ret > 0) {
			return NT_STATUS_OBJECT_NAME_COLLISION;
		}

		if (ret < 0) {
			DEBUG(0,("Failure searching for CN=%s: %s\n",
				 name, ldb_errstring(secret_state->sam_ldb)));
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
					 "cn=%s,cn=LSA Secrets", name);
		NT_STATUS_HAVE_NO_MEMORY(msg->dn);
		ret = ldb_msg_add_string(msg, "cn", name);
		if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
	}

	ret = ldb_msg_add_string(msg, "objectClass", "secret");
	if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;

	secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
	NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);

	/* create the secret */
	ret = ldb_add(secret_state->sam_ldb, msg);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to create secret record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(secret_state->sam_ldb)));
		return NT_STATUS_ACCESS_DENIED;
	}

	handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
	NT_STATUS_HAVE_NO_MEMORY(handle);

	handle->data = talloc_steal(handle, secret_state);

	secret_state->access_mask = r->in.access_mask;
	secret_state->policy = talloc_reference(secret_state, policy_state);
	NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);

	*r->out.sec_handle = handle->wire_handle;

	return NT_STATUS_OK;
}