diff --git a/cib/callbacks.c b/cib/callbacks.c
index 7c89dc3b7a..13cd4b12e5 100644
--- a/cib/callbacks.c
+++ b/cib/callbacks.c
@@ -1,1342 +1,1366 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
+
+#if ENABLE_ACL
 #include <pwd.h>
+#endif
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/common/cluster.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <cibio.h>
 #include <callbacks.h>
 #include <cibmessages.h>
 #include <notify.h>
 #include "common.h"
 
 extern GMainLoop*  mainloop;
 extern gboolean cib_shutdown_flag;
 extern gboolean stand_alone;
 extern const char* cib_root;
 #if SUPPORT_HEARTBEAT
 extern ll_cluster_t *hb_conn;
 #endif
 
 extern void cib_ha_connection_destroy(gpointer user_data);
 
 extern enum cib_errors cib_update_counter(
 	xmlNode *xml_obj, const char *field, gboolean reset);
 
 extern void GHFunc_count_peers(
 	gpointer key, gpointer value, gpointer user_data);
 
 void initiate_exit(void);
 void terminate_cib(const char *caller);
 gint cib_GCompareFunc(gconstpointer a, gconstpointer b);
 gboolean can_write(int flags);
 void send_cib_replace(const xmlNode *sync_request, const char *host);
 void cib_process_request(
 	xmlNode *request, gboolean privileged, gboolean force_synchronous,
 	gboolean from_peer, cib_client_t *cib_client);
 void cib_common_callback_worker(xmlNode *op_request, cib_client_t *cib_client,
 				gboolean force_synchronous, gboolean privileged);
 
 extern GHashTable *client_list;
 
 int        next_client_id  = 0;
 extern const char *cib_our_uname;
 extern unsigned long cib_num_ops, cib_num_local, cib_num_updates, cib_num_fail;
 extern unsigned long cib_bad_connects, cib_num_timeouts;
 extern longclock_t cib_call_time;
 extern enum cib_errors cib_status;
 
 
 int send_via_callback_channel(xmlNode *msg, const char *token);
 
 enum cib_errors cib_process_command(
 	xmlNode *request, xmlNode **reply,
 	xmlNode **cib_diff, gboolean privileged);
 
 gboolean cib_common_callback(IPC_Channel *channel, cib_client_t *cib_client,
 			     gboolean force_synchronous, gboolean privileged);
 
 gboolean cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client);
 int num_clients = 0;
 
 static void
 cib_ipc_connection_destroy(gpointer user_data)
 {
 	cib_client_t *cib_client = user_data;
 	
 	/* cib_process_disconnect */
 
 	if(cib_client == NULL) {
 		crm_debug_4("Destroying %p", user_data);
 		return;
 	}
 
 	if(cib_client->source != NULL) {
 		crm_debug_4("Deleting %s (%p) from mainloop",
 			    cib_client->name, cib_client->source);
 		G_main_del_IPC_Channel(cib_client->source); 
 		cib_client->source = NULL;
 	}
 	
 	crm_debug_3("Destroying %s (%p)", cib_client->name, user_data);
 	num_clients--;
 	crm_debug_2("Num unfree'd clients: %d", num_clients);
 	crm_free(cib_client->name);
 	crm_free(cib_client->callback_id);
 	crm_free(cib_client->id);
 	crm_free(cib_client);
 	crm_debug_4("Freed the cib client");
 
 	return;
 }
 
 gboolean
 cib_client_connect(IPC_Channel *channel, gpointer user_data)
 {
 	cl_uuid_t client_id;
 	xmlNode *reg_msg = NULL;
 	cib_client_t *new_client = NULL;
 	char uuid_str[UU_UNPARSE_SIZEOF];
 	const char *channel_name = user_data;
 	gboolean (*callback)(IPC_Channel *channel, gpointer user_data);
 	
 	crm_debug_3("Connecting channel");
 
 	if (channel == NULL) {
 		crm_err("Channel was NULL");
 		cib_bad_connects++;
 		return FALSE;
 
 	} else if (channel->ch_status != IPC_CONNECT) {
 		crm_err("Channel was disconnected");
 		cib_bad_connects++;
 		return FALSE;
 		
 	} else if(channel_name == NULL) {
 		crm_err("user_data must contain channel name");
 		cib_bad_connects++;
 		return FALSE;
 		
 	} else if(cib_shutdown_flag) {
 		crm_info("Ignoring new client [%d] during shutdown",
 			channel->farside_pid);
 		return FALSE;		
 	}
 
 	callback = cib_ro_callback;
 	if(safe_str_eq(channel_name, cib_channel_rw)) {
 		callback = cib_rw_callback;
 	}
 	
 	crm_malloc0(new_client, sizeof(cib_client_t));
 	num_clients++;
 	new_client->channel = channel;
 	new_client->channel_name = channel_name;
 	
 	crm_debug_3("Created channel %p for channel %s",
 		    new_client, new_client->channel_name);
 	
 	channel->ops->set_recv_qlen(channel, 1024);
 	channel->ops->set_send_qlen(channel, 1024);
 	
 	new_client->source = G_main_add_IPC_Channel(
 	    G_PRIORITY_DEFAULT, channel, FALSE, callback,
 	    new_client, cib_ipc_connection_destroy);
 	
 	crm_debug_3("Channel %s connected for client %s",
 		    new_client->channel_name, new_client->id);
 	
 	cl_uuid_generate(&client_id);
 	cl_uuid_unparse(&client_id, uuid_str);
 
 	CRM_CHECK(new_client->id == NULL, crm_free(new_client->id));
 	new_client->id = crm_strdup(uuid_str);
 	
 	/* make sure we can find ourselves later for sync calls
 	 * redirected to the master instance
 	 */
 	g_hash_table_insert(client_list, new_client->id, new_client);
 	
 	reg_msg = create_xml_node(NULL, "callback");
 	crm_xml_add(reg_msg, F_CIB_OPERATION, CRM_OP_REGISTER);
 	crm_xml_add(reg_msg, F_CIB_CLIENTID,  new_client->id);
 	
 	send_ipc_message(channel, reg_msg);		
 	free_xml(reg_msg);
 	
 	return TRUE;
 }
 
 gboolean
 cib_rw_callback(IPC_Channel *channel, gpointer user_data)
 {
 	gboolean result = FALSE;
 	result = cib_common_callback(channel, user_data, FALSE, TRUE);
 	return result;
 }
 
 gboolean
 cib_ro_callback(IPC_Channel *channel, gpointer user_data)
 {
 	gboolean result = FALSE;
 	result = cib_common_callback(channel, user_data, FALSE, FALSE);
 	return result;
 }
 
 void
 cib_common_callback_worker(xmlNode *op_request, cib_client_t *cib_client,
 			   gboolean force_synchronous, gboolean privileged)
 {
 	longclock_t call_stop = 0;
 	longclock_t call_start = 0;
 	
 	const char *op = crm_element_value(op_request, F_CIB_OPERATION);
 
 	if(crm_str_eq(op, CRM_OP_REGISTER, TRUE)) {
 	    return;
 	    
 	} else if(crm_str_eq(op, T_CIB_NOTIFY, TRUE)) {
 	    /* Update the notify filters for this client */
 	    int on_off = 0;
 	    const char *type = crm_element_value(op_request, F_CIB_NOTIFY_TYPE);;
 	    crm_element_value_int(op_request, F_CIB_NOTIFY_ACTIVATE, &on_off);
 	    
 	    crm_debug("Setting %s callbacks for %s (%s): %s",
 		     type, cib_client->name, cib_client->id, on_off?"on":"off");
 	    
 	    if(safe_str_eq(type, T_CIB_POST_NOTIFY)) {
 		cib_client->post_notify = on_off;
 		
 	    } else if(safe_str_eq(type, T_CIB_PRE_NOTIFY)) {
 		cib_client->pre_notify = on_off;
 		
 	    } else if(safe_str_eq(type, T_CIB_UPDATE_CONFIRM)) {
 		cib_client->confirmations = on_off;
 		
 	    } else if(safe_str_eq(type, T_CIB_DIFF_NOTIFY)) {
 		cib_client->diffs = on_off;
 		
 	    } else if(safe_str_eq(type, T_CIB_REPLACE_NOTIFY)) {
 		cib_client->replace = on_off;
 	    }
 	    return;
 	}
 	
 	cib_client->num_calls++;
 	call_start = time_longclock();
 	cib_process_request(
 	    op_request, force_synchronous, privileged, FALSE, cib_client);
 
 	call_stop = time_longclock();
 	cib_call_time += (call_stop - call_start);
 }
 
 gboolean
 cib_common_callback(IPC_Channel *channel, cib_client_t *cib_client,
 		    gboolean force_synchronous, gboolean privileged)
 {
 	int lpc = 0;
 	const char *value = NULL;
 	xmlNode *op_request = NULL;
 	gboolean keep_channel = TRUE;
 
 	CRM_CHECK(cib_client != NULL, crm_err("Invalid client"); return FALSE);
 	CRM_CHECK(cib_client->id != NULL, crm_err("Invalid client: %p", cib_client); return FALSE);
 
 	/*
 	 * Do enough work to make entering worthwhile
 	 * But don't allow a single client to monopolize the CIB
 	 */
 	while(lpc < 5
 	      && IPC_ISRCONN(channel)
 	      && channel->ops->is_message_pending(channel)) {
 
 		lpc++;
 		op_request = xmlfromIPC(channel, MAX_IPC_DELAY);
 		if (op_request == NULL) {
 			break;
 		}
 
 		if(cib_client->name == NULL) {
 		    value = crm_element_value(op_request, F_CIB_CLIENTNAME);
 		    if(value == NULL) {
 			cib_client->name = crm_itoa(channel->farside_pid);
 		    } else {
 			cib_client->name = crm_strdup(value);
 		    }
 		}
 
+#if ENABLE_ACL
 		if(cib_client->user == NULL) {
 		    struct passwd *pwent = NULL;
 
 		    pwent = getpwuid(channel->farside_uid);
 		    if (pwent == NULL) {
 			crm_perror(LOG_ERR, "Cannot get password entry of uid: %d", channel->farside_uid);
 		    } else {
 			cib_client->user = crm_strdup(pwent->pw_name);
 		    }
 		}
+#endif
 
 		crm_xml_add(op_request, F_CIB_CLIENTID, cib_client->id);
 		crm_xml_add(op_request, F_CIB_CLIENTNAME, cib_client->name);
+#if ENABLE_ACL
 		crm_xml_add(op_request, F_CIB_USER, cib_client->user);
+#endif
 		/* crm_log_xml(LOG_MSG, "Client[inbound]", op_request); */
 
 		if(cib_client->callback_id == NULL) {
 		    value = crm_element_value(op_request, F_CIB_CALLBACK_TOKEN);
 		    if(value != NULL) {
 			cib_client->callback_id = crm_strdup(value);
 
 		    } else {
 			cib_client->callback_id = crm_strdup(cib_client->id);			
 		    }
 		}
 		
 		cib_common_callback_worker(
 			op_request, cib_client, force_synchronous, privileged);
 
 		free_xml(op_request);
 	}
 
 	if(channel->ch_status != IPC_CONNECT) {
 		crm_debug_2("Client disconnected");
 		keep_channel = cib_process_disconnect(channel, cib_client);	
 	}
 
 	return keep_channel;
 }
 
 static void
 do_local_notify(xmlNode *notify_src, const char *client_id,
 		gboolean sync_reply, gboolean from_peer) 
 {
 	/* send callback to originating child */
 	cib_client_t *client_obj = NULL;
 	enum cib_errors local_rc = cib_ok;
 
 	crm_debug_2("Performing notification");
 
 	if(client_id != NULL) {
 		client_obj = g_hash_table_lookup(client_list, client_id);
 	} else {
 		crm_debug_2("No client to sent the response to."
 			    "  F_CIB_CLIENTID not set.");
 	}
 	
 	crm_debug_3("Sending callback to request originator");
 	if(client_obj == NULL) {
 		local_rc = cib_reply_failed;
 		
 	} else {
 		const char *client_id = client_obj->callback_id;
 		crm_debug_2("Sending %ssync response to %s %s",
 			    sync_reply?"":"an a-",
 			    client_obj->name,
 			    from_peer?"(originator of delegated request)":"");
 		
 		if(sync_reply) {
 			client_id = client_obj->id;
 		}
 		local_rc = send_via_callback_channel(notify_src, client_id);
 	} 
 	
 	if(local_rc != cib_ok && client_obj != NULL) {
 		crm_warn("%sSync reply to %s failed: %s",
 			 sync_reply?"":"A-",
 			 client_obj?client_obj->name:"<unknown>", cib_error2string(local_rc));
 	}
 }
 
 static void
 parse_local_options(
 	cib_client_t *cib_client, int call_type, int call_options, const char *host, const char *op, 
 	gboolean *local_notify, gboolean *needs_reply, gboolean *process, gboolean *needs_forward) 
 {
 	if(cib_op_modifies(call_type)
 	   && !(call_options & cib_inhibit_bcast)) {
 		/* we need to send an update anyway */
 		*needs_reply = TRUE;
 	} else {
 		*needs_reply = FALSE;
 	}
 	
 	if(host == NULL && (call_options & cib_scope_local)) {
 		crm_debug_2("Processing locally scoped %s op from %s",
 			    op, cib_client->name);
 		*local_notify = TRUE;
 		
 	} else if(host == NULL && cib_is_master) {
 		crm_debug_2("Processing master %s op locally from %s",
 			    op, cib_client->name);
 		*local_notify = TRUE;
 		
 	} else if(safe_str_eq(host, cib_our_uname)) {
 		crm_debug_2("Processing locally addressed %s op from %s",
 			    op, cib_client->name);
 		*local_notify = TRUE;
 
 	} else if(stand_alone) {
 		*needs_forward = FALSE;
 		*local_notify = TRUE;
 		*process = TRUE;
 		
 	} else {
 		crm_debug_2("%s op from %s needs to be forwarded to %s",
 			    op, cib_client->name,
 			    host?host:"the master instance");
 		*needs_forward = TRUE;
 		*process = FALSE;
 	}		
 }
 
 static gboolean
 parse_peer_options(
 	int call_type, xmlNode *request, 
 	gboolean *local_notify, gboolean *needs_reply, gboolean *process, gboolean *needs_forward) 
 {
 	const char *op         = crm_element_value(request, F_CIB_OPERATION);
 	const char *originator = crm_element_value(request, F_ORIG);
 	const char *host       = crm_element_value(request, F_CIB_HOST);
 	const char *reply_to   = crm_element_value(request, F_CIB_ISREPLY);
 	const char *update     = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
 	const char *delegated  = crm_element_value(request, F_CIB_DELEGATED);
 
 	if(safe_str_eq(op, "cib_shutdown_req")) {
 		if(reply_to != NULL) {
 			crm_debug("Processing %s from %s", op, host);
 			*needs_reply = FALSE;
 			
 		} else {
 			crm_debug("Processing %s reply from %s", op, host);
 		}
 		return TRUE;
 		
 	} else if(crm_is_true(update) && safe_str_eq(reply_to, cib_our_uname)) {
 		crm_debug_2("Processing global/peer update from %s"
 			    " that originated from us", originator);
 		*needs_reply = FALSE;
 		if(crm_element_value(request, F_CIB_CLIENTID) != NULL) {
 			*local_notify = TRUE;
 		}
 		return TRUE;
 		
 	} else if(crm_is_true(update)) {
 		crm_debug_2("Processing global/peer update from %s", originator);
 		*needs_reply = FALSE;
 		return TRUE;
 
 	} else if(host != NULL && safe_str_eq(host, cib_our_uname)) {
 		crm_debug_2("Processing request sent to us from %s", originator);
 		return TRUE;
 
 	} else if(delegated != NULL && cib_is_master == TRUE) {
 		crm_debug_2("Processing request sent to master instance from %s",
 			originator);
 		return TRUE;
 
 	} else if(reply_to != NULL && safe_str_eq(reply_to, cib_our_uname)) {
 		crm_debug_2("Forward reply sent from %s to local clients",
 			  originator);
 		*process = FALSE;
 		*needs_reply = FALSE;
 		*local_notify = TRUE;
 		return TRUE;
 
 	} else if(delegated != NULL) {
 		crm_debug_2("Ignoring msg for master instance");
 
 	} else if(host != NULL) {
 		/* this is for a specific instance and we're not it */
 		crm_debug_2("Ignoring msg for instance on %s", crm_str(host));
 		
 	} else if(reply_to == NULL && cib_is_master == FALSE) {
 		/* this is for the master instance and we're not it */
 		crm_debug_2("Ignoring reply to %s", crm_str(reply_to));
 		
 	} else {
 		crm_err("Nothing for us to do?");
 		crm_log_xml(LOG_ERR, "Peer[inbound]", request);
 	}
 
 	return FALSE;
 }
 
 		
 static void
 forward_request(xmlNode *request, cib_client_t *cib_client, int call_options)
 {
 	xmlNode *forward_msg = NULL;
 	const char *op         = crm_element_value(request, F_CIB_OPERATION);
 	const char *host       = crm_element_value(request, F_CIB_HOST);
 
 	forward_msg = cib_msg_copy(request, TRUE);
 	crm_xml_add(forward_msg, F_CIB_DELEGATED, cib_our_uname);
 	
 	if(host != NULL) {
 		crm_debug_2("Forwarding %s op to %s", op, host);
 		send_cluster_message(host, crm_msg_cib, forward_msg, FALSE);
 		
 	} else {
 		crm_debug_2("Forwarding %s op to master instance", op);
 		send_cluster_message(NULL, crm_msg_cib, forward_msg, FALSE);
 	}
 	
 	if(call_options & cib_discard_reply) {
 		crm_debug_2("Client not interested in reply");
 	} 
 	free_xml(forward_msg);
 }
 
 static void
 send_peer_reply(
 	xmlNode *msg, xmlNode *result_diff, const char *originator, gboolean broadcast)
 {
 	xmlNode *reply_copy = NULL;
 
 	CRM_ASSERT(msg != NULL);
 
  	reply_copy = cib_msg_copy(msg, TRUE);
 	
 	if(broadcast) {
 		/* this (successful) call modified the CIB _and_ the
 		 * change needs to be broadcast...
 		 *   send via HA to other nodes
 		 */
 		int diff_add_updates = 0;
 		int diff_add_epoch   = 0;
 		int diff_add_admin_epoch = 0;
 		
 		int diff_del_updates = 0;
 		int diff_del_epoch   = 0;
 		int diff_del_admin_epoch = 0;
 
 		char *digest = NULL;
 		
 		cib_diff_version_details(
 			result_diff,
 			&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, 
 			&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);
 
 		crm_debug_2("Sending update diff %d.%d.%d -> %d.%d.%d",
 			    diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
 			    diff_add_admin_epoch,diff_add_epoch,diff_add_updates);
 
 		crm_xml_add(reply_copy, F_CIB_ISREPLY, originator);
 		crm_xml_add(reply_copy, F_CIB_GLOBAL_UPDATE, XML_BOOLEAN_TRUE);
 		crm_xml_add(reply_copy, F_CIB_OPERATION, CIB_OP_APPLY_DIFF);
 
 		digest = calculate_xml_digest(the_cib, FALSE, TRUE);
 		crm_xml_add(result_diff, XML_ATTR_DIGEST, digest);
 /* 		crm_log_xml_debug(the_cib, digest); */
 		crm_free(digest);
 		
  		add_message_xml(reply_copy, F_CIB_UPDATE_DIFF, result_diff);
 		crm_log_xml(LOG_DEBUG_3, "copy", reply_copy);
 		send_cluster_message(NULL, crm_msg_cib, reply_copy, TRUE);
 		
 	} else if(originator != NULL) {
 		/* send reply via HA to originating node */
 		crm_debug_2("Sending request result to originator only");
 		crm_xml_add(reply_copy, F_CIB_ISREPLY, originator);
 		send_cluster_message(originator, crm_msg_cib, reply_copy, FALSE);
 	}
 	
 	free_xml(reply_copy);
 }
 	
 void
 cib_process_request(
 	xmlNode *request, gboolean force_synchronous, gboolean privileged,
 	gboolean from_peer, cib_client_t *cib_client) 
 {
 	int call_type    = 0;
 	int call_options = 0;
 
 	gboolean process = TRUE;		
 	gboolean is_update = TRUE;
 	gboolean needs_reply = TRUE;
 	gboolean local_notify = FALSE;
 	gboolean needs_forward = FALSE;
 	gboolean global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));
 	
 	xmlNode *op_reply = NULL;
 	xmlNode *result_diff = NULL;
 
 	enum cib_errors rc = cib_ok;
 	const char *op         = crm_element_value(request, F_CIB_OPERATION);
 	const char *originator = crm_element_value(request, F_ORIG);
 	const char *host       = crm_element_value(request, F_CIB_HOST);
 
 	crm_debug_4("%s Processing msg %s",
 		  cib_our_uname, crm_element_value(request, F_SEQ));
 
 	cib_num_ops++;
 	if(cib_num_ops == 0) {
 		cib_num_fail = 0;
 		cib_num_local = 0;
 		cib_num_updates = 0;
 		crm_info("Stats wrapped around");
 	}
 	
 	if(host != NULL && strlen(host) == 0) {
 		host = NULL;
 	}	
 
 	crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
 	if(force_synchronous) {
 		call_options |= cib_sync_call;
 	}
 	
 	crm_debug_2("Processing %s message (%s) for %s...",
 		    from_peer?"peer":"local",
 		    from_peer?originator:cib_our_uname, host?host:"master");
 
 	rc = cib_get_operation_id(op, &call_type);
 	if(rc != cib_ok) {
 		/* TODO: construct error reply? */
 		crm_err("Pre-processing of command failed: %s", cib_error2string(rc));
 		return;
 	}
 	
 	is_update = cib_op_modifies(call_type);
 	if(is_update) {
 		cib_num_updates++;
 	}
 	
 	if(from_peer == FALSE) {
 		parse_local_options(cib_client, call_type, call_options, host, op,
 				    &local_notify, &needs_reply, &process, &needs_forward);
 		
 	} else if(parse_peer_options(call_type, request, &local_notify,
 				     &needs_reply, &process, &needs_forward) == FALSE) {
 		return;
 	}
 	crm_debug_3("Finished determining processing actions");
 
 	if(call_options & cib_discard_reply) {
 		needs_reply = is_update;
 		local_notify = FALSE;
 	}
 	
 	if(needs_forward) {
 		forward_request(request, cib_client, call_options);
 		return;
 	}
 
 	if(cib_status != cib_ok) {
 	    rc = cib_status;
 	    crm_err("Operation ignored, cluster configuration is invalid."
 		    " Please repair and restart: %s",
 		    cib_error2string(cib_status));
 	    op_reply = cib_construct_reply(request, the_cib, cib_status);
 
 	} else if(process) {
 		int level = LOG_INFO;
 		const char *section = crm_element_value(request, F_CIB_SECTION);
 		
 		cib_num_local++;
 		rc = cib_process_command(
 			request, &op_reply, &result_diff, privileged);
 
 		if(global_update) {
 		    switch(rc) {
 			case cib_ok:
 			case cib_old_data:
 			case cib_diff_resync:
 			case cib_diff_failed:
 			    level = LOG_DEBUG_2;
 			    break;
 			default:
 			    level = LOG_ERR;
 		    }
 
 		} else if(safe_str_eq(op, CIB_OP_QUERY)) {
 		    level = LOG_DEBUG_2;
 
 		} else if(rc != cib_ok) {
 		    cib_num_fail++;
 		    level = LOG_WARNING;
 
 		} else if(safe_str_eq(op, CIB_OP_SLAVE)) {
 		    level = LOG_DEBUG_2;
 
 		} else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) {
 		    level = LOG_DEBUG_2;
 		}
 		
 		if(crm_log_level >= level) {
 		    /* Avoid all the xml lookups if we're not going to print the results */
 		    do_crm_log(level, "Operation complete: op %s for section %s (origin=%s/%s/%s, version=%s.%s.%s): %s (rc=%d)",
 			       op, section?section:"'all'", originator?originator:"local",
 			       crm_element_value(request, F_CIB_CLIENTNAME),
 			       crm_element_value(request, F_CIB_CALLID),
 			       the_cib?crm_element_value(the_cib, XML_ATTR_GENERATION_ADMIN):"0",
 			       the_cib?crm_element_value(the_cib, XML_ATTR_GENERATION):"0",
 			       the_cib?crm_element_value(the_cib, XML_ATTR_NUMUPDATES):"0",
 			       cib_error2string(rc), rc);
 		}
 		
 		if(op_reply == NULL && (needs_reply || local_notify)) {
 			crm_err("Unexpected NULL reply to message");
 			crm_log_xml(LOG_ERR, "null reply", request);
 			needs_reply = FALSE;
 			local_notify = FALSE;
 		}		
 	}
 	crm_debug_3("processing response cases");
 	
 	if(local_notify) {
 		const char *client_id = crm_element_value(request, F_CIB_CLIENTID);
 		if(process == FALSE) {
 			do_local_notify(request, client_id, call_options & cib_sync_call, from_peer);
 		} else {
 			do_local_notify(op_reply, client_id, call_options & cib_sync_call, from_peer);
 		}
 	}
 
 	/* from now on we are the server */ 
 	if(needs_reply == FALSE || stand_alone) {
 		/* nothing more to do...
 		 * this was a non-originating slave update
 		 */
 		crm_debug_2("Completed slave update");
 
 	} else if(rc == cib_ok
 		  && result_diff != NULL
 		  && !(call_options & cib_inhibit_bcast)) {
 		send_peer_reply(request, result_diff, originator, TRUE);
 		
 	} else if(call_options & cib_discard_reply) {
 		crm_debug_4("Caller isn't interested in reply");
 		
 	} else if (from_peer) {		
 		if(is_update == FALSE || result_diff == NULL) {
 			crm_debug_3("Request not broadcast: R/O call");
 
 		} else if(call_options & cib_inhibit_bcast) {
 			crm_debug_3("Request not broadcast: inhibited");
 
 		} else if(rc != cib_ok) {
 			crm_debug_3("Request not broadcast: call failed: %s",
 				    cib_error2string(rc));
 		} else {
 		    crm_debug_2("Directing reply to %s", originator);
 		}
 
 		send_peer_reply(op_reply, result_diff, originator, FALSE);
 	}
 	
 	free_xml(op_reply);
 	free_xml(result_diff);
 
 	return;	
 }
 
 xmlNode *
 cib_construct_reply(xmlNode *request, xmlNode *output, int rc) 
 {
 	int lpc = 0;
 	xmlNode *reply = NULL;
 	
 	const char *name = NULL;
 	const char *value = NULL;
 	const char *names[] = {
 		F_CIB_OPERATION,
 		F_CIB_CALLID,
 		F_CIB_CLIENTID,
 		F_CIB_CALLOPTS
 	};
 
 	crm_debug_4("Creating a basic reply");
 	reply = create_xml_node(NULL, "cib-reply");
 	crm_xml_add(reply, F_TYPE, T_CIB);
 
 	for(lpc = 0; lpc < DIMOF(names); lpc++) {
 		name = names[lpc];
 		value = crm_element_value(request, name);
 		crm_xml_add(reply, name, value);
 	}
 
 	crm_xml_add_int(reply, F_CIB_RC, rc);
 
 	if(output != NULL) {
 		crm_debug_4("Attaching reply output");
 		add_message_xml(reply, F_CIB_CALLDATA, output);
 	}
 	return reply;
 }
 
 enum cib_errors
 cib_process_command(xmlNode *request, xmlNode **reply,
 		    xmlNode **cib_diff, gboolean privileged)
 {
     xmlNode *input       = NULL;
     xmlNode *output      = NULL;
     xmlNode *result_cib  = NULL;
     xmlNode *current_cib = NULL;
+#if ENABLE_ACL
     xmlNode *filtered_current_cib = NULL;
+#endif
 	
     int call_type    = 0;
     int call_options = 0;
     int log_level    = LOG_DEBUG_4;
 
     const char *op = NULL;
     const char *section = NULL;
 
     enum cib_errors rc = cib_ok;
     enum cib_errors rc2 = cib_ok;
 	
     gboolean send_r_notify = FALSE;
     gboolean global_update = FALSE;
     gboolean config_changed = FALSE;
     gboolean manage_counters = TRUE;
 	
     CRM_ASSERT(cib_status == cib_ok);
 
     *reply = NULL;
     *cib_diff = NULL;
     current_cib = the_cib;
 	
     /* Start processing the request... */
     op = crm_element_value(request, F_CIB_OPERATION);
     crm_element_value_int(request, F_CIB_CALLOPTS, &call_options);
     rc = cib_get_operation_id(op, &call_type);
 	
     if(rc == cib_ok) {
 	rc = cib_op_can_run(call_type, call_options, privileged, global_update);
     }
 	
     rc2 = cib_op_prepare(call_type, request, &input, &section);
     if(rc == cib_ok) {
 	rc = rc2;
     }
 	
     if(rc != cib_ok) {
 	crm_debug_2("Call setup failed: %s", cib_error2string(rc));
 	goto done;
 		
     } else if(cib_op_modifies(call_type) == FALSE) {
+#if ENABLE_ACL
 	if (acl_filter_cib(request, current_cib, current_cib, &filtered_current_cib) == FALSE) {
+#endif
 	    rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
 			    section, request, input, FALSE, &config_changed,
 			    current_cib, &result_cib, NULL, &output);
+#if ENABLE_ACL
 	} else {
 	    crm_debug("Pre-filtered the queried cib according to the ACLs");
 	    if (filtered_current_cib == NULL) {
 		rc = cib_permission_denied;
 	    } else {
 		rc = cib_perform_op(op, call_options, cib_op_func(call_type), TRUE,
 				section, request, input, FALSE, &config_changed,
 				filtered_current_cib, &result_cib, NULL, &output);
 	    }
 	}
+#endif
 
 	CRM_CHECK(result_cib == NULL, free_xml(result_cib));
 	goto done;
     }	
 
     /* Handle a valid write action */
     global_update = crm_is_true(crm_element_value(request, F_CIB_GLOBAL_UPDATE));
     if(global_update) {
 	manage_counters = FALSE;
 	call_options |= cib_force_diff;		
 
 	CRM_CHECK(call_type == 3 || call_type == 4,
 		  crm_err("Call type: %d", call_type);
 		  crm_log_xml(LOG_ERR, "bad op", request));
     }
 #ifdef SUPPORT_PRENOTIFY
     if((call_options & cib_inhibit_notify) == 0) {
 	cib_pre_notify(call_options, op, the_cib, input);
     }
 #endif
     
     if(rc == cib_ok) {
 	if(call_options & cib_inhibit_bcast) {
 	    /* skip */
 	    crm_debug_2("Skipping update: inhibit broadcast");
 	    manage_counters = FALSE;
 	}	
 	    
 	rc = cib_perform_op(op, call_options, cib_op_func(call_type), FALSE,
 			    section, request, input, manage_counters, &config_changed,
 			    current_cib, &result_cib, cib_diff, &output);
 
 	if(manage_counters == FALSE) {
 	    config_changed = cib_config_changed(current_cib, result_cib, cib_diff);
 	}
 
+#if ENABLE_ACL
 	if (acl_check_diff(request, current_cib, result_cib, *cib_diff) == FALSE) {
 	    rc = cib_permission_denied;
 	}
+#endif
     }    
     
     if(rc == cib_ok) {
 	rc = activateCibXml(result_cib, config_changed, op);
 	
 	if(crm_str_eq(CIB_OP_REPLACE, op, TRUE)) {
 	    if(section == NULL) {
 		send_r_notify = TRUE;
 		
 	    } else if(safe_str_eq(section, XML_TAG_CIB)) {
 		send_r_notify = TRUE;
 		
 	    } else if(safe_str_eq(section, XML_CIB_TAG_NODES)) {
 		send_r_notify = TRUE;
 		
 	    } else if(safe_str_eq(section, XML_CIB_TAG_STATUS)) {
 		send_r_notify = TRUE;
 	    }
 
 	} else if(crm_str_eq(CIB_OP_ERASE, op, TRUE)) {
 	    send_r_notify = TRUE;
 	}
 
     } else if(rc == cib_dtd_validation) {
+#if ENABLE_ACL
 	xmlNode *filtered_result_cib = NULL;
+#endif
 
 	if(output != NULL) {
 	    crm_log_xml_info(output, "cib:output");
 	    free_xml(output);
 	} 
 
+#if ENABLE_ACL
 	if (acl_filter_cib(request, current_cib, result_cib, &filtered_result_cib) == FALSE) {
+#endif
 	    output = result_cib;
+
+#if ENABLE_ACL
 	} else {
 	    crm_debug("Filtered the result cib for output according to the ACLs");
 	    output = filtered_result_cib;
 	    if (result_cib != NULL) {
 		free_xml(result_cib);
 	    }
 	}
+#endif
 
     } else {
 	free_xml(result_cib);    
     }
     
     if((call_options & cib_inhibit_notify) == 0) {
 	const char *call_id = crm_element_value(request, F_CIB_CALLID);
 	const char *client = crm_element_value(request, F_CIB_CLIENTNAME);
 
 #ifdef SUPPORT_POSTNOTIFY
 	cib_post_notify(call_options, op, input, rc, the_cib);
 #endif
 	cib_diff_notify(call_options, client, call_id, op, input, rc, *cib_diff);
     }
 
     if(send_r_notify) {
 	const char *origin = crm_element_value(request, F_ORIG);
 	cib_replace_notify(origin, the_cib, rc, *cib_diff);
     }	
     
     if(rc != cib_ok) {
 	log_level = LOG_DEBUG_4;
 	if(rc == cib_dtd_validation && global_update) {
 	    log_level = LOG_WARNING;
 	    crm_log_xml_info(input, "cib:global_update");
 	}
 	
     } else if(config_changed) {
 	log_level = LOG_DEBUG_3;
 	if(cib_is_master) {
 	    log_level = LOG_INFO;
 	}
 	
     } else if(cib_is_master) {
 	log_level = LOG_DEBUG_2;
     }
 	
     log_xml_diff(log_level, *cib_diff, "cib:diff");
 
   done:
     if((call_options & cib_discard_reply) == 0) {
 	*reply = cib_construct_reply(request, output, rc);
 	/* crm_log_xml_info(*reply, "cib:reply"); */
     }
 
+#if ENABLE_ACL
     if (filtered_current_cib != NULL) {
 	free_xml(filtered_current_cib);
     }
+#endif
 
     if(call_type >= 0) {
 	cib_op_cleanup(call_type, call_options, &input, &output);
     }
     return rc;
 }
 
 int
 send_via_callback_channel(xmlNode *msg, const char *token) 
 {
 	cib_client_t *hash_client = NULL;
 	enum cib_errors rc = cib_ok;
 	
 	crm_debug_3("Delivering msg %p to client %s", msg, token);
 
 	if(token == NULL) {
 		crm_err("No client id token, cant send message");
 		if(rc == cib_ok) {
 			rc = cib_missing;
 		}
 
 	} else if(msg == NULL) {
 		crm_err("No message to send");
 		rc = cib_reply_failed;
 	    
 	} else {
 		/* A client that left before we could reply is not really
 		 * _our_ error.  Warn instead.
 		 */
 		hash_client = g_hash_table_lookup(client_list, token);
 		if(hash_client == NULL) {
 			crm_warn("Cannot find client for token %s", token);
 			rc = cib_client_gone;
 			
 		} else if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) {
 		    /* just hope it's alive */
 		    
 		} else if(hash_client->channel == NULL) {
 			crm_err("Cannot find channel for client %s", token);
 			rc = cib_client_corrupt;
 		}
 	}
 
 	if(rc == cib_ok) {
 	    crm_debug_3("Delivering reply to client %s (%s)",
 			token, hash_client->channel_name);
 	    if (crm_str_eq(hash_client->channel_name, "remote", FALSE)) {
 		cib_send_remote_msg(hash_client->channel, msg, hash_client->encrypted);
 		
 	    } else if(send_ipc_message(hash_client->channel, msg) == FALSE) {
 		crm_warn("Delivery of reply to client %s/%s failed",
 			 hash_client->name, token);
 		rc = cib_reply_failed;
 	    }
 	}
 	
 	return rc;
 }
 
 gint cib_GCompareFunc(gconstpointer a, gconstpointer b)
 {
 	const xmlNode *a_msg = a;
 	const xmlNode *b_msg = b;
 
 	int msg_a_id = 0;
 	int msg_b_id = 0;
 	const char *value = NULL;
 	
 	value = crm_element_value_const(a_msg, F_CIB_CALLID);
 	msg_a_id = crm_parse_int(value, NULL);
 
 	value = crm_element_value_const(b_msg, F_CIB_CALLID);
 	msg_b_id = crm_parse_int(value, NULL);
 	
 	if(msg_a_id == msg_b_id) {
 		return 0;
 	} else if(msg_a_id < msg_b_id) {
 		return -1;
 	}
 	return 1;
 }
 
 gboolean
 cib_process_disconnect(IPC_Channel *channel, cib_client_t *cib_client)
 {
 	if (channel == NULL) {
 		CRM_DEV_ASSERT(cib_client == NULL);
 		
 	} else if (cib_client == NULL) {
 		crm_err("No client");
 		
 	} else {
 		CRM_DEV_ASSERT(channel->ch_status != IPC_CONNECT);
 		crm_debug_2("Cleaning up after client disconnect: %s/%s/%s",
 			    crm_str(cib_client->name),
 			    cib_client->channel_name,
 			    cib_client->id);
 		
 		if(cib_client->id != NULL) {
 			if(!g_hash_table_remove(client_list, cib_client->id)) {
 				crm_err("Client %s not found in the hashtable",
 					cib_client->name);
 			}
 		}		
 	}
 
 	if(cib_shutdown_flag && g_hash_table_size(client_list) == 0) {
 		crm_info("All clients disconnected...");
 		initiate_exit();
 	}
 	
 	return FALSE;
 }
 
 void
 cib_ha_peer_callback(HA_Message * msg, void* private_data)
 {
     xmlNode *xml = convert_ha_message(NULL, msg, __FUNCTION__);
     cib_peer_callback(xml, private_data);
     free_xml(xml);
 }
 
 void
 cib_peer_callback(xmlNode * msg, void* private_data)
 {
     crm_node_t *node = NULL;
     const char *reason = NULL;
     const char *originator = crm_element_value(msg, F_ORIG);
     
     if(originator == NULL || crm_str_eq(originator, cib_our_uname, TRUE)) {
 	/* message is from ourselves */
 	return;
 	
     } else if(crm_peer_cache == NULL) {
 	reason = "membership not established";
 	goto bail;
     }
 
     node = crm_get_peer(0, originator);
     if(node == NULL || (node->processes & crm_proc_cib) == 0) {
 	reason = "not in our membership";
 	goto bail;
     }
     
     if(crm_element_value(msg, F_CIB_CLIENTNAME) == NULL) {
 	crm_xml_add(msg, F_CIB_CLIENTNAME, originator);
     }
     
     /* crm_log_xml(LOG_MSG, "Peer[inbound]", msg); */
     cib_process_request(msg, FALSE, TRUE, TRUE, NULL);
     return;
     
   bail:
     if(reason) {
 	const char *seq = crm_element_value(msg, F_SEQ);
 	const char *op  = crm_element_value(msg, F_CIB_OPERATION);
 	crm_warn("Discarding %s message (%s) from %s: %s", op, seq, originator, reason);
     }
 }
 
 void
 cib_client_status_callback(const char * node, const char * client,
 			   const char * status, void * private)
 {
     crm_node_t *member = NULL;
     if(safe_str_eq(client, CRM_SYSTEM_CIB)) {
 	crm_info("Status update: Client %s/%s now has status [%s]",
 		 node, client, status);
 	
 	if(safe_str_eq(status, JOINSTATUS)){
 		    status = ONLINESTATUS;
 		    
 	} else if(safe_str_eq(status, LEAVESTATUS)){
 	    status = OFFLINESTATUS;
 	}
 
 	member = crm_get_peer(0, node);
 	if(member == NULL) {
 	    /* Make sure it gets created */
 	    const char *uuid = get_uuid(node);
 	    member = crm_update_peer(0, 0, 0, -1, 0, uuid, node, NULL, NULL);
 	}
 	
 	crm_update_peer_proc(node, crm_proc_cib, status);
     }
     return;
 }
 
 #if SUPPORT_HEARTBEAT
 extern oc_ev_t *cib_ev_token;
 
 gboolean cib_ccm_dispatch(int fd, gpointer user_data)
 {
 	int rc = 0;
 	oc_ev_t *ccm_token = (oc_ev_t*)user_data;
 	crm_debug_2("received callback");	
 	rc = oc_ev_handle_event(ccm_token);
 	if(0 == rc) {
 		return TRUE;
 
 	}
 
 	crm_err("CCM connection appears to have failed: rc=%d.", rc);
 
 	/* eventually it might be nice to recover and reconnect... but until then... */
 	crm_err("Exiting to recover from CCM connection failure");
 	exit(2);
 	
 	return FALSE;
 }
 
 int current_instance = 0;
 void 
 cib_ccm_msg_callback(
 	oc_ed_t event, void *cookie, size_t size, const void *data)
 {
 	gboolean update_id = FALSE;
 	const oc_ev_membership_t *membership = data;
 
 	CRM_ASSERT(membership != NULL);
 
 	crm_info("Processing CCM event=%s (id=%d)",
 		 ccm_event_name(event), membership->m_instance);
 
 	if(current_instance > membership->m_instance) {
 		crm_err("Membership instance ID went backwards! %d->%d",
 			current_instance, membership->m_instance);
 		CRM_ASSERT(current_instance <= membership->m_instance);
 	}
 	
 	switch(event) {
 		case OC_EV_MS_NEW_MEMBERSHIP:
 		case OC_EV_MS_INVALID:
 			update_id = TRUE;
 			break;
 		case OC_EV_MS_PRIMARY_RESTORED:
 			update_id = TRUE;
 			break;
 		case OC_EV_MS_NOT_PRIMARY:
 			crm_debug_2("Ignoring transitional CCM event: %s",
 				    ccm_event_name(event));
 			break;
 		case OC_EV_MS_EVICTED:
 			crm_err("Evicted from CCM: %s", ccm_event_name(event));
 			break;
 		default:
 			crm_err("Unknown CCM event: %d", event);
 	}
 	
 	if(update_id) {
 		unsigned int lpc = 0;
 		CRM_CHECK(membership != NULL, return);
 	
 		current_instance = membership->m_instance;
 
 		for(lpc=0; lpc < membership->m_n_out; lpc++) {
 		    crm_update_ccm_node(
 			membership, lpc+membership->m_out_idx, CRM_NODE_LOST, current_instance);
 		}
 		
 		for(lpc=0; lpc < membership->m_n_member; lpc++) {
 		    crm_update_ccm_node(
 			membership, lpc+membership->m_memb_idx,CRM_NODE_ACTIVE, current_instance);
 		}
 	}
 	
 	oc_ev_callback_done(cookie);
 	return;
 }
 #endif
 
 gboolean
 can_write(int flags)
 {
 	return TRUE;
 }
 
 static gboolean
 cib_force_exit(gpointer data)
 {
 	crm_notice("Forcing exit!");
 	terminate_cib(__FUNCTION__);
 	return FALSE;
 }
 
 void
 initiate_exit(void)
 {
 	int active = 0;
 	xmlNode *leaving = NULL;
 
 	active = crm_active_peers(crm_proc_cib);
 	if(active < 2) {
 		terminate_cib(__FUNCTION__);
 		return;
 	} 
 
 	crm_info("Sending disconnect notification to %d peers...", active);
 
 	leaving = create_xml_node(NULL, "exit-notification");	
 	crm_xml_add(leaving, F_TYPE, "cib");
 	crm_xml_add(leaving, F_CIB_OPERATION, "cib_shutdown_req");
 	
 	send_cluster_message(NULL, crm_msg_cib, leaving, TRUE);
 	free_xml(leaving);
 	
 	g_timeout_add(crm_get_msec("5s"), cib_force_exit, NULL);
 }
 
 extern int remote_fd;
 extern int remote_tls_fd;
 
 void
 terminate_cib(const char *caller) 
 {
     if(remote_fd > 0) {
 	close(remote_fd);
     }
     if(remote_tls_fd > 0) {
 	close(remote_tls_fd);
     }
     
 #if SUPPORT_COROSYNC
     if(is_openais_cluster()) {
 	cib_ha_connection_destroy(NULL);
 	return;
     } 
 #endif
 #if SUPPORT_HEARTBEAT
     if(hb_conn != NULL) {
 	crm_info("%s: Disconnecting heartbeat", caller);
 	hb_conn->llc_ops->signoff(hb_conn, FALSE);
 
     } else {
 	crm_err("%s: No heartbeat connection", caller);
     }
 #endif
 		
     uninitializeCib();
      
     crm_info("Exiting...");
     
     if (mainloop != NULL && g_main_is_running(mainloop)) {
 	g_main_quit(mainloop);
 	
     } else {
 	exit(LSB_EXIT_OK);
     }
 
 }
diff --git a/cib/common.c b/cib/common.c
index 61815999d7..de37f79523 100644
--- a/cib/common.c
+++ b/cib/common.c
@@ -1,336 +1,338 @@
 /* 
  * Copyright (C) 2008 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <crm_internal.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 
 #include <crm/crm.h>
 #include <crm/cib.h>
 #include <crm/msg_xml.h>
 #include <crm/common/ipc.h>
 #include <crm/common/cluster.h>
 
 #include <crm/common/xml.h>
 #include <crm/common/msg.h>
 
 #include <cibio.h>
 #include <callbacks.h>
 #include <cibmessages.h>
 #include "common.h"
 
 extern gboolean cib_is_master;
 extern const char* cib_root;
 gboolean stand_alone = FALSE;
 extern enum cib_errors cib_status;
 extern gboolean can_write(int flags);
 extern enum cib_errors cib_perform_command(
     xmlNode *request, xmlNode **reply, xmlNode **cib_diff, gboolean privileged);
 
 static xmlNode *
 cib_prepare_common(xmlNode *root, const char *section)
 {
     xmlNode *data = NULL;
 	
     /* extract the CIB from the fragment */
     if(root == NULL) {
 	return NULL;
 
     } else if(safe_str_eq(crm_element_name(root), XML_TAG_FRAGMENT)
 	      || safe_str_eq(crm_element_name(root), F_CRM_DATA)
 	      || safe_str_eq(crm_element_name(root), F_CIB_CALLDATA)) {
 	data = first_named_child(root, XML_TAG_CIB);
 
     } else {
 	data = root;
     }
 
     /* grab the section specified for the command */
     if(section != NULL
        && data != NULL
        && crm_str_eq(crm_element_name(data), XML_TAG_CIB, TRUE)){
 	data = get_object_root(section, data);
     }
 
     /* crm_log_xml_debug_4(root, "cib:input"); */
     return data;
 }
 
 static enum cib_errors
 cib_prepare_none(xmlNode *request, xmlNode **data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return cib_ok;
 }
 
 static enum cib_errors
 cib_prepare_data(xmlNode *request, xmlNode **data, const char **section)
 {
     xmlNode *input_fragment = get_message_xml(request, F_CIB_CALLDATA);
     *section = crm_element_value(request, F_CIB_SECTION);
     *data = cib_prepare_common(input_fragment, *section);
     /* crm_log_xml_debug(*data, "data"); */
     return cib_ok;
 }
 
 static enum cib_errors
 cib_prepare_sync(xmlNode *request, xmlNode **data, const char **section)
 {
     *data = NULL;
     *section = crm_element_value(request, F_CIB_SECTION);
     return cib_ok;
 }
 
 static enum cib_errors
 cib_prepare_diff(xmlNode *request, xmlNode **data, const char **section)
 {
     xmlNode *input_fragment = NULL;
     const char *update = crm_element_value(request, F_CIB_GLOBAL_UPDATE);
 
     *data = NULL;
     *section = NULL;
 
     if(crm_is_true(update)) {
 	input_fragment = get_message_xml(request,F_CIB_UPDATE_DIFF);
 		
     } else {
 	input_fragment = get_message_xml(request, F_CIB_CALLDATA);
     }
 
     CRM_CHECK_AND_STORE(input_fragment != NULL,crm_log_xml(LOG_WARNING, "no input", request));
     *data = cib_prepare_common(input_fragment, NULL);
     return cib_ok;
 }
 
 static enum cib_errors
 cib_cleanup_query(int options, xmlNode **data, xmlNode **output) 
 {
     CRM_DEV_ASSERT(*data == NULL);
     if((options & cib_no_children)
        || safe_str_eq(crm_element_name(*output), "xpath-query")) {
 	free_xml(*output);
     }
     return cib_ok;
 }
 
 static enum cib_errors
 cib_cleanup_data(int options, xmlNode **data, xmlNode **output) 
 {
     free_xml(*output);
     *data = NULL;
     return cib_ok;
 }
 
 static enum cib_errors
 cib_cleanup_output(int options, xmlNode **data, xmlNode **output) 
 {
     free_xml(*output);
     return cib_ok;
 }
 
 static enum cib_errors
 cib_cleanup_none(int options, xmlNode **data, xmlNode **output) 
 {
     CRM_DEV_ASSERT(*data == NULL);
     CRM_DEV_ASSERT(*output == NULL);
     return cib_ok;
 }
 
 static enum cib_errors
 cib_cleanup_sync(int options, xmlNode **data, xmlNode **output) 
 {
     /* data is non-NULL but doesnt need to be free'd */
     CRM_DEV_ASSERT(*data == NULL);
     CRM_DEV_ASSERT(*output == NULL);
     return cib_ok;
 }
 
 /*
   typedef struct cib_operation_s
   {
   const char* 	operation;
   gboolean	modifies_cib;
   gboolean	needs_privileges;
   gboolean	needs_quorum;
   enum cib_errors (*prepare)(xmlNode *, xmlNode**, const char **);
   enum cib_errors (*cleanup)(xmlNode**, xmlNode**);
   enum cib_errors (*fn)(
   const char *, int, const char *,
   xmlNode*, xmlNode*, xmlNode**, xmlNode**);
   } cib_operation_t;
 */
 /* technically bump does modify the cib...
  * but we want to split the "bump" from the "sync"
  */
 static cib_operation_t cib_server_ops[] = {
     {NULL,             FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
     {CIB_OP_QUERY,     FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_query,  cib_process_query},
     {CIB_OP_MODIFY,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_modify},
     {CIB_OP_APPLY_DIFF,TRUE,  TRUE,  TRUE,  cib_prepare_diff, cib_cleanup_data,   cib_server_process_diff},
     {CIB_OP_REPLACE,   TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_replace_svr},
     {CIB_OP_CREATE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_create},
     {CIB_OP_DELETE,    TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete},
     {CIB_OP_SYNC,      FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_sync},
     {CIB_OP_BUMP,      TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_bump},
     {CIB_OP_ERASE,     TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_erase},
     {CRM_OP_NOOP,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_default},
     {CIB_OP_DELETE_ALT,TRUE,  TRUE,  TRUE,  cib_prepare_data, cib_cleanup_data,   cib_process_delete_absolute},
     {CIB_OP_UPGRADE,   TRUE,  TRUE,  TRUE,  cib_prepare_none, cib_cleanup_output, cib_process_upgrade},
     {CIB_OP_SLAVE,     FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
     {CIB_OP_SLAVEALL,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
     {CIB_OP_SYNC_ONE,  FALSE, TRUE,  FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_sync_one},
     {CIB_OP_MASTER,    TRUE,  TRUE,  FALSE, cib_prepare_data, cib_cleanup_data,   cib_process_readwrite},
     {CIB_OP_ISMASTER,  FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_readwrite},
     {"cib_shutdown_req",FALSE, TRUE, FALSE, cib_prepare_sync, cib_cleanup_sync,   cib_process_shutdown_req},
     {CRM_OP_QUIT,      FALSE, TRUE,  FALSE, cib_prepare_none, cib_cleanup_none,   cib_process_quit},
     {CRM_OP_PING,      FALSE, FALSE, FALSE, cib_prepare_none, cib_cleanup_output, cib_process_ping},
 };
 
 enum cib_errors
 cib_get_operation_id(const char *op, int *operation) 
 {
     int lpc = 0;
     static int max_msg_types = DIMOF(cib_server_ops);
 
     if(op != NULL) {
 	for (lpc = 1; lpc < max_msg_types; lpc++) {
 	    if (strcmp(op, cib_server_ops[lpc].operation) == 0) {
 		*operation = lpc;
 		return cib_ok;
 	    }
 	}
     }
     crm_err("Operation %s is not valid", op);
     *operation = -1;
     return cib_operation;
 }
 
 xmlNode *
 cib_msg_copy(xmlNode *msg, gboolean with_data) 
 {
 	int lpc = 0;
 	const char *field = NULL;
 	const char *value = NULL;
 	xmlNode *value_struct = NULL;
 
 	static const char *field_list[] = {
 		F_XML_TAGNAME	,
 		F_TYPE		,
 		F_CIB_CLIENTID  ,
 		F_CIB_CALLOPTS  ,
 		F_CIB_CALLID    ,
 		F_CIB_OPERATION ,
 		F_CIB_ISREPLY   ,
 		F_CIB_SECTION   ,
 		F_CIB_HOST	,
 		F_CIB_RC	,
 		F_CIB_DELEGATED	,
 		F_CIB_OBJID	,
 		F_CIB_OBJTYPE	,
 		F_CIB_EXISTING	,
 		F_CIB_SEENCOUNT	,
 		F_CIB_TIMEOUT	,
 		F_CIB_CALLBACK_TOKEN	,
 		F_CIB_GLOBAL_UPDATE	,
 		F_CIB_CLIENTNAME	,
+#if ENABLE_ACL
 		F_CIB_USER		,
+#endif
 		F_CIB_NOTIFY_TYPE	,
 		F_CIB_NOTIFY_ACTIVATE
 	};
 	
 	static const char *data_list[] = {
 		F_CIB_CALLDATA  ,
 		F_CIB_UPDATE	,
 		F_CIB_UPDATE_RESULT
 	};
 
 	xmlNode *copy = create_xml_node(NULL, "copy");
 	CRM_ASSERT(copy != NULL);
 	
 	for(lpc = 0; lpc < DIMOF(field_list); lpc++) {
 		field = field_list[lpc];
 		value = crm_element_value(msg, field);
 		if(value != NULL) {
 			crm_xml_add(copy, field, value);
 		}
 	}
 	for(lpc = 0; with_data && lpc < DIMOF(data_list); lpc++) {
 		field = data_list[lpc];
 		value_struct = get_message_xml(msg, field);
 		if(value_struct != NULL) {
 			add_message_xml(copy, field, value_struct);
 		}
 	}
 
 	return copy;
 }
 
 cib_op_t *cib_op_func(int call_type) 
 {
     return &(cib_server_ops[call_type].fn);
 }
 
 gboolean cib_op_modifies(int call_type) 
 {
     return cib_server_ops[call_type].modifies_cib;
 }
 
 int cib_op_can_run(
     int call_type, int call_options, gboolean privileged, gboolean global_update)
 {
     int rc = cib_ok;
     
     if(rc == cib_ok &&
        cib_server_ops[call_type].needs_privileges
        && privileged == FALSE) {
 	/* abort */
 	return cib_not_authorized;
     }
 #if 0
     if(rc == cib_ok
        && stand_alone == FALSE
        && global_update == FALSE
        && (call_options & cib_quorum_override) == 0
        && cib_server_ops[call_type].needs_quorum) {
 	return cib_no_quorum;
     }
 #endif
     return cib_ok;
 }
 
 
 int cib_op_prepare(
     int call_type, xmlNode *request, xmlNode **input, const char **section) 
 {
     return cib_server_ops[call_type].prepare(request, input, section);
 }
 
 int cib_op_cleanup(
     int call_type, int options, xmlNode **input, xmlNode **output) 
 {
     return cib_server_ops[call_type].cleanup(options, input, output);
 }
 
diff --git a/cib/remote.c b/cib/remote.c
index 466ecc5deb..b4e3cbeb40 100644
--- a/cib/remote.c
+++ b/cib/remote.c
@@ -1,543 +1,547 @@
 /* 
  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <crm_internal.h>
 #include <crm/crm.h>
 
 #include <sys/param.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 
 #include <netinet/ip.h>
 
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <glib.h>
 
 #include <crm/common/ipc.h>
 #include <crm/common/xml.h>
 #include "callbacks.h"
 /* #undef HAVE_PAM_PAM_APPL_H */
 /* #undef HAVE_GNUTLS_GNUTLS_H */
 
 #ifdef HAVE_GNUTLS_GNUTLS_H
 #  undef KEYFILE
 #  include <gnutls/gnutls.h>
 #endif
 
 #include <pwd.h>
 #include <grp.h>
 #if HAVE_SECURITY_PAM_APPL_H
 #  include <security/pam_appl.h>
 #  define HAVE_PAM 1
 #else
 #  if HAVE_PAM_PAM_APPL_H
 #    include <pam/pam_appl.h>
 #    define HAVE_PAM 1
 #  endif
 #endif
 
 extern int remote_tls_fd;
 int init_remote_listener(int port, gboolean encrypted);
 
 
 #ifdef HAVE_GNUTLS_GNUTLS_H
 #  define DH_BITS 1024
 gnutls_dh_params dh_params;
 extern gnutls_anon_server_credentials anon_cred_s;
 static void debug_log(int level, const char *str)
 {
 	fputs (str, stderr);
 }
 extern gnutls_session *create_tls_session(int csock, int type);
 
 #endif
 
 extern int num_clients;
 int authenticate_user(const char* user, const char* passwd);
 gboolean cib_remote_listen(int ssock, gpointer data);
 gboolean cib_remote_msg(int csock, gpointer data);
 
 extern void cib_common_callback_worker(
     xmlNode *op_request, cib_client_t *cib_client, gboolean force_synchronous, gboolean privileged);
 
 
 
 #define ERROR_SUFFIX "  Shutting down remote listener"
 int
 init_remote_listener(int port, gboolean encrypted) 
 {
 	int 			ssock;
 	struct sockaddr_in 	saddr;
 	int			optval;
 
 	if(port <= 0) {
 		/* dont start it */
 		return 0;
 	}
 
 	if(encrypted) {
 #ifndef HAVE_GNUTLS_GNUTLS_H
 	    crm_warn("TLS support is not available");
 	    return 0;
 #else
 	    crm_notice("Starting a tls listener on port %d.", port);	
 	    gnutls_global_init();
 /* 	gnutls_global_set_log_level (10); */
 	    gnutls_global_set_log_function (debug_log);
 	    gnutls_dh_params_init(&dh_params);
 	    gnutls_dh_params_generate2(dh_params, DH_BITS);
 	    gnutls_anon_allocate_server_credentials (&anon_cred_s);
 	    gnutls_anon_set_server_dh_params (anon_cred_s, dh_params);
 #endif
 	} else {
 	    crm_warn("Starting a plain_text listener on port %d.", port);	
 	}	
 #ifndef HAVE_PAM
 	    crm_warn("PAM is _not_ enabled!");	
 #endif
 
 	/* create server socket */
 	ssock = socket(AF_INET, SOCK_STREAM, 0);
 	if (ssock == -1) {
 	    crm_perror(LOG_ERR,"Can not create server socket."ERROR_SUFFIX);
 	    return -1;
 	}
 	
 	/* reuse address */
 	optval = 1;
 	setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));	
 	
 	/* bind server socket*/
 	memset(&saddr, '\0', sizeof(saddr));
 	saddr.sin_family = AF_INET;
 	saddr.sin_addr.s_addr = INADDR_ANY;
 	saddr.sin_port = htons(port);
 	if (bind(ssock, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
 	    crm_perror(LOG_ERR,"Can not bind server socket."ERROR_SUFFIX);
 	    return -2;
 	}
 	if (listen(ssock, 10) == -1) {
 	    crm_perror(LOG_ERR,"Can not start listen."ERROR_SUFFIX);
 	    return -3;
 	}
 	
 	G_main_add_fd(G_PRIORITY_HIGH, ssock, FALSE,
 		      cib_remote_listen, NULL,
 		      default_ipc_connection_destroy);
 	
 	return ssock;
 }
 
 static int
 check_group_membership(const char* usr, const char* grp)
 {
 	int index = 0;
 	struct passwd *pwd = NULL;
 	struct group *group = NULL;
 	
 	CRM_CHECK(usr != NULL, return FALSE);
 	CRM_CHECK(grp != NULL, return FALSE);
 
 	pwd = getpwnam(usr);
 	if (pwd == NULL) {
 		crm_err("No user named '%s' exists!", usr);
 		return FALSE;
 	}
 
 	group = getgrgid(pwd->pw_gid);
 	if (group != NULL && crm_str_eq(grp, group->gr_name, TRUE)) {
 		return TRUE;
 	}
 	
 	group = getgrnam(grp);
 	if (group == NULL) {
 		crm_err("No group named '%s' exists!", grp);
 		return FALSE;
 	}
 
 	while (TRUE) {
 		char* member = group->gr_mem[index++];
 		if(member == NULL) {
 			break;
 
 		} else if (crm_str_eq(usr, member, TRUE)) {
 			return TRUE;
 		}
 	};
 
 	return FALSE;
 }
 
 gboolean
 cib_remote_listen(int ssock, gpointer data)
 {
 	int lpc = 0;
 	int csock = 0;
 	unsigned laddr;
 	struct sockaddr_in addr;
 #ifdef HAVE_GNUTLS_GNUTLS_H
 	gnutls_session *session = NULL;
 #endif
 	cib_client_t *new_client = NULL;
 
 	xmlNode *login = NULL;
 	const char *user = NULL;
 	const char *pass = NULL;
 	const char *tmp = NULL;
 
 	cl_uuid_t client_id;
 	char uuid_str[UU_UNPARSE_SIZEOF];
 	
 	/* accept the connection */
 	laddr = sizeof(addr);
 	csock = accept(ssock, (struct sockaddr*)&addr, &laddr);
 	crm_debug("New %s connection from %s",
 		  ssock == remote_tls_fd?"secure":"clear-text",
 		  inet_ntoa(addr.sin_addr));
 
 	if (csock == -1) {
 		crm_err("accept socket failed");
 		return TRUE;
 	}
 
 	if(ssock == remote_tls_fd) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
 	    /* create gnutls session for the server socket */
 	    session = create_tls_session(csock, GNUTLS_SERVER);
 	    if (session == NULL) {
 		crm_err("TLS session creation failed");
 		close(csock);
 		return TRUE;
 	    }
 #endif
 	}
 
 	do {
 		crm_debug_2("Iter: %d", lpc);
 		if(ssock == remote_tls_fd) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
 		    login = cib_recv_remote_msg(session, TRUE);
 #endif
 		} else {
 		    login = cib_recv_remote_msg(GINT_TO_POINTER(csock), FALSE);
 		}
 		sleep(1);
 		
 	} while(login == NULL && ++lpc < 10);
 	
 	crm_log_xml_info(login, "Login: ");
 	if(login == NULL) {
 		goto bail;
 	}
 	
 	tmp = crm_element_name(login);
 	if(safe_str_neq(tmp, "cib_command")) {
 		crm_err("Wrong tag: %s", tmp);
 		goto bail;
 	}
 
 	tmp = crm_element_value(login, "op");
 	if(safe_str_neq(tmp, "authenticate")) {
 		crm_err("Wrong operation: %s", tmp);
 		goto bail;
 	}
 	
 	user = crm_element_value(login, "user");
 	pass = crm_element_value(login, "password");
 
 	/* Non-root daemons can only validate the password of the
 	 * user they're running as
 	 */
 	if(check_group_membership(user, CRM_DAEMON_GROUP) == FALSE) {
 		crm_err("User is not a member of the required group");
 		goto bail;
 
 	} else if (authenticate_user(user, pass) == FALSE) {
 		crm_err("PAM auth failed");
 		goto bail;
 	}
 
 	/* send ACK */
 	crm_malloc0(new_client, sizeof(cib_client_t));
 	num_clients++;
 	new_client->channel_name = "remote";
 	new_client->name = crm_element_value_copy(login, "name");
 	
 	cl_uuid_generate(&client_id);
 	cl_uuid_unparse(&client_id, uuid_str);
 
 	CRM_CHECK(new_client->id == NULL, crm_free(new_client->id));
 	new_client->id = crm_strdup(uuid_str);
 
+#if ENABLE_ACL
 	new_client->user = crm_strdup(user);
+#endif
 	
 	new_client->callback_id = NULL;
 	if(ssock == remote_tls_fd) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
 	    new_client->encrypted = TRUE;
 	    new_client->channel = (void*)session;
 #endif
 	} else {
 	    new_client->channel = GINT_TO_POINTER(csock);
 	}	
 
 	free_xml(login);
 	login = create_xml_node(NULL, "cib_result");
 	crm_xml_add(login, F_CIB_OPERATION, CRM_OP_REGISTER);
 	crm_xml_add(login, F_CIB_CLIENTID,  new_client->id);
 	cib_send_remote_msg(new_client->channel, login, new_client->encrypted);
 	free_xml(login);
 
 	new_client->source = (void*)G_main_add_fd(
 		G_PRIORITY_DEFAULT, csock, FALSE, cib_remote_msg, new_client,
 		default_ipc_connection_destroy);
 
 	g_hash_table_insert(client_list, new_client->id, new_client);
 
 	return TRUE;
 
   bail:
 	if(ssock == remote_tls_fd) {
 #ifdef HAVE_GNUTLS_GNUTLS_H
 	    gnutls_bye(*session, GNUTLS_SHUT_RDWR);
 	    gnutls_deinit(*session);
 	    gnutls_free(session);
 #endif
 	}
 	close(csock);
 	free_xml(login);
 	return TRUE;
 }
 
 gboolean
 cib_remote_msg(int csock, gpointer data)
 {
 	const char *value = NULL;
 	xmlNode *command = NULL;
 	cib_client_t *client = data;
 	crm_debug_2("%s callback", client->encrypted?"secure":"clear-text");
 
 	command = cib_recv_remote_msg(client->channel, client->encrypted);
 	if(command == NULL) {
 	    return FALSE;
 	}
 	
 	value = crm_element_name(command);
 	if(safe_str_neq(value, "cib_command")) {
 	    crm_log_xml(LOG_MSG, "Bad command: ", command);
 	    goto bail;
 	}
 
 	if(client->name == NULL) {
 	    value = crm_element_value(command, F_CLIENTNAME);
 	    if(value == NULL) {
 		client->name = crm_strdup(client->id);
 	    } else {
 		client->name = crm_strdup(value);
 	    }
 	}
 
 	if(client->callback_id == NULL) {
 	    value = crm_element_value(command, F_CIB_CALLBACK_TOKEN);
 	    if(value != NULL) {
 		client->callback_id = crm_strdup(value);
 		crm_debug_2("Callback channel for %s is %s",
 			    client->id, client->callback_id);
 		
 	    } else {
 		client->callback_id = crm_strdup(client->id);			
 	    }
 	}
 
 	
 	/* unset dangerous options */
 	xml_remove_prop(command, F_ORIG);
 	xml_remove_prop(command, F_CIB_HOST);
 	xml_remove_prop(command, F_CIB_GLOBAL_UPDATE);
 
 	crm_xml_add(command, F_TYPE, T_CIB);
 	crm_xml_add(command, F_CIB_CLIENTID, client->id);
 	crm_xml_add(command, F_CIB_CLIENTNAME, client->name);
+#if ENABLE_ACL
 	crm_xml_add(command, F_CIB_USER, client->user);
+#endif
 	
 	if(crm_element_value(command, F_CIB_CALLID) == NULL) {
 	    cl_uuid_t call_id;
 	    char call_uuid[UU_UNPARSE_SIZEOF];
 
 	    /* fix the command */
 	    cl_uuid_generate(&call_id);
 	    cl_uuid_unparse(&call_id, call_uuid);
 	    crm_xml_add(command, F_CIB_CALLID, call_uuid);
 	}
 	
 	if(crm_element_value(command, F_CIB_CALLOPTS) == NULL) {
 		crm_xml_add_int(command, F_CIB_CALLOPTS, 0);
 	}
 
 	crm_log_xml(LOG_MSG, "Remote command: ", command);
 	cib_common_callback_worker(command, client, FALSE, TRUE);
   bail:
 	free_xml(command);
 	command = NULL;
 	return TRUE;
 }
 
 #ifdef HAVE_PAM
 /* 
  * Useful Examples:
  *    http://www.kernel.org/pub/linux/libs/pam/Linux-PAM-html
  *    http://developer.apple.com/samplecode/CryptNoMore/index.html
  */
 static int
 construct_pam_passwd(int num_msg, const struct pam_message **msg,
 		     struct pam_response **response, void *data)
 {
     int count = 0;
     struct pam_response *reply;
     char *string = (char*)data;
 
     CRM_CHECK(data, return PAM_CONV_ERR);
     CRM_CHECK(num_msg == 1, return PAM_CONV_ERR); /* We only want to handle one message */
 
     reply = calloc(1, sizeof(struct pam_response));
     CRM_ASSERT(reply != NULL);
     
     for (count=0; count < num_msg; ++count) {
 	switch (msg[count]->msg_style) {
 	    case PAM_TEXT_INFO:
 		crm_info("PAM: %s\n", msg[count]->msg);
 		break;
 	    case PAM_PROMPT_ECHO_OFF:
 	    case PAM_PROMPT_ECHO_ON:
 		reply[count].resp_retcode = 0;
 		reply[count].resp = string; /* We already made a copy */
 	    case PAM_ERROR_MSG:
 		/* In theory we'd want to print this, but then
 		 * we see the password prompt in the logs
 		 */
 		/* crm_err("PAM error: %s\n", msg[count]->msg); */
 		break;
 	    default:
 		crm_err("Unhandled conversation type: %d", msg[count]->msg_style);
 		goto bail;
 	}
     }
 
     *response = reply;
     reply = NULL;
 
     return PAM_SUCCESS;
 
 bail:
     for (count=0; count < num_msg; ++count) {
 	if(reply[count].resp != NULL) {
 	    switch (msg[count]->msg_style) {
 		case PAM_PROMPT_ECHO_ON:
 		case PAM_PROMPT_ECHO_OFF:
 		    /* Erase the data - it contained a password */
 		    while (*(reply[count].resp)) {
 			*(reply[count].resp)++ = '\0';
 		    }
 		    free(reply[count].resp);
 		    break;
 	    }
 	    reply[count].resp = NULL;
 	}
     }
     free(reply);
     reply = NULL;
 
     return PAM_CONV_ERR;
 }
 #endif
 
 int 
 authenticate_user(const char* user, const char* passwd)
 {
 #ifndef HAVE_PAM
 	gboolean pass = TRUE;
 #else
 	int rc = 0;
 	gboolean pass = FALSE;
 	const void *p_user = NULL;
 	
 	struct pam_conv p_conv;
 	struct pam_handle *pam_h = NULL;
 	static const char *pam_name = NULL;
 
 	if(pam_name == NULL) {
 	    pam_name = getenv("CIB_pam_service");
 	}
 	if(pam_name == NULL) {
 	    pam_name = "login";
 	}
 	
 	p_conv.conv = construct_pam_passwd;
 	p_conv.appdata_ptr = strdup(passwd);
 
 	rc = pam_start (pam_name, user, &p_conv, &pam_h);
 	if (rc != PAM_SUCCESS) {
 		crm_err("Could not initialize PAM: %s (%d)", pam_strerror(pam_h, rc), rc);
 		goto bail;
 	}
 	
 	rc = pam_authenticate (pam_h, 0);
 	if(rc != PAM_SUCCESS) {
 		crm_err("Authentication failed for %s: %s (%d)",
 			user, pam_strerror(pam_h, rc), rc);
 		goto bail;
 	}
 
 	/* Make sure we authenticated the user we wanted to authenticate.
 	 * Since we also run as non-root, it might be worth pre-checking
 	 * the user has the same EID as us, since that the only user we
 	 * can authenticate.
 	 */
 	rc = pam_get_item(pam_h, PAM_USER, &p_user);	
 	if(rc != PAM_SUCCESS) {
 	    crm_err("Internal PAM error: %s (%d)", pam_strerror(pam_h, rc), rc);
 	    goto bail;
 	    
 	} else if (p_user == NULL) {
 	    crm_err("Unknown user authenticated.");
 	    goto bail;
 	    
 	} else if (safe_str_neq(p_user, user)) {
 	    crm_err("User mismatch: %s vs. %s.", (const char*)p_user, (const char*)user);
 	    goto bail;
 	}
 
 	rc = pam_acct_mgmt(pam_h, 0);
 	if(rc != PAM_SUCCESS) {
 	    crm_err("Access denied: %s (%d)", pam_strerror(pam_h, rc), rc);
 	    goto bail;
 	}
 	pass = TRUE;
 	
   bail:
 	rc = pam_end (pam_h, rc);
 #endif
 	return pass;
 }
 
diff --git a/configure.ac b/configure.ac
index 12c9793dea..0d9c8f594b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,1579 +1,1625 @@
 dnl
 dnl autoconf for Pacemaker
 dnl
 dnl License: GNU General Public License (GPL)
 
 dnl ===============================================
 dnl Bootstrap 
 dnl ===============================================
 AC_PREREQ(2.53)
 
 dnl Suggested structure:
 dnl     information on the package
 dnl     checks for programs
 dnl     checks for libraries
 dnl     checks for header files
 dnl     checks for types
 dnl     checks for structures
 dnl     checks for compiler characteristics
 dnl     checks for library functions
 dnl     checks for system services
 
 AC_INIT(pacemaker, 1.1.3, pacemaker@oss.clusterlabs.org)
 CRM_DTD_VERSION="1.2"
 
 PKG_FEATURES=""
 HB_PKG=heartbeat
 
 AC_CONFIG_AUX_DIR(.)
 AC_CANONICAL_HOST
 
 dnl Where #defines go (e.g. `AC_CHECK_HEADERS' below)
 dnl
 dnl Internal header: include/config.h
 dnl   - Contains ALL defines
 dnl   - include/config.h.in is generated automatically by autoheader
 dnl   - NOT to be included in any header files except lha_internal.h
 dnl     (which is also not to be included in any other header files)
 dnl
 dnl External header: include/crm_config.h
 dnl   - Contains a subset of defines checked here
 dnl   - Manually edit include/crm_config.h.in to have configure include
 dnl     new defines
 dnl   - Should not include HAVE_* defines
 dnl   - Safe to include anywhere
 AM_CONFIG_HEADER(include/config.h include/crm_config.h)
 ALL_LINGUAS="en fr"
 
 AC_ARG_WITH(version,
     [  --with-version=version   Override package version (if you're a packager needing to pretend) ],
     [ PACKAGE_VERSION="$withval" ])
 
 AC_ARG_WITH(pkg-name,
     [  --with-pkg-name=name     Override package name (if you're a packager needing to pretend) ],
     [ PACKAGE_NAME="$withval" ])
 
 AM_INIT_AUTOMAKE($PACKAGE_NAME, $PACKAGE_VERSION)
 AC_DEFINE_UNQUOTED(PACEMAKER_VERSION, "$PACKAGE_VERSION", Current pacemaker version)
 
 PACKAGE_SERIES=`echo $PACKAGE_VERSION | awk -F. '{ print $1"."$2 }'`
 AC_SUBST(PACKAGE_SERIES)
 
 dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
 dnl normal compilation.  When a failure occurs, it will then display the full 
 dnl command line
 dnl Wrap in m4_ifdef to avoid breaking on older platforms
 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES])
 
 CC_IN_CONFIGURE=yes
 export CC_IN_CONFIGURE
 
 LDD=ldd
 
 dnl ========================================================================
 dnl Compiler characteristics
 dnl ========================================================================
 
 AC_PROG_CC dnl Can force other with environment variable "CC".
 AM_PROG_CC_C_O
 AC_PROG_CC_STDC
 
 AC_LIBTOOL_DLOPEN               dnl Enable dlopen support...
 AC_LIBLTDL_CONVENIENCE          dnl make libltdl a convenience lib
 AC_PROG_LIBTOOL
 
 AC_C_STRINGIZE
 AC_TYPE_SIZE_T
 AC_CHECK_SIZEOF(char)
 AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(long long)
 AC_STRUCT_TIMEZONE
 
 dnl ===============================================
 dnl Helpers 
 dnl ===============================================
 cc_supports_flag() {
          local CFLAGS="$@"
          AC_MSG_CHECKING(whether $CC supports "$@")
          AC_COMPILE_IFELSE([int main(){return 0;}] ,[RC=0; AC_MSG_RESULT(yes)],[RC=1; AC_MSG_RESULT(no)])
          return $RC
 }
 
 extract_header_define() {
 	  AC_MSG_CHECKING(for $2 in $1)
 	  Cfile=/tmp/extract_define.$2.${$}
 	  printf "#include <stdio.h>\n" > ${Cfile}.c
 	  printf "#include <%s>\n" $1 >> ${Cfile}.c
 	  printf "int main(int argc, char **argv) { printf(\"%%s\", %s); return 0; }\n" $2 >> ${Cfile}.c
 	  $CC $CFLAGS ${Cfile}.c -o ${Cfile}
 	  value=`${Cfile}`
 	  AC_MSG_RESULT($value)
 	  printf $value
 	  rm -f ${Cfile}.c ${Cfile}
 	}
 
 dnl ===============================================
 dnl Configure Options
 dnl ===============================================
 
 dnl Some systems, like Solaris require a custom package name
 AC_ARG_WITH(pkgname,
     [  --with-pkgname=name     name for pkg (typically for Solaris) ],
     [ PKGNAME="$withval" ],
     [ PKGNAME="LXHAhb" ],
   )
 AC_SUBST(PKGNAME)
 
 AC_ARG_ENABLE([ansi],
 [  --enable-ansi force GCC to compile to ANSI/ANSI standard for older compilers.
      [default=no]])
 
 AC_ARG_ENABLE([fatal-warnings],
 [  --enable-fatal-warnings very pedantic and fatal warnings for gcc
      [default=yes]])
 
 AC_ARG_ENABLE([quiet],
 [  --enable-quiet 
      Supress make output unless there is an error
      [default=no]])
 
 AC_ARG_ENABLE([thread-safe],
 [  --enable-thread-safe Enable some client libraries to be thread safe.
      [default=no]])
 
 AC_ARG_ENABLE([bundled-ltdl],
 [  --enable-bundled-ltdl  Configure, build and install the standalone ltdl library bundled with ${PACKAGE} [default=no]]) 
 LTDL_LIBS=""
 
 AC_ARG_WITH(ais,
     [  --with-ais     
        Support the Corosync messaging and membership layer ],
     [ SUPPORT_CS=$withval ],
     [ SUPPORT_CS=try ],
 )
 
 AC_ARG_WITH(corosync,
     [  --with-corosync     
        Support the Corosync messaging and membership layer ],
     [ SUPPORT_CS=$withval ],
     [ SUPPORT_CS=try ],
 )
 
 AC_ARG_WITH(heartbeat,
     [  --with-heartbeat     
        Support the Heartbeat messaging and membership layer ],
     [ SUPPORT_HEARTBEAT=$withval ],
     [ SUPPORT_HEARTBEAT=try ],
 )
 
 AC_ARG_WITH(cman,
     [  --with-cman     
        Support the consumption of membership and quorum from cman ],
     [ SUPPORT_CMAN=$withval ],
     [ SUPPORT_CMAN=try ],
 )
 
 AC_ARG_WITH(cpg,
     [  --with-cs-quorum     
        Support the consumption of membership and quorum from corosync ],
     [ SUPPORT_CS_QUORUM=$withval ],
     [ SUPPORT_CS_QUORUM=try ],
 )
 
 AC_ARG_WITH(snmp,
     [  --with-snmp     
        Support the SNMP protocol ],
     [ SUPPORT_SNMP=$withval ],
     [ SUPPORT_SNMP=try ],
 )
 
 AC_ARG_WITH(esmtp,
     [  --with-esmtp  
        Support the sending mail notifications with the esmtp library ],
     [ SUPPORT_ESMTP=$withval ],
     [ SUPPORT_ESMTP=try ],
 )
 
+AC_ARG_WITH(acl,
+    [  --with-acl
+       Support CIB ACL ],
+    [ SUPPORT_ACL=$withval ],
+    [ SUPPORT_ACL=try ],
+)
+
 CSPREFIX=""
 AC_ARG_WITH(ais-prefix,
     [  --with-ais-prefix=DIR  Prefix used when Corosync was installed [$prefix]],
     [ CSPREFIX=$withval ], 
     [ CSPREFIX=$prefix ])
 
 LCRSODIR=""
 AC_ARG_WITH(lcrso-dir, 
     [  --with-lcrso-dir=DIR   Corosync lcrso files. ],
     [ LCRSODIR="$withval" ])
 
 INITDIR=""
 AC_ARG_WITH(initdir,
     [  --with-initdir=DIR      directory for init (rc) scripts [${INITDIR}]],
     [ INITDIR="$withval" ])
 
 SUPPORT_TRACING=1
 AC_ARG_WITH(trace-data,
     [  --with-trace-data     
        Support the dynamic enablement of addition trace logging ],
     [ SUPPORT_TRACING=$withval ])
 
 PUBLICAN_BRAND="common"
 AC_ARG_WITH(brand,
     [  --with-brand=brand  Brand to use for generated documentation [$PUBLICAN_BRAND]],
     [ PUBLICAN_BRAND="$withval" ])
 AC_SUBST(PUBLICAN_BRAND)
 
 dnl ===============================================
 dnl General Processing
 dnl ===============================================
 
 AC_SUBST(HB_PKG)
 
 INIT_EXT=""
 echo Our Host OS: $host_os/$host
 
 
 AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
 case $prefix in
   NONE)	prefix=/usr;;
 esac
 
 AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
 case $exec_prefix in
   dnl For consistency with Heartbeat, map NONE->$prefix
   NONE)	  exec_prefix=$prefix;;
   prefix) exec_prefix=$prefix;;
 esac
 
 AC_MSG_NOTICE(Sanitizing ais_prefix: ${CSPREFIX})
 case $CSPREFIX in
   dnl For consistency with Heartbeat, map NONE->$prefix
   NONE)	  CSPREFIX=$prefix;;
   prefix) CSPREFIX=$prefix;;
 esac
 
 AC_MSG_NOTICE(Sanitizing INITDIR: ${INITDIR})
 case $INITDIR in
   prefix) INITDIR=$prefix;;
   "")
     AC_MSG_CHECKING(which init (rc) directory to use)
       for initdir in /etc/init.d /etc/rc.d/init.d /sbin/init.d	\
 	   /usr/local/etc/rc.d /etc/rc.d
       do
         if
           test -d $initdir
         then
           INITDIR=$initdir
           break
         fi
       done
       AC_MSG_RESULT($INITDIR);;
 esac
 AC_SUBST(INITDIR)
 
 AC_MSG_NOTICE(Sanitizing libdir: ${libdir})
 case $libdir in
   dnl For consistency with Heartbeat, map NONE->$prefix
   *prefix*|NONE)
     AC_MSG_CHECKING(which lib directory to use)
     for aDir in lib64 lib
     do
       trydir="${exec_prefix}/${aDir}"
       if
         test -d ${trydir}
       then
         libdir=${trydir}
         break
       fi
     done
     AC_MSG_RESULT($libdir);
     ;;
 esac
 
 dnl Expand autoconf variables so that we dont end up with '${prefix}' 
 dnl in #defines and python scripts
 dnl NOTE: Autoconf deliberately leaves them unexpanded to allow
 dnl    make exec_prefix=/foo install
 dnl No longer being able to do this seems like no great loss to me...
 
 eval prefix="`eval echo ${prefix}`"
 eval exec_prefix="`eval echo ${exec_prefix}`"
 eval bindir="`eval echo ${bindir}`"
 eval sbindir="`eval echo ${sbindir}`"
 eval libexecdir="`eval echo ${libexecdir}`"
 eval datadir="`eval echo ${datadir}`"
 eval sysconfdir="`eval echo ${sysconfdir}`"
 eval sharedstatedir="`eval echo ${sharedstatedir}`"
 eval localstatedir="`eval echo ${localstatedir}`"
 eval libdir="`eval echo ${libdir}`"
 eval includedir="`eval echo ${includedir}`"
 eval oldincludedir="`eval echo ${oldincludedir}`"
 eval infodir="`eval echo ${infodir}`"
 eval mandir="`eval echo ${mandir}`"
 
 dnl Home-grown variables
 eval INITDIR="${INITDIR}"
 eval docdir="`eval echo ${docdir}`"
 if test x"${docdir}" = x""; then
    docdir=${datadir}/doc/${PACKAGE}-${VERSION}
    #docdir=${datadir}/doc/packages/${PACKAGE}
 fi
 AC_SUBST(docdir)
 
 for j in prefix exec_prefix bindir sbindir libexecdir datadir sysconfdir \
     sharedstatedir localstatedir libdir includedir oldincludedir infodir \
     mandir INITDIR docdir
 do 
   dirname=`eval echo '${'${j}'}'`
   if
     test ! -d "$dirname"
   then
     AC_MSG_WARN([$j directory ($dirname) does not exist!])
   fi
 done
 
 dnl This OS-based decision-making is poor autotools practice;
 dnl feature-based mechanisms are strongly preferred.
 dnl
 dnl So keep this section to a bare minimum; regard as a "necessary evil". 
 
 case "$host_os" in
 *bsd*)		LIBS="-L/usr/local/lib"
 		CPPFLAGS="$CPPFLAGS -I/usr/local/include"
 		INIT_EXT=".sh"
 		;;
 *solaris*)
 		;;
 *linux*)	
 		AC_DEFINE_UNQUOTED(ON_LINUX, 1, Compiling for Linux platform)
   		CFLAGS="$CFLAGS -I${prefix}/include"
  		;;
 darwin*)	
 		AC_DEFINE_UNQUOTED(ON_DARWIN, 1, Compiling for Darwin platform)
   		LIBS="$LIBS -L${prefix}/lib"
   		CFLAGS="$CFLAGS -I${prefix}/include"
 		;;
 esac
 
 dnl Eventually remove this 
 CFLAGS="$CFLAGS -I${prefix}/include/heartbeat"
 
 AC_SUBST(INIT_EXT)
 AC_DEFINE_UNQUOTED(HA_LOG_FACILITY, LOG_DAEMON, Default logging facility)
 
 AC_MSG_NOTICE(Host CPU: $host_cpu)
 
 case "$host_cpu" in
   ppc64|powerpc64)
     case $CFLAGS in
      *powerpc64*)			;;
      *)	if test "$GCC" = yes; then
 	  CFLAGS="$CFLAGS -m64"
 	fi				;;
     esac
 esac
 
 AC_MSG_CHECKING(which format is needed to print uint64_t)
 
 ac_save_CFLAGS=$CFLAGS
 CFLAGS="-Wall -Werror"
 
 AC_COMPILE_IFELSE(
     [AC_LANG_PROGRAM(
       [
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
       ],
       [
 int max = 512;	
 uint64_t bignum = 42;
 char *buffer = malloc(max);
 const char *random = "random";
 snprintf(buffer, max-1, "<quorum id=%lu quorate=%s/>", bignum, random);
 fprintf(stderr, "Result: %s\n", buffer);
       ]
     )], 
     [U64T="%lu"],
     [U64T="%llu"]
 )
 CFLAGS=$ac_save_CFLAGS
 
 AC_MSG_RESULT($U64T)
 AC_DEFINE_UNQUOTED(U64T, "$U64T", Correct printf format for logging uint64_t)
 
 AC_CHECK_HEADERS(hb_config.h)
 AC_CHECK_HEADERS(glue_config.h)
 AC_CHECK_HEADERS(agent_config.h)
 GLUE_HEADER=none
 if test "$ac_cv_header_glue_config_h" = "yes";  then
    GLUE_HEADER=glue_config.h
 
 elif test "$ac_cv_header_hb_config_h" = "yes"; then
    GLUE_HEADER=hb_config.h
 
 else
    AC_MSG_FAILURE(Core development headers were not found)
 fi
 
 dnl Variables needed for substitution
 CRM_DTD_DIRECTORY="${datadir}/pacemaker"
 AC_DEFINE_UNQUOTED(CRM_DTD_DIRECTORY,"$CRM_DTD_DIRECTORY", Location for the Pacemaker Relax-NG Schema)
 AC_SUBST(CRM_DTD_DIRECTORY)
 
 AC_DEFINE_UNQUOTED(CRM_DTD_VERSION,"$CRM_DTD_VERSION", Current version of the Pacemaker Relax-NG Schema)
 AC_SUBST(CRM_DTD_VERSION)
 
 CRM_DAEMON_USER=`extract_header_define $GLUE_HEADER HA_CCMUSER`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_USER,"$CRM_DAEMON_USER", User to run Pacemaker daemons as)
 AC_SUBST(CRM_DAEMON_USER)
 
 CRM_DAEMON_GROUP=`extract_header_define $GLUE_HEADER HA_APIGROUP`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_GROUP,"$CRM_DAEMON_GROUP", Group to run Pacemaker daemons as)
 AC_SUBST(CRM_DAEMON_GROUP)
 
 CRM_STATE_DIR=${localstatedir}/run/crm
 AC_DEFINE_UNQUOTED(CRM_STATE_DIR,"$CRM_STATE_DIR", Where to keep state files and sockets)
 AC_SUBST(CRM_STATE_DIR)
 
 PE_STATE_DIR="${localstatedir}/lib/pengine"
 AC_DEFINE_UNQUOTED(PE_STATE_DIR,"$PE_STATE_DIR", Where to keep PEngine outputs)
 AC_SUBST(PE_STATE_DIR)
 
 dnl Eventually move out of the heartbeat dir tree and create compatability code
 CRM_CONFIG_DIR="${localstatedir}/lib/heartbeat/crm"
 AC_DEFINE_UNQUOTED(CRM_CONFIG_DIR,"$CRM_CONFIG_DIR", Where to keep CIB configuration files)
 AC_SUBST(CRM_CONFIG_DIR)
 
 dnl Eventually move out of the heartbeat dir tree and create compatability code
 dnl CRM_DAEMON_DIR=$libdir/pacemaker
 CRM_DAEMON_DIR=`extract_header_define $GLUE_HEADER HA_LIBHBDIR`
 AC_DEFINE_UNQUOTED(CRM_DAEMON_DIR,"$CRM_DAEMON_DIR", Location for Pacemaker daemons)
 AC_SUBST(CRM_DAEMON_DIR)
 
 dnl Create symlinks to here from CRM_DAEMON_DIR when needed
 HB_DAEMON_DIR=`extract_header_define $GLUE_HEADER HA_LIBHBDIR`
 AC_DEFINE_UNQUOTED(HB_DAEMON_DIR,"$HB_DAEMON_DIR", Location for Heartbeat expects Pacemaker daemons to be in)
 AC_SUBST(HB_DAEMON_DIR)
 
 dnl Needed so that the Corosync plugin can clear out the directory as Heartbeat does
 HA_STATE_DIR=`extract_header_define $GLUE_HEADER HA_VARRUNDIR`
 AC_DEFINE_UNQUOTED(HA_STATE_DIR,"$HA_STATE_DIR", Where Heartbeat keeps state files and sockets)
 AC_SUBST(HA_STATE_DIR)
 
 CRM_RSCTMP_DIR=
 if test "$ac_cv_header_agent_config_h" = "yes";  then
    CRM_RSCTMP_DIR=`extract_header_define agent_config.h HA_RSCTMPDIR`
 else
    AC_MSG_WARN(Agents development headers were not found.)
 fi
 
 if test x$CRM_RSCTMP_DIR = x; then
    CRM_RSCTMP_DIR="$HA_STATE_DIR/heartbeat/rsctmp"
 fi
 AC_MSG_CHECKING(Scratch dir for resource agents)
 AC_MSG_RESULT($CRM_RSCTMP_DIR)
 AC_DEFINE_UNQUOTED(CRM_RSCTMP_DIR,"$CRM_RSCTMP_DIR", Where resource agents should keep state files)
 AC_SUBST(CRM_RSCTMP_DIR)
 
 dnl Needed for the location of hostcache in CTS.py
 HA_VARLIBHBDIR=`extract_header_define $GLUE_HEADER HA_VARLIBHBDIR`
 AC_SUBST(HA_VARLIBHBDIR)
 
 AC_DEFINE_UNQUOTED(UUID_FILE,"$localstatedir/lib/heartbeat/hb_uuid", Location of Heartbeat's UUID file)
 
 OCF_ROOT_DIR=`extract_header_define $GLUE_HEADER OCF_ROOT_DIR`
 if test "X$OCF_ROOT_DIR" = X; then
   AC_MSG_ERROR(Could not locate OCF directory)
 fi
 AC_SUBST(OCF_ROOT_DIR)
 
 OCF_RA_DIR=`extract_header_define $GLUE_HEADER OCF_RA_DIR`
 AC_DEFINE_UNQUOTED(OCF_RA_DIR,"$OCF_RA_DIR", Location for OCF RAs)
 AC_SUBST(OCF_RA_DIR)
 
 dnl Extract this value from glue_config.h once we no longer support anything else
 STONITH_PLUGIN_DIR="$libdir/stonith/plugins/stonith/"
 AC_DEFINE_UNQUOTED(STONITH_PLUGIN_DIR,"$STONITH_PLUGIN_DIR", Location for Stonith plugins)
 AC_SUBST(STONITH_PLUGIN_DIR)
 
 RH_STONITH_DIR="$sbindir"
 AC_DEFINE_UNQUOTED(RH_STONITH_DIR,"$RH_STONITH_DIR", Location for Red Hat Stonith agents)
 
 RH_STONITH_PREFIX="fence_"
 AC_DEFINE_UNQUOTED(RH_STONITH_PREFIX,"$RH_STONITH_PREFIX", Prefix for Red Hat Stonith agents)
 
 AC_PATH_PROGS(HG, hg false)
 AC_MSG_CHECKING(build version)
 BUILD_VERSION=unknown
 if test -f $srcdir/.hg_archival.txt; then
    BUILD_VERSION=`cat $srcdir/.hg_archival.txt | awk '/node:/ { print $2 }'`
 elif test -x $HG -a -d .hg; then
    BUILD_VERSION=`$HG id -i`
    if test $? != 0; then
        BUILD_VERSION=unknown
    fi
 fi
 
 AC_DEFINE_UNQUOTED(BUILD_VERSION, "$BUILD_VERSION", Build version)
 AC_MSG_RESULT($BUILD_VERSION)
 AC_SUBST(BUILD_VERSION)
 
 dnl ===============================================
 dnl Program Paths
 dnl ===============================================
 
 PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin"
 export PATH
 
 
 dnl Replacing AC_PROG_LIBTOOL with AC_CHECK_PROG because LIBTOOL
 dnl was NOT being expanded all the time thus causing things to fail.
 AC_CHECK_PROGS(LIBTOOL, glibtool libtool libtool15 libtool13)
 
 AM_PATH_PYTHON
 AC_CHECK_PROGS(MAKE, gmake make)
 AC_PATH_PROGS(HTML2TXT, lynx w3m)
 AC_PATH_PROGS(HELP2MAN, help2man)
 AC_PATH_PROGS(POD2MAN, pod2man, pod2man)
 AC_PATH_PROGS(ASCIIDOC, asciidoc)
 AC_PATH_PROGS(PUBLICAN, publican)
 AC_PATH_PROGS(XSLTPROC, xsltproc)
 AC_PATH_PROGS(FOP, fop)
 AC_PATH_PROGS(SSH, ssh, /usr/bin/ssh)
 AC_PATH_PROGS(SCP, scp, /usr/bin/scp)
 AC_PATH_PROGS(HG, hg, /bin/false)
 AC_PATH_PROGS(TAR, tar)
 AC_PATH_PROGS(MD5, md5)
 AC_PATH_PROGS(TEST, test)
 AC_PATH_PROGS(PKGCONFIG, pkg-config)
 AC_PATH_PROGS(XML2CONFIG, xml2-config)
 AC_PATH_PROGS(VALGRIND_BIN, valgrind, /usr/bin/valgrind)
 AC_DEFINE_UNQUOTED(VALGRIND_BIN, "$VALGRIND_BIN", Valgrind command)
 
 if test x"${LIBTOOL}" = x""; then
    AC_MSG_ERROR(You need (g)libtool installed in order to build ${PACKAGE})
 fi
 if test x"${MAKE}" = x""; then
    AC_MSG_ERROR(You need (g)make installed in order to build ${PACKAGE})
 fi
 
 AM_CONDITIONAL(BUILD_HELP, test x"${HELP2MAN}" != x"")
 if test x"${HELP2MAN}" != x""; then
    PKG_FEATURES="$PKG_FEATURES manpages"
 fi
 
 MANPAGE_XSLT=""
 if test x"${XSLTPROC}" != x""; then
   AC_MSG_CHECKING(docbook to manpage transform)
   XSLT=`find ${datadir} -name docbook.xsl`
   for xsl in $XSLT; do
     dname=`dirname $xsl`
     bname=`basename $dname`
     if test "$bname" = "manpages"; then
        MANPAGE_XSLT="$xsl"
        break
     fi
   done
 fi
 AC_MSG_RESULT($MANPAGE_XSLT)
 AC_SUBST(MANPAGE_XSLT)
 
 AM_CONDITIONAL(BUILD_XML_HELP, test x"${MANPAGE_XSLT}" != x"")
 if test x"${MANPAGE_XSLT}" != x""; then
    PKG_FEATURES="$PKG_FEATURES docbook-manpages"
 fi
 
 AM_CONDITIONAL(BUILD_ASCIIDOC, test x"${ASCIIDOC}" != x"")
 if test x"${ASCIIDOC}" != x""; then
    PKG_FEATURES="$PKG_FEATURES asciidoc"
 fi
 
 AM_CONDITIONAL(BUILD_DOCBOOK, test ${PUBLICAN} != x"")
 if test ${PUBLICAN} != x""; then
    PKG_FEATURES="$PKG_FEATURES publican"
 fi
 
 dnl ===============================================
 dnl Libraries
 dnl ===============================================
 AC_CHECK_LIB(socket, socket)			dnl -lsocket
 AC_CHECK_LIB(c, dlopen)				dnl if dlopen is in libc...
 AC_CHECK_LIB(dl, dlopen)			dnl -ldl (for Linux)
 AC_CHECK_LIB(rt, sched_getscheduler)            dnl -lrt (for Tru64)
 AC_CHECK_LIB(gnugetopt, getopt_long)		dnl -lgnugetopt ( if available )
 AC_CHECK_LIB(pam, pam_start)			dnl -lpam (if available)
 AC_CHECK_LIB(uuid, uuid_parse)			dnl e2fsprogs
 AC_CHECK_LIB(uuid, uuid_create)			dnl ossp
 
 if test x"${PKGCONFIG}" = x""; then
    AC_MSG_ERROR(You need pkgconfig installed in order to build ${PACKAGE})
 fi
 
 dnl
 dnl     On many systems libcrypto is needed when linking against libsnmp.
 dnl     Check to see if it exists, and if so use it.
 dnl
 AC_CHECK_LIB(crypto, CRYPTO_free, CRYPTOLIB="-lcrypto",)
 AC_SUBST(CRYPTOLIB)
 
 if test "x${enable_thread_safe}" = "xyes"; then
         GPKGNAME="gthread-2.0"
 else
         GPKGNAME="glib-2.0"
 fi
 
 if 
    $PKGCONFIG --exists $GPKGNAME
 then
 	GLIBCONFIG="$PKGCONFIG $GPKGNAME"
 else
 	set -x
         echo PKG_CONFIG_PATH=$PKG_CONFIG_PATH
 	$PKGCONFIG --exists $GPKGNAME; echo $?
 	$PKGCONFIG --cflags $GPKGNAME; echo $?
 	$PKGCONFIG $GPKGNAME; echo $?
 	set +x
         
 	AC_MSG_ERROR(You need glib2-devel installed in order to build ${PACKAGE})
 fi
 AC_MSG_RESULT(using $GLIBCONFIG)
 
 #
 #	Where is dlopen?
 #
 if test "$ac_cv_lib_c_dlopen" = yes; then
 	LIBADD_DL=""
 elif test "$ac_cv_lib_dl_dlopen" = yes; then
 	LIBADD_DL=-ldl
 else
         LIBADD_DL=${lt_cv_dlopen_libs}
 fi
 dnl
 dnl Check for location of gettext
 dnl
 dnl On at least Solaris 2.x, where it is in libc, specifying lintl causes
 dnl grief. Ensure minimal result, not the sum of all possibilities.
 dnl And do libc first.
 dnl Known examples:
 dnl    c:      Linux, Solaris 2.6+
 dnl    intl:   BSD, AIX
 
 AC_CHECK_LIB(c, gettext)
 if test x$ac_cv_lib_c_gettext != xyes; then
    AC_CHECK_LIB(intl, gettext)
 fi
 
 if test x$ac_cv_lib_c_gettext != xyes -a x$ac_cv_lib_intl_gettext != xyes; then
    AC_MSG_ERROR(You need gettext installed in order to build ${PACKAGE})
 fi
 
 if test "X$GLIBCONFIG" != X; then
 	AC_MSG_CHECKING(for special glib includes: )
 	GLIBHEAD=`$GLIBCONFIG --cflags`
 	AC_MSG_RESULT($GLIBHEAD)
 	CPPFLAGS="$CPPFLAGS $GLIBHEAD"
 
 	AC_MSG_CHECKING(for glib library flags)
 	GLIBLIB=`$GLIBCONFIG --libs`
 	AC_MSG_RESULT($GLIBLIB)
 	LIBS="$LIBS $GLIBLIB"
 fi
 
 dnl ========================================================================
 dnl Headers
 dnl ========================================================================
 
 AC_HEADER_STDC
 AC_CHECK_HEADERS(arpa/inet.h)
 AC_CHECK_HEADERS(asm/types.h)
 AC_CHECK_HEADERS(assert.h)
 AC_CHECK_HEADERS(auth-client.h)
 AC_CHECK_HEADERS(ctype.h)
 AC_CHECK_HEADERS(dirent.h)
 AC_CHECK_HEADERS(errno.h)
 AC_CHECK_HEADERS(fcntl.h)
 AC_CHECK_HEADERS(getopt.h)
 AC_CHECK_HEADERS(glib.h)
 AC_CHECK_HEADERS(grp.h)
 AC_CHECK_HEADERS(limits.h)
 AC_CHECK_HEADERS(linux/errqueue.h)
 AC_CHECK_HEADERS(malloc.h)
 AC_CHECK_HEADERS(netdb.h)
 AC_CHECK_HEADERS(netinet/in.h)
 AC_CHECK_HEADERS(netinet/ip.h)
 AC_CHECK_HEADERS(pam/pam_appl.h)
 AC_CHECK_HEADERS(pthread.h)
 AC_CHECK_HEADERS(pwd.h)
 AC_CHECK_HEADERS(security/pam_appl.h)
 AC_CHECK_HEADERS(sgtty.h)
 AC_CHECK_HEADERS(signal.h)
 AC_CHECK_HEADERS(stdarg.h)
 AC_CHECK_HEADERS(stddef.h)
 AC_CHECK_HEADERS(stdio.h)
 AC_CHECK_HEADERS(stdlib.h)
 AC_CHECK_HEADERS(string.h)
 AC_CHECK_HEADERS(strings.h)
 AC_CHECK_HEADERS(sys/dir.h)
 AC_CHECK_HEADERS(sys/ioctl.h)
 AC_CHECK_HEADERS(sys/param.h)
 AC_CHECK_HEADERS(sys/poll.h)
 AC_CHECK_HEADERS(sys/resource.h)
 AC_CHECK_HEADERS(sys/select.h)
 AC_CHECK_HEADERS(sys/socket.h)
 AC_CHECK_HEADERS(sys/sockio.h)
 AC_CHECK_HEADERS(sys/stat.h)
 AC_CHECK_HEADERS(sys/time.h)
 AC_CHECK_HEADERS(sys/timeb.h)
 AC_CHECK_HEADERS(sys/types.h)
 AC_CHECK_HEADERS(sys/uio.h)
 AC_CHECK_HEADERS(sys/un.h)
 AC_CHECK_HEADERS(sys/utsname.h)
 AC_CHECK_HEADERS(sys/wait.h)
 AC_CHECK_HEADERS(time.h)
 AC_CHECK_HEADERS(unistd.h)
 AC_CHECK_HEADERS(winsock.h)
 
 dnl These headers need prerequisits before the tests will pass 
 dnl AC_CHECK_HEADERS(net/if.h)
 dnl AC_CHECK_HEADERS(netinet/icmp6.h)
 dnl AC_CHECK_HEADERS(netinet/ip6.h)
 dnl AC_CHECK_HEADERS(netinet/ip_icmp.h)
 
 AC_MSG_CHECKING(for special libxml2 includes)
 if test "x$XML2CONFIG" = "x"; then
    AC_MSG_ERROR(libxml2 config not found)
 else
    XML2HEAD="`$XML2CONFIG --cflags`"
    AC_MSG_RESULT($XML2HEAD)
    AC_CHECK_LIB(xml2, xmlReadMemory)
    AC_CHECK_LIB(xslt, xsltApplyStylesheet)
 fi
 
 CPPFLAGS="$CPPFLAGS $XML2HEAD"
 
 AC_CHECK_HEADERS(libxml/xpath.h)
 AC_CHECK_HEADERS(libxslt/xslt.h)
 if test "$ac_cv_header_libxml_xpath_h" != "yes"; then
    AC_MSG_ERROR(The libxml developement headers were not found)
 fi
 if test "$ac_cv_header_libxslt_xslt_h" != "yes"; then
    AC_MSG_ERROR(The libxslt developement headers were not found)
 fi
 
 dnl ========================================================================
 dnl Structures
 dnl ========================================================================
 
 AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include <time.h>]])
 AC_CHECK_MEMBERS([lrm_op_t.rsc_deleted],,,[[#include <lrm/lrm_api.h>]])
 
 dnl ========================================================================
 dnl Functions
 dnl ========================================================================
 
 AC_CHECK_FUNCS(g_log_set_default_handler)
 AC_CHECK_FUNCS(getopt, AC_DEFINE(HAVE_DECL_GETOPT,  1, [Have getopt function]))
 
 dnl ========================================================================
 dnl   ltdl
 dnl ========================================================================
 
 AC_CHECK_LIB(ltdl, lt_dlopen, [LTDL_foo=1])
 if test "x${enable_bundled_ltdl}" = "xyes"; then
    if test $ac_cv_lib_ltdl_lt_dlopen = yes; then
       AC_MSG_NOTICE([Disabling usage of installed ltdl])
    fi
    ac_cv_lib_ltdl_lt_dlopen=no
 fi
 
 LIBLTDL_DIR=""
 if test $ac_cv_lib_ltdl_lt_dlopen != yes ; then
    AC_MSG_NOTICE([Installing local ltdl])
    LIBLTDL_DIR=libltdl
    ( cd $srcdir ; $TAR -xvf libltdl.tar )
    if test "$?" -ne 0; then
      AC_MSG_ERROR([$TAR of libltdl.tar in $srcdir failed])
    fi
    AC_CONFIG_SUBDIRS(libltdl)
 else
    LIBS="$LIBS -lltdl"
    AC_MSG_NOTICE([Using installed ltdl])
    INCLTDL=""
    LIBLTDL=""
 fi
 
 AC_SUBST(INCLTDL)
 AC_SUBST(LIBLTDL)
 AC_SUBST(LIBLTDL_DIR)
 
 dnl ========================================================================
 dnl   bzip2
 dnl ========================================================================
 AC_CHECK_HEADERS(bzlib.h)
 AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress)
 
 if test x$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress != xyes ; then
    AC_MSG_ERROR(BZ2 libraries not found)
 fi
 
 if test x$ac_cv_header_bzlib_h != xyes; then
    AC_MSG_ERROR(BZ2 Development headers not found)
 fi
 
 
 dnl ========================================================================
 dnl   ncurses
 dnl ========================================================================
 dnl
 dnl A few OSes (e.g. Linux) deliver a default "ncurses" alongside "curses".
 dnl Many non-Linux deliver "curses"; sites may add "ncurses".
 dnl
 dnl However, the source-code recommendation for both is to #include "curses.h"
 dnl (i.e. "ncurses" still wants the include to be simple, no-'n', "curses.h").
 dnl
 dnl ncurse takes precedence.
 dnl
 AC_CHECK_HEADERS(curses.h)
 AC_CHECK_HEADERS(curses/curses.h)
 AC_CHECK_HEADERS(ncurses.h)
 AC_CHECK_HEADERS(ncurses/ncurses.h)
 
 dnl Although n-library is preferred, only look for it if the n-header was found.
 CURSESLIBS=''
 if test "$ac_cv_header_ncurses_h" = "yes"; then
   AC_CHECK_LIB(ncurses, printw,
     [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]
   )
 fi
 
 if test "$ac_cv_header_ncurses_ncurses_h" = "yes"; then
   AC_CHECK_LIB(ncurses, printw,
     [CURSESLIBS='-lncurses'; AC_DEFINE(HAVE_LIBNCURSES,1, have ncurses library)]
   )
 fi
 
 dnl Only look for non-n-library if there was no n-library.
 if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_h" = "yes"; then
   AC_CHECK_LIB(curses, printw,
     [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]
   )
 fi
 
 dnl Only look for non-n-library if there was no n-library.
 if test X"$CURSESLIBS" = X"" -a "$ac_cv_header_curses_curses_h" = "yes"; then
   AC_CHECK_LIB(curses, printw,
     [CURSESLIBS='-lcurses'; AC_DEFINE(HAVE_LIBCURSES,1, have curses library)]
   )
 fi
 
 if test "x$CURSESLIBS" != "x"; then
    PKG_FEATURES="$PKG_FEATURES ncurses"
 fi
 
 dnl Check for printw() prototype compatibility
 if test X"$CURSESLIBS" != X"" && cc_supports_flag -Wcast-qual && cc_supports_flag -Werror; then 
     AC_MSG_CHECKING(whether printw() requires argument of "const char *")
     ac_save_LIBS=$LIBS
     LIBS="$CURSESLIBS  $LIBS"
     ac_save_CFLAGS=$CFLAGS
     CFLAGS="-Wcast-qual -Werror"
 
     AC_LINK_IFELSE(
 	    [AC_LANG_PROGRAM(
 	      [
 #if defined(HAVE_CURSES_H)
 #  include <curses.h>
 #elif defined(HAVE_NCURSES_H)
 #  include <ncurses.h>
 #endif
 	      ],
 	      [printw((const char *)"Test");]
 	    )], 
 	    [ac_cv_compatible_printw=yes],
 	    [ac_cv_compatible_printw=no]
     )
 
     LIBS=$ac_save_LIBS
     CFLAGS=$ac_save_CFLAGS
 
     AC_MSG_RESULT([$ac_cv_compatible_printw])
 
     if test "$ac_cv_compatible_printw" = no; then
 		AC_MSG_WARN([The printw() function of your ncurses or curses library is old, we will disable usage of the library. If you want to use this library anyway, please update to newer version of the library, ncurses 5.4 or later is recommended. You can get the library from http://www.gnu.org/software/ncurses/.])
 		AC_MSG_NOTICE([Disabling curses])
 		AC_DEFINE(HAVE_INCOMPATIBLE_PRINTW, 1, [Do we have incompatible printw() in curses library?])
     fi
 fi
 
 AC_SUBST(CURSESLIBS)
 
 case $SUPPORT_TRACING in
      1|yes|true) SUPPORT_TRACING=1; PKG_FEATURES="$PKG_FEATURES trace-logging";;
      *) SUPPORT_TRACING=0;;
 esac
 AC_DEFINE_UNQUOTED(SUPPORT_TRACING, $SUPPORT_TRACING, Support the dynamic enablement of addition trace logging)
 
 
 dnl ========================================================================
 dnl    Cluster infrastructure - Heartbeat
 dnl ========================================================================
 
 dnl On Debian, AC_CHECK_LIBS fail if a library has any unresolved symbols
 dnl So check for all the depenancies (so they're added to LIBS) before checking for -lplumb
 
 AC_CHECK_LIB(pils, PILLoadPlugin)
 AC_CHECK_LIB(plumb, G_main_add_IPC_Channel)
 
 if test x"$ac_cv_lib_plumb_G_main_add_IPC_Channel" != x"yes"; then
    AC_MSG_FAILURE(Core Heartbeat utility libraries not found: $ac_cv_lib_plumb_G_main_add_IPC_Channel)
 fi
 
 dnl Compatability checks
 AC_CHECK_FUNCS(msgfromIPC_timeout)
 AC_CHECK_MEMBERS([struct lrm_ops.fail_rsc],,,[[#include <lrm/lrm_api.h>]])
 
 dnl ========================================================================
 dnl    Cluster stack - Heartbeat
 dnl ========================================================================
 
 case $SUPPORT_HEARTBEAT in
      1|yes|true) 
         AC_CHECK_LIB(hbclient, ll_cluster_new, 
    		[SUPPORT_HEARTBEAT=1], [AC_MSG_FAILURE(Unable to support Heartbeat: client libraries not found)]);;
      try)
         AC_CHECK_LIB(hbclient, ll_cluster_new, 
    		[SUPPORT_HEARTBEAT=1], [SUPPORT_HEARTBEAT=0]);;
      *) SUPPORT_HEARTBEAT=0;;
 esac
 
 AM_CONDITIONAL(BUILD_HEARTBEAT_SUPPORT, test $SUPPORT_HEARTBEAT = 1)
 AC_DEFINE_UNQUOTED(SUPPORT_HEARTBEAT, $SUPPORT_HEARTBEAT, Support the Heartbeat messaging and membership layer)
 
 
 dnl ========================================================================
 dnl    Cluster stack - Corosync
 dnl ========================================================================
 
 CSLIB=""
 
 dnl Normalize the values
 case $SUPPORT_CS in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *) SUPPORT_CS=no;;
 esac
 
 AC_MSG_CHECKING(for native corosync)
 AISMSGLIB=""
 CS_VERSION="none"
 COROSYNC_PKG="$PKGCONFIG libcoroipcc"
 
 if test $SUPPORT_CS = no; then
    AC_MSG_RESULT(no... not requested.)
 
 else
    AC_MSG_RESULT($SUPPORT_CS, with '$CSPREFIX')
 
    AC_CHECK_HEADERS(openais/saAis.h)
    AC_CHECK_HEADERS(corosync/coroipcc.h)
 
    $COROSYNC_PKG --exists
    if test $? = 0; then
        CS_VERSION="corosync"
    else
        aisreason="Corosync installation not found by pkg_config"
    fi  
 fi
 
 if test $CS_VERSION != "none"; then
    AC_MSG_CHECKING(for Corosync branch)
    AC_MSG_RESULT($CS_VERSION)
 fi
 
 if test $CS_VERSION = "corosync"; then
    if test "$ac_cv_header_corosync_coroipcc_h" != "yes"; then
        CS_VERSION="none"
        aisreason="Corosync headers not found"
    fi
 
    saveLIBS="$LIBS"
    LIBS="$LIBS `$COROSYNC_PKG --libs-only-L`"
    AC_CHECK_LIB(coroipcc, coroipcc_msg_send_reply_receive, [])
    LIBS="$saveLIBS"
 
    if test $ac_cv_lib_coroipcc_coroipcc_msg_send_reply_receive != yes; then
         AC_MSG_RESULT(Cannot locate corosync messaging library)
 	aisreason="requred Corosync libraries not found"
         CS_VERSION="none"
    fi
 
 fi
 
 SUPPORT_CS=1
 case $CS_VERSION in
     corosync)
 	AC_DEFINE_UNQUOTED(SUPPORT_COROSYNC, 1, Support the Corosync messaging and membership layer)
    	LCRSODIR=`$PKGCONFIG corosync --variable=lcrsodir`
    	CFLAGS="$CFLAGS `$COROSYNC_PKG --cflags`"
 	CSMSGLIB=`$COROSYNC_PKG --libs`
 	;;
     none)
      	SUPPORT_CS=0
 	if test "x$aisreason" != x; then
      	  if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support Corosync: $aisreason) 
           else
 	    AC_MSG_FAILURE(Unable to support Corosync: $aisreason) 
           fi
         fi
 	;;
     *) AC_MSG_FAILURE(Unknown Corosync branch: $CS_VERSION);;
 esac
 
 AC_DEFINE_UNQUOTED(AIS_COROSYNC, $SUPPORT_CS, Compatability alias for SUPPORT_COROSYNC)
 AC_DEFINE_UNQUOTED(SUPPORT_AIS, $SUPPORT_CS, Compatability alias for SUPPORT_COROSYNC)
 AM_CONDITIONAL(BUILD_CS_SUPPORT, test $SUPPORT_CS = 1)
 
 PCMK_SERVICE_ID=9
 if test $SUPPORT_CMAN != no; then
     AC_MSG_CHECKING(for cman)
     $PKGCONFIG libcman --exists
     if test $? = 0; then
 	AC_MSG_RESULT(yes)
     else
 	AC_MSG_RESULT(no)
     fi
 
     AC_MSG_CHECKING(for cpg)
     $PKGCONFIG libcpg --exists
     if test $? = 0; then
 	AC_MSG_RESULT(yes)
     else
 	AC_MSG_RESULT(no)
     fi
 
     AC_MSG_CHECKING(for fenced)
     $PKGCONFIG libfenced --exists
     if test $? = 0; then
 	AC_MSG_RESULT(yes)
     else
 	AC_MSG_RESULT(no)
     fi
 
     $PKGCONFIG libcpg libcman libfenced --exists
     if test $? = 0; then
 	CFLAGS="$CFLAGS `$PKGCONFIG libcpg libcman libfenced --cflags`"
 	CSMSGLIB="$CSMSGLIB `$PKGCONFIG libcpg libcman libfenced --libs`"
 	
 	PKG_FEATURES="$PKG_FEATURES cman"
 	AC_DEFINE_UNQUOTED(SUPPORT_CMAN, 1, Support the consumption of membership and quorum from cman)
     fi
 fi
 AC_DEFINE_UNQUOTED(PCMK_SERVICE_ID, $PCMK_SERVICE_ID, Corosync service number)
 
 if test $SUPPORT_CS_QUORUM != no; then
     AC_MSG_CHECKING(for cpg)
     $PKGCONFIG libcpg --exists
     if test $? = 0; then
 	AC_MSG_RESULT(yes)
     else
 	AC_MSG_RESULT(no)
     fi
 
     AC_MSG_CHECKING(for quorum)
     $PKGCONFIG libquorum --exists
     if test $? = 0; then
 	AC_MSG_RESULT(yes)
     else
 	AC_MSG_RESULT(no)
     fi
 
     $PKGCONFIG libcpg libquorum --exists
     if test $? = 0; then
 	CFLAGS="$CFLAGS `$PKGCONFIG libcpg libquorum --cflags`"
 	CSMSGLIB="$CSMSGLIB `$PKGCONFIG libcpg libquorum --libs`"
 	
 	PKG_FEATURES="$PKG_FEATURES cs-quorum"
 	AC_DEFINE_UNQUOTED(SUPPORT_CS_QUORUM, 1, Support the consumption of membership and quorum from corosync)
     fi
 fi
 
 dnl
 dnl    Cluster stack - Sanity
 dnl
 
 STACKS=""
 CLUSTERLIBS=""
 if test $SUPPORT_HEARTBEAT = 1; then
    STACKS="$STACKS heartbeat"
    CLUSTERLIBS="$CLUSTERLIBS -lhbclient -lccmclient"
 fi
 
 if test $SUPPORT_CS = 1; then
    STACKS="$STACKS $CS_VERSION"
    CLUSTERLIBS="$CLUSTERLIBS ${CSMSGLIB}"
 else
    CSPREFIX=""
    LCRSODIR="$libdir"
 fi
 
 PKG_FEATURES="$PKG_FEATURES$STACKS"
 
 AC_MSG_CHECKING(for supported stacks)
 if test x"$STACKS" = x; then
    AC_MSG_FAILURE(You must choose at least one cluster stack to support)
 fi
 AC_MSG_RESULT($STACKS)
 
 AC_SUBST(CLUSTERLIBS)
 AC_SUBST(LCRSODIR)
 
 dnl ========================================================================
 dnl    SNMP
 dnl ========================================================================
 
 case $SUPPORT_SNMP in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *)		 SUPPORT_SNMP=no;;
 esac
 
 SNMPLIBS=""
 
 AC_MSG_CHECKING(for snmp support)
 if test $SUPPORT_SNMP = no; then
    AC_MSG_RESULT(no... not requested.)
    SUPPORT_SNMP=0
 else
    SNMPCONFIG=""
    AC_MSG_RESULT($SUPPORT_SNMP)
    AC_CHECK_HEADERS(net-snmp/net-snmp-config.h)
 
    if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then
 	SUPPORT_SNMP="no"
    fi
 
    if test $SUPPORT_SNMP != no; then
 	AC_PATH_PROGS(SNMPCONFIG, net-snmp-config)
 	if test "X${SNMPCONFIG}" = "X"; then
 		AC_MSG_RESULT(You need the net_snmp development package to continue.)
 		SUPPORT_SNMP=no
 	fi
    fi
 
    if test $SUPPORT_SNMP != no; then
 	AC_MSG_CHECKING(for special snmp libraries)
 	SNMPLIBS=`$SNMPCONFIG --agent-libs`
 	AC_MSG_RESULT($SNMPLIBS)
    fi
 
    if test $SUPPORT_SNMP != no; then
       savedLibs=$LIBS
       LIBS="$LIBS $SNMPLIBS"
       AC_CHECK_FUNCS(netsnmp_transport_open_client)
       if test $ac_cv_func_netsnmp_transport_open_client != yes; then
          AC_CHECK_FUNCS(netsnmp_tdomain_transport)
          if test $ac_cv_func_netsnmp_tdomain_transport != yes; then
             SUPPORT_SNMP=no
 	 else
             AC_DEFINE_UNQUOTED(NETSNMPV53, 1, [Use the older 5.3 version of the net-snmp API])
          fi
       fi
       LIBS=$savedLibs
    fi
 
    if test $SUPPORT_SNMP = no; then
    	SNMPLIBS=""
    	SUPPORT_SNMP=0
      	if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support SNMP) 
         else
 	    AC_MSG_FAILURE(Unable to support SNMP) 
         fi
    else
    	SUPPORT_SNMP=1
    fi
 fi
 
 if test $SUPPORT_SNMP = 1; then
    PKG_FEATURES="$PKG_FEATURES snmp"
 fi
 
 AC_SUBST(SNMPLIBS)
 AM_CONDITIONAL(ENABLE_SNMP, test "$SUPPORT_SNMP" = "1")
 AC_DEFINE_UNQUOTED(ENABLE_SNMP, $SUPPORT_SNMP, Build in support for sending SNMP traps)
 
 dnl ========================================================================
 dnl    ESMTP
 dnl ========================================================================
 
 case $SUPPORT_ESMTP in
      1|yes|true) missingisfatal=1;;
      try)        missingisfatal=0;;
      *)		 SUPPORT_ESMTP=no;;
 esac
 
 ESMTPLIB=""
 
 AC_MSG_CHECKING(for esmtp support)
 if test $SUPPORT_ESMTP = no; then
    AC_MSG_RESULT(no... not requested.)
    SUPPORT_ESMTP=0
 else
    ESMTPCONFIG=""
    AC_MSG_RESULT($SUPPORT_ESMTP)
    AC_CHECK_HEADERS(libesmtp.h)
 
    if test "x${ac_cv_header_libesmtp_h}" != "xyes"; then
 	ENABLE_ESMTP="no"
    fi
 
    if test $SUPPORT_ESMTP != no; then
 	AC_PATH_PROGS(ESMTPCONFIG, libesmtp-config)
 	if test "X${ESMTPCONFIG}" = "X"; then
 		AC_MSG_RESULT(You need the libesmtp development package to continue.)
 		SUPPORT_ESMTP=no
 	fi
    fi
 
    if test $SUPPORT_ESMTP != no; then
 	AC_MSG_CHECKING(for special esmtp libraries)
 	ESMTPLIBS=`$ESMTPCONFIG --libs | tr '\n' ' '`
 	AC_MSG_RESULT($ESMTPLIBS)
    fi
 
    if test $SUPPORT_ESMTP = no; then
    	SUPPORT_ESMTP=0
      	if test $missingisfatal = 0; then
 	    AC_MSG_WARN(Unable to support ESMTP) 
         else
 	    AC_MSG_FAILURE(Unable to support ESMTP) 
         fi
    else
    	SUPPORT_ESMTP=1
    fi
 fi
 
 if test $SUPPORT_ESMTP = 1; then
    PKG_FEATURES="$PKG_FEATURES libesmtp"
 fi
 
 AC_SUBST(ESMTPLIBS)
 AM_CONDITIONAL(ENABLE_ESMTP, test "$SUPPORT_ESMTP" = "1")
 AC_DEFINE_UNQUOTED(ENABLE_ESMTP, $SUPPORT_ESMTP, Build in support for sending mail notifications with ESMTP)
 
+dnl ========================================================================
+dnl    ACL 
+dnl ========================================================================
+
+case $SUPPORT_ACL in
+     1|yes|true) missingisfatal=1;;
+     try)        missingisfatal=0;;
+     *)		 SUPPORT_ACL=no;;
+esac
+
+AC_MSG_CHECKING(for acl support)
+if test $SUPPORT_ACL = no; then
+   AC_MSG_RESULT(no... not requested.)
+   SUPPORT_ACL=0
+else
+   AC_MSG_RESULT($SUPPORT_ACL)
+
+   AC_CHECK_MEMBERS([struct IPC_CHANNEL.farside_uid],
+		    [SUPPORT_ACL=yes], [SUPPORT_ACL=no], [[#include <clplumbing/ipc.h>]])
+
+   if test $SUPPORT_ACL = no; then
+   	SUPPORT_ACL=0
+     	if test $missingisfatal = 0; then
+	    AC_MSG_WARN(Unable to support ACL. You need to use cluster-glue >= 1.0.6) 
+        else
+	    AC_MSG_FAILURE(Unable to support ACL. You need to use cluster-glue >= 1.0.6) 
+        fi
+   else
+   	SUPPORT_ACL=1
+   fi
+fi
+
+if test $SUPPORT_ACL = 1; then
+   PKG_FEATURES="$PKG_FEATURES acl"
+fi
+
+AM_CONDITIONAL(ENABLE_ACL, test "$SUPPORT_ACL" = "1")
+AC_DEFINE_UNQUOTED(ENABLE_ACL, $SUPPORT_ACL, Build in support for CIB ACL)
+
 dnl ========================================================================
 dnl    GnuTLS
 dnl ========================================================================
 
 AC_CHECK_HEADERS(gnutls/gnutls.h)
 AC_CHECK_HEADERS(security/pam_appl.h pam/pam_appl.h)
 
 dnl GNUTLS library: Attempt to determine by 'libgnutls-config' program.
 dnl If no 'libgnutls-config', try traditional autoconf means.
 AC_PATH_PROGS(LIBGNUTLS_CONFIG, libgnutls-config)
 
 if test -n "$LIBGNUTLS_CONFIG"; then
 	AC_MSG_CHECKING(for gnutls header flags)
 	GNUTLSHEAD="`$LIBGNUTLS_CONFIG --cflags`";
 	AC_MSG_RESULT($GNUTLSHEAD)
 	AC_MSG_CHECKING(for gnutls library flags)
 	GNUTLSLIBS="`$LIBGNUTLS_CONFIG --libs`";
 	AC_MSG_RESULT($GNUTLSLIBS)
 else
 	AC_CHECK_LIB(gnutls, gnutls_init)
 fi
 AC_SUBST(GNUTLSHEAD)
 AC_SUBST(GNUTLSLIBS)
 
 
 dnl ========================================================================
 dnl    System Health
 dnl ========================================================================
 
 dnl Check if servicelog development package is installed
 SERVICELOG=servicelog-1
 SERVICELOG_EXISTS="no"
 AC_MSG_CHECKING(for $SERVICELOG packages)
 if
     $PKGCONFIG --exists $SERVICELOG
 then
     SERVICELOG_EXISTS="yes"
 fi
 AC_MSG_RESULT($SERVICELOG_EXISTS)
 AM_CONDITIONAL(BUILD_SERVICELOG, test "$SERVICELOG_EXISTS" = "yes")
 
 dnl Check if OpenIMPI packages and servicelog are installed
 OPENIPMI="OpenIPMI OpenIPMIposix"
 OPENIPMI_SERVICELOG_EXISTS="no"
 AC_MSG_CHECKING(for $SERVICELOG $OPENIPMI packages)
 if
     $PKGCONFIG --exists $OPENIPMI $SERVICELOG
 then
     OPENIPMI_SERVICELOG_EXISTS="yes"
 fi
 AC_MSG_RESULT($OPENIPMI_SERVICELOG_EXISTS)
 AM_CONDITIONAL(BUILD_OPENIPMI_SERVICELOG, test "$OPENIPMI_SERVICELOG_EXISTS" = "yes")
 
 dnl ========================================================================
 dnl checks for library functions to replace them
 dnl
 dnl     NoSuchFunctionName:
 dnl             is a dummy function which no system supplies.  It is here to make
 dnl             the system compile semi-correctly on OpenBSD which doesn't know
 dnl             how to create an empty archive
 dnl
 dnl     scandir: Only on BSD.
 dnl             System-V systems may have it, but hidden and/or deprecated.
 dnl             A replacement function is supplied for it.
 dnl
 dnl     setenv: is some bsdish function that should also be avoided (use
 dnl             putenv instead)
 dnl             On the other hand, putenv doesn't provide the right API for the
 dnl             code and has memory leaks designed in (sigh...)  Fortunately this
 dnl             A replacement function is supplied for it.
 dnl
 dnl     strerror: returns a string that corresponds to an errno.
 dnl             A replacement function is supplied for it.
 dnl
 dnl     unsetenv: is some bsdish function that should also be avoided (No 
 dnl             replacement)
 dnl             A replacement function is supplied for it.
 dnl
 dnl	strnlen: is a gnu function similar to strlen, but safer.
 dnl		We wrote a tolearably-fast replacement function for it.
 dnl
 dnl	strndup: is a gnu function similar to strdup, but safer.
 dnl		We wrote a tolearably-fast replacement function for it.
 dnl
 dnl	daemon: is a GNU function.  The daemon() function is for programs wishing to
 dnl             detach themselves from the controlling terminal and run in the
 dnl             background as system daemon
 dnl             A replacement function is supplied for it.
 
 AC_REPLACE_FUNCS(alphasort inet_pton NoSuchFunctionName scandir setenv strerror unsetenv strnlen strndup daemon strlcpy strlcat)
 
 dnl ========================================================================
 dnl Compiler flags
 dnl ========================================================================
 
 dnl Make sure that CFLAGS is not exported. If the user did
 dnl not have CFLAGS in their environment then this should have
 dnl no effect. However if CFLAGS was exported from the user's
 dnl environment, then the new CFLAGS will also be exported
 dnl to sub processes.
 
 CC_ERRORS=""
 CC_EXTRAS=""
 
 if export | fgrep " CFLAGS=" > /dev/null; then
 	SAVED_CFLAGS="$CFLAGS"
 	unset CFLAGS
 	CFLAGS="$SAVED_CFLAGS"
 	unset SAVED_CFLAGS
 fi
 
 if test "$GCC" != yes; then
         CFLAGS="$CFLAGS -g"
 	enable_fatal_warnings=no
 else
         CFLAGS="$CFLAGS -ggdb3 -O0"
 
 	# We had to eliminate -Wnested-externs because of libtool changes
         EXTRA_FLAGS="-fgnu89-inline
 		-fstack-protector-all
 		-Wall
 		-Waggregate-return
 		-Wbad-function-cast 
 		-Wcast-align 
 		-Wdeclaration-after-statement
 		-Wendif-labels
 		-Wfloat-equal
 		-Wformat=2
 		-Wformat-security
 		-Wformat-nonliteral
 		-Winline
 		-Wmissing-prototypes 
 		-Wmissing-declarations 
 		-Wnested-externs
 		-Wno-long-long
 		-Wno-strict-aliasing
 		-Wpointer-arith 
 		-Wstrict-prototypes
     		-Wunsigned-char
 		-Wwrite-strings"
 
 # Additional warnings it might be nice to enable one day
 #		-Wshadow
 #		-Wunreachable-code
 
 	for j in $EXTRA_FLAGS
 	do
 	  if
 	    cc_supports_flag $j
 	  then
 	    CC_EXTRAS="$CC_EXTRAS $j"
 	  fi
 	done
 
 dnl In lib/ais/Makefile.am there's a gcc option available as of v4.x
 
 	GCC_MAJOR=`gcc -v 2>&1 | awk 'END{print $3}' | sed 's/[.].*//'`
 	AM_CONDITIONAL(GCC_4, test "${GCC_MAJOR}" = 4)
 
 dnl System specific options
 
 	case "$host_os" in
   	*linux*|*bsd*)
 		if test "${enable_fatal_warnings}" = "unknown"; then
         		enable_fatal_warnings=yes
         	fi
           	;;
 	esac
 
 	if test "x${enable_fatal_warnings}" != xno && cc_supports_flag -Werror ; then
 	   enable_fatal_warnings=yes
 	else
 	   enable_fatal_warnings=no
         fi
 
 	if test "x${enable_ansi}" = xyes && cc_supports_flag -std=iso9899:199409 ; then
 	  AC_MSG_NOTICE(Enabling ANSI Compatibility)
 	  CC_EXTRAS="$CC_EXTRAS -ansi -D_GNU_SOURCE -DANSI_ONLY"
 	fi
 
   	AC_MSG_NOTICE(Activated additional gcc flags: ${CC_EXTRAS})
 fi
 
 CFLAGS="$CFLAGS $CC_EXTRAS"
 
 NON_FATAL_CFLAGS="$CFLAGS"
 AC_SUBST(NON_FATAL_CFLAGS)
 
 dnl
 dnl We reset CFLAGS to include our warnings *after* all function
 dnl checking goes on, so that our warning flags don't keep the
 dnl AC_*FUNCS() calls above from working.  In particular, -Werror will
 dnl *always* cause us troubles if we set it before here.
 dnl
 dnl
 if test "x${enable_fatal_warnings}" = xyes ; then
    AC_MSG_NOTICE(Enabling Fatal Warnings)
    CFLAGS="$CFLAGS -Werror"
 fi
 AC_SUBST(CFLAGS)
 
 dnl This is useful for use in Makefiles that need to remove one specific flag
 CFLAGS_COPY="$CFLAGS"
 AC_SUBST(CFLAGS_COPY)
 
 AC_SUBST(LIBADD_DL)	dnl extra flags for dynamic linking libraries
 AC_SUBST(LIBADD_INTL)	dnl extra flags for GNU gettext stuff...
 
 AC_SUBST(LOCALE)
 
 dnl Options for cleaning up the compiler output 
 QUIET_LIBTOOL_OPTS=""
 QUIET_MAKE_OPTS=""
 if test "x${enable_quiet}" = "xyes"; then
    QUIET_LIBTOOL_OPTS="--quiet"
    QUIET_MAKE_OPTS="--quiet"
 fi
 
 AC_MSG_RESULT(Supress make details: ${enable_quiet})
 
 dnl Put the above variables to use
 LIBTOOL="${LIBTOOL} --tag=CC \$(QUIET_LIBTOOL_OPTS)"
 MAKE="${MAKE} \$(QUIET_MAKE_OPTS)"
 
 AC_SUBST(CC)
 AC_SUBST(MAKE)
 AC_SUBST(LIBTOOL)
 AC_SUBST(QUIET_MAKE_OPTS)
 AC_SUBST(QUIET_LIBTOOL_OPTS)
 AC_DEFINE_UNQUOTED(CRM_FEATURES, "$PKG_FEATURES", Set of enabled features)
 AC_SUBST(PKG_FEATURES)
 
 dnl The Makefiles and shell scripts we output
 AC_CONFIG_FILES(Makefile				        \
 cts/Makefile					        	\
 	cts/CTSvars.py						\
 	cts/LSBDummy						\
 	cts/benchmark/Makefile					\
 		cts/benchmark/clubench				\
 cib/Makefile							\
 crmd/Makefile							\
 pengine/Makefile						\
 	pengine/regression.core.sh				\
 doc/Makefile							\
 	doc/Pacemaker_Explained/publican.cfg			\
 	doc/Clusters_from_Scratch/publican.cfg			\
 include/Makefile						\
 	include/crm/Makefile					\
 		include/crm/common/Makefile			\
 		include/crm/pengine/Makefile			\
 replace/Makefile						\
 lib/Makefile							\
 	lib/ais/Makefile					\
 	lib/common/Makefile					\
 	lib/cib/Makefile					\
 	lib/pengine/Makefile					\
 	lib/transition/Makefile					\
 	lib/fencing/Makefile					\
 	lib/plugins/Makefile					\
 		lib/plugins/lrm/Makefile			\
 mcp/Makefile							\
 	mcp/pacemaker						\
 fencing/Makefile                                                \
 extra/Makefile							\
 	extra/resources/Makefile				\
 tools/Makefile							\
 	tools/crm_report					\
 	tools/hb2openais.sh					\
 	tools/crm_primitive.py					\
 shell/Makefile							\
 	shell/templates/Makefile				\
 	shell/regression/Makefile				\
 	shell/regression/testcases/Makefile			\
 	shell/modules/Makefile					\
 	shell/modules/ui.py					\
 	shell/modules/ra.py					\
 	shell/modules/vars.py					\
 	shell/modules/help.py					\
 xml/Makefile							\
 		)
 
 dnl Now process the entire list of files added by previous 
 dnl  calls to AC_CONFIG_FILES()
 AC_OUTPUT()
 
 dnl *****************
 dnl Configure summary
 dnl *****************
 
 AC_MSG_RESULT([])
 AC_MSG_RESULT([$PACKAGE configuration:])
 AC_MSG_RESULT([  Version                  = ${VERSION} (Build: $BUILD_VERSION)])
 AC_MSG_RESULT([  Features                 =${PKG_FEATURES}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  Prefix                   = ${prefix}])
 AC_MSG_RESULT([  Executables              = ${sbindir}])
 AC_MSG_RESULT([  Man pages                = ${mandir}])
 AC_MSG_RESULT([  Libraries                = ${libdir}])
 AC_MSG_RESULT([  Header files             = ${includedir}])
 AC_MSG_RESULT([  Arch-independent files   = ${datadir}])
 AC_MSG_RESULT([  State information        = ${localstatedir}])
 AC_MSG_RESULT([  System configuration     = ${sysconfdir}])
 AC_MSG_RESULT([  Corosync Plugins         = ${LCRSODIR}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  Use system LTDL          = ${ac_cv_lib_ltdl_lt_dlopen}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  HA group name            = ${CRM_DAEMON_GROUP}])
 AC_MSG_RESULT([  HA user name             = ${CRM_DAEMON_USER}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([  CFLAGS                   = ${CFLAGS}])
 AC_MSG_RESULT([  Libraries                = ${LIBS}])
 AC_MSG_RESULT([  Stack Libraries          = ${CLUSTERLIBS}])
 
diff --git a/lib/cib/Makefile.am b/lib/cib/Makefile.am
index f4eee720f5..aa00cb1802 100644
--- a/lib/cib/Makefile.am
+++ b/lib/cib/Makefile.am
@@ -1,39 +1,42 @@
 #
 # Copyright (C) 2004 Andrew Beekhof
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # as published by the Free Software Foundation; either version 2
 # of the License, or (at your option) any later version.
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #
 MAINTAINERCLEANFILES    = Makefile.in
 
 INCLUDES        = -I$(top_builddir)/include  -I$(top_srcdir)/include  \
 		  -I$(top_builddir)/libltdl  -I$(top_srcdir)/libltdl
 
 ## libraries
 lib_LTLIBRARIES	= libcib.la
 
 ## SOURCES
 noinst_HEADERS		= cib_private.h
 libcib_la_SOURCES	= cib_ops.c cib_utils.c cib_client.c cib_native.c cib_attrs.c \
-			cib_version.c cib_file.c cib_remote.c cib_acl.c
+			cib_version.c cib_file.c cib_remote.c
+if ENABLE_ACL
+libcib_la_SOURCES       += cib_acl.c
+endif
 
 libcib_la_LDFLAGS	= -version-info 1:1:0 $(top_builddir)/lib/common/libcrmcommon.la $(CRYPTOLIB)
 libcib_la_CFLAGS	= -I$(top_srcdir)
 
 clean-generic:
 	rm -f *.log *.debug *.xml *~
 
 install-exec-local:
 
 uninstall-local:
diff --git a/lib/cib/cib_acl.c b/lib/cib/cib_acl.c
index 8bfb275588..34c7b662c3 100644
--- a/lib/cib/cib_acl.c
+++ b/lib/cib/cib_acl.c
@@ -1,735 +1,737 @@
 /* 
  * Copyright (C) 2009 Yan Gao <ygao@novell.com>
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  * 
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <crm_internal.h>
+
 #include <pwd.h>
 
 #include <crm/cib.h>
 #include <cib_private.h>
 
 typedef struct acl_obj_s
 {
 	const char *mode;
 	const char *tag;
 	const char *ref;
 	const char *xpath;
 	const char *attribute;
 } acl_obj_t;
 
 typedef struct xml_perm_s
 {
 	const char *mode;
 	GHashTable *attribute_perms;
 } xml_perm_t;
 
 static gboolean req_by_superuser(xmlNode *request);
 
 static gboolean unpack_user_acl(xmlNode *xml_acls, const char *user, GListPtr *user_acl);
 static gboolean user_match(const char *user, const char *uid);
 static gboolean unpack_acl(xmlNode *xml_acls, xmlNode *xml_acl, GListPtr *acl);
 static gboolean unpack_role_acl(xmlNode *xml_acls, const char *role, GListPtr *acl);
 static gboolean acl_append(xmlNode *acl_child, GListPtr *acl);
 static void free_acl(GListPtr acl);
 static gboolean parse_acl_xpath(xmlNode *xml, GListPtr acl, GListPtr *parsed_acl);
 
 static gboolean gen_xml_perms(xmlNode *xml, GListPtr acl, GHashTable **xml_perms);
 static int search_xml_children(GListPtr *children, xmlNode *root,
                   const char *tag, const char *field, const char *value,
                   gboolean search_matches);
 static int search_xpath_objects(GListPtr *objects, xmlNode *xml_obj, const char *xpath);
 static gboolean update_xml_perms(xmlNode *xml, acl_obj_t *acl_obj, GHashTable *xml_perms);
 static gboolean update_xml_children_perms(xmlNode *xml, const char *mode, GHashTable *xml_perms);
 static void free_xml_perm(gpointer xml_perm);
 
 static gboolean acl_filter_xml(xmlNode *xml, GHashTable *xml_perms);
 static gboolean acl_check_diff_xml(xmlNode *xml, GHashTable *xml_perms);
 
 
 /* rc = TRUE if orig_cib has been filtered*/
 /* That means *filtered_cib rather than orig_cib should be exploited afterwards*/
 gboolean
 acl_filter_cib(xmlNode *request, xmlNode *current_cib, xmlNode *orig_cib, xmlNode **filtered_cib)
 {
 	const char *user = NULL;
 	xmlNode *xml_acls = NULL;
 	xmlNode *tmp_cib = NULL;
 	GListPtr user_acl = NULL;
 	GHashTable *xml_perms = NULL;
 
 	*filtered_cib = NULL;
 
 	if (req_by_superuser(request)) {
 		return FALSE;
 	}
 
 	if (orig_cib == NULL) {
 		return FALSE;
 	}
 
 	if (current_cib == NULL) {
 		return TRUE;
 	}
 
 	user = crm_element_value(request, F_CIB_USER);
 	if (user == NULL) {
 		crm_warn("Cannot identify the client user");
 		return TRUE;
 	}
 
 	xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib);
 	if (xml_acls == NULL) {
 		crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user);
 		return TRUE;
 	}
 
 	unpack_user_acl(xml_acls, user, &user_acl);
 
 	tmp_cib = copy_xml(orig_cib);
 
 	gen_xml_perms(tmp_cib, user_acl, &xml_perms);
 
 	if (acl_filter_xml(tmp_cib, xml_perms)) {
 		crm_warn("User '%s' doesn't have the permission for the whole CIB", user);
 		tmp_cib = NULL;
 	}
 
 	g_hash_table_destroy(xml_perms);
 	free_acl(user_acl);
 	
 	*filtered_cib = tmp_cib;
 	return TRUE;
 }
 
 /* rc = TRUE if the request passes the ACL check */
 /* rc = FALSE if the permission is denied */
 gboolean
 acl_check_diff(xmlNode *request, xmlNode *current_cib, xmlNode *result_cib, xmlNode *diff)
 {
 	const char *user = NULL;
 	xmlNode *xml_acls = NULL;
 	GListPtr user_acl = NULL;
 	int rc = FALSE;
 
 	if (req_by_superuser(request)) {
 		return TRUE;
 	}
 
 	if (diff == NULL) {
 		return TRUE;
 	}
 
 	if (current_cib == NULL) {
 		return FALSE;
 	}
 
 	user = crm_element_value(request, F_CIB_USER);
 	if (user == NULL) {
 		crm_warn("Cannot identify the client user");
 		return FALSE;
 	}
 
 	xml_acls = get_object_root(XML_CIB_TAG_ACLS, current_cib);
 	if (xml_acls == NULL) {
 		crm_warn("Ordinary users cannot access the CIB without any defined ACLs: '%s'", user);
 		return FALSE;
 	}
 
 	unpack_user_acl(xml_acls, user, &user_acl);
 
 	xml_child_iter(
 		diff, diff_child,
 		const char *tag = crm_element_name(diff_child);
 		GListPtr parsed_acl = NULL;
 
 		crm_debug("Preparing ACL checking on '%s'", tag);
 
 		if (crm_str_eq(tag, XML_TAG_DIFF_REMOVED, TRUE)) {
 			crm_debug("Parsing any xpaths under the ACL according to the current CIB");
 			parse_acl_xpath(current_cib, user_acl, &parsed_acl);
 		} else if (crm_str_eq(tag, XML_TAG_DIFF_ADDED, TRUE)) {
 			crm_debug("Parsing any xpaths under the ACL according to the result CIB");
 			parse_acl_xpath(result_cib, user_acl, &parsed_acl);
 		} else {
 			continue;
 		}
 
 		xml_child_iter(
 			diff_child, diff_cib,
 			GHashTable *xml_perms = NULL;
 
 			gen_xml_perms(diff_cib, parsed_acl, &xml_perms);
 			rc = acl_check_diff_xml(diff_cib, xml_perms);
 			g_hash_table_destroy(xml_perms);
 
 			if (rc == FALSE) {
 				crm_warn("User '%s' doesn't have enough permission to modify the CIB objects", user);
 				goto done;
 			}
 			);
 		free_acl(parsed_acl);
 		);
 
 done:
 	free_acl(user_acl);
 	return rc;
 }
 
 static gboolean
 req_by_superuser(xmlNode *request)
 {
 	const char *user = crm_element_value(request, F_CIB_USER);
 	if (crm_str_eq(user, CRM_DAEMON_USER, TRUE)
 			|| crm_str_eq(user, "root", TRUE)) {
 		return TRUE;
 	}
 	return FALSE;
 }
 
 static gboolean
 unpack_user_acl(xmlNode *xml_acls, const char *user, GListPtr *user_acl)
 {
 	if (xml_acls == NULL) {
 		return FALSE;
 	}
 	
 	xml_child_iter(
         	xml_acls, xml_acl,
 		const char *tag = crm_element_name(xml_acl);
 		const char *id = crm_element_value(xml_acl, XML_ATTR_ID);
 
 		if (crm_str_eq(tag, XML_ACL_TAG_USER, TRUE)) {
 			if (user_match(user, id)) {
 				crm_debug("Unpacking ACL of user: '%s'", id);
 				unpack_acl(xml_acls, xml_acl, user_acl);
 				return TRUE;
 			}
 		}
 		);
 	return FALSE;
 }
 
 static gboolean
 user_match(const char *user, const char *uid)
 {
 	struct passwd *pwent = NULL;
 	int user_uid_num = -1;
 	int uid_num = -1;
 
 	if (crm_str_eq(user, uid, TRUE)) {
 		return TRUE;
 	}
 
 	pwent = getpwnam(user);
 	if (pwent == NULL) {
 		crm_warn("No user named '%s' exists!", user);
 		return FALSE;
 	}
 	user_uid_num = pwent->pw_uid;
 
 	uid_num = crm_int_helper(uid, NULL);
 	if(errno == 0 && uid_num == user_uid_num) {
 		return TRUE;
         }
 
 	return FALSE;
 }
 
 static gboolean
 unpack_acl(xmlNode *xml_acls, xmlNode *xml_acl, GListPtr *acl)
 {
 	const char *role = crm_element_value(xml_acl, XML_ACL_ATTR_ROLE_REF);
 
 	if (role) {
 		unpack_role_acl(xml_acls, role, acl);
 	}
 
 	xml_child_iter(
 		xml_acl, acl_child,
 		const char *tag = crm_element_name(acl_child);
 
 		if (crm_str_eq(XML_ACL_TAG_READ, tag, TRUE)
 			|| crm_str_eq(XML_ACL_TAG_WRITE, tag, TRUE)
 			|| crm_str_eq(XML_ACL_TAG_DENY, tag, TRUE))
 				acl_append(acl_child, acl);
 		);
 	return TRUE;
 }
 
 static gboolean
 unpack_role_acl(xmlNode *xml_acls, const char *role, GListPtr *acl)
 {
 	xml_child_iter_filter(
         	xml_acls, xml_acl, XML_ACL_TAG_ROLE,
 		const char *role_id = crm_element_value(xml_acl, XML_ATTR_ID);
 
 		if (role_id && crm_str_eq(role, role_id, TRUE)) {
 			crm_debug("Unpacking ACL of the referenced role: '%s'", role);
 			unpack_acl(xml_acls, xml_acl, acl);
 			return TRUE;
 		}
 		);
 	return FALSE;
 }
 
 static gboolean
 acl_append(xmlNode *acl_child, GListPtr *acl)
 {
 	acl_obj_t *acl_obj = NULL;
 
 	const char *tag = crm_element_value(acl_child, XML_ACL_ATTR_TAG);
 	const char *ref = crm_element_value(acl_child, XML_ACL_ATTR_REF);
 	const char *xpath = crm_element_value(acl_child, XML_ACL_ATTR_XPATH);
 
 	if (tag == NULL && ref == NULL && xpath == NULL) {
 		return FALSE;
 	}
 
 	crm_malloc0(acl_obj, sizeof(acl_obj_t));
 	if (acl_obj == NULL) {
 		return FALSE;
 	}
 
 	acl_obj->mode = crm_element_name(acl_child);
 	acl_obj->tag = tag;
 	acl_obj->ref = ref;
 	acl_obj->xpath = xpath;
 	acl_obj->attribute = crm_element_value(acl_child, XML_ACL_ATTR_ATTRIBUTE);
 
 	*acl = g_list_append(*acl, acl_obj);
 
 	crm_debug_3("ACL object appended: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s",
 			acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute);
 
 	return TRUE;
 }
 
 static void
 free_acl(GListPtr acl)
 {
 	GListPtr iterator = acl;
 	while(iterator != NULL) {
 		crm_free(iterator->data);
 		iterator = iterator->next;
 	}
 	if(acl != NULL) {
 		g_list_free(acl);
 	}
 }
 
 static gboolean
 parse_acl_xpath(xmlNode *xml, GListPtr acl, GListPtr *parsed_acl)
 {
 	GListPtr acl_iterator = acl;
 	acl_obj_t *new_acl_obj = NULL;
 	
 	*parsed_acl = NULL;
 
 	while (acl_iterator != NULL) {
 		acl_obj_t *acl_obj = acl_iterator->data;
 
 		if (acl_obj->tag || acl_obj->ref) {
 			crm_malloc0(new_acl_obj, sizeof(acl_obj_t));
 			if (new_acl_obj == NULL) {
 				return  FALSE;
 			}
 
 			memcpy(new_acl_obj, acl_obj, sizeof(acl_obj_t));
 
 			*parsed_acl = g_list_append(*parsed_acl, new_acl_obj);
 
 			crm_debug_3("Copied ACL object: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s",
 					new_acl_obj->mode, new_acl_obj->tag, new_acl_obj->ref,
 					new_acl_obj->xpath, new_acl_obj->attribute);
 
 		} else if (acl_obj->xpath) {
 			GListPtr children = NULL;
 			GListPtr children_iterator = NULL;
 
 			search_xpath_objects(&children, xml, acl_obj->xpath);
 
 			children_iterator = children;
 			while (children_iterator != NULL) {
 				crm_malloc0(new_acl_obj, sizeof(acl_obj_t));
 				if (new_acl_obj == NULL) {
 					return  FALSE;
 				}
 
 				new_acl_obj->mode = acl_obj->mode;
 				new_acl_obj->tag = crm_element_name(children_iterator->data);
 				new_acl_obj->ref = crm_element_value(children_iterator->data, XML_ATTR_ID);
 				new_acl_obj->attribute = acl_obj->attribute;
 
 				*parsed_acl = g_list_append(*parsed_acl, new_acl_obj);
 
 				crm_debug_3("Parsed the ACL object with xpath '%s' to: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s",
 						acl_obj->xpath, new_acl_obj->mode, new_acl_obj->tag,
 						new_acl_obj->ref, new_acl_obj->xpath, new_acl_obj->attribute);
 
 				children_iterator = children_iterator->next;
 			}
 			g_list_free(children);
 		}
 		acl_iterator = acl_iterator->next;
 	}
 
 	return TRUE;
 }
 
 static gboolean
 gen_xml_perms(xmlNode *xml, GListPtr acl, GHashTable **xml_perms)
 {
 	GListPtr acl_iterator = acl;
 
 	if (*xml_perms == NULL) {
 		*xml_perms = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_xml_perm);
 	}
 
 	while (acl_iterator != NULL) {
 		acl_obj_t *acl_obj = acl_iterator->data;
 		GListPtr children = NULL;
 		GListPtr children_iterator = NULL;
 
 		crm_debug("Generating permissions with ACL: mode=%s, tag=%s, ref=%s, xpath=%s, attribute=%s",
 				acl_obj->mode, acl_obj->tag, acl_obj->ref, acl_obj->xpath, acl_obj->attribute);
 		if (acl_obj->tag || acl_obj->ref) {
 			search_xml_children(&children, xml, acl_obj->tag, XML_ATTR_ID, acl_obj->ref, TRUE);
 
 		} else if (acl_obj->xpath) {
 			/* Never be here for a modification operation */
 			/* Already parse_acl_xpath() previously */
 			search_xpath_objects(&children, xml, acl_obj->xpath);
 		}
 
 		children_iterator = children;
 		while (children_iterator != NULL) {
 			update_xml_perms(children_iterator->data, acl_obj, *xml_perms);
 
 			children_iterator = children_iterator->next;
 		}
 		g_list_free(children);
 
 		acl_iterator = acl_iterator->next;
 	}
 	
 	return TRUE;
 }
 
 /* Borrowed from lib/common/xml.c: find_xml_children() */
 /* But adding the original xmlNode pointers into a GList */
 static int
 search_xml_children(GListPtr *children, xmlNode *root,
 		  const char *tag, const char *field, const char *value,
 		  gboolean search_matches)
 {
 	int match_found = 0;
 	
 	CRM_CHECK(root != NULL, return FALSE);
 	CRM_CHECK(children != NULL, return FALSE);
 	
 	if(tag != NULL && safe_str_neq(tag, crm_element_name(root))) {
 
 	} else if(value != NULL
 		  && safe_str_neq(value, crm_element_value(root, field))) {
 
 	} else {
 		*children = g_list_append(*children, root);
 		match_found = 1;
 	}
 
 	if(search_matches || match_found == 0) {
 		xml_child_iter(
 			root, child, 
 			match_found += search_xml_children(
 				children, child, tag, field, value,
 				search_matches);
 			);
 	}
 	
 	return match_found;
 }
 
 static int
 search_xpath_objects(GListPtr *objects, xmlNode *xml_obj, const char *xpath)
 {
 	int match_found = 0;
 	xmlXPathObjectPtr xpathObj = NULL;
 
 	if(xpath == NULL) {
 		return 0;
 	}
 
 	xpathObj = xpath_search(xml_obj, xpath);
 
 	if(xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr < 1) {
 		crm_debug("No match for %s in %s", xpath, xmlGetNodePath(xml_obj));
 
 	} else if(xpathObj->nodesetval->nodeNr > 0) {
 		int lpc = 0, max = xpathObj->nodesetval->nodeNr;
 
 		for(lpc = 0; lpc < max; lpc++) {
 			xmlNode *match = getXpathResult(xpathObj, lpc);
 			if (match == NULL) {
 				continue;
 			}
 
 			*objects = g_list_append(*objects, match);
 			match_found++;
 		}
 	}
 
 	if(xpathObj) {
 		xmlXPathFreeObject(xpathObj);
 	}
 	return match_found;
 }
 
 static gboolean
 update_xml_perms(xmlNode *xml, acl_obj_t *acl_obj, GHashTable *xml_perms)
 {
 	xml_perm_t *perm = NULL;
 
 	if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm)) {
 		if (perm->mode != NULL) {
 			return FALSE;
 		}
 	} else {
 		crm_malloc0(perm, sizeof(xml_perm_t));
 		if (perm == NULL) {
 			return FALSE;
 		}
 		g_hash_table_insert(xml_perms, xml, perm);
 	}
 
 	if (acl_obj->attribute == NULL) {
 		perm->mode = acl_obj->mode;
 		crm_debug_3("Permission for element: element_mode=%s, tag=%s, id=%s",
                                 perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 
 		xml_child_iter(
 			xml, child,
 			update_xml_children_perms(child, perm->mode, xml_perms);
 			);
 
 	} else {
 		if (perm->attribute_perms == NULL
 				|| (g_hash_table_lookup_extended(perm->attribute_perms, 
 					acl_obj->attribute, NULL, NULL) == FALSE)) {
 
 			if (perm->attribute_perms == NULL) {
 				perm->attribute_perms = g_hash_table_new_full(
 						g_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str);
 			}
 
 			g_hash_table_insert(perm->attribute_perms,
 					crm_strdup(acl_obj->attribute), crm_strdup(acl_obj->mode));
 			crm_debug_3("Permission for attribute: attribute_mode=%s, tag=%s, id=%s attribute=%s",
                                 	acl_obj->mode, crm_element_name(xml),
 					crm_element_value(xml, XML_ATTR_ID), acl_obj->attribute);
 		}
 	}
 
 	return TRUE;
 }
 
 static gboolean
 update_xml_children_perms(xmlNode *xml, const char *mode, GHashTable *xml_perms)
 {
 	xml_perm_t *perm = NULL;
 
 	if (g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm)) {
 		if (perm->mode != NULL) {
 			return FALSE;
 		}
 	} else {
 		crm_malloc0(perm, sizeof(xml_perm_t));
 		if (perm == NULL) {
 			return FALSE;
 		}
 		g_hash_table_insert(xml_perms, xml, perm);
 	}
 
 	perm->mode = mode;
 	crm_debug_4("Permission for child element: element_mode=%s, tag=%s, id=%s",
 			mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 
 	xml_child_iter(
 		xml, child,
 		update_xml_children_perms(child, mode, xml_perms);
 		);
 
 	return TRUE;
 }
 
 static void
 free_xml_perm(gpointer xml_perm)
 {
 	xml_perm_t *perm = xml_perm;
 
 	if (perm == NULL) {
 		return;
 	}
 
 	if (perm->attribute_perms != NULL) {
 		g_hash_table_destroy(perm->attribute_perms);
 	}
 
 	crm_free(perm);
 }
 
 #define can_read(mode) (crm_str_eq(mode, XML_ACL_TAG_READ, TRUE) \
 			|| crm_str_eq(mode, XML_ACL_TAG_WRITE, TRUE))
 
 #define can_write(mode) crm_str_eq(mode, XML_ACL_TAG_WRITE, TRUE)
 
 /* rc = TRUE if the xml is filtered out*/
 static gboolean
 acl_filter_xml(xmlNode *xml, GHashTable *xml_perms)
 {
 	int children_counter = 0;
 	xml_perm_t *perm = NULL;
 	int allow_counter = 0;
 
 	xml_child_iter(
 		xml, child, 
 		if (acl_filter_xml(child, xml_perms) == FALSE) {
 			children_counter++;
 		}
 		);
 
 	g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm);
 
 	if (perm == NULL) {
 		crm_debug_4("No ACL defined to read the element: tag=%s, id=%s",
 				crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 		goto end_filter;
 	}
 
 	if (perm->attribute_perms == NULL) {
 		if (can_read(perm->mode)) {
 			return FALSE;
 		} else {
 			crm_debug_4("No enough permission to read the element: element_mode=%s, tag=%s, id=%s",
 					 perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 			goto end_filter;
 		}
 	}
 
 	xml_prop_iter(xml, prop_name, prop_value,
 		gpointer mode = NULL;
 
 		if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) {
 			if (can_read(mode)) {
 				allow_counter++;
 			} else {
 				xml_remove_prop(xml, prop_name);
 				crm_debug_4("Filtered out the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s",
 						 (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 			}
 		} else {
 			if (can_read(perm->mode)) {
 				allow_counter++;
 			} else if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE) == FALSE) {
 				xml_remove_prop(xml, prop_name);
 				crm_debug_4("Filtered out the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s",
 						 perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 			}
 		}
 		);
 
 	if (allow_counter) {
 		return FALSE;
 	}
 
 	if (can_read(perm->mode)) {
 		return FALSE;
 	}
 
 end_filter:
 	if (children_counter) {
 		crm_debug_4("Don't filter out the element (tag=%s, id=%s) because user can read its children",
 				crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 		return FALSE;
 	}
 
 	free_xml_from_parent(NULL, xml);
 	crm_debug_4("Filtered out the element: tag=%s, id=%s",
 			crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID));
 	return TRUE;
 }
 
 static gboolean
 acl_check_diff_xml(xmlNode *xml, GHashTable *xml_perms)
 {
 	xml_perm_t *perm = NULL;
 
 	xml_child_iter(
 		xml, child, 
 		if (acl_check_diff_xml(child, xml_perms) == FALSE) {
 			return FALSE;
 		}
 		);
 
 	g_hash_table_lookup_extended(xml_perms, xml, NULL, (gpointer)&perm);
 
 	xml_prop_iter(xml, prop_name, prop_value,
 		gpointer mode = NULL;
 
 		if (crm_str_eq(crm_element_name(xml), XML_TAG_CIB, TRUE)) {
 			if (crm_str_eq(prop_name, XML_ATTR_GENERATION, TRUE)
 					|| crm_str_eq(prop_name, XML_ATTR_NUMUPDATES, TRUE)
 					|| crm_str_eq(prop_name, XML_ATTR_GENERATION_ADMIN, TRUE)) {
 				continue;
 			}
 		}
 
 		if (crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) {
 			continue;
 		}
 
 		if (perm == NULL) {
 			crm_warn("No ACL defined to modify the element: tag=%s, id=%s, attribute=%s",
 					 crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 			return FALSE;
 		}
 
 		if (perm->attribute_perms == NULL) {
 			if (can_write(perm->mode)) {
 				return TRUE;
 			} else {
 				crm_warn("No enough permission to modify the element: element_mode=%s, tag=%s, id=%s, attribute=%s",
 						 perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 				return FALSE;
 			}
 		}
 
 		if (g_hash_table_lookup_extended(perm->attribute_perms, prop_name, NULL, &mode)) {
 			if (can_write(mode) == FALSE) {
 				crm_warn("No enough permission to modify the attribute: attribute_mode=%s, tag=%s, id=%s, attribute=%s",
 						 (char *)mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 				return FALSE;
 			}
 		} else if (can_write(perm->mode) == FALSE) {
 			crm_warn("No enough permission to modify the element and the attribute: element_mode=%s, tag=%s, id=%s, attribute=%s",
 					 perm->mode, crm_element_name(xml), crm_element_value(xml, XML_ATTR_ID), prop_name);
 			return FALSE;
 		}
 
 		);
 
 	return TRUE;
 }