Просмотр исходного кода

Support for uidgid feature

git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@2198 fd59a12c-fef9-0310-b244-a6a79926bd2f
Jan Friesse 16 лет назад
Родитель
Сommit
ae22983140
4 измененных файлов с 170 добавлено и 5 удалено
  1. 95 3
      exec/coroparse.c
  2. 9 2
      exec/main.c
  3. 50 0
      exec/mainconfig.c
  4. 16 0
      exec/mainconfig.h

+ 95 - 3
exec/coroparse.c

@@ -46,6 +46,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <dirent.h>
 
 #include <corosync/lcr/lcr_comp.h>
 #include <corosync/engine/objdb.h>
@@ -83,10 +84,20 @@ static char *remove_whitespace(char *string)
 	return start;
 }
 
+#define PCHECK_ADD_SUBSECTION 1
+#define PCHECK_ADD_ITEM       2
+
+typedef int (*parser_check_item_f)(struct objdb_iface_ver0 *objdb,
+				hdb_handle_t parent_handle,
+				int type,
+				const char *name,
+				const char **error_string);
+
 static int parse_section(FILE *fp,
 			 struct objdb_iface_ver0 *objdb,
 			 hdb_handle_t parent_handle,
-			 const char **error_string)
+			 const char **error_string,
+			 parser_check_item_f parser_check_item_call)
 {
 	char line[512];
 	int i;
@@ -123,9 +134,15 @@ static int parse_section(FILE *fp,
 
 			loc--;
 			*loc = '\0';
+			if (parser_check_item_call) {
+				if (!parser_check_item_call(objdb, parent_handle, PCHECK_ADD_SUBSECTION,
+				    section, error_string))
+					    return -1;
+			}
+
 			objdb->object_create (parent_handle, &new_parent,
 					      section, strlen (section));
-			if (parse_section(fp, objdb, new_parent, error_string))
+			if (parse_section(fp, objdb, new_parent, error_string, parser_check_item_call))
 				return -1;
 		}
 
@@ -137,6 +154,11 @@ static int parse_section(FILE *fp,
 			*(loc-1) = '\0';
 			key = remove_whitespace(line);
 			value = remove_whitespace(loc);
+			if (parser_check_item_call) {
+				if (!parser_check_item_call(objdb, parent_handle, PCHECK_ADD_ITEM,
+				    key, error_string))
+					    return -1;
+			}
 			objdb->object_key_create (parent_handle, key,
 				strlen (key),
 				value, strlen (value) + 1);
@@ -155,7 +177,73 @@ static int parse_section(FILE *fp,
 	return 0;
 }
 
+static int parser_check_item_uidgid(struct objdb_iface_ver0 *objdb,
+			hdb_handle_t parent_handle,
+			int type,
+			const char *name,
+			const char **error_string)
+{
+	if (type == PCHECK_ADD_SUBSECTION) {
+		if (parent_handle != OBJECT_PARENT_HANDLE) {
+			*error_string = "uidgid: Can't add second level subsection";
+			return 0;
+		}
+
+		if (strcmp (name, "uidgid") != 0) {
+			*error_string = "uidgid: Can't add subsection different then uidgid";
+			return 0;
+		}
+	}
+
+	if (type == PCHECK_ADD_ITEM) {
+		if (!(strcmp (name, "uid") == 0 || strcmp (name, "gid") == 0)) {
+			*error_string = "uidgid: Only uid and gid are allowed items";
+			return 0;
+		}
+	}
 
+	return 1;
+}
+
+static int read_uidgid_files_into_objdb(
+	struct objdb_iface_ver0 *objdb,
+	const char **error_string)
+{
+	FILE *fp;
+	const char *dirname;
+	DIR *dp;
+	struct dirent *dirent;
+	char filename[PATH_MAX + NAME_MAX + 1];
+	int res = 0;
+
+	dirname = SYSCONFDIR "/corosync/uidgid.d";
+	dp = opendir (dirname);
+
+	if (dp == NULL)
+		return 0;
+
+	while ((dirent = readdir (dp))) {
+		if (dirent->d_type == DT_REG) {
+			snprintf(filename, sizeof (filename), "%s/%s", dirname, dirent->d_name);
+
+			fp = fopen (filename, "r");
+			if (fp == NULL) continue;
+
+			res = parse_section(fp, objdb, OBJECT_PARENT_HANDLE, error_string, parser_check_item_uidgid);
+
+			fclose (fp);
+
+			if (res != 0) {
+				goto error_exit;
+			}
+		}
+	}
+
+error_exit:
+	closedir(dp);
+
+	return res;
+}
 
 /* Read config file and load into objdb */
 static int read_config_file_into_objdb(
@@ -180,10 +268,14 @@ static int read_config_file_into_objdb(
 		return -1;
 	}
 
-	res = parse_section(fp, objdb, OBJECT_PARENT_HANDLE, error_string);
+	res = parse_section(fp, objdb, OBJECT_PARENT_HANDLE, error_string, NULL);
 
 	fclose(fp);
 
+	if (res == 0) {
+	        res = read_uidgid_files_into_objdb(objdb, error_string);
+	}
+
 	if (res == 0) {
 		snprintf (error_reason, sizeof(error_string_response),
 			"Successfully read main configuration file '%s'.\n", filename);

+ 9 - 2
exec/main.c

@@ -150,6 +150,7 @@ void corosync_request_shutdown (void)
 	poll_stop (0);
 	totempg_finalize ();
 	coroipcs_ipc_exit ();
+
 	corosync_exit_error (AIS_DONE_EXIT);
 }
 
@@ -482,12 +483,18 @@ static coroipcs_handler_fn_lvalue corosync_handler_fn_get (unsigned int service,
 
 static int corosync_security_valid (int euid, int egid)
 {
+	struct list_head *iter;
 	if (euid == 0 || egid == 0) {
 		return (1);
 	}
-	if (euid == ug_config.uid || egid == ug_config.gid) {
-		return (1);
+
+	for (iter = ug_config.uidgid_list.next; iter != &ug_config.uidgid_list; iter = iter->next) {
+		struct uidgid_item *ugi = list_entry (iter, struct uidgid_item, list);
+
+		if (euid == ugi->uid || egid == ugi->gid)
+			return (1);
 	}
+
 	return (0);
 }
 

+ 50 - 0
exec/mainconfig.c

@@ -670,6 +670,54 @@ static void add_logsys_config_notification(
 
 }
 
+static int corosync_main_config_read_uidgid (
+	struct objdb_iface_ver0 *objdb,
+	const char **error_string,
+	struct ug_config *ug_config)
+{
+	hdb_handle_t object_find_handle;
+	hdb_handle_t object_service_handle;
+	char *value;
+	int uid, gid;
+	struct uidgid_item *ugi;
+
+	list_init (&ug_config->uidgid_list);
+
+	objdb->object_find_create (
+		OBJECT_PARENT_HANDLE,
+		"uidgid",
+		strlen ("uidgid"),
+		&object_find_handle);
+
+	while (objdb->object_find_next (
+		object_find_handle,
+		&object_service_handle) == 0) {
+		uid = -1;
+		gid = -1;
+
+		if (!objdb_get_string (objdb,object_service_handle, "uid", &value)) {
+			uid = uid_determine(value);
+		}
+
+		if (!objdb_get_string (objdb,object_service_handle, "gid", &value)) {
+			gid = gid_determine(value);
+		}
+
+		if (uid > -1 || gid > -1) {
+			ugi = malloc (sizeof (*ugi));
+			if (ugi == NULL) {
+				_corosync_out_of_memory_error();
+			}
+			ugi->uid = uid;
+			ugi->gid = gid;
+			list_add (&ugi->list, &ug_config->uidgid_list);
+		}
+	}
+	objdb->object_find_destroy (object_find_handle);
+
+	return 0;
+}
+
 int corosync_main_config_read (
 	struct objdb_iface_ver0 *objdb,
 	const char **error_string,
@@ -718,6 +766,8 @@ int corosync_main_config_read (
 		ug_config->gid = gid_determine("ais");
 	}
 
+	corosync_main_config_read_uidgid (objdb, error_string, ug_config);
+
 	add_logsys_config_notification(objdb);
 
 	return 0;

+ 16 - 0
exec/mainconfig.h

@@ -37,6 +37,7 @@
 
 #include <corosync/engine/objdb.h>
 #include <corosync/engine/logsys.h>
+#include <corosync/list.h>
 
 /*
  * All service handlers in the AIS
@@ -49,14 +50,29 @@ struct dynamic_service {
 };
 #define MAX_DYNAMIC_SERVICES 128
 
+/*
+ * Structure describing cached uidgid item
+ */
+struct uidgid_item {
+	struct list_head list;
+	int uid;
+	int gid;
+};
+
 struct ug_config {
 	/*
 	 * user/group to run as
 	 */
 	int uid;
 	int gid;
+
+	/*
+	 * Allowed users/group to connect. This is of type uidgid item.
+	 */
+	struct list_head uidgid_list;
 };
 
+
 extern int corosync_main_config_read (
 	struct objdb_iface_ver0 *objdb,
 	const char **error_string,