The ability to load extensions is turned off by default.  It must be
enabled by calling sqlite3_enable_load_extension() before it will work.
This prevents security problems in legacy applications.  Ticket #1863. (CVS 3311)

FossilOrigin-Name: 4692319ccf28b0ebe64d5c5d189f444034fe0cb2
diff --git a/manifest b/manifest
index 516fb01..d0b503f 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Changes\sto\sbuild\ssuccessfully\swith\s-DSQLITE_OMIT_LOAD_EXTENSION=1\s(CVS\s3310)
-D 2006-06-27T14:37:20
+C The\sability\sto\sload\sextensions\sis\sturned\soff\sby\sdefault.\s\sIt\smust\sbe\nenabled\sby\scalling\ssqlite3_enable_load_extension()\sbefore\sit\swill\swork.\nThis\sprevents\ssecurity\sproblems\sin\slegacy\sapplications.\s\sTicket\s#1863.\s(CVS\s3311)
+D 2006-06-27T15:16:15
 F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -48,7 +48,7 @@
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
 F src/insert.c 63f01d3f4e0ba7ed171934a24aece2191824faec
 F src/legacy.c 10e01a902d7f2c872c7922fedf19a2df70935857
-F src/loadext.c e4a39d0c8443827b517024a3369584024ba23e17
+F src/loadext.c 040853b36adf535bba6a2e9f5d921422a4394baf
 F src/main.c 2f78bd86852fdd42e3e9e0e4dba54000d9dc516d
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235
@@ -71,13 +71,13 @@
 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
 F src/select.c 380fa06c99ae01050c0054c4b1db91e9f1d8322d
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
-F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36
-F src/sqlite.h.in af0ec0cfb2f8211e42cabf2523d1c8783f35ccaf
+F src/shell.c 48d8e65784c2fcb8c906d464f3c441640ff21c9d
+F src/sqlite.h.in a1ae5f372affd1313d9bea98155f01626f538fbd
 F src/sqlite3ext.h c611255287e9a11ce4f1fe6251c2a0b9d32a828b
-F src/sqliteInt.h 3e3f9efa7f043f3b677a35652120092c5902dd3d
+F src/sqliteInt.h e07a49b3e349c2c5f1bcb7dd9371fc3faf5ba338
 F src/table.c e707e822aad688034d391b93df63d6b2d302fdca
 F src/tclsqlite.c 32d9e0147077f2e2c127c5f214fb3fe03ef97d18
-F src/test1.c d398aa0c2227b76696a249f0fb9a506e6e391928
+F src/test1.c 4127f457e4d9bf086c58b32297c098963defddf6
 F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
 F src/test3.c 833dc8346e431182ae6bd0648455c3d4cc65a19f
 F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
@@ -196,7 +196,7 @@
 F test/laststmtchanges.test 19a6d0c11f7a31dc45465b495f7b845a62cbec17
 F test/like.test 5f7d76574752a9101cac13372c8a85999d0d91e6
 F test/limit.test 2a87b9cb2165abb49ca0ddcf5cb43cf24074581f
-F test/loadext.test 6a047b9bb784a92643c371643bf8acf29a0beb6e
+F test/loadext.test 146ead2c34b76fe4d51a5054b7e52b76f35fba90
 F test/lock.test 9b7afcb24f53d24da502abb33daaad2cd6d44107
 F test/lock2.test d83ba79d3c4fffdb5b926c7d8ca7a36c34288a55
 F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
@@ -374,7 +374,7 @@
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 5612b287059c75488f995625d447c4e9521d1637
-R 3722049afc5fc0079c432abf2589144f
+P 783369e870df9d189fc75c98fa574fe4fc9843d0
+R 03b010c340d22a562ee989d0414f81c5
 U drh
-Z 5ed9e00c9b5d8d18b3e6766a2179c4cd
+Z b75df8d7be6621720643222d3b606d63
diff --git a/manifest.uuid b/manifest.uuid
index 1ffc493..7dd2e0b 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-783369e870df9d189fc75c98fa574fe4fc9843d0
\ No newline at end of file
+4692319ccf28b0ebe64d5c5d189f444034fe0cb2
\ No newline at end of file
diff --git a/src/loadext.c b/src/loadext.c
index 2d254aa..60ec053 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -261,6 +261,19 @@
   char *zErrmsg = 0;
   SQLITE_LIBRARY_TYPE *aHandle;
 
+  /* Ticket #1863.  To avoid a creating security problems for older
+  ** applications that relink against newer versions of SQLite, the
+  ** ability to run load_extension is turned off by default.  One
+  ** must call sqlite3_enable_load_extension() to turn on extension
+  ** loading.  Otherwise you get the following error.
+  */
+  if( (db->flags & SQLITE_LoadExtension)==0 ){
+    if( pzErrMsg ){
+      *pzErrMsg = sqlite3_mprintf("not authorized");
+    }
+    return SQLITE_ERROR;
+  }
+
   if( zProc==0 ){
     zProc = "sqlite3_extension_init";
   }
@@ -326,4 +339,17 @@
 #endif
 }
 
+/*
+** Enable or disable extension loading.  Extension loading is disabled by
+** default so as not to open security holes in older applications.
+*/
+int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
+  if( onoff ){
+    db->flags |= SQLITE_LoadExtension;
+  }else{
+    db->flags &= ~SQLITE_LoadExtension;
+  }
+  return SQLITE_OK;
+}
+
 #endif /* SQLITE_OMIT_LOAD_EXTENSION */
diff --git a/src/shell.c b/src/shell.c
index fdb9c1a..9d163c3 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -12,7 +12,7 @@
 ** This file contains code to implement the "sqlite" command line
 ** utility for accessing SQLite databases.
 **
-** $Id: shell.c,v 1.142 2006/06/13 15:12:21 drh Exp $
+** $Id: shell.c,v 1.143 2006/06/27 15:16:15 drh Exp $
 */
 #include <stdlib.h>
 #include <string.h>
@@ -807,6 +807,9 @@
           p->zDbFilename, sqlite3_errmsg(db));
       exit(1);
     }
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+    sqlite3_enable_load_extension(p->db, 1);
+#endif
   }
 }
 
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 8687655..6b17901 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.184 2006/06/26 21:35:45 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.185 2006/06/27 15:16:15 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -1485,7 +1485,7 @@
 **
 ** Attempt to load an SQLite extension library contained in the file
 ** zFile.  The entry point is zProc.  zProc may be 0 in which case the
-** name of the entry point is derived from the filename.
+** name of the entry point defaults to "sqlite3_extension_init".
 **
 ** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
 **
@@ -1493,23 +1493,8 @@
 ** error message text.  The calling function should free this memory
 ** by calling sqlite3_free().
 **
-** The entry point name is derived from the filename according to the
-** following steps:
-**
-**    * Convert the name to lower case
-**    * Remove the path prefix from the name
-**    * Remove the first "." and all following characters from the name
-**    * If the name begins with "lib" remove the first 3 characters
-**    * Remove all characters that are not US-ASCII alphanumerics
-**      or underscores
-**    * Remove any leading digits and underscores from the name
-**    * Append "_init" to the name
-**
-** So, for example, if the input filename is "/home/drh/libtest1.52.so"
-** then the entry point would be computed as "test1_init".
-**
-** The derived entry point name is limited to a reasonable number of
-** characters (currently 200).
+** Extension loading must be enabled using sqlite3_enable_load_extension()
+** prior to calling this API or an error will be returned.
 **
 ****** EXPERIMENTAL - subject to change without notice **************
 */
@@ -1521,6 +1506,18 @@
 );
 
 /*
+** So as not to open security holes in older applications that are
+** unprepared to deal with extension load, and as a means of disabling
+** extension loading while executing user-entered SQL, the following
+** API is provided to turn the extension loading mechanism on and
+** off.  It is off by default.  See ticket #1863.
+**
+** Call this routine with onoff==1 to turn extension loading on
+** and call it with onoff==0 to turn it back off again.
+*/
+int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+
+/*
 ****** EXPERIMENTAL - subject to change without notice **************
 **
 ** The interface to the virtual-table mechanism is currently considered
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 6a76acf..39876fe 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.516 2006/06/27 14:37:20 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.517 2006/06/27 15:16:15 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -536,9 +536,10 @@
 #define SQLITE_NoReadlock     0x00001000  /* Readlocks are omitted when 
                                           ** accessing read-only databases */
 #define SQLITE_IgnoreChecks   0x00002000  /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x00004000  /* For shared-cache mode */
+#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */
 #define SQLITE_LegacyFileFmt  0x00008000  /* Create new databases in format 1 */
 #define SQLITE_FullFSync      0x00010000  /* Use full fsync on the backend */
+#define SQLITE_LoadExtension  0x00020000  /* Enable load_extension */
 
 /*
 ** Possible values for the sqlite.magic field.
diff --git a/src/test1.c b/src/test1.c
index ac8a263..efbb182 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.214 2006/06/27 12:51:13 drh Exp $
+** $Id: test1.c,v 1.215 2006/06/27 15:16:16 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -1094,6 +1094,7 @@
 }
 #endif
 
+
 /*
 ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
 */
@@ -1133,7 +1134,12 @@
   ** TCL_ERROR and load any error string into the interpreter. If no 
   ** error occurs, set rc to TCL_OK.
   */
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+  rc = SQLITE_ERROR;
+  zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
+#else
   rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
+#endif
   if( rc!=SQLITE_OK ){
     Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
     rc = TCL_ERROR;
@@ -1146,6 +1152,48 @@
 }
 
 /*
+** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
+*/
+static int test_enable_load(
+  ClientData clientData, /* Not used */
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int objc,              /* Number of arguments */
+  Tcl_Obj *CONST objv[]  /* Command arguments */
+){
+  Tcl_CmdInfo cmdInfo;
+  sqlite3 *db;
+  char *zDb;
+  int onoff;
+
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
+    return TCL_ERROR;
+  }
+  zDb = Tcl_GetString(objv[1]);
+
+  /* Extract the C database handle from the Tcl command name */
+  if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
+    Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
+    return TCL_ERROR;
+  }
+  db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
+  assert(db);
+
+  /* Get the onoff parameter */
+  if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
+    return TCL_ERROR;
+  }
+
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+  Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
+  return TCL_ERROR;
+#else
+  sqlite3_enable_load_extension(db, onoff);
+  return TCL_OK;
+#endif
+}
+
+/*
 ** Usage:  sqlite_abort
 **
 ** Shutdown the process immediately.  This is not a clean shutdown.
@@ -3692,6 +3740,9 @@
      { "sqlite3_tsd_release",           test_tsd_release,        0},
      { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
 
+     { "sqlite3_load_extension",        test_load_extension,     0},
+     { "sqlite3_enable_load_extension", test_enable_load,        0},
+
      /* sqlite3_column_*() API */
      { "sqlite3_column_count",          test_column_count  ,0 },
      { "sqlite3_data_count",            test_data_count    ,0 },
@@ -3752,9 +3803,6 @@
 #ifdef SQLITE_ENABLE_COLUMN_METADATA
      { "sqlite3_table_column_metadata", test_table_column_metadata, 0  },
 #endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
-     { "sqlite3_load_extension", test_load_extension, 0  },
-#endif
   };
   static int bitmask_size = sizeof(Bitmask)*8;
   int i;
diff --git a/test/loadext.test b/test/loadext.test
index b53e8ba..514edb3 100644
--- a/test/loadext.test
+++ b/test/loadext.test
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this script is in-memory database backend.
 #
-# $Id: loadext.test,v 1.4 2006/06/26 21:35:46 drh Exp $
+# $Id: loadext.test,v 1.5 2006/06/27 15:16:16 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -50,6 +50,7 @@
   }
 } {1 {no such function: half}}
 do_test loadext-1.2 {
+  sqlite3_enable_load_extension db 1
   sqlite3_load_extension db $testextension testloadext_init
   catchsql {
     SELECT half(1.0);
@@ -60,6 +61,7 @@
 #
 do_test loadext-1.3 {
   sqlite3 db2 test.db
+  sqlite3_enable_load_extension db2 1
   catchsql {
     SELECT half(1.0);
   } db2
@@ -83,6 +85,7 @@
 
 db2 close
 sqlite3 db test.db
+sqlite3_enable_load_extension db 1
 
 # Try to load an extension for which the file does not exist.
 #
@@ -136,6 +139,7 @@
 
 db close
 sqlite3 db test.db
+sqlite3_enable_load_extension db 1
 do_test loadext-3.1 {
   catchsql {
     SELECT half(5);
@@ -158,4 +162,31 @@
   }
 } {0 2.5}
 
+# Ticket #1863
+# Make sure the extension loading mechanism will not work unless it
+# is explicitly enabled.
+#
+db close
+sqlite3 db test.db
+do_test loadext-4.1 {
+  catchsql {
+    SELECT load_extension($::testextension,'testloadext_init')
+  }
+} {1 {not authorized}}
+do_test loadext-4.2 {
+  sqlite3_enable_load_extension db 1
+  catchsql {
+    SELECT load_extension($::testextension,'testloadext_init')
+  }
+} {0 {{}}}
+
+do_test loadext-4.3 {
+  sqlite3_enable_load_extension db 0
+  catchsql {
+    SELECT load_extension($::testextension,'testloadext_init')
+  }
+} {1 {not authorized}}
+
+
+
 finish_test