Currently openais does not allow unprivileged users to use the various
libraries, which I think is quite a serious restriction.

This patch enables normal users to call IPC routines that are specified
in the openais_lib_handler structure (the default is still privileged only).

I've slightly changed the meaning of the meaning of the
conn_info->authorized flag. Previously it was both part of the stata
machine and a flag saying the connection was correctly authorized. Now
it simply informs the state machine and the ->privileged flag indicates
whether the connection can perform privileged operations.

Comments?

Patrick
Index: exec/service.h
===================================================================
--- exec/service.h	(revision 1499)
+++ exec/service.h	(working copy)
@@ -42,11 +42,17 @@
 	OPENAIS_FLOW_CONTROL_NOT_REQUIRED = 2
 };
 
+enum openais_unprivileged_call {
+	OPENAIS_UNPRIVILEGED_CALL_NO = 0,
+	OPENAIS_UNPRIVILEGED_CALL_YES = 1,
+};
+
 struct openais_lib_handler {
 	void (*lib_handler_fn) (void *conn, void *msg);
 	int response_size;
 	int response_id;
 	enum openais_flow_control flow_control;
+	enum openais_unprivileged_call unpriv_call;
 };
 
 struct openais_exec_handler {
Index: exec/cpg.c
===================================================================
--- exec/cpg.c	(revision 1499)
+++ exec/cpg.c	(working copy)
@@ -198,43 +198,50 @@
 		.lib_handler_fn				= message_handler_req_lib_cpg_join,
 		.response_size				= sizeof (struct res_lib_cpg_join),
 		.response_id				= MESSAGE_RES_CPG_JOIN,
-		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES,
 	},
 	{ /* 1 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_leave,
 		.response_size				= sizeof (struct res_lib_cpg_leave),
 		.response_id				= MESSAGE_RES_CPG_LEAVE,
-		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES,
 	},
 	{ /* 2 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_mcast,
 		.response_size				= sizeof (struct res_lib_cpg_mcast),
 		.response_id				= MESSAGE_RES_CPG_MCAST,
-		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES,
 	},
 	{ /* 3 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_membership,
 		.response_size				= sizeof (mar_res_header_t),
 		.response_id				= MESSAGE_RES_CPG_MEMBERSHIP,
-		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES
 	},
 	{ /* 4 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_trackstart,
 		.response_size				= sizeof (struct res_lib_cpg_trackstart),
 		.response_id				= MESSAGE_RES_CPG_TRACKSTART,
-		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES
 	},
 	{ /* 5 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_trackstop,
 		.response_size				= sizeof (struct res_lib_cpg_trackstart),
 		.response_id				= MESSAGE_RES_CPG_TRACKSTOP,
-		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES
 	},
 	{ /* 6 */
 		.lib_handler_fn				= message_handler_req_lib_cpg_local_get,
 		.response_size				= sizeof (struct res_lib_cpg_local_get),
 		.response_id				= MESSAGE_RES_CPG_LOCAL_GET,
-		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED
+		.flow_control				= OPENAIS_FLOW_CONTROL_NOT_REQUIRED,
+		.unpriv_call                            = OPENAIS_UNPRIVILEGED_CALL_YES
 	}
 };
 
Index: exec/ipc.c
===================================================================
--- exec/ipc.c	(revision 1499)
+++ exec/ipc.c	(working copy)
@@ -140,7 +140,8 @@
 	struct queue outq;	/* Circular queue for outgoing requests */
 	int byte_start;		/* Byte to start sending from in head of queue */
 	enum service_types service;/* Type of service so dispatch knows how to route message */
-	int authenticated;	/* Is this connection authenticated? */
+	int authenticated;	/* Has this this connection been authenticated? */
+	int privileged;	        /* Is this connection privileged? */
 	void *private_data;	/* library connection private data */
 	struct conn_info *conn_info_partner;	/* partner connection dispatch<->response */
 	unsigned int flow_control_handle;	/* flow control identifier */
@@ -766,11 +767,9 @@
 		gid_t egid = -1;
 		if (getpeereid(conn_info->fd, &euid, &egid) != -1 &&
 		    (euid == 0 || egid == g_gid_valid)) {
-			conn_info->authenticated = 1;
+			conn_info->privileged = 1;
 		}
-		if (conn_info->authenticated == 0) {
-			log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", egid, g_gid_valid);
-		}
+		con_info->authenticated = 1;
 #endif
 	}
 
@@ -787,13 +786,11 @@
 			euid = ucred_geteuid(uc);
 			egid = ucred_getegid(uc);
 			if ((euid == 0) || (egid == g_gid_valid)) {
-				conn_info->authenticated = 1;
+				conn_info->privileged = 1;
 			}
 			ucred_free(uc);
 		}
-		if (conn_info->authenticated == 0) {
-			log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", (int)egid, g_gid_valid);
-		}
+		con_info->authenticated = 1;
 #else
 		log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated "
 				"because platform does not support "
@@ -839,12 +836,10 @@
 		if (cred) {
 			if (cred->uid == 0 || cred->gid == g_gid_valid) {
 				setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
-				conn_info->authenticated = 1;
+				conn_info->privileged = 1;
 			}
 		}
-		if (conn_info->authenticated == 0) {
-			log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", cred->gid, g_gid_valid);
-		}
+		conn_info->authenticated = 1;
 	}
 #endif
 	/*
@@ -879,40 +874,57 @@
 			}
 
 			/*
-			 * If flow control is required of the library handle, determine that
-			 * openais is not in synchronization and that totempg has room available
-			 * to queue a message, otherwise tell the library we are busy and to
-			 * try again later
+			 * Check if this is a privileged call, and if we are allowed to use it
 			 */
-			send_ok_joined_iovec.iov_base = (char *)header;
-			send_ok_joined_iovec.iov_len = header->size;
-			send_ok_joined = totempg_groups_send_ok_joined (openais_group_handle,
-				&send_ok_joined_iovec, 1);
-
-			send_ok =
-				(sync_primary_designated() == 1) && (
-				(ais_service[service]->lib_service[header->id].flow_control == OPENAIS_FLOW_CONTROL_NOT_REQUIRED) ||
-				((ais_service[service]->lib_service[header->id].flow_control == OPENAIS_FLOW_CONTROL_REQUIRED) &&
-				(send_ok_joined) &&
-				(sync_in_process() == 0)));
-
-			if (send_ok) {
-				ais_service[service]->lib_service[header->id].lib_handler_fn(conn_info, header);
-			} else {
-
-				/*
-				 * Overload, tell library to retry
-				 */
+			if ((ais_service[service]->lib_service[header->id].unpriv_call == OPENAIS_UNPRIVILEGED_CALL_NO) &&
+			    !conn_info->privileged) {
 				res_overlay.header.size =
 					ais_service[service]->lib_service[header->id].response_size;
 				res_overlay.header.id =
 					ais_service[service]->lib_service[header->id].response_id;
-				res_overlay.header.error = SA_AIS_ERR_TRY_AGAIN;
+				res_overlay.header.error = SA_AIS_ERR_ACCESS;
 				openais_conn_send_response (
 					conn_info,
 					&res_overlay,
 					res_overlay.header.size);
 			}
+			else {
+				/*
+				 * If flow control is required of the library handle, determine that
+				 * openais is not in synchronization and that totempg has room available
+				 * to queue a message, otherwise tell the library we are busy and to
+				 * try again later
+				 */
+				send_ok_joined_iovec.iov_base = (char *)header;
+				send_ok_joined_iovec.iov_len = header->size;
+				send_ok_joined = totempg_groups_send_ok_joined (openais_group_handle,
+										&send_ok_joined_iovec, 1);
+
+				send_ok =
+					(sync_primary_designated() == 1) && (
+						(ais_service[service]->lib_service[header->id].flow_control == OPENAIS_FLOW_CONTROL_NOT_REQUIRED) ||
+						((ais_service[service]->lib_service[header->id].flow_control == OPENAIS_FLOW_CONTROL_REQUIRED) &&
+						 (send_ok_joined) &&
+						 (sync_in_process() == 0)));
+
+				if (send_ok) {
+					ais_service[service]->lib_service[header->id].lib_handler_fn(conn_info, header);
+				} else {
+
+					/*
+					 * Overload, tell library to retry
+					 */
+					res_overlay.header.size =
+						ais_service[service]->lib_service[header->id].response_size;
+					res_overlay.header.id =
+						ais_service[service]->lib_service[header->id].response_id;
+					res_overlay.header.error = SA_AIS_ERR_TRY_AGAIN;
+					openais_conn_send_response (
+						conn_info,
+						&res_overlay,
+						res_overlay.header.size);
+				}
+			}
 		}
 		conn_info->inb_inuse -= header->size;
 	} /* while */
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to