Fossil SCM
Minor internal API changes to support using a session cookie for logins, but there are side effects which still need to be investigated before exposing that option to the UI, e.g. login groups and any other use of the user.cexpire field.
Commit
ba3cf9c4de03f3e72e76fd18a67d558ef057a217d2fe72cfb50fde9bd067e06e
Parent
d0749d7886a6f47…
2 files changed
+2
-2
+15
-9
+2
-2
| --- src/json_login.c | ||
| +++ src/json_login.c | ||
| @@ -145,13 +145,13 @@ | ||
| 145 | 145 | }else{ |
| 146 | 146 | char * cookie = NULL; |
| 147 | 147 | cson_object * po; |
| 148 | 148 | char * cap = NULL; |
| 149 | 149 | if(anonSeed){ |
| 150 | - login_set_anon_cookie(NULL, &cookie); | |
| 150 | + login_set_anon_cookie(NULL, &cookie, 0); | |
| 151 | 151 | }else{ |
| 152 | - login_set_user_cookie(name, uid, &cookie); | |
| 152 | + login_set_user_cookie(name, uid, &cookie, 0); | |
| 153 | 153 | } |
| 154 | 154 | payload = cson_value_new_object(); |
| 155 | 155 | po = cson_value_get_object(payload); |
| 156 | 156 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 157 | 157 | free(cookie); |
| 158 | 158 |
| --- src/json_login.c | |
| +++ src/json_login.c | |
| @@ -145,13 +145,13 @@ | |
| 145 | }else{ |
| 146 | char * cookie = NULL; |
| 147 | cson_object * po; |
| 148 | char * cap = NULL; |
| 149 | if(anonSeed){ |
| 150 | login_set_anon_cookie(NULL, &cookie); |
| 151 | }else{ |
| 152 | login_set_user_cookie(name, uid, &cookie); |
| 153 | } |
| 154 | payload = cson_value_new_object(); |
| 155 | po = cson_value_get_object(payload); |
| 156 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 157 | free(cookie); |
| 158 |
| --- src/json_login.c | |
| +++ src/json_login.c | |
| @@ -145,13 +145,13 @@ | |
| 145 | }else{ |
| 146 | char * cookie = NULL; |
| 147 | cson_object * po; |
| 148 | char * cap = NULL; |
| 149 | if(anonSeed){ |
| 150 | login_set_anon_cookie(NULL, &cookie, 0); |
| 151 | }else{ |
| 152 | login_set_user_cookie(name, uid, &cookie, 0); |
| 153 | } |
| 154 | payload = cson_value_new_object(); |
| 155 | po = cson_value_get_object(payload); |
| 156 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 157 | free(cookie); |
| 158 |
+15
-9
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -261,19 +261,22 @@ | ||
| 261 | 261 | ** and user.cexpire fields for the given user. |
| 262 | 262 | ** |
| 263 | 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | 265 | ** eventually pass it to free()). |
| 266 | +** | |
| 267 | +** If bSessionCookie is true, the cookie will be a session cookie. | |
| 266 | 268 | */ |
| 267 | 269 | void login_set_user_cookie( |
| 268 | 270 | const char *zUsername, /* User's name */ |
| 269 | 271 | int uid, /* User's ID */ |
| 270 | - char **zDest /* Optional: store generated cookie value. */ | |
| 272 | + char **zDest, /* Optional: store generated cookie value. */ | |
| 273 | + int bSessionCookie /* True for session-only cookie */ | |
| 271 | 274 | ){ |
| 272 | 275 | const char *zCookieName = login_cookie_name(); |
| 273 | - const char *zExpire = db_get("cookie-expire","8766"); | |
| 274 | - int expires = atoi(zExpire)*3600; | |
| 276 | + const char *zExpire = bSessionCookie ? 0 : db_get("cookie-expire","8766"); | |
| 277 | + int expires = bSessionCookie ? 0 : atoi(zExpire)*3600; | |
| 275 | 278 | char *zHash; |
| 276 | 279 | char *zCookie; |
| 277 | 280 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */ |
| 278 | 281 | |
| 279 | 282 | assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data."); |
| @@ -306,31 +309,34 @@ | ||
| 306 | 309 | ** |
| 307 | 310 | ** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret. |
| 308 | 311 | ** |
| 309 | 312 | ** If zCookieDest is not NULL then the generated cookie is assigned to |
| 310 | 313 | ** *zCookieDest and the caller must eventually free() it. |
| 314 | +** | |
| 315 | +** If bSessionCookie is true, the cookie will be a session cookie. | |
| 311 | 316 | */ |
| 312 | -void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest ){ | |
| 317 | +void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest, | |
| 318 | + int bSessionCookie ){ | |
| 313 | 319 | const char *zNow; /* Current time (julian day number) */ |
| 314 | 320 | char *zCookie; /* The login cookie */ |
| 315 | 321 | const char *zCookieName; /* Name of the login cookie */ |
| 316 | 322 | Blob b; /* Blob used during cookie construction */ |
| 323 | + int expires = bSessionCookie ? 0 : 6*3600; | |
| 317 | 324 | zCookieName = login_cookie_name(); |
| 318 | 325 | zNow = db_text("0", "SELECT julianday('now')"); |
| 319 | 326 | assert( zCookieName && zNow ); |
| 320 | 327 | blob_init(&b, zNow, -1); |
| 321 | 328 | blob_appendf(&b, "/%s", db_get("captcha-secret","")); |
| 322 | 329 | sha1sum_blob(&b, &b); |
| 323 | 330 | zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow); |
| 324 | 331 | blob_reset(&b); |
| 325 | - cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), 6*3600); | |
| 332 | + cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); | |
| 326 | 333 | if( zCookieDest ){ |
| 327 | 334 | *zCookieDest = zCookie; |
| 328 | 335 | }else{ |
| 329 | 336 | free(zCookie); |
| 330 | 337 | } |
| 331 | - | |
| 332 | 338 | } |
| 333 | 339 | |
| 334 | 340 | /* |
| 335 | 341 | ** "Unsets" the login cookie (insofar as cookies can be unset) and |
| 336 | 342 | ** clears the current user's (g.userUid) login information from the |
| @@ -601,11 +607,11 @@ | ||
| 601 | 607 | } |
| 602 | 608 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 603 | 609 | zReferer = P("HTTP_REFERER"); |
| 604 | 610 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 605 | 611 | if( uid>0 ){ |
| 606 | - login_set_anon_cookie(zIpAddr, NULL); | |
| 612 | + login_set_anon_cookie(zIpAddr, NULL, 0); | |
| 607 | 613 | record_login_attempt("anonymous", zIpAddr, 1); |
| 608 | 614 | redirect_to_g(); |
| 609 | 615 | } |
| 610 | 616 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 611 | 617 | /* Attempting to log in as a user other than anonymous. |
| @@ -625,11 +631,11 @@ | ||
| 625 | 631 | ** HASH/PROJECT/LOGIN |
| 626 | 632 | ** |
| 627 | 633 | ** where HASH is a random hex number, PROJECT is either project |
| 628 | 634 | ** code prefix, and LOGIN is the user name. |
| 629 | 635 | */ |
| 630 | - login_set_user_cookie(zUsername, uid, NULL); | |
| 636 | + login_set_user_cookie(zUsername, uid, NULL, 0); | |
| 631 | 637 | redirect_to_g(); |
| 632 | 638 | } |
| 633 | 639 | } |
| 634 | 640 | style_header("Login/Logout"); |
| 635 | 641 | style_adunit_config(ADUNIT_OFF); |
| @@ -1598,11 +1604,11 @@ | ||
| 1598 | 1604 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1599 | 1605 | zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr); |
| 1600 | 1606 | fossil_free(zPass); |
| 1601 | 1607 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1602 | 1608 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1603 | - login_set_user_cookie(zUserID, uid, NULL); | |
| 1609 | + login_set_user_cookie(zUserID, uid, NULL, 0); | |
| 1604 | 1610 | if( doAlerts ){ |
| 1605 | 1611 | /* Also make the new user a subscriber. */ |
| 1606 | 1612 | Blob hdr, body; |
| 1607 | 1613 | AlertSender *pSender; |
| 1608 | 1614 | sqlite3_int64 id; /* New subscriber Id */ |
| 1609 | 1615 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -261,19 +261,22 @@ | |
| 261 | ** and user.cexpire fields for the given user. |
| 262 | ** |
| 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | ** eventually pass it to free()). |
| 266 | */ |
| 267 | void login_set_user_cookie( |
| 268 | const char *zUsername, /* User's name */ |
| 269 | int uid, /* User's ID */ |
| 270 | char **zDest /* Optional: store generated cookie value. */ |
| 271 | ){ |
| 272 | const char *zCookieName = login_cookie_name(); |
| 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."); |
| @@ -306,31 +309,34 @@ | |
| 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 ){ |
| 327 | *zCookieDest = zCookie; |
| 328 | }else{ |
| 329 | free(zCookie); |
| 330 | } |
| 331 | |
| 332 | } |
| 333 | |
| 334 | /* |
| 335 | ** "Unsets" the login cookie (insofar as cookies can be unset) and |
| 336 | ** clears the current user's (g.userUid) login information from the |
| @@ -601,11 +607,11 @@ | |
| 601 | } |
| 602 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 603 | zReferer = P("HTTP_REFERER"); |
| 604 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 605 | if( uid>0 ){ |
| 606 | login_set_anon_cookie(zIpAddr, NULL); |
| 607 | record_login_attempt("anonymous", zIpAddr, 1); |
| 608 | redirect_to_g(); |
| 609 | } |
| 610 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 611 | /* Attempting to log in as a user other than anonymous. |
| @@ -625,11 +631,11 @@ | |
| 625 | ** HASH/PROJECT/LOGIN |
| 626 | ** |
| 627 | ** where HASH is a random hex number, PROJECT is either project |
| 628 | ** code prefix, and LOGIN is the user name. |
| 629 | */ |
| 630 | login_set_user_cookie(zUsername, uid, NULL); |
| 631 | redirect_to_g(); |
| 632 | } |
| 633 | } |
| 634 | style_header("Login/Logout"); |
| 635 | style_adunit_config(ADUNIT_OFF); |
| @@ -1598,11 +1604,11 @@ | |
| 1598 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1599 | zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr); |
| 1600 | fossil_free(zPass); |
| 1601 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1602 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1603 | login_set_user_cookie(zUserID, uid, NULL); |
| 1604 | if( doAlerts ){ |
| 1605 | /* Also make the new user a subscriber. */ |
| 1606 | Blob hdr, body; |
| 1607 | AlertSender *pSender; |
| 1608 | sqlite3_int64 id; /* New subscriber Id */ |
| 1609 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -261,19 +261,22 @@ | |
| 261 | ** and user.cexpire fields for the given user. |
| 262 | ** |
| 263 | ** If zDest is not NULL then the generated cookie is copied to |
| 264 | ** *zDdest and ownership is transfered to the caller (who should |
| 265 | ** eventually pass it to free()). |
| 266 | ** |
| 267 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 268 | */ |
| 269 | void login_set_user_cookie( |
| 270 | const char *zUsername, /* User's name */ |
| 271 | int uid, /* User's ID */ |
| 272 | char **zDest, /* Optional: store generated cookie value. */ |
| 273 | int bSessionCookie /* True for session-only cookie */ |
| 274 | ){ |
| 275 | const char *zCookieName = login_cookie_name(); |
| 276 | const char *zExpire = bSessionCookie ? 0 : db_get("cookie-expire","8766"); |
| 277 | int expires = bSessionCookie ? 0 : atoi(zExpire)*3600; |
| 278 | char *zHash; |
| 279 | char *zCookie; |
| 280 | const char *zIpAddr = PD("REMOTE_ADDR","nil"); /* IP address of user */ |
| 281 | |
| 282 | assert((zUsername && *zUsername) && (uid > 0) && "Invalid user data."); |
| @@ -306,31 +309,34 @@ | |
| 309 | ** |
| 310 | ** Where HASH is the sha1sum of TIME/SECRET, in which SECRET is captcha-secret. |
| 311 | ** |
| 312 | ** If zCookieDest is not NULL then the generated cookie is assigned to |
| 313 | ** *zCookieDest and the caller must eventually free() it. |
| 314 | ** |
| 315 | ** If bSessionCookie is true, the cookie will be a session cookie. |
| 316 | */ |
| 317 | void login_set_anon_cookie(const char *zIpAddr, char **zCookieDest, |
| 318 | int bSessionCookie ){ |
| 319 | const char *zNow; /* Current time (julian day number) */ |
| 320 | char *zCookie; /* The login cookie */ |
| 321 | const char *zCookieName; /* Name of the login cookie */ |
| 322 | Blob b; /* Blob used during cookie construction */ |
| 323 | int expires = bSessionCookie ? 0 : 6*3600; |
| 324 | zCookieName = login_cookie_name(); |
| 325 | zNow = db_text("0", "SELECT julianday('now')"); |
| 326 | assert( zCookieName && zNow ); |
| 327 | blob_init(&b, zNow, -1); |
| 328 | blob_appendf(&b, "/%s", db_get("captcha-secret","")); |
| 329 | sha1sum_blob(&b, &b); |
| 330 | zCookie = mprintf("%s/%s/anonymous", blob_buffer(&b), zNow); |
| 331 | blob_reset(&b); |
| 332 | cgi_set_cookie(zCookieName, zCookie, login_cookie_path(), expires); |
| 333 | if( zCookieDest ){ |
| 334 | *zCookieDest = zCookie; |
| 335 | }else{ |
| 336 | free(zCookie); |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | /* |
| 341 | ** "Unsets" the login cookie (insofar as cookies can be unset) and |
| 342 | ** clears the current user's (g.userUid) login information from the |
| @@ -601,11 +607,11 @@ | |
| 607 | } |
| 608 | zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */ |
| 609 | zReferer = P("HTTP_REFERER"); |
| 610 | uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs")); |
| 611 | if( uid>0 ){ |
| 612 | login_set_anon_cookie(zIpAddr, NULL, 0); |
| 613 | record_login_attempt("anonymous", zIpAddr, 1); |
| 614 | redirect_to_g(); |
| 615 | } |
| 616 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 617 | /* Attempting to log in as a user other than anonymous. |
| @@ -625,11 +631,11 @@ | |
| 631 | ** HASH/PROJECT/LOGIN |
| 632 | ** |
| 633 | ** where HASH is a random hex number, PROJECT is either project |
| 634 | ** code prefix, and LOGIN is the user name. |
| 635 | */ |
| 636 | login_set_user_cookie(zUsername, uid, NULL, 0); |
| 637 | redirect_to_g(); |
| 638 | } |
| 639 | } |
| 640 | style_header("Login/Logout"); |
| 641 | style_adunit_config(ADUNIT_OFF); |
| @@ -1598,11 +1604,11 @@ | |
| 1604 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1605 | zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr); |
| 1606 | fossil_free(zPass); |
| 1607 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1608 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1609 | login_set_user_cookie(zUserID, uid, NULL, 0); |
| 1610 | if( doAlerts ){ |
| 1611 | /* Also make the new user a subscriber. */ |
| 1612 | Blob hdr, body; |
| 1613 | AlertSender *pSender; |
| 1614 | sqlite3_int64 id; /* New subscriber Id */ |
| 1615 |