mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
pgindent run before 6.3 release, with Thomas' requested changes.
This commit is contained in:
@ -43,34 +43,39 @@ static void CheckPgUserAclNotNull(void);
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
static
|
||||
void UpdatePgPwdFile(char* sql) {
|
||||
void
|
||||
UpdatePgPwdFile(char *sql)
|
||||
{
|
||||
|
||||
char* filename;
|
||||
char* tempname;
|
||||
char *filename;
|
||||
char *tempname;
|
||||
|
||||
/* Create a temporary filename to be renamed later. This prevents the
|
||||
* backend from clobbering the pg_pwd file while the postmaster might be
|
||||
* reading from it.
|
||||
*/
|
||||
filename = crypt_getpwdfilename();
|
||||
tempname = (char*)malloc(strlen(filename) + 12);
|
||||
sprintf(tempname, "%s.%d", filename, MyProcPid);
|
||||
/*
|
||||
* Create a temporary filename to be renamed later. This prevents the
|
||||
* backend from clobbering the pg_pwd file while the postmaster might
|
||||
* be reading from it.
|
||||
*/
|
||||
filename = crypt_getpwdfilename();
|
||||
tempname = (char *) malloc(strlen(filename) + 12);
|
||||
sprintf(tempname, "%s.%d", filename, MyProcPid);
|
||||
|
||||
/* Copy the contents of pg_shadow to the pg_pwd ASCII file using a the SEPCHAR
|
||||
* character as the delimiter between fields. Then rename the file to its
|
||||
* final name.
|
||||
*/
|
||||
sprintf(sql, "copy %s to '%s' using delimiters %s", ShadowRelationName, tempname, CRYPT_PWD_FILE_SEPCHAR);
|
||||
pg_exec_query(sql, (char**)NULL, (Oid*)NULL, 0);
|
||||
rename(tempname, filename);
|
||||
free((void*)tempname);
|
||||
/*
|
||||
* Copy the contents of pg_shadow to the pg_pwd ASCII file using a the
|
||||
* SEPCHAR character as the delimiter between fields. Then rename the
|
||||
* file to its final name.
|
||||
*/
|
||||
sprintf(sql, "copy %s to '%s' using delimiters %s", ShadowRelationName, tempname, CRYPT_PWD_FILE_SEPCHAR);
|
||||
pg_exec_query(sql, (char **) NULL, (Oid *) NULL, 0);
|
||||
rename(tempname, filename);
|
||||
free((void *) tempname);
|
||||
|
||||
/* Create a flag file the postmaster will detect the next time it tries to
|
||||
* authenticate a user. The postmaster will know to reload the pg_pwd file
|
||||
* contents.
|
||||
*/
|
||||
filename = crypt_getpwdreloadfilename();
|
||||
creat(filename, S_IRUSR | S_IWUSR);
|
||||
/*
|
||||
* Create a flag file the postmaster will detect the next time it
|
||||
* tries to authenticate a user. The postmaster will know to reload
|
||||
* the pg_pwd file contents.
|
||||
*/
|
||||
filename = crypt_getpwdreloadfilename();
|
||||
creat(filename, S_IRUSR | S_IWUSR);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
@ -80,352 +85,407 @@ void UpdatePgPwdFile(char* sql) {
|
||||
* user is specified in the desired groups of defined in pg_group.
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
void DefineUser(CreateUserStmt *stmt) {
|
||||
void
|
||||
DefineUser(CreateUserStmt *stmt)
|
||||
{
|
||||
|
||||
char* pg_user;
|
||||
Relation pg_shadow_rel;
|
||||
TupleDesc pg_shadow_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
char* sql_end;
|
||||
bool exists = false,
|
||||
n,
|
||||
inblock;
|
||||
int max_id = -1;
|
||||
char *pg_user;
|
||||
Relation pg_shadow_rel;
|
||||
TupleDesc pg_shadow_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
char *sql_end;
|
||||
bool exists = false,
|
||||
n,
|
||||
inblock;
|
||||
int max_id = -1;
|
||||
|
||||
if (stmt->password)
|
||||
CheckPgUserAclNotNull();
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
if (stmt->password)
|
||||
CheckPgUserAclNotNull();
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
|
||||
/* Make sure the user attempting to create a user can insert into the pg_shadow
|
||||
* relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR | ACL_AP) != ACLCHECK_OK) {
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "defineUser: user \"%s\" does not have SELECT and INSERT privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Make sure the user attempting to create a user can insert into the
|
||||
* pg_shadow relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR | ACL_AP) != ACLCHECK_OK)
|
||||
{
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "defineUser: user \"%s\" does not have SELECT and INSERT privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan the pg_shadow relation to be certain the user doesn't already exist.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_shadow_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
/* Secure a write lock on pg_shadow so we can be sure of what the next usesysid
|
||||
* should be.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
/*
|
||||
* Scan the pg_shadow relation to be certain the user doesn't already
|
||||
* exist.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_shadow_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer))) {
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &n);
|
||||
/*
|
||||
* Secure a write lock on pg_shadow so we can be sure of what the next
|
||||
* usesysid should be.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
|
||||
if (!exists && !strncmp((char*)datum, stmt->user, strlen(stmt->user)))
|
||||
exists = true;
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer)))
|
||||
{
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &n);
|
||||
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &n);
|
||||
if ((int)datum > max_id)
|
||||
max_id = (int)datum;
|
||||
if (!exists && !strncmp((char *) datum, stmt->user, strlen(stmt->user)))
|
||||
exists = true;
|
||||
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &n);
|
||||
if ((int) datum > max_id)
|
||||
max_id = (int) datum;
|
||||
|
||||
if (exists) {
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "defineUser: user \"%s\" has already been created", stmt->user);
|
||||
return;
|
||||
}
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
|
||||
/* Build the insert statment to be executed.
|
||||
*/
|
||||
sprintf(sql, "insert into %s(usename,usesysid,usecreatedb,usetrace,usesuper,usecatupd,passwd", ShadowRelationName);
|
||||
/* if (stmt->password)
|
||||
strcat(sql, ",passwd"); -- removed so that insert empty string when no password */
|
||||
if (stmt->validUntil)
|
||||
strcat(sql, ",valuntil");
|
||||
if (exists)
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "defineUser: user \"%s\" has already been created", stmt->user);
|
||||
return;
|
||||
}
|
||||
|
||||
sql_end = sql + strlen(sql);
|
||||
sprintf(sql_end, ") values('%s',%d", stmt->user, max_id + 1);
|
||||
if (stmt->createdb && *stmt->createdb)
|
||||
strcat(sql_end, ",'t','t'");
|
||||
else
|
||||
strcat(sql_end, ",'f','t'");
|
||||
if (stmt->createuser && *stmt->createuser)
|
||||
strcat(sql_end, ",'t','t'");
|
||||
else
|
||||
strcat(sql_end, ",'f','t'");
|
||||
sql_end += strlen(sql_end);
|
||||
if (stmt->password) {
|
||||
sprintf(sql_end, ",'%s'", stmt->password);
|
||||
sql_end += strlen(sql_end);
|
||||
} else {
|
||||
strcpy(sql_end, ",''");
|
||||
sql_end += strlen(sql_end);
|
||||
}
|
||||
if (stmt->validUntil) {
|
||||
sprintf(sql_end, ",'%s'", stmt->validUntil);
|
||||
sql_end += strlen(sql_end);
|
||||
}
|
||||
strcat(sql_end, ")");
|
||||
/*
|
||||
* Build the insert statment to be executed.
|
||||
*/
|
||||
sprintf(sql, "insert into %s(usename,usesysid,usecreatedb,usetrace,usesuper,usecatupd,passwd", ShadowRelationName);
|
||||
/* if (stmt->password)
|
||||
strcat(sql, ",passwd"); -- removed so that insert empty string when no password */
|
||||
if (stmt->validUntil)
|
||||
strcat(sql, ",valuntil");
|
||||
|
||||
pg_exec_query(sql, (char**)NULL, (Oid*)NULL, 0);
|
||||
sql_end = sql + strlen(sql);
|
||||
sprintf(sql_end, ") values('%s',%d", stmt->user, max_id + 1);
|
||||
if (stmt->createdb && *stmt->createdb)
|
||||
strcat(sql_end, ",'t','t'");
|
||||
else
|
||||
strcat(sql_end, ",'f','t'");
|
||||
if (stmt->createuser && *stmt->createuser)
|
||||
strcat(sql_end, ",'t','t'");
|
||||
else
|
||||
strcat(sql_end, ",'f','t'");
|
||||
sql_end += strlen(sql_end);
|
||||
if (stmt->password)
|
||||
{
|
||||
sprintf(sql_end, ",'%s'", stmt->password);
|
||||
sql_end += strlen(sql_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(sql_end, ",''");
|
||||
sql_end += strlen(sql_end);
|
||||
}
|
||||
if (stmt->validUntil)
|
||||
{
|
||||
sprintf(sql_end, ",'%s'", stmt->validUntil);
|
||||
sql_end += strlen(sql_end);
|
||||
}
|
||||
strcat(sql_end, ")");
|
||||
|
||||
/* Add the stuff here for groups.
|
||||
*/
|
||||
pg_exec_query(sql, (char **) NULL, (Oid *) NULL, 0);
|
||||
|
||||
UpdatePgPwdFile(sql);
|
||||
/*
|
||||
* Add the stuff here for groups.
|
||||
*/
|
||||
|
||||
/* This goes after the UpdatePgPwdFile to be certain that two backends to not
|
||||
* attempt to write to the pg_pwd file at the same time.
|
||||
*/
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UpdatePgPwdFile(sql);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
/*
|
||||
* This goes after the UpdatePgPwdFile to be certain that two backends
|
||||
* to not attempt to write to the pg_pwd file at the same time.
|
||||
*/
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
}
|
||||
|
||||
|
||||
extern void AlterUser(AlterUserStmt *stmt) {
|
||||
extern void
|
||||
AlterUser(AlterUserStmt *stmt)
|
||||
{
|
||||
|
||||
char* pg_user;
|
||||
Relation pg_shadow_rel;
|
||||
TupleDesc pg_shadow_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
char* sql_end;
|
||||
bool exists = false,
|
||||
n,
|
||||
inblock;
|
||||
char *pg_user;
|
||||
Relation pg_shadow_rel;
|
||||
TupleDesc pg_shadow_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
char *sql_end;
|
||||
bool exists = false,
|
||||
n,
|
||||
inblock;
|
||||
|
||||
if (stmt->password)
|
||||
CheckPgUserAclNotNull();
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
if (stmt->password)
|
||||
CheckPgUserAclNotNull();
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
|
||||
/* Make sure the user attempting to create a user can insert into the pg_shadow
|
||||
* relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR) != ACLCHECK_OK) {
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "alterUser: user \"%s\" does not have SELECT and UPDATE privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Make sure the user attempting to create a user can insert into the
|
||||
* pg_shadow relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR) != ACLCHECK_OK)
|
||||
{
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "alterUser: user \"%s\" does not have SELECT and UPDATE privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Scan the pg_shadow relation to be certain the user exists.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_shadow_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
/* Secure a write lock on pg_shadow so we can be sure that when the dump of
|
||||
* the pg_pwd file is done, there is not another backend doing the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
/*
|
||||
* Scan the pg_shadow relation to be certain the user exists.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_shadow_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer))) {
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &n);
|
||||
/*
|
||||
* Secure a write lock on pg_shadow so we can be sure that when the
|
||||
* dump of the pg_pwd file is done, there is not another backend doing
|
||||
* the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
|
||||
if (!strncmp((char*)datum, stmt->user, strlen(stmt->user))) {
|
||||
exists = true;
|
||||
ReleaseBuffer(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap_endscan(scan);
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer)))
|
||||
{
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &n);
|
||||
|
||||
if (!exists) {
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
|
||||
return;
|
||||
}
|
||||
if (!strncmp((char *) datum, stmt->user, strlen(stmt->user)))
|
||||
{
|
||||
exists = true;
|
||||
ReleaseBuffer(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap_endscan(scan);
|
||||
|
||||
/* Create the update statement to modify the user.
|
||||
*/
|
||||
sprintf(sql, "update %s set", ShadowRelationName);
|
||||
sql_end = sql;
|
||||
if (stmt->password) {
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " passwd = '%s'", stmt->password);
|
||||
}
|
||||
if (stmt->createdb) {
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
if (*stmt->createdb)
|
||||
strcat(sql_end, " usecreatedb = 't'");
|
||||
else
|
||||
strcat(sql_end, " usecreatedb = 'f'");
|
||||
}
|
||||
if (stmt->createuser) {
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
if (*stmt->createuser)
|
||||
strcat(sql_end, " usesuper = 't'");
|
||||
else
|
||||
strcat(sql_end, " usesuper = 'f'");
|
||||
}
|
||||
if (stmt->validUntil) {
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " valuntil = '%s'", stmt->validUntil);
|
||||
}
|
||||
if (sql_end != sql) {
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " where usename = '%s'", stmt->user);
|
||||
pg_exec_query(sql, (char**)NULL, (Oid*)NULL, 0);
|
||||
}
|
||||
if (!exists)
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
|
||||
return;
|
||||
}
|
||||
|
||||
/* do the pg_group stuff here */
|
||||
/*
|
||||
* Create the update statement to modify the user.
|
||||
*/
|
||||
sprintf(sql, "update %s set", ShadowRelationName);
|
||||
sql_end = sql;
|
||||
if (stmt->password)
|
||||
{
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " passwd = '%s'", stmt->password);
|
||||
}
|
||||
if (stmt->createdb)
|
||||
{
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
if (*stmt->createdb)
|
||||
strcat(sql_end, " usecreatedb = 't'");
|
||||
else
|
||||
strcat(sql_end, " usecreatedb = 'f'");
|
||||
}
|
||||
if (stmt->createuser)
|
||||
{
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
if (*stmt->createuser)
|
||||
strcat(sql_end, " usesuper = 't'");
|
||||
else
|
||||
strcat(sql_end, " usesuper = 'f'");
|
||||
}
|
||||
if (stmt->validUntil)
|
||||
{
|
||||
if (sql_end != sql)
|
||||
strcat(sql_end, ",");
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " valuntil = '%s'", stmt->validUntil);
|
||||
}
|
||||
if (sql_end != sql)
|
||||
{
|
||||
sql_end += strlen(sql_end);
|
||||
sprintf(sql_end, " where usename = '%s'", stmt->user);
|
||||
pg_exec_query(sql, (char **) NULL, (Oid *) NULL, 0);
|
||||
}
|
||||
|
||||
UpdatePgPwdFile(sql);
|
||||
/* do the pg_group stuff here */
|
||||
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UpdatePgPwdFile(sql);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
}
|
||||
|
||||
|
||||
extern void RemoveUser(char* user) {
|
||||
extern void
|
||||
RemoveUser(char *user)
|
||||
{
|
||||
|
||||
char* pg_user;
|
||||
Relation pg_shadow_rel,
|
||||
pg_rel;
|
||||
TupleDesc pg_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
bool n,
|
||||
inblock;
|
||||
int usesysid = -1,
|
||||
ndbase = 0;
|
||||
char** dbase = NULL;
|
||||
char *pg_user;
|
||||
Relation pg_shadow_rel,
|
||||
pg_rel;
|
||||
TupleDesc pg_dsc;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
Datum datum;
|
||||
Buffer buffer;
|
||||
char sql[512];
|
||||
bool n,
|
||||
inblock;
|
||||
int usesysid = -1,
|
||||
ndbase = 0;
|
||||
char **dbase = NULL;
|
||||
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
if (!(inblock = IsTransactionBlock()))
|
||||
BeginTransactionBlock();
|
||||
|
||||
/* Make sure the user attempting to create a user can delete from the pg_shadow
|
||||
* relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR) != ACLCHECK_OK) {
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "removeUser: user \"%s\" does not have SELECT and DELETE privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Make sure the user attempting to create a user can delete from the
|
||||
* pg_shadow relation.
|
||||
*/
|
||||
pg_user = GetPgUserName();
|
||||
if (pg_aclcheck(ShadowRelationName, pg_user, ACL_RD | ACL_WR) != ACLCHECK_OK)
|
||||
{
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "removeUser: user \"%s\" does not have SELECT and DELETE privilege for \"%s\"",
|
||||
pg_user, ShadowRelationName);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform a scan of the pg_shadow relation to find the usesysid of the user to
|
||||
* be deleted. If it is not found, then return a warning message.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
/* Secure a write lock on pg_shadow so we can be sure that when the dump of
|
||||
* the pg_pwd file is done, there is not another backend doing the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
/*
|
||||
* Perform a scan of the pg_shadow relation to find the usesysid of
|
||||
* the user to be deleted. If it is not found, then return a warning
|
||||
* message.
|
||||
*/
|
||||
pg_shadow_rel = heap_openr(ShadowRelationName);
|
||||
pg_dsc = RelationGetTupleDescriptor(pg_shadow_rel);
|
||||
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer))) {
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_dsc, &n);
|
||||
/*
|
||||
* Secure a write lock on pg_shadow so we can be sure that when the
|
||||
* dump of the pg_pwd file is done, there is not another backend doing
|
||||
* the same.
|
||||
*/
|
||||
RelationSetLockForWrite(pg_shadow_rel);
|
||||
|
||||
if (!strncmp((char*)datum, user, strlen(user))) {
|
||||
usesysid = (int)heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_dsc, &n);
|
||||
ReleaseBuffer(buffer);
|
||||
break;
|
||||
}
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
scan = heap_beginscan(pg_shadow_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer)))
|
||||
{
|
||||
datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_dsc, &n);
|
||||
|
||||
if (usesysid == -1) {
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
|
||||
return;
|
||||
}
|
||||
if (!strncmp((char *) datum, user, strlen(user)))
|
||||
{
|
||||
usesysid = (int) heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_dsc, &n);
|
||||
ReleaseBuffer(buffer);
|
||||
break;
|
||||
}
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
|
||||
/* Perform a scan of the pg_database relation to find the databases owned by
|
||||
* usesysid. Then drop them.
|
||||
*/
|
||||
pg_rel = heap_openr(DatabaseRelationName);
|
||||
pg_dsc = RelationGetTupleDescriptor(pg_rel);
|
||||
if (usesysid == -1)
|
||||
{
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UserAbortTransactionBlock();
|
||||
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
|
||||
return;
|
||||
}
|
||||
|
||||
scan = heap_beginscan(pg_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer))) {
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datdba, pg_dsc, &n);
|
||||
/*
|
||||
* Perform a scan of the pg_database relation to find the databases
|
||||
* owned by usesysid. Then drop them.
|
||||
*/
|
||||
pg_rel = heap_openr(DatabaseRelationName);
|
||||
pg_dsc = RelationGetTupleDescriptor(pg_rel);
|
||||
|
||||
if ((int)datum == usesysid) {
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n);
|
||||
if (memcmp((void*)datum, "template1", 9)) {
|
||||
dbase = (char**)realloc((void*)dbase, sizeof(char*) * (ndbase + 1));
|
||||
dbase[ndbase] = (char*)malloc(NAMEDATALEN + 1);
|
||||
memcpy((void*)dbase[ndbase], (void*)datum, NAMEDATALEN);
|
||||
dbase[ndbase++][NAMEDATALEN] = '\0';
|
||||
}
|
||||
}
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(pg_rel);
|
||||
scan = heap_beginscan(pg_rel, false, false, 0, NULL);
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0, &buffer)))
|
||||
{
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datdba, pg_dsc, &n);
|
||||
|
||||
while (ndbase--) {
|
||||
elog(NOTICE, "Dropping database %s", dbase[ndbase]);
|
||||
sprintf(sql, "drop database %s", dbase[ndbase]);
|
||||
free((void*)dbase[ndbase]);
|
||||
pg_exec_query(sql, (char**)NULL, (Oid*)NULL, 0);
|
||||
}
|
||||
if (dbase)
|
||||
free((void*)dbase);
|
||||
if ((int) datum == usesysid)
|
||||
{
|
||||
datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n);
|
||||
if (memcmp((void *) datum, "template1", 9))
|
||||
{
|
||||
dbase = (char **) realloc((void *) dbase, sizeof(char *) * (ndbase + 1));
|
||||
dbase[ndbase] = (char *) malloc(NAMEDATALEN + 1);
|
||||
memcpy((void *) dbase[ndbase], (void *) datum, NAMEDATALEN);
|
||||
dbase[ndbase++][NAMEDATALEN] = '\0';
|
||||
}
|
||||
}
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(pg_rel);
|
||||
|
||||
/* Since pg_shadow is global over all databases, one of two things must be done
|
||||
* to insure complete consistency. First, pg_shadow could be made non-global.
|
||||
* This would elminate the code above for deleting database and would require
|
||||
* the addition of code to delete tables, views, etc owned by the user.
|
||||
*
|
||||
* The second option would be to create a means of deleting tables, view,
|
||||
* etc. owned by the user from other databases. Pg_user is global and so
|
||||
* this must be done at some point.
|
||||
*
|
||||
* Let us not forget that the user should be removed from the pg_groups also.
|
||||
*
|
||||
* Todd A. Brandys 11/18/1997
|
||||
*
|
||||
*/
|
||||
while (ndbase--)
|
||||
{
|
||||
elog(NOTICE, "Dropping database %s", dbase[ndbase]);
|
||||
sprintf(sql, "drop database %s", dbase[ndbase]);
|
||||
free((void *) dbase[ndbase]);
|
||||
pg_exec_query(sql, (char **) NULL, (Oid *) NULL, 0);
|
||||
}
|
||||
if (dbase)
|
||||
free((void *) dbase);
|
||||
|
||||
/* Remove the user from the pg_shadow table
|
||||
*/
|
||||
sprintf(sql, "delete from %s where usename = '%s'", ShadowRelationName, user);
|
||||
pg_exec_query(sql, (char**)NULL, (Oid*)NULL, 0);
|
||||
/*
|
||||
* Since pg_shadow is global over all databases, one of two things
|
||||
* must be done to insure complete consistency. First, pg_shadow
|
||||
* could be made non-global. This would elminate the code above for
|
||||
* deleting database and would require the addition of code to delete
|
||||
* tables, views, etc owned by the user.
|
||||
*
|
||||
* The second option would be to create a means of deleting tables, view,
|
||||
* etc. owned by the user from other databases. Pg_user is global and
|
||||
* so this must be done at some point.
|
||||
*
|
||||
* Let us not forget that the user should be removed from the pg_groups
|
||||
* also.
|
||||
*
|
||||
* Todd A. Brandys 11/18/1997
|
||||
*
|
||||
*/
|
||||
|
||||
UpdatePgPwdFile(sql);
|
||||
/*
|
||||
* Remove the user from the pg_shadow table
|
||||
*/
|
||||
sprintf(sql, "delete from %s where usename = '%s'", ShadowRelationName, user);
|
||||
pg_exec_query(sql, (char **) NULL, (Oid *) NULL, 0);
|
||||
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
UpdatePgPwdFile(sql);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
||||
heap_close(pg_shadow_rel);
|
||||
|
||||
if (IsTransactionBlock() && !inblock)
|
||||
EndTransactionBlock();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -433,9 +493,10 @@ extern void RemoveUser(char* user) {
|
||||
*
|
||||
* check to see if there is an ACL on pg_shadow
|
||||
*/
|
||||
static void CheckPgUserAclNotNull()
|
||||
static void
|
||||
CheckPgUserAclNotNull()
|
||||
{
|
||||
HeapTuple htp;
|
||||
HeapTuple htp;
|
||||
|
||||
htp = SearchSysCacheTuple(RELNAME, PointerGetDatum(ShadowRelationName),
|
||||
0, 0, 0);
|
||||
@ -451,6 +512,6 @@ HeapTuple htp;
|
||||
elog(NOTICE, "so normal users can not read the passwords.");
|
||||
elog(ERROR, "Try 'REVOKE ALL ON pg_shadow FROM PUBLIC'");
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user