[pgpool-hackers: 1263] new watchdog IPC authentication mechanism

Muhammad Usama m.usama at gmail.com
Thu Dec 24 00:17:38 JST 2015


Hi Yugo

As you mentioned in your watchdog code review comments that there should be
a mechanism to authenticate the watchdog IPC commands, Although this was
also one of the TODO items in my list but somehow slipped out of radar.

So please find the attached patch for the purpose.

Basically the patch utilizes the *wd_authkey* configuration parameter to
authenticate the watchdog IPC command clients. And since the IPC is meant
for communication between internal pgpool-II processes and with external
processes on the same machine, so instead of calculating the hash and
inventing a more complicated process of IPC authentication, the simple
wd_authkey matching is used to validate the clients. And when the
wd_authkey is not provided by the user in pgpool.conf than the
authentication is disabled.

The patch also takes care of other authentication related problem in the
watchdog IPC system. Since there are some watchdog functions visible by the
IPC commands, and we want to restrict their access to the outer world. Like
for example the interlocking command functions and failover related
functions. So for those functions, the patch creates a shared key in the
shared memory, and execution of these functions is only allowed if that
shard key in that function data matches with the current shred key in
shared memory. And when some external client tries to call these internal
only functions, the authentication error will be returned to that since the
key is secret to the pgpool-II only.

So what are your thoughts on the mechanism and using the *wd_authkey* for
the purpose.

Thanks
Best regards
Muhammad Usama
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.sraoss.jp/pipermail/pgpool-hackers/attachments/20151223/c95c7869/attachment-0001.html>
-------------- next part --------------
diff --git a/src/auth/pool_auth.c b/src/auth/pool_auth.c
index e165521..597d56b 100644
--- a/src/auth/pool_auth.c
+++ b/src/auth/pool_auth.c
@@ -1275,6 +1275,7 @@ int pool_read_int(POOL_CONNECTION_POOL *cp)
  */
 void pool_random_salt(char *md5Salt)
 {
+	srandom(time(NULL));
 	long rand = random();
 
 	md5Salt[0] = (rand % 255) + 1;
diff --git a/src/include/watchdog/watchdog.h b/src/include/watchdog/watchdog.h
index 93a5ab7..c1bcf25 100644
--- a/src/include/watchdog/watchdog.h
+++ b/src/include/watchdog/watchdog.h
@@ -36,6 +36,10 @@
 #define WD_TIME_DIFF_SEC(a,b) (int)(((a).tv_sec - (b).tv_sec) + \
                                     ((a).tv_usec - (b).tv_usec) / 1000000.0)
 
+#define WD_IPC_AUTH_KEY			"IPCAuthKey"
+#define WD_IPC_SHARED_KEY		"IPCSharedKey"
+
+
 /*
  * watchdog state
  */
diff --git a/src/include/watchdog/wd_ipc_commands.h b/src/include/watchdog/wd_ipc_commands.h
index 2e969c3..9dcc602 100644
--- a/src/include/watchdog/wd_ipc_commands.h
+++ b/src/include/watchdog/wd_ipc_commands.h
@@ -7,7 +7,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2012	PgPool Global Development Group
+ * Copyright (c) 2003-2015	PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -45,6 +45,8 @@ typedef struct WDIPCCmdResult
 
 extern void wd_ipc_initialize_data(void);
 extern char* get_watchdog_ipc_address(void);
+extern unsigned int* get_ipc_shared_key(void);
+
 
 extern int wd_set_node_mask_for_failback_req(int *node_id_set, int count);
 extern int wd_set_node_mask_for_degenerate_req(int *node_id_set, int count);
diff --git a/src/include/watchdog/wd_json_data.h b/src/include/watchdog/wd_json_data.h
index 53ff9d6..940f416 100644
--- a/src/include/watchdog/wd_json_data.h
+++ b/src/include/watchdog/wd_json_data.h
@@ -43,11 +43,12 @@ extern WatchdogNode* get_watchdog_node_from_json(char* json_data, int data_len,
 extern char* get_watchdog_node_info_json(WatchdogNode* wdNode, char* authkey);
 extern POOL_CONFIG* get_pool_config_from_json(char* json_data, int data_len);
 extern char* get_pool_config_json(void);
-extern char* get_lifecheck_node_status_change_json(int nodeID, int nodeStatus, char* message);
+extern char* get_lifecheck_node_status_change_json(int nodeID, int nodeStatus, char* message, char* authKey);
 extern bool parse_node_status_json(char* json_data, int data_len, int* nodeID, int* nodeStatus, char** message);
 
 extern WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source);
 
-extern char* get_wd_node_function_json(char* func_name, int *node_id_set, int count);
+extern char* get_wd_node_function_json(char* func_name, int *node_id_set, int count, unsigned int sharedKey, char* authKey);
 extern bool parse_wd_node_function_json(char* json_data, int data_len, char** func_name, int **node_id_set, int *count);
+extern char* get_wd_simple_error_message_json(char* message);
 #endif
diff --git a/src/watchdog/watchdog.c b/src/watchdog/watchdog.c
index 6fbb54a..027c053 100644
--- a/src/watchdog/watchdog.c
+++ b/src/watchdog/watchdog.c
@@ -261,7 +261,7 @@ typedef struct wd_cluster
 	bool			network_error;
 	bool			escalated;
 	bool			clusterInitialized;
-
+	bool			ipc_auth_needed;
 	struct timeval  network_error_time;
 
 	List			*unidentified_socks;
@@ -364,7 +364,7 @@ static bool wd_commands_packet_processor(WD_EVENTS event, WatchdogNode* wdNode,
 static WDIPCCommandData* get_wd_IPC_command_from_reply(WDPacketData* pkt);
 static WDIPCCommandData* get_wd_IPC_command_from_socket(int sock);
 
-static IPC_CMD_PREOCESS_RES process_IPC_command(WDIPCCommandData* IPCCommand);
+static IPC_CMD_PREOCESS_RES process_IPC_command(WDIPCCommandData* ipcCommand);
 static IPC_CMD_PREOCESS_RES process_IPC_nodeStatusChange_command(WDIPCCommandData* IPCCommand);
 static IPC_CMD_PREOCESS_RES process_IPC_nodeList_command(WDIPCCommandData* IPCCommand);
 static IPC_CMD_PREOCESS_RES process_IPC_replicate_variable(WDIPCCommandData* IPCCommand);
@@ -396,6 +396,8 @@ static void wd_check_config(void);
 static pid_t watchdog_main(void);
 static pid_t fork_watchdog_child(void);
 static void cluster_in_stable_state(void);
+static bool check_IPC_client_authentication(json_value *rootObj, bool internal_client_only);
+static bool check_and_report_IPC_authentication(WDIPCCommandData* ipcCommand);
 
 static void print_received_packet_info(WDPacketData* pkt,WatchdogNode* wdNode);
 /* global variables */
@@ -506,6 +508,7 @@ static void wd_cluster_initialize(void)
 	g_cluster.ipc_command_socks = NULL;
 	g_cluster.wd_timer_commands = NULL;
 	g_cluster.localNode->state = WD_DEAD;
+	g_cluster.ipc_auth_needed = strlen(pool_config->wd_authkey)?true:false;
 
 	/* initialize the memory for command object */
 	g_cluster.currentCommand.nodeResults = palloc0((sizeof(WDCommandNodeResult) * g_cluster.remoteNodeCount));
@@ -1380,7 +1383,7 @@ static bool read_ipc_command_and_process(int sock, bool *remove_socket)
 	IPCCommand->issueing_sock = sock;
 	IPCCommand->type = type;
 	gettimeofday(&IPCCommand->issue_time, NULL);
-	
+
 	if (data_len > 0)
 	{
 		IPCCommand->data_buf = palloc(data_len);
@@ -1425,35 +1428,54 @@ static bool read_ipc_command_and_process(int sock, bool *remove_socket)
 	return (res != IPC_CMD_ERROR);
 }
 
-static IPC_CMD_PREOCESS_RES process_IPC_command(WDIPCCommandData* IPCCommand)
+static IPC_CMD_PREOCESS_RES process_IPC_command(WDIPCCommandData* ipcCommand)
 {
-	switch(IPCCommand->type)
+	/* authenticate the client first */
+	if (check_and_report_IPC_authentication(ipcCommand) == false)
+	{
+		return IPC_CMD_ERROR;
+	}
+
+	switch(ipcCommand->type)
 	{
 		case WD_NODE_STATUS_CHANGE_COMMAND:
-			return process_IPC_nodeStatusChange_command(IPCCommand);
+			return process_IPC_nodeStatusChange_command(ipcCommand);
 			break;
 
 		case WD_REGISTER_FOR_NOTIFICATION:
 			/* Add this socket to the notify socket list*/
-			g_cluster.notify_clients = lappend_int(g_cluster.notify_clients, IPCCommand->issueing_sock);
+			g_cluster.notify_clients = lappend_int(g_cluster.notify_clients, ipcCommand->issueing_sock);
 			/* The command is completed successfully */
 			return IPC_CMD_COMPLETE;
 			break;
 
 		case WD_GET_NODES_LIST_COMMAND:
-			return process_IPC_nodeList_command(IPCCommand);
+			return process_IPC_nodeList_command(ipcCommand);
 			break;
 
 		case WD_FUNCTION_COMMAND:
-			return process_IPC_replicate_variable(IPCCommand);
+			return process_IPC_replicate_variable(ipcCommand);
 			break;
 
 		case WD_FAILOVER_CMD_SYNC_REQUEST:
-			return process_IPC_failover_cmd_synchronise(IPCCommand);
+			return process_IPC_failover_cmd_synchronise(ipcCommand);
 
 		default:
+		{
+			char* error_json;
 			ereport(LOG,
-					(errmsg("invalid IPC command type %c",IPCCommand->type)));
+					(errmsg("invalid IPC command type %c",ipcCommand->type)));
+
+			error_json = get_wd_simple_error_message_json("unknown IPC command type");
+			if (write_ipc_command_with_result_data(ipcCommand, WD_IPC_CMD_RESULT_BAD,
+												   error_json, strlen(error_json) +1))
+			{
+				ereport(LOG,
+						(errmsg("failed to forward error message of process node list command to IPC socket")));
+			}
+			pfree(error_json);
+
+		}
 			break;
 	}
 	return IPC_CMD_ERROR;
@@ -1479,12 +1501,14 @@ static IPC_CMD_PREOCESS_RES process_IPC_nodeList_command(WDIPCCommandData* IPCCo
 				(errmsg("unable to parse json data from get node list command")));
 		return IPC_CMD_ERROR;
 	}
+
 	/* If it is a node function ?*/
 	if (json_get_int_value_for_key(root, "NodeID", &NodeID))
 	{
 		json_value_free(root);
 		return IPC_CMD_ERROR;
 	}
+
 	json_value_free(root);
 	jNode = get_node_list_json(NodeID);
 	ret = write_ipc_command_with_result_data(IPCCommand, WD_IPC_CMD_RESULT_OK,
@@ -3527,6 +3551,7 @@ static int watchdog_state_machine_joining(WD_EVENTS event, WatchdogNode* wdNode,
   default:
 			break;
 	}
+
 	return 0;
 }
 
@@ -4951,6 +4976,167 @@ static bool verify_authhash_for_node(WatchdogNode* wdNode, char* authhash)
 	return true;
 }
 
+/*
+ * function authenticates the IPC command by looking for the
+ * auth key in the JSON data of IPC command.
+ * For IPC commands comming from outer wrold the function validates the
+ * authkey in JSON packet with configured pool_config->wd_authkey.
+ * if internal_client_only is true than the JSON data must contain the
+ * shared key present in the pgpool-II shared memory. This can be used
+ * to restrict certain watchdog IPC functions for outside of pgpool-II
+ */
+static bool check_IPC_client_authentication(json_value *rootObj, bool internal_client_only)
+{
+	char *packet_auth_key;
+	unsigned int packet_key;
+	bool has_shared_key;
+	unsigned int *shared_key = get_ipc_shared_key();
+
+	if (json_get_int_value_for_key(rootObj, WD_IPC_SHARED_KEY, (int*)&packet_key))
+	{
+		ereport(LOG,
+				(errmsg("invalid json data packet"),
+				 errdetail("authentication shared key not found in json data")));
+		has_shared_key = false;
+	}
+	else
+	{
+		has_shared_key = true;
+	}
+
+	if (internal_client_only)
+	{
+
+		if (shared_key == NULL)
+		{
+			ereport(LOG,
+					(errmsg("shared key not initialized")));
+			return false;
+		}
+
+		/* If it is a node function ?*/
+		if (has_shared_key == false)
+		{
+			ereport(LOG,
+				(errmsg("invalid json data packet"),
+					 errdetail("authentication shared key not found in json data")));
+			return false;
+		}
+		/* compare if shared keys match */
+		if (*shared_key != packet_key)
+			return false;
+
+		/* providing a valid shared key for inetenal clients is enough */
+		return true;
+	}
+
+	/* If no authentication is required, no need to look further */
+	if (g_cluster.ipc_auth_needed == false)
+		return true;
+
+	/* if shared key is provided and it matched, we are good */
+	if (has_shared_key == true && *shared_key == packet_key)
+		return true;
+
+	/* shared key is out of question validate the authKey valurs */
+	packet_auth_key = json_get_string_value_for_key(rootObj, WD_IPC_AUTH_KEY);
+
+	if (packet_auth_key == NULL)
+	{
+		ereport(DEBUG1,
+			(errmsg("invalid json data packet"),
+				 errdetail("authentication key not found in json data")));
+		return false;
+	}
+
+	/* compare the packet key with configured auth key */
+	if (strcmp(pool_config->wd_authkey, packet_auth_key) != 0)
+		return false;
+	return true;
+}
+
+/*
+ * function to check authentication of IPC command based on the command type
+ * this one also informs the calling client about the failure
+ */
+
+static bool check_and_report_IPC_authentication(WDIPCCommandData* ipcCommand)
+{
+	json_value *root = NULL;
+	bool internal_client_only = false;
+	bool ret;
+
+	if (ipcCommand == NULL)
+		return false;	/* should never happen*/
+
+	/* first identify the command type */
+	switch(ipcCommand->type)
+	{
+		case WD_NODE_STATUS_CHANGE_COMMAND:
+		case WD_REGISTER_FOR_NOTIFICATION:
+		case WD_GET_NODES_LIST_COMMAND:
+			internal_client_only = false;
+			break;
+
+		case WD_FUNCTION_COMMAND:
+		case WD_FAILOVER_CMD_SYNC_REQUEST:
+			/* only allowed internaly.*/
+			internal_client_only = true;
+			break;
+
+		default:
+			/* unknown command, ignore it */
+			return true;
+			break;
+	}
+
+	if (internal_client_only == false && g_cluster.ipc_auth_needed == false)
+	{
+		/* no need to look further */
+		return true;
+	}
+
+	if (ipcCommand->data_len <= 0 || ipcCommand->data_buf == NULL)
+	{
+		ereport(LOG,
+			(errmsg("authentication failed"),
+				 errdetail("IPC command contains no data")));
+		return false;
+	}
+
+	root = json_parse(ipcCommand->data_buf,ipcCommand->data_len);
+	/* The root node must be object */
+	if (root == NULL || root->type != json_object)
+	{
+		json_value_free(root);
+		ereport(LOG,
+			(errmsg("authentication failed"),
+				 errdetail("IPC command contains an invalid data")));
+		return false;
+	}
+
+	ret = check_IPC_client_authentication(root, internal_client_only);
+	json_value_free(root);
+
+	if (ret == false)
+	{
+		char* error_json;
+		ereport(WARNING,
+			(errmsg("authentication failed"),
+				 errdetail("invalid IPC key")));
+
+		error_json = get_wd_simple_error_message_json("IPC client authentication failed");
+		if (write_ipc_command_with_result_data(ipcCommand, WD_IPC_CMD_RESULT_BAD,
+											   error_json, strlen(error_json) +1))
+		{
+			ereport(LOG,
+					(errmsg("failed to forward error message to IPC socket")));
+		}
+		pfree(error_json);
+	}
+	return ret;
+}
+
 /* DEBUG */
 static void print_watchdog_node_info(WatchdogNode* wdNode)
 {
diff --git a/src/watchdog/wd_commands.c b/src/watchdog/wd_commands.c
index 08b6137..e5ecf2a 100644
--- a/src/watchdog/wd_commands.c
+++ b/src/watchdog/wd_commands.c
@@ -70,8 +70,13 @@ static int wd_chk_node_mask (unsigned char req_mask, int *node_id_set, int count
 
 static int open_wd_command_sock(bool throw_error);
 
-unsigned char *WD_Node_List = NULL;		/* Lives in shared memory */
-char* watchdog_ipc_address = NULL;
+/* shared memory variables */
+unsigned char *WD_Node_List = NULL;
+char *watchdog_ipc_address = NULL;
+unsigned int *ipc_shared_key = NULL;   /* key lives in shared memory
+										* used to identify the ipc internal
+										* clients
+										*/
 
 void wd_ipc_initialize_data(void)
 {
@@ -86,6 +91,7 @@ void wd_ipc_initialize_data(void)
 						MAX_WATCHDOG_NUM,
 						sizeof(unsigned char) * MAX_NUM_BACKENDS)));
 	}
+
 	if (watchdog_ipc_address == NULL)
 	{
 		char wd_ipc_sock_addr[255];
@@ -96,6 +102,15 @@ void wd_ipc_initialize_data(void)
 		watchdog_ipc_address = pool_shared_memory_create(strlen(wd_ipc_sock_addr) +1);
 		strcpy(watchdog_ipc_address, wd_ipc_sock_addr);
 	}
+
+	if (ipc_shared_key == NULL)
+	{
+		ipc_shared_key = pool_shared_memory_create(sizeof(unsigned int));
+		*ipc_shared_key = 0;
+		while (*ipc_shared_key == 0) {
+			pool_random_salt((char*)ipc_shared_key);
+		}
+	}
 }
 
 char* get_watchdog_ipc_address(void)
@@ -103,6 +118,11 @@ char* get_watchdog_ipc_address(void)
 	return watchdog_ipc_address;
 }
 
+unsigned int* get_ipc_shared_key(void)
+{
+	return ipc_shared_key;
+}
+
 /*
  * function issues the command to watchdog process over the watchdog
  * IPC command socket.
@@ -229,8 +249,11 @@ WdCommandResult
 wd_start_recovery(void)
 {
 	char type;
-	char* func = get_wd_node_function_json(WD_FUNCTION_START_RECOVERY, NULL,0);
-	
+	unsigned int *shared_key = get_ipc_shared_key();
+
+	char* func = get_wd_node_function_json(WD_FUNCTION_START_RECOVERY, NULL,0,
+										   shared_key?*shared_key:0,pool_config->wd_authkey);
+
 	WDIPCCmdResult *result = issue_command_to_watchdog(WD_FUNCTION_COMMAND,
 													   pool_config->recovery_timeout,
 													   func, strlen(func), true);
@@ -264,7 +287,11 @@ WdCommandResult
 wd_end_recovery(void)
 {
 	char type;
-	char* func = get_wd_node_function_json(WD_FUNCTION_END_RECOVERY, NULL, 0);
+	unsigned int *shared_key = get_ipc_shared_key();
+
+	char* func = get_wd_node_function_json(WD_FUNCTION_END_RECOVERY, NULL, 0,
+										   shared_key?*shared_key:0,pool_config->wd_authkey);
+
 	
 	WDIPCCmdResult *result = issue_command_to_watchdog(WD_FUNCTION_COMMAND,
 													   WD_DEFAULT_IPC_COMMAND_TIMEOUT,
@@ -302,13 +329,15 @@ wd_send_failback_request(int node_id)
 	int n = node_id;
 	char type;
 	char* func;
-	
-	
+	unsigned int *shared_key = get_ipc_shared_key();
+
 	/* if failback packet is received already, do nothing */
 	if (wd_chk_node_mask_for_failback_req(&n,1))
 		return COMMAND_OK;
 	
-	func = get_wd_node_function_json(WD_FUNCTION_FAILBACK_REQUEST,&n, 1);
+	func = get_wd_node_function_json(WD_FUNCTION_FAILBACK_REQUEST,&n, 1,
+									 shared_key?*shared_key:0,pool_config->wd_authkey);
+
 	WDIPCCmdResult *result = issue_command_to_watchdog(WD_FUNCTION_COMMAND,
 													   WD_DEFAULT_IPC_COMMAND_TIMEOUT,
 													   func, strlen(func), true);
@@ -342,7 +371,12 @@ static char* get_wd_failover_cmd_type_json(WDFailoverCMDTypes cmdType, char* req
 {
 	char* json_str;
 	JsonNode* jNode = jw_create_with_object(true);
-	
+	unsigned int *shared_key = get_ipc_shared_key();
+
+	jw_put_int(jNode, WD_IPC_SHARED_KEY, shared_key?*shared_key:0); /* put the shared key*/
+	if (pool_config->wd_authkey != NULL && strlen(pool_config->wd_authkey) > 0)
+		jw_put_string(jNode, WD_IPC_AUTH_KEY, pool_config->wd_authkey); /*  put the auth key*/
+
 	jw_put_int(jNode, "FailoverCMDType", cmdType);
 	jw_put_string(jNode, "SyncRequestType", reqType);
 	jw_finish_document(jNode);
@@ -410,13 +444,15 @@ wd_degenerate_backend_set(int *node_id_set, int count)
 {
 	char type;
 	char* func;
-	
-	
+	unsigned int *shared_key = get_ipc_shared_key();
+
 	/* if failback packet is received already, do nothing */
 	if (wd_chk_node_mask_for_degenerate_req(node_id_set,count))
 		return COMMAND_OK;
 	
-	func = get_wd_node_function_json(WD_FUNCTION_DEGENERATE_REQUEST,node_id_set, count);
+	func = get_wd_node_function_json(WD_FUNCTION_DEGENERATE_REQUEST,node_id_set, count,
+									 shared_key?*shared_key:0,pool_config->wd_authkey);
+
 	WDIPCCmdResult *result = issue_command_to_watchdog(WD_FUNCTION_COMMAND ,
 													   WD_DEFAULT_IPC_COMMAND_TIMEOUT,
 													   func, strlen(func), true);
@@ -453,12 +489,14 @@ wd_promote_backend(int node_id)
 	char type;
 	char* func;
 	WDIPCCmdResult *result;
-	
+	unsigned int *shared_key = get_ipc_shared_key();
+
 	/* if promote packet is received already, do nothing */
 	if (wd_chk_node_mask_for_promote_req(&n,1))
 		return COMMAND_OK;
 	
-	func = get_wd_node_function_json(WD_FUNCTION_PROMOTE_REQUEST,&n, 1);
+	func = get_wd_node_function_json(WD_FUNCTION_PROMOTE_REQUEST,&n, 1,
+									 shared_key?*shared_key:0,pool_config->wd_authkey);
 	result = issue_command_to_watchdog(WD_FUNCTION_COMMAND ,
 									   WD_DEFAULT_IPC_COMMAND_TIMEOUT,
 									   func, strlen(func), true);
@@ -496,8 +534,16 @@ char* wd_get_watchdog_nodes(int nodeID)
 {
 	WDIPCCmdResult *result;
 	char* json_str;
+	unsigned int *shared_key = get_ipc_shared_key();
+
 	JsonNode* jNode = jw_create_with_object(true);
 	jw_put_int(jNode, "NodeID", nodeID);
+
+	jw_put_int(jNode, WD_IPC_SHARED_KEY, shared_key?*shared_key:0); /* put the shared key*/
+
+	if (pool_config->wd_authkey != NULL && strlen(pool_config->wd_authkey) > 0)
+		jw_put_string(jNode, WD_IPC_AUTH_KEY, pool_config->wd_authkey); /*  put the auth key*/
+
 	jw_finish_document(jNode);
 	
 	json_str = jw_get_json_string(jNode);
diff --git a/src/watchdog/wd_json_data.c b/src/watchdog/wd_json_data.c
index f7e5f35..1698f9e 100644
--- a/src/watchdog/wd_json_data.c
+++ b/src/watchdog/wd_json_data.c
@@ -6,7 +6,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2014	PgPool Global Development Group
+ * Copyright (c) 2003-2015	PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -310,10 +310,14 @@ WatchdogNode* get_watchdog_node_from_json(char* json_data, int data_len, char**
 }
 
 
-char* get_lifecheck_node_status_change_json(int nodeID, int nodeStatus, char* message)
+char* get_lifecheck_node_status_change_json(int nodeID, int nodeStatus, char* message, char* authKey)
 {
 	char* json_str;
 	JsonNode* jNode = jw_create_with_object(true);
+
+	if (authKey != NULL && strlen(authKey) > 0)
+		jw_put_string(jNode, WD_IPC_AUTH_KEY, authKey); /*  put the auth key*/
+
 	/* add the node ID */
 	jw_put_int(jNode, "NodeID", nodeID);
 	/* add the node status */
@@ -425,12 +429,17 @@ WDNodeInfo* get_WDNodeInfo_from_wd_node_json(json_value* source)
 	
 }
 
-char* get_wd_node_function_json(char* func_name, int *node_id_set, int count)
+char* get_wd_node_function_json(char* func_name, int *node_id_set, int count, unsigned int sharedKey, char* authKey)
 {
 	char* json_str;
 	int  i;
 	JsonNode* jNode = jw_create_with_object(true);
 
+	jw_put_int(jNode, WD_IPC_SHARED_KEY, sharedKey); /* put the shared key*/
+
+	if (authKey != NULL && strlen(authKey) > 0)
+		jw_put_string(jNode, WD_IPC_AUTH_KEY, authKey); /*  put the auth key*/
+
 	jw_put_string(jNode, "Function", func_name);
 	jw_put_int(jNode, "NodeCount", count);
 	if (count > 0)
@@ -528,4 +537,15 @@ bool parse_wd_node_function_json(char* json_data, int data_len, char** func_name
 	return true;
 }
 
+char* get_wd_simple_error_message_json(char* message)
+{
+	char* json_str;
+	JsonNode* jNode = jw_create_with_object(true);
+
+	jw_put_string(jNode, "ERROR", message);
+	jw_finish_document(jNode);
+	json_str = pstrdup(jw_get_json_string(jNode));
+	jw_destroy(jNode);
+	return json_str;
+}
 
diff --git a/src/watchdog/wd_lifecheck.c b/src/watchdog/wd_lifecheck.c
index 8d638a7..b516c3f 100644
--- a/src/watchdog/wd_lifecheck.c
+++ b/src/watchdog/wd_lifecheck.c
@@ -467,7 +467,7 @@ static bool inform_node_status(LifeCheckNode* node, char *message)
 			(errmsg("informing the node status change to watchdog"),
 				 errdetail("node id :%d status = \"%s\" message:\"%s\"",node->ID,new_status,message)));
 
-	json_data = get_lifecheck_node_status_change_json(node->ID, node_status, message);
+	json_data = get_lifecheck_node_status_change_json(node->ID, node_status, message, pool_config->wd_authkey);
 	if (json_data == NULL)
 		return false;
 


More information about the pgpool-hackers mailing list