Fossil

Check-in [9b4e157b]
Login

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

Overview
Comment:Merge the fix to the login-by-email-address patch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 9b4e157b1e1e51247b285e6773fe510de12f71b3e58d26491262a557ce5a9299
User & Date: drh 2018-08-12 10:42:50
Context
2018-08-12
21:35
Add /forum link to sitemap if user has RdForum capability check-in: 5ad7222f user: wyoung tags: trunk
10:42
Merge the fix to the login-by-email-address patch. check-in: 9b4e157b user: drh tags: trunk
06:11
URL fix in forum.wiki check-in: 542c5576 user: wyoung tags: trunk
2018-08-11
23:51
Coding style tweak. Closed-Leaf check-in: 52b9caa5 user: mistachkin tags: login-with-email
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/json_login.c.

   122    122       }
   123    123     }
   124    124   
   125    125   #if 0
   126    126     {
   127    127       /* only for debugging the PD()-incorrect-result problem */
   128    128       cson_object * o = NULL;
   129         -    uid = login_search_uid( name, pw );
          129  +    uid = login_search_uid( &name, pw );
   130    130       payload = cson_value_new_object();
   131    131       o = cson_value_get_object(payload);
   132    132       cson_object_set( o, "n", cson_value_new_string(name,strlen(name)));
   133    133       cson_object_set( o, "p", cson_value_new_string(pw,strlen(pw)));
   134    134       return payload;
   135    135     }
   136    136   #endif
   137    137     uid = anonSeed
   138    138       ? login_is_valid_anonymous(name, pw, anonSeed)
   139         -    : login_search_uid(name, pw)
          139  +    : login_search_uid(&name, pw)
   140    140       ;
   141    141     if( !uid ){
   142    142       g.json.resultCode = preciseErrors
   143    143         ? FSL_JSON_E_LOGIN_FAILED_NOTFOUND
   144    144         : FSL_JSON_E_LOGIN_FAILED;
   145    145       return NULL;
   146    146     }else{

Changes to src/login.c.

   204    204   }
   205    205   
   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  +** <human@example.com>".  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;
   247    259   }
   248    260   
................................................................................
   648    660       login_set_anon_cookie(zIpAddr, NULL);
   649    661       record_login_attempt("anonymous", zIpAddr, 1);
   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.
   661    673            @ </span></p>
   662    674         ;
................................................................................
   949    961       zDecode[i] = 0;
   950    962       zUsername = zDecode;
   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         /* The user attempted to login specifically with HTTP basic
   963    975         ** auth, but provided invalid credentials. Inform them of

Changes to src/smtp.c.

  1351   1351     fflush(stdout);
  1352   1352     if( pLog ) fprintf(pLog, "S: %s\n", zLine);
  1353   1353   }
  1354   1354   
  1355   1355   /*
  1356   1356   ** Try to log in for zUser and zPass.
  1357   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.
         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.
  1361   1360   */
  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;
  1375   1363   }
  1376   1364   
  1377   1365   /*
  1378   1366   ** COMMAND: pop3d
  1379   1367   **
  1380   1368   ** Usage: %fossil pop3d [OPTIONS] REPOSITORY
  1381   1369   **