Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
ccfaf906
Commit
ccfaf906
authored
Apr 29, 2002
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement checking of USAGE rights on namespaces.
parent
88ef7067
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
197 additions
and
107 deletions
+197
-107
src/backend/catalog/namespace.c
src/backend/catalog/namespace.c
+197
-107
No files found.
src/backend/catalog/namespace.c
View file @
ccfaf906
...
...
@@ -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.1
4 2002/04/27 03:45:00
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.1
5 2002/04/29 22:15:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -37,9 +37,10 @@
#include "storage/backendid.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/
catcache
.h"
#include "utils/
inval
.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
...
...
@@ -66,10 +67,25 @@
* path is determined by GUC. The factory default path contains the PUBLIC
* namespace (if it exists), preceded by the user's personal namespace
* (if one exists).
*
* If namespaceSearchPathValid is false, then namespaceSearchPath (and the
* derived variables) need to be recomputed from namespace_search_path.
* We mark it invalid upon an assignment to namespace_search_path or receipt
* of a syscache invalidation event for pg_namespace. The recomputation
* is done during the next lookup attempt.
*
* Any namespaces mentioned in namespace_search_path that are not readable
* by the current user ID are simply left out of namespaceSearchPath; so
* we have to be willing to recompute the path when current userid changes.
* namespaceUser is the userid the path has been computed for.
*/
static
List
*
namespaceSearchPath
=
NIL
;
static
bool
namespaceSearchPathValid
=
true
;
static
Oid
namespaceUser
=
InvalidOid
;
/* this flag must be updated correctly when namespaceSearchPath is changed */
static
bool
pathContainsSystemNamespace
=
false
;
...
...
@@ -103,12 +119,14 @@ typedef struct DelConstraint
/* Local functions */
static
void
recomputeNamespacePath
(
void
);
static
Oid
GetTempTableNamespace
(
void
);
static
void
RemoveTempRelations
(
Oid
tempNamespaceId
);
static
List
*
FindTempRelations
(
Oid
tempNamespaceId
);
static
List
*
FindDeletionConstraints
(
List
*
relOids
);
static
List
*
TopoSortRels
(
List
*
relOids
,
List
*
constraintList
);
static
void
RemoveTempRelationsCallback
(
void
);
static
void
NamespaceCallback
(
Datum
arg
,
Oid
relid
);
/*
...
...
@@ -137,12 +155,18 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
if
(
relation
->
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
relation
->
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
relation
->
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
relation
->
schemaname
);
relId
=
get_relname_relid
(
relation
->
relname
,
namespaceId
);
}
else
...
...
@@ -210,11 +234,14 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
else
{
/* use the default creation namespace */
recomputeNamespacePath
();
namespaceId
=
defaultCreationNamespace
;
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"No namespace has been selected to create in"
);
}
/* Note: callers will check for CREATE rights when appropriate */
return
namespaceId
;
}
...
...
@@ -229,9 +256,11 @@ RelnameGetRelid(const char *relname)
Oid
relid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If a TEMP-table namespace has been set up, it is implicitly first
* in the search path.
* in the search path.
We do not need to check USAGE permission.
*/
if
(
OidIsValid
(
myTempNamespace
))
{
...
...
@@ -241,7 +270,8 @@ RelnameGetRelid(const char *relname)
}
/*
* If system namespace is not in path, implicitly search it before path
* If system namespace is not in path, implicitly search it before path.
* We do not check USAGE permission.
*/
if
(
!
pathContainsSystemNamespace
)
{
...
...
@@ -281,6 +311,8 @@ TypenameGetTypid(const char *typname)
Oid
typid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If system namespace is not in path, implicitly search it before path
*/
...
...
@@ -327,6 +359,8 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
Oid
opcid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If system namespace is not in path, implicitly search it before path
*/
...
...
@@ -414,17 +448,23 @@ FuncnameGetCandidates(List *names, int nargs)
if
(
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
schemaname
);
}
else
{
/* flag to indicate we need namespace search */
namespaceId
=
InvalidOid
;
recomputeNamespacePath
();
}
/* Search syscache by name and (optionally) nargs only */
...
...
@@ -598,17 +638,23 @@ OpernameGetCandidates(List *names, char oprkind)
if
(
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
schemaname
);
}
else
{
/* flag to indicate we need namespace search */
namespaceId
=
InvalidOid
;
recomputeNamespacePath
();
}
/* Search syscache by name only */
...
...
@@ -736,6 +782,8 @@ OpclassGetCandidates(Oid amid)
CatCList
*
catlist
;
int
i
;
recomputeNamespacePath
();
/* Search syscache by AM OID only */
catlist
=
SearchSysCacheList
(
CLAAMNAMENSP
,
1
,
ObjectIdGetDatum
(
amid
),
...
...
@@ -891,11 +939,14 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
else
{
/* use the default creation namespace */
recomputeNamespacePath
();
namespaceId
=
defaultCreationNamespace
;
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"No namespace has been selected to create in"
);
}
/* Note: callers will check for CREATE rights when appropriate */
*
objname_p
=
objname
;
return
namespaceId
;
}
...
...
@@ -965,6 +1016,118 @@ isTempNamespace(Oid namespaceId)
return
false
;
}
/*
* recomputeNamespacePath - recompute path derived variables if needed.
*/
static
void
recomputeNamespacePath
(
void
)
{
Oid
userId
=
GetUserId
();
char
*
rawname
;
List
*
namelist
;
List
*
oidlist
;
List
*
newpath
;
List
*
l
;
MemoryContext
oldcxt
;
/*
* Do nothing if path is already valid.
*/
if
(
namespaceSearchPathValid
&&
namespaceUser
==
userId
)
return
;
/* Need a modifiable copy of namespace_search_path string */
rawname
=
pstrdup
(
namespace_search_path
);
/* Parse string into list of identifiers */
if
(
!
SplitIdentifierString
(
rawname
,
','
,
&
namelist
))
{
/* syntax error in name list */
/* this should not happen if GUC checked check_search_path */
elog
(
ERROR
,
"recomputeNamespacePath: invalid list syntax"
);
}
/*
* Convert the list of names to a list of OIDs. If any names are not
* recognizable or we don't have read access, just leave them out of
* the list. (We can't raise an error, since the search_path setting
* has already been accepted.)
*/
oidlist
=
NIL
;
foreach
(
l
,
namelist
)
{
char
*
curname
=
(
char
*
)
lfirst
(
l
);
Oid
namespaceId
;
if
(
strcmp
(
curname
,
"$user"
)
==
0
)
{
/* $user --- substitute namespace matching user name, if any */
HeapTuple
tuple
;
tuple
=
SearchSysCache
(
SHADOWSYSID
,
ObjectIdGetDatum
(
userId
),
0
,
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
{
char
*
uname
;
uname
=
NameStr
(((
Form_pg_shadow
)
GETSTRUCT
(
tuple
))
->
usename
);
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
uname
),
0
,
0
,
0
);
ReleaseSysCache
(
tuple
);
if
(
OidIsValid
(
namespaceId
)
&&
pg_namespace_aclcheck
(
namespaceId
,
userId
,
ACL_USAGE
)
==
ACLCHECK_OK
)
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
else
{
/* normal namespace reference */
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
curname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
)
&&
pg_namespace_aclcheck
(
namespaceId
,
userId
,
ACL_USAGE
)
==
ACLCHECK_OK
)
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
/*
* Now that we've successfully built the new list of namespace OIDs,
* save it in permanent storage.
*/
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryContext
);
newpath
=
listCopy
(
oidlist
);
MemoryContextSwitchTo
(
oldcxt
);
/* Now safe to assign to state variable. */
freeList
(
namespaceSearchPath
);
namespaceSearchPath
=
newpath
;
/*
* Update info derived from search path.
*/
pathContainsSystemNamespace
=
intMember
(
PG_CATALOG_NAMESPACE
,
namespaceSearchPath
);
if
(
namespaceSearchPath
==
NIL
)
defaultCreationNamespace
=
InvalidOid
;
else
defaultCreationNamespace
=
(
Oid
)
lfirsti
(
namespaceSearchPath
);
/* Mark the path valid. */
namespaceSearchPathValid
=
true
;
namespaceUser
=
userId
;
/* Clean up. */
pfree
(
rawname
);
freeList
(
namelist
);
freeList
(
oidlist
);
}
/*
* GetTempTableNamespace
* Initialize temp table namespace on first use in a particular backend
...
...
@@ -979,8 +1142,12 @@ GetTempTableNamespace(void)
* First, do permission check to see if we are authorized to make
* temp tables. We use a nonstandard error message here since
* "databasename: permission denied" might be a tad cryptic.
*
* Note we apply the check to the session user, not the currently
* active userid, since we are not going to change our minds about
* temp table availability during the session.
*/
if
(
pg_database_aclcheck
(
MyDatabaseId
,
GetUserId
(),
if
(
pg_database_aclcheck
(
MyDatabaseId
,
Get
Session
UserId
(),
ACL_CREATE_TEMP
)
!=
ACLCHECK_OK
)
elog
(
ERROR
,
"%s: not authorized to create temp tables"
,
DatabaseName
);
...
...
@@ -1320,7 +1487,8 @@ check_search_path(const char *proposed)
/*
* Verify that all the names are either valid namespace names or "$user".
* (We do not require $user to correspond to a valid namespace; should we?)
* We do not require $user to correspond to a valid namespace.
* We do not check for USAGE rights, either; should we?
*/
foreach
(
l
,
namelist
)
{
...
...
@@ -1348,104 +1516,12 @@ check_search_path(const char *proposed)
void
assign_search_path
(
const
char
*
newval
)
{
char
*
rawname
;
List
*
namelist
;
List
*
oidlist
;
List
*
newpath
;
List
*
l
;
MemoryContext
oldcxt
;
/*
* If we aren't inside a transaction, we cannot do database access so
* cannot look up the names. In this case, do nothing; the internal
* search path will be fixed later by InitializeSearchPath. (We assume
* this situation can only happen in the postmaster or early in backend
* startup.)
*/
if
(
!
IsTransactionState
())
return
;
/* Need a modifiable copy of string */
rawname
=
pstrdup
(
newval
);
/* Parse string into list of identifiers */
if
(
!
SplitIdentifierString
(
rawname
,
','
,
&
namelist
))
{
/* syntax error in name list */
/* this should not happen if GUC checked check_search_path */
elog
(
ERROR
,
"assign_search_path: invalid list syntax"
);
}
/*
*
Convert the list of names to a list of OIDs. If any names are not
*
recognizable, just leave them out of the list. (This is our only
*
reasonable recourse when the already-accepted default is bogus.)
*
We mark the path as needing recomputation, but don't do anything until
*
it's needed. This avoids trying to do database access during GUC
*
initialization.
*/
oidlist
=
NIL
;
foreach
(
l
,
namelist
)
{
char
*
curname
=
(
char
*
)
lfirst
(
l
);
Oid
namespaceId
;
if
(
strcmp
(
curname
,
"$user"
)
==
0
)
{
/* $user --- substitute namespace matching user name, if any */
HeapTuple
tuple
;
tuple
=
SearchSysCache
(
SHADOWSYSID
,
ObjectIdGetDatum
(
GetSessionUserId
()),
0
,
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
{
char
*
uname
;
uname
=
NameStr
(((
Form_pg_shadow
)
GETSTRUCT
(
tuple
))
->
usename
);
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
uname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
))
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
ReleaseSysCache
(
tuple
);
}
}
else
{
/* normal namespace reference */
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
curname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
))
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
/*
* Now that we've successfully built the new list of namespace OIDs,
* save it in permanent storage.
*/
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryContext
);
newpath
=
listCopy
(
oidlist
);
MemoryContextSwitchTo
(
oldcxt
);
/* Now safe to assign to state variable. */
freeList
(
namespaceSearchPath
);
namespaceSearchPath
=
newpath
;
/*
* Update info derived from search path.
*/
pathContainsSystemNamespace
=
intMember
(
PG_CATALOG_NAMESPACE
,
namespaceSearchPath
);
if
(
namespaceSearchPath
==
NIL
)
defaultCreationNamespace
=
InvalidOid
;
else
defaultCreationNamespace
=
(
Oid
)
lfirsti
(
namespaceSearchPath
);
/* Clean up. */
pfree
(
rawname
);
freeList
(
namelist
);
freeList
(
oidlist
);
namespaceSearchPathValid
=
false
;
}
/*
...
...
@@ -1469,19 +1545,32 @@ InitializeSearchPath(void)
MemoryContextSwitchTo
(
oldcxt
);
pathContainsSystemNamespace
=
true
;
defaultCreationNamespace
=
PG_CATALOG_NAMESPACE
;
namespaceSearchPathValid
=
true
;
namespaceUser
=
GetUserId
();
}
else
{
/*
* I
f a search path setting was provided before we were able to
*
execute lookups, establish the internal search path now
.
* I
n normal mode, arrange for a callback on any syscache invalidation
*
of pg_namespace rows
.
*/
if
(
namespace_search_path
&&
*
namespace_search_path
&&
namespaceSearchPath
==
NIL
)
assign_search_path
(
namespace_search_path
);
CacheRegisterSyscacheCallback
(
NAMESPACEOID
,
NamespaceCallback
,
(
Datum
)
0
);
}
}
/*
* NamespaceCallback
* Syscache inval callback function
*/
static
void
NamespaceCallback
(
Datum
arg
,
Oid
relid
)
{
/* Force search path to be recomputed on next use */
namespaceSearchPathValid
=
false
;
}
/*
* Fetch the active search path, expressed as a List of OIDs.
*
...
...
@@ -1490,5 +1579,6 @@ InitializeSearchPath(void)
List
*
fetch_search_path
(
void
)
{
recomputeNamespacePath
();
return
namespaceSearchPath
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment