Fossil SCM

Eliminate IP prefix tracking as part of the login cookie.

drh 2020-03-31 21:13 trunk
Commit 7d18c40b8339eed6db748459e649ec731859406b7b213b21d3a0bc65893027ef
2 files changed +20 -65 -12
+20 -65
--- src/login.c
+++ src/login.c
@@ -111,36 +111,10 @@
111111
}else{
112112
fossil_redirect_home();
113113
}
114114
}
115115
116
-/*
117
-** The IP address of the client is stored as part of login cookies.
118
-** But some clients are behind firewalls that shift the IP address
119
-** with each HTTP request. To allow such (broken) clients to log in,
120
-** extract just a prefix of the IP address.
121
-*/
122
-static char *ipPrefix(const char *zIP){
123
- int i, j;
124
- static int ip_prefix_terms = -1;
125
- if( ip_prefix_terms<0 ){
126
- if( db_get_int("redirect-to-https",0)>=2 ){
127
- ip_prefix_terms = 0;
128
- }else{
129
- ip_prefix_terms = db_get_int("ip-prefix-terms",2);
130
- }
131
- }
132
- if( ip_prefix_terms==0 ) return mprintf("0");
133
- for(i=j=0; zIP[i]; i++){
134
- if( zIP[i]=='.' ){
135
- j++;
136
- if( j==ip_prefix_terms ) break;
137
- }
138
- }
139
- return mprintf("%.*s", i, zIP);
140
-}
141
-
142116
/*
143117
** Return an abbreviated project code. The abbreviation is the first
144118
** 16 characters of the project code.
145119
**
146120
** Memory is obtained from malloc.
@@ -299,30 +273,27 @@
299273
const char *zExpire = db_get("cookie-expire","8766");
300274
int expires = atoi(zExpire)*3600;
301275
char *zHash;
302276
char *zCookie;
303277
const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
304
- char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
305278
306279
assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
307280
zHash = db_text(0,
308281
"SELECT cookie FROM user"
309282
" WHERE uid=%d"
310
- " AND ipaddr=%Q"
311283
" AND cexpire>julianday('now')"
312284
" AND length(cookie)>30",
313
- uid, zRemoteAddr);
285
+ uid);
314286
if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
315287
zCookie = login_gen_user_cookie_value(zUsername, zHash);
316288
cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
317289
record_login_attempt(zUsername, zIpAddr, 1);
318290
db_multi_exec(
319
- "UPDATE user SET cookie=%Q, ipaddr=%Q, "
291
+ "UPDATE user SET cookie=%Q,"
320292
" cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
321
- zHash, zRemoteAddr, expires, uid
293
+ zHash, expires, uid
322294
);
323
- free(zRemoteAddr);
324295
free(zHash);
325296
if( zDest ){
326297
*zDest = zCookie;
327298
}else{
328299
free(zCookie);
@@ -331,34 +302,25 @@
331302
332303
/* Sets a cookie for an anonymous user login, which looks like this:
333304
**
334305
** HASH/TIME/anonymous
335306
**
336
-** Where HASH is the sha1sum of TIME/IPADDR/SECRET, in which IPADDR
337
-** is the abbreviated IP address and SECRET is captcha-secret.
338
-**
339
-** If either zIpAddr or zRemoteAddr are NULL then REMOTE_ADDR
340
-** is used.
307
+** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret.
341308
**
342309
** If zCookieDest is not NULL then the generated cookie is assigned to
343310
** *zCookieDest and the caller must eventually free() it.
344311
*/
345312
void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
346313
const char *zNow; /* Current time (julian day number) */
347314
char *zCookie; /* The login cookie */
348315
const char *zCookieName; /* Name of the login cookie */
349316
Blob b; /* Blob used during cookie construction */
350
- char *zRemoteAddr; /* Abbreviated IP address */
351
- if(!zIpAddr){
352
- zIpAddr = PD("REMOTE_ADDR","nil");
353
- }
354
- zRemoteAddr = ipPrefix(zIpAddr);
355317
zCookieName = login_cookie_name();
356318
zNow = db_text("0", "SELECT julianday('now')");
357
- assert( zCookieName && zRemoteAddr && zIpAddr && zNow );
319
+ assert( zCookieName && zNow );
358320
blob_init(&b, zNow, -1);
359
- blob_appendf(&b, "/%s/%s", zRemoteAddr, db_get("captcha-secret",""));
321
+ blob_appendf(&b, "/%s", db_get("captcha-secret",""));
360322
sha1sum_blob(&b, &b);
361323
zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow);
362324
blob_reset(&b);
363325
cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), 6*3600);
364326
if( zCookieDest ){
@@ -813,12 +775,11 @@
813775
** Return true if a transfer was made and false if not.
814776
*/
815777
static int login_transfer_credentials(
816778
const char *zLogin, /* Login we are looking for */
817779
const char *zCode, /* Project code of peer repository */
818
- const char *zHash, /* HASH from login cookie HASH/CODE/LOGIN */
819
- const char *zRemoteAddr /* Request comes from here */
780
+ const char *zHash /* HASH from login cookie HASH/CODE/LOGIN */
820781
){
821782
sqlite3 *pOther = 0; /* The other repository */
822783
sqlite3_stmt *pStmt; /* Query against the other repository */
823784
char *zSQL; /* SQL of the query against other repo */
824785
char *zOtherRepo; /* Filename of the other repository */
@@ -842,24 +803,23 @@
842803
constant_time_cmp_function, 0, 0);
843804
sqlite3_busy_timeout(pOther, 5000);
844805
zSQL = mprintf(
845806
"SELECT cexpire FROM user"
846807
" WHERE login=%Q"
847
- " AND ipaddr=%Q"
848808
" AND length(cap)>0"
849809
" AND length(pw)>0"
850810
" AND cexpire>julianday('now')"
851811
" AND constant_time_cmp(cookie,%Q)=0",
852
- zLogin, zRemoteAddr, zHash
812
+ zLogin, zHash
853813
);
854814
pStmt = 0;
855815
rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
856816
if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
857817
db_multi_exec(
858
- "UPDATE user SET cookie=%Q, ipaddr=%Q, cexpire=%.17g"
818
+ "UPDATE user SET cookie=%Q, cexpire=%.17g"
859819
" WHERE login=%Q",
860
- zHash, zRemoteAddr,
820
+ zHash,
861821
sqlite3_column_double(pStmt, 0), zLogin
862822
);
863823
nXfer++;
864824
}
865825
sqlite3_finalize(pStmt);
@@ -879,33 +839,30 @@
879839
if( fossil_strcmp(zLogin, "reader")==0 ) return 1;
880840
return 0;
881841
}
882842
883843
/*
884
-** Lookup the uid for a non-built-in user with zLogin and zCookie and
885
-** zRemoteAddr. Return 0 if not found.
844
+** Lookup the uid for a non-built-in user with zLogin and zCookie.
845
+** Return 0 if not found.
886846
**
887847
** Note that this only searches for logged-in entries with matching
888
-** zCookie (db: user.cookie) and zRemoteAddr (db: user.ipaddr)
889
-** entries.
848
+** zCookie (db: user.cookie) entries.
890849
*/
891850
static int login_find_user(
892851
const char *zLogin, /* User name */
893
- const char *zCookie, /* Login cookie value */
894
- const char *zRemoteAddr /* Abbreviated IP address for valid login */
852
+ const char *zCookie /* Login cookie value */
895853
){
896854
int uid;
897855
if( login_is_special(zLogin) ) return 0;
898856
uid = db_int(0,
899857
"SELECT uid FROM user"
900858
" WHERE login=%Q"
901
- " AND ipaddr=%Q"
902859
" AND cexpire>julianday('now')"
903860
" AND length(cap)>0"
904861
" AND length(pw)>0"
905862
" AND constant_time_cmp(cookie,%Q)=0",
906
- zLogin, zRemoteAddr, zCookie
863
+ zLogin, zCookie
907864
);
908865
return uid;
909866
}
910867
911868
/*
@@ -974,11 +931,10 @@
974931
*/
975932
void login_check_credentials(void){
976933
int uid = 0; /* User id */
977934
const char *zCookie; /* Text of the login cookie */
978935
const char *zIpAddr; /* Raw IP address of the requestor */
979
- char *zRemoteAddr; /* Abbreviated IP address of the requestor */
980936
const char *zCap = 0; /* Capability string */
981937
const char *zPublicPages = 0; /* GLOB patterns of public pages */
982938
const char *zLogin = 0; /* Login user for credentials */
983939
984940
/* Only run this check once. */
@@ -992,11 +948,11 @@
992948
** then there is no need to check user credentials.
993949
**
994950
** This feature allows the "fossil ui" command to give the user
995951
** full access rights without having to log in.
996952
*/
997
- zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
953
+ zIpAddr = PD("REMOTE_ADDR","nil");
998954
if( ( cgi_is_loopback(zIpAddr)
999955
|| (g.fSshClient & CGI_SSH_CLIENT)!=0 )
1000956
&& g.useLocalauth
1001957
&& db_get_int("localauth",0)==0
1002958
&& P("HTTPS")==0
@@ -1041,12 +997,11 @@
1041997
** SECRET is the "captcha-secret" value in the repository.
1042998
*/
1043999
double rTime = atof(zArg);
10441000
Blob b;
10451001
blob_zero(&b);
1046
- blob_appendf(&b, "%s/%s/%s",
1047
- zArg, zRemoteAddr, db_get("captcha-secret",""));
1002
+ blob_appendf(&b, "%s/%s", zArg, db_get("captcha-secret",""));
10481003
sha1sum_blob(&b, &b);
10491004
if( fossil_strcmp(zHash, blob_str(&b))==0 ){
10501005
uid = db_int(0,
10511006
"SELECT uid FROM user WHERE login='anonymous'"
10521007
" AND length(cap)>0"
@@ -1059,13 +1014,13 @@
10591014
}else{
10601015
/* Cookies of the form "HASH/CODE/USER". Search first in the
10611016
** local user table, then the user table for project CODE if we
10621017
** are part of a login-group.
10631018
*/
1064
- uid = login_find_user(zUser, zHash, zRemoteAddr);
1065
- if( uid==0 && login_transfer_credentials(zUser,zArg,zHash,zRemoteAddr) ){
1066
- uid = login_find_user(zUser, zHash, zRemoteAddr);
1019
+ uid = login_find_user(zUser, zHash);
1020
+ if( uid==0 && login_transfer_credentials(zUser,zArg,zHash) ){
1021
+ uid = login_find_user(zUser, zHash);
10671022
if( uid ) record_login_attempt(zUser, zIpAddr, 1);
10681023
}
10691024
}
10701025
sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
10711026
}
10721027
--- src/login.c
+++ src/login.c
@@ -111,36 +111,10 @@
111 }else{
112 fossil_redirect_home();
113 }
114 }
115
116 /*
117 ** The IP address of the client is stored as part of login cookies.
118 ** But some clients are behind firewalls that shift the IP address
119 ** with each HTTP request. To allow such (broken) clients to log in,
120 ** extract just a prefix of the IP address.
121 */
122 static char *ipPrefix(const char *zIP){
123 int i, j;
124 static int ip_prefix_terms = -1;
125 if( ip_prefix_terms<0 ){
126 if( db_get_int("redirect-to-https",0)>=2 ){
127 ip_prefix_terms = 0;
128 }else{
129 ip_prefix_terms = db_get_int("ip-prefix-terms",2);
130 }
131 }
132 if( ip_prefix_terms==0 ) return mprintf("0");
133 for(i=j=0; zIP[i]; i++){
134 if( zIP[i]=='.' ){
135 j++;
136 if( j==ip_prefix_terms ) break;
137 }
138 }
139 return mprintf("%.*s", i, zIP);
140 }
141
142 /*
143 ** Return an abbreviated project code. The abbreviation is the first
144 ** 16 characters of the project code.
145 **
146 ** Memory is obtained from malloc.
@@ -299,30 +273,27 @@
299 const char *zExpire = db_get("cookie-expire","8766");
300 int expires = atoi(zExpire)*3600;
301 char *zHash;
302 char *zCookie;
303 const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
304 char *zRemoteAddr = ipPrefix(zIpAddr); /* Abbreviated IP address */
305
306 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
307 zHash = db_text(0,
308 "SELECT cookie FROM user"
309 " WHERE uid=%d"
310 " AND ipaddr=%Q"
311 " AND cexpire>julianday('now')"
312 " AND length(cookie)>30",
313 uid, zRemoteAddr);
314 if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
315 zCookie = login_gen_user_cookie_value(zUsername, zHash);
316 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
317 record_login_attempt(zUsername, zIpAddr, 1);
318 db_multi_exec(
319 "UPDATE user SET cookie=%Q, ipaddr=%Q, "
320 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
321 zHash, zRemoteAddr, expires, uid
322 );
323 free(zRemoteAddr);
324 free(zHash);
325 if( zDest ){
326 *zDest = zCookie;
327 }else{
328 free(zCookie);
@@ -331,34 +302,25 @@
331
332 /* Sets a cookie for an anonymous user login, which looks like this:
333 **
334 ** HASH/TIME/anonymous
335 **
336 ** Where HASH is the sha1sum of TIME/IPADDR/SECRET, in which IPADDR
337 ** is the abbreviated IP address and SECRET is captcha-secret.
338 **
339 ** If either zIpAddr or zRemoteAddr are NULL then REMOTE_ADDR
340 ** is used.
341 **
342 ** If zCookieDest is not NULL then the generated cookie is assigned to
343 ** *zCookieDest and the caller must eventually free() it.
344 */
345 void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
346 const char *zNow; /* Current time (julian day number) */
347 char *zCookie; /* The login cookie */
348 const char *zCookieName; /* Name of the login cookie */
349 Blob b; /* Blob used during cookie construction */
350 char *zRemoteAddr; /* Abbreviated IP address */
351 if(!zIpAddr){
352 zIpAddr = PD("REMOTE_ADDR","nil");
353 }
354 zRemoteAddr = ipPrefix(zIpAddr);
355 zCookieName = login_cookie_name();
356 zNow = db_text("0", "SELECT julianday('now')");
357 assert( zCookieName && zRemoteAddr && zIpAddr && zNow );
358 blob_init(&b, zNow, -1);
359 blob_appendf(&b, "/%s/%s", zRemoteAddr, db_get("captcha-secret",""));
360 sha1sum_blob(&b, &b);
361 zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow);
362 blob_reset(&b);
363 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), 6*3600);
364 if( zCookieDest ){
@@ -813,12 +775,11 @@
813 ** Return true if a transfer was made and false if not.
814 */
815 static int login_transfer_credentials(
816 const char *zLogin, /* Login we are looking for */
817 const char *zCode, /* Project code of peer repository */
818 const char *zHash, /* HASH from login cookie HASH/CODE/LOGIN */
819 const char *zRemoteAddr /* Request comes from here */
820 ){
821 sqlite3 *pOther = 0; /* The other repository */
822 sqlite3_stmt *pStmt; /* Query against the other repository */
823 char *zSQL; /* SQL of the query against other repo */
824 char *zOtherRepo; /* Filename of the other repository */
@@ -842,24 +803,23 @@
842 constant_time_cmp_function, 0, 0);
843 sqlite3_busy_timeout(pOther, 5000);
844 zSQL = mprintf(
845 "SELECT cexpire FROM user"
846 " WHERE login=%Q"
847 " AND ipaddr=%Q"
848 " AND length(cap)>0"
849 " AND length(pw)>0"
850 " AND cexpire>julianday('now')"
851 " AND constant_time_cmp(cookie,%Q)=0",
852 zLogin, zRemoteAddr, zHash
853 );
854 pStmt = 0;
855 rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
856 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
857 db_multi_exec(
858 "UPDATE user SET cookie=%Q, ipaddr=%Q, cexpire=%.17g"
859 " WHERE login=%Q",
860 zHash, zRemoteAddr,
861 sqlite3_column_double(pStmt, 0), zLogin
862 );
863 nXfer++;
864 }
865 sqlite3_finalize(pStmt);
@@ -879,33 +839,30 @@
879 if( fossil_strcmp(zLogin, "reader")==0 ) return 1;
880 return 0;
881 }
882
883 /*
884 ** Lookup the uid for a non-built-in user with zLogin and zCookie and
885 ** zRemoteAddr. Return 0 if not found.
886 **
887 ** Note that this only searches for logged-in entries with matching
888 ** zCookie (db: user.cookie) and zRemoteAddr (db: user.ipaddr)
889 ** entries.
890 */
891 static int login_find_user(
892 const char *zLogin, /* User name */
893 const char *zCookie, /* Login cookie value */
894 const char *zRemoteAddr /* Abbreviated IP address for valid login */
895 ){
896 int uid;
897 if( login_is_special(zLogin) ) return 0;
898 uid = db_int(0,
899 "SELECT uid FROM user"
900 " WHERE login=%Q"
901 " AND ipaddr=%Q"
902 " AND cexpire>julianday('now')"
903 " AND length(cap)>0"
904 " AND length(pw)>0"
905 " AND constant_time_cmp(cookie,%Q)=0",
906 zLogin, zRemoteAddr, zCookie
907 );
908 return uid;
909 }
910
911 /*
@@ -974,11 +931,10 @@
974 */
975 void login_check_credentials(void){
976 int uid = 0; /* User id */
977 const char *zCookie; /* Text of the login cookie */
978 const char *zIpAddr; /* Raw IP address of the requestor */
979 char *zRemoteAddr; /* Abbreviated IP address of the requestor */
980 const char *zCap = 0; /* Capability string */
981 const char *zPublicPages = 0; /* GLOB patterns of public pages */
982 const char *zLogin = 0; /* Login user for credentials */
983
984 /* Only run this check once. */
@@ -992,11 +948,11 @@
992 ** then there is no need to check user credentials.
993 **
994 ** This feature allows the "fossil ui" command to give the user
995 ** full access rights without having to log in.
996 */
997 zRemoteAddr = ipPrefix(zIpAddr = PD("REMOTE_ADDR","nil"));
998 if( ( cgi_is_loopback(zIpAddr)
999 || (g.fSshClient & CGI_SSH_CLIENT)!=0 )
1000 && g.useLocalauth
1001 && db_get_int("localauth",0)==0
1002 && P("HTTPS")==0
@@ -1041,12 +997,11 @@
1041 ** SECRET is the "captcha-secret" value in the repository.
1042 */
1043 double rTime = atof(zArg);
1044 Blob b;
1045 blob_zero(&b);
1046 blob_appendf(&b, "%s/%s/%s",
1047 zArg, zRemoteAddr, db_get("captcha-secret",""));
1048 sha1sum_blob(&b, &b);
1049 if( fossil_strcmp(zHash, blob_str(&b))==0 ){
1050 uid = db_int(0,
1051 "SELECT uid FROM user WHERE login='anonymous'"
1052 " AND length(cap)>0"
@@ -1059,13 +1014,13 @@
1059 }else{
1060 /* Cookies of the form "HASH/CODE/USER". Search first in the
1061 ** local user table, then the user table for project CODE if we
1062 ** are part of a login-group.
1063 */
1064 uid = login_find_user(zUser, zHash, zRemoteAddr);
1065 if( uid==0 && login_transfer_credentials(zUser,zArg,zHash,zRemoteAddr) ){
1066 uid = login_find_user(zUser, zHash, zRemoteAddr);
1067 if( uid ) record_login_attempt(zUser, zIpAddr, 1);
1068 }
1069 }
1070 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
1071 }
1072
--- src/login.c
+++ src/login.c
@@ -111,36 +111,10 @@
111 }else{
112 fossil_redirect_home();
113 }
114 }
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116 /*
117 ** Return an abbreviated project code. The abbreviation is the first
118 ** 16 characters of the project code.
119 **
120 ** Memory is obtained from malloc.
@@ -299,30 +273,27 @@
273 const char *zExpire = db_get("cookie-expire","8766");
274 int expires = atoi(zExpire)*3600;
275 char *zHash;
276 char *zCookie;
277 const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */
 
278
279 assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data.");
280 zHash = db_text(0,
281 "SELECT cookie FROM user"
282 " WHERE uid=%d"
 
283 " AND cexpire>julianday('now')"
284 " AND length(cookie)>30",
285 uid);
286 if( zHash==0 ) zHash = db_text(0, "SELECT hex(randomblob(25))");
287 zCookie = login_gen_user_cookie_value(zUsername, zHash);
288 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires);
289 record_login_attempt(zUsername, zIpAddr, 1);
290 db_multi_exec(
291 "UPDATE user SET cookie=%Q,"
292 " cexpire=julianday('now')+%d/86400.0 WHERE uid=%d",
293 zHash, expires, uid
294 );
 
295 free(zHash);
296 if( zDest ){
297 *zDest = zCookie;
298 }else{
299 free(zCookie);
@@ -331,34 +302,25 @@
302
303 /* Sets a cookie for an anonymous user login, which looks like this:
304 **
305 ** HASH/TIME/anonymous
306 **
307 ** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret.
 
 
 
 
308 **
309 ** If zCookieDest is not NULL then the generated cookie is assigned to
310 ** *zCookieDest and the caller must eventually free() it.
311 */
312 void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){
313 const char *zNow; /* Current time (julian day number) */
314 char *zCookie; /* The login cookie */
315 const char *zCookieName; /* Name of the login cookie */
316 Blob b; /* Blob used during cookie construction */
 
 
 
 
 
317 zCookieName = login_cookie_name();
318 zNow = db_text("0", "SELECT julianday('now')");
319 assert( zCookieName && zNow );
320 blob_init(&b, zNow, -1);
321 blob_appendf(&b, "/%s", db_get("captcha-secret",""));
322 sha1sum_blob(&b, &b);
323 zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow);
324 blob_reset(&b);
325 cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), 6*3600);
326 if( zCookieDest ){
@@ -813,12 +775,11 @@
775 ** Return true if a transfer was made and false if not.
776 */
777 static int login_transfer_credentials(
778 const char *zLogin, /* Login we are looking for */
779 const char *zCode, /* Project code of peer repository */
780 const char *zHash /* HASH from login cookie HASH/CODE/LOGIN */
 
781 ){
782 sqlite3 *pOther = 0; /* The other repository */
783 sqlite3_stmt *pStmt; /* Query against the other repository */
784 char *zSQL; /* SQL of the query against other repo */
785 char *zOtherRepo; /* Filename of the other repository */
@@ -842,24 +803,23 @@
803 constant_time_cmp_function, 0, 0);
804 sqlite3_busy_timeout(pOther, 5000);
805 zSQL = mprintf(
806 "SELECT cexpire FROM user"
807 " WHERE login=%Q"
 
808 " AND length(cap)>0"
809 " AND length(pw)>0"
810 " AND cexpire>julianday('now')"
811 " AND constant_time_cmp(cookie,%Q)=0",
812 zLogin, zHash
813 );
814 pStmt = 0;
815 rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0);
816 if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
817 db_multi_exec(
818 "UPDATE user SET cookie=%Q, cexpire=%.17g"
819 " WHERE login=%Q",
820 zHash,
821 sqlite3_column_double(pStmt, 0), zLogin
822 );
823 nXfer++;
824 }
825 sqlite3_finalize(pStmt);
@@ -879,33 +839,30 @@
839 if( fossil_strcmp(zLogin, "reader")==0 ) return 1;
840 return 0;
841 }
842
843 /*
844 ** Lookup the uid for a non-built-in user with zLogin and zCookie.
845 ** Return 0 if not found.
846 **
847 ** Note that this only searches for logged-in entries with matching
848 ** zCookie (db: user.cookie) entries.
 
849 */
850 static int login_find_user(
851 const char *zLogin, /* User name */
852 const char *zCookie /* Login cookie value */
 
853 ){
854 int uid;
855 if( login_is_special(zLogin) ) return 0;
856 uid = db_int(0,
857 "SELECT uid FROM user"
858 " WHERE login=%Q"
 
859 " AND cexpire>julianday('now')"
860 " AND length(cap)>0"
861 " AND length(pw)>0"
862 " AND constant_time_cmp(cookie,%Q)=0",
863 zLogin, zCookie
864 );
865 return uid;
866 }
867
868 /*
@@ -974,11 +931,10 @@
931 */
932 void login_check_credentials(void){
933 int uid = 0; /* User id */
934 const char *zCookie; /* Text of the login cookie */
935 const char *zIpAddr; /* Raw IP address of the requestor */
 
936 const char *zCap = 0; /* Capability string */
937 const char *zPublicPages = 0; /* GLOB patterns of public pages */
938 const char *zLogin = 0; /* Login user for credentials */
939
940 /* Only run this check once. */
@@ -992,11 +948,11 @@
948 ** then there is no need to check user credentials.
949 **
950 ** This feature allows the "fossil ui" command to give the user
951 ** full access rights without having to log in.
952 */
953 zIpAddr = PD("REMOTE_ADDR","nil");
954 if( ( cgi_is_loopback(zIpAddr)
955 || (g.fSshClient & CGI_SSH_CLIENT)!=0 )
956 && g.useLocalauth
957 && db_get_int("localauth",0)==0
958 && P("HTTPS")==0
@@ -1041,12 +997,11 @@
997 ** SECRET is the "captcha-secret" value in the repository.
998 */
999 double rTime = atof(zArg);
1000 Blob b;
1001 blob_zero(&b);
1002 blob_appendf(&b, "%s/%s", zArg, db_get("captcha-secret",""));
 
1003 sha1sum_blob(&b, &b);
1004 if( fossil_strcmp(zHash, blob_str(&b))==0 ){
1005 uid = db_int(0,
1006 "SELECT uid FROM user WHERE login='anonymous'"
1007 " AND length(cap)>0"
@@ -1059,13 +1014,13 @@
1014 }else{
1015 /* Cookies of the form "HASH/CODE/USER". Search first in the
1016 ** local user table, then the user table for project CODE if we
1017 ** are part of a login-group.
1018 */
1019 uid = login_find_user(zUser, zHash);
1020 if( uid==0 && login_transfer_credentials(zUser,zArg,zHash) ){
1021 uid = login_find_user(zUser, zHash);
1022 if( uid ) record_login_attempt(zUser, zIpAddr, 1);
1023 }
1024 }
1025 sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zHash);
1026 }
1027
-12
--- src/setup.c
+++ src/setup.c
@@ -402,22 +402,10 @@
402402
@ variable or the "Authentication:" HTTP header to find the username and
403403
@ password. This is another way of supporting Basic Authenitication.
404404
@ (Property: "http_authentication_ok")
405405
@ </p>
406406
@
407
- @ <hr />
408
- entry_attribute("IP address terms used in login cookie", 3,
409
- "ip-prefix-terms", "ipt", "2", 0);
410
- @ <p>The number of octets of of the IP address used in the login cookie
411
- @ when using unencrypted HTTP instead of HTTPS.
412
- @ Set to zero to omit the IP address from the login cookie. A value of
413
- @ 2 is recommended.
414
- @ If the "Redirect to HTTP" above is set to "Always", then the IP address
415
- @ is not used in the login cookie and this setting is irrelevant.
416
- @ (Property: "ip-prefix-terms")
417
- @ </p>
418
- @
419407
@ <hr />
420408
entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
421409
"8766", 0);
422410
@ <p>The number of hours for which a login is valid. This must be a
423411
@ positive number. The default is 8766 hours which is approximately equal
424412
--- src/setup.c
+++ src/setup.c
@@ -402,22 +402,10 @@
402 @ variable or the "Authentication:" HTTP header to find the username and
403 @ password. This is another way of supporting Basic Authenitication.
404 @ (Property: "http_authentication_ok")
405 @ </p>
406 @
407 @ <hr />
408 entry_attribute("IP address terms used in login cookie", 3,
409 "ip-prefix-terms", "ipt", "2", 0);
410 @ <p>The number of octets of of the IP address used in the login cookie
411 @ when using unencrypted HTTP instead of HTTPS.
412 @ Set to zero to omit the IP address from the login cookie. A value of
413 @ 2 is recommended.
414 @ If the "Redirect to HTTP" above is set to "Always", then the IP address
415 @ is not used in the login cookie and this setting is irrelevant.
416 @ (Property: "ip-prefix-terms")
417 @ </p>
418 @
419 @ <hr />
420 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
421 "8766", 0);
422 @ <p>The number of hours for which a login is valid. This must be a
423 @ positive number. The default is 8766 hours which is approximately equal
424
--- src/setup.c
+++ src/setup.c
@@ -402,22 +402,10 @@
402 @ variable or the "Authentication:" HTTP header to find the username and
403 @ password. This is another way of supporting Basic Authenitication.
404 @ (Property: "http_authentication_ok")
405 @ </p>
406 @
 
 
 
 
 
 
 
 
 
 
 
 
407 @ <hr />
408 entry_attribute("Login expiration time", 6, "cookie-expire", "cex",
409 "8766", 0);
410 @ <p>The number of hours for which a login is valid. This must be a
411 @ positive number. The default is 8766 hours which is approximately equal
412

Keyboard Shortcuts

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