[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