]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When inserting a row into a child table, invoke the authorization callback to request...
authordan <dan@noemail.net>
Fri, 2 Oct 2009 14:23:41 +0000 (14:23 +0000)
committerdan <dan@noemail.net>
Fri, 2 Oct 2009 14:23:41 +0000 (14:23 +0000)
FossilOrigin-Name: 9842f2d5f606eb8f641ecae9fbc5368b8d7e4286

manifest
manifest.uuid
src/auth.c
src/fkey.c
src/sqliteInt.h
test/fkey2.test

index c91a80b6de67aaf524ec9dad1240c8f335c2e9d7..16ea33baa79f7f42ed130acd801e1037b72a300d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\stest\sto\scheck\sthat\sthe\sincrblob\sAPI\scannot\sbe\sused\sto\swrite\sto\san\sIPK\scolumn.\sAlso\sa\scomment\sto\sexplain\swhy\sthe\sincrblob\scode\sdoes\snot\sneed\sto\scheck\sif\sa\scolumn\sis\spart\sof\sa\sparent\skey\sbefore\swriting\sto\sit.
-D 2009-10-02T06:35:06
+C When\sinserting\sa\srow\sinto\sa\schild\stable,\sinvoke\sthe\sauthorization\scallback\sto\srequest\spermission\sto\sread\sthe\sparent\skey\scolumns.
+D 2009-10-02T14:23:42
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -102,7 +102,7 @@ F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
 F src/alter.c 1b63d4f2a6e76af9e2964d4d86ccc8e74c3fae4a
 F src/analyze.c 5a8b8aa3d170eac5e71af45458cec61f83c623ee
 F src/attach.c 13995348fc5a26cdd136a50806faf292aabc173f
-F src/auth.c d6a88bf8e81e6a079ccb8881002b327e42ec46b9
+F src/auth.c 50a4fd3ad4a0d3dec95cec7c022a6ca9d5ca3f4e
 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
 F src/bitvec.c ed215b95734045e58358c3b3e16448f8fe6a235a
 F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
@@ -116,7 +116,7 @@ F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
 F src/delete.c 308e300d599d2d11b838687e2cf7309d42f29a1a
 F src/expr.c c7f3f718bd5c392344ec8694a41c1824f30cf375
 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
-F src/fkey.c b20074e0dcbf6bbaafa8a520ed12efb30bb6aac3
+F src/fkey.c bcc2af88a4f88cb2127cd5fb68d4e09e73e03063
 F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
@@ -164,7 +164,7 @@ F src/select.c 1d0a13137532321b4364f964e46f057d271691e3
 F src/shell.c d6e64471aafb81f355262533393169a70529847a
 F src/sqlite.h.in 5af8181f815831a8672c3834c60e6b4418448bcc
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 6730f9584eed76460ed85d2ade13914a6b68caab
+F src/sqliteInt.h 20ca4172804c85745445bd3291d7884446b67bd7
 F src/sqliteLimit.h 504a3161886d2938cbd163054ad620b8356df758
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@@ -330,7 +330,7 @@ F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68
 F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8
 F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43
 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
-F test/fkey2.test 8a3620f0f230d90c9a934064203061c697948a92
+F test/fkey2.test e4bc39a77e140bff6f5b8f6adfad599a0dca1720
 F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
 F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -755,7 +755,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P aaa005b6da222f711f201c453d28f5be40e9c601
-R 41b569942ce78deea05315bc00bbbc6d
+P dca2a7f608d9237039541707846c76cd460f5805
+R 30336a7d8a841925ec6f327a1d0cb82e
 U dan
-Z 9732e09af43d5f7c1ec2d1ca2b86bc1f
+Z f7abd111a6647a2871746e5a320e0ffd
index bc06f7eedc4c0446b58e04518a35e4e348731c80..598e939dfbe6ecc71cd47fd9fccbd23e69ac0895 100644 (file)
@@ -1 +1 @@
-dca2a7f608d9237039541707846c76cd460f5805
\ No newline at end of file
+9842f2d5f606eb8f641ecae9fbc5368b8d7e4286
\ No newline at end of file
index ec35142572827739238323eb0a257b30ea9b47fc..042fc66150c7ce6605dee0a62a3ce3c63ffaad3c 100644 (file)
@@ -91,6 +91,41 @@ static void sqliteAuthBadReturnCode(Parse *pParse){
   pParse->rc = SQLITE_ERROR;
 }
 
+/*
+** Invoke the authorization callback for permission to read column zCol from
+** table zTab in database zDb. This function assumes that an authorization
+** callback has been registered (i.e. that sqlite3.xAuth is not NULL).
+**
+** If SQLITE_IGNORE is returned and pExpr is not NULL, then pExpr is changed
+** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE_IGNORE
+** is treated as SQLITE_DENY. In this case an error is left in pParse.
+*/
+void sqlite3AuthReadCol(
+  Parse *pParse,                  /* The parser context */
+  const char *zTab,               /* Table name */
+  const char *zCol,               /* Column name */
+  int iDb,                        /* Index of containing database. */
+  Expr *pExpr                     /* Optional expression */
+){
+  sqlite3 *db = pParse->db;       /* Database handle */
+  char *zDb = db->aDb[iDb].zName; /* Name of attached database */
+  int rc;                         /* Auth callback return code */
+
+  rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
+  if( rc!=SQLITE_IGNORE && rc!=SQLITE_DENY && rc!=SQLITE_OK ){
+    sqliteAuthBadReturnCode(pParse);
+  }else if( rc==SQLITE_IGNORE && pExpr ){
+    pExpr->op = TK_NULL;
+  }else if( rc!=SQLITE_OK ){
+    if( db->nDb>2 || iDb!=0 ){
+      sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
+    }else{
+      sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
+    }
+    pParse->rc = SQLITE_AUTH;
+  }
+}
+
 /*
 ** The pExpr should be a TK_COLUMN expression.  The table referred to
 ** is in pTabList or else it is the NEW or OLD table of a trigger.  
@@ -107,11 +142,9 @@ void sqlite3AuthRead(
   SrcList *pTabList     /* All table that pExpr might refer to */
 ){
   sqlite3 *db = pParse->db;
-  int rc;
   Table *pTab = 0;      /* The table being read */
   const char *zCol;     /* Name of the column of the table */
   int iSrc;             /* Index in pTabList->a[] of table being read */
-  const char *zDBase;   /* Name of database being accessed */
   int iDb;              /* The index of the database the expression refers to */
   int iCol;             /* Index of column in table */
 
@@ -148,22 +181,7 @@ void sqlite3AuthRead(
     zCol = "ROWID";
   }
   assert( iDb>=0 && iDb<db->nDb );
-  zDBase = db->aDb[iDb].zName;
-  rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, 
-                 pParse->zAuthContext);
-  if( rc==SQLITE_IGNORE ){
-    pExpr->op = TK_NULL;
-  }else if( rc==SQLITE_DENY ){
-    if( db->nDb>2 || iDb!=0 ){
-      sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", 
-         zDBase, pTab->zName, zCol);
-    }else{
-      sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol);
-    }
-    pParse->rc = SQLITE_AUTH;
-  }else if( rc!=SQLITE_OK ){
-    sqliteAuthBadReturnCode(pParse);
-  }
+  sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb, pExpr);
 }
 
 /*
index 4d6a32ad698487764af4f5bcce2f1a953e8eec0d..dc5b4199cc54bab036aa551b21d3c383b5c5f0da 100644 (file)
@@ -732,6 +732,13 @@ void sqlite3FkCheck(
       if( aiCol[i]==pTab->iPKey ){
         aiCol[i] = -1;
       }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+      /* Request permission to read the parent key columns. */
+      if( db->xAuth ){
+        char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
+        sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb, 0);
+      }
+#endif
     }
 
     /* Take a shared-cache advisory read-lock on the parent table. Allocate 
index f97a81ca648dece165987e4135a375c6fe38519d..a82bbdfc8a38fe6ce780f30fe76c84252c815203 100644 (file)
@@ -2734,6 +2734,7 @@ void sqlite3DeferForeignKey(Parse*, int);
   int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
   void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
   void sqlite3AuthContextPop(AuthContext*);
+  void sqlite3AuthReadCol(Parse*, const char *, const char *, int, Expr *);
 #else
 # define sqlite3AuthRead(a,b,c,d)
 # define sqlite3AuthCheck(a,b,c,d,e)    SQLITE_OK
index c742073f2767e8739e4aeb9ff84a1cabca825d45..45d36a08c9d19da4140595702da11d5b25517eaf 100644 (file)
@@ -1351,13 +1351,78 @@ do_test fkey2-17.2.9 {
 do_test fkey2-17.2.10 {
   execsql { SELECT * FROM high ; SELECT * FROM low }
 } {}
+execsql { PRAGMA count_changes = 0 }
 
 #-------------------------------------------------------------------------
 # Test that the authorization callback works.
 #
 
+ifcapable auth {
+  do_test fkey2-18.1 {
+    execsql {
+      CREATE TABLE long(a, b PRIMARY KEY, c);
+      CREATE TABLE short(d, e, f REFERENCES long);
+      CREATE TABLE mid(g, h, i REFERENCES long DEFERRABLE INITIALLY DEFERRED);
+    }
+  } {}
+
+  proc auth {args} {eval lappend ::authargs $args ; return SQLITE_OK}
+  db auth auth
+
+  # An insert on the parent table must read the child key of any deferred
+  # foreign key constraints. But not the child key of immediate constraints.
+  set authargs {}
+  do_test fkey2-18.2 {
+    execsql { INSERT INTO long VALUES(1, 2, 3) }
+    set authargs
+  } {SQLITE_INSERT long {} main {} SQLITE_READ mid i main {}}
+
+  # An insert on the child table of an immediate constraint must read the
+  # parent key columns (to see if it is a violation or not).
+  set authargs {}
+  do_test fkey2-18.3 {
+    execsql { INSERT INTO short VALUES(1, 3, 2) }
+    set authargs
+  } {SQLITE_INSERT short {} main {} SQLITE_READ long b main {}}
+  
+  # As must an insert on the child table of a deferred constraint.
+  set authargs {}
+  do_test fkey2-18.4 {
+    execsql { INSERT INTO mid VALUES(1, 3, 2) }
+    set authargs
+  } {SQLITE_INSERT mid {} main {} SQLITE_READ long b main {}}
+
+  do_test fkey2-18.5 {
+    execsql {
+      CREATE TABLE nought(a, b PRIMARY KEY, c);
+      CREATE TABLE cross(d, e, f,
+        FOREIGN KEY(e) REFERENCES nought(b) ON UPDATE CASCADE
+      );
+    }
+    execsql { INSERT INTO nought VALUES(2, 1, 2) }
+    execsql { INSERT INTO cross VALUES(0, 1, 0) }
+    set authargs [list]
+    execsql { UPDATE nought SET b = 5 }
+    set authargs
+  } {SQLITE_UPDATE nought b main {} SQLITE_READ cross e main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {} SQLITE_UPDATE cross e main {} SQLITE_READ nought b main {} SQLITE_READ cross e main {} SQLITE_READ nought b main {} SQLITE_READ nought b main {}}
+
+  do_test fkey2-18.6 {
+    execsql {SELECT * FROM cross}
+  } {0 5 0}
+
+  rename auth {}
+  proc auth {args} {
+    if {[lindex $args 1] == "long"} {return SQLITE_IGNORE}
+    return SQLITE_OK
+  }
+  do_test fkey2-18.7 {
+    catchsql { INSERT INTO short VALUES(1, 3, 2) }
+  } {1 {access to long.b is prohibited}}
+
+  db auth {}
+  unset authargs
+}
 
-execsql { PRAGMA count_changes = 0 }
 #-------------------------------------------------------------------------
 # The following block of tests, those prefixed with "fkey2-genfkey.", are 
 # the same tests that were used to test the ".genfkey" command provided