Fossil

Check-in [33522ff4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix to checkin [8c91be8b], which was intended to allow the user to log in with the email found in the contact info field of the user table. That checkin is fine as far as it goes, but it only works if the caller doesn't subsequently try to use the passed user name for anything else, since it isn't actually a user name. This checkin causes the low-level login checking function to re-point the user name pointer at the actual login name discovered while scanning for matching email addresses.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | login-with-email
Files: files | file ages | folders
SHA3-256:33522ff4e6f074983f3ec0418ffdfe8eb98c8098f0a315412c4be13e9412e2b5
User & Date: wyoung 2018-08-11 16:59:58
Context
2018-08-11
23:51
Coding style tweak. Closed-Leaf check-in: 52b9caa5 user: mistachkin tags: login-with-email
16:59
Fix to checkin [8c91be8b], which was intended to allow the user to log in with the email found in the contact info field of the user table. That checkin is fine as far as it goes, but it only works if the caller doesn't subsequently try to use the passed user name for anything else, since it isn't actually a user name. This checkin causes the low-level login checking function to re-point the user name pointer at the actual login name discovered while scanning for matching email addresses. check-in: 33522ff4 user: wyoung tags: login-with-email
2018-08-10
23:28
Try to put the human name of the person who posted on the From: line of email notifications for new forum posts. check-in: ad419331 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/json_login.c.

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    }
  }

#if 0
  {
    /* only for debugging the PD()-incorrect-result problem */
    cson_object * o = NULL;
    uid = login_search_uid( name, pw );
    payload = cson_value_new_object();
    o = cson_value_get_object(payload);
    cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
    cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
    return payload;
  }
#endif
  uid = anonSeed
    ? login_is_valid_anonymous(name, pw, anonSeed)
    : login_search_uid(name, pw)
    ;
  if( !uid ){
    g.json.resultCode = preciseErrors
      ? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
      : FSL_JSON_E_LOGIN_FAILED;
    return NULL;
  }else{







|









|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    }
  }

#if 0
  {
    /* only for debugging the PD()-incorrect-result problem */
    cson_object * o = NULL;
    uid = login_search_uid( &name, pw );
    payload = cson_value_new_object();
    o = cson_value_get_object(payload);
    cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
    cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
    return payload;
  }
#endif
  uid = anonSeed
    ? login_is_valid_anonymous(name, pw, anonSeed)
    : login_search_uid(&name, pw)
    ;
  if( !uid ){
    g.json.resultCode = preciseErrors
      ? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
      : FSL_JSON_E_LOGIN_FAILED;
    return NULL;
  }else{

Changes to src/login.c.

204
205
206
207
208
209
210








211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241




242
243
244
245
246
247
248
...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
...
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
}

/*
** Searches for the user ID matching the given name and password.
** On success it returns a positive value. On error it returns 0.
** On serious (DB-level) error it will probably exit.
**








** zPassword may be either the plain-text form or the encrypted
** form of the user's password.
*/
int login_search_uid(const char *zUsername, const char *zPasswd){
  char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
  int 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 (length(pw)<>40 AND pw=%Q))"
    "   AND (info NOT LIKE '%%expires 20%%'"
    "      OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
    zUsername, zSha1Pw, zPasswd
  );

  /* If we did not find a login on the first attempt, and the username
  ** looks like an email address, the perhaps the user entired their
  ** email address instead of their login.  Try again to match the user
  ** against email addresses contained in the "info" field.
  */
  if( uid==0 && strchr(zUsername,'@')!=0 ){
    Stmt q;
    db_prepare(&q,
      "SELECT login FROM user"
      " WHERE find_emailaddr(info)=%Q"
      "   AND instr(login,'@')==0",
      zUsername
    );
    while( uid==0 && db_step(&q)==SQLITE_ROW ){
       uid = login_search_uid(db_column_text(&q,0),zPasswd);




    }
    db_finalize(&q);
  }    
  free(zSha1Pw);
  return uid;
}

................................................................................
    login_set_anon_cookie(zIpAddr, NULL);
    record_login_attempt("anonymous", zIpAddr, 1);
    redirect_to_g();
  }
  if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
    /* Attempting to log in as a user other than anonymous.
    */
    uid = login_search_uid(zUsername, zPasswd);
    if( uid<=0 ){
      sleep(1);
      zErrMsg =
         @ <p><span class="loginError">
         @ You entered an unknown user or an incorrect password.
         @ </span></p>
      ;
................................................................................
    zDecode[i] = 0;
    zUsername = zDecode;
    zPasswd = &zDecode[i+1];

    /* Attempting to log in as the user provided by HTTP
    ** basic auth
    */
    uid = login_search_uid(zUsername, zPasswd);
    if( uid>0 ){
      record_login_attempt(zUsername, zIpAddr, 1);
    }else{
      record_login_attempt(zUsername, zIpAddr, 0);

      /* The user attempted to login specifically with HTTP basic
      ** auth, but provided invalid credentials. Inform them of







>
>
>
>
>
>
>
>



|
|








|



|



|





|

|
|
>
>
>
>







 







|







 







|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
}

/*
** Searches for the user ID matching the given name and password.
** On success it returns a positive value. On error it returns 0.
** On serious (DB-level) error it will probably exit.
**
** zUsername uses double indirection because we may re-point *zUsername
** at a C string allocated with fossil_strdup() if you pass an email
** address instead and we find that address in the user table's info
** field, which is expected to contain a string of the form "Human Name
** <human@example.com>".  In that case, *zUsername will point to that
** user's actual login name on return, causing a leak unless the caller
** is diligent enough to check whether its pointer was re-pointed.
**
** zPassword may be either the plain-text form or the encrypted
** form of the user's password.
*/
int login_search_uid(const char **zUsername, const char *zPasswd){
  char *zSha1Pw = sha1_shared_secret(zPasswd, *zUsername, 0);
  int 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 (length(pw)<>40 AND pw=%Q))"
    "   AND (info NOT LIKE '%%expires 20%%'"
    "      OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
    *zUsername, zSha1Pw, zPasswd
  );

  /* If we did not find a login on the first attempt, and the username
  ** looks like an email address, then perhaps the user entered their
  ** email address instead of their login.  Try again to match the user
  ** against email addresses contained in the "info" field.
  */
  if( uid==0 && strchr(*zUsername,'@')!=0 ){
    Stmt q;
    db_prepare(&q,
      "SELECT login FROM user"
      " WHERE find_emailaddr(info)=%Q"
      "   AND instr(login,'@')==0",
      *zUsername
    );
    while( db_step(&q)==SQLITE_ROW ){
      const char *zLogin = db_column_text(&q,0);
      if( (uid = login_search_uid(&zLogin, zPasswd) ) != 0 ){
        *zUsername = fossil_strdup(zLogin);
        break;
      }
    }
    db_finalize(&q);
  }    
  free(zSha1Pw);
  return uid;
}

................................................................................
    login_set_anon_cookie(zIpAddr, NULL);
    record_login_attempt("anonymous", zIpAddr, 1);
    redirect_to_g();
  }
  if( zUsername!=0 && zPasswd!=0 && zPasswd[0]!=0 ){
    /* Attempting to log in as a user other than anonymous.
    */
    uid = login_search_uid(&zUsername, zPasswd);
    if( uid<=0 ){
      sleep(1);
      zErrMsg =
         @ <p><span class="loginError">
         @ You entered an unknown user or an incorrect password.
         @ </span></p>
      ;
................................................................................
    zDecode[i] = 0;
    zUsername = zDecode;
    zPasswd = &zDecode[i+1];

    /* Attempting to log in as the user provided by HTTP
    ** basic auth
    */
    uid = login_search_uid(&zUsername, zPasswd);
    if( uid>0 ){
      record_login_attempt(zUsername, zIpAddr, 1);
    }else{
      record_login_attempt(zUsername, zIpAddr, 0);

      /* The user attempted to login specifically with HTTP basic
      ** auth, but provided invalid credentials. Inform them of

Changes to src/smtp.c.

1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
  fflush(stdout);
  if( pLog ) fprintf(pLog, "S: %s\n", zLine);
}

/*
** Try to log in for zUser and zPass.
**
** If zUser/zPass does not work as written, then modify zUser by
** omitting everything after the "@" (if there is one) and trying
** again.
*/
static int pop3_login(char *zUser, char *zPass){
  int uid;
  int i;
  uid = login_search_uid(zUser, zPass);
  if( uid ) return 1;
  for(i=0; zUser[i] && zUser[i]!='@'; i++){}
  if( zUser[i]=='@' ){
    zUser[i] = 0;
    uid = login_search_uid(zUser, zPass);
    if( uid ) return 1;
    zUser[i] = '@';
  }
  return 0; 
}

/*
** COMMAND: pop3d
**
** Usage: %fossil pop3d [OPTIONS] REPOSITORY
**







|
|
<

|
<
<
|
<
<
<
<
<
<
<
<
<







1351
1352
1353
1354
1355
1356
1357
1358
1359

1360
1361


1362









1363
1364
1365
1366
1367
1368
1369
  fflush(stdout);
  if( pLog ) fprintf(pLog, "S: %s\n", zLine);
}

/*
** Try to log in for zUser and zPass.
**
** zUser can either point to a Fossil user name or to an email address
** found in the user table's info field, in angle brackets.

*/
static int pop3_login(const char *zUser, char *zPass){


  return login_search_uid(&zUser, zPass) != 0;









}

/*
** COMMAND: pop3d
**
** Usage: %fossil pop3d [OPTIONS] REPOSITORY
**