]> granicus.if.org Git - postgresql/commitdiff
From: Dan McGuirk <mcguirk@indirect.com>
authorMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 20:48:48 +0000 (20:48 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Wed, 12 Mar 1997 20:48:48 +0000 (20:48 +0000)
Subject: [HACKERS] better access control error messages

This patch replaces the 'no such class or insufficient privilege' with
distinct error messages that tell you whether the table really doesn't
exist or whether access was denied.

src/backend/commands/copy.c
src/backend/executor/execMain.c
src/backend/parser/parse_query.c
src/backend/tcop/aclchk.c
src/backend/tcop/utility.c
src/include/utils/acl.h

index f46a848d42499da44f145a6a0d3a132cd55f6488..12ee1c28f17328b254a3441dfddcb1d11e4796e3 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.21 1997/01/10 17:46:33 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.22 1997/03/12 20:47:32 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,13 +102,15 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
     Relation rel;
     extern char *UserName;    /* defined in global.c */
     const AclMode required_access = from ? ACL_WR : ACL_RD;
+    int result;
 
     rel = heap_openr(relname);
     if (rel == NULL) elog(WARN, "COPY command failed.  Class %s "
                           "does not exist.", relname);
-    
-    if (!pg_aclcheck(relname, UserName, required_access))
-        elog(WARN, "%s %s", relname, ACL_NO_PRIV_WARNING);
+
+    result = pg_aclcheck(relname, UserName, required_access);
+    if(result != ACLCHECK_OK)
+        elog(WARN, "%s: %s", relname, aclcheck_error_strings[result]);
         /* Above should not return */
     else if (!superuser() && !pipe)
         elog(WARN, "You must have Postgres superuser privilege to do a COPY "
index 11c8f91a8d40591231cf69a73eb4a88f4b3d814d..cff5081c3744ee13adc6973654684133cd76719a 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.10 1997/01/22 05:26:27 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.11 1997/03/12 20:47:41 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -289,7 +289,7 @@ ExecCheckPerms(CmdType operation,
     HeapTuple htp;
     List *lp;
     List *qvars, *tvars;
-    int32 ok = 1;
+    int32 ok = 1, aclcheck_result = -1;
     char *opstr;
     NameData rname;
     char *userName;
@@ -317,21 +317,21 @@ ExecCheckPerms(CmdType operation,
            if (intMember(resultRelation, qvars) ||
                intMember(resultRelation, tvars)) {
                /* result relation is scanned */
-               ok = CHECK(ACL_RD);
+               ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
                opstr = "read";
                if (!ok)
                    break;
            }
            switch (operation) {
            case CMD_INSERT:
-               ok = CHECK(ACL_AP) ||
-                   CHECK(ACL_WR);
+               ok = ((aclcheck_result = CHECK(ACL_AP)) == ACLCHECK_OK) ||
+                    ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
                opstr = "append";
                break;
            case CMD_NOTIFY: /* what does this mean?? -- jw, 1/6/94 */
            case CMD_DELETE:
            case CMD_UPDATE:
-               ok = CHECK(ACL_WR);
+               ok = ((aclcheck_result = CHECK(ACL_WR)) == ACLCHECK_OK);
                opstr = "write";
                break;
            default:
@@ -340,7 +340,7 @@ ExecCheckPerms(CmdType operation,
            }
        } else {
            /* XXX NOTIFY?? */
-           ok = CHECK(ACL_RD);
+           ok = ((aclcheck_result = CHECK(ACL_RD)) == ACLCHECK_OK);
            opstr = "read";
        }
        if (!ok)
@@ -352,7 +352,7 @@ ExecCheckPerms(CmdType operation,
        elog(WARN, "%s on \"%-.*s\": permission denied", opstr, 
             NAMEDATALEN, rname.data);
 */         
-       elog(WARN, "%s %s", rname.data, ACL_NO_PRIV_WARNING);
+       elog(WARN, "%s: %s", rname.data, aclcheck_error_strings[aclcheck_result]);
     }
 }
 
index 398685bed4adcabfffc195fe0e42f7a93c796a11..2411e264974c69823ef7f37bea291e91a7c4a4dc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.14 1997/02/14 23:02:29 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.15 1997/03/12 20:47:57 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,7 +133,7 @@ addRangeTableEntry(ParseState *pstate,
     relation = heap_openr(relname);
     if (relation == NULL) {
        elog(WARN,"%s: %s",
-            relname, ACL_NO_PRIV_WARNING);
+            relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
     }
 
     /*
index b58a750343c7bd63cc0649340a5dede5c7dfb0d9..20748e16c6a720f9e87b1831b9a0fd545549f04b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.6 1997/01/23 19:33:31 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.7 1997/03/12 20:48:17 scrappy Exp $
  *
  * NOTES
  *    See acl.h.
@@ -17,7 +17,7 @@
 #include <string.h>
 #include "postgres.h"
 
-#include "utils/acl.h"         /* where declarations for this file goes */
+#include "utils/acl.h"         /* where declarations for this file go */
 #include "access/heapam.h"
 #include "access/htup.h"
 #include "access/tupmacs.h"
 #define        Name_pg_group                   "pggroup"
 #endif
 
+/* warning messages, now more explicit. */
+/* should correspond to the order of the ACLCHK_* result codes above. */
+char *aclcheck_error_strings[] = {
+  "No error.",
+  "Permission denied.",
+  "Table does not exist.",
+  "Must be table owner."
+};
+
 #ifdef ACLDEBUG_TRACE
 static
 dumpacl(Acl *acl)
@@ -268,10 +277,10 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
      * the system never creates an empty ACL.
      */
     if (num < 1) {
-#ifdef ACLDEBUG_TRACE
+#ifdef ACLDEBUG_TRACE || 1
        elog(DEBUG, "aclcheck: zero-length ACL, returning 1");
 #endif
-       return(1);
+       return ACLCHECK_OK;
     }
 
     switch (idtype) {
@@ -284,7 +293,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
                elog(DEBUG, "aclcheck: found %d/%d",
                     aip->ai_id, aip->ai_mode);
 #endif
-               return((aip->ai_mode & mode) ? 1 : 0);
+               return((aip->ai_mode & mode) ? ACLCHECK_OK : ACLCHECK_NO_PRIV);
            }
        }
        for (found_group = 0;
@@ -304,7 +313,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
                    elog(DEBUG, "aclcheck: found %d/%d",
                         aip->ai_id, aip->ai_mode);
 #endif
-                   return(0);
+                   return ACLCHECK_NO_PRIV;
                }
 #endif
            }
@@ -313,7 +322,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
 #ifdef ACLDEBUG_TRACE
            elog(DEBUG,"aclcheck: all groups ok");
 #endif
-           return(1);
+           return ACLCHECK_OK;
        }
        break;
     case ACL_IDTYPE_GID:
@@ -329,7 +338,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
                elog(DEBUG, "aclcheck: found %d/%d",
                     aip->ai_id, aip->ai_mode);
 #endif
-               return((aip->ai_mode & mode) ? 1 : 0);
+               return((aip->ai_mode & mode) ? ACLCHECK_OK : ACLCHECK_NO_PRIV);
            }
        }
        break;
@@ -343,7 +352,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
 #ifdef ACLDEBUG_TRACE
     elog(DEBUG, "aclcheck: using world=%d", aidat->ai_mode);
 #endif
-    return((aidat->ai_mode & mode) ? 1 : 0);
+    return((aidat->ai_mode & mode) ? ACLCHECK_OK : ACLCHECK_NO_PRIV);
 }
 
 int32
@@ -370,7 +379,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
           pg_database table, there is still additional permissions checking
           in dbcommands.c */
        if (mode & ACL_AP)
-           return (1);
+           return ACLCHECK_OK;
     }
 
     /*
@@ -383,7 +392,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
        !((Form_pg_user) GETSTRUCT(htp))->usecatupd) {
        elog(DEBUG, "pg_aclcheck: catalog update to \"%-.*s\": permission denied",
             NAMEDATALEN, relname);
-       return(0);
+       return ACLCHECK_NO_PRIV;
     }
        
     /*
@@ -394,7 +403,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
        elog(DEBUG, "pg_aclcheck: \"%-.*s\" is superuser",
             NAMEDATALEN, usename);
 #endif
-       return(1);
+       return ACLCHECK_OK;
     }
        
 #ifndef ACLDEBUG
@@ -403,7 +412,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
     if (!HeapTupleIsValid(htp)) {
        elog(WARN, "pg_aclcheck: class \"%-.*s\" not found",
             NAMEDATALEN, relname);
-       return(1);
+       /* an elog(WARN) kills us, so no need to return anything. */
     }
     if (!heap_attisnull(htp, Anum_pg_class_relacl)) {
        relation = heap_openr(RelationRelationName);
@@ -436,7 +445,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
        if (!RelationIsValid(relation)) {
            elog(NOTICE, "pg_checkacl: could not open \"%-.*s\"??",
                 RelationRelationName);
-           return(1);
+           return ACLCHECK_NO_CLASS;
        }
        fmgr_info(NameEqualRegProcedure,
                  &relkey[0].sk_func,
@@ -494,8 +503,8 @@ pg_ownercheck(char *usename,
     switch (cacheid) {
     case OPROID:
        if (!HeapTupleIsValid(htp))
-           elog(WARN, "pg_ownercheck: operator %d not found",
-                (int) value);
+           elog(WARN, "pg_ownercheck: operator %ld not found",
+                PointerGetDatum(value));
        owner_id = ((OperatorTupleForm) GETSTRUCT(htp))->oprowner;
        break;
     case PRONAME:
index 693dadc8346096cd82dfc360f93a2a6709790b64..065d01457cc0feb0de0896162367608461d868f1 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.11 1997/01/16 14:56:21 momjian Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.12 1997/03/12 20:48:27 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -381,10 +381,13 @@ ProcessUtility(Node *parsetree,
     case T_RuleStmt:            /* CREATE RULE */
        {
            RuleStmt *stmt = (RuleStmt *)parsetree;
+           int aclcheck_result;
+
 #ifndef NO_SECURITY
            relname = stmt->object->relname;
-           if (!pg_aclcheck(relname, userName, ACL_RU))
-               elog(WARN, "%s %s", relname, ACL_NO_PRIV_WARNING);      
+           aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
+           if(aclcheck_result != ACLCHECK_OK)
+               elog(WARN, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); 
 #endif
            commandTag = "CREATE";
            CHECK_IF_ABORTED();
@@ -423,19 +426,21 @@ ProcessUtility(Node *parsetree,
                         relname);
 #ifndef NO_SECURITY
                if (!pg_ownercheck(userName, relname, RELNAME))
-                   elog(WARN, "you do not own class \"%s\"",
-                        relname);
+                   elog(WARN, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
 #endif
                RemoveIndex(relname);
                break;
            case RULE:
                {
                    char *rulename = stmt->name;
+                   int aclcheck_result;
 #ifndef NO_SECURITY
                
                    relationName = RewriteGetRuleEventRel(rulename);
-                   if (!pg_aclcheck(relationName, userName, ACL_RU))
-                       elog(WARN, "%s %s", relationName, ACL_NO_PRIV_WARNING);
+                   aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
+                   if(aclcheck_result != ACLCHECK_OK) {
+                       elog(WARN, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
+                   }
 #endif
                    RemoveRewriteRule(rulename);
                }
@@ -457,7 +462,7 @@ ProcessUtility(Node *parsetree,
                    ruleName = MakeRetrieveViewRuleName(viewName);
                    relationName = RewriteGetRuleEventRel(ruleName);
                    if (!pg_ownercheck(userName, relationName, RELNAME))
-                       elog(WARN, "%s %s", relationName, ACL_NO_PRIV_WARNING);
+                       elog(WARN, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
                    pfree(ruleName);
 #endif
                    RemoveView(viewName);
index 978950150413f85b1c3c795d433929b1387c992e..bc4473d37d7dce500aa0b92364bf363b673c5e06 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: acl.h,v 1.4 1996/11/10 03:06:14 momjian Exp $
+ * $Id: acl.h,v 1.5 1997/03/12 20:48:48 scrappy Exp $
  *
  * NOTES
  *    For backward-compatability purposes we have to allow there
@@ -111,10 +111,14 @@ typedef ArrayType IdList;
 #define        ACL_MODE_WR_CHR         'w'
 #define        ACL_MODE_RU_CHR         'R'
 
-/* we use this warning string both for non-existent tables and
-   insufficient privilege so non-privileged users cannot ascertain whether 
-   the class exists or not */
-#define ACL_NO_PRIV_WARNING "Either no such class or insufficient privilege"
+/* result codes for pg_aclcheck */
+#define ACLCHECK_OK               0
+#define ACLCHECK_NO_PRIV          1
+#define ACLCHECK_NO_CLASS         2
+#define ACLCHECK_NOT_OWNER        3
+
+/* warning messages.  set these in aclchk.c. */
+extern char *aclcheck_error_strings[];
 
 /*
  * Enable ACL execution tracing and table dumps