| | @@ -230,12 +230,14 @@ |
| 230 | 230 | } |
| 231 | 231 | if( g.perm.Password && zPasswd && (zNew1 = P("n1"))!=0 && (zNew2 = P("n2"))!=0 ){ |
| 232 | 232 | /* The user requests a password change */ |
| 233 | 233 | zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0); |
| 234 | 234 | if( db_int(1, "SELECT 0 FROM user" |
| 235 | | - " WHERE uid=%d AND (pw=%Q OR pw=%Q)", |
| 236 | | - g.userUid, zPasswd, zSha1Pw) ){ |
| 235 | + " WHERE uid=%d" |
| 236 | + " AND (constant_time_eq(pw,%Q)=0" |
| 237 | + " OR constant_time_eq(pw,%Q)=0)", |
| 238 | + g.userUid, zSha1Pw, zPasswd) ){ |
| 237 | 239 | sleep(1); |
| 238 | 240 | zErrMsg = |
| 239 | 241 | @ <p><span class="loginError"> |
| 240 | 242 | @ You entered an incorrect old password while attempting to change |
| 241 | 243 | @ your password. Your password is unchanged. |
| | @@ -308,12 +310,12 @@ |
| 308 | 310 | uid = db_int(0, |
| 309 | 311 | "SELECT uid FROM user" |
| 310 | 312 | " WHERE login=%Q" |
| 311 | 313 | " AND length(cap)>0 AND length(pw)>0" |
| 312 | 314 | " AND login NOT IN ('anonymous','nobody','developer','reader')" |
| 313 | | - " AND (pw=%Q OR pw=%Q)", |
| 314 | | - zUsername, zPasswd, zSha1Pw |
| 315 | + " AND (constant_time_eq(pw,%Q)=0 OR constant_time_eq(pw,%Q)=0)", |
| 316 | + zUsername, zSha1Pw, zPasswd |
| 315 | 317 | ); |
| 316 | 318 | if( uid<=0 ){ |
| 317 | 319 | sleep(1); |
| 318 | 320 | zErrMsg = |
| 319 | 321 | @ <p><span class="loginError"> |
| | @@ -484,17 +486,17 @@ |
| 484 | 486 | if( rc==SQLITE_OK ){ |
| 485 | 487 | sqlite3_create_function(pOther,"now",0,SQLITE_ANY,0,db_now_function,0,0); |
| 486 | 488 | sqlite3_busy_timeout(pOther, 5000); |
| 487 | 489 | zSQL = mprintf( |
| 488 | 490 | "SELECT cexpire FROM user" |
| 489 | | - " WHERE cookie=%Q" |
| 491 | + " WHERE login=%Q" |
| 490 | 492 | " AND ipaddr=%Q" |
| 491 | | - " AND login=%Q" |
| 492 | 493 | " AND length(cap)>0" |
| 493 | 494 | " AND length(pw)>0" |
| 494 | | - " AND cexpire>julianday('now')", |
| 495 | | - zHash, zRemoteAddr, zLogin |
| 495 | + " AND cexpire>julianday('now')" |
| 496 | + " AND constant_time_eq(cookie,%Q)=0", |
| 497 | + zLogin, zRemoteAddr, zHash |
| 496 | 498 | ); |
| 497 | 499 | pStmt = 0; |
| 498 | 500 | rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0); |
| 499 | 501 | if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ |
| 500 | 502 | db_multi_exec( |
| | @@ -527,19 +529,46 @@ |
| 527 | 529 | if( fossil_strcmp(zLogin, "developer")==0 ) return 0; |
| 528 | 530 | if( fossil_strcmp(zLogin, "reader")==0 ) return 0; |
| 529 | 531 | uid = db_int(0, |
| 530 | 532 | "SELECT uid FROM user" |
| 531 | 533 | " WHERE login=%Q" |
| 532 | | - " AND cookie=%Q" |
| 533 | 534 | " AND ipaddr=%Q" |
| 534 | 535 | " AND cexpire>julianday('now')" |
| 535 | 536 | " AND length(cap)>0" |
| 536 | | - " AND length(pw)>0", |
| 537 | | - zLogin, zCookie, zRemoteAddr |
| 537 | + " AND length(pw)>0" |
| 538 | + " AND constant_time_eq(cookie,%Q)=0", |
| 539 | + zLogin, zRemoteAddr, zCookie |
| 538 | 540 | ); |
| 539 | 541 | return uid; |
| 540 | 542 | } |
| 543 | + |
| 544 | +/* |
| 545 | +** SQL function for constant time comparison of two values. |
| 546 | +** Sets result to 0 if two values are equal. |
| 547 | +*/ |
| 548 | +static void constant_time_eq_function( |
| 549 | + sqlite3_context *context, |
| 550 | + int argc, |
| 551 | + sqlite3_value **argv |
| 552 | +){ |
| 553 | + const unsigned char *buf1, *buf2; |
| 554 | + int len, i; |
| 555 | + unsigned char rc = 0; |
| 556 | + |
| 557 | + assert( argc==2 ); |
| 558 | + len = sqlite3_value_bytes(argv[0]); |
| 559 | + if( len==0 || len!=sqlite3_value_bytes(argv[1]) ){ |
| 560 | + rc = 1; |
| 561 | + }else{ |
| 562 | + buf1 = sqlite3_value_text(argv[0]); |
| 563 | + buf2 = sqlite3_value_text(argv[1]); |
| 564 | + for( i=0; i<len; i++ ){ |
| 565 | + rc = rc | (buf1[i] ^ buf2[i]); |
| 566 | + } |
| 567 | + } |
| 568 | + sqlite3_result_int(context, rc); |
| 569 | +} |
| 541 | 570 | |
| 542 | 571 | /* |
| 543 | 572 | ** This routine examines the login cookie to see if it exists and |
| 544 | 573 | ** and is valid. If the login cookie checks out, it then sets |
| 545 | 574 | ** global variables appropriately. Global variables set include |
| | @@ -554,10 +583,13 @@ |
| 554 | 583 | char *zRemoteAddr; /* Abbreviated IP address of the requestor */ |
| 555 | 584 | const char *zCap = 0; /* Capability string */ |
| 556 | 585 | |
| 557 | 586 | /* Only run this check once. */ |
| 558 | 587 | if( g.userUid!=0 ) return; |
| 588 | + |
| 589 | + sqlite3_create_function(g.db, "constant_time_eq", 2, SQLITE_UTF8, 0, |
| 590 | + constant_time_eq_function, 0, 0); |
| 559 | 591 | |
| 560 | 592 | /* If the HTTP connection is coming over 127.0.0.1 and if |
| 561 | 593 | ** local login is disabled and if we are using HTTP and not HTTPS, |
| 562 | 594 | ** then there is no need to check user credentials. |
| 563 | 595 | ** |
| 564 | 596 | |