Fossil SCM

Merge the fix to the login-by-email-address patch.

drh 2018-08-12 10:42 trunk merge
Commit 9b4e157b1e1e51247b285e6773fe510de12f71b3e58d26491262a557ce5a9299
3 files changed +2 -2 +22 -10 +4 -16
--- src/json_login.c
+++ src/json_login.c
@@ -124,21 +124,21 @@
124124
125125
#if 0
126126
{
127127
/* only for debugging the PD()-incorrect-result problem */
128128
cson_object * o = NULL;
129
- uid = login_search_uid( name, pw );
129
+ uid = login_search_uid( &name, pw );
130130
payload = cson_value_new_object();
131131
o = cson_value_get_object(payload);
132132
cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
133133
cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
134134
return payload;
135135
}
136136
#endif
137137
uid = anonSeed
138138
? login_is_valid_anonymous(name, pw, anonSeed)
139
- : login_search_uid(name, pw)
139
+ : login_search_uid(&name, pw)
140140
;
141141
if( !uid ){
142142
g.json.resultCode = preciseErrors
143143
? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
144144
: FSL_JSON_E_LOGIN_FAILED;
145145
--- src/json_login.c
+++ src/json_login.c
@@ -124,21 +124,21 @@
124
125 #if 0
126 {
127 /* only for debugging the PD()-incorrect-result problem */
128 cson_object * o = NULL;
129 uid = login_search_uid( name, pw );
130 payload = cson_value_new_object();
131 o = cson_value_get_object(payload);
132 cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
133 cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
134 return payload;
135 }
136 #endif
137 uid = anonSeed
138 ? login_is_valid_anonymous(name, pw, anonSeed)
139 : login_search_uid(name, pw)
140 ;
141 if( !uid ){
142 g.json.resultCode = preciseErrors
143 ? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
144 : FSL_JSON_E_LOGIN_FAILED;
145
--- src/json_login.c
+++ src/json_login.c
@@ -124,21 +124,21 @@
124
125 #if 0
126 {
127 /* only for debugging the PD()-incorrect-result problem */
128 cson_object * o = NULL;
129 uid = login_search_uid( &name, pw );
130 payload = cson_value_new_object();
131 o = cson_value_get_object(payload);
132 cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
133 cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
134 return payload;
135 }
136 #endif
137 uid = anonSeed
138 ? login_is_valid_anonymous(name, pw, anonSeed)
139 : login_search_uid(&name, pw)
140 ;
141 if( !uid ){
142 g.json.resultCode = preciseErrors
143 ? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
144 : FSL_JSON_E_LOGIN_FAILED;
145
+22 -10
--- src/login.c
+++ src/login.c
@@ -206,41 +206,53 @@
206206
/*
207207
** Searches for the user ID matching the given name and password.
208208
** On success it returns a positive value. On error it returns 0.
209209
** On serious (DB-level) error it will probably exit.
210210
**
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
+**
211219
** zPassword may be either the plain-text form or the encrypted
212220
** form of the user's password.
213221
*/
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);
216224
int uid = db_int(0,
217225
"SELECT uid FROM user"
218226
" WHERE login=%Q"
219227
" AND length(cap)>0 AND length(pw)>0"
220228
" AND login NOT IN ('anonymous','nobody','developer','reader')"
221229
" AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
222230
" AND (info NOT LIKE '%%expires 20%%'"
223231
" OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
224
- zUsername, zSha1Pw, zPasswd
232
+ *pzUsername, zSha1Pw, zPasswd
225233
);
226234
227235
/* 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
229237
** email address instead of their login. Try again to match the user
230238
** against email addresses contained in the "info" field.
231239
*/
232
- if( uid==0 && strchr(zUsername,'@')!=0 ){
240
+ if( uid==0 && strchr(*pzUsername,'@')!=0 ){
233241
Stmt q;
234242
db_prepare(&q,
235243
"SELECT login FROM user"
236244
" WHERE find_emailaddr(info)=%Q"
237245
" AND instr(login,'@')==0",
238
- zUsername
246
+ *pzUsername
239247
);
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
+ }
242254
}
243255
db_finalize(&q);
244256
}
245257
free(zSha1Pw);
246258
return uid;
@@ -650,11 +662,11 @@
650662
redirect_to_g();
651663
}
652664
if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
653665
/* Attempting to log in as a user other than anonymous.
654666
*/
655
- uid = login_search_uid(zUsername, zPasswd);
667
+ uid = login_search_uid(&zUsername, zPasswd);
656668
if( uid<=0 ){
657669
sleep(1);
658670
zErrMsg =
659671
@ <p><span class="loginError">
660672
@ You entered an unknown user or an incorrect password.
@@ -951,11 +963,11 @@
951963
zPasswd = &zDecode[i+1];
952964
953965
/* Attempting to log in as the user provided by HTTP
954966
** basic auth
955967
*/
956
- uid = login_search_uid(zUsername, zPasswd);
968
+ uid = login_search_uid(&zUsername, zPasswd);
957969
if( uid>0 ){
958970
record_login_attempt(zUsername, zIpAddr, 1);
959971
}else{
960972
record_login_attempt(zUsername, zIpAddr, 0);
961973
962974
--- src/login.c
+++ src/login.c
@@ -206,41 +206,53 @@
206 /*
207 ** Searches for the user ID matching the given name and password.
208 ** On success it returns a positive value. On error it returns 0.
209 ** On serious (DB-level) error it will probably exit.
210 **
 
 
 
 
 
 
 
 
211 ** zPassword may be either the plain-text form or the encrypted
212 ** form of the user's password.
213 */
214 int login_search_uid(const char *zUsername, const char *zPasswd){
215 char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
216 int uid = db_int(0,
217 "SELECT uid FROM user"
218 " WHERE login=%Q"
219 " AND length(cap)>0 AND length(pw)>0"
220 " AND login NOT IN ('anonymous','nobody','developer','reader')"
221 " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
222 " AND (info NOT LIKE '%%expires 20%%'"
223 " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
224 zUsername, zSha1Pw, zPasswd
225 );
226
227 /* 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
229 ** email address instead of their login. Try again to match the user
230 ** against email addresses contained in the "info" field.
231 */
232 if( uid==0 && strchr(zUsername,'@')!=0 ){
233 Stmt q;
234 db_prepare(&q,
235 "SELECT login FROM user"
236 " WHERE find_emailaddr(info)=%Q"
237 " AND instr(login,'@')==0",
238 zUsername
239 );
240 while( uid==0 && db_step(&q)==SQLITE_ROW ){
241 uid = login_search_uid(db_column_text(&q,0),zPasswd);
 
 
 
 
242 }
243 db_finalize(&q);
244 }
245 free(zSha1Pw);
246 return uid;
@@ -650,11 +662,11 @@
650 redirect_to_g();
651 }
652 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
653 /* Attempting to log in as a user other than anonymous.
654 */
655 uid = login_search_uid(zUsername, zPasswd);
656 if( uid<=0 ){
657 sleep(1);
658 zErrMsg =
659 @ <p><span class="loginError">
660 @ You entered an unknown user or an incorrect password.
@@ -951,11 +963,11 @@
951 zPasswd = &zDecode[i+1];
952
953 /* Attempting to log in as the user provided by HTTP
954 ** basic auth
955 */
956 uid = login_search_uid(zUsername, zPasswd);
957 if( uid>0 ){
958 record_login_attempt(zUsername, zIpAddr, 1);
959 }else{
960 record_login_attempt(zUsername, zIpAddr, 0);
961
962
--- src/login.c
+++ src/login.c
@@ -206,41 +206,53 @@
206 /*
207 ** Searches for the user ID matching the given name and password.
208 ** On success it returns a positive value. On error it returns 0.
209 ** On serious (DB-level) error it will probably exit.
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 **
219 ** zPassword may be either the plain-text form or the encrypted
220 ** form of the user's password.
221 */
222 int login_search_uid(const char **pzUsername, const char *zPasswd){
223 char *zSha1Pw = sha1_shared_secret(zPasswd, *pzUsername, 0);
224 int uid = db_int(0,
225 "SELECT uid FROM user"
226 " WHERE login=%Q"
227 " AND length(cap)>0 AND length(pw)>0"
228 " AND login NOT IN ('anonymous','nobody','developer','reader')"
229 " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
230 " AND (info NOT LIKE '%%expires 20%%'"
231 " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
232 *pzUsername, zSha1Pw, zPasswd
233 );
234
235 /* If we did not find a login on the first attempt, and the username
236 ** looks like an email address, then perhaps the user entered their
237 ** email address instead of their login. Try again to match the user
238 ** against email addresses contained in the "info" field.
239 */
240 if( uid==0 && strchr(*pzUsername,'@')!=0 ){
241 Stmt q;
242 db_prepare(&q,
243 "SELECT login FROM user"
244 " WHERE find_emailaddr(info)=%Q"
245 " AND instr(login,'@')==0",
246 *pzUsername
247 );
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 }
254 }
255 db_finalize(&q);
256 }
257 free(zSha1Pw);
258 return uid;
@@ -650,11 +662,11 @@
662 redirect_to_g();
663 }
664 if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
665 /* Attempting to log in as a user other than anonymous.
666 */
667 uid = login_search_uid(&zUsername, zPasswd);
668 if( uid<=0 ){
669 sleep(1);
670 zErrMsg =
671 @ <p><span class="loginError">
672 @ You entered an unknown user or an incorrect password.
@@ -951,11 +963,11 @@
963 zPasswd = &zDecode[i+1];
964
965 /* Attempting to log in as the user provided by HTTP
966 ** basic auth
967 */
968 uid = login_search_uid(&zUsername, zPasswd);
969 if( uid>0 ){
970 record_login_attempt(zUsername, zIpAddr, 1);
971 }else{
972 record_login_attempt(zUsername, zIpAddr, 0);
973
974
+4 -16
--- src/smtp.c
+++ src/smtp.c
@@ -1353,27 +1353,15 @@
13531353
}
13541354
13551355
/*
13561356
** Try to log in for zUser and zPass.
13571357
**
1358
-** If zUser/zPass does not work as written, then modify zUser by
1359
-** omitting everything after the "@" (if there is one) and trying
1360
-** again.
1358
+** zUser can either point to a Fossil user name or to an email address
1359
+** found in the user table's info field, in angle brackets.
13611360
*/
1362
-static int pop3_login(char *zUser, char *zPass){
1363
- int uid;
1364
- int i;
1365
- uid = login_search_uid(zUser, zPass);
1366
- if( uid ) return 1;
1367
- for(i=0; zUser[i] && zUser[i]!='@'; i++){}
1368
- if( zUser[i]=='@' ){
1369
- zUser[i] = 0;
1370
- uid = login_search_uid(zUser, zPass);
1371
- if( uid ) return 1;
1372
- zUser[i] = '@';
1373
- }
1374
- return 0;
1361
+static int pop3_login(const char *zUser, char *zPass){
1362
+ return login_search_uid(&zUser, zPass) != 0;
13751363
}
13761364
13771365
/*
13781366
** COMMAND: pop3d
13791367
**
13801368
--- src/smtp.c
+++ src/smtp.c
@@ -1353,27 +1353,15 @@
1353 }
1354
1355 /*
1356 ** Try to log in for zUser and zPass.
1357 **
1358 ** If zUser/zPass does not work as written, then modify zUser by
1359 ** omitting everything after the "@" (if there is one) and trying
1360 ** again.
1361 */
1362 static int pop3_login(char *zUser, char *zPass){
1363 int uid;
1364 int i;
1365 uid = login_search_uid(zUser, zPass);
1366 if( uid ) return 1;
1367 for(i=0; zUser[i] && zUser[i]!='@'; i++){}
1368 if( zUser[i]=='@' ){
1369 zUser[i] = 0;
1370 uid = login_search_uid(zUser, zPass);
1371 if( uid ) return 1;
1372 zUser[i] = '@';
1373 }
1374 return 0;
1375 }
1376
1377 /*
1378 ** COMMAND: pop3d
1379 **
1380
--- src/smtp.c
+++ src/smtp.c
@@ -1353,27 +1353,15 @@
1353 }
1354
1355 /*
1356 ** Try to log in for zUser and zPass.
1357 **
1358 ** zUser can either point to a Fossil user name or to an email address
1359 ** found in the user table's info field, in angle brackets.
 
1360 */
1361 static int pop3_login(const char *zUser, char *zPass){
1362 return login_search_uid(&zUser, zPass) != 0;
 
 
 
 
 
 
 
 
 
 
 
1363 }
1364
1365 /*
1366 ** COMMAND: pop3d
1367 **
1368

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button