Fossil SCM

Every database connection now has a default authorizer, which calls out to an operation-specific authorizer if needed.

drh 2020-08-17 19:59 sec2020
Commit f98ef3c1034e1d8d5174c4d8d11448586a049a2ef3eacbf8a3b2701d28ce6ab3
2 files changed +46 -5 +1 -2
+46 -5
--- src/db.c
+++ src/db.c
@@ -134,10 +134,13 @@
134134
const char *zStartFile; /* File in which transaction was started */
135135
int iStartLine; /* Line of zStartFile where transaction started */
136136
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
137137
void *pAuthArg; /* Argument to the authorizer */
138138
const char *zAuthName; /* Name of the authorizer */
139
+ char protectUser; /* Prevent changes to the USER table */
140
+ char protectSensitive; /* Prevent changes to sensitive CONFIG entries */
141
+ char protectConfig; /* Prevent any changes to the CONFIG table */
139142
} db = {0, 0, 0, 0, 0, 0, };
140143
141144
/*
142145
** Arrange for the given file to be deleted on a failure.
143146
*/
@@ -320,10 +323,51 @@
320323
}
321324
db.aHook[db.nCommitHook].sequence = sequence;
322325
db.aHook[db.nCommitHook].xHook = x;
323326
db.nCommitHook++;
324327
}
328
+
329
+/*
330
+** Every Fossil database connection automatically registers the following
331
+** overarching authenticator callback, and leaves it registered for the
332
+** duration of the connection. This authenticator will call any
333
+** sub-authenticators that are registered using db_set_authorizer().
334
+*/
335
+static int db_top_authorizer(
336
+ void *pNotUsed,
337
+ int eCode,
338
+ const char *z0,
339
+ const char *z1,
340
+ const char *z2,
341
+ const char *z3
342
+){
343
+ int rc = SQLITE_OK;
344
+ switch( eCode ){
345
+ case SQLITE_INSERT:
346
+ case SQLITE_UPDATE:
347
+ case SQLITE_DELETE: {
348
+ if( db.protectUser && sqlite3_stricmp(z0,"user")==0 ){
349
+ rc = SQLITE_DENY;
350
+ }else if( db.protectConfig &&
351
+ (sqlite3_stricmp(z0,"config")==0 ||
352
+ sqlite3_stricmp(z0,"global_config")==0) ){
353
+ rc = SQLITE_DENY;
354
+ }
355
+ break;
356
+ }
357
+ case SQLITE_DROP_TEMP_TRIGGER: {
358
+ if( db.protectSensitive ){
359
+ rc = SQLITE_DENY;
360
+ }
361
+ break;
362
+ }
363
+ }
364
+ if( db.xAuth && rc==SQLITE_OK ){
365
+ rc = db.xAuth(db.pAuthArg, eCode, z0, z1, z2, z3);
366
+ }
367
+ return rc;
368
+}
325369
326370
/*
327371
** Set or unset the query authorizer callback function
328372
*/
329373
void db_set_authorizer(
@@ -332,23 +376,22 @@
332376
const char *zName /* for tracing */
333377
){
334378
if( db.xAuth ){
335379
fossil_panic("multiple active db_set_authorizer() calls");
336380
}
337
- if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
338381
db.xAuth = xAuth;
339382
db.pAuthArg = pArg;
340383
db.zAuthName = zName;
341384
if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
342385
}
343386
void db_clear_authorizer(void){
344387
if( db.zAuthName && g.fSqlTrace ){
345388
fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
346389
}
347
- if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
348390
db.xAuth = 0;
349391
db.pAuthArg = 0;
392
+ db.zAuthName = 0;
350393
}
351394
352395
#if INTERFACE
353396
/*
354397
** Possible flags to db_vprepare
@@ -902,13 +945,10 @@
902945
const char *zSql;
903946
va_list ap;
904947
905948
xdb = db_open(zFileName ? zFileName : ":memory:");
906949
sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
907
- if( db.xAuth ){
908
- sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
909
- }
910950
rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
911951
if( rc!=SQLITE_OK ){
912952
db_err("%s", sqlite3_errmsg(xdb));
913953
}
914954
va_start(ap, zSchema);
@@ -1402,10 +1442,11 @@
14021442
if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, db_sql_trace, 0);
14031443
db_add_aux_functions(db);
14041444
re_add_sql_func(db); /* The REGEXP operator */
14051445
foci_register(db); /* The "files_of_checkin" virtual table */
14061446
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 0, &rc);
1447
+ sqlite3_set_authorizer(db, db_top_authorizer, db);
14071448
return db;
14081449
}
14091450
14101451
14111452
/*
14121453
--- src/db.c
+++ src/db.c
@@ -134,10 +134,13 @@
134 const char *zStartFile; /* File in which transaction was started */
135 int iStartLine; /* Line of zStartFile where transaction started */
136 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
137 void *pAuthArg; /* Argument to the authorizer */
138 const char *zAuthName; /* Name of the authorizer */
 
 
 
139 } db = {0, 0, 0, 0, 0, 0, };
140
141 /*
142 ** Arrange for the given file to be deleted on a failure.
143 */
@@ -320,10 +323,51 @@
320 }
321 db.aHook[db.nCommitHook].sequence = sequence;
322 db.aHook[db.nCommitHook].xHook = x;
323 db.nCommitHook++;
324 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
326 /*
327 ** Set or unset the query authorizer callback function
328 */
329 void db_set_authorizer(
@@ -332,23 +376,22 @@
332 const char *zName /* for tracing */
333 ){
334 if( db.xAuth ){
335 fossil_panic("multiple active db_set_authorizer() calls");
336 }
337 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
338 db.xAuth = xAuth;
339 db.pAuthArg = pArg;
340 db.zAuthName = zName;
341 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
342 }
343 void db_clear_authorizer(void){
344 if( db.zAuthName && g.fSqlTrace ){
345 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
346 }
347 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
348 db.xAuth = 0;
349 db.pAuthArg = 0;
 
350 }
351
352 #if INTERFACE
353 /*
354 ** Possible flags to db_vprepare
@@ -902,13 +945,10 @@
902 const char *zSql;
903 va_list ap;
904
905 xdb = db_open(zFileName ? zFileName : ":memory:");
906 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
907 if( db.xAuth ){
908 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
909 }
910 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
911 if( rc!=SQLITE_OK ){
912 db_err("%s", sqlite3_errmsg(xdb));
913 }
914 va_start(ap, zSchema);
@@ -1402,10 +1442,11 @@
1402 if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, db_sql_trace, 0);
1403 db_add_aux_functions(db);
1404 re_add_sql_func(db); /* The REGEXP operator */
1405 foci_register(db); /* The "files_of_checkin" virtual table */
1406 sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 0, &rc);
 
1407 return db;
1408 }
1409
1410
1411 /*
1412
--- src/db.c
+++ src/db.c
@@ -134,10 +134,13 @@
134 const char *zStartFile; /* File in which transaction was started */
135 int iStartLine; /* Line of zStartFile where transaction started */
136 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
137 void *pAuthArg; /* Argument to the authorizer */
138 const char *zAuthName; /* Name of the authorizer */
139 char protectUser; /* Prevent changes to the USER table */
140 char protectSensitive; /* Prevent changes to sensitive CONFIG entries */
141 char protectConfig; /* Prevent any changes to the CONFIG table */
142 } db = {0, 0, 0, 0, 0, 0, };
143
144 /*
145 ** Arrange for the given file to be deleted on a failure.
146 */
@@ -320,10 +323,51 @@
323 }
324 db.aHook[db.nCommitHook].sequence = sequence;
325 db.aHook[db.nCommitHook].xHook = x;
326 db.nCommitHook++;
327 }
328
329 /*
330 ** Every Fossil database connection automatically registers the following
331 ** overarching authenticator callback, and leaves it registered for the
332 ** duration of the connection. This authenticator will call any
333 ** sub-authenticators that are registered using db_set_authorizer().
334 */
335 static int db_top_authorizer(
336 void *pNotUsed,
337 int eCode,
338 const char *z0,
339 const char *z1,
340 const char *z2,
341 const char *z3
342 ){
343 int rc = SQLITE_OK;
344 switch( eCode ){
345 case SQLITE_INSERT:
346 case SQLITE_UPDATE:
347 case SQLITE_DELETE: {
348 if( db.protectUser && sqlite3_stricmp(z0,"user")==0 ){
349 rc = SQLITE_DENY;
350 }else if( db.protectConfig &&
351 (sqlite3_stricmp(z0,"config")==0 ||
352 sqlite3_stricmp(z0,"global_config")==0) ){
353 rc = SQLITE_DENY;
354 }
355 break;
356 }
357 case SQLITE_DROP_TEMP_TRIGGER: {
358 if( db.protectSensitive ){
359 rc = SQLITE_DENY;
360 }
361 break;
362 }
363 }
364 if( db.xAuth && rc==SQLITE_OK ){
365 rc = db.xAuth(db.pAuthArg, eCode, z0, z1, z2, z3);
366 }
367 return rc;
368 }
369
370 /*
371 ** Set or unset the query authorizer callback function
372 */
373 void db_set_authorizer(
@@ -332,23 +376,22 @@
376 const char *zName /* for tracing */
377 ){
378 if( db.xAuth ){
379 fossil_panic("multiple active db_set_authorizer() calls");
380 }
 
381 db.xAuth = xAuth;
382 db.pAuthArg = pArg;
383 db.zAuthName = zName;
384 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
385 }
386 void db_clear_authorizer(void){
387 if( db.zAuthName && g.fSqlTrace ){
388 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
389 }
 
390 db.xAuth = 0;
391 db.pAuthArg = 0;
392 db.zAuthName = 0;
393 }
394
395 #if INTERFACE
396 /*
397 ** Possible flags to db_vprepare
@@ -902,13 +945,10 @@
945 const char *zSql;
946 va_list ap;
947
948 xdb = db_open(zFileName ? zFileName : ":memory:");
949 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
 
 
 
950 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
951 if( rc!=SQLITE_OK ){
952 db_err("%s", sqlite3_errmsg(xdb));
953 }
954 va_start(ap, zSchema);
@@ -1402,10 +1442,11 @@
1442 if( g.fSqlTrace ) sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, db_sql_trace, 0);
1443 db_add_aux_functions(db);
1444 re_add_sql_func(db); /* The REGEXP operator */
1445 foci_register(db); /* The "files_of_checkin" virtual table */
1446 sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, 0, &rc);
1447 sqlite3_set_authorizer(db, db_top_authorizer, db);
1448 return db;
1449 }
1450
1451
1452 /*
1453
+1 -2
--- src/tkt.c
+++ src/tkt.c
@@ -451,16 +451,15 @@
451451
db_multi_exec(
452452
"DROP TABLE IF EXISTS ticket;"
453453
"DROP TABLE IF EXISTS ticketchng;"
454454
);
455455
zSql = ticket_table_schema();
456
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
456457
if( separateConnection ){
457458
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
- db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459459
db_init_database(g.zRepositoryName, zSql, 0);
460460
}else{
461
- db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462461
db_multi_exec("%s", zSql/*safe-for-%s*/);
463462
}
464463
db_clear_authorizer();
465464
fossil_free(zSql);
466465
}
467466
--- src/tkt.c
+++ src/tkt.c
@@ -451,16 +451,15 @@
451 db_multi_exec(
452 "DROP TABLE IF EXISTS ticket;"
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
 
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
--- src/tkt.c
+++ src/tkt.c
@@ -451,16 +451,15 @@
451 db_multi_exec(
452 "DROP TABLE IF EXISTS ticket;"
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
457 if( separateConnection ){
458 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
 
461 db_multi_exec("%s", zSql/*safe-for-%s*/);
462 }
463 db_clear_authorizer();
464 fossil_free(zSql);
465 }
466

Keyboard Shortcuts

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