diff -rpNU3 base/src/bin/initdb/initdb.c sepgsql-new/src/bin/initdb/initdb.c --- base/src/bin/initdb/initdb.c 2009-12-15 16:55:43.000000000 +0900 +++ sepgsql-new/src/bin/initdb/initdb.c 2009-12-15 17:05:57.000000000 +0900 @@ -94,6 +94,7 @@ static bool debug = false; static bool noclean = false; static bool show_setting = false; static char *xlog_dir = ""; +static bool enable_selinux = false; /* internal vars */ @@ -1224,6 +1225,13 @@ setup_config(void) "#default_text_search_config = 'pg_catalog.simple'", repltok); + if (enable_selinux) + { + strcpy(repltok, "sepostgresql = on"); + conflines = replace_token(conflines, + "#sepostgresql = off", repltok); + } + snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data); writefile(path, conflines); @@ -2395,6 +2403,7 @@ usage(const char *progname) printf(_(" -U, --username=NAME database superuser name\n")); printf(_(" -W, --pwprompt prompt for a password for the new superuser\n")); printf(_(" --pwfile=FILE read password for the new superuser from file\n")); + printf(_(" --enable-selinux enables SELinux support, if compiled\n")); printf(_(" -?, --help show this help, then exit\n")); printf(_(" -V, --version output version information, then exit\n")); printf(_("\nLess commonly used options:\n")); @@ -2429,6 +2438,7 @@ main(int argc, char *argv[]) {"auth", required_argument, NULL, 'A'}, {"pwprompt", no_argument, NULL, 'W'}, {"pwfile", required_argument, NULL, 9}, + {"enable-selinux", no_argument, NULL, 10}, {"username", required_argument, NULL, 'U'}, {"help", no_argument, NULL, '?'}, {"version", no_argument, NULL, 'V'}, @@ -2543,6 +2553,9 @@ main(int argc, char *argv[]) case 9: pwfilename = xstrdup(optarg); break; + case 10: + enable_selinux = true; + break; case 's': show_setting = true; break; diff -rpNU3 base/src/bin/pg_dump/pg_dump.c sepgsql-new/src/bin/pg_dump/pg_dump.c --- base/src/bin/pg_dump/pg_dump.c 2009-09-10 20:11:35.000000000 +0900 +++ sepgsql-new/src/bin/pg_dump/pg_dump.c 2009-09-10 20:24:37.000000000 +0900 @@ -118,6 +118,8 @@ static int g_numNamespaces; /* flag to turn on/off dollar quoting */ static int disable_dollar_quoting = 0; +/* flag to turn on/off security context support */ +static int enable_selinux = 0; static void help(const char *progname); static void expand_schema_name_patterns(SimpleStringList *patterns, @@ -267,6 +269,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}, + {"security-context", no_argument, &enable_selinux, 1}, {NULL, 0, NULL, 0} }; @@ -419,6 +422,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, "security-context") == 0) + enable_selinux = 1; else { fprintf(stderr, @@ -549,6 +554,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); + /* check availability of SE-PostgreSQL */ + if (enable_selinux > 0) + { + const char *sepostgresql + = PQparameterStatus(g_conn, "sepostgresql"); + + if (!sepostgresql) + { + write_msg(NULL, "could not obtain server status."); + exit(1); + } + if (strcmp(sepostgresql, "on") != 0) + { + write_msg(NULL, "SE-PostgreSQL is not available now."); + exit(1); + } + } + /* Set the datestyle to ISO to ensure the dump's portability */ do_sql_command(g_conn, "SET DATESTYLE = ISO"); @@ -771,6 +794,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(_(" --security-context enable to dump security context of SE-PostgreSQL\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); @@ -1171,7 +1195,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 > 0 ? "security_context," : ""), fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, classname)); } @@ -1791,11 +1816,29 @@ dumpBlobComments(Archive *AH, void *arg) Oid blobOid; char *comment; + blobOid = atooid(PQgetvalue(res, i, 0)); + if (enable_selinux > 0) + { + char query[256]; + PGresult *sres; + + snprintf(query, sizeof(query), + "SELECT lo_get_security(%u)", blobOid); + sres = PQexec(g_conn, query); + if (sres) + { + if (PQresultStatus(res) == PGRES_TUPLES_OK + && PQntuples(res) == 1) + archprintf(AH, "SELECT lo_set_security(%u, '%s');\n", + blobOid, PQgetvalue(sres, 0, 0)); + PQclear(sres); + } + } + /* 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 ", @@ -2893,6 +2936,7 @@ getTables(int *numTables) int i_owning_col; int i_reltablespace; int i_reloptions; + int i_relseclabel; /* Make sure we are in proper schema */ selectSourceSchema("pg_catalog"); @@ -2932,7 +2976,8 @@ getTables(int *numTables) "d.refobjid as owning_tab, " "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 " + "array_to_string(c.reloptions, ', ') as reloptions, " + "%s as security_label " "from pg_class c " "left join pg_depend d on " "(c.relkind = '%c' and " @@ -2942,6 +2987,7 @@ getTables(int *numTables) "where relkind in ('%c', '%c', '%c', '%c') " "order by c.oid", username_subquery, + (enable_selinux > 0 ? "c.security_context" : "NULL"), RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); @@ -2961,7 +3007,8 @@ getTables(int *numTables) "d.refobjid as owning_tab, " "d.refobjsubid as owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "NULL as reloptions " + "NULL as reloptions, " + "NULL as security_label " "from pg_class c " "left join pg_depend d on " "(c.relkind = '%c' and " @@ -2990,7 +3037,8 @@ getTables(int *numTables) "d.refobjid as owning_tab, " "d.refobjsubid as owning_col, " "NULL as reltablespace, " - "NULL as reloptions " + "NULL as reloptions, " + "NULL as security_label, " "from pg_class c " "left join pg_depend d on " "(c.relkind = '%c' and " @@ -3015,7 +3063,8 @@ getTables(int *numTables) "NULL::oid as owning_tab, " "NULL::int4 as owning_col, " "NULL as reltablespace, " - "NULL as reloptions " + "NULL as reloptions, " + "NULL as security_label, " "from pg_class " "where relkind in ('%c', '%c', '%c') " "order by oid", @@ -3035,7 +3084,8 @@ getTables(int *numTables) "NULL::oid as owning_tab, " "NULL::int4 as owning_col, " "NULL as reltablespace, " - "NULL as reloptions " + "NULL as reloptions, " + "NULL as security_label " "from pg_class " "where relkind in ('%c', '%c', '%c') " "order by oid", @@ -3065,7 +3115,8 @@ getTables(int *numTables) "NULL::oid as owning_tab, " "NULL::int4 as owning_col, " "NULL as reltablespace, " - "NULL as reloptions " + "NULL as reloptions, " + "NULL as security_label " "from pg_class c " "where relkind in ('%c', '%c') " "order by oid", @@ -3108,6 +3159,7 @@ getTables(int *numTables) i_owning_col = PQfnumber(res, "owning_col"); i_reltablespace = PQfnumber(res, "reltablespace"); i_reloptions = PQfnumber(res, "reloptions"); + i_relseclabel = PQfnumber(res, "security_label"); for (i = 0; i < ntups; i++) { @@ -3138,6 +3190,7 @@ getTables(int *numTables) } tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace)); tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions)); + tblinfo[i].relseclabel = strdup(PQgetvalue(res, i, i_relseclabel)); /* other fields were zeroed above */ @@ -4326,6 +4379,7 @@ getTableAttrs(TableInfo *tblinfo, int nu int i_atthasdef; int i_attisdropped; int i_attislocal; + int i_attseclabel; PGresult *res; int ntups; bool hasdefaults; @@ -4368,12 +4422,14 @@ getTableAttrs(TableInfo *tblinfo, int nu /* need left join here to not fail on dropped columns ... */ 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 " + "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname, " + "%s as security_label " "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 > 0 ? "a.security_context" : "NULL"), tbinfo->dobj.catId.oid); } else if (g_fout->remoteVersion >= 70100) @@ -4385,7 +4441,8 @@ getTableAttrs(TableInfo *tblinfo, int nu */ appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, " "a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, " - "format_type(t.oid,a.atttypmod) as atttypname " + "format_type(t.oid,a.atttypmod) as atttypname, " + "NULL as security_label " "from pg_attribute a left join pg_type t " "on a.atttypid = t.oid " "where a.attrelid = '%u'::oid " @@ -4398,7 +4455,8 @@ getTableAttrs(TableInfo *tblinfo, int nu /* format_type not available before 7.1 */ appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, " "attnotnull, atthasdef, false as attisdropped, false as attislocal, " - "(select typname from pg_type where oid = atttypid) as atttypname " + "(select typname from pg_type where oid = atttypid) as atttypname, " + "NULL as security_label " "from pg_attribute a " "where attrelid = '%u'::oid " "and attnum > 0::int2 " @@ -4422,6 +4480,7 @@ getTableAttrs(TableInfo *tblinfo, int nu i_atthasdef = PQfnumber(res, "atthasdef"); i_attisdropped = PQfnumber(res, "attisdropped"); i_attislocal = PQfnumber(res, "attislocal"); + i_attseclabel = PQfnumber(res, "attseclabel"); tbinfo->numatts = ntups; tbinfo->attnames = (char **) malloc(ntups * sizeof(char *)); @@ -4432,6 +4491,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->attseclabel = (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)); @@ -4455,6 +4515,7 @@ getTableAttrs(TableInfo *tblinfo, int nu tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage)); tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't'); tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't'); + tbinfo->attseclabel[j] = strdup(PQgetvalue(res, j, i_attseclabel)); tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't'); tbinfo->attrdefs[j] = NULL; /* fix below */ if (PQgetvalue(res, j, i_atthasdef)[0] == 't') @@ -6436,6 +6497,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) char *procost; char *prorows; char *lanname; + char *proseclabel; char *rettypename; int nallargs; char **allargtypes = NULL; @@ -6465,9 +6527,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "proallargtypes, proargmodes, proargnames, " "provolatile, proisstrict, prosecdef, " "proconfig, procost, prorows, " - "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, " + "%s as security_label " "FROM pg_catalog.pg_proc " "WHERE oid = '%u'::pg_catalog.oid", + (enable_selinux > 0 ? "security_context" : "NULL"), finfo->dobj.catId.oid); } else if (g_fout->remoteVersion >= 80100) @@ -6477,7 +6541,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "proallargtypes, proargmodes, proargnames, " "provolatile, proisstrict, prosecdef, " "null as proconfig, 0 as procost, 0 as prorows, " - "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, " + "NULL as security_label " "FROM pg_catalog.pg_proc " "WHERE oid = '%u'::pg_catalog.oid", finfo->dobj.catId.oid); @@ -6491,7 +6556,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "proargnames, " "provolatile, proisstrict, prosecdef, " "null as proconfig, 0 as procost, 0 as prorows, " - "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, " + "NULL as security_label " "FROM pg_catalog.pg_proc " "WHERE oid = '%u'::pg_catalog.oid", finfo->dobj.catId.oid); @@ -6505,7 +6571,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "null as proargnames, " "provolatile, proisstrict, prosecdef, " "null as proconfig, 0 as procost, 0 as prorows, " - "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, " + "NULL as security_label " "FROM pg_catalog.pg_proc " "WHERE oid = '%u'::pg_catalog.oid", finfo->dobj.catId.oid); @@ -6521,7 +6588,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "proisstrict, " "'f'::boolean as prosecdef, " "null as proconfig, 0 as procost, 0 as prorows, " - "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, " + "NULL as security_label " "FROM pg_proc " "WHERE oid = '%u'::oid", finfo->dobj.catId.oid); @@ -6537,7 +6605,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo) "'f'::boolean as proisstrict, " "'f'::boolean as prosecdef, " "null as proconfig, 0 as procost, 0 as prorows, " - "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname " + "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, " + "NULL as security_label " "FROM pg_proc " "WHERE oid = '%u'::oid", finfo->dobj.catId.oid); @@ -6568,6 +6637,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo) procost = PQgetvalue(res, 0, PQfnumber(res, "procost")); prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows")); lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname")); + proseclabel = PQgetvalue(res, 0, PQfnumber(res, "security_label")); /* * See backend/commands/define.c for details of how the 'AS' clause is @@ -6705,6 +6775,9 @@ dumpFunc(Archive *fout, FuncInfo *finfo) if (prosecdef[0] == 't') appendPQExpBuffer(q, " SECURITY DEFINER"); + if (proseclabel[0] != '\0') + appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", proseclabel); + /* * 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 @@ -8786,6 +8859,10 @@ dumpTableSchema(Archive *fout, TableInfo if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j]) appendPQExpBuffer(q, " NOT NULL"); + if (tbinfo->attseclabel[j] != '\0' && + strcmp(tbinfo->attseclabel[j], tbinfo->relseclabel) != 0) + appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", tbinfo->attseclabel[j]); + actual_atts++; } } @@ -8833,6 +8910,9 @@ dumpTableSchema(Archive *fout, TableInfo if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions); + if (tbinfo->relseclabel[0] != '\0') + appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", tbinfo->relseclabel); + appendPQExpBuffer(q, ";\n"); /* Loop dumping statistics and storage statements */ @@ -10250,6 +10330,13 @@ fmtCopyColumnList(const TableInfo *ti) appendPQExpBuffer(q, "("); needComma = false; + + if (enable_selinux > 0) + { + appendPQExpBuffer(q, "%s", "security_context"); + needComma = true; + } + for (i = 0; i < numatts; i++) { if (attisdropped[i]) diff -rpNU3 base/src/bin/pg_dump/pg_dump.h sepgsql-new/src/bin/pg_dump/pg_dump.h --- base/src/bin/pg_dump/pg_dump.h 2009-02-02 11:47:17.000000000 +0900 +++ sepgsql-new/src/bin/pg_dump/pg_dump.h 2009-03-13 18:14:33.000000000 +0900 @@ -238,6 +238,7 @@ typedef struct _tableInfo char relkind; char *reltablespace; /* relation tablespace */ char *reloptions; /* options specified by WITH (...) */ + char *relseclabel; /* security context 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 **attseclabel; /* security context of attribute (column) */ /* * Note: we need to store per-attribute notnull, default, and constraint diff -rpNU3 base/src/bin/pg_dump/pg_dumpall.c sepgsql-new/src/bin/pg_dump/pg_dumpall.c --- base/src/bin/pg_dump/pg_dumpall.c 2008-01-07 23:51:33.000000000 +0900 +++ sepgsql-new/src/bin/pg_dump/pg_dumpall.c 2009-03-13 18:14:33.000000000 +0900 @@ -67,6 +67,9 @@ static int disable_triggers = 0; static int use_setsessauth = 0; static int server_version; +/* flag to turn on/off security context support */ +static int enable_selinux = 0; + static FILE *OPF; static char *filename = NULL; @@ -119,6 +122,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}, + {"security-context", no_argument, &enable_selinux, 1}, {NULL, 0, NULL, 0} }; @@ -290,6 +294,8 @@ 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, "security-context") == 0) + enable_selinux = 1; else { fprintf(stderr, @@ -316,6 +322,8 @@ main(int argc, char *argv[]) appendPQExpBuffer(pgdumpopts, " --disable-triggers"); if (use_setsessauth) appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization"); + if (enable_selinux) + appendPQExpBuffer(pgdumpopts, " --security-context"); if (optind < argc) { @@ -391,6 +399,24 @@ main(int argc, char *argv[]) } } + /* check availability of SE-PostgreSQL */ + if (enable_selinux > 0) + { + const char *sepostgresql + = PQparameterStatus(conn, "sepostgresql"); + + if (!sepostgresql) + { + fprintf(stderr, "could not obtain server status."); + exit(1); + } + if (strcmp(sepostgresql, "on") != 0) + { + fprintf(stderr, "SE-PostgreSQL is not available now."); + exit(1); + } + } + /* * Open the output file if required, otherwise use stdout */ @@ -505,6 +531,7 @@ help(void) printf(_(" --use-set-session-authorization\n" " use SESSION AUTHORIZATION commands instead of\n" " OWNER TO commands\n")); + printf(_(" --security-context enable to dump security context of SE-PostgreSQL\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); @@ -915,41 +942,46 @@ 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 " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, " + "%s as security_label " "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 > 0 ? "d.security_context" : "NULL")); 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), " "datistemplate, datacl, -1 as datconnlimit, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " + "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, " + "NULL as security_label " "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), " "datistemplate, datacl, -1 as datconnlimit, " - "'pg_default' AS dattablespace " + "'pg_default' AS dattablespace, " + "NULL as security_label " "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), " "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " "datistemplate, '' as datacl, -1 as datconnlimit, " - "'pg_default' AS dattablespace " + "'pg_default' AS dattablespace, " + "NULL as security_label " "FROM pg_database d " "WHERE datallowconn ORDER BY 1"); else @@ -958,16 +990,18 @@ 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), " "'f' as datistemplate, " "'' as datacl, -1 as datconnlimit, " - "'pg_default' AS dattablespace " + "'pg_default' AS dattablespace, " + "NULL as security_label " "FROM pg_database d " "ORDER BY 1"); } + res = executeQuery(conn, buf->data); for (i = 0; i < PQntuples(res); i++) { @@ -978,6 +1012,7 @@ dumpCreateDB(PGconn *conn) char *dbacl = PQgetvalue(res, i, 4); char *dbconnlimit = PQgetvalue(res, i, 5); char *dbtablespace = PQgetvalue(res, i, 6); + char *dbseclabel = PQgetvalue(res, i, 7); char *fdbname; fdbname = strdup(fmtId(dbname)); @@ -1021,6 +1056,9 @@ dumpCreateDB(PGconn *conn) appendPQExpBuffer(buf, " CONNECTION LIMIT = %s", dbconnlimit); + if (dbseclabel[0] != '\0') + appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", dbseclabel); + appendPQExpBuffer(buf, ";\n"); if (strcmp(dbistemplate, "t") == 0)