Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v retrieving revision 1.124 diff -c -r1.124 runtime.sgml *** doc/src/sgml/runtime.sgml 12 Aug 2002 00:36:11 -0000 1.124 --- doc/src/sgml/runtime.sgml 14 Aug 2002 01:30:15 -0000 *************** *** 1191,1196 **** --- 1191,1208 ---- + DB_USER_NAMESPACE (boolean) + + + Prepends the database name and a period to the username when + connecting to the database. This allows per-database users. + The user who ran initdb is excluded from this + handling. + + + + + deadlock timeout Index: src/backend/libpq/auth.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/libpq/auth.c,v retrieving revision 1.82 diff -c -r1.82 auth.c *** src/backend/libpq/auth.c 20 Jun 2002 20:29:28 -0000 1.82 --- src/backend/libpq/auth.c 14 Aug 2002 01:30:15 -0000 *************** *** 117,123 **** version, PG_KRB4_VERSION); return STATUS_ERROR; } ! if (strncmp(port->user, auth_data.pname, SM_USER) != 0) { elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"", port->user, auth_data.pname); --- 117,123 ---- version, PG_KRB4_VERSION); return STATUS_ERROR; } ! if (strncmp(port->user, auth_data.pname, SM_DATABASE_USER) != 0) { elog(LOG, "pg_krb4_recvauth: name \"%s\" != \"%s\"", port->user, auth_data.pname); *************** *** 290,296 **** } kusername = pg_an_to_ln(kusername); ! if (strncmp(port->user, kusername, SM_USER)) { elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"", port->user, kusername); --- 290,296 ---- } kusername = pg_an_to_ln(kusername); ! if (strncmp(port->user, kusername, SM_DATABASE_USER)) { elog(LOG, "pg_krb5_recvauth: user name \"%s\" != krb5 name \"%s\"", port->user, kusername); Index: src/backend/postmaster/postmaster.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v retrieving revision 1.283 diff -c -r1.283 postmaster.c *** src/backend/postmaster/postmaster.c 10 Aug 2002 20:29:18 -0000 1.283 --- src/backend/postmaster/postmaster.c 14 Aug 2002 01:30:17 -0000 *************** *** 116,122 **** sigset_t UnBlockSig, BlockSig, AuthBlockSig; - #else int UnBlockSig, BlockSig, --- 116,121 ---- *************** *** 191,196 **** --- 190,197 ---- bool HostnameLookup; /* for ps display */ bool ShowPortNumber; bool Log_connections = false; + bool Db_user_namespace = false; + /* Startup/shutdown state */ static pid_t StartupPID = 0, *************** *** 208,213 **** --- 209,216 ---- bool ClientAuthInProgress = false; /* T during new-client authentication */ + static char InstallUser[SM_USER+1]; + /* * State for assigning random salts and cancel keys. * Also, the global MyCancelKey passes the cancel key assigned to a given *************** *** 258,263 **** --- 261,267 ---- static void SignalChildren(int signal); static int CountChildren(void); static bool CreateOptsFile(int argc, char *argv[]); + static bool GetInstallUser(void); static pid_t SSDataBase(int xlop); void postmaster_error(const char *fmt,...) *************** *** 690,695 **** --- 694,702 ---- if (!CreateOptsFile(argc, argv)) ExitPostmaster(1); + if (!GetInstallUser()) + ExitPostmaster(1); + /* * Set up signal handlers for the postmaster process. * *************** *** 1161,1166 **** --- 1168,1182 ---- if (port->user[0] == '\0') elog(FATAL, "no PostgreSQL user name specified in startup packet"); + /* Prefix database name for per-db user namespace */ + if (Db_user_namespace && strcmp(port->user, InstallUser)) + { + char hold_user[SM_DATABASE_USER]; + snprintf(hold_user, SM_DATABASE_USER, "%s.%s", port->database, + port->user); + strcpy(port->user, hold_user); + } + /* * If we're going to reject the connection due to database state, say * so now instead of wasting cycles on an authentication exchange. *************** *** 2587,2597 **** if (FindExec(fullprogname, argv[0], "postmaster") < 0) return false; ! filename = palloc(strlen(DataDir) + 20); sprintf(filename, "%s/postmaster.opts", DataDir); ! fp = fopen(filename, "w"); ! if (fp == NULL) { postmaster_error("cannot create file %s: %s", filename, strerror(errno)); --- 2603,2612 ---- if (FindExec(fullprogname, argv[0], "postmaster") < 0) return false; ! filename = palloc(strlen(DataDir) + 17); sprintf(filename, "%s/postmaster.opts", DataDir); ! if ((fp = fopen(filename, "w")) == NULL) { postmaster_error("cannot create file %s: %s", filename, strerror(errno)); *************** *** 2614,2619 **** --- 2629,2669 ---- return true; } + /* + * Load install user so db_user_namespace can skip it. + */ + static bool + GetInstallUser(void) + { + char *filename; + FILE *fp; + + filename = palloc(strlen(DataDir) + 14); + sprintf(filename, "%s/PG_INSTALLER", DataDir); + + if ((fp = fopen(filename, "r")) == NULL) + { + postmaster_error("cannot open file %s: %s", + filename, strerror(errno)); + return false; + } + + if (fgets(InstallUser, SM_USER+1, fp) == NULL) + { + postmaster_error("cannot read file %s: %s", + filename, strerror(errno)); + return false; + } + + /* Trim off trailing newline */ + if (strchr(InstallUser, '\n') != NULL) + *strchr(InstallUser, '\n') = '\0'; + + fclose(fp); + return true; + } + + /* * This should be used only for reporting "interactive" errors (ie, errors * during startup. Once the postmaster is launched, use elog. Index: src/backend/utils/misc/guc.c =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v retrieving revision 1.79 diff -c -r1.79 guc.c *** src/backend/utils/misc/guc.c 12 Aug 2002 00:36:11 -0000 1.79 --- src/backend/utils/misc/guc.c 14 Aug 2002 01:30:20 -0000 *************** *** 482,487 **** --- 482,491 ---- { "transform_null_equals", PGC_USERSET }, &Transform_null_equals, false, NULL, NULL }, + { + { "db_user_namespace", PGC_SIGHUP }, &Db_user_namespace, + false, NULL, NULL + }, { { NULL, 0 }, NULL, false, NULL, NULL Index: src/backend/utils/misc/postgresql.conf.sample =================================================================== RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v retrieving revision 1.44 diff -c -r1.44 postgresql.conf.sample *** src/backend/utils/misc/postgresql.conf.sample 12 Aug 2002 00:36:12 -0000 1.44 --- src/backend/utils/misc/postgresql.conf.sample 14 Aug 2002 01:30:20 -0000 *************** *** 113,119 **** # # Message display # - #server_min_messages = notice # Values, in order of decreasing detail: # debug5, debug4, debug3, debug2, debug1, # info, notice, warning, error, log, fatal, --- 113,118 ---- *************** *** 201,203 **** --- 200,203 ---- #sql_inheritance = true #transform_null_equals = false #statement_timeout = 0 # 0 is disabled + #db_user_namespace = false Index: src/bin/initdb/initdb.sh =================================================================== RCS file: /cvsroot/pgsql-server/src/bin/initdb/initdb.sh,v retrieving revision 1.165 diff -c -r1.165 initdb.sh *** src/bin/initdb/initdb.sh 8 Aug 2002 19:39:05 -0000 1.165 --- src/bin/initdb/initdb.sh 14 Aug 2002 01:30:20 -0000 *************** *** 603,608 **** --- 603,613 ---- # Top level PG_VERSION is checked by bootstrapper, so make it first echo "$short_version" > "$PGDATA/PG_VERSION" || exit_nicely + # Top level PG_INSTALLER is used by db_user_namespace to prevent username + # mapping just for the install user. + echo "$POSTGRES_SUPERUSERNAME" > "$PGDATA/PG_INSTALLER" || exit_nicely + + cat "$POSTGRES_BKI" \ | sed -e "s/POSTGRES/$POSTGRES_SUPERUSERNAME/g" \ -e "s/ENCODING/$MULTIBYTEID/g" \ Index: src/include/libpq/libpq-be.h =================================================================== RCS file: /cvsroot/pgsql-server/src/include/libpq/libpq-be.h,v retrieving revision 1.32 diff -c -r1.32 libpq-be.h *** src/include/libpq/libpq-be.h 20 Jun 2002 20:29:49 -0000 1.32 --- src/include/libpq/libpq-be.h 14 Aug 2002 01:30:20 -0000 *************** *** 59,65 **** ProtocolVersion proto; char database[SM_DATABASE + 1]; ! char user[SM_USER + 1]; char options[SM_OPTIONS + 1]; char tty[SM_TTY + 1]; char auth_arg[MAX_AUTH_ARG]; --- 59,65 ---- ProtocolVersion proto; char database[SM_DATABASE + 1]; ! char user[SM_DATABASE_USER + 1]; char options[SM_OPTIONS + 1]; char tty[SM_TTY + 1]; char auth_arg[MAX_AUTH_ARG]; *************** *** 72,78 **** SSL *ssl; X509 *peer; char peer_dn[128 + 1]; ! char peer_cn[SM_USER + 1]; unsigned long count; #endif } Port; --- 72,78 ---- SSL *ssl; X509 *peer; char peer_dn[128 + 1]; ! char peer_cn[SM_DATABASE_USER + 1]; unsigned long count; #endif } Port; Index: src/include/libpq/pqcomm.h =================================================================== RCS file: /cvsroot/pgsql-server/src/include/libpq/pqcomm.h,v retrieving revision 1.65 diff -c -r1.65 pqcomm.h *** src/include/libpq/pqcomm.h 12 Aug 2002 14:35:26 -0000 1.65 --- src/include/libpq/pqcomm.h 14 Aug 2002 01:30:20 -0000 *************** *** 114,119 **** --- 114,121 ---- #define SM_DATABASE 64 /* SM_USER should be the same size as the others. bjm 2002-06-02 */ #define SM_USER 32 + /* We prepend database name if db_user_namespace true. */ + #define SM_DATABASE_USER (SM_DATABASE+SM_USER) #define SM_OPTIONS 64 #define SM_UNUSED 64 #define SM_TTY 64 *************** *** 124,135 **** --- 126,139 ---- { ProtocolVersion protoVersion; /* Protocol version */ char database[SM_DATABASE]; /* Database name */ + /* Db_user_namespace prepends dbname */ char user[SM_USER]; /* User name */ char options[SM_OPTIONS]; /* Optional additional args */ char unused[SM_UNUSED]; /* Unused */ char tty[SM_TTY]; /* Tty for debug output */ } StartupPacket; + extern bool Db_user_namespace; /* These are the authentication requests sent by the backend. */