Fossil SCM

Disable writes the CONFIG and USER tables by default. Permission to write to those tables is turned on as needed. Note - might have missed a few places so expect bugs.

drh 2020-08-18 01:54 sec2020
Commit ca9156aa0adb36839383491c609de61e8d6889494826a48e69efa35a4a6f98c5
--- src/alerts.c
+++ src/alerts.c
@@ -1769,18 +1769,20 @@
17691769
"UPDATE subscriber SET sverified=1"
17701770
" WHERE subscriberCode=hextoblob(%Q)",
17711771
zName);
17721772
if( db_get_boolean("selfreg-verify",0) ){
17731773
char *zNewCap = db_get("default-perms","u");
1774
+ db_unprotect(PROTECT_USER);
17741775
db_multi_exec(
17751776
"UPDATE user"
17761777
" SET cap=%Q"
17771778
" WHERE cap='7' AND login=("
17781779
" SELECT suname FROM subscriber"
17791780
" WHERE subscriberCode=hextoblob(%Q))",
17801781
zNewCap, zName
17811782
);
1783
+ db_protect_pop();
17821784
login_set_capabilities(zNewCap, 0);
17831785
}
17841786
@ <h1>Your email alert subscription has been verified!</h1>
17851787
@ <p>Use the form below to update your subscription information.</p>
17861788
@ <p>Hint: Bookmark this page so that you can more easily update
17871789
--- src/alerts.c
+++ src/alerts.c
@@ -1769,18 +1769,20 @@
1769 "UPDATE subscriber SET sverified=1"
1770 " WHERE subscriberCode=hextoblob(%Q)",
1771 zName);
1772 if( db_get_boolean("selfreg-verify",0) ){
1773 char *zNewCap = db_get("default-perms","u");
 
1774 db_multi_exec(
1775 "UPDATE user"
1776 " SET cap=%Q"
1777 " WHERE cap='7' AND login=("
1778 " SELECT suname FROM subscriber"
1779 " WHERE subscriberCode=hextoblob(%Q))",
1780 zNewCap, zName
1781 );
 
1782 login_set_capabilities(zNewCap, 0);
1783 }
1784 @ <h1>Your email alert subscription has been verified!</h1>
1785 @ <p>Use the form below to update your subscription information.</p>
1786 @ <p>Hint: Bookmark this page so that you can more easily update
1787
--- src/alerts.c
+++ src/alerts.c
@@ -1769,18 +1769,20 @@
1769 "UPDATE subscriber SET sverified=1"
1770 " WHERE subscriberCode=hextoblob(%Q)",
1771 zName);
1772 if( db_get_boolean("selfreg-verify",0) ){
1773 char *zNewCap = db_get("default-perms","u");
1774 db_unprotect(PROTECT_USER);
1775 db_multi_exec(
1776 "UPDATE user"
1777 " SET cap=%Q"
1778 " WHERE cap='7' AND login=("
1779 " SELECT suname FROM subscriber"
1780 " WHERE subscriberCode=hextoblob(%Q))",
1781 zNewCap, zName
1782 );
1783 db_protect_pop();
1784 login_set_capabilities(zNewCap, 0);
1785 }
1786 @ <h1>Your email alert subscription has been verified!</h1>
1787 @ <p>Use the form below to update your subscription information.</p>
1788 @ <p>Hint: Bookmark this page so that you can more easily update
1789
--- src/allrepo.c
+++ src/allrepo.c
@@ -334,11 +334,13 @@
334334
"VALUES('repo:%q',1)", z
335335
);
336336
if( dryRunFlag ){
337337
fossil_print("%s\n", blob_sql_text(&sql));
338338
}else{
339
+ db_unprotect(PROTECT_CONFIG);
339340
db_multi_exec("%s", blob_sql_text(&sql));
341
+ db_protect_pop();
340342
}
341343
}
342344
db_end_transaction(0);
343345
blob_reset(&sql);
344346
blob_reset(&fn);
345347
--- src/allrepo.c
+++ src/allrepo.c
@@ -334,11 +334,13 @@
334 "VALUES('repo:%q',1)", z
335 );
336 if( dryRunFlag ){
337 fossil_print("%s\n", blob_sql_text(&sql));
338 }else{
 
339 db_multi_exec("%s", blob_sql_text(&sql));
 
340 }
341 }
342 db_end_transaction(0);
343 blob_reset(&sql);
344 blob_reset(&fn);
345
--- src/allrepo.c
+++ src/allrepo.c
@@ -334,11 +334,13 @@
334 "VALUES('repo:%q',1)", z
335 );
336 if( dryRunFlag ){
337 fossil_print("%s\n", blob_sql_text(&sql));
338 }else{
339 db_unprotect(PROTECT_CONFIG);
340 db_multi_exec("%s", blob_sql_text(&sql));
341 db_protect_pop();
342 }
343 }
344 db_end_transaction(0);
345 blob_reset(&sql);
346 blob_reset(&fn);
347
--- src/captcha.c
+++ src/captcha.c
@@ -458,14 +458,16 @@
458458
Blob b;
459459
static char zRes[20];
460460
461461
zSecret = db_get("captcha-secret", 0);
462462
if( zSecret==0 ){
463
+ db_unprotect(PROTECT_CONFIG);
463464
db_multi_exec(
464465
"REPLACE INTO config(name,value)"
465466
" VALUES('captcha-secret', lower(hex(randomblob(20))));"
466467
);
468
+ db_protect_pop();
467469
zSecret = db_get("captcha-secret", 0);
468470
assert( zSecret!=0 );
469471
}
470472
blob_init(&b, 0, 0);
471473
blob_appendf(&b, "%s-%x", zSecret, seed);
472474
--- src/captcha.c
+++ src/captcha.c
@@ -458,14 +458,16 @@
458 Blob b;
459 static char zRes[20];
460
461 zSecret = db_get("captcha-secret", 0);
462 if( zSecret==0 ){
 
463 db_multi_exec(
464 "REPLACE INTO config(name,value)"
465 " VALUES('captcha-secret', lower(hex(randomblob(20))));"
466 );
 
467 zSecret = db_get("captcha-secret", 0);
468 assert( zSecret!=0 );
469 }
470 blob_init(&b, 0, 0);
471 blob_appendf(&b, "%s-%x", zSecret, seed);
472
--- src/captcha.c
+++ src/captcha.c
@@ -458,14 +458,16 @@
458 Blob b;
459 static char zRes[20];
460
461 zSecret = db_get("captcha-secret", 0);
462 if( zSecret==0 ){
463 db_unprotect(PROTECT_CONFIG);
464 db_multi_exec(
465 "REPLACE INTO config(name,value)"
466 " VALUES('captcha-secret', lower(hex(randomblob(20))));"
467 );
468 db_protect_pop();
469 zSecret = db_get("captcha-secret", 0);
470 assert( zSecret!=0 );
471 }
472 blob_init(&b, 0, 0);
473 blob_appendf(&b, "%s-%x", zSecret, seed);
474
--- src/clone.c
+++ src/clone.c
@@ -202,15 +202,17 @@
202202
blob_zero(&fn);
203203
file_canonical_name(g.zSSLIdentity, &fn, 0);
204204
db_set("ssl-identity", blob_str(&fn), 0);
205205
blob_reset(&fn);
206206
}
207
+ db_unprotect(PROTECT_CONFIG);
207208
db_multi_exec(
208209
"REPLACE INTO config(name,value,mtime)"
209210
" VALUES('server-code', lower(hex(randomblob(20))), now());"
210211
"DELETE FROM config WHERE name='project-code';"
211212
);
213
+ db_protect_pop();
212214
url_enable_proxy(0);
213215
clone_ssh_db_set_options();
214216
url_get_password_if_needed();
215217
g.xlinkClusterOnly = 1;
216218
nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0);
217219
--- src/clone.c
+++ src/clone.c
@@ -202,15 +202,17 @@
202 blob_zero(&fn);
203 file_canonical_name(g.zSSLIdentity, &fn, 0);
204 db_set("ssl-identity", blob_str(&fn), 0);
205 blob_reset(&fn);
206 }
 
207 db_multi_exec(
208 "REPLACE INTO config(name,value,mtime)"
209 " VALUES('server-code', lower(hex(randomblob(20))), now());"
210 "DELETE FROM config WHERE name='project-code';"
211 );
 
212 url_enable_proxy(0);
213 clone_ssh_db_set_options();
214 url_get_password_if_needed();
215 g.xlinkClusterOnly = 1;
216 nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0);
217
--- src/clone.c
+++ src/clone.c
@@ -202,15 +202,17 @@
202 blob_zero(&fn);
203 file_canonical_name(g.zSSLIdentity, &fn, 0);
204 db_set("ssl-identity", blob_str(&fn), 0);
205 blob_reset(&fn);
206 }
207 db_unprotect(PROTECT_CONFIG);
208 db_multi_exec(
209 "REPLACE INTO config(name,value,mtime)"
210 " VALUES('server-code', lower(hex(randomblob(20))), now());"
211 "DELETE FROM config WHERE name='project-code';"
212 );
213 db_protect_pop();
214 url_enable_proxy(0);
215 clone_ssh_db_set_options();
216 url_get_password_if_needed();
217 g.xlinkClusterOnly = 1;
218 nErr = client_sync(syncFlags,CONFIGSET_ALL,0,0);
219
--- src/configure.c
+++ src/configure.c
@@ -836,13 +836,17 @@
836836
export_config(mask, g.argv[3], 0, zBackup);
837837
for(i=0; i<count(aConfig); i++){
838838
const char *zName = aConfig[i].zName;
839839
if( (aConfig[i].groupMask & mask)==0 ) continue;
840840
if( zName[0]!='@' ){
841
+ db_unprotect(PROTECT_CONFIG);
841842
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
843
+ db_protect_pop();
842844
}else if( fossil_strcmp(zName,"@user")==0 ){
845
+ db_unprotect(PROTECT_USER);
843846
db_multi_exec("DELETE FROM user");
847
+ db_protect_pop();
844848
db_create_default_users(0, 0);
845849
}else if( fossil_strcmp(zName,"@concealed")==0 ){
846850
db_multi_exec("DELETE FROM concealed");
847851
}else if( fossil_strcmp(zName,"@shun")==0 ){
848852
db_multi_exec("DELETE FROM shun");
@@ -1050,10 +1054,11 @@
10501054
}else if( zBlob ){
10511055
blob_read_from_file(&x, zBlob, ExtFILE);
10521056
}else{
10531057
blob_init(&x,g.argv[3],-1);
10541058
}
1059
+ db_unprotect(PROTECT_CONFIG);
10551060
db_prepare(&ins,
10561061
"REPLACE INTO config(name,value,mtime)"
10571062
"VALUES(%Q,:val,now())", zVar);
10581063
if( zBlob ){
10591064
db_bind_blob(&ins, ":val", &x);
@@ -1060,7 +1065,8 @@
10601065
}else{
10611066
db_bind_text(&ins, ":val", blob_str(&x));
10621067
}
10631068
db_step(&ins);
10641069
db_finalize(&ins);
1070
+ db_protect_pop();
10651071
blob_reset(&x);
10661072
}
10671073
--- src/configure.c
+++ src/configure.c
@@ -836,13 +836,17 @@
836 export_config(mask, g.argv[3], 0, zBackup);
837 for(i=0; i<count(aConfig); i++){
838 const char *zName = aConfig[i].zName;
839 if( (aConfig[i].groupMask & mask)==0 ) continue;
840 if( zName[0]!='@' ){
 
841 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
 
842 }else if( fossil_strcmp(zName,"@user")==0 ){
 
843 db_multi_exec("DELETE FROM user");
 
844 db_create_default_users(0, 0);
845 }else if( fossil_strcmp(zName,"@concealed")==0 ){
846 db_multi_exec("DELETE FROM concealed");
847 }else if( fossil_strcmp(zName,"@shun")==0 ){
848 db_multi_exec("DELETE FROM shun");
@@ -1050,10 +1054,11 @@
1050 }else if( zBlob ){
1051 blob_read_from_file(&x, zBlob, ExtFILE);
1052 }else{
1053 blob_init(&x,g.argv[3],-1);
1054 }
 
1055 db_prepare(&ins,
1056 "REPLACE INTO config(name,value,mtime)"
1057 "VALUES(%Q,:val,now())", zVar);
1058 if( zBlob ){
1059 db_bind_blob(&ins, ":val", &x);
@@ -1060,7 +1065,8 @@
1060 }else{
1061 db_bind_text(&ins, ":val", blob_str(&x));
1062 }
1063 db_step(&ins);
1064 db_finalize(&ins);
 
1065 blob_reset(&x);
1066 }
1067
--- src/configure.c
+++ src/configure.c
@@ -836,13 +836,17 @@
836 export_config(mask, g.argv[3], 0, zBackup);
837 for(i=0; i<count(aConfig); i++){
838 const char *zName = aConfig[i].zName;
839 if( (aConfig[i].groupMask & mask)==0 ) continue;
840 if( zName[0]!='@' ){
841 db_unprotect(PROTECT_CONFIG);
842 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
843 db_protect_pop();
844 }else if( fossil_strcmp(zName,"@user")==0 ){
845 db_unprotect(PROTECT_USER);
846 db_multi_exec("DELETE FROM user");
847 db_protect_pop();
848 db_create_default_users(0, 0);
849 }else if( fossil_strcmp(zName,"@concealed")==0 ){
850 db_multi_exec("DELETE FROM concealed");
851 }else if( fossil_strcmp(zName,"@shun")==0 ){
852 db_multi_exec("DELETE FROM shun");
@@ -1050,10 +1054,11 @@
1054 }else if( zBlob ){
1055 blob_read_from_file(&x, zBlob, ExtFILE);
1056 }else{
1057 blob_init(&x,g.argv[3],-1);
1058 }
1059 db_unprotect(PROTECT_CONFIG);
1060 db_prepare(&ins,
1061 "REPLACE INTO config(name,value,mtime)"
1062 "VALUES(%Q,:val,now())", zVar);
1063 if( zBlob ){
1064 db_bind_blob(&ins, ":val", &x);
@@ -1060,7 +1065,8 @@
1065 }else{
1066 db_bind_text(&ins, ":val", blob_str(&x));
1067 }
1068 db_step(&ins);
1069 db_finalize(&ins);
1070 db_protect_pop();
1071 blob_reset(&x);
1072 }
1073
+101 -11
--- src/db.c
+++ src/db.c
@@ -114,10 +114,11 @@
114114
/*
115115
** All static variable that a used by only this file are gathered into
116116
** the following structure.
117117
*/
118118
static struct DbLocalData {
119
+ unsigned protectMask; /* Prevent changes to database */
119120
int nBegin; /* Nesting depth of BEGIN */
120121
int doRollback; /* True to force a rollback */
121122
int nCommitHook; /* Number of commit hooks */
122123
int wrTxn; /* Outer-most TNX is a write */
123124
Stmt *pAllStmt; /* List of all unfinalized statements */
@@ -134,14 +135,15 @@
134135
const char *zStartFile; /* File in which transaction was started */
135136
int iStartLine; /* Line of zStartFile where transaction started */
136137
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
137138
void *pAuthArg; /* Argument to the authorizer */
138139
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, };
140
+ int nProtect; /* Slots of aProtect used */
141
+ unsigned aProtect[10]; /* Saved values of protectMask */
142
+} db = {
143
+ PROTECT_USER|PROTECT_CONFIG, /* protectMask */
144
+ 0, 0, 0, 0, 0, 0, };
143145
144146
/*
145147
** Arrange for the given file to be deleted on a failure.
146148
*/
147149
void db_delete_on_failure(const char *zFilename){
@@ -323,10 +325,53 @@
323325
}
324326
db.aHook[db.nCommitHook].sequence = sequence;
325327
db.aHook[db.nCommitHook].xHook = x;
326328
db.nCommitHook++;
327329
}
330
+
331
+#if INTERFACE
332
+/*
333
+** Flag bits for db_protect() and db_unprotect()
334
+*/
335
+#define PROTECT_USER 0x01
336
+#define PROTECT_CONFIG 0x02
337
+#define PROTECT_SENSITIVE 0x04
338
+#define PROTECT_READONLY 0x08
339
+#define PROTECT_ALL 0x0f /* All of the above */
340
+#endif /* INTERFACE */
341
+
342
+/*
343
+** Enable or disable database write protections.
344
+** Use db_protect() to enable write permissions. Use
345
+** db_unprotect() to disable them.
346
+**
347
+** Each call to db_protect() and/or db_unprotect() should be followed
348
+** by a corresponding call to db_protect_pop(). The db_protect_pop()
349
+** call restores the protection settings to what they were before.
350
+**
351
+** The stack of protection settings is finite, so do not nest calls
352
+** to db_protect()/db_unprotect() too deeply. And make sure calls
353
+** to db_protect()/db_unprotect() are balanced.
354
+*/
355
+void db_protect(unsigned flags){
356
+ if( db.nProtect>=count(db.aProtect) ){
357
+ fossil_fatal("too many db_protect() calls");
358
+ }
359
+ db.aProtect[db.nProtect++] = db.protectMask;
360
+ db.protectMask |= flags;
361
+}
362
+void db_unprotect(unsigned flags){
363
+ if( db.nProtect>=count(db.aProtect) ){
364
+ fossil_fatal("too many db_unprotect() calls");
365
+ }
366
+ db.aProtect[db.nProtect++] = db.protectMask;
367
+ db.protectMask &= ~flags;
368
+}
369
+void db_protect_pop(void){
370
+ if( db.nProtect<1 ) fossil_fatal("too many db_protect_pop() calls");
371
+ db.protectMask = db.aProtect[--db.nProtect];
372
+}
328373
329374
/*
330375
** Every Fossil database connection automatically registers the following
331376
** overarching authenticator callback, and leaves it registered for the
332377
** duration of the connection. This authenticator will call any
@@ -343,23 +388,25 @@
343388
int rc = SQLITE_OK;
344389
switch( eCode ){
345390
case SQLITE_INSERT:
346391
case SQLITE_UPDATE:
347392
case SQLITE_DELETE: {
348
- if( db.protectUser && sqlite3_stricmp(z0,"user")==0 ){
393
+ if( (db.protectMask & PROTECT_USER)!=0
394
+ && sqlite3_stricmp(z0,"user")==0 ){
349395
rc = SQLITE_DENY;
350
- }else if( db.protectConfig &&
396
+ }else if( (db.protectMask & PROTECT_CONFIG)!=0 &&
351397
(sqlite3_stricmp(z0,"config")==0 ||
352398
sqlite3_stricmp(z0,"global_config")==0) ){
399
+ rc = SQLITE_DENY;
400
+ }else if( (db.protectMask & PROTECT_READONLY)!=0
401
+ && sqlite3_stricmp(z2,"temp")!=0 ){
353402
rc = SQLITE_DENY;
354403
}
355404
break;
356405
}
357406
case SQLITE_DROP_TEMP_TRIGGER: {
358
- if( db.protectSensitive ){
359
- rc = SQLITE_DENY;
360
- }
407
+ rc = SQLITE_DENY;
361408
break;
362409
}
363410
}
364411
if( db.xAuth && rc==SQLITE_OK ){
365412
rc = db.xAuth(db.pAuthArg, eCode, z0, z1, z2, z3);
@@ -1154,10 +1201,35 @@
11541201
}
11551202
strcpy(zOut, zTemp = obscure((char*)zIn));
11561203
fossil_free(zTemp);
11571204
sqlite3_result_text(context, zOut, strlen(zOut), sqlite3_free);
11581205
}
1206
+
1207
+/*
1208
+** Implement the protected_setting(X) SQL function. This function returns
1209
+** true if X is the name of a protected (security-sensitive) setting and
1210
+** the db.protectSensitive flag is enabled. It returns false otherwise.
1211
+*/
1212
+LOCAL void db_protected_setting(
1213
+ sqlite3_context *context,
1214
+ int argc,
1215
+ sqlite3_value **argv
1216
+){
1217
+ const char *zSetting;
1218
+ const Setting *pSetting;
1219
+ if( (db.protectMask & PROTECT_SENSITIVE)==0 ){
1220
+ sqlite3_result_int(context, 0);
1221
+ return;
1222
+ }
1223
+ zSetting = (const char*)sqlite3_value_text(argv[0]);
1224
+ pSetting = zSetting ? db_find_setting(zSetting,0) : 0;
1225
+ if( pSetting && pSetting->sensitive ){
1226
+ sqlite3_result_int(context, 1);
1227
+ }else{
1228
+ sqlite3_result_int(context, 0);
1229
+ }
1230
+}
11591231
11601232
/*
11611233
** Register the SQL functions that are useful both to the internal
11621234
** representation and to the "fossil sql" command.
11631235
*/
@@ -1184,10 +1256,12 @@
11841256
alert_find_emailaddr_func, 0, 0);
11851257
sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
11861258
alert_display_name_func, 0, 0);
11871259
sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
11881260
db_obscure, 0, 0);
1261
+ sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
1262
+ db_protected_setting, 0, 0);
11891263
}
11901264
11911265
#if USE_SEE
11921266
/*
11931267
** This is a pointer to the saved database encryption key string.
@@ -2304,10 +2378,11 @@
23042378
zUser = fossil_getenv("USERNAME");
23052379
}
23062380
if( zUser==0 ){
23072381
zUser = "root";
23082382
}
2383
+ db_unprotect(PROTECT_USER);
23092384
db_multi_exec(
23102385
"INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
23112386
);
23122387
db_multi_exec(
23132388
"UPDATE user SET cap='s', pw=%Q"
@@ -2323,10 +2398,11 @@
23232398
" VALUES('developer','','ei','Dev');"
23242399
"INSERT OR IGNORE INTO user(login,pw,cap,info)"
23252400
" VALUES('reader','','kptw','Reader');"
23262401
);
23272402
}
2403
+ db_protect_pop();
23282404
}
23292405
23302406
/*
23312407
** Return a pointer to a string that contains the RHS of an IN operator
23322408
** that will select CONFIG table names that are in the list of control
@@ -2374,10 +2450,11 @@
23742450
){
23752451
char *zDate;
23762452
Blob hash;
23772453
Blob manifest;
23782454
2455
+ db_unprotect(PROTECT_ALL);
23792456
db_set("content-schema", CONTENT_SCHEMA, 0);
23802457
db_set("aux-schema", AUX_SCHEMA_MAX, 0);
23812458
db_set("rebuilt", get_version(), 0);
23822459
db_set("admin-log", "1", 0);
23832460
db_set("access-log", "1", 0);
@@ -2432,10 +2509,11 @@
24322509
" photo = (SELECT u2.photo FROM settingSrc.user u2"
24332510
" WHERE u2.login = user.login)"
24342511
" WHERE user.login IN ('anonymous','nobody','developer','reader');"
24352512
);
24362513
}
2514
+ db_protect_pop();
24372515
24382516
if( zInitialDate ){
24392517
int rid;
24402518
blob_zero(&manifest);
24412519
blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
@@ -2929,10 +3007,11 @@
29293007
}
29303008
return z;
29313009
}
29323010
void db_set(const char *zName, const char *zValue, int globalFlag){
29333011
db_begin_transaction();
3012
+ db_unprotect(PROTECT_CONFIG);
29343013
if( globalFlag ){
29353014
db_swap_connections();
29363015
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
29373016
zName, zValue);
29383017
db_swap_connections();
@@ -2941,14 +3020,16 @@
29413020
zName, zValue);
29423021
}
29433022
if( globalFlag && g.repositoryOpen ){
29443023
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
29453024
}
3025
+ db_protect_pop();
29463026
db_end_transaction(0);
29473027
}
29483028
void db_unset(const char *zName, int globalFlag){
29493029
db_begin_transaction();
3030
+ db_unprotect(PROTECT_CONFIG);
29503031
if( globalFlag ){
29513032
db_swap_connections();
29523033
db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName);
29533034
db_swap_connections();
29543035
}else{
@@ -2955,10 +3036,11 @@
29553036
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
29563037
}
29573038
if( globalFlag && g.repositoryOpen ){
29583039
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
29593040
}
3041
+ db_protect_pop();
29603042
db_end_transaction(0);
29613043
}
29623044
int db_is_global(const char *zName){
29633045
int rc = 0;
29643046
if( g.zConfigDbName ){
@@ -2988,10 +3070,11 @@
29883070
db_swap_connections();
29893071
}
29903072
return v;
29913073
}
29923074
void db_set_int(const char *zName, int value, int globalFlag){
3075
+ db_unprotect(PROTECT_CONFIG);
29933076
if( globalFlag ){
29943077
db_swap_connections();
29953078
db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
29963079
zName, value);
29973080
db_swap_connections();
@@ -3000,10 +3083,11 @@
30003083
zName, value);
30013084
}
30023085
if( globalFlag && g.repositoryOpen ){
30033086
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
30043087
}
3088
+ db_protect_pop();
30053089
}
30063090
int db_get_boolean(const char *zName, int dflt){
30073091
char *zVal = db_get(zName, dflt ? "on" : "off");
30083092
if( is_truth(zVal) ){
30093093
dflt = 1;
@@ -3129,24 +3213,28 @@
31293213
}
31303214
file_canonical_name(zName, &full, 0);
31313215
(void)filename_collation(); /* Initialize before connection swap */
31323216
db_swap_connections();
31333217
zRepoSetting = mprintf("repo:%q", blob_str(&full));
3218
+
3219
+ db_unprotect(PROTECT_CONFIG);
31343220
db_multi_exec(
31353221
"DELETE FROM global_config WHERE name %s = %Q;",
31363222
filename_collation(), zRepoSetting
31373223
);
31383224
db_multi_exec(
31393225
"INSERT OR IGNORE INTO global_config(name,value)"
31403226
"VALUES(%Q,1);",
31413227
zRepoSetting
31423228
);
3229
+ db_protect_pop();
31433230
fossil_free(zRepoSetting);
31443231
if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
31453232
Blob localRoot;
31463233
file_canonical_name(g.zLocalRoot, &localRoot, 1);
31473234
zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
3235
+ db_unprotect(PROTECT_CONFIG|PROTECT_SENSITIVE);
31483236
db_multi_exec(
31493237
"DELETE FROM global_config WHERE name %s = %Q;",
31503238
filename_collation(), zCkoutSetting
31513239
);
31523240
db_multi_exec(
@@ -3162,10 +3250,11 @@
31623250
db_optional_sql("repository",
31633251
"REPLACE INTO config(name,value,mtime)"
31643252
"VALUES(%Q,1,now());",
31653253
zCkoutSetting
31663254
);
3255
+ db_protect_pop();
31673256
fossil_free(zCkoutSetting);
31683257
blob_reset(&localRoot);
31693258
}else{
31703259
db_swap_connections();
31713260
}
@@ -3444,12 +3533,13 @@
34443533
const char *name; /* Name of the setting */
34453534
const char *var; /* Internal variable name used by db_set() */
34463535
int width; /* Width of display. 0 for boolean values and
34473536
** negative for values which should not appear
34483537
** on the /setup_settings page. */
3449
- int versionable; /* Is this setting versionable? */
3450
- int forceTextArea; /* Force using a text area for display? */
3538
+ char versionable; /* Is this setting versionable? */
3539
+ char forceTextArea; /* Force using a text area for display? */
3540
+ char sensitive; /* True if this a security-sensitive setting */
34513541
const char *def; /* Default value */
34523542
};
34533543
#endif /* INTERFACE */
34543544
34553545
/*
34563546
--- src/db.c
+++ src/db.c
@@ -114,10 +114,11 @@
114 /*
115 ** All static variable that a used by only this file are gathered into
116 ** the following structure.
117 */
118 static struct DbLocalData {
 
119 int nBegin; /* Nesting depth of BEGIN */
120 int doRollback; /* True to force a rollback */
121 int nCommitHook; /* Number of commit hooks */
122 int wrTxn; /* Outer-most TNX is a write */
123 Stmt *pAllStmt; /* List of all unfinalized statements */
@@ -134,14 +135,15 @@
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 */
147 void db_delete_on_failure(const char *zFilename){
@@ -323,10 +325,53 @@
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
@@ -343,23 +388,25 @@
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);
@@ -1154,10 +1201,35 @@
1154 }
1155 strcpy(zOut, zTemp = obscure((char*)zIn));
1156 fossil_free(zTemp);
1157 sqlite3_result_text(context, zOut, strlen(zOut), sqlite3_free);
1158 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1159
1160 /*
1161 ** Register the SQL functions that are useful both to the internal
1162 ** representation and to the "fossil sql" command.
1163 */
@@ -1184,10 +1256,12 @@
1184 alert_find_emailaddr_func, 0, 0);
1185 sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
1186 alert_display_name_func, 0, 0);
1187 sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
1188 db_obscure, 0, 0);
 
 
1189 }
1190
1191 #if USE_SEE
1192 /*
1193 ** This is a pointer to the saved database encryption key string.
@@ -2304,10 +2378,11 @@
2304 zUser = fossil_getenv("USERNAME");
2305 }
2306 if( zUser==0 ){
2307 zUser = "root";
2308 }
 
2309 db_multi_exec(
2310 "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
2311 );
2312 db_multi_exec(
2313 "UPDATE user SET cap='s', pw=%Q"
@@ -2323,10 +2398,11 @@
2323 " VALUES('developer','','ei','Dev');"
2324 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
2325 " VALUES('reader','','kptw','Reader');"
2326 );
2327 }
 
2328 }
2329
2330 /*
2331 ** Return a pointer to a string that contains the RHS of an IN operator
2332 ** that will select CONFIG table names that are in the list of control
@@ -2374,10 +2450,11 @@
2374 ){
2375 char *zDate;
2376 Blob hash;
2377 Blob manifest;
2378
 
2379 db_set("content-schema", CONTENT_SCHEMA, 0);
2380 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
2381 db_set("rebuilt", get_version(), 0);
2382 db_set("admin-log", "1", 0);
2383 db_set("access-log", "1", 0);
@@ -2432,10 +2509,11 @@
2432 " photo = (SELECT u2.photo FROM settingSrc.user u2"
2433 " WHERE u2.login = user.login)"
2434 " WHERE user.login IN ('anonymous','nobody','developer','reader');"
2435 );
2436 }
 
2437
2438 if( zInitialDate ){
2439 int rid;
2440 blob_zero(&manifest);
2441 blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
@@ -2929,10 +3007,11 @@
2929 }
2930 return z;
2931 }
2932 void db_set(const char *zName, const char *zValue, int globalFlag){
2933 db_begin_transaction();
 
2934 if( globalFlag ){
2935 db_swap_connections();
2936 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
2937 zName, zValue);
2938 db_swap_connections();
@@ -2941,14 +3020,16 @@
2941 zName, zValue);
2942 }
2943 if( globalFlag && g.repositoryOpen ){
2944 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
2945 }
 
2946 db_end_transaction(0);
2947 }
2948 void db_unset(const char *zName, int globalFlag){
2949 db_begin_transaction();
 
2950 if( globalFlag ){
2951 db_swap_connections();
2952 db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName);
2953 db_swap_connections();
2954 }else{
@@ -2955,10 +3036,11 @@
2955 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
2956 }
2957 if( globalFlag && g.repositoryOpen ){
2958 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
2959 }
 
2960 db_end_transaction(0);
2961 }
2962 int db_is_global(const char *zName){
2963 int rc = 0;
2964 if( g.zConfigDbName ){
@@ -2988,10 +3070,11 @@
2988 db_swap_connections();
2989 }
2990 return v;
2991 }
2992 void db_set_int(const char *zName, int value, int globalFlag){
 
2993 if( globalFlag ){
2994 db_swap_connections();
2995 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
2996 zName, value);
2997 db_swap_connections();
@@ -3000,10 +3083,11 @@
3000 zName, value);
3001 }
3002 if( globalFlag && g.repositoryOpen ){
3003 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3004 }
 
3005 }
3006 int db_get_boolean(const char *zName, int dflt){
3007 char *zVal = db_get(zName, dflt ? "on" : "off");
3008 if( is_truth(zVal) ){
3009 dflt = 1;
@@ -3129,24 +3213,28 @@
3129 }
3130 file_canonical_name(zName, &full, 0);
3131 (void)filename_collation(); /* Initialize before connection swap */
3132 db_swap_connections();
3133 zRepoSetting = mprintf("repo:%q", blob_str(&full));
 
 
3134 db_multi_exec(
3135 "DELETE FROM global_config WHERE name %s = %Q;",
3136 filename_collation(), zRepoSetting
3137 );
3138 db_multi_exec(
3139 "INSERT OR IGNORE INTO global_config(name,value)"
3140 "VALUES(%Q,1);",
3141 zRepoSetting
3142 );
 
3143 fossil_free(zRepoSetting);
3144 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
3145 Blob localRoot;
3146 file_canonical_name(g.zLocalRoot, &localRoot, 1);
3147 zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
 
3148 db_multi_exec(
3149 "DELETE FROM global_config WHERE name %s = %Q;",
3150 filename_collation(), zCkoutSetting
3151 );
3152 db_multi_exec(
@@ -3162,10 +3250,11 @@
3162 db_optional_sql("repository",
3163 "REPLACE INTO config(name,value,mtime)"
3164 "VALUES(%Q,1,now());",
3165 zCkoutSetting
3166 );
 
3167 fossil_free(zCkoutSetting);
3168 blob_reset(&localRoot);
3169 }else{
3170 db_swap_connections();
3171 }
@@ -3444,12 +3533,13 @@
3444 const char *name; /* Name of the setting */
3445 const char *var; /* Internal variable name used by db_set() */
3446 int width; /* Width of display. 0 for boolean values and
3447 ** negative for values which should not appear
3448 ** on the /setup_settings page. */
3449 int versionable; /* Is this setting versionable? */
3450 int forceTextArea; /* Force using a text area for display? */
 
3451 const char *def; /* Default value */
3452 };
3453 #endif /* INTERFACE */
3454
3455 /*
3456
--- src/db.c
+++ src/db.c
@@ -114,10 +114,11 @@
114 /*
115 ** All static variable that a used by only this file are gathered into
116 ** the following structure.
117 */
118 static struct DbLocalData {
119 unsigned protectMask; /* Prevent changes to database */
120 int nBegin; /* Nesting depth of BEGIN */
121 int doRollback; /* True to force a rollback */
122 int nCommitHook; /* Number of commit hooks */
123 int wrTxn; /* Outer-most TNX is a write */
124 Stmt *pAllStmt; /* List of all unfinalized statements */
@@ -134,14 +135,15 @@
135 const char *zStartFile; /* File in which transaction was started */
136 int iStartLine; /* Line of zStartFile where transaction started */
137 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
138 void *pAuthArg; /* Argument to the authorizer */
139 const char *zAuthName; /* Name of the authorizer */
140 int nProtect; /* Slots of aProtect used */
141 unsigned aProtect[10]; /* Saved values of protectMask */
142 } db = {
143 PROTECT_USER|PROTECT_CONFIG, /* protectMask */
144 0, 0, 0, 0, 0, 0, };
145
146 /*
147 ** Arrange for the given file to be deleted on a failure.
148 */
149 void db_delete_on_failure(const char *zFilename){
@@ -323,10 +325,53 @@
325 }
326 db.aHook[db.nCommitHook].sequence = sequence;
327 db.aHook[db.nCommitHook].xHook = x;
328 db.nCommitHook++;
329 }
330
331 #if INTERFACE
332 /*
333 ** Flag bits for db_protect() and db_unprotect()
334 */
335 #define PROTECT_USER 0x01
336 #define PROTECT_CONFIG 0x02
337 #define PROTECT_SENSITIVE 0x04
338 #define PROTECT_READONLY 0x08
339 #define PROTECT_ALL 0x0f /* All of the above */
340 #endif /* INTERFACE */
341
342 /*
343 ** Enable or disable database write protections.
344 ** Use db_protect() to enable write permissions. Use
345 ** db_unprotect() to disable them.
346 **
347 ** Each call to db_protect() and/or db_unprotect() should be followed
348 ** by a corresponding call to db_protect_pop(). The db_protect_pop()
349 ** call restores the protection settings to what they were before.
350 **
351 ** The stack of protection settings is finite, so do not nest calls
352 ** to db_protect()/db_unprotect() too deeply. And make sure calls
353 ** to db_protect()/db_unprotect() are balanced.
354 */
355 void db_protect(unsigned flags){
356 if( db.nProtect>=count(db.aProtect) ){
357 fossil_fatal("too many db_protect() calls");
358 }
359 db.aProtect[db.nProtect++] = db.protectMask;
360 db.protectMask |= flags;
361 }
362 void db_unprotect(unsigned flags){
363 if( db.nProtect>=count(db.aProtect) ){
364 fossil_fatal("too many db_unprotect() calls");
365 }
366 db.aProtect[db.nProtect++] = db.protectMask;
367 db.protectMask &= ~flags;
368 }
369 void db_protect_pop(void){
370 if( db.nProtect<1 ) fossil_fatal("too many db_protect_pop() calls");
371 db.protectMask = db.aProtect[--db.nProtect];
372 }
373
374 /*
375 ** Every Fossil database connection automatically registers the following
376 ** overarching authenticator callback, and leaves it registered for the
377 ** duration of the connection. This authenticator will call any
@@ -343,23 +388,25 @@
388 int rc = SQLITE_OK;
389 switch( eCode ){
390 case SQLITE_INSERT:
391 case SQLITE_UPDATE:
392 case SQLITE_DELETE: {
393 if( (db.protectMask & PROTECT_USER)!=0
394 && sqlite3_stricmp(z0,"user")==0 ){
395 rc = SQLITE_DENY;
396 }else if( (db.protectMask & PROTECT_CONFIG)!=0 &&
397 (sqlite3_stricmp(z0,"config")==0 ||
398 sqlite3_stricmp(z0,"global_config")==0) ){
399 rc = SQLITE_DENY;
400 }else if( (db.protectMask & PROTECT_READONLY)!=0
401 && sqlite3_stricmp(z2,"temp")!=0 ){
402 rc = SQLITE_DENY;
403 }
404 break;
405 }
406 case SQLITE_DROP_TEMP_TRIGGER: {
407 rc = SQLITE_DENY;
 
 
408 break;
409 }
410 }
411 if( db.xAuth && rc==SQLITE_OK ){
412 rc = db.xAuth(db.pAuthArg, eCode, z0, z1, z2, z3);
@@ -1154,10 +1201,35 @@
1201 }
1202 strcpy(zOut, zTemp = obscure((char*)zIn));
1203 fossil_free(zTemp);
1204 sqlite3_result_text(context, zOut, strlen(zOut), sqlite3_free);
1205 }
1206
1207 /*
1208 ** Implement the protected_setting(X) SQL function. This function returns
1209 ** true if X is the name of a protected (security-sensitive) setting and
1210 ** the db.protectSensitive flag is enabled. It returns false otherwise.
1211 */
1212 LOCAL void db_protected_setting(
1213 sqlite3_context *context,
1214 int argc,
1215 sqlite3_value **argv
1216 ){
1217 const char *zSetting;
1218 const Setting *pSetting;
1219 if( (db.protectMask & PROTECT_SENSITIVE)==0 ){
1220 sqlite3_result_int(context, 0);
1221 return;
1222 }
1223 zSetting = (const char*)sqlite3_value_text(argv[0]);
1224 pSetting = zSetting ? db_find_setting(zSetting,0) : 0;
1225 if( pSetting && pSetting->sensitive ){
1226 sqlite3_result_int(context, 1);
1227 }else{
1228 sqlite3_result_int(context, 0);
1229 }
1230 }
1231
1232 /*
1233 ** Register the SQL functions that are useful both to the internal
1234 ** representation and to the "fossil sql" command.
1235 */
@@ -1184,10 +1256,12 @@
1256 alert_find_emailaddr_func, 0, 0);
1257 sqlite3_create_function(db, "display_name", 1, SQLITE_UTF8, 0,
1258 alert_display_name_func, 0, 0);
1259 sqlite3_create_function(db, "obscure", 1, SQLITE_UTF8, 0,
1260 db_obscure, 0, 0);
1261 sqlite3_create_function(db, "protected_setting", 1, SQLITE_UTF8, 0,
1262 db_protected_setting, 0, 0);
1263 }
1264
1265 #if USE_SEE
1266 /*
1267 ** This is a pointer to the saved database encryption key string.
@@ -2304,10 +2378,11 @@
2378 zUser = fossil_getenv("USERNAME");
2379 }
2380 if( zUser==0 ){
2381 zUser = "root";
2382 }
2383 db_unprotect(PROTECT_USER);
2384 db_multi_exec(
2385 "INSERT OR IGNORE INTO user(login, info) VALUES(%Q,'')", zUser
2386 );
2387 db_multi_exec(
2388 "UPDATE user SET cap='s', pw=%Q"
@@ -2323,10 +2398,11 @@
2398 " VALUES('developer','','ei','Dev');"
2399 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
2400 " VALUES('reader','','kptw','Reader');"
2401 );
2402 }
2403 db_protect_pop();
2404 }
2405
2406 /*
2407 ** Return a pointer to a string that contains the RHS of an IN operator
2408 ** that will select CONFIG table names that are in the list of control
@@ -2374,10 +2450,11 @@
2450 ){
2451 char *zDate;
2452 Blob hash;
2453 Blob manifest;
2454
2455 db_unprotect(PROTECT_ALL);
2456 db_set("content-schema", CONTENT_SCHEMA, 0);
2457 db_set("aux-schema", AUX_SCHEMA_MAX, 0);
2458 db_set("rebuilt", get_version(), 0);
2459 db_set("admin-log", "1", 0);
2460 db_set("access-log", "1", 0);
@@ -2432,10 +2509,11 @@
2509 " photo = (SELECT u2.photo FROM settingSrc.user u2"
2510 " WHERE u2.login = user.login)"
2511 " WHERE user.login IN ('anonymous','nobody','developer','reader');"
2512 );
2513 }
2514 db_protect_pop();
2515
2516 if( zInitialDate ){
2517 int rid;
2518 blob_zero(&manifest);
2519 blob_appendf(&manifest, "C initial\\sempty\\scheck-in\n");
@@ -2929,10 +3007,11 @@
3007 }
3008 return z;
3009 }
3010 void db_set(const char *zName, const char *zValue, int globalFlag){
3011 db_begin_transaction();
3012 db_unprotect(PROTECT_CONFIG);
3013 if( globalFlag ){
3014 db_swap_connections();
3015 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%Q)",
3016 zName, zValue);
3017 db_swap_connections();
@@ -2941,14 +3020,16 @@
3020 zName, zValue);
3021 }
3022 if( globalFlag && g.repositoryOpen ){
3023 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3024 }
3025 db_protect_pop();
3026 db_end_transaction(0);
3027 }
3028 void db_unset(const char *zName, int globalFlag){
3029 db_begin_transaction();
3030 db_unprotect(PROTECT_CONFIG);
3031 if( globalFlag ){
3032 db_swap_connections();
3033 db_multi_exec("DELETE FROM global_config WHERE name=%Q", zName);
3034 db_swap_connections();
3035 }else{
@@ -2955,10 +3036,11 @@
3036 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3037 }
3038 if( globalFlag && g.repositoryOpen ){
3039 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3040 }
3041 db_protect_pop();
3042 db_end_transaction(0);
3043 }
3044 int db_is_global(const char *zName){
3045 int rc = 0;
3046 if( g.zConfigDbName ){
@@ -2988,10 +3070,11 @@
3070 db_swap_connections();
3071 }
3072 return v;
3073 }
3074 void db_set_int(const char *zName, int value, int globalFlag){
3075 db_unprotect(PROTECT_CONFIG);
3076 if( globalFlag ){
3077 db_swap_connections();
3078 db_multi_exec("REPLACE INTO global_config(name,value) VALUES(%Q,%d)",
3079 zName, value);
3080 db_swap_connections();
@@ -3000,10 +3083,11 @@
3083 zName, value);
3084 }
3085 if( globalFlag && g.repositoryOpen ){
3086 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
3087 }
3088 db_protect_pop();
3089 }
3090 int db_get_boolean(const char *zName, int dflt){
3091 char *zVal = db_get(zName, dflt ? "on" : "off");
3092 if( is_truth(zVal) ){
3093 dflt = 1;
@@ -3129,24 +3213,28 @@
3213 }
3214 file_canonical_name(zName, &full, 0);
3215 (void)filename_collation(); /* Initialize before connection swap */
3216 db_swap_connections();
3217 zRepoSetting = mprintf("repo:%q", blob_str(&full));
3218
3219 db_unprotect(PROTECT_CONFIG);
3220 db_multi_exec(
3221 "DELETE FROM global_config WHERE name %s = %Q;",
3222 filename_collation(), zRepoSetting
3223 );
3224 db_multi_exec(
3225 "INSERT OR IGNORE INTO global_config(name,value)"
3226 "VALUES(%Q,1);",
3227 zRepoSetting
3228 );
3229 db_protect_pop();
3230 fossil_free(zRepoSetting);
3231 if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
3232 Blob localRoot;
3233 file_canonical_name(g.zLocalRoot, &localRoot, 1);
3234 zCkoutSetting = mprintf("ckout:%q", blob_str(&localRoot));
3235 db_unprotect(PROTECT_CONFIG|PROTECT_SENSITIVE);
3236 db_multi_exec(
3237 "DELETE FROM global_config WHERE name %s = %Q;",
3238 filename_collation(), zCkoutSetting
3239 );
3240 db_multi_exec(
@@ -3162,10 +3250,11 @@
3250 db_optional_sql("repository",
3251 "REPLACE INTO config(name,value,mtime)"
3252 "VALUES(%Q,1,now());",
3253 zCkoutSetting
3254 );
3255 db_protect_pop();
3256 fossil_free(zCkoutSetting);
3257 blob_reset(&localRoot);
3258 }else{
3259 db_swap_connections();
3260 }
@@ -3444,12 +3533,13 @@
3533 const char *name; /* Name of the setting */
3534 const char *var; /* Internal variable name used by db_set() */
3535 int width; /* Width of display. 0 for boolean values and
3536 ** negative for values which should not appear
3537 ** on the /setup_settings page. */
3538 char versionable; /* Is this setting versionable? */
3539 char forceTextArea; /* Force using a text area for display? */
3540 char sensitive; /* True if this a security-sensitive setting */
3541 const char *def; /* Default value */
3542 };
3543 #endif /* INTERFACE */
3544
3545 /*
3546
--- src/forum.c
+++ src/forum.c
@@ -1195,13 +1195,15 @@
11951195
moderation_approve('f', fpid);
11961196
if( g.perm.AdminForum
11971197
&& PB("trust")
11981198
&& (zUserToTrust = P("trustuser"))!=0
11991199
){
1200
+ db_unprotect(PROTECT_USER);
12001201
db_multi_exec("UPDATE user SET cap=cap||'4' "
12011202
"WHERE login=%Q AND cap NOT GLOB '*4*'",
12021203
zUserToTrust);
1204
+ db_protect_pop();
12031205
}
12041206
cgi_redirectf("%R/forumpost/%S",P("fpid"));
12051207
return;
12061208
}
12071209
if( P("reject") ){
12081210
--- src/forum.c
+++ src/forum.c
@@ -1195,13 +1195,15 @@
1195 moderation_approve('f', fpid);
1196 if( g.perm.AdminForum
1197 && PB("trust")
1198 && (zUserToTrust = P("trustuser"))!=0
1199 ){
 
1200 db_multi_exec("UPDATE user SET cap=cap||'4' "
1201 "WHERE login=%Q AND cap NOT GLOB '*4*'",
1202 zUserToTrust);
 
1203 }
1204 cgi_redirectf("%R/forumpost/%S",P("fpid"));
1205 return;
1206 }
1207 if( P("reject") ){
1208
--- src/forum.c
+++ src/forum.c
@@ -1195,13 +1195,15 @@
1195 moderation_approve('f', fpid);
1196 if( g.perm.AdminForum
1197 && PB("trust")
1198 && (zUserToTrust = P("trustuser"))!=0
1199 ){
1200 db_unprotect(PROTECT_USER);
1201 db_multi_exec("UPDATE user SET cap=cap||'4' "
1202 "WHERE login=%Q AND cap NOT GLOB '*4*'",
1203 zUserToTrust);
1204 db_protect_pop();
1205 }
1206 cgi_redirectf("%R/forumpost/%S",P("fpid"));
1207 return;
1208 }
1209 if( P("reject") ){
1210
+8
--- src/hook.c
+++ src/hook.c
@@ -123,15 +123,17 @@
123123
** If N==0, then there is no expectation of new artifacts arriving
124124
** soon and so post-receive hooks can be run without delay.
125125
*/
126126
void hook_expecting_more_artifacts(int N){
127127
if( N>0 ){
128
+ db_unprotect(PROTECT_CONFIG);
128129
db_multi_exec(
129130
"REPLACE INTO config(name,value,mtime)"
130131
"VALUES('hook-embargo',now()+%d,now())",
131132
N
132133
);
134
+ db_protect_pop();
133135
}else{
134136
db_unset("hook-embargo",0);
135137
}
136138
}
137139
@@ -243,10 +245,11 @@
243245
fossil_fatal("the --command and --type options are required");
244246
}
245247
validate_type(zType);
246248
nSeq = zSeq ? atoi(zSeq) : 10;
247249
db_begin_write();
250
+ db_unprotect(PROTECT_CONFIG);
248251
db_multi_exec(
249252
"INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
250253
"UPDATE config"
251254
" SET value=json_insert("
252255
" CASE WHEN json_valid(value) THEN value ELSE '[]' END,'$[#]',"
@@ -253,10 +256,11 @@
253256
" json_object('cmd',%Q,'type',%Q,'seq',%d)),"
254257
" mtime=now()"
255258
" WHERE name='hooks';",
256259
zCmd, zType, nSeq
257260
);
261
+ db_protect_pop();
258262
db_commit_transaction();
259263
}else
260264
if( strncmp(zCmd, "edit", nCmd)==0 ){
261265
const char *zCmd = find_option("command",0,1);
262266
const char *zType = find_option("type",0,1);
@@ -290,20 +294,23 @@
290294
}
291295
if( zSeq ){
292296
blob_append_sql(&sql, ",'$[%d].seq',%d", id, nSeq);
293297
}
294298
blob_append_sql(&sql,") WHERE name='hooks';");
299
+ db_unprotect(PROTECT_CONFIG);
295300
db_multi_exec("%s", blob_sql_text(&sql));
301
+ db_protect_pop();
296302
blob_reset(&sql);
297303
}
298304
db_commit_transaction();
299305
}else
300306
if( strncmp(zCmd, "delete", nCmd)==0 ){
301307
int i;
302308
verify_all_options();
303309
if( g.argc<4 ) usage("delete ID ...");
304310
db_begin_write();
311
+ db_unprotect(PROTECT_CONFIG);
305312
db_multi_exec(
306313
"INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
307314
);
308315
for(i=3; i<g.argc; i++){
309316
const char *zId = g.argv[i];
@@ -321,10 +328,11 @@
321328
" mtime=now()"
322329
" WHERE name='hooks';",
323330
atoi(zId)
324331
);
325332
}
333
+ db_protect_pop();
326334
db_commit_transaction();
327335
}else
328336
if( strncmp(zCmd, "list", nCmd)==0 ){
329337
Stmt q;
330338
int n = 0;
331339
--- src/hook.c
+++ src/hook.c
@@ -123,15 +123,17 @@
123 ** If N==0, then there is no expectation of new artifacts arriving
124 ** soon and so post-receive hooks can be run without delay.
125 */
126 void hook_expecting_more_artifacts(int N){
127 if( N>0 ){
 
128 db_multi_exec(
129 "REPLACE INTO config(name,value,mtime)"
130 "VALUES('hook-embargo',now()+%d,now())",
131 N
132 );
 
133 }else{
134 db_unset("hook-embargo",0);
135 }
136 }
137
@@ -243,10 +245,11 @@
243 fossil_fatal("the --command and --type options are required");
244 }
245 validate_type(zType);
246 nSeq = zSeq ? atoi(zSeq) : 10;
247 db_begin_write();
 
248 db_multi_exec(
249 "INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
250 "UPDATE config"
251 " SET value=json_insert("
252 " CASE WHEN json_valid(value) THEN value ELSE '[]' END,'$[#]',"
@@ -253,10 +256,11 @@
253 " json_object('cmd',%Q,'type',%Q,'seq',%d)),"
254 " mtime=now()"
255 " WHERE name='hooks';",
256 zCmd, zType, nSeq
257 );
 
258 db_commit_transaction();
259 }else
260 if( strncmp(zCmd, "edit", nCmd)==0 ){
261 const char *zCmd = find_option("command",0,1);
262 const char *zType = find_option("type",0,1);
@@ -290,20 +294,23 @@
290 }
291 if( zSeq ){
292 blob_append_sql(&sql, ",'$[%d].seq',%d", id, nSeq);
293 }
294 blob_append_sql(&sql,") WHERE name='hooks';");
 
295 db_multi_exec("%s", blob_sql_text(&sql));
 
296 blob_reset(&sql);
297 }
298 db_commit_transaction();
299 }else
300 if( strncmp(zCmd, "delete", nCmd)==0 ){
301 int i;
302 verify_all_options();
303 if( g.argc<4 ) usage("delete ID ...");
304 db_begin_write();
 
305 db_multi_exec(
306 "INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
307 );
308 for(i=3; i<g.argc; i++){
309 const char *zId = g.argv[i];
@@ -321,10 +328,11 @@
321 " mtime=now()"
322 " WHERE name='hooks';",
323 atoi(zId)
324 );
325 }
 
326 db_commit_transaction();
327 }else
328 if( strncmp(zCmd, "list", nCmd)==0 ){
329 Stmt q;
330 int n = 0;
331
--- src/hook.c
+++ src/hook.c
@@ -123,15 +123,17 @@
123 ** If N==0, then there is no expectation of new artifacts arriving
124 ** soon and so post-receive hooks can be run without delay.
125 */
126 void hook_expecting_more_artifacts(int N){
127 if( N>0 ){
128 db_unprotect(PROTECT_CONFIG);
129 db_multi_exec(
130 "REPLACE INTO config(name,value,mtime)"
131 "VALUES('hook-embargo',now()+%d,now())",
132 N
133 );
134 db_protect_pop();
135 }else{
136 db_unset("hook-embargo",0);
137 }
138 }
139
@@ -243,10 +245,11 @@
245 fossil_fatal("the --command and --type options are required");
246 }
247 validate_type(zType);
248 nSeq = zSeq ? atoi(zSeq) : 10;
249 db_begin_write();
250 db_unprotect(PROTECT_CONFIG);
251 db_multi_exec(
252 "INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
253 "UPDATE config"
254 " SET value=json_insert("
255 " CASE WHEN json_valid(value) THEN value ELSE '[]' END,'$[#]',"
@@ -253,10 +256,11 @@
256 " json_object('cmd',%Q,'type',%Q,'seq',%d)),"
257 " mtime=now()"
258 " WHERE name='hooks';",
259 zCmd, zType, nSeq
260 );
261 db_protect_pop();
262 db_commit_transaction();
263 }else
264 if( strncmp(zCmd, "edit", nCmd)==0 ){
265 const char *zCmd = find_option("command",0,1);
266 const char *zType = find_option("type",0,1);
@@ -290,20 +294,23 @@
294 }
295 if( zSeq ){
296 blob_append_sql(&sql, ",'$[%d].seq',%d", id, nSeq);
297 }
298 blob_append_sql(&sql,") WHERE name='hooks';");
299 db_unprotect(PROTECT_CONFIG);
300 db_multi_exec("%s", blob_sql_text(&sql));
301 db_protect_pop();
302 blob_reset(&sql);
303 }
304 db_commit_transaction();
305 }else
306 if( strncmp(zCmd, "delete", nCmd)==0 ){
307 int i;
308 verify_all_options();
309 if( g.argc<4 ) usage("delete ID ...");
310 db_begin_write();
311 db_unprotect(PROTECT_CONFIG);
312 db_multi_exec(
313 "INSERT OR IGNORE INTO config(name,value) VALUES('hooks','[]');\n"
314 );
315 for(i=3; i<g.argc; i++){
316 const char *zId = g.argv[i];
@@ -321,10 +328,11 @@
328 " mtime=now()"
329 " WHERE name='hooks';",
330 atoi(zId)
331 );
332 }
333 db_protect_pop();
334 db_commit_transaction();
335 }else
336 if( strncmp(zCmd, "list", nCmd)==0 ){
337 Stmt q;
338 int n = 0;
339
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -576,16 +576,18 @@
576576
Blob sql;
577577
char *zSep = "(";
578578
db_begin_transaction();
579579
blob_init(&sql, 0, 0);
580580
if( g.argc==4 && find_option("all",0,0)!=0 ){
581
+ db_unprotect(PROTECT_CONFIG);
581582
blob_append_sql(&sql,
582583
"DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
583584
"DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
584585
"DELETE FROM config WHERE name GLOB 'cert:*';\n"
585586
"DELETE FROM config WHERE name GLOB 'trusted:*';\n"
586587
);
588
+ db_protect_pop();
587589
}else{
588590
if( g.argc<4 ){
589591
usage("remove-exception DOMAIN-NAME ...");
590592
}
591593
blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
592594
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -576,16 +576,18 @@
576 Blob sql;
577 char *zSep = "(";
578 db_begin_transaction();
579 blob_init(&sql, 0, 0);
580 if( g.argc==4 && find_option("all",0,0)!=0 ){
 
581 blob_append_sql(&sql,
582 "DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
583 "DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
584 "DELETE FROM config WHERE name GLOB 'cert:*';\n"
585 "DELETE FROM config WHERE name GLOB 'trusted:*';\n"
586 );
 
587 }else{
588 if( g.argc<4 ){
589 usage("remove-exception DOMAIN-NAME ...");
590 }
591 blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
592
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -576,16 +576,18 @@
576 Blob sql;
577 char *zSep = "(";
578 db_begin_transaction();
579 blob_init(&sql, 0, 0);
580 if( g.argc==4 && find_option("all",0,0)!=0 ){
581 db_unprotect(PROTECT_CONFIG);
582 blob_append_sql(&sql,
583 "DELETE FROM global_config WHERE name GLOB 'cert:*';\n"
584 "DELETE FROM global_config WHERE name GLOB 'trusted:*';\n"
585 "DELETE FROM config WHERE name GLOB 'cert:*';\n"
586 "DELETE FROM config WHERE name GLOB 'trusted:*';\n"
587 );
588 db_protect_pop();
589 }else{
590 if( g.argc<4 ){
591 usage("remove-exception DOMAIN-NAME ...");
592 }
593 blob_append_sql(&sql,"DELETE FROM global_config WHERE name IN ");
594
--- src/json_user.c
+++ src/json_user.c
@@ -212,13 +212,15 @@
212212
json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
213213
"User %s already exists.", zName);
214214
goto error;
215215
}else{
216216
Stmt ins = empty_Stmt;
217
+ db_unprotect(PROTECT_USER);
217218
db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
218219
db_step( &ins );
219220
db_finalize(&ins);
221
+ db_protect_pop();
220222
uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
221223
assert(uid>0);
222224
zNameNew = zName;
223225
cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
224226
}
@@ -345,13 +347,15 @@
345347
#endif
346348
#if 0
347349
puts(blob_str(&sql));
348350
cson_output_FILE( cson_object_value(pUser), stdout, NULL );
349351
#endif
352
+ db_unprotect(PROTECT_USER);
350353
db_prepare(&q, "%s", blob_sql_text(&sql));
351354
db_exec(&q);
352355
db_finalize(&q);
356
+ db_protect_pop();
353357
#if TRY_LOGIN_GROUP
354358
if( zPW || cson_value_get_bool(forceLogout) ){
355359
Blob groupSql = empty_blob;
356360
char * zErr = NULL;
357361
blob_append_sql(&groupSql,
@@ -358,11 +362,13 @@
358362
"INSERT INTO user(login)"
359363
" SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
360364
zName, zName
361365
);
362366
blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
367
+ db_unprotect(PROTECT_USER);
363368
login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
369
+ db_protect_pop();
364370
blob_reset(&groupSql);
365371
if( zErr ){
366372
json_set_err( FSL_JSON_E_UNKNOWN,
367373
"Repo-group update at least partially failed: %s",
368374
zErr);
369375
--- src/json_user.c
+++ src/json_user.c
@@ -212,13 +212,15 @@
212 json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
213 "User %s already exists.", zName);
214 goto error;
215 }else{
216 Stmt ins = empty_Stmt;
 
217 db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
218 db_step( &ins );
219 db_finalize(&ins);
 
220 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
221 assert(uid>0);
222 zNameNew = zName;
223 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
224 }
@@ -345,13 +347,15 @@
345 #endif
346 #if 0
347 puts(blob_str(&sql));
348 cson_output_FILE( cson_object_value(pUser), stdout, NULL );
349 #endif
 
350 db_prepare(&q, "%s", blob_sql_text(&sql));
351 db_exec(&q);
352 db_finalize(&q);
 
353 #if TRY_LOGIN_GROUP
354 if( zPW || cson_value_get_bool(forceLogout) ){
355 Blob groupSql = empty_blob;
356 char * zErr = NULL;
357 blob_append_sql(&groupSql,
@@ -358,11 +362,13 @@
358 "INSERT INTO user(login)"
359 " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
360 zName, zName
361 );
362 blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
 
363 login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
 
364 blob_reset(&groupSql);
365 if( zErr ){
366 json_set_err( FSL_JSON_E_UNKNOWN,
367 "Repo-group update at least partially failed: %s",
368 zErr);
369
--- src/json_user.c
+++ src/json_user.c
@@ -212,13 +212,15 @@
212 json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
213 "User %s already exists.", zName);
214 goto error;
215 }else{
216 Stmt ins = empty_Stmt;
217 db_unprotect(PROTECT_USER);
218 db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
219 db_step( &ins );
220 db_finalize(&ins);
221 db_protect_pop();
222 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
223 assert(uid>0);
224 zNameNew = zName;
225 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
226 }
@@ -345,13 +347,15 @@
347 #endif
348 #if 0
349 puts(blob_str(&sql));
350 cson_output_FILE( cson_object_value(pUser), stdout, NULL );
351 #endif
352 db_unprotect(PROTECT_USER);
353 db_prepare(&q, "%s", blob_sql_text(&sql));
354 db_exec(&q);
355 db_finalize(&q);
356 db_protect_pop();
357 #if TRY_LOGIN_GROUP
358 if( zPW || cson_value_get_bool(forceLogout) ){
359 Blob groupSql = empty_blob;
360 char * zErr = NULL;
361 blob_append_sql(&groupSql,
@@ -358,11 +362,13 @@
362 "INSERT INTO user(login)"
363 " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM user WHERE login=%Q);",
364 zName, zName
365 );
366 blob_append(&groupSql, blob_str(&sql), blob_size(&sql));
367 db_unprotect(PROTECT_USER);
368 login_group_sql(blob_str(&groupSql), NULL, NULL, &zErr);
369 db_protect_pop();
370 blob_reset(&groupSql);
371 if( zErr ){
372 json_set_err( FSL_JSON_E_UNKNOWN,
373 "Repo-group update at least partially failed: %s",
374 zErr);
375
+21 -2
--- src/login.c
+++ src/login.c
@@ -293,13 +293,15 @@
293293
if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
294294
zCookie = login_gen_user_cookie_value(zUsername, zHash);
295295
cgi_set_cookie(zCookieName, zCookie, login_cookie_path(),
296296
bSessionCookie ? 0 : expires);
297297
record_login_attempt(zUsername, zIpAddr, 1);
298
+ db_unprotect(PROTECT_USER);
298299
db_multi_exec("UPDATE user SET cookie=%Q,"
299300
" cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
300301
zHash, expires, uid);
302
+ db_protect_pop();
301303
fossil_free(zHash);
302304
if( zDest ){
303305
*zDest = zCookie;
304306
}else{
305307
free(zCookie);
@@ -356,14 +358,16 @@
356358
}else{
357359
const char *cookie = login_cookie_name();
358360
/* To logout, change the cookie value to an empty string */
359361
cgi_set_cookie(cookie, "",
360362
login_cookie_path(), -86400);
363
+ db_unprotect(PROTECT_USER);
361364
db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
362365
" cexpire=0 WHERE uid=%d"
363366
" AND login NOT IN ('anonymous','nobody',"
364367
" 'developer','reader')", g.userUid);
368
+ db_protect_pop();
365369
cgi_replace_parameter(cookie, NULL);
366370
cgi_replace_parameter("anon", NULL);
367371
}
368372
}
369373
@@ -580,22 +584,27 @@
580584
;
581585
}else{
582586
char *zNewPw = sha1_shared_secret(zNew1, g.zLogin, 0);
583587
char *zChngPw;
584588
char *zErr;
589
+ int rc;
590
+
591
+ db_unprotect(PROTECT_USER);
585592
db_multi_exec(
586593
"UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
587594
);
588
- fossil_free(zNewPw);
589595
zChngPw = mprintf(
590596
"UPDATE user"
591597
" SET pw=shared_secret(%Q,%Q,"
592598
" (SELECT value FROM config WHERE name='project-code'))"
593599
" WHERE login=%Q",
594600
zNew1, g.zLogin, g.zLogin
595601
);
596
- if( login_group_sql(zChngPw, "<p>", "</p>\n", &zErr) ){
602
+ fossil_free(zNewPw);
603
+ rc = login_group_sql(zChngPw, "<p>", "</p>\n", &zErr);
604
+ db_protect_pop();
605
+ if( rc ){
597606
zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
598607
fossil_free(zErr);
599608
}else{
600609
redirect_to_g();
601610
return;
@@ -835,16 +844,18 @@
835844
zLogin, zHash
836845
);
837846
pStmt = 0;
838847
rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
839848
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
849
+ db_unprotect(PROTECT_USER);
840850
db_multi_exec(
841851
"UPDATE user SET cookie=%Q, cexpire=%.17g"
842852
" WHERE login=%Q",
843853
zHash,
844854
sqlite3_column_double(pStmt, 0), zLogin
845855
);
856
+ db_protect_pop();
846857
nXfer++;
847858
}
848859
sqlite3_finalize(pStmt);
849860
}
850861
sqlite3_close(pOther);
@@ -1619,11 +1630,13 @@
16191630
"INSERT INTO user(login,pw,cap,info,mtime)\n"
16201631
"VALUES(%Q,%Q,%Q,"
16211632
"'%q <%q>\nself-register from ip %q on '||datetime('now'),now())",
16221633
zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr);
16231634
fossil_free(zPass);
1635
+ db_unprotect(PROTECT_USER);
16241636
db_multi_exec("%s", blob_sql_text(&sql));
1637
+ db_protect_pop();
16251638
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID);
16261639
login_set_user_cookie(zUserID, uid, NULL, 0);
16271640
if( doAlerts ){
16281641
/* Also make the new user a subscriber. */
16291642
Blob hdr, body;
@@ -1832,14 +1845,16 @@
18321845
while( db_step(&q)==SQLITE_ROW ){
18331846
const char *zRepoName = db_column_text(&q, 1);
18341847
if( file_size(zRepoName, ExtFILE)<0 ){
18351848
/* Silently remove non-existent repositories from the login group. */
18361849
const char *zLabel = db_column_text(&q, 0);
1850
+ db_unprotect(PROTECT_CONFIG);
18371851
db_multi_exec(
18381852
"DELETE FROM config WHERE name GLOB 'peer-*-%q'",
18391853
&zLabel[10]
18401854
);
1855
+ db_protect_pop();
18411856
continue;
18421857
}
18431858
rc = sqlite3_open_v2(
18441859
zRepoName, &pPeer,
18451860
SQLITE_OPEN_READWRITE,
@@ -2004,11 +2019,13 @@
20042019
"REPLACE INTO config(name,value,mtime) VALUES('peer-name-%q',%Q,now());"
20052020
"REPLACE INTO config(name,value,mtime) VALUES('peer-repo-%q',%Q,now());"
20062021
"COMMIT;",
20072022
zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
20082023
);
2024
+ db_unprotect(PROTECT_CONFIG);
20092025
login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
2026
+ db_protect_pop();
20102027
fossil_free(zSql);
20112028
}
20122029
20132030
/*
20142031
** Leave the login group that we are currently part of.
@@ -2025,17 +2042,19 @@
20252042
" WHERE name='login-group-name'"
20262043
" AND (SELECT count(*) FROM config WHERE name GLOB 'peer-*')==0;",
20272044
zProjCode
20282045
);
20292046
fossil_free(zProjCode);
2047
+ db_unprotect(PROTECT_CONFIG);
20302048
login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
20312049
fossil_free(zSql);
20322050
db_multi_exec(
20332051
"DELETE FROM config "
20342052
" WHERE name GLOB 'peer-*'"
20352053
" OR name GLOB 'login-group-*';"
20362054
);
2055
+ db_protect_pop();
20372056
}
20382057
20392058
/*
20402059
** COMMAND: login-group*
20412060
**
20422061
--- src/login.c
+++ src/login.c
@@ -293,13 +293,15 @@
293 if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
294 zCookie = login_gen_user_cookie_value(zUsername, zHash);
295 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(),
296 bSessionCookie ? 0 : expires);
297 record_login_attempt(zUsername, zIpAddr, 1);
 
298 db_multi_exec("UPDATE user SET cookie=%Q,"
299 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
300 zHash, expires, uid);
 
301 fossil_free(zHash);
302 if( zDest ){
303 *zDest = zCookie;
304 }else{
305 free(zCookie);
@@ -356,14 +358,16 @@
356 }else{
357 const char *cookie = login_cookie_name();
358 /* To logout, change the cookie value to an empty string */
359 cgi_set_cookie(cookie, "",
360 login_cookie_path(), -86400);
 
361 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
362 " cexpire=0 WHERE uid=%d"
363 " AND login NOT IN ('anonymous','nobody',"
364 " 'developer','reader')", g.userUid);
 
365 cgi_replace_parameter(cookie, NULL);
366 cgi_replace_parameter("anon", NULL);
367 }
368 }
369
@@ -580,22 +584,27 @@
580 ;
581 }else{
582 char *zNewPw = sha1_shared_secret(zNew1, g.zLogin, 0);
583 char *zChngPw;
584 char *zErr;
 
 
 
585 db_multi_exec(
586 "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
587 );
588 fossil_free(zNewPw);
589 zChngPw = mprintf(
590 "UPDATE user"
591 " SET pw=shared_secret(%Q,%Q,"
592 " (SELECT value FROM config WHERE name='project-code'))"
593 " WHERE login=%Q",
594 zNew1, g.zLogin, g.zLogin
595 );
596 if( login_group_sql(zChngPw, "<p>", "</p>\n", &zErr) ){
 
 
 
597 zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
598 fossil_free(zErr);
599 }else{
600 redirect_to_g();
601 return;
@@ -835,16 +844,18 @@
835 zLogin, zHash
836 );
837 pStmt = 0;
838 rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
839 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
 
840 db_multi_exec(
841 "UPDATE user SET cookie=%Q, cexpire=%.17g"
842 " WHERE login=%Q",
843 zHash,
844 sqlite3_column_double(pStmt, 0), zLogin
845 );
 
846 nXfer++;
847 }
848 sqlite3_finalize(pStmt);
849 }
850 sqlite3_close(pOther);
@@ -1619,11 +1630,13 @@
1619 "INSERT INTO user(login,pw,cap,info,mtime)\n"
1620 "VALUES(%Q,%Q,%Q,"
1621 "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())",
1622 zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr);
1623 fossil_free(zPass);
 
1624 db_multi_exec("%s", blob_sql_text(&sql));
 
1625 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID);
1626 login_set_user_cookie(zUserID, uid, NULL, 0);
1627 if( doAlerts ){
1628 /* Also make the new user a subscriber. */
1629 Blob hdr, body;
@@ -1832,14 +1845,16 @@
1832 while( db_step(&q)==SQLITE_ROW ){
1833 const char *zRepoName = db_column_text(&q, 1);
1834 if( file_size(zRepoName, ExtFILE)<0 ){
1835 /* Silently remove non-existent repositories from the login group. */
1836 const char *zLabel = db_column_text(&q, 0);
 
1837 db_multi_exec(
1838 "DELETE FROM config WHERE name GLOB 'peer-*-%q'",
1839 &zLabel[10]
1840 );
 
1841 continue;
1842 }
1843 rc = sqlite3_open_v2(
1844 zRepoName, &pPeer,
1845 SQLITE_OPEN_READWRITE,
@@ -2004,11 +2019,13 @@
2004 "REPLACE INTO config(name,value,mtime) VALUES('peer-name-%q',%Q,now());"
2005 "REPLACE INTO config(name,value,mtime) VALUES('peer-repo-%q',%Q,now());"
2006 "COMMIT;",
2007 zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
2008 );
 
2009 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
 
2010 fossil_free(zSql);
2011 }
2012
2013 /*
2014 ** Leave the login group that we are currently part of.
@@ -2025,17 +2042,19 @@
2025 " WHERE name='login-group-name'"
2026 " AND (SELECT count(*) FROM config WHERE name GLOB 'peer-*')==0;",
2027 zProjCode
2028 );
2029 fossil_free(zProjCode);
 
2030 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
2031 fossil_free(zSql);
2032 db_multi_exec(
2033 "DELETE FROM config "
2034 " WHERE name GLOB 'peer-*'"
2035 " OR name GLOB 'login-group-*';"
2036 );
 
2037 }
2038
2039 /*
2040 ** COMMAND: login-group*
2041 **
2042
--- src/login.c
+++ src/login.c
@@ -293,13 +293,15 @@
293 if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
294 zCookie = login_gen_user_cookie_value(zUsername, zHash);
295 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(),
296 bSessionCookie ? 0 : expires);
297 record_login_attempt(zUsername, zIpAddr, 1);
298 db_unprotect(PROTECT_USER);
299 db_multi_exec("UPDATE user SET cookie=%Q,"
300 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
301 zHash, expires, uid);
302 db_protect_pop();
303 fossil_free(zHash);
304 if( zDest ){
305 *zDest = zCookie;
306 }else{
307 free(zCookie);
@@ -356,14 +358,16 @@
358 }else{
359 const char *cookie = login_cookie_name();
360 /* To logout, change the cookie value to an empty string */
361 cgi_set_cookie(cookie, "",
362 login_cookie_path(), -86400);
363 db_unprotect(PROTECT_USER);
364 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
365 " cexpire=0 WHERE uid=%d"
366 " AND login NOT IN ('anonymous','nobody',"
367 " 'developer','reader')", g.userUid);
368 db_protect_pop();
369 cgi_replace_parameter(cookie, NULL);
370 cgi_replace_parameter("anon", NULL);
371 }
372 }
373
@@ -580,22 +584,27 @@
584 ;
585 }else{
586 char *zNewPw = sha1_shared_secret(zNew1, g.zLogin, 0);
587 char *zChngPw;
588 char *zErr;
589 int rc;
590
591 db_unprotect(PROTECT_USER);
592 db_multi_exec(
593 "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
594 );
 
595 zChngPw = mprintf(
596 "UPDATE user"
597 " SET pw=shared_secret(%Q,%Q,"
598 " (SELECT value FROM config WHERE name='project-code'))"
599 " WHERE login=%Q",
600 zNew1, g.zLogin, g.zLogin
601 );
602 fossil_free(zNewPw);
603 rc = login_group_sql(zChngPw, "<p>", "</p>\n", &zErr);
604 db_protect_pop();
605 if( rc ){
606 zErrMsg = mprintf("<span class=\"loginError\">%s</span>", zErr);
607 fossil_free(zErr);
608 }else{
609 redirect_to_g();
610 return;
@@ -835,16 +844,18 @@
844 zLogin, zHash
845 );
846 pStmt = 0;
847 rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
848 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
849 db_unprotect(PROTECT_USER);
850 db_multi_exec(
851 "UPDATE user SET cookie=%Q, cexpire=%.17g"
852 " WHERE login=%Q",
853 zHash,
854 sqlite3_column_double(pStmt, 0), zLogin
855 );
856 db_protect_pop();
857 nXfer++;
858 }
859 sqlite3_finalize(pStmt);
860 }
861 sqlite3_close(pOther);
@@ -1619,11 +1630,13 @@
1630 "INSERT INTO user(login,pw,cap,info,mtime)\n"
1631 "VALUES(%Q,%Q,%Q,"
1632 "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())",
1633 zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr);
1634 fossil_free(zPass);
1635 db_unprotect(PROTECT_USER);
1636 db_multi_exec("%s", blob_sql_text(&sql));
1637 db_protect_pop();
1638 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID);
1639 login_set_user_cookie(zUserID, uid, NULL, 0);
1640 if( doAlerts ){
1641 /* Also make the new user a subscriber. */
1642 Blob hdr, body;
@@ -1832,14 +1845,16 @@
1845 while( db_step(&q)==SQLITE_ROW ){
1846 const char *zRepoName = db_column_text(&q, 1);
1847 if( file_size(zRepoName, ExtFILE)<0 ){
1848 /* Silently remove non-existent repositories from the login group. */
1849 const char *zLabel = db_column_text(&q, 0);
1850 db_unprotect(PROTECT_CONFIG);
1851 db_multi_exec(
1852 "DELETE FROM config WHERE name GLOB 'peer-*-%q'",
1853 &zLabel[10]
1854 );
1855 db_protect_pop();
1856 continue;
1857 }
1858 rc = sqlite3_open_v2(
1859 zRepoName, &pPeer,
1860 SQLITE_OPEN_READWRITE,
@@ -2004,11 +2019,13 @@
2019 "REPLACE INTO config(name,value,mtime) VALUES('peer-name-%q',%Q,now());"
2020 "REPLACE INTO config(name,value,mtime) VALUES('peer-repo-%q',%Q,now());"
2021 "COMMIT;",
2022 zSelfProjCode, zSelfLabel, zSelfProjCode, zSelfRepo
2023 );
2024 db_unprotect(PROTECT_CONFIG);
2025 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
2026 db_protect_pop();
2027 fossil_free(zSql);
2028 }
2029
2030 /*
2031 ** Leave the login group that we are currently part of.
@@ -2025,17 +2042,19 @@
2042 " WHERE name='login-group-name'"
2043 " AND (SELECT count(*) FROM config WHERE name GLOB 'peer-*')==0;",
2044 zProjCode
2045 );
2046 fossil_free(zProjCode);
2047 db_unprotect(PROTECT_CONFIG);
2048 login_group_sql(zSql, "<li> ", "</li>", pzErrMsg);
2049 fossil_free(zSql);
2050 db_multi_exec(
2051 "DELETE FROM config "
2052 " WHERE name GLOB 'peer-*'"
2053 " OR name GLOB 'login-group-*';"
2054 );
2055 db_protect_pop();
2056 }
2057
2058 /*
2059 ** COMMAND: login-group*
2060 **
2061
+2
--- src/main.c
+++ src/main.c
@@ -1372,19 +1372,21 @@
13721372
g.zTop = &g.zBaseURL[7+strlen(zHost)];
13731373
g.zHttpsURL = mprintf("https://%s%.*s", zHost, i, zCur);
13741374
}
13751375
}
13761376
if( db_is_writeable("repository") ){
1377
+ db_unprotect(PROTECT_CONFIG);
13771378
if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
13781379
db_multi_exec("INSERT INTO config(name,value,mtime)"
13791380
"VALUES('baseurl:%q',1,now())", g.zBaseURL);
13801381
}else{
13811382
db_optional_sql("repository",
13821383
"REPLACE INTO config(name,value,mtime)"
13831384
"VALUES('baseurl:%q',1,now())", g.zBaseURL
13841385
);
13851386
}
1387
+ db_protect_pop();
13861388
}
13871389
}
13881390
13891391
/*
13901392
** Send an HTTP redirect back to the designated Index Page.
13911393
--- src/main.c
+++ src/main.c
@@ -1372,19 +1372,21 @@
1372 g.zTop = &g.zBaseURL[7+strlen(zHost)];
1373 g.zHttpsURL = mprintf("https://%s%.*s", zHost, i, zCur);
1374 }
1375 }
1376 if( db_is_writeable("repository") ){
 
1377 if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
1378 db_multi_exec("INSERT INTO config(name,value,mtime)"
1379 "VALUES('baseurl:%q',1,now())", g.zBaseURL);
1380 }else{
1381 db_optional_sql("repository",
1382 "REPLACE INTO config(name,value,mtime)"
1383 "VALUES('baseurl:%q',1,now())", g.zBaseURL
1384 );
1385 }
 
1386 }
1387 }
1388
1389 /*
1390 ** Send an HTTP redirect back to the designated Index Page.
1391
--- src/main.c
+++ src/main.c
@@ -1372,19 +1372,21 @@
1372 g.zTop = &g.zBaseURL[7+strlen(zHost)];
1373 g.zHttpsURL = mprintf("https://%s%.*s", zHost, i, zCur);
1374 }
1375 }
1376 if( db_is_writeable("repository") ){
1377 db_unprotect(PROTECT_CONFIG);
1378 if( !db_exists("SELECT 1 FROM config WHERE name='baseurl:%q'", g.zBaseURL)){
1379 db_multi_exec("INSERT INTO config(name,value,mtime)"
1380 "VALUES('baseurl:%q',1,now())", g.zBaseURL);
1381 }else{
1382 db_optional_sql("repository",
1383 "REPLACE INTO config(name,value,mtime)"
1384 "VALUES('baseurl:%q',1,now())", g.zBaseURL
1385 );
1386 }
1387 db_protect_pop();
1388 }
1389 }
1390
1391 /*
1392 ** Send an HTTP redirect back to the designated Index Page.
1393
+2 -1
--- src/mkindex.c
+++ src/mkindex.c
@@ -480,14 +480,15 @@
480480
if( zVar ){
481481
printf(" \"%s\",%*s", zVar, (int)(15-strlen(zVar)), "");
482482
}else{
483483
printf(" 0,%*s", 16, "");
484484
}
485
- printf(" %3d, %d, %d, \"%s\"%*s },\n",
485
+ printf(" %3d, %d, %d, %d, \"%s\"%*s },\n",
486486
aEntry[i].iWidth,
487487
(aEntry[i].eType & CMDFLAG_VERSIONABLE)!=0,
488488
(aEntry[i].eType & CMDFLAG_BLOCKTEXT)!=0,
489
+ (aEntry[i].eType & CMDFLAG_SENSITIVE)!=0,
489490
zDef, (int)(10-strlen(zDef)), ""
490491
);
491492
if( aEntry[i].zIf ){
492493
printf("#endif\n");
493494
}
494495
--- src/mkindex.c
+++ src/mkindex.c
@@ -480,14 +480,15 @@
480 if( zVar ){
481 printf(" \"%s\",%*s", zVar, (int)(15-strlen(zVar)), "");
482 }else{
483 printf(" 0,%*s", 16, "");
484 }
485 printf(" %3d, %d, %d, \"%s\"%*s },\n",
486 aEntry[i].iWidth,
487 (aEntry[i].eType & CMDFLAG_VERSIONABLE)!=0,
488 (aEntry[i].eType & CMDFLAG_BLOCKTEXT)!=0,
 
489 zDef, (int)(10-strlen(zDef)), ""
490 );
491 if( aEntry[i].zIf ){
492 printf("#endif\n");
493 }
494
--- src/mkindex.c
+++ src/mkindex.c
@@ -480,14 +480,15 @@
480 if( zVar ){
481 printf(" \"%s\",%*s", zVar, (int)(15-strlen(zVar)), "");
482 }else{
483 printf(" 0,%*s", 16, "");
484 }
485 printf(" %3d, %d, %d, %d, \"%s\"%*s },\n",
486 aEntry[i].iWidth,
487 (aEntry[i].eType & CMDFLAG_VERSIONABLE)!=0,
488 (aEntry[i].eType & CMDFLAG_BLOCKTEXT)!=0,
489 (aEntry[i].eType & CMDFLAG_SENSITIVE)!=0,
490 zDef, (int)(10-strlen(zDef)), ""
491 );
492 if( aEntry[i].zIf ){
493 printf("#endif\n");
494 }
495
--- src/rebuild.c
+++ src/rebuild.c
@@ -52,10 +52,11 @@
5252
}
5353
5454
/* Add the user.mtime column if it is missing. (2011-04-27)
5555
*/
5656
if( !db_table_has_column("repository", "user", "mtime") ){
57
+ db_unprotect(PROTECT_ALL);
5758
db_multi_exec(
5859
"CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
5960
"DROP TABLE user;"
6061
"CREATE TABLE user(\n"
6162
" uid INTEGER PRIMARY KEY,\n"
@@ -72,19 +73,22 @@
7273
"INSERT OR IGNORE INTO user"
7374
" SELECT uid, login, pw, cap, cookie,"
7475
" ipaddr, cexpire, info, now(), photo FROM temp_user;"
7576
"DROP TABLE temp_user;"
7677
);
78
+ db_protect_pop();
7779
}
7880
7981
/* Add the config.mtime column if it is missing. (2011-04-27)
8082
*/
8183
if( !db_table_has_column("repository", "config", "mtime") ){
84
+ db_unprotect(PROTECT_CONFIG);
8285
db_multi_exec(
8386
"ALTER TABLE config ADD COLUMN mtime INTEGER;"
8487
"UPDATE config SET mtime=now();"
8588
);
89
+ db_protect_pop();
8690
}
8791
8892
/* Add the shun.mtime and shun.scom columns if they are missing.
8993
** (2011-04-27)
9094
*/
@@ -382,10 +386,11 @@
382386
percent_complete(0);
383387
}
384388
alert_triggers_disable();
385389
rebuild_update_schema();
386390
blob_init(&sql, 0, 0);
391
+ db_unprotect(PROTECT_ALL);
387392
db_prepare(&q,
388393
"SELECT name FROM sqlite_schema /*scan*/"
389394
" WHERE type='table'"
390395
" AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
391396
"'config','shun','private','reportfmt',"
@@ -475,10 +480,11 @@
475480
alert_triggers_enable();
476481
if(!g.fQuiet && ttyOutput ){
477482
percent_complete(1000);
478483
fossil_print("\n");
479484
}
485
+ db_protect_pop();
480486
return errCnt;
481487
}
482488
483489
/*
484490
** Number of neighbors to search
@@ -667,10 +673,11 @@
667673
668674
/* We should be done with options.. */
669675
verify_all_options();
670676
671677
db_begin_transaction();
678
+ db_unprotect(PROTECT_ALL);
672679
if( !compressOnlyFlag ){
673680
search_drop_index();
674681
ttyOutput = 1;
675682
errCnt = rebuild_db(randomizeFlag, 1, doClustering);
676683
reconstruct_private_table();
@@ -720,10 +727,11 @@
720727
if( activateWal ){
721728
db_multi_exec("PRAGMA journal_mode=WAL;");
722729
}
723730
}
724731
if( runReindex ) search_rebuild_index();
732
+ db_protect_pop();
725733
if( showStats ){
726734
static const struct { int idx; const char *zLabel; } aStat[] = {
727735
{ CFTYPE_ANY, "Artifacts:" },
728736
{ CFTYPE_MANIFEST, "Manifests:" },
729737
{ CFTYPE_CLUSTER, "Clusters:" },
@@ -755,18 +763,20 @@
755763
** testing by cloning a working project repository.
756764
*/
757765
void test_detach_cmd(void){
758766
db_find_and_open_repository(0, 2);
759767
db_begin_transaction();
768
+ db_unprotect(PROTECT_CONFIG);
760769
db_multi_exec(
761770
"DELETE FROM config WHERE name GLOB 'last-sync-*';"
762771
"DELETE FROM config WHERE name GLOB 'sync-*:*';"
763772
"UPDATE config SET value=lower(hex(randomblob(20)))"
764773
" WHERE name='project-code';"
765774
"UPDATE config SET value='detached-' || value"
766775
" WHERE name='project-name' AND value NOT GLOB 'detached-*';"
767776
);
777
+ db_protect_pop();
768778
db_end_transaction(0);
769779
}
770780
771781
/*
772782
** COMMAND: test-create-clusters
@@ -910,10 +920,11 @@
910920
if( privateOnly || bVerily ){
911921
bNeedRebuild = db_exists("SELECT 1 FROM private");
912922
delete_private_content();
913923
}
914924
if( !privateOnly ){
925
+ db_unprotect(PROTECT_ALL);
915926
db_multi_exec(
916927
"UPDATE user SET pw='';"
917928
"DELETE FROM config WHERE name GLOB 'last-sync-*';"
918929
"DELETE FROM config WHERE name GLOB 'sync-*:*';"
919930
"DELETE FROM config WHERE name GLOB 'peer-*';"
@@ -933,14 +944,17 @@
933944
"DROP TABLE IF EXISTS purgeitem;\n"
934945
"DROP TABLE IF EXISTS admin_log;\n"
935946
"DROP TABLE IF EXISTS vcache;\n"
936947
);
937948
}
949
+ db_protect_pop();
938950
}
939951
if( !bNeedRebuild ){
940952
db_end_transaction(0);
953
+ db_unprotect(PROTECT_ALL);
941954
db_multi_exec("VACUUM;");
955
+ db_protect_pop();
942956
}else{
943957
rebuild_db(0, 1, 0);
944958
db_end_transaction(0);
945959
}
946960
}
947961
--- src/rebuild.c
+++ src/rebuild.c
@@ -52,10 +52,11 @@
52 }
53
54 /* Add the user.mtime column if it is missing. (2011-04-27)
55 */
56 if( !db_table_has_column("repository", "user", "mtime") ){
 
57 db_multi_exec(
58 "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
59 "DROP TABLE user;"
60 "CREATE TABLE user(\n"
61 " uid INTEGER PRIMARY KEY,\n"
@@ -72,19 +73,22 @@
72 "INSERT OR IGNORE INTO user"
73 " SELECT uid, login, pw, cap, cookie,"
74 " ipaddr, cexpire, info, now(), photo FROM temp_user;"
75 "DROP TABLE temp_user;"
76 );
 
77 }
78
79 /* Add the config.mtime column if it is missing. (2011-04-27)
80 */
81 if( !db_table_has_column("repository", "config", "mtime") ){
 
82 db_multi_exec(
83 "ALTER TABLE config ADD COLUMN mtime INTEGER;"
84 "UPDATE config SET mtime=now();"
85 );
 
86 }
87
88 /* Add the shun.mtime and shun.scom columns if they are missing.
89 ** (2011-04-27)
90 */
@@ -382,10 +386,11 @@
382 percent_complete(0);
383 }
384 alert_triggers_disable();
385 rebuild_update_schema();
386 blob_init(&sql, 0, 0);
 
387 db_prepare(&q,
388 "SELECT name FROM sqlite_schema /*scan*/"
389 " WHERE type='table'"
390 " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
391 "'config','shun','private','reportfmt',"
@@ -475,10 +480,11 @@
475 alert_triggers_enable();
476 if(!g.fQuiet && ttyOutput ){
477 percent_complete(1000);
478 fossil_print("\n");
479 }
 
480 return errCnt;
481 }
482
483 /*
484 ** Number of neighbors to search
@@ -667,10 +673,11 @@
667
668 /* We should be done with options.. */
669 verify_all_options();
670
671 db_begin_transaction();
 
672 if( !compressOnlyFlag ){
673 search_drop_index();
674 ttyOutput = 1;
675 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
676 reconstruct_private_table();
@@ -720,10 +727,11 @@
720 if( activateWal ){
721 db_multi_exec("PRAGMA journal_mode=WAL;");
722 }
723 }
724 if( runReindex ) search_rebuild_index();
 
725 if( showStats ){
726 static const struct { int idx; const char *zLabel; } aStat[] = {
727 { CFTYPE_ANY, "Artifacts:" },
728 { CFTYPE_MANIFEST, "Manifests:" },
729 { CFTYPE_CLUSTER, "Clusters:" },
@@ -755,18 +763,20 @@
755 ** testing by cloning a working project repository.
756 */
757 void test_detach_cmd(void){
758 db_find_and_open_repository(0, 2);
759 db_begin_transaction();
 
760 db_multi_exec(
761 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
762 "DELETE FROM config WHERE name GLOB 'sync-*:*';"
763 "UPDATE config SET value=lower(hex(randomblob(20)))"
764 " WHERE name='project-code';"
765 "UPDATE config SET value='detached-' || value"
766 " WHERE name='project-name' AND value NOT GLOB 'detached-*';"
767 );
 
768 db_end_transaction(0);
769 }
770
771 /*
772 ** COMMAND: test-create-clusters
@@ -910,10 +920,11 @@
910 if( privateOnly || bVerily ){
911 bNeedRebuild = db_exists("SELECT 1 FROM private");
912 delete_private_content();
913 }
914 if( !privateOnly ){
 
915 db_multi_exec(
916 "UPDATE user SET pw='';"
917 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
918 "DELETE FROM config WHERE name GLOB 'sync-*:*';"
919 "DELETE FROM config WHERE name GLOB 'peer-*';"
@@ -933,14 +944,17 @@
933 "DROP TABLE IF EXISTS purgeitem;\n"
934 "DROP TABLE IF EXISTS admin_log;\n"
935 "DROP TABLE IF EXISTS vcache;\n"
936 );
937 }
 
938 }
939 if( !bNeedRebuild ){
940 db_end_transaction(0);
 
941 db_multi_exec("VACUUM;");
 
942 }else{
943 rebuild_db(0, 1, 0);
944 db_end_transaction(0);
945 }
946 }
947
--- src/rebuild.c
+++ src/rebuild.c
@@ -52,10 +52,11 @@
52 }
53
54 /* Add the user.mtime column if it is missing. (2011-04-27)
55 */
56 if( !db_table_has_column("repository", "user", "mtime") ){
57 db_unprotect(PROTECT_ALL);
58 db_multi_exec(
59 "CREATE TEMP TABLE temp_user AS SELECT * FROM user;"
60 "DROP TABLE user;"
61 "CREATE TABLE user(\n"
62 " uid INTEGER PRIMARY KEY,\n"
@@ -72,19 +73,22 @@
73 "INSERT OR IGNORE INTO user"
74 " SELECT uid, login, pw, cap, cookie,"
75 " ipaddr, cexpire, info, now(), photo FROM temp_user;"
76 "DROP TABLE temp_user;"
77 );
78 db_protect_pop();
79 }
80
81 /* Add the config.mtime column if it is missing. (2011-04-27)
82 */
83 if( !db_table_has_column("repository", "config", "mtime") ){
84 db_unprotect(PROTECT_CONFIG);
85 db_multi_exec(
86 "ALTER TABLE config ADD COLUMN mtime INTEGER;"
87 "UPDATE config SET mtime=now();"
88 );
89 db_protect_pop();
90 }
91
92 /* Add the shun.mtime and shun.scom columns if they are missing.
93 ** (2011-04-27)
94 */
@@ -382,10 +386,11 @@
386 percent_complete(0);
387 }
388 alert_triggers_disable();
389 rebuild_update_schema();
390 blob_init(&sql, 0, 0);
391 db_unprotect(PROTECT_ALL);
392 db_prepare(&q,
393 "SELECT name FROM sqlite_schema /*scan*/"
394 " WHERE type='table'"
395 " AND name NOT IN ('admin_log', 'blob','delta','rcvfrom','user','alias',"
396 "'config','shun','private','reportfmt',"
@@ -475,10 +480,11 @@
480 alert_triggers_enable();
481 if(!g.fQuiet && ttyOutput ){
482 percent_complete(1000);
483 fossil_print("\n");
484 }
485 db_protect_pop();
486 return errCnt;
487 }
488
489 /*
490 ** Number of neighbors to search
@@ -667,10 +673,11 @@
673
674 /* We should be done with options.. */
675 verify_all_options();
676
677 db_begin_transaction();
678 db_unprotect(PROTECT_ALL);
679 if( !compressOnlyFlag ){
680 search_drop_index();
681 ttyOutput = 1;
682 errCnt = rebuild_db(randomizeFlag, 1, doClustering);
683 reconstruct_private_table();
@@ -720,10 +727,11 @@
727 if( activateWal ){
728 db_multi_exec("PRAGMA journal_mode=WAL;");
729 }
730 }
731 if( runReindex ) search_rebuild_index();
732 db_protect_pop();
733 if( showStats ){
734 static const struct { int idx; const char *zLabel; } aStat[] = {
735 { CFTYPE_ANY, "Artifacts:" },
736 { CFTYPE_MANIFEST, "Manifests:" },
737 { CFTYPE_CLUSTER, "Clusters:" },
@@ -755,18 +763,20 @@
763 ** testing by cloning a working project repository.
764 */
765 void test_detach_cmd(void){
766 db_find_and_open_repository(0, 2);
767 db_begin_transaction();
768 db_unprotect(PROTECT_CONFIG);
769 db_multi_exec(
770 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
771 "DELETE FROM config WHERE name GLOB 'sync-*:*';"
772 "UPDATE config SET value=lower(hex(randomblob(20)))"
773 " WHERE name='project-code';"
774 "UPDATE config SET value='detached-' || value"
775 " WHERE name='project-name' AND value NOT GLOB 'detached-*';"
776 );
777 db_protect_pop();
778 db_end_transaction(0);
779 }
780
781 /*
782 ** COMMAND: test-create-clusters
@@ -910,10 +920,11 @@
920 if( privateOnly || bVerily ){
921 bNeedRebuild = db_exists("SELECT 1 FROM private");
922 delete_private_content();
923 }
924 if( !privateOnly ){
925 db_unprotect(PROTECT_ALL);
926 db_multi_exec(
927 "UPDATE user SET pw='';"
928 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
929 "DELETE FROM config WHERE name GLOB 'sync-*:*';"
930 "DELETE FROM config WHERE name GLOB 'peer-*';"
@@ -933,14 +944,17 @@
944 "DROP TABLE IF EXISTS purgeitem;\n"
945 "DROP TABLE IF EXISTS admin_log;\n"
946 "DROP TABLE IF EXISTS vcache;\n"
947 );
948 }
949 db_protect_pop();
950 }
951 if( !bNeedRebuild ){
952 db_end_transaction(0);
953 db_unprotect(PROTECT_ALL);
954 db_multi_exec("VACUUM;");
955 db_protect_pop();
956 }else{
957 rebuild_db(0, 1, 0);
958 db_end_transaction(0);
959 }
960 }
961
--- src/security_audit.c
+++ src/security_audit.c
@@ -596,15 +596,17 @@
596596
if( P("cancel") ){
597597
/* User pressed the cancel button. Go back */
598598
cgi_redirect("secaudit0");
599599
}
600600
if( P("apply") ){
601
+ db_unprotect(PROTECT_USER);
601602
db_multi_exec(
602603
"UPDATE user SET cap=''"
603604
" WHERE login IN ('nobody','anonymous');"
604605
"DELETE FROM config WHERE name='public-pages';"
605606
);
607
+ db_protect_pop();
606608
db_set("self-register","0",0);
607609
cgi_redirect("secaudit0");
608610
}
609611
style_header("Make This Website Private");
610612
@ <p>Click the "Make It Private" button below to disable all
611613
--- src/security_audit.c
+++ src/security_audit.c
@@ -596,15 +596,17 @@
596 if( P("cancel") ){
597 /* User pressed the cancel button. Go back */
598 cgi_redirect("secaudit0");
599 }
600 if( P("apply") ){
 
601 db_multi_exec(
602 "UPDATE user SET cap=''"
603 " WHERE login IN ('nobody','anonymous');"
604 "DELETE FROM config WHERE name='public-pages';"
605 );
 
606 db_set("self-register","0",0);
607 cgi_redirect("secaudit0");
608 }
609 style_header("Make This Website Private");
610 @ <p>Click the "Make It Private" button below to disable all
611
--- src/security_audit.c
+++ src/security_audit.c
@@ -596,15 +596,17 @@
596 if( P("cancel") ){
597 /* User pressed the cancel button. Go back */
598 cgi_redirect("secaudit0");
599 }
600 if( P("apply") ){
601 db_unprotect(PROTECT_USER);
602 db_multi_exec(
603 "UPDATE user SET cap=''"
604 " WHERE login IN ('nobody','anonymous');"
605 "DELETE FROM config WHERE name='public-pages';"
606 );
607 db_protect_pop();
608 db_set("self-register","0",0);
609 cgi_redirect("secaudit0");
610 }
611 style_header("Make This Website Private");
612 @ <p>Click the "Make It Private" button below to disable all
613
+16
--- src/setup.c
+++ src/setup.c
@@ -27,14 +27,16 @@
2727
*/
2828
void setup_incr_cfgcnt(void){
2929
static int once = 1;
3030
if( once ){
3131
once = 0;
32
+ db_unprotect(PROTECT_CONFIG);
3233
db_multi_exec("UPDATE config SET value=value+1 WHERE name='cfgcnt'");
3334
if( db_changes()==0 ){
3435
db_multi_exec("INSERT INTO config(name,value) VALUES('cfgcnt',1)");
3536
}
37
+ db_protect_pop();
3638
}
3739
}
3840
3941
/*
4042
** Output a single entry for a menu generated using an HTML table.
@@ -1157,11 +1159,13 @@
11571159
login_needed(0);
11581160
return;
11591161
}
11601162
db_begin_transaction();
11611163
if( P("clear")!=0 && cgi_csrf_safe(1) ){
1164
+ db_unprotect(PROTECT_CONFIG);
11621165
db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
1166
+ db_protect_pop();
11631167
cgi_replace_parameter("adunit","");
11641168
cgi_replace_parameter("adright","");
11651169
setup_incr_cfgcnt();
11661170
}
11671171
@@ -1255,10 +1259,11 @@
12551259
if( !g.perm.Admin ){
12561260
login_needed(0);
12571261
return;
12581262
}
12591263
db_begin_transaction();
1264
+ db_unprotect(PROTECT_CONFIG);
12601265
if( !cgi_csrf_safe(1) ){
12611266
/* Allow no state changes if not safe from CSRF */
12621267
}else if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
12631268
Blob img;
12641269
Stmt ins;
@@ -1285,10 +1290,11 @@
12851290
cgi_redirect("setup_logo");
12861291
}else if( P("setbg")!=0 && zBgMime && zBgMime[0] && szBgImg>0 ){
12871292
Blob img;
12881293
Stmt ins;
12891294
blob_init(&img, aBgImg, szBgImg);
1295
+ db_unprotect(PROTECT_CONFIG);
12901296
db_prepare(&ins,
12911297
"REPLACE INTO config(name,value,mtime)"
12921298
" VALUES('background-image',:bytes,now())"
12931299
);
12941300
db_bind_blob(&ins, ":bytes", &img);
@@ -1297,13 +1303,15 @@
12971303
db_multi_exec(
12981304
"REPLACE INTO config(name,value,mtime)"
12991305
" VALUES('background-mimetype',%Q,now())",
13001306
zBgMime
13011307
);
1308
+ db_protect_pop();
13021309
db_end_transaction(0);
13031310
cgi_redirect("setup_logo");
13041311
}else if( P("clrbg")!=0 ){
1312
+ db_unprotect(PROTECT_CONFIG);
13051313
db_multi_exec(
13061314
"DELETE FROM config WHERE name IN "
13071315
"('background-image','background-mimetype')"
13081316
);
13091317
db_end_transaction(0);
@@ -1310,10 +1318,11 @@
13101318
cgi_redirect("setup_logo");
13111319
}else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){
13121320
Blob img;
13131321
Stmt ins;
13141322
blob_init(&img, aIconImg, szIconImg);
1323
+ db_unprotect(PROTECT_CONFIG);
13151324
db_prepare(&ins,
13161325
"REPLACE INTO config(name,value,mtime)"
13171326
" VALUES('icon-image',:bytes,now())"
13181327
);
13191328
db_bind_blob(&ins, ":bytes", &img);
@@ -1322,10 +1331,11 @@
13221331
db_multi_exec(
13231332
"REPLACE INTO config(name,value,mtime)"
13241333
" VALUES('icon-mimetype',%Q,now())",
13251334
zIconMime
13261335
);
1336
+ db_protect_pop();
13271337
db_end_transaction(0);
13281338
cgi_redirect("setup_logo");
13291339
}else if( P("clricon")!=0 ){
13301340
db_multi_exec(
13311341
"DELETE FROM config WHERE name IN "
@@ -1781,22 +1791,27 @@
17811791
const char *zValue
17821792
){
17831793
if( !cgi_csrf_safe(1) ) return;
17841794
if( zNewName[0]==0 || zValue[0]==0 ){
17851795
if( zOldName[0] ){
1796
+ db_unprotect(PROTECT_CONFIG);
17861797
blob_append_sql(pSql,
17871798
"DELETE FROM config WHERE name='walias:%q';\n",
17881799
zOldName);
1800
+ db_protect_pop();
17891801
}
17901802
return;
17911803
}
17921804
if( zOldName[0]==0 ){
1805
+ db_unprotect(PROTECT_CONFIG);
17931806
blob_append_sql(pSql,
17941807
"INSERT INTO config(name,value,mtime) VALUES('walias:%q',%Q,now());\n",
17951808
zNewName, zValue);
1809
+ db_protect_pop();
17961810
return;
17971811
}
1812
+ db_unprotect(PROTECT_CONFIG);
17981813
if( strcmp(zOldName, zNewName)!=0 ){
17991814
blob_append_sql(pSql,
18001815
"UPDATE config SET name='walias:%q', value=%Q, mtime=now()"
18011816
" WHERE name='walias:%q';\n",
18021817
zNewName, zValue, zOldName);
@@ -1804,10 +1819,11 @@
18041819
blob_append_sql(pSql,
18051820
"UPDATE config SET value=%Q, mtime=now()"
18061821
" WHERE name='walias:%q' AND value<>%Q;\n",
18071822
zValue, zOldName, zValue);
18081823
}
1824
+ db_protect_pop();
18091825
}
18101826
18111827
/*
18121828
** WEBPAGE: waliassetup
18131829
**
18141830
--- src/setup.c
+++ src/setup.c
@@ -27,14 +27,16 @@
27 */
28 void setup_incr_cfgcnt(void){
29 static int once = 1;
30 if( once ){
31 once = 0;
 
32 db_multi_exec("UPDATE config SET value=value+1 WHERE name='cfgcnt'");
33 if( db_changes()==0 ){
34 db_multi_exec("INSERT INTO config(name,value) VALUES('cfgcnt',1)");
35 }
 
36 }
37 }
38
39 /*
40 ** Output a single entry for a menu generated using an HTML table.
@@ -1157,11 +1159,13 @@
1157 login_needed(0);
1158 return;
1159 }
1160 db_begin_transaction();
1161 if( P("clear")!=0 && cgi_csrf_safe(1) ){
 
1162 db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
 
1163 cgi_replace_parameter("adunit","");
1164 cgi_replace_parameter("adright","");
1165 setup_incr_cfgcnt();
1166 }
1167
@@ -1255,10 +1259,11 @@
1255 if( !g.perm.Admin ){
1256 login_needed(0);
1257 return;
1258 }
1259 db_begin_transaction();
 
1260 if( !cgi_csrf_safe(1) ){
1261 /* Allow no state changes if not safe from CSRF */
1262 }else if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
1263 Blob img;
1264 Stmt ins;
@@ -1285,10 +1290,11 @@
1285 cgi_redirect("setup_logo");
1286 }else if( P("setbg")!=0 && zBgMime && zBgMime[0] && szBgImg>0 ){
1287 Blob img;
1288 Stmt ins;
1289 blob_init(&img, aBgImg, szBgImg);
 
1290 db_prepare(&ins,
1291 "REPLACE INTO config(name,value,mtime)"
1292 " VALUES('background-image',:bytes,now())"
1293 );
1294 db_bind_blob(&ins, ":bytes", &img);
@@ -1297,13 +1303,15 @@
1297 db_multi_exec(
1298 "REPLACE INTO config(name,value,mtime)"
1299 " VALUES('background-mimetype',%Q,now())",
1300 zBgMime
1301 );
 
1302 db_end_transaction(0);
1303 cgi_redirect("setup_logo");
1304 }else if( P("clrbg")!=0 ){
 
1305 db_multi_exec(
1306 "DELETE FROM config WHERE name IN "
1307 "('background-image','background-mimetype')"
1308 );
1309 db_end_transaction(0);
@@ -1310,10 +1318,11 @@
1310 cgi_redirect("setup_logo");
1311 }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){
1312 Blob img;
1313 Stmt ins;
1314 blob_init(&img, aIconImg, szIconImg);
 
1315 db_prepare(&ins,
1316 "REPLACE INTO config(name,value,mtime)"
1317 " VALUES('icon-image',:bytes,now())"
1318 );
1319 db_bind_blob(&ins, ":bytes", &img);
@@ -1322,10 +1331,11 @@
1322 db_multi_exec(
1323 "REPLACE INTO config(name,value,mtime)"
1324 " VALUES('icon-mimetype',%Q,now())",
1325 zIconMime
1326 );
 
1327 db_end_transaction(0);
1328 cgi_redirect("setup_logo");
1329 }else if( P("clricon")!=0 ){
1330 db_multi_exec(
1331 "DELETE FROM config WHERE name IN "
@@ -1781,22 +1791,27 @@
1781 const char *zValue
1782 ){
1783 if( !cgi_csrf_safe(1) ) return;
1784 if( zNewName[0]==0 || zValue[0]==0 ){
1785 if( zOldName[0] ){
 
1786 blob_append_sql(pSql,
1787 "DELETE FROM config WHERE name='walias:%q';\n",
1788 zOldName);
 
1789 }
1790 return;
1791 }
1792 if( zOldName[0]==0 ){
 
1793 blob_append_sql(pSql,
1794 "INSERT INTO config(name,value,mtime) VALUES('walias:%q',%Q,now());\n",
1795 zNewName, zValue);
 
1796 return;
1797 }
 
1798 if( strcmp(zOldName, zNewName)!=0 ){
1799 blob_append_sql(pSql,
1800 "UPDATE config SET name='walias:%q', value=%Q, mtime=now()"
1801 " WHERE name='walias:%q';\n",
1802 zNewName, zValue, zOldName);
@@ -1804,10 +1819,11 @@
1804 blob_append_sql(pSql,
1805 "UPDATE config SET value=%Q, mtime=now()"
1806 " WHERE name='walias:%q' AND value<>%Q;\n",
1807 zValue, zOldName, zValue);
1808 }
 
1809 }
1810
1811 /*
1812 ** WEBPAGE: waliassetup
1813 **
1814
--- src/setup.c
+++ src/setup.c
@@ -27,14 +27,16 @@
27 */
28 void setup_incr_cfgcnt(void){
29 static int once = 1;
30 if( once ){
31 once = 0;
32 db_unprotect(PROTECT_CONFIG);
33 db_multi_exec("UPDATE config SET value=value+1 WHERE name='cfgcnt'");
34 if( db_changes()==0 ){
35 db_multi_exec("INSERT INTO config(name,value) VALUES('cfgcnt',1)");
36 }
37 db_protect_pop();
38 }
39 }
40
41 /*
42 ** Output a single entry for a menu generated using an HTML table.
@@ -1157,11 +1159,13 @@
1159 login_needed(0);
1160 return;
1161 }
1162 db_begin_transaction();
1163 if( P("clear")!=0 && cgi_csrf_safe(1) ){
1164 db_unprotect(PROTECT_CONFIG);
1165 db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
1166 db_protect_pop();
1167 cgi_replace_parameter("adunit","");
1168 cgi_replace_parameter("adright","");
1169 setup_incr_cfgcnt();
1170 }
1171
@@ -1255,10 +1259,11 @@
1259 if( !g.perm.Admin ){
1260 login_needed(0);
1261 return;
1262 }
1263 db_begin_transaction();
1264 db_unprotect(PROTECT_CONFIG);
1265 if( !cgi_csrf_safe(1) ){
1266 /* Allow no state changes if not safe from CSRF */
1267 }else if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
1268 Blob img;
1269 Stmt ins;
@@ -1285,10 +1290,11 @@
1290 cgi_redirect("setup_logo");
1291 }else if( P("setbg")!=0 && zBgMime && zBgMime[0] && szBgImg>0 ){
1292 Blob img;
1293 Stmt ins;
1294 blob_init(&img, aBgImg, szBgImg);
1295 db_unprotect(PROTECT_CONFIG);
1296 db_prepare(&ins,
1297 "REPLACE INTO config(name,value,mtime)"
1298 " VALUES('background-image',:bytes,now())"
1299 );
1300 db_bind_blob(&ins, ":bytes", &img);
@@ -1297,13 +1303,15 @@
1303 db_multi_exec(
1304 "REPLACE INTO config(name,value,mtime)"
1305 " VALUES('background-mimetype',%Q,now())",
1306 zBgMime
1307 );
1308 db_protect_pop();
1309 db_end_transaction(0);
1310 cgi_redirect("setup_logo");
1311 }else if( P("clrbg")!=0 ){
1312 db_unprotect(PROTECT_CONFIG);
1313 db_multi_exec(
1314 "DELETE FROM config WHERE name IN "
1315 "('background-image','background-mimetype')"
1316 );
1317 db_end_transaction(0);
@@ -1310,10 +1318,11 @@
1318 cgi_redirect("setup_logo");
1319 }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){
1320 Blob img;
1321 Stmt ins;
1322 blob_init(&img, aIconImg, szIconImg);
1323 db_unprotect(PROTECT_CONFIG);
1324 db_prepare(&ins,
1325 "REPLACE INTO config(name,value,mtime)"
1326 " VALUES('icon-image',:bytes,now())"
1327 );
1328 db_bind_blob(&ins, ":bytes", &img);
@@ -1322,10 +1331,11 @@
1331 db_multi_exec(
1332 "REPLACE INTO config(name,value,mtime)"
1333 " VALUES('icon-mimetype',%Q,now())",
1334 zIconMime
1335 );
1336 db_protect_pop();
1337 db_end_transaction(0);
1338 cgi_redirect("setup_logo");
1339 }else if( P("clricon")!=0 ){
1340 db_multi_exec(
1341 "DELETE FROM config WHERE name IN "
@@ -1781,22 +1791,27 @@
1791 const char *zValue
1792 ){
1793 if( !cgi_csrf_safe(1) ) return;
1794 if( zNewName[0]==0 || zValue[0]==0 ){
1795 if( zOldName[0] ){
1796 db_unprotect(PROTECT_CONFIG);
1797 blob_append_sql(pSql,
1798 "DELETE FROM config WHERE name='walias:%q';\n",
1799 zOldName);
1800 db_protect_pop();
1801 }
1802 return;
1803 }
1804 if( zOldName[0]==0 ){
1805 db_unprotect(PROTECT_CONFIG);
1806 blob_append_sql(pSql,
1807 "INSERT INTO config(name,value,mtime) VALUES('walias:%q',%Q,now());\n",
1808 zNewName, zValue);
1809 db_protect_pop();
1810 return;
1811 }
1812 db_unprotect(PROTECT_CONFIG);
1813 if( strcmp(zOldName, zNewName)!=0 ){
1814 blob_append_sql(pSql,
1815 "UPDATE config SET name='walias:%q', value=%Q, mtime=now()"
1816 " WHERE name='walias:%q';\n",
1817 zNewName, zValue, zOldName);
@@ -1804,10 +1819,11 @@
1819 blob_append_sql(pSql,
1820 "UPDATE config SET value=%Q, mtime=now()"
1821 " WHERE name='walias:%q' AND value<>%Q;\n",
1822 zValue, zOldName, zValue);
1823 }
1824 db_protect_pop();
1825 }
1826
1827 /*
1828 ** WEBPAGE: waliassetup
1829 **
1830
--- src/setupuser.c
+++ src/setupuser.c
@@ -315,11 +315,13 @@
315315
/* Check for requests to delete the user */
316316
if( P("delete") && cgi_csrf_safe(1) ){
317317
int n;
318318
if( P("verifydelete") ){
319319
/* Verified delete user request */
320
+ db_unprotect(PROTECT_USER);
320321
db_multi_exec("DELETE FROM user WHERE uid=%d", uid);
322
+ db_protect_pop();
321323
moderation_disapprove_for_missing_users();
322324
admin_log("Deleted user [%s] (uid %d).",
323325
PD("login","???")/*safe-for-%s*/, uid);
324326
cgi_redirect(cgi_referer("setup_ulist"));
325327
return;
@@ -401,15 +403,17 @@
401403
@ [Bummer]</a></p>
402404
style_footer();
403405
return;
404406
}
405407
login_verify_csrf_secret();
408
+ db_unprotect(PROTECT_USER);
406409
db_multi_exec(
407410
"REPLACE INTO user(uid,login,info,pw,cap,mtime) "
408411
"VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
409412
uid, zLogin, P("info"), zPw, zCap
410413
);
414
+ db_protect_pop();
411415
setup_incr_cfgcnt();
412416
admin_log( "Updated user [%q] with capabilities [%q].",
413417
zLogin, zCap );
414418
if( atoi(PD("all","0"))>0 ){
415419
Blob sql;
@@ -432,11 +436,13 @@
432436
" mtime=now()"
433437
" WHERE login=%Q;",
434438
zLogin, P("pw"), zLogin, P("info"), zCap,
435439
zOldLogin
436440
);
441
+ db_unprotect(PROTECT_USER);
437442
login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
443
+ db_protect_pop();
438444
blob_reset(&sql);
439445
admin_log( "Updated user [%q] in all login groups "
440446
"with capabilities [%q].",
441447
zLogin, zCap );
442448
if( zErr ){
443449
--- src/setupuser.c
+++ src/setupuser.c
@@ -315,11 +315,13 @@
315 /* Check for requests to delete the user */
316 if( P("delete") && cgi_csrf_safe(1) ){
317 int n;
318 if( P("verifydelete") ){
319 /* Verified delete user request */
 
320 db_multi_exec("DELETE FROM user WHERE uid=%d", uid);
 
321 moderation_disapprove_for_missing_users();
322 admin_log("Deleted user [%s] (uid %d).",
323 PD("login","???")/*safe-for-%s*/, uid);
324 cgi_redirect(cgi_referer("setup_ulist"));
325 return;
@@ -401,15 +403,17 @@
401 @ [Bummer]</a></p>
402 style_footer();
403 return;
404 }
405 login_verify_csrf_secret();
 
406 db_multi_exec(
407 "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
408 "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
409 uid, zLogin, P("info"), zPw, zCap
410 );
 
411 setup_incr_cfgcnt();
412 admin_log( "Updated user [%q] with capabilities [%q].",
413 zLogin, zCap );
414 if( atoi(PD("all","0"))>0 ){
415 Blob sql;
@@ -432,11 +436,13 @@
432 " mtime=now()"
433 " WHERE login=%Q;",
434 zLogin, P("pw"), zLogin, P("info"), zCap,
435 zOldLogin
436 );
 
437 login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
 
438 blob_reset(&sql);
439 admin_log( "Updated user [%q] in all login groups "
440 "with capabilities [%q].",
441 zLogin, zCap );
442 if( zErr ){
443
--- src/setupuser.c
+++ src/setupuser.c
@@ -315,11 +315,13 @@
315 /* Check for requests to delete the user */
316 if( P("delete") && cgi_csrf_safe(1) ){
317 int n;
318 if( P("verifydelete") ){
319 /* Verified delete user request */
320 db_unprotect(PROTECT_USER);
321 db_multi_exec("DELETE FROM user WHERE uid=%d", uid);
322 db_protect_pop();
323 moderation_disapprove_for_missing_users();
324 admin_log("Deleted user [%s] (uid %d).",
325 PD("login","???")/*safe-for-%s*/, uid);
326 cgi_redirect(cgi_referer("setup_ulist"));
327 return;
@@ -401,15 +403,17 @@
403 @ [Bummer]</a></p>
404 style_footer();
405 return;
406 }
407 login_verify_csrf_secret();
408 db_unprotect(PROTECT_USER);
409 db_multi_exec(
410 "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
411 "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
412 uid, zLogin, P("info"), zPw, zCap
413 );
414 db_protect_pop();
415 setup_incr_cfgcnt();
416 admin_log( "Updated user [%q] with capabilities [%q].",
417 zLogin, zCap );
418 if( atoi(PD("all","0"))>0 ){
419 Blob sql;
@@ -432,11 +436,13 @@
436 " mtime=now()"
437 " WHERE login=%Q;",
438 zLogin, P("pw"), zLogin, P("info"), zCap,
439 zOldLogin
440 );
441 db_unprotect(PROTECT_USER);
442 login_group_sql(blob_str(&sql), "<li> ", " </li>\n", &zErr);
443 db_protect_pop();
444 blob_reset(&sql);
445 admin_log( "Updated user [%q] in all login groups "
446 "with capabilities [%q].",
447 zLogin, zCap );
448 if( zErr ){
449
+14
--- src/skins.c
+++ src/skins.c
@@ -360,14 +360,16 @@
360360
zLabel = mprintf("skins/default/%s.txt", azSkinFile[i]);
361361
z = builtin_text(zLabel);
362362
fossil_free(zLabel);
363363
}
364364
}
365
+ db_unprotect(PROTECT_CONFIG);
365366
blob_appendf(&val,
366367
"REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n",
367368
azSkinFile[i], z
368369
);
370
+ db_protect_pop();
369371
}
370372
return blob_str(&val);
371373
}
372374
373375
/*
@@ -402,14 +404,16 @@
402404
login_insert_csrf_secret();
403405
@ </div></form>
404406
style_footer();
405407
return 1;
406408
}
409
+ db_unprotect(PROTECT_CONFIG);
407410
db_multi_exec(
408411
"UPDATE config SET name='skin:%q' WHERE name='skin:%q';",
409412
zNewName, zOldName
410413
);
414
+ db_protect_pop();
411415
return 0;
412416
}
413417
414418
/*
415419
** Respond to a Save button press. Return TRUE if a dialog was painted.
@@ -440,15 +444,17 @@
440444
login_insert_csrf_secret();
441445
@ </div></form>
442446
style_footer();
443447
return 1;
444448
}
449
+ db_unprotect(PROTECT_CONFIG);
445450
db_multi_exec(
446451
"INSERT OR IGNORE INTO config(name, value, mtime)"
447452
"VALUES('skin:%q',%Q,now())",
448453
zNewName, zCurrent
449454
);
455
+ db_protect_pop();
450456
return 0;
451457
}
452458
453459
/*
454460
** WEBPAGE: setup_skin_admin
@@ -491,16 +497,20 @@
491497
style_footer();
492498
db_end_transaction(1);
493499
return;
494500
}
495501
if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
502
+ db_unprotect(PROTECT_CONFIG);
496503
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
504
+ db_protect_pop();
497505
}
498506
if( P("draftdel")!=0 ){
499507
const char *zDraft = P("name");
500508
if( sqlite3_strglob("draft[1-9]",zDraft)==0 ){
509
+ db_unprotect(PROTECT_CONFIG);
501510
db_multi_exec("DELETE FROM config WHERE name GLOB '%q-*'", zDraft);
511
+ db_protect_pop();
502512
}
503513
}
504514
if( skinRename() || skinSave(zCurrent) ){
505515
db_end_transaction(0);
506516
return;
@@ -521,15 +531,17 @@
521531
}
522532
if( !seen ){
523533
seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
524534
" AND value=%Q", zCurrent);
525535
if( !seen ){
536
+ db_unprotect(PROTECT_CONFIG);
526537
db_multi_exec(
527538
"INSERT INTO config(name,value,mtime) VALUES("
528539
" strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
529540
" %Q,now())", zCurrent
530541
);
542
+ db_protect_pop();
531543
}
532544
}
533545
seen = 0;
534546
for(i=0; i<count(aBuiltinSkin); i++){
535547
if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
@@ -867,15 +879,17 @@
867879
if( !seen ){
868880
seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
869881
" AND value=%Q", zCurrent);
870882
}
871883
if( !seen ){
884
+ db_unprotect(PROTECT_CONFIG);
872885
db_multi_exec(
873886
"INSERT INTO config(name,value,mtime) VALUES("
874887
" strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
875888
" %Q,now())", zCurrent
876889
);
890
+ db_protect_pop();
877891
}
878892
879893
/* Publish draft iSkin */
880894
for(i=0; i<count(azSkinFile); i++){
881895
char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
882896
--- src/skins.c
+++ src/skins.c
@@ -360,14 +360,16 @@
360 zLabel = mprintf("skins/default/%s.txt", azSkinFile[i]);
361 z = builtin_text(zLabel);
362 fossil_free(zLabel);
363 }
364 }
 
365 blob_appendf(&val,
366 "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n",
367 azSkinFile[i], z
368 );
 
369 }
370 return blob_str(&val);
371 }
372
373 /*
@@ -402,14 +404,16 @@
402 login_insert_csrf_secret();
403 @ </div></form>
404 style_footer();
405 return 1;
406 }
 
407 db_multi_exec(
408 "UPDATE config SET name='skin:%q' WHERE name='skin:%q';",
409 zNewName, zOldName
410 );
 
411 return 0;
412 }
413
414 /*
415 ** Respond to a Save button press. Return TRUE if a dialog was painted.
@@ -440,15 +444,17 @@
440 login_insert_csrf_secret();
441 @ </div></form>
442 style_footer();
443 return 1;
444 }
 
445 db_multi_exec(
446 "INSERT OR IGNORE INTO config(name, value, mtime)"
447 "VALUES('skin:%q',%Q,now())",
448 zNewName, zCurrent
449 );
 
450 return 0;
451 }
452
453 /*
454 ** WEBPAGE: setup_skin_admin
@@ -491,16 +497,20 @@
491 style_footer();
492 db_end_transaction(1);
493 return;
494 }
495 if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
 
496 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
 
497 }
498 if( P("draftdel")!=0 ){
499 const char *zDraft = P("name");
500 if( sqlite3_strglob("draft[1-9]",zDraft)==0 ){
 
501 db_multi_exec("DELETE FROM config WHERE name GLOB '%q-*'", zDraft);
 
502 }
503 }
504 if( skinRename() || skinSave(zCurrent) ){
505 db_end_transaction(0);
506 return;
@@ -521,15 +531,17 @@
521 }
522 if( !seen ){
523 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
524 " AND value=%Q", zCurrent);
525 if( !seen ){
 
526 db_multi_exec(
527 "INSERT INTO config(name,value,mtime) VALUES("
528 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
529 " %Q,now())", zCurrent
530 );
 
531 }
532 }
533 seen = 0;
534 for(i=0; i<count(aBuiltinSkin); i++){
535 if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
@@ -867,15 +879,17 @@
867 if( !seen ){
868 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
869 " AND value=%Q", zCurrent);
870 }
871 if( !seen ){
 
872 db_multi_exec(
873 "INSERT INTO config(name,value,mtime) VALUES("
874 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
875 " %Q,now())", zCurrent
876 );
 
877 }
878
879 /* Publish draft iSkin */
880 for(i=0; i<count(azSkinFile); i++){
881 char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
882
--- src/skins.c
+++ src/skins.c
@@ -360,14 +360,16 @@
360 zLabel = mprintf("skins/default/%s.txt", azSkinFile[i]);
361 z = builtin_text(zLabel);
362 fossil_free(zLabel);
363 }
364 }
365 db_unprotect(PROTECT_CONFIG);
366 blob_appendf(&val,
367 "REPLACE INTO config(name,value,mtime) VALUES(%Q,%Q,now());\n",
368 azSkinFile[i], z
369 );
370 db_protect_pop();
371 }
372 return blob_str(&val);
373 }
374
375 /*
@@ -402,14 +404,16 @@
404 login_insert_csrf_secret();
405 @ </div></form>
406 style_footer();
407 return 1;
408 }
409 db_unprotect(PROTECT_CONFIG);
410 db_multi_exec(
411 "UPDATE config SET name='skin:%q' WHERE name='skin:%q';",
412 zNewName, zOldName
413 );
414 db_protect_pop();
415 return 0;
416 }
417
418 /*
419 ** Respond to a Save button press. Return TRUE if a dialog was painted.
@@ -440,15 +444,17 @@
444 login_insert_csrf_secret();
445 @ </div></form>
446 style_footer();
447 return 1;
448 }
449 db_unprotect(PROTECT_CONFIG);
450 db_multi_exec(
451 "INSERT OR IGNORE INTO config(name, value, mtime)"
452 "VALUES('skin:%q',%Q,now())",
453 zNewName, zCurrent
454 );
455 db_protect_pop();
456 return 0;
457 }
458
459 /*
460 ** WEBPAGE: setup_skin_admin
@@ -491,16 +497,20 @@
497 style_footer();
498 db_end_transaction(1);
499 return;
500 }
501 if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
502 db_unprotect(PROTECT_CONFIG);
503 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
504 db_protect_pop();
505 }
506 if( P("draftdel")!=0 ){
507 const char *zDraft = P("name");
508 if( sqlite3_strglob("draft[1-9]",zDraft)==0 ){
509 db_unprotect(PROTECT_CONFIG);
510 db_multi_exec("DELETE FROM config WHERE name GLOB '%q-*'", zDraft);
511 db_protect_pop();
512 }
513 }
514 if( skinRename() || skinSave(zCurrent) ){
515 db_end_transaction(0);
516 return;
@@ -521,15 +531,17 @@
531 }
532 if( !seen ){
533 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
534 " AND value=%Q", zCurrent);
535 if( !seen ){
536 db_unprotect(PROTECT_CONFIG);
537 db_multi_exec(
538 "INSERT INTO config(name,value,mtime) VALUES("
539 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
540 " %Q,now())", zCurrent
541 );
542 db_protect_pop();
543 }
544 }
545 seen = 0;
546 for(i=0; i<count(aBuiltinSkin); i++){
547 if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
@@ -867,15 +879,17 @@
879 if( !seen ){
880 seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
881 " AND value=%Q", zCurrent);
882 }
883 if( !seen ){
884 db_unprotect(PROTECT_CONFIG);
885 db_multi_exec(
886 "INSERT INTO config(name,value,mtime) VALUES("
887 " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
888 " %Q,now())", zCurrent
889 );
890 db_protect_pop();
891 }
892
893 /* Publish draft iSkin */
894 for(i=0; i<count(azSkinFile); i++){
895 char *zNew = db_get_mprintf("", "draft%d-%s", iSkin, azSkinFile[i]);
896
+6
--- src/sync.c
+++ src/sync.c
@@ -425,13 +425,15 @@
425425
/* fossil remote off
426426
** Forget the last-sync-URL and its password
427427
*/
428428
if( g.argc!=3 ) usage("off");
429429
remote_delete_default:
430
+ db_unprotect(PROTECT_CONFIG);
430431
db_multi_exec(
431432
"DELETE FROM config WHERE name GLOB 'last-sync-*';"
432433
);
434
+ db_protect_pop();
433435
return;
434436
}
435437
if( strncmp(zArg, "list", nArg)==0 || strcmp(zArg,"ls")==0 ){
436438
Stmt q;
437439
if( g.argc!=3 ) usage("list");
@@ -457,10 +459,11 @@
457459
zName = g.argv[3];
458460
zUrl = g.argv[4];
459461
if( strcmp(zName,"default")==0 ) goto remote_add_default;
460462
url_parse_local(zUrl, URL_PROMPT_PW, &x);
461463
db_begin_write();
464
+ db_unprotect(PROTECT_CONFIG);
462465
db_multi_exec(
463466
"REPLACE INTO config(name, value, mtime)"
464467
" VALUES('sync-url:%q',%Q,now())",
465468
zName, x.canonical
466469
);
@@ -467,21 +470,24 @@
467470
db_multi_exec(
468471
"REPLACE INTO config(name, value, mtime)"
469472
" VALUES('sync-pw:%q',obscure(%Q),now())",
470473
zName, x.passwd
471474
);
475
+ db_protect_pop();
472476
db_commit_transaction();
473477
return;
474478
}
475479
if( strncmp(zArg, "delete", nArg)==0 ){
476480
char *zName;
477481
if( g.argc!=4 ) usage("delete NAME");
478482
zName = g.argv[3];
479483
if( strcmp(zName,"default")==0 ) goto remote_delete_default;
480484
db_begin_write();
485
+ db_unprotect(PROTECT_CONFIG);
481486
db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
482487
db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
488
+ db_protect_pop();
483489
db_commit_transaction();
484490
return;
485491
}
486492
if( sqlite3_strlike("http://%",zArg,0)==0
487493
|| sqlite3_strlike("https://%",zArg,0)==0
488494
--- src/sync.c
+++ src/sync.c
@@ -425,13 +425,15 @@
425 /* fossil remote off
426 ** Forget the last-sync-URL and its password
427 */
428 if( g.argc!=3 ) usage("off");
429 remote_delete_default:
 
430 db_multi_exec(
431 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
432 );
 
433 return;
434 }
435 if( strncmp(zArg, "list", nArg)==0 || strcmp(zArg,"ls")==0 ){
436 Stmt q;
437 if( g.argc!=3 ) usage("list");
@@ -457,10 +459,11 @@
457 zName = g.argv[3];
458 zUrl = g.argv[4];
459 if( strcmp(zName,"default")==0 ) goto remote_add_default;
460 url_parse_local(zUrl, URL_PROMPT_PW, &x);
461 db_begin_write();
 
462 db_multi_exec(
463 "REPLACE INTO config(name, value, mtime)"
464 " VALUES('sync-url:%q',%Q,now())",
465 zName, x.canonical
466 );
@@ -467,21 +470,24 @@
467 db_multi_exec(
468 "REPLACE INTO config(name, value, mtime)"
469 " VALUES('sync-pw:%q',obscure(%Q),now())",
470 zName, x.passwd
471 );
 
472 db_commit_transaction();
473 return;
474 }
475 if( strncmp(zArg, "delete", nArg)==0 ){
476 char *zName;
477 if( g.argc!=4 ) usage("delete NAME");
478 zName = g.argv[3];
479 if( strcmp(zName,"default")==0 ) goto remote_delete_default;
480 db_begin_write();
 
481 db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
482 db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
 
483 db_commit_transaction();
484 return;
485 }
486 if( sqlite3_strlike("http://%",zArg,0)==0
487 || sqlite3_strlike("https://%",zArg,0)==0
488
--- src/sync.c
+++ src/sync.c
@@ -425,13 +425,15 @@
425 /* fossil remote off
426 ** Forget the last-sync-URL and its password
427 */
428 if( g.argc!=3 ) usage("off");
429 remote_delete_default:
430 db_unprotect(PROTECT_CONFIG);
431 db_multi_exec(
432 "DELETE FROM config WHERE name GLOB 'last-sync-*';"
433 );
434 db_protect_pop();
435 return;
436 }
437 if( strncmp(zArg, "list", nArg)==0 || strcmp(zArg,"ls")==0 ){
438 Stmt q;
439 if( g.argc!=3 ) usage("list");
@@ -457,10 +459,11 @@
459 zName = g.argv[3];
460 zUrl = g.argv[4];
461 if( strcmp(zName,"default")==0 ) goto remote_add_default;
462 url_parse_local(zUrl, URL_PROMPT_PW, &x);
463 db_begin_write();
464 db_unprotect(PROTECT_CONFIG);
465 db_multi_exec(
466 "REPLACE INTO config(name, value, mtime)"
467 " VALUES('sync-url:%q',%Q,now())",
468 zName, x.canonical
469 );
@@ -467,21 +470,24 @@
470 db_multi_exec(
471 "REPLACE INTO config(name, value, mtime)"
472 " VALUES('sync-pw:%q',obscure(%Q),now())",
473 zName, x.passwd
474 );
475 db_protect_pop();
476 db_commit_transaction();
477 return;
478 }
479 if( strncmp(zArg, "delete", nArg)==0 ){
480 char *zName;
481 if( g.argc!=4 ) usage("delete NAME");
482 zName = g.argv[3];
483 if( strcmp(zName,"default")==0 ) goto remote_delete_default;
484 db_begin_write();
485 db_unprotect(PROTECT_CONFIG);
486 db_multi_exec("DELETE FROM config WHERE name glob 'sync-url:%q'", zName);
487 db_multi_exec("DELETE FROM config WHERE name glob 'sync-pw:%q'", zName);
488 db_protect_pop();
489 db_commit_transaction();
490 return;
491 }
492 if( sqlite3_strlike("http://%",zArg,0)==0
493 || sqlite3_strlike("https://%",zArg,0)==0
494
+5
--- src/user.c
+++ src/user.c
@@ -432,12 +432,14 @@
432432
}
433433
if( blob_size(&pw)==0 ){
434434
fossil_print("password unchanged\n");
435435
}else{
436436
char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
437
+ db_unprotect(PROTECT_USER);
437438
db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
438439
zSecret, uid);
440
+ db_protect_pop();
439441
free(zSecret);
440442
}
441443
}else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
442444
int uid;
443445
if( g.argc!=4 && g.argc!=5 ){
@@ -446,14 +448,16 @@
446448
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
447449
if( uid==0 ){
448450
fossil_fatal("no such user: %s", g.argv[3]);
449451
}
450452
if( g.argc==5 ){
453
+ db_unprotect(PROTECT_USER);
451454
db_multi_exec(
452455
"UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
453456
g.argv[4], uid
454457
);
458
+ db_protect_pop();
455459
}
456460
fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
457461
}else{
458462
fossil_fatal("user subcommand should be one of: "
459463
"capabilities default list new password");
@@ -573,10 +577,11 @@
573577
void user_hash_passwords_cmd(void){
574578
if( g.argc!=3 ) usage("REPOSITORY");
575579
db_open_repository(g.argv[2]);
576580
sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
577581
sha1_shared_secret_sql_function, 0, 0);
582
+ db_unprotect(PROTECT_ALL);
578583
db_multi_exec(
579584
"UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
580585
" WHERE length(pw)>0 AND length(pw)!=40"
581586
);
582587
}
583588
--- src/user.c
+++ src/user.c
@@ -432,12 +432,14 @@
432 }
433 if( blob_size(&pw)==0 ){
434 fossil_print("password unchanged\n");
435 }else{
436 char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
 
437 db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
438 zSecret, uid);
 
439 free(zSecret);
440 }
441 }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
442 int uid;
443 if( g.argc!=4 && g.argc!=5 ){
@@ -446,14 +448,16 @@
446 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
447 if( uid==0 ){
448 fossil_fatal("no such user: %s", g.argv[3]);
449 }
450 if( g.argc==5 ){
 
451 db_multi_exec(
452 "UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
453 g.argv[4], uid
454 );
 
455 }
456 fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
457 }else{
458 fossil_fatal("user subcommand should be one of: "
459 "capabilities default list new password");
@@ -573,10 +577,11 @@
573 void user_hash_passwords_cmd(void){
574 if( g.argc!=3 ) usage("REPOSITORY");
575 db_open_repository(g.argv[2]);
576 sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
577 sha1_shared_secret_sql_function, 0, 0);
 
578 db_multi_exec(
579 "UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
580 " WHERE length(pw)>0 AND length(pw)!=40"
581 );
582 }
583
--- src/user.c
+++ src/user.c
@@ -432,12 +432,14 @@
432 }
433 if( blob_size(&pw)==0 ){
434 fossil_print("password unchanged\n");
435 }else{
436 char *zSecret = sha1_shared_secret(blob_str(&pw), g.argv[3], 0);
437 db_unprotect(PROTECT_USER);
438 db_multi_exec("UPDATE user SET pw=%Q, mtime=now() WHERE uid=%d",
439 zSecret, uid);
440 db_protect_pop();
441 free(zSecret);
442 }
443 }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
444 int uid;
445 if( g.argc!=4 && g.argc!=5 ){
@@ -446,14 +448,16 @@
448 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
449 if( uid==0 ){
450 fossil_fatal("no such user: %s", g.argv[3]);
451 }
452 if( g.argc==5 ){
453 db_unprotect(PROTECT_USER);
454 db_multi_exec(
455 "UPDATE user SET cap=%Q, mtime=now() WHERE uid=%d",
456 g.argv[4], uid
457 );
458 db_protect_pop();
459 }
460 fossil_print("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
461 }else{
462 fossil_fatal("user subcommand should be one of: "
463 "capabilities default list new password");
@@ -573,10 +577,11 @@
577 void user_hash_passwords_cmd(void){
578 if( g.argc!=3 ) usage("REPOSITORY");
579 db_open_repository(g.argv[2]);
580 sqlite3_create_function(g.db, "shared_secret", 2, SQLITE_UTF8, 0,
581 sha1_shared_secret_sql_function, 0, 0);
582 db_unprotect(PROTECT_ALL);
583 db_multi_exec(
584 "UPDATE user SET pw=shared_secret(pw,login), mtime=now()"
585 " WHERE length(pw)>0 AND length(pw)!=40"
586 );
587 }
588
+6
--- src/xfer.c
+++ src/xfer.c
@@ -1657,11 +1657,13 @@
16571657
int x = db_column_int(&q,3);
16581658
const char *zName = db_column_text(&q,4);
16591659
if( db_column_int64(&q,1)<=iNow-maxAge || !is_a_leaf(x) ){
16601660
/* check-in locks expire after maxAge seconds, or when the
16611661
** check-in is no longer a leaf */
1662
+ db_unprotect(PROTECT_CONFIG);
16621663
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1664
+ db_protect_pop();
16631665
continue;
16641666
}
16651667
if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
16661668
const char *zClientId = db_column_text(&q, 2);
16671669
const char *zLogin = db_column_text(&q,0);
@@ -1672,16 +1674,18 @@
16721674
seenFault = 1;
16731675
}
16741676
}
16751677
db_finalize(&q);
16761678
if( !seenFault ){
1679
+ db_unprotect(PROTECT_CONFIG);
16771680
db_multi_exec(
16781681
"REPLACE INTO config(name,value,mtime)"
16791682
"VALUES('ci-lock-%q',json_object('login',%Q,'clientid',%Q),now())",
16801683
blob_str(&xfer.aToken[2]), g.zLogin,
16811684
blob_str(&xfer.aToken[3])
16821685
);
1686
+ db_protect_pop();
16831687
}
16841688
if( db_get_boolean("forbid-delta-manifests",0) ){
16851689
@ pragma avoid-delta-manifests
16861690
}
16871691
}
@@ -1694,16 +1698,18 @@
16941698
*/
16951699
if( blob_eq(&xfer.aToken[1], "ci-unlock")
16961700
&& xfer.nToken==3
16971701
&& blob_is_hname(&xfer.aToken[2])
16981702
){
1703
+ db_unprotect(PROTECT_CONFIG);
16991704
db_multi_exec(
17001705
"DELETE FROM config"
17011706
" WHERE name GLOB 'ci-lock-*'"
17021707
" AND json_extract(value,'$.clientid')=%Q",
17031708
blob_str(&xfer.aToken[2])
17041709
);
1710
+ db_protect_pop();
17051711
}
17061712
17071713
}else
17081714
17091715
/* Unknown message
17101716
--- src/xfer.c
+++ src/xfer.c
@@ -1657,11 +1657,13 @@
1657 int x = db_column_int(&q,3);
1658 const char *zName = db_column_text(&q,4);
1659 if( db_column_int64(&q,1)<=iNow-maxAge || !is_a_leaf(x) ){
1660 /* check-in locks expire after maxAge seconds, or when the
1661 ** check-in is no longer a leaf */
 
1662 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
 
1663 continue;
1664 }
1665 if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
1666 const char *zClientId = db_column_text(&q, 2);
1667 const char *zLogin = db_column_text(&q,0);
@@ -1672,16 +1674,18 @@
1672 seenFault = 1;
1673 }
1674 }
1675 db_finalize(&q);
1676 if( !seenFault ){
 
1677 db_multi_exec(
1678 "REPLACE INTO config(name,value,mtime)"
1679 "VALUES('ci-lock-%q',json_object('login',%Q,'clientid',%Q),now())",
1680 blob_str(&xfer.aToken[2]), g.zLogin,
1681 blob_str(&xfer.aToken[3])
1682 );
 
1683 }
1684 if( db_get_boolean("forbid-delta-manifests",0) ){
1685 @ pragma avoid-delta-manifests
1686 }
1687 }
@@ -1694,16 +1698,18 @@
1694 */
1695 if( blob_eq(&xfer.aToken[1], "ci-unlock")
1696 && xfer.nToken==3
1697 && blob_is_hname(&xfer.aToken[2])
1698 ){
 
1699 db_multi_exec(
1700 "DELETE FROM config"
1701 " WHERE name GLOB 'ci-lock-*'"
1702 " AND json_extract(value,'$.clientid')=%Q",
1703 blob_str(&xfer.aToken[2])
1704 );
 
1705 }
1706
1707 }else
1708
1709 /* Unknown message
1710
--- src/xfer.c
+++ src/xfer.c
@@ -1657,11 +1657,13 @@
1657 int x = db_column_int(&q,3);
1658 const char *zName = db_column_text(&q,4);
1659 if( db_column_int64(&q,1)<=iNow-maxAge || !is_a_leaf(x) ){
1660 /* check-in locks expire after maxAge seconds, or when the
1661 ** check-in is no longer a leaf */
1662 db_unprotect(PROTECT_CONFIG);
1663 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
1664 db_protect_pop();
1665 continue;
1666 }
1667 if( fossil_strcmp(zName+8, blob_str(&xfer.aToken[2]))==0 ){
1668 const char *zClientId = db_column_text(&q, 2);
1669 const char *zLogin = db_column_text(&q,0);
@@ -1672,16 +1674,18 @@
1674 seenFault = 1;
1675 }
1676 }
1677 db_finalize(&q);
1678 if( !seenFault ){
1679 db_unprotect(PROTECT_CONFIG);
1680 db_multi_exec(
1681 "REPLACE INTO config(name,value,mtime)"
1682 "VALUES('ci-lock-%q',json_object('login',%Q,'clientid',%Q),now())",
1683 blob_str(&xfer.aToken[2]), g.zLogin,
1684 blob_str(&xfer.aToken[3])
1685 );
1686 db_protect_pop();
1687 }
1688 if( db_get_boolean("forbid-delta-manifests",0) ){
1689 @ pragma avoid-delta-manifests
1690 }
1691 }
@@ -1694,16 +1698,18 @@
1698 */
1699 if( blob_eq(&xfer.aToken[1], "ci-unlock")
1700 && xfer.nToken==3
1701 && blob_is_hname(&xfer.aToken[2])
1702 ){
1703 db_unprotect(PROTECT_CONFIG);
1704 db_multi_exec(
1705 "DELETE FROM config"
1706 " WHERE name GLOB 'ci-lock-*'"
1707 " AND json_extract(value,'$.clientid')=%Q",
1708 blob_str(&xfer.aToken[2])
1709 );
1710 db_protect_pop();
1711 }
1712
1713 }else
1714
1715 /* Unknown message
1716

Keyboard Shortcuts

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