Index: src/blob.c ================================================================== --- src/blob.c +++ src/blob.c @@ -311,10 +311,36 @@ sz = szA @ You entered an incorrect old password while attempting to change @ your password. Your password is unchanged. @@ -308,12 +310,12 @@ uid = db_int(0, "SELECT uid FROM user" " WHERE login=%Q" " AND length(cap)>0 AND length(pw)>0" " AND login NOT IN ('anonymous','nobody','developer','reader')" - " AND (pw=%Q OR pw=%Q)", - zUsername, zPasswd, zSha1Pw + " AND (constant_time_cmp(pw,%Q)=0 OR constant_time_cmp(pw,%Q)=0)", + zUsername, zSha1Pw, zPasswd ); if( uid<=0 ){ sleep(1); zErrMsg = @

@@ -451,10 +453,37 @@ @ @ } style_footer(); } + +/* +** SQL function for constant time comparison of two values. +** Sets result to 0 if two values are equal. +*/ +static void constant_time_cmp_function( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *buf1, *buf2; + int len, i; + unsigned char rc = 0; + + assert( argc==2 ); + len = sqlite3_value_bytes(argv[0]); + if( len==0 || len!=sqlite3_value_bytes(argv[1]) ){ + rc = 1; + }else{ + buf1 = sqlite3_value_text(argv[0]); + buf2 = sqlite3_value_text(argv[1]); + for( i=0; i0" " AND length(pw)>0" - " AND cexpire>julianday('now')", - zHash, zRemoteAddr, zLogin + " AND cexpire>julianday('now')" + " AND constant_time_cmp(cookie,%Q)=0", + zLogin, zRemoteAddr, zHash ); pStmt = 0; rc = sqlite3_prepare_v2(pOther, zSQL, -1, &pStmt, 0); if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){ db_multi_exec( @@ -527,16 +558,16 @@ if( fossil_strcmp(zLogin, "developer")==0 ) return 0; if( fossil_strcmp(zLogin, "reader")==0 ) return 0; uid = db_int(0, "SELECT uid FROM user" " WHERE login=%Q" - " AND cookie=%Q" " AND ipaddr=%Q" " AND cexpire>julianday('now')" " AND length(cap)>0" - " AND length(pw)>0", - zLogin, zCookie, zRemoteAddr + " AND length(pw)>0" + " AND constant_time_cmp(cookie,%Q)=0", + zLogin, zRemoteAddr, zCookie ); return uid; } /* @@ -554,10 +585,13 @@ char *zRemoteAddr; /* Abbreviated IP address of the requestor */ const char *zCap = 0; /* Capability string */ /* Only run this check once. */ if( g.userUid!=0 ) return; + + sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0, + constant_time_cmp_function, 0, 0); /* If the HTTP connection is coming over 127.0.0.1 and if ** local login is disabled and if we are using HTTP and not HTTPS, ** then there is no need to check user credentials. ** Index: src/xfer.c ================================================================== --- src/xfer.c +++ src/xfer.c @@ -573,11 +573,11 @@ blob_zero(&combined); blob_copy(&combined, pNonce); blob_append(&combined, blob_buffer(&pw), szPw); sha1sum_blob(&combined, &hash); assert( blob_size(&hash)==40 ); - rc = blob_compare(&hash, pSig); + rc = blob_constant_time_cmp(&hash, pSig); blob_reset(&hash); blob_reset(&combined); if( rc!=0 && szPw!=40 ){ /* If this server stores cleartext passwords and the password did not ** match, then perhaps the client is sending SHA1 passwords. Try @@ -588,11 +588,11 @@ blob_zero(&combined); blob_copy(&combined, pNonce); blob_append(&combined, zSecret, -1); free(zSecret); sha1sum_blob(&combined, &hash); - rc = blob_compare(&hash, pSig); + rc = blob_constant_time_cmp(&hash, pSig); blob_reset(&hash); blob_reset(&combined); } if( rc==0 ){ const char *zCap;