[3/4] - sepostgresql-pg_dump-8.4devel-3.patch

This patch gives us a feature to dump database with security attribute.
It is turned on with '--enable-selinux' option at pg_dump/pg_dumpall,
when the server works as SE- version.
No need to say, users need to have enough capabilities to dump whole of
database. It it same when they tries to restore the database.

-- 
OSS Platform Development Division, NEC
KaiGai Kohei <[EMAIL PROTECTED]>
diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
--- pgace/src/bin/pg_dump/pg_dump.c	2008-02-03 01:18:48.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.c	2008-02-03 01:26:35.000000000 +0900
@@ -118,6 +118,9 @@ static int	g_numNamespaces;
 /* flag to turn on/off dollar quoting */
 static int	disable_dollar_quoting = 0;
 
+/* flag to tuen on/off SE-PostgreSQL support */
+#define SELINUX_SYSATTR_NAME	"security_context"
+static int enable_selinux = 0;
 
 static void help(const char *progname);
 static void expand_schema_name_patterns(SimpleStringList *patterns,
@@ -267,6 +270,7 @@ main(int argc, char **argv)
 		{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
 		{"disable-triggers", no_argument, &disable_triggers, 1},
 		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"enable-selinux", no_argument, &enable_selinux, 1},
 
 		{NULL, 0, NULL, 0}
 	};
@@ -419,6 +423,8 @@ main(int argc, char **argv)
 					disable_triggers = 1;
 				else if (strcmp(optarg, "use-set-session-authorization") == 0)
 					use_setsessauth = 1;
+				else if (strcmp(optarg, "enable-selinux") == 0)
+					enable_selinux = 1;
 				else
 				{
 					fprintf(stderr,
@@ -549,6 +555,24 @@ main(int argc, char **argv)
 	std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
 	g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
 
+	if (enable_selinux) {
+		/* confirm whther server support SELinux features */
+		const char *tmp = PQparameterStatus(g_conn, "security_sysattr_name");
+
+		if (!tmp) {
+			write_msg(NULL, "could not get security_sysattr_name from libpq\n");
+			exit(1);
+		}
+		if (!!strcmp(SELINUX_SYSATTR_NAME, tmp) != 0) {
+			write_msg(NULL, "server does not have SELinux feature\n");
+			exit(1);
+		}
+		if (g_fout->remoteVersion < 80204) {
+			write_msg(NULL, "server version is too old (%u)\n", g_fout->remoteVersion);
+			exit(1);
+		}
+	}
+
 	/* Set the datestyle to ISO to ensure the dump's portability */
 	do_sql_command(g_conn, "SET DATESTYLE = ISO");
 
@@ -771,6 +795,7 @@ help(const char *progname)
 	printf(_("  --use-set-session-authorization\n"
 			 "                              use SESSION AUTHORIZATION commands instead of\n"
 	"                              ALTER OWNER commands to set ownership\n"));
+	printf(_("  --enable-selinux            enable to dump security context in SE-PostgreSQL\n"));
 
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -1160,7 +1185,8 @@ dumpTableData_insert(Archive *fout, void
 	if (fout->remoteVersion >= 70100)
 	{
 		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
-						  "SELECT * FROM ONLY %s",
+						  "SELECT * %s FROM ONLY %s",
+						  (!enable_selinux ? "" : "," SELINUX_SYSATTR_NAME),
 						  fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
 										 classname));
 	}
@@ -1774,11 +1800,32 @@ dumpBlobComments(Archive *AH, void *arg)
 			Oid			blobOid;
 			char	   *comment;
 
+			blobOid = atooid(PQgetvalue(res, i, 0));
+
+			/* dump security context of binary large object */
+			if (enable_selinux) {
+				PGresult	*__res;
+				char		query[512];
+
+				snprintf(query, sizeof(query),
+						 "SELECT lo_get_security(%u)", blobOid);
+				__res = PQexec(g_conn, query);
+				check_sql_result(__res, g_conn, query, PGRES_TUPLES_OK);
+
+				if (PQntuples(__res) != 1) {
+					write_msg(NULL, "lo_get_security(%u) returns %d tuples\n",
+							  blobOid, PQntuples(__res));
+					exit_nicely();
+				}
+				archprintf(AH, "SELECT lo_set_security(%u, '%s');\n",
+						   blobOid, PQgetvalue(__res, 0, 0));
+				PQclear(__res);
+			}
+
 			/* ignore blobs without comments */
 			if (PQgetisnull(res, i, 1))
 				continue;
 
-			blobOid = atooid(PQgetvalue(res, i, 0));
 			comment = PQgetvalue(res, i, 1);
 
 			printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
@@ -2886,6 +2933,7 @@ getTables(int *numTables)
 	int			i_owning_col;
 	int			i_reltablespace;
 	int			i_reloptions;
+	int			i_selinux;
 
 	/* Make sure we are in proper schema */
 	selectSourceSchema("pg_catalog");
@@ -2926,6 +2974,7 @@ getTables(int *numTables)
 						  "d.refobjsubid as owning_col, "
 						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
 						  "array_to_string(c.reloptions, ', ') as reloptions "
+						  "%s "
 						  "from pg_class c "
 						  "left join pg_depend d on "
 						  "(c.relkind = '%c' and "
@@ -2935,6 +2984,7 @@ getTables(int *numTables)
 						  "where relkind in ('%c', '%c', '%c', '%c') "
 						  "order by c.oid",
 						  username_subquery,
+						  (!enable_selinux ? "" : ",c." SELINUX_SYSATTR_NAME),
 						  RELKIND_SEQUENCE,
 						  RELKIND_RELATION, RELKIND_SEQUENCE,
 						  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
@@ -3101,6 +3151,7 @@ getTables(int *numTables)
 	i_owning_col = PQfnumber(res, "owning_col");
 	i_reltablespace = PQfnumber(res, "reltablespace");
 	i_reloptions = PQfnumber(res, "reloptions");
+	i_selinux = PQfnumber(res, SELINUX_SYSATTR_NAME);
 
 	for (i = 0; i < ntups; i++)
 	{
@@ -3131,6 +3182,9 @@ getTables(int *numTables)
 		}
 		tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
 		tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
+		tblinfo[i].relsecurity = NULL;
+		if (i_selinux >= 0)
+			tblinfo[i].relsecurity = strdup(PQgetvalue(res, i, i_selinux));
 
 		/* other fields were zeroed above */
 
@@ -4319,6 +4373,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 	int			i_atthasdef;
 	int			i_attisdropped;
 	int			i_attislocal;
+	int			i_attselinux;
 	PGresult   *res;
 	int			ntups;
 	bool		hasdefaults;
@@ -4362,11 +4417,13 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
 				  "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
 				   "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
+							  "%s "		/* security context, if required */
 			 "from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
 							  "on a.atttypid = t.oid "
 							  "where a.attrelid = '%u'::pg_catalog.oid "
 							  "and a.attnum > 0::pg_catalog.int2 "
 							  "order by a.attrelid, a.attnum",
+							  (!enable_selinux ? "" : ",a." SELINUX_SYSATTR_NAME),
 							  tbinfo->dobj.catId.oid);
 		}
 		else if (g_fout->remoteVersion >= 70100)
@@ -4415,6 +4472,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 		i_atthasdef = PQfnumber(res, "atthasdef");
 		i_attisdropped = PQfnumber(res, "attisdropped");
 		i_attislocal = PQfnumber(res, "attislocal");
+		i_attselinux = PQfnumber(res, SELINUX_SYSATTR_NAME);
 
 		tbinfo->numatts = ntups;
 		tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
@@ -4425,6 +4483,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 		tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
 		tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
 		tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
+		tbinfo->attsecurity = (char **) malloc(ntups * sizeof(char *));
 		tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
 		tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
 		tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -4456,6 +4515,11 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			tbinfo->inhAttrs[j] = false;
 			tbinfo->inhAttrDef[j] = false;
 			tbinfo->inhNotNull[j] = false;
+
+			/* security attribute, if defined */
+			tbinfo->attsecurity[j] = NULL;
+			if (i_attselinux >= 0 && !PQgetisnull(res, j, i_attselinux))
+				tbinfo->attsecurity[j] = strdup(PQgetvalue(res, j, i_attselinux));
 		}
 
 		PQclear(res);
@@ -6428,6 +6492,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	char	   *proconfig;
 	char	   *procost;
 	char	   *prorows;
+	char	   *proselinux = NULL;
 	char	   *lanname;
 	char	   *rettypename;
 	int			nallargs;
@@ -6459,8 +6524,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "provolatile, proisstrict, prosecdef, "
 						  "proconfig, procost, prorows, "
 						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+						  "%s "		/* security context, if required */
 						  "FROM pg_catalog.pg_proc "
 						  "WHERE oid = '%u'::pg_catalog.oid",
+						  (!enable_selinux ? "" : "," SELINUX_SYSATTR_NAME),
 						  finfo->dobj.catId.oid);
 	}
 	else if (g_fout->remoteVersion >= 80100)
@@ -6562,6 +6629,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
 	lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
 
+	if (enable_selinux) {
+		int i_selinux = PQfnumber(res, "security_context");
+
+		if (i_selinux >= 0 && !PQgetisnull(res, 0, i_selinux))
+			proselinux = PQgetvalue(res, 0, i_selinux);
+	}
+
 	/*
 	 * See backend/commands/define.c for details of how the 'AS' clause is
 	 * used.
@@ -6698,6 +6772,9 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	if (prosecdef[0] == 't')
 		appendPQExpBuffer(q, " SECURITY DEFINER");
 
+	if (proselinux)
+		appendPQExpBuffer(q, " CONTEXT = '%s'", proselinux);
+
 	/*
 	 * COST and ROWS are emitted only if present and not default, so as not to
 	 * break backwards-compatibility of the dump without need.	Keep this code
@@ -8779,6 +8856,9 @@ dumpTableSchema(Archive *fout, TableInfo
 				if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
 					appendPQExpBuffer(q, " NOT NULL");
 
+				if (enable_selinux && tbinfo->attsecurity[j])
+					appendPQExpBuffer(q, " CONTEXT = '%s'", tbinfo->attsecurity[j]);
+
 				actual_atts++;
 			}
 		}
@@ -8826,6 +8906,9 @@ dumpTableSchema(Archive *fout, TableInfo
 		if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
 			appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
 
+		if (enable_selinux && tbinfo->relsecurity)
+			appendPQExpBuffer(q, " CONTEXT = '%s'", tbinfo->relsecurity);
+
 		appendPQExpBuffer(q, ";\n");
 
 		/* Loop dumping statistics and storage statements */
@@ -10243,6 +10326,12 @@ fmtCopyColumnList(const TableInfo *ti)
 
 	appendPQExpBuffer(q, "(");
 	needComma = false;
+
+	if (enable_selinux) {
+		appendPQExpBuffer(q, SELINUX_SYSATTR_NAME);
+		needComma = true;
+	}
+
 	for (i = 0; i < numatts; i++)
 	{
 		if (attisdropped[i])
diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.h sepgsql/src/bin/pg_dump/pg_dump.h
--- pgace/src/bin/pg_dump/pg_dump.h	2008-01-08 01:39:49.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.h	2008-01-10 18:25:12.000000000 +0900
@@ -238,6 +238,7 @@ typedef struct _tableInfo
 	char		relkind;
 	char	   *reltablespace;	/* relation tablespace */
 	char	   *reloptions;		/* options specified by WITH (...) */
+	char	   *relsecurity;	/* security attribute of the relation */
 	bool		hasindex;		/* does it have any indexes? */
 	bool		hasrules;		/* does it have any rules? */
 	bool		hasoids;		/* does it have OIDs? */
@@ -262,6 +263,7 @@ typedef struct _tableInfo
 	char	   *typstorage;		/* type storage scheme */
 	bool	   *attisdropped;	/* true if attr is dropped; don't dump it */
 	bool	   *attislocal;		/* true if attr has local definition */
+	char	  **attsecurity;	/* security attribute of attribute (column) */
 
 	/*
 	 * Note: we need to store per-attribute notnull, default, and constraint
diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpall.c
--- pgace/src/bin/pg_dump/pg_dumpall.c	2008-01-08 01:39:49.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dumpall.c	2008-01-10 18:25:12.000000000 +0900
@@ -67,6 +67,10 @@ static int	disable_triggers = 0;
 static int	use_setsessauth = 0;
 static int	server_version;
 
+/* flag to tuen on/off SE-PostgreSQL support */
+#define SELINUX_SYSATTR_NAME	"security_context"
+static int  enable_selinux = 0;
+
 static FILE *OPF;
 static char *filename = NULL;
 
@@ -119,6 +123,7 @@ main(int argc, char *argv[])
 		{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
 		{"disable-triggers", no_argument, &disable_triggers, 1},
 		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"enable-selinux", no_argument, NULL, 1001},
 
 		{NULL, 0, NULL, 0}
 	};
@@ -290,6 +295,10 @@ main(int argc, char *argv[])
 					appendPQExpBuffer(pgdumpopts, " --disable-triggers");
 				else if (strcmp(optarg, "use-set-session-authorization") == 0)
 					 /* no-op, still allowed for compatibility */ ;
+				else if (strcmp(optarg, "enable-selinux") == 0) {
+					appendPQExpBuffer(pgdumpopts, " --enable-selinux");
+					enable_selinux = 1;
+				}
 				else
 				{
 					fprintf(stderr,
@@ -300,6 +309,11 @@ main(int argc, char *argv[])
 				}
 				break;
 
+			case 1001:
+				appendPQExpBuffer(pgdumpopts, " --enable-selinux");
+				enable_selinux = 1;
+				break;
+
 			case 0:
 				break;
 
@@ -391,6 +405,24 @@ main(int argc, char *argv[])
 		}
 	}
 
+	if (enable_selinux) {
+        /* confirm whther server support SELinux features */
+        const char *tmp = PQparameterStatus(conn, "security_sysattr_name");
+
+        if (!tmp) {
+			fprintf(stderr, "could not get security_sysattr_name from libpq\n");
+            exit(1);
+        }
+        if (!!strcmp(SELINUX_SYSATTR_NAME, tmp) != 0) {
+			fprintf(stderr, "server does not have SELinux feature\n");
+            exit(1);
+        }
+        if (server_version < 80204) {
+			fprintf(stderr, "server version is too old (%u)\n", server_version);
+            exit(1);
+        }
+	}
+
 	/*
 	 * Open the output file if required, otherwise use stdout
 	 */
@@ -505,6 +537,7 @@ help(void)
 	printf(_("  --use-set-session-authorization\n"
 			 "                           use SESSION AUTHORIZATION commands instead of\n"
 			 "                           OWNER TO commands\n"));
+	printf(_("  --enable-selinux         enable to dump security attribute\n"));
 
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -915,16 +948,18 @@ dumpCreateDB(PGconn *conn)
 	fprintf(OPF, "--\n-- Database creation\n--\n\n");
 
 	if (server_version >= 80100)
-		res = executeQuery(conn,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 						   "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
 						   "pg_encoding_to_char(d.encoding), "
 						   "datistemplate, datacl, datconnlimit, "
 						   "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
+						   "%s "
 			  "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
-						   "WHERE datallowconn ORDER BY 1");
+						   "WHERE datallowconn ORDER BY 1",
+						   (!enable_selinux ? "" : "d." SELINUX_SYSATTR_NAME));
 	else if (server_version >= 80000)
-		res = executeQuery(conn,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 						   "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
 						   "pg_encoding_to_char(d.encoding), "
@@ -933,7 +968,7 @@ dumpCreateDB(PGconn *conn)
 		   "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
 						   "WHERE datallowconn ORDER BY 1");
 	else if (server_version >= 70300)
-		res = executeQuery(conn,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 						   "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
 						   "pg_encoding_to_char(d.encoding), "
@@ -942,7 +977,7 @@ dumpCreateDB(PGconn *conn)
 		   "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
 						   "WHERE datallowconn ORDER BY 1");
 	else if (server_version >= 70100)
-		res = executeQuery(conn,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 						   "coalesce("
 					"(select usename from pg_shadow where usesysid=datdba), "
@@ -958,7 +993,7 @@ dumpCreateDB(PGconn *conn)
 		 * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal
 		 * with getting a NULL by not printing any OWNER clause.
 		 */
-		res = executeQuery(conn,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 					"(select usename from pg_shadow where usesysid=datdba), "
 						   "pg_encoding_to_char(d.encoding), "
@@ -968,6 +1003,7 @@ dumpCreateDB(PGconn *conn)
 						   "FROM pg_database d "
 						   "ORDER BY 1");
 	}
+	res = executeQuery(conn, buf->data);
 
 	for (i = 0; i < PQntuples(res); i++)
 	{
@@ -978,6 +1014,7 @@ dumpCreateDB(PGconn *conn)
 		char	   *dbacl = PQgetvalue(res, i, 4);
 		char	   *dbconnlimit = PQgetvalue(res, i, 5);
 		char	   *dbtablespace = PQgetvalue(res, i, 6);
+		char	   *dbsecurity = PQgetvalue(res, i, 7);
 		char	   *fdbname;
 
 		fdbname = strdup(fmtId(dbname));
@@ -1021,6 +1058,9 @@ dumpCreateDB(PGconn *conn)
 				appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
 								  dbconnlimit);
 
+			if (enable_selinux && dbsecurity)
+				appendPQExpBuffer(buf, " CONTEXT = '%s'", dbsecurity);
+
 			appendPQExpBuffer(buf, ";\n");
 
 			if (strcmp(dbistemplate, "t") == 0)
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to