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/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;