1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Fix permissions-checking bugs and namespace-search-path bugs in

CONVERSION code.  Still need to figure out what to do about inappropriate
coding in parsing.
This commit is contained in:
Tom Lane
2002-11-02 02:33:03 +00:00
parent 08dd92cdeb
commit 6a7273e14c
6 changed files with 86 additions and 148 deletions

View File

@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.36 2002/09/23 20:43:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.37 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1275,32 +1275,33 @@ PopSpecialNamespace(Oid namespaceId)
Oid
FindConversionByName(List *name)
{
char *schemaname;
char *conversion_name;
Oid namespaceId;
Oid conoid;
List *lptr;
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
/* deconstruct the name list */
DeconstructQualifiedName(name, &schemaname, &conversion_name);
if (length(name) > 1)
if (schemaname)
{
/* Check we have usage rights in target namespace */
if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
return InvalidOid;
/* use exact schema given */
namespaceId = LookupExplicitNamespace(schemaname);
return FindConversion(conversion_name, namespaceId);
}
recomputeNamespacePath();
foreach(lptr, namespaceSearchPath)
else
{
Oid namespaceId = (Oid) lfirsti(lptr);
/* search for it in search path */
recomputeNamespacePath();
conoid = FindConversion(conversion_name, namespaceId);
if (OidIsValid(conoid))
return conoid;
foreach(lptr, namespaceSearchPath)
{
namespaceId = (Oid) lfirsti(lptr);
conoid = FindConversion(conversion_name, namespaceId);
if (OidIsValid(conoid))
return conoid;
}
}
/* Not found in path */
@@ -1308,7 +1309,7 @@ FindConversionByName(List *name)
}
/*
* FindDefaultConversionProc - find default encoding cnnversion proc
* FindDefaultConversionProc - find default encoding conversion proc
*/
Oid
FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.6 2002/09/04 20:31:14 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.7 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,16 +30,15 @@
#include "utils/acl.h"
#include "miscadmin.h"
/* ----------------
/*
* ConversionCreate
*
* Add a new tuple to pg_coversion.
* ---------------
* Add a new tuple to pg_conversion.
*/
Oid
ConversionCreate(const char *conname, Oid connamespace,
int32 conowner,
int4 conforencoding, int4 contoencoding,
int32 conforencoding, int32 contoencoding,
Oid conproc, bool def)
{
int i;
@@ -58,7 +57,7 @@ ConversionCreate(const char *conname, Oid connamespace,
elog(ERROR, "no conversion name supplied");
/* make sure there is no existing conversion of same name */
if (SearchSysCacheExists(CONNAMESP,
if (SearchSysCacheExists(CONNAMENSP,
PointerGetDatum(conname),
ObjectIdGetDatum(connamespace),
0, 0))
@@ -74,7 +73,8 @@ ConversionCreate(const char *conname, Oid connamespace,
conforencoding,
contoencoding))
elog(ERROR, "default conversion for %s to %s already exists",
pg_encoding_to_char(conforencoding), pg_encoding_to_char(contoencoding));
pg_encoding_to_char(conforencoding),
pg_encoding_to_char(contoencoding));
}
/* open pg_conversion */
@@ -96,10 +96,7 @@ ConversionCreate(const char *conname, Oid connamespace,
values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
if (def == true)
values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
else
nulls[Anum_pg_conversion_condefault - 1] = 'n';
values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
tup = heap_formtuple(tupDesc, values, nulls);
@@ -110,11 +107,11 @@ ConversionCreate(const char *conname, Oid connamespace,
/* update the index if any */
CatalogUpdateIndexes(rel, tup);
myself.classId = get_system_catalog_relid(ConversionRelationName);
myself.classId = RelationGetRelid(rel);
myself.objectId = HeapTupleGetOid(tup);
myself.objectSubId = 0;
/* dependency on conversion procedure */
/* create dependency on conversion procedure */
referenced.classId = RelOid_pg_proc;
referenced.objectId = conproc;
referenced.objectSubId = 0;
@@ -126,79 +123,46 @@ ConversionCreate(const char *conname, Oid connamespace,
return oid;
}
/* ----------------
/*
* ConversionDrop
*
* Drop a conversion and do dependency check.
* ---------------
* Drop a conversion after doing permission checks.
*/
void
ConversionDrop(const char *conname, Oid connamespace,
int32 conowner, DropBehavior behavior)
ConversionDrop(Oid conversionOid, DropBehavior behavior)
{
Relation rel;
TupleDesc tupDesc;
HeapTuple tuple;
HeapScanDesc scan;
ScanKeyData scanKeyData;
Form_pg_conversion body;
ObjectAddress object;
Oid myoid;
/* sanity checks */
if (!conname)
elog(ERROR, "no conversion name supplied");
ScanKeyEntryInitialize(&scanKeyData,
0,
Anum_pg_conversion_connamespace,
F_OIDEQ,
ObjectIdGetDatum(connamespace));
/* open pg_conversion */
rel = heap_openr(ConversionRelationName, AccessShareLock);
tupDesc = rel->rd_att;
scan = heap_beginscan(rel, SnapshotNow,
1, &scanKeyData);
/* search for the target tuple */
while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
{
body = (Form_pg_conversion) GETSTRUCT(tuple);
if (!strncmp(NameStr(body->conname), conname, NAMEDATALEN))
break;
}
tuple = SearchSysCache(CONOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
elog(ERROR, "conversion %s not found", conname);
return;
}
elog(ERROR, "Conversion %u search from syscache failed",
conversionOid);
if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
if (!superuser() &&
((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
elog(ERROR, "permission denied");
myoid = HeapTupleGetOid(tuple);
heap_endscan(scan);
heap_close(rel, AccessShareLock);
ReleaseSysCache(tuple);
/*
* Do the deletion
*/
object.classId = get_system_catalog_relid(ConversionRelationName);
object.objectId = myoid;
object.objectId = conversionOid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
/* ----------------
/*
* RemoveConversionById
*
* Remove a tuple from pg_conversion by Oid. This function is soley
* Remove a tuple from pg_conversion by Oid. This function is solely
* called inside catalog/dependency.c
* --------------- */
*/
void
RemoveConversionById(Oid conversionOid)
{
@@ -230,15 +194,17 @@ RemoveConversionById(Oid conversionOid)
heap_close(rel, RowExclusiveLock);
}
/* ----------------
/*
* FindDefaultConversion
*
* Find "default" conversion proc by for_encoding and to_encoding in this name space.
* If found, returns the procedure's oid, otherwise InvalidOid.
* ---------------
* Find "default" conversion proc by for_encoding and to_encoding in the
* given namespace.
*
* If found, returns the procedure's oid, otherwise InvalidOid. Note that
* you get the procedure's OID not the conversion's OID!
*/
Oid
FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
{
CatCList *catlist;
HeapTuple tuple;
@@ -246,10 +212,6 @@ FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
Oid proc = InvalidOid;
int i;
/* Check we have usage rights in target namespace */
if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
return proc;
catlist = SearchSysCacheList(CONDEFAULT, 3,
ObjectIdGetDatum(name_space),
Int32GetDatum(for_encoding),
@@ -260,7 +222,7 @@ FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
{
tuple = &catlist->members[i]->tuple;
body = (Form_pg_conversion) GETSTRUCT(tuple);
if (body->condefault == TRUE)
if (body->condefault)
{
proc = body->conproc;
break;
@@ -270,12 +232,11 @@ FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
return proc;
}
/* ----------------
* FindConversionByName
/*
* FindConversion
*
* Find conversion by namespace and conversion name.
* Returns conversion oid.
* ---------------
* Returns conversion OID.
*/
Oid
FindConversion(const char *conname, Oid connamespace)
@@ -286,13 +247,13 @@ FindConversion(const char *conname, Oid connamespace)
AclResult aclresult;
/* search pg_conversion by connamespace and conversion name */
tuple = SearchSysCache(CONNAMESP,
tuple = SearchSysCache(CONNAMENSP,
PointerGetDatum(conname),
ObjectIdGetDatum(connamespace),
0, 0);
if (!HeapTupleIsValid(tuple))
return InvalidOid;
procoid = ((Form_pg_conversion) GETSTRUCT(tuple))->conproc;
conoid = HeapTupleGetOid(tuple);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.4 2002/09/04 20:31:14 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.5 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,17 +38,14 @@ CreateConversionCommand(CreateConversionStmt *stmt)
int for_encoding;
int to_encoding;
Oid funcoid;
Oid funcnamespace;
char *dummy;
const char *for_encoding_name = stmt->for_encoding_name;
const char *to_encoding_name = stmt->to_encoding_name;
List *func_name = stmt->func_name;
static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID};
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name, &conversion_name);
namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
&conversion_name);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
@@ -70,17 +67,13 @@ CreateConversionCommand(CreateConversionStmt *stmt)
*/
funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid), funcargs);
if (!OidIsValid(funcoid))
elog(ERROR, "Function %s does not exist", NameListToString(func_name));
/* Check the rights for this function and name space */
funcnamespace = QualifiedNameGetCreationNamespace(func_name, &dummy);
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_namespace_name(funcnamespace));
func_error("CreateConversion", func_name,
sizeof(funcargs) / sizeof(Oid), funcargs, NULL);
/* Check we have EXECUTE rights for the function */
aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_namespace_name(funcnamespace));
aclcheck_error(aclresult, NameListToString(func_name));
/*
* All seem ok, go ahead (possible failure would be a duplicate
@@ -96,21 +89,12 @@ CreateConversionCommand(CreateConversionStmt *stmt)
void
DropConversionCommand(List *name, DropBehavior behavior)
{
Oid namespaceId;
char *conversion_name;
AclResult aclresult;
Oid conversionOid;
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
conversionOid = FindConversionByName(name);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_namespace_name(namespaceId));
if (!OidIsValid(conversionOid))
elog(ERROR, "conversion %s not found", NameListToString(name));
/*
* Go ahead (possible failure would be: none existing conversion not
* ower of this conversion
*/
ConversionDrop(conversion_name, namespaceId, GetUserId(), behavior);
ConversionDrop(conversionOid, behavior);
}

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_conversion.h,v 1.6 2002/09/04 20:31:37 momjian Exp $
* $Id: pg_conversion.h,v 1.7 2002/11/02 02:33:03 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -85,12 +85,11 @@ typedef FormData_pg_conversion *Form_pg_conversion;
extern Oid ConversionCreate(const char *conname, Oid connamespace,
int32 conowner,
int4 conforencoding, int4 contoencoding,
int32 conforencoding, int32 contoencoding,
Oid conproc, bool def);
extern void ConversionDrop(const char *conname, Oid connamespace,
int32 conowner, DropBehavior behavior);
extern void ConversionDrop(Oid conversionOid, DropBehavior behavior);
extern void RemoveConversionById(Oid conversionOid);
extern Oid FindConversion(const char *conname, Oid connamespace);
extern Oid FindDefaultConversion(Oid connamespace, int4 for_encoding, int4 to_encoding);
extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding, int32 to_encoding);
#endif /* PG_CONVERSION_H */

View File

@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: syscache.h,v 1.53 2002/09/04 20:31:46 momjian Exp $
* $Id: syscache.h,v 1.54 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,7 +40,7 @@
#define CLAAMNAMENSP 9
#define CLAOID 10
#define CONDEFAULT 11
#define CONNAMESP 12
#define CONNAMENSP 12
#define CONOID 13
#define GRONAME 14
#define GROSYSID 15