Fossil SCM

Only require CSRF checks for /chat-send if the request was authenticated by cookie. Follow-up to [4caa8cb9ff819f7e].

drh 2025-12-23 14:50 trunk
Commit 10006db404afa55865890ad8884b6d30076cb7ce30746642fb58b3571b972daa
+1 -1
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443443
const char *zUserName;
444444
login_check_credentials();
445445
if( 0==g.perm.Chat ) {
446446
chat_emit_permissions_error(0);
447447
return;
448
- }else if( 0==cgi_csrf_safe(1) ){
448
+ }else if( g.eAuthMethod==AUTH_COOKIE && 0==cgi_csrf_safe(1) ){
449449
chat_emit_csrf_error();
450450
return;
451451
}
452452
zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453453
nByte = atoi(PD("file:bytes","0"));
454454
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443 const char *zUserName;
444 login_check_credentials();
445 if( 0==g.perm.Chat ) {
446 chat_emit_permissions_error(0);
447 return;
448 }else if( 0==cgi_csrf_safe(1) ){
449 chat_emit_csrf_error();
450 return;
451 }
452 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453 nByte = atoi(PD("file:bytes","0"));
454
--- src/chat.c
+++ src/chat.c
@@ -443,11 +443,11 @@
443 const char *zUserName;
444 login_check_credentials();
445 if( 0==g.perm.Chat ) {
446 chat_emit_permissions_error(0);
447 return;
448 }else if( g.eAuthMethod==AUTH_COOKIE && 0==cgi_csrf_safe(1) ){
449 chat_emit_csrf_error();
450 return;
451 }
452 zUserName = (g.zLogin && g.zLogin[0]) ? g.zLogin : "nobody";
453 nByte = atoi(PD("file:bytes","0"));
454
--- src/login.c
+++ src/login.c
@@ -1371,10 +1371,11 @@
13711371
** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
13721372
** g.perm Permissions granted to this user
13731373
** g.anon Permissions that would be available to anonymous
13741374
** g.isRobot True if the client is known to be a spider or robot
13751375
** g.perm Populated based on user account's capabilities
1376
+** g.eAuthMethod The mechanism used for authentication
13761377
**
13771378
*/
13781379
void login_check_credentials(void){
13791380
int uid = 0; /* User id */
13801381
const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
14111412
}
14121413
g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
14131414
zCap = "sxy";
14141415
g.noPswd = 1;
14151416
g.isRobot = 0;
1417
+ g.eAuthMethod = AUTH_LOCAL;
14161418
zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
14171419
" FROM user WHERE uid=%d", uid);
14181420
login_create_csrf_secret(zSeed);
14191421
fossil_free(zSeed);
14201422
}
@@ -1490,10 +1492,11 @@
14901492
" AND octet_length(cap)>0"
14911493
" AND octet_length(pw)>0");
14921494
}
14931495
}
14941496
}
1497
+ if( uid ) g.eAuthMethod = AUTH_COOKIE;
14951498
login_create_csrf_secret(zHash);
14961499
}
14971500
14981501
/* If no user found and the REMOTE_USER environment variable is set,
14991502
** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
15021505
const char *zRemoteUser = P("REMOTE_USER");
15031506
if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
15041507
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
15051508
" AND octet_length(cap)>0 AND octet_length(pw)>0",
15061509
zRemoteUser);
1510
+ if( uid ) g.eAuthMethod = AUTH_ENV;
15071511
}
15081512
}
15091513
15101514
/* If the request didn't provide a login cookie or the login cookie didn't
15111515
** match a known valid user, check the HTTP "Authorization" header and
15121516
** see if those credentials are valid for a known user.
15131517
*/
15141518
if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
15151519
uid = login_basic_authentication(zIpAddr);
1520
+ if( uid ) g.eAuthMethod = AUTH_HTTP;
15161521
}
15171522
15181523
/* Check for magic query parameters "resid" (for the username) and
15191524
** "token" for the password. Both values (if they exist) will be
15201525
** obfuscated.
@@ -1529,10 +1534,11 @@
15291534
" WHERE login=%Q"
15301535
" AND (constant_time_cmp(pw,%Q)=0"
15311536
" OR constant_time_cmp(pw,%Q)=0)",
15321537
zUsr, zSha1Pw, zPW);
15331538
fossil_free(zSha1Pw);
1539
+ if( uid ) g.eAuthMethod = AUTH_PW;
15341540
}
15351541
}
15361542
15371543
/* If no user found yet, try to log in as "nobody" */
15381544
if( uid==0 ){
15391545
--- src/login.c
+++ src/login.c
@@ -1371,10 +1371,11 @@
1371 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
1372 ** g.perm Permissions granted to this user
1373 ** g.anon Permissions that would be available to anonymous
1374 ** g.isRobot True if the client is known to be a spider or robot
1375 ** g.perm Populated based on user account's capabilities
 
1376 **
1377 */
1378 void login_check_credentials(void){
1379 int uid = 0; /* User id */
1380 const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
1411 }
1412 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
1413 zCap = "sxy";
1414 g.noPswd = 1;
1415 g.isRobot = 0;
 
1416 zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
1417 " FROM user WHERE uid=%d", uid);
1418 login_create_csrf_secret(zSeed);
1419 fossil_free(zSeed);
1420 }
@@ -1490,10 +1492,11 @@
1490 " AND octet_length(cap)>0"
1491 " AND octet_length(pw)>0");
1492 }
1493 }
1494 }
 
1495 login_create_csrf_secret(zHash);
1496 }
1497
1498 /* If no user found and the REMOTE_USER environment variable is set,
1499 ** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
1502 const char *zRemoteUser = P("REMOTE_USER");
1503 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
1504 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
1505 " AND octet_length(cap)>0 AND octet_length(pw)>0",
1506 zRemoteUser);
 
1507 }
1508 }
1509
1510 /* If the request didn't provide a login cookie or the login cookie didn't
1511 ** match a known valid user, check the HTTP "Authorization" header and
1512 ** see if those credentials are valid for a known user.
1513 */
1514 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1515 uid = login_basic_authentication(zIpAddr);
 
1516 }
1517
1518 /* Check for magic query parameters "resid" (for the username) and
1519 ** "token" for the password. Both values (if they exist) will be
1520 ** obfuscated.
@@ -1529,10 +1534,11 @@
1529 " WHERE login=%Q"
1530 " AND (constant_time_cmp(pw,%Q)=0"
1531 " OR constant_time_cmp(pw,%Q)=0)",
1532 zUsr, zSha1Pw, zPW);
1533 fossil_free(zSha1Pw);
 
1534 }
1535 }
1536
1537 /* If no user found yet, try to log in as "nobody" */
1538 if( uid==0 ){
1539
--- src/login.c
+++ src/login.c
@@ -1371,10 +1371,11 @@
1371 ** g.zLogin Database USER.LOGIN value. NULL for user "nobody"
1372 ** g.perm Permissions granted to this user
1373 ** g.anon Permissions that would be available to anonymous
1374 ** g.isRobot True if the client is known to be a spider or robot
1375 ** g.perm Populated based on user account's capabilities
1376 ** g.eAuthMethod The mechanism used for authentication
1377 **
1378 */
1379 void login_check_credentials(void){
1380 int uid = 0; /* User id */
1381 const char *zCookie; /* Text of the login cookie */
@@ -1411,10 +1412,11 @@
1412 }
1413 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
1414 zCap = "sxy";
1415 g.noPswd = 1;
1416 g.isRobot = 0;
1417 g.eAuthMethod = AUTH_LOCAL;
1418 zSeed = db_text("??", "SELECT uid||quote(login)||quote(pw)||quote(cookie)"
1419 " FROM user WHERE uid=%d", uid);
1420 login_create_csrf_secret(zSeed);
1421 fossil_free(zSeed);
1422 }
@@ -1490,10 +1492,11 @@
1492 " AND octet_length(cap)>0"
1493 " AND octet_length(pw)>0");
1494 }
1495 }
1496 }
1497 if( uid ) g.eAuthMethod = AUTH_COOKIE;
1498 login_create_csrf_secret(zHash);
1499 }
1500
1501 /* If no user found and the REMOTE_USER environment variable is set,
1502 ** then accept the value of REMOTE_USER as the user.
@@ -1502,19 +1505,21 @@
1505 const char *zRemoteUser = P("REMOTE_USER");
1506 if( zRemoteUser && db_get_boolean("remote_user_ok",0) ){
1507 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q"
1508 " AND octet_length(cap)>0 AND octet_length(pw)>0",
1509 zRemoteUser);
1510 if( uid ) g.eAuthMethod = AUTH_ENV;
1511 }
1512 }
1513
1514 /* If the request didn't provide a login cookie or the login cookie didn't
1515 ** match a known valid user, check the HTTP "Authorization" header and
1516 ** see if those credentials are valid for a known user.
1517 */
1518 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1519 uid = login_basic_authentication(zIpAddr);
1520 if( uid ) g.eAuthMethod = AUTH_HTTP;
1521 }
1522
1523 /* Check for magic query parameters "resid" (for the username) and
1524 ** "token" for the password. Both values (if they exist) will be
1525 ** obfuscated.
@@ -1529,10 +1534,11 @@
1534 " WHERE login=%Q"
1535 " AND (constant_time_cmp(pw,%Q)=0"
1536 " OR constant_time_cmp(pw,%Q)=0)",
1537 zUsr, zSha1Pw, zPW);
1538 fossil_free(zSha1Pw);
1539 if( uid ) g.eAuthMethod = AUTH_PW;
1540 }
1541 }
1542
1543 /* If no user found yet, try to log in as "nobody" */
1544 if( uid==0 ){
1545
+7
--- src/main.c
+++ src/main.c
@@ -236,10 +236,17 @@
236236
* applicable when using SEE on Windows or Linux. */
237237
#endif
238238
int useLocalauth; /* No login required if from 127.0.0.1 */
239239
int noPswd; /* Logged in without password (on 127.0.0.1) */
240240
int userUid; /* Integer user id */
241
+ int eAuthMethod; /* How the user authenticated to us */
242
+# define AUTH_NONE 0 /* Not authenticated */
243
+# define AUTH_COOKIE 1 /* Authentication by cookie */
244
+# define AUTH_LOCAL 2 /* Uses loopback */
245
+# define AUTH_PW 3 /* Authentication by password */
246
+# define AUTH_ENV 4 /* Authenticated by REMOTE_USER environment var */
247
+# define AUTH_HTTP 5 /* HTTP Basic Authentication */
241248
int isRobot; /* True if the client is definitely a robot. False
242249
** negatives are common for this flag */
243250
int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
244251
** accessed through get_comment_format(). */
245252
const char *zSockName; /* Name of the unix-domain socket file */
246253
--- src/main.c
+++ src/main.c
@@ -236,10 +236,17 @@
236 * applicable when using SEE on Windows or Linux. */
237 #endif
238 int useLocalauth; /* No login required if from 127.0.0.1 */
239 int noPswd; /* Logged in without password (on 127.0.0.1) */
240 int userUid; /* Integer user id */
 
 
 
 
 
 
 
241 int isRobot; /* True if the client is definitely a robot. False
242 ** negatives are common for this flag */
243 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
244 ** accessed through get_comment_format(). */
245 const char *zSockName; /* Name of the unix-domain socket file */
246
--- src/main.c
+++ src/main.c
@@ -236,10 +236,17 @@
236 * applicable when using SEE on Windows or Linux. */
237 #endif
238 int useLocalauth; /* No login required if from 127.0.0.1 */
239 int noPswd; /* Logged in without password (on 127.0.0.1) */
240 int userUid; /* Integer user id */
241 int eAuthMethod; /* How the user authenticated to us */
242 # define AUTH_NONE 0 /* Not authenticated */
243 # define AUTH_COOKIE 1 /* Authentication by cookie */
244 # define AUTH_LOCAL 2 /* Uses loopback */
245 # define AUTH_PW 3 /* Authentication by password */
246 # define AUTH_ENV 4 /* Authenticated by REMOTE_USER environment var */
247 # define AUTH_HTTP 5 /* HTTP Basic Authentication */
248 int isRobot; /* True if the client is definitely a robot. False
249 ** negatives are common for this flag */
250 int comFmtFlags; /* Zero or more "COMMENT_PRINT_*" bit flags, should be
251 ** accessed through get_comment_format(). */
252 const char *zSockName; /* Name of the unix-domain socket file */
253
--- src/style.c
+++ src/style.c
@@ -1442,10 +1442,15 @@
14421442
@ g.zHttpsURL = %h(g.zHttpsURL)<br>
14431443
@ g.zTop = %h(g.zTop)<br>
14441444
@ g.zPath = %h(g.zPath)<br>
14451445
@ g.userUid = %d(g.userUid)<br>
14461446
@ g.zLogin = %h(g.zLogin)<br>
1447
+ if( g.eAuthMethod!=AUTH_NONE ){
1448
+ const char *zMethod[] = { "COOKIE", "LOCAL", "PW", "ENV", "HTTP" };
1449
+ @ g.eAuthMethod = %d(g.eAuthMethod) (%h(zMethod[g.eAuthMethod-1]))\
1450
+ @ <br>
1451
+ }
14471452
@ g.isRobot = %d(g.isRobot)<br>
14481453
@ g.jsHref = %d(g.jsHref)<br>
14491454
if( g.zLocalRoot ){
14501455
@ g.zLocalRoot = %h(g.zLocalRoot)<br>
14511456
}else{
14521457
--- src/style.c
+++ src/style.c
@@ -1442,10 +1442,15 @@
1442 @ g.zHttpsURL = %h(g.zHttpsURL)<br>
1443 @ g.zTop = %h(g.zTop)<br>
1444 @ g.zPath = %h(g.zPath)<br>
1445 @ g.userUid = %d(g.userUid)<br>
1446 @ g.zLogin = %h(g.zLogin)<br>
 
 
 
 
 
1447 @ g.isRobot = %d(g.isRobot)<br>
1448 @ g.jsHref = %d(g.jsHref)<br>
1449 if( g.zLocalRoot ){
1450 @ g.zLocalRoot = %h(g.zLocalRoot)<br>
1451 }else{
1452
--- src/style.c
+++ src/style.c
@@ -1442,10 +1442,15 @@
1442 @ g.zHttpsURL = %h(g.zHttpsURL)<br>
1443 @ g.zTop = %h(g.zTop)<br>
1444 @ g.zPath = %h(g.zPath)<br>
1445 @ g.userUid = %d(g.userUid)<br>
1446 @ g.zLogin = %h(g.zLogin)<br>
1447 if( g.eAuthMethod!=AUTH_NONE ){
1448 const char *zMethod[] = { "COOKIE", "LOCAL", "PW", "ENV", "HTTP" };
1449 @ g.eAuthMethod = %d(g.eAuthMethod) (%h(zMethod[g.eAuthMethod-1]))\
1450 @ <br>
1451 }
1452 @ g.isRobot = %d(g.isRobot)<br>
1453 @ g.jsHref = %d(g.jsHref)<br>
1454 if( g.zLocalRoot ){
1455 @ g.zLocalRoot = %h(g.zLocalRoot)<br>
1456 }else{
1457

Keyboard Shortcuts

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