From 81e293b4b20430af25d00f5538808b8f8fe44444 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 6 Jun 2003 19:00:42 +0000 Subject: [PATCH] Extend the authorization mechanism to disallow the ATTACH and DETACH commands. Ticket #340. (CVS 1010) FossilOrigin-Name: a97dca73aed0b42d8dcf944360667ae93c5324fd --- manifest | 18 ++++----- manifest.uuid | 2 +- src/attach.c | 50 +++++++++++++++--------- src/sqlite.h.in | 5 ++- src/tclsqlite.c | 4 +- test/auth.test | 102 +++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 150 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index cbc8db9fe5..1ff9d6d556 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sbtree_rb.c\sand\sopcodes.c\sto\sthe\ssource\sbuilt\sby\sthe\s"target_source"\starget\nof\sthe\smain\smakefile.\s(CVS\s1009) -D 2003-06-06T16:13:41 +C Extend\sthe\sauthorization\smechanism\sto\sdisallow\sthe\sATTACH\sand\sDETACH\scommands.\nTicket\s#340.\s(CVS\s1010) +D 2003-06-06T19:00:42 F Makefile.in 98a14dc13a78ca0e12007e974c93aeb098db7f68 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -19,7 +19,7 @@ F publish.sh 86b5e8535830a2588f62ce1d5d1ef00e1dede23a F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 -F src/attach.c db89b086f58b679e3f140296e3b95942989b04ba +F src/attach.c 0f0dd4b0d2dbd7432a46bed74114c7cc8de4c8e3 F src/auth.c c8f50d4507e37779d96ff3c55417bc2b612dfed6 F src/btree.c 6656625305e5e99adda818a772bf7432a7b15d97 F src/btree.h 9b7c09f1e64274d7bb74a57bbfc63778f67b1048 @@ -46,10 +46,10 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c 76b3a5cda76421cfe82d6a96c72308c2518cb2f9 F src/shell.c b63089a91d6584df06eaa2e53ea1150c68ab1e61 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e -F src/sqlite.h.in 58329e102ee5df8753620487f608a91611ba4592 +F src/sqlite.h.in 54619fa5df4c83b22def66bb3d24808fd03dcbae F src/sqliteInt.h d1d883d9116dadf63ffe1bafe17ba6455b7db59e F src/table.c 4301926464d88d2c2c7cd21c3360aa75bf068b95 -F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d +F src/tclsqlite.c d6860dcd56348b9521726280b72c412d2a33ae97 F src/test1.c 4596acd9d9f2a49fda0160a8a6dee5bfc7c6c325 F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5 @@ -64,7 +64,7 @@ F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21 F src/where.c 1e645d430cb4b347159c28c6085e9801160f2099 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test 71905b5e7a5a712e7ea47d249431740e617ec75e -F test/auth.test dee78be1f4f920bd6b15c4c947ce4d01bfe2826d +F test/auth.test a618f0e96bb5baa7a5623eb939388e9ac5f5d9a2 F test/bigfile.test 1cd8256d4619c39bea48147d344f348823e78678 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/btree.test 1e3463c7838e7e71bbf37c9c6e45beee9c8975ba @@ -165,7 +165,7 @@ F www/speed.tcl 296cc5632d069b56d3ef5409ca0df90f486c10fb F www/sqlite.tcl 4bd1729e320f5fa9125f0022b281fbe839192125 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 048cf55c7da92e363f6a2ab594e17280c9573410 -R 24123d17093bb9adb37edb5fe60ff41b +P 09546972991601697925c10b6ef31694b0be2385 +R 2688e6833b4c30f26b7524864dd64eb2 U drh -Z 96edff991735bfd9ca5acb39a9aa9cd1 +Z 160fa4fe206cb761a89db5dbd54f41dd diff --git a/manifest.uuid b/manifest.uuid index fad213455e..51b178fcf9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -09546972991601697925c10b6ef31694b0be2385 \ No newline at end of file +a97dca73aed0b42d8dcf944360667ae93c5324fd \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index d8901187be..e2d4de230b 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.5 2003/06/03 01:47:11 drh Exp $ +** $Id: attach.c,v 1.6 2003/06/06 19:00:42 drh Exp $ */ #include "sqliteInt.h" @@ -43,6 +43,32 @@ void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ pParse->rc = SQLITE_ERROR; return; } + + zFile = 0; + sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); + if( zFile==0 ) return; + sqliteDequote(zFile); +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){ + sqliteFree(zFile); + return; + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + zName = 0; + sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); + if( zName==0 ) return; + sqliteDequote(zName); + for(i=0; inDb; i++){ + if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ + sqliteErrorMsg(pParse, "database %z is already in use", zName); + pParse->rc = SQLITE_ERROR; + sqliteFree(zFile); + sqliteFree(zName); + return; + } + } + if( db->aDb==db->aDbStatic ){ aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; @@ -58,24 +84,7 @@ void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); - - zName = 0; - sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); - if( zName==0 ) return; - sqliteDequote(zName); - for(i=0; inDb; i++){ - if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ - sqliteErrorMsg(pParse, "database %z is already in use", zName); - db->nDb--; - pParse->rc = SQLITE_ERROR; - return; - } - } aNew->zName = zName; - zFile = 0; - sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); - if( zFile==0 ) return; - sqliteDequote(zFile); rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt); if( rc ){ sqliteErrorMsg(pParse, "unable to open database: %s", zFile); @@ -117,6 +126,11 @@ void sqliteDetach(Parse *pParse, Token *pDbname){ sqliteErrorMsg(pParse, "cannot detach database %T", pDbname); return; } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){ + return; + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ sqliteBtreeClose(db->aDb[i].pBt); db->aDb[i].pBt = 0; sqliteFree(db->aDb[i].zName); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 3b1a5082ef..02c233a6aa 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.48 2003/06/06 15:44:01 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.49 2003/06/06 19:00:42 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -555,6 +555,9 @@ int sqlite_set_authorizer( #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* NULL NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ + /* ** The return value of the authorization function should be one of the diff --git a/src/tclsqlite.c b/src/tclsqlite.c index ed4eb6c475..20d7499f0d 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.48 2003/04/23 12:25:24 drh Exp $ +** $Id: tclsqlite.c,v 1.49 2003/06/06 19:00:42 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -380,6 +380,8 @@ static int auth_callback( case SQLITE_SELECT : zCode="SQLITE_SELECT"; break; case SQLITE_TRANSACTION : zCode="SQLITE_TRANSACTION"; break; case SQLITE_UPDATE : zCode="SQLITE_UPDATE"; break; + case SQLITE_ATTACH : zCode="SQLITE_ATTACH"; break; + case SQLITE_DETACH : zCode="SQLITE_DETACH"; break; default : zCode="????"; break; } Tcl_DStringInit(&str); diff --git a/test/auth.test b/test/auth.test index 84b3802e1b..6dde44d880 100644 --- a/test/auth.test +++ b/test/auth.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: auth.test,v 1.9 2003/04/25 17:52:11 drh Exp $ +# $Id: auth.test,v 1.10 2003/06/06 19:00:42 drh Exp $ # set testdir [file dirname $argv0] @@ -1591,6 +1591,106 @@ do_test auth-1.250 { execsql {SELECT * FROM t2} } {11 2 33 7 8 9} +# ticket #340 - authorization for ATTACH and DETACH. +# +do_test auth-1.251 { + db authorizer ::auth + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_ATTACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + } + return SQLITE_OK + } + catchsql { + ATTACH DATABASE ':memory:' AS test1 + } +} {0 {}} +do_test auth-1.252 { + set ::authargs +} {:memory: {} {} {}} +do_test auth-1.253 { + catchsql {DETACH DATABASE test1} + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_ATTACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + return SQLITE_DENY + } + return SQLITE_OK + } + catchsql { + ATTACH DATABASE ':memory:' AS test1; + } +} {1 {not authorized}} +do_test auth-1.254 { + lindex [execsql {PRAGMA database_list}] 7 +} {} +do_test auth-1.255 { + catchsql {DETACH DATABASE test1} + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_ATTACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + return SQLITE_IGNORE + } + return SQLITE_OK + } + catchsql { + ATTACH DATABASE ':memory:' AS test1; + } +} {0 {}} +do_test auth-1.256 { + lindex [execsql {PRAGMA database_list}] 7 +} {} +do_test auth-1.257 { + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_DETACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + return SQLITE_OK + } + return SQLITE_OK + } + execsql {ATTACH DATABASE ':memory:' AS test1} + catchsql { + DETACH DATABASE test1; + } +} {0 {}} +do_test auth-1.258 { + lindex [execsql {PRAGMA database_list}] 7 +} {} +do_test auth-1.259 { + execsql {ATTACH DATABASE ':memory:' AS test1} + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_DETACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + return SQLITE_IGNORE + } + return SQLITE_OK + } + catchsql { + DETACH DATABASE test1; + } +} {0 {}} +do_test auth-1.260 { + lindex [execsql {PRAGMA database_list}] 7 +} {test1} +do_test auth-1.261 { + proc auth {code arg1 arg2 arg3 arg4} { + if {$code=="SQLITE_DETACH"} { + set ::authargs [list $arg1 $arg2 $arg3 $arg4] + return SQLITE_DENY + } + return SQLITE_OK + } + catchsql { + DETACH DATABASE test1; + } +} {1 {not authorized}} +do_test auth-1.262 { + lindex [execsql {PRAGMA database_list}] 7 +} {test1} +db authorizer {} +execsql {DETACH DATABASE test1} + + do_test auth-2.1 { proc auth {code arg1 arg2 arg3 arg4} { if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {