Fossil SCM
Reduce the timeout for anonymous logins to 1 hours. Add the IP address to the anonymous login cookie.
Commit
60a9fac4e1dca5f43cbf68101adaf0f8ac7f7496b8686ded994ab742634dcd77
Parent
639b96b9ad54dbf…
1 file changed
+16
-9
+16
-9
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -341,32 +341,35 @@ | ||
| 341 | 341 | } |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | 344 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 345 | 345 | ** |
| 346 | -** HASH/TIME/anonymous | |
| 346 | +** HASH/TIME:IPADDR/anonymous | |
| 347 | 347 | ** |
| 348 | -** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret. | |
| 348 | +** Where HASH is the sha1sum of TIME:IPADDR/SECRET, in which SECRET | |
| 349 | +** is captcha-secret. | |
| 349 | 350 | ** |
| 350 | 351 | ** If zCookieDest is not NULL then the generated cookie is assigned to |
| 351 | 352 | ** *zCookieDest and the caller must eventually free() it. |
| 352 | 353 | ** |
| 353 | 354 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 354 | 355 | */ |
| 355 | 356 | void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){ |
| 356 | 357 | char *zNow; /* Current time (julian day number) */ |
| 357 | 358 | char *zCookie; /* The login cookie */ |
| 359 | + const char *zIpAddr; /* IP Address */ | |
| 358 | 360 | const char *zCookieName; /* Name of the login cookie */ |
| 359 | 361 | Blob b; /* Blob used during cookie construction */ |
| 360 | - int expires = bSessionCookie ? 0 : 6*3600; | |
| 362 | + int expires = bSessionCookie ? 0 : 3600; /* Valid for 60 minutes */ | |
| 361 | 363 | zCookieName = login_cookie_name(); |
| 362 | 364 | zNow = db_text("0", "SELECT julianday('now')"); |
| 363 | 365 | assert( zCookieName && zNow ); |
| 364 | 366 | blob_init(&b, zNow, -1); |
| 365 | - blob_appendf(&b, "/%z", captcha_secret(0)); | |
| 367 | + zIpAddr = PD("REMOTE_ADDR","nil"); | |
| 368 | + blob_appendf(&b, ":%s/%z", zIpAddr, captcha_secret(0)); | |
| 366 | 369 | sha1sum_blob(&b, &b); |
| 367 | - zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow); | |
| 370 | + zCookie = mprintf("%s/%s:%s/anonymous", blob_buffer(&b), zNow, zIpAddr); | |
| 368 | 371 | blob_reset(&b); |
| 369 | 372 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 370 | 373 | if( zCookieDest ){ |
| 371 | 374 | *zCookieDest = zCookie; |
| 372 | 375 | }else{ |
| @@ -1458,20 +1461,24 @@ | ||
| 1458 | 1461 | } |
| 1459 | 1462 | } |
| 1460 | 1463 | if( zUser==0 ){ |
| 1461 | 1464 | /* Invalid cookie */ |
| 1462 | 1465 | }else if( fossil_strcmp(zUser, "anonymous")==0 ){ |
| 1463 | - /* Cookies of the form "HASH/TIME/anonymous". The TIME must not be | |
| 1464 | - ** too old and the sha1 hash of TIME/SECRET must match HASH. | |
| 1465 | - ** SECRET is the "captcha-secret" value in the repository. | |
| 1466 | + /* Cookies of the form "HASH/TIME:IPADDR/anonymous". The TIME must | |
| 1467 | + ** not be too old and the sha1 hash of TIME:IPADDR/SECRET must match | |
| 1468 | + ** HASH. SECRET is the "captcha-secret" value in the repository. | |
| 1466 | 1469 | */ |
| 1467 | 1470 | double rTime = atof(zArg); |
| 1471 | + const char *zCookieIP; | |
| 1468 | 1472 | Blob b; |
| 1469 | 1473 | char *zSecret; |
| 1470 | 1474 | int n = 0; |
| 1471 | 1475 | |
| 1476 | + zCookieIP = strchr(zArg,':'); | |
| 1477 | + if( zCookieIP && strcmp(zCookieIP+1,zIpAddr)!=0 ) zCookieIP = 0; | |
| 1472 | 1478 | do{ |
| 1479 | + if( zCookieIP==0 ) break; | |
| 1473 | 1480 | blob_zero(&b); |
| 1474 | 1481 | zSecret = captcha_secret(n++); |
| 1475 | 1482 | if( zSecret==0 ) break; |
| 1476 | 1483 | blob_appendf(&b, "%s/%s", zArg, zSecret); |
| 1477 | 1484 | sha1sum_blob(&b, &b); |
| @@ -1478,11 +1485,11 @@ | ||
| 1478 | 1485 | if( fossil_strcmp(zHash, blob_str(&b))==0 ){ |
| 1479 | 1486 | uid = db_int(0, |
| 1480 | 1487 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1481 | 1488 | " AND octet_length(cap)>0" |
| 1482 | 1489 | " AND octet_length(pw)>0" |
| 1483 | - " AND %.17g+0.25>julianday('now')", | |
| 1490 | + " AND %.17g+0.0416667>julianday('now')", | |
| 1484 | 1491 | rTime |
| 1485 | 1492 | ); |
| 1486 | 1493 | } |
| 1487 | 1494 | }while( uid==0 ); |
| 1488 | 1495 | blob_reset(&b); |
| 1489 | 1496 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -341,32 +341,35 @@ | |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 345 | ** |
| 346 | ** HASH/TIME/anonymous |
| 347 | ** |
| 348 | ** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret. |
| 349 | ** |
| 350 | ** If zCookieDest is not NULL then the generated cookie is assigned to |
| 351 | ** *zCookieDest and the caller must eventually free() it. |
| 352 | ** |
| 353 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 354 | */ |
| 355 | void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){ |
| 356 | char *zNow; /* Current time (julian day number) */ |
| 357 | char *zCookie; /* The login cookie */ |
| 358 | const char *zCookieName; /* Name of the login cookie */ |
| 359 | Blob b; /* Blob used during cookie construction */ |
| 360 | int expires = bSessionCookie ? 0 : 6*3600; |
| 361 | zCookieName = login_cookie_name(); |
| 362 | zNow = db_text("0", "SELECT julianday('now')"); |
| 363 | assert( zCookieName && zNow ); |
| 364 | blob_init(&b, zNow, -1); |
| 365 | blob_appendf(&b, "/%z", captcha_secret(0)); |
| 366 | sha1sum_blob(&b, &b); |
| 367 | zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow); |
| 368 | blob_reset(&b); |
| 369 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 370 | if( zCookieDest ){ |
| 371 | *zCookieDest = zCookie; |
| 372 | }else{ |
| @@ -1458,20 +1461,24 @@ | |
| 1458 | } |
| 1459 | } |
| 1460 | if( zUser==0 ){ |
| 1461 | /* Invalid cookie */ |
| 1462 | }else if( fossil_strcmp(zUser, "anonymous")==0 ){ |
| 1463 | /* Cookies of the form "HASH/TIME/anonymous". The TIME must not be |
| 1464 | ** too old and the sha1 hash of TIME/SECRET must match HASH. |
| 1465 | ** SECRET is the "captcha-secret" value in the repository. |
| 1466 | */ |
| 1467 | double rTime = atof(zArg); |
| 1468 | Blob b; |
| 1469 | char *zSecret; |
| 1470 | int n = 0; |
| 1471 | |
| 1472 | do{ |
| 1473 | blob_zero(&b); |
| 1474 | zSecret = captcha_secret(n++); |
| 1475 | if( zSecret==0 ) break; |
| 1476 | blob_appendf(&b, "%s/%s", zArg, zSecret); |
| 1477 | sha1sum_blob(&b, &b); |
| @@ -1478,11 +1485,11 @@ | |
| 1478 | if( fossil_strcmp(zHash, blob_str(&b))==0 ){ |
| 1479 | uid = db_int(0, |
| 1480 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1481 | " AND octet_length(cap)>0" |
| 1482 | " AND octet_length(pw)>0" |
| 1483 | " AND %.17g+0.25>julianday('now')", |
| 1484 | rTime |
| 1485 | ); |
| 1486 | } |
| 1487 | }while( uid==0 ); |
| 1488 | blob_reset(&b); |
| 1489 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -341,32 +341,35 @@ | |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | /* Sets a cookie for an anonymous user login, which looks like this: |
| 345 | ** |
| 346 | ** HASH/TIME:IPADDR/anonymous |
| 347 | ** |
| 348 | ** Where HASH is the sha1sum of TIME:IPADDR/SECRET, in which SECRET |
| 349 | ** is captcha-secret. |
| 350 | ** |
| 351 | ** If zCookieDest is not NULL then the generated cookie is assigned to |
| 352 | ** *zCookieDest and the caller must eventually free() it. |
| 353 | ** |
| 354 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 355 | */ |
| 356 | void login_set_anon_cookie(char **zCookieDest, int bSessionCookie){ |
| 357 | char *zNow; /* Current time (julian day number) */ |
| 358 | char *zCookie; /* The login cookie */ |
| 359 | const char *zIpAddr; /* IP Address */ |
| 360 | const char *zCookieName; /* Name of the login cookie */ |
| 361 | Blob b; /* Blob used during cookie construction */ |
| 362 | int expires = bSessionCookie ? 0 : 3600; /* Valid for 60 minutes */ |
| 363 | zCookieName = login_cookie_name(); |
| 364 | zNow = db_text("0", "SELECT julianday('now')"); |
| 365 | assert( zCookieName && zNow ); |
| 366 | blob_init(&b, zNow, -1); |
| 367 | zIpAddr = PD("REMOTE_ADDR","nil"); |
| 368 | blob_appendf(&b, ":%s/%z", zIpAddr, captcha_secret(0)); |
| 369 | sha1sum_blob(&b, &b); |
| 370 | zCookie = mprintf("%s/%s:%s/anonymous", blob_buffer(&b), zNow, zIpAddr); |
| 371 | blob_reset(&b); |
| 372 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 373 | if( zCookieDest ){ |
| 374 | *zCookieDest = zCookie; |
| 375 | }else{ |
| @@ -1458,20 +1461,24 @@ | |
| 1461 | } |
| 1462 | } |
| 1463 | if( zUser==0 ){ |
| 1464 | /* Invalid cookie */ |
| 1465 | }else if( fossil_strcmp(zUser, "anonymous")==0 ){ |
| 1466 | /* Cookies of the form "HASH/TIME:IPADDR/anonymous". The TIME must |
| 1467 | ** not be too old and the sha1 hash of TIME:IPADDR/SECRET must match |
| 1468 | ** HASH. SECRET is the "captcha-secret" value in the repository. |
| 1469 | */ |
| 1470 | double rTime = atof(zArg); |
| 1471 | const char *zCookieIP; |
| 1472 | Blob b; |
| 1473 | char *zSecret; |
| 1474 | int n = 0; |
| 1475 | |
| 1476 | zCookieIP = strchr(zArg,':'); |
| 1477 | if( zCookieIP && strcmp(zCookieIP+1,zIpAddr)!=0 ) zCookieIP = 0; |
| 1478 | do{ |
| 1479 | if( zCookieIP==0 ) break; |
| 1480 | blob_zero(&b); |
| 1481 | zSecret = captcha_secret(n++); |
| 1482 | if( zSecret==0 ) break; |
| 1483 | blob_appendf(&b, "%s/%s", zArg, zSecret); |
| 1484 | sha1sum_blob(&b, &b); |
| @@ -1478,11 +1485,11 @@ | |
| 1485 | if( fossil_strcmp(zHash, blob_str(&b))==0 ){ |
| 1486 | uid = db_int(0, |
| 1487 | "SELECT uid FROM user WHERE login='anonymous'" |
| 1488 | " AND octet_length(cap)>0" |
| 1489 | " AND octet_length(pw)>0" |
| 1490 | " AND %.17g+0.0416667>julianday('now')", |
| 1491 | rTime |
| 1492 | ); |
| 1493 | } |
| 1494 | }while( uid==0 ); |
| 1495 | blob_reset(&b); |
| 1496 |