Fossil SCM

Additional defenses to prevent the db_protect() and db_protect_pop() SQL functions from being misused.

drh 2020-11-29 12:50 trunk
Commit 6ade35427f4651f0df50335bc90dbc6d81448e24f00a92466d55a6554049ca5a
1 file changed +37 -13
+37 -13
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -32,10 +32,15 @@
3232
3333
#ifndef _WIN32
3434
# include "linenoise.h"
3535
#endif
3636
37
+/*
38
+** True if the "fossil sql" command has the --test flag. False otherwise.
39
+*/
40
+static int local_bSqlCmdTest = 0;
41
+
3742
/*
3843
** Implementation of the "content(X)" SQL function. Return the complete
3944
** content of artifact identified by X as a blob.
4045
*/
4146
static void sqlcmd_content(
@@ -163,33 +168,46 @@
163168
** Undocumented test SQL functions:
164169
**
165170
** db_protect(X)
166171
** db_protect_pop(X)
167172
**
168
-** These invoke the corresponding C routines. Misuse may result in
169
-** an assertion fault.
173
+** These invoke the corresponding C routines.
174
+**
175
+** WARNING:
176
+** Do not instantiate these functions for any Fossil webpage or command
177
+** method of than the "fossil sql" command. If an attacker gains access
178
+** to these functions, he will be able to disable other defense mechanisms.
179
+**
180
+** This routines are for interactiving testing only. They are experimental
181
+** and undocumented (apart from this comments) and might go away or change
182
+** in future releases.
183
+**
184
+** 2020-11-29: This functions are now only available if the "fossil sql"
185
+** command is started with the --test option.
170186
*/
171187
static void sqlcmd_db_protect(
172188
sqlite3_context *context,
173189
int argc,
174190
sqlite3_value **argv
175191
){
176192
unsigned mask = 0;
177193
const char *z = (const char*)sqlite3_value_text(argv[0]);
178
- if( sqlite3_stricmp(z,"user")==0 ) mask |= PROTECT_USER;
179
- if( sqlite3_stricmp(z,"config")==0 ) mask |= PROTECT_CONFIG;
180
- if( sqlite3_stricmp(z,"sensitive")==0 ) mask |= PROTECT_SENSITIVE;
181
- if( sqlite3_stricmp(z,"readonly")==0 ) mask |= PROTECT_READONLY;
182
- if( sqlite3_stricmp(z,"all")==0 ) mask |= PROTECT_ALL;
183
- db_protect(mask);
194
+ if( z!=0 && local_bSqlCmdTest ){
195
+ if( sqlite3_stricmp(z,"user")==0 ) mask |= PROTECT_USER;
196
+ if( sqlite3_stricmp(z,"config")==0 ) mask |= PROTECT_CONFIG;
197
+ if( sqlite3_stricmp(z,"sensitive")==0 ) mask |= PROTECT_SENSITIVE;
198
+ if( sqlite3_stricmp(z,"readonly")==0 ) mask |= PROTECT_READONLY;
199
+ if( sqlite3_stricmp(z,"all")==0 ) mask |= PROTECT_ALL;
200
+ db_protect(mask);
201
+ }
184202
}
185203
static void sqlcmd_db_protect_pop(
186204
sqlite3_context *context,
187205
int argc,
188206
sqlite3_value **argv
189207
){
190
- db_protect_pop();
208
+ if( !local_bSqlCmdTest ) db_protect_pop();
191209
}
192210
193211
194212
195213
@@ -232,14 +250,16 @@
232250
** will get cleaned up when the shell closes the database connection */
233251
if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
234252
sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
235253
db_protect_only(PROTECT_NONE);
236254
sqlite3_set_authorizer(db, db_top_authorizer, db);
237
- sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
238
- sqlcmd_db_protect, 0, 0);
239
- sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
240
- sqlcmd_db_protect_pop, 0, 0);
255
+ if( local_bSqlCmdTest ){
256
+ sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
257
+ sqlcmd_db_protect, 0, 0);
258
+ sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
259
+ sqlcmd_db_protect_pop, 0, 0);
260
+ }
241261
return SQLITE_OK;
242262
}
243263
244264
/*
245265
** atexit() handler that cleans up global state modified by this module.
@@ -329,10 +349,13 @@
329349
** --readonly Open the repository read-only. No changes
330350
** are allowed. This is a recommended safety
331351
** precaution to prevent repository damage.
332352
**
333353
** -R REPOSITORY Use REPOSITORY as the repository database
354
+**
355
+** --test Enable some testing and analysis features
356
+** that are normally disabled.
334357
**
335358
** All of the standard sqlite3 command-line shell options should also
336359
** work.
337360
**
338361
** The following SQL extensions are provided with this Fossil-enhanced
@@ -397,10 +420,11 @@
397420
extern int sqlite3_shell(int, char**);
398421
#ifdef FOSSIL_ENABLE_TH1_HOOKS
399422
g.fNoThHook = 1;
400423
#endif
401424
noRepository = find_option("no-repository", 0, 0)!=0;
425
+ local_bSqlCmdTest = find_option("test",0,0)!=0;
402426
if( !noRepository ){
403427
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
404428
}
405429
db_open_config(1,0);
406430
zConfigDb = fossil_strdup(g.zConfigDbName);
407431
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -32,10 +32,15 @@
32
33 #ifndef _WIN32
34 # include "linenoise.h"
35 #endif
36
 
 
 
 
 
37 /*
38 ** Implementation of the "content(X)" SQL function. Return the complete
39 ** content of artifact identified by X as a blob.
40 */
41 static void sqlcmd_content(
@@ -163,33 +168,46 @@
163 ** Undocumented test SQL functions:
164 **
165 ** db_protect(X)
166 ** db_protect_pop(X)
167 **
168 ** These invoke the corresponding C routines. Misuse may result in
169 ** an assertion fault.
 
 
 
 
 
 
 
 
 
 
 
170 */
171 static void sqlcmd_db_protect(
172 sqlite3_context *context,
173 int argc,
174 sqlite3_value **argv
175 ){
176 unsigned mask = 0;
177 const char *z = (const char*)sqlite3_value_text(argv[0]);
178 if( sqlite3_stricmp(z,"user")==0 ) mask |= PROTECT_USER;
179 if( sqlite3_stricmp(z,"config")==0 ) mask |= PROTECT_CONFIG;
180 if( sqlite3_stricmp(z,"sensitive")==0 ) mask |= PROTECT_SENSITIVE;
181 if( sqlite3_stricmp(z,"readonly")==0 ) mask |= PROTECT_READONLY;
182 if( sqlite3_stricmp(z,"all")==0 ) mask |= PROTECT_ALL;
183 db_protect(mask);
 
 
184 }
185 static void sqlcmd_db_protect_pop(
186 sqlite3_context *context,
187 int argc,
188 sqlite3_value **argv
189 ){
190 db_protect_pop();
191 }
192
193
194
195
@@ -232,14 +250,16 @@
232 ** will get cleaned up when the shell closes the database connection */
233 if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
234 sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
235 db_protect_only(PROTECT_NONE);
236 sqlite3_set_authorizer(db, db_top_authorizer, db);
237 sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
238 sqlcmd_db_protect, 0, 0);
239 sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
240 sqlcmd_db_protect_pop, 0, 0);
 
 
241 return SQLITE_OK;
242 }
243
244 /*
245 ** atexit() handler that cleans up global state modified by this module.
@@ -329,10 +349,13 @@
329 ** --readonly Open the repository read-only. No changes
330 ** are allowed. This is a recommended safety
331 ** precaution to prevent repository damage.
332 **
333 ** -R REPOSITORY Use REPOSITORY as the repository database
 
 
 
334 **
335 ** All of the standard sqlite3 command-line shell options should also
336 ** work.
337 **
338 ** The following SQL extensions are provided with this Fossil-enhanced
@@ -397,10 +420,11 @@
397 extern int sqlite3_shell(int, char**);
398 #ifdef FOSSIL_ENABLE_TH1_HOOKS
399 g.fNoThHook = 1;
400 #endif
401 noRepository = find_option("no-repository", 0, 0)!=0;
 
402 if( !noRepository ){
403 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
404 }
405 db_open_config(1,0);
406 zConfigDb = fossil_strdup(g.zConfigDbName);
407
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -32,10 +32,15 @@
32
33 #ifndef _WIN32
34 # include "linenoise.h"
35 #endif
36
37 /*
38 ** True if the "fossil sql" command has the --test flag. False otherwise.
39 */
40 static int local_bSqlCmdTest = 0;
41
42 /*
43 ** Implementation of the "content(X)" SQL function. Return the complete
44 ** content of artifact identified by X as a blob.
45 */
46 static void sqlcmd_content(
@@ -163,33 +168,46 @@
168 ** Undocumented test SQL functions:
169 **
170 ** db_protect(X)
171 ** db_protect_pop(X)
172 **
173 ** These invoke the corresponding C routines.
174 **
175 ** WARNING:
176 ** Do not instantiate these functions for any Fossil webpage or command
177 ** method of than the "fossil sql" command. If an attacker gains access
178 ** to these functions, he will be able to disable other defense mechanisms.
179 **
180 ** This routines are for interactiving testing only. They are experimental
181 ** and undocumented (apart from this comments) and might go away or change
182 ** in future releases.
183 **
184 ** 2020-11-29: This functions are now only available if the "fossil sql"
185 ** command is started with the --test option.
186 */
187 static void sqlcmd_db_protect(
188 sqlite3_context *context,
189 int argc,
190 sqlite3_value **argv
191 ){
192 unsigned mask = 0;
193 const char *z = (const char*)sqlite3_value_text(argv[0]);
194 if( z!=0 && local_bSqlCmdTest ){
195 if( sqlite3_stricmp(z,"user")==0 ) mask |= PROTECT_USER;
196 if( sqlite3_stricmp(z,"config")==0 ) mask |= PROTECT_CONFIG;
197 if( sqlite3_stricmp(z,"sensitive")==0 ) mask |= PROTECT_SENSITIVE;
198 if( sqlite3_stricmp(z,"readonly")==0 ) mask |= PROTECT_READONLY;
199 if( sqlite3_stricmp(z,"all")==0 ) mask |= PROTECT_ALL;
200 db_protect(mask);
201 }
202 }
203 static void sqlcmd_db_protect_pop(
204 sqlite3_context *context,
205 int argc,
206 sqlite3_value **argv
207 ){
208 if( !local_bSqlCmdTest ) db_protect_pop();
209 }
210
211
212
213
@@ -232,14 +250,16 @@
250 ** will get cleaned up when the shell closes the database connection */
251 if( g.fSqlTrace ) mTrace |= SQLITE_TRACE_PROFILE;
252 sqlite3_trace_v2(db, mTrace, db_sql_trace, 0);
253 db_protect_only(PROTECT_NONE);
254 sqlite3_set_authorizer(db, db_top_authorizer, db);
255 if( local_bSqlCmdTest ){
256 sqlite3_create_function(db, "db_protect", 1, SQLITE_UTF8, 0,
257 sqlcmd_db_protect, 0, 0);
258 sqlite3_create_function(db, "db_protect_pop", 0, SQLITE_UTF8, 0,
259 sqlcmd_db_protect_pop, 0, 0);
260 }
261 return SQLITE_OK;
262 }
263
264 /*
265 ** atexit() handler that cleans up global state modified by this module.
@@ -329,10 +349,13 @@
349 ** --readonly Open the repository read-only. No changes
350 ** are allowed. This is a recommended safety
351 ** precaution to prevent repository damage.
352 **
353 ** -R REPOSITORY Use REPOSITORY as the repository database
354 **
355 ** --test Enable some testing and analysis features
356 ** that are normally disabled.
357 **
358 ** All of the standard sqlite3 command-line shell options should also
359 ** work.
360 **
361 ** The following SQL extensions are provided with this Fossil-enhanced
@@ -397,10 +420,11 @@
420 extern int sqlite3_shell(int, char**);
421 #ifdef FOSSIL_ENABLE_TH1_HOOKS
422 g.fNoThHook = 1;
423 #endif
424 noRepository = find_option("no-repository", 0, 0)!=0;
425 local_bSqlCmdTest = find_option("test",0,0)!=0;
426 if( !noRepository ){
427 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
428 }
429 db_open_config(1,0);
430 zConfigDb = fossil_strdup(g.zConfigDbName);
431

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button