| | @@ -206,41 +206,53 @@ |
| 206 | 206 | /* |
| 207 | 207 | ** Searches for the user ID matching the given name and password. |
| 208 | 208 | ** On success it returns a positive value. On error it returns 0. |
| 209 | 209 | ** On serious (DB-level) error it will probably exit. |
| 210 | 210 | ** |
| 211 | +** zUsername uses double indirection because we may re-point *zUsername |
| 212 | +** at a C string allocated with fossil_strdup() if you pass an email |
| 213 | +** address instead and we find that address in the user table's info |
| 214 | +** field, which is expected to contain a string of the form "Human Name |
| 215 | +** <[email protected]>". In that case, *zUsername will point to that |
| 216 | +** user's actual login name on return, causing a leak unless the caller |
| 217 | +** is diligent enough to check whether its pointer was re-pointed. |
| 218 | +** |
| 211 | 219 | ** zPassword may be either the plain-text form or the encrypted |
| 212 | 220 | ** form of the user's password. |
| 213 | 221 | */ |
| 214 | | -int login_search_uid(const char *zUsername, const char *zPasswd){ |
| 215 | | - char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0); |
| 222 | +int login_search_uid(const char **pzUsername, const char *zPasswd){ |
| 223 | + char *zSha1Pw = sha1_shared_secret(zPasswd, *pzUsername, 0); |
| 216 | 224 | int uid = db_int(0, |
| 217 | 225 | "SELECT uid FROM user" |
| 218 | 226 | " WHERE login=%Q" |
| 219 | 227 | " AND length(cap)>0 AND length(pw)>0" |
| 220 | 228 | " AND login NOT IN ('anonymous','nobody','developer','reader')" |
| 221 | 229 | " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))" |
| 222 | 230 | " AND (info NOT LIKE '%%expires 20%%'" |
| 223 | 231 | " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))", |
| 224 | | - zUsername, zSha1Pw, zPasswd |
| 232 | + *pzUsername, zSha1Pw, zPasswd |
| 225 | 233 | ); |
| 226 | 234 | |
| 227 | 235 | /* If we did not find a login on the first attempt, and the username |
| 228 | | - ** looks like an email address, the perhaps the user entired their |
| 236 | + ** looks like an email address, then perhaps the user entered their |
| 229 | 237 | ** email address instead of their login. Try again to match the user |
| 230 | 238 | ** against email addresses contained in the "info" field. |
| 231 | 239 | */ |
| 232 | | - if( uid==0 && strchr(zUsername,'@')!=0 ){ |
| 240 | + if( uid==0 && strchr(*pzUsername,'@')!=0 ){ |
| 233 | 241 | Stmt q; |
| 234 | 242 | db_prepare(&q, |
| 235 | 243 | "SELECT login FROM user" |
| 236 | 244 | " WHERE find_emailaddr(info)=%Q" |
| 237 | 245 | " AND instr(login,'@')==0", |
| 238 | | - zUsername |
| 246 | + *pzUsername |
| 239 | 247 | ); |
| 240 | | - while( uid==0 && db_step(&q)==SQLITE_ROW ){ |
| 241 | | - uid = login_search_uid(db_column_text(&q,0),zPasswd); |
| 248 | + while( db_step(&q)==SQLITE_ROW ){ |
| 249 | + const char *zLogin = db_column_text(&q,0); |
| 250 | + if( (uid = login_search_uid(&zLogin, zPasswd) ) != 0 ){ |
| 251 | + *pzUsername = fossil_strdup(zLogin); |
| 252 | + break; |
| 253 | + } |
| 242 | 254 | } |
| 243 | 255 | db_finalize(&q); |
| 244 | 256 | } |
| 245 | 257 | free(zSha1Pw); |
| 246 | 258 | return uid; |
| | @@ -650,11 +662,11 @@ |
| 650 | 662 | redirect_to_g(); |
| 651 | 663 | } |
| 652 | 664 | if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){ |
| 653 | 665 | /* Attempting to log in as a user other than anonymous. |
| 654 | 666 | */ |
| 655 | | - uid = login_search_uid(zUsername, zPasswd); |
| 667 | + uid = login_search_uid(&zUsername, zPasswd); |
| 656 | 668 | if( uid<=0 ){ |
| 657 | 669 | sleep(1); |
| 658 | 670 | zErrMsg = |
| 659 | 671 | @ <p><span class="loginError"> |
| 660 | 672 | @ You entered an unknown user or an incorrect password. |
| | @@ -951,11 +963,11 @@ |
| 951 | 963 | zPasswd = &zDecode[i+1]; |
| 952 | 964 | |
| 953 | 965 | /* Attempting to log in as the user provided by HTTP |
| 954 | 966 | ** basic auth |
| 955 | 967 | */ |
| 956 | | - uid = login_search_uid(zUsername, zPasswd); |
| 968 | + uid = login_search_uid(&zUsername, zPasswd); |
| 957 | 969 | if( uid>0 ){ |
| 958 | 970 | record_login_attempt(zUsername, zIpAddr, 1); |
| 959 | 971 | }else{ |
| 960 | 972 | record_login_attempt(zUsername, zIpAddr, 0); |
| 961 | 973 | |
| 962 | 974 | |