Fossil

Check-in [60212796]
Login

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

Overview
Comment:Make sure that "nobody" and "anonymous" privileges by users who attempt to sync with higher privileges.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 60212796377638c9444935d8e80a9cdac819a0ed
User & Date: drh 2009-09-11 23:04:50
Context
2009-09-12
03:45
fixed documentation for the 'fossil branch list' command check-in: da436330 user: rwilson tags: trunk
2009-09-11
23:04
Make sure that "nobody" and "anonymous" privileges by users who attempt to sync with higher privileges. check-in: 60212796 user: drh tags: trunk
21:05
Fix the "ui"/"server" command for win32 so that it works even if run from cygwin in a directory that contains a space in its name. check-in: 73431266 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/login.c.

294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
...
360
361
362
363
364
365
366

367
368
369

370
371
372
373
374





375
376
377
378
379
380
381
382
383
384
385
386
387
388




389
390
391
392












393

394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
**
*/
void login_check_credentials(void){
  int uid = 0;                  /* User id */
  const char *zCookie;          /* Text of the login cookie */
  const char *zRemoteAddr;      /* IP address of the requestor */
  const char *zCap = 0;         /* Capability string */
  const char *zNcap;            /* Capabilities of user "nobody" */
  const char *zAcap;            /* Capabllities of user "anonymous" */

  /* Only run this check once.  */
  if( g.userUid!=0 ) return;


  /* 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, 
................................................................................
          rTime, &zCookie[i], blob_buffer(&b)
      );
      blob_reset(&b);
    }
    sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie);
  }


  if( uid==0 ){
    uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
    if( uid==0 ){

      uid = -1;
      zCap = "";
    }
    strcpy(g.zCsrfToken, "none");
  }





  if( zCap==0 ){
    if( uid ){
      Stmt s;
      db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid);
      if( db_step(&s)==SQLITE_ROW ){
        g.zLogin = db_column_malloc(&s, 0);
        zCap = db_column_malloc(&s, 1);
      }
      db_finalize(&s);
    }
    if( zCap==0 ){
      zCap = "";
    }
  }




  g.userUid = uid;
  if( g.zLogin && strcmp(g.zLogin,"nobody")==0 ){
    g.zLogin = 0;
  }












  if( uid && g.zLogin ){

    /* All logged-in users inherit privileges from "nobody" */
    zNcap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
    login_set_capabilities(zNcap);
    if( strcmp(g.zLogin, "anonymous")!=0 ){
      /* All logged-in users inherit privileges from "anonymous" */
      zAcap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
      login_set_capabilities(zAcap);
    }

  }
  login_set_capabilities(zCap);
}

/*
** Set the global capability flags based on a capability string.
*/
void login_set_capabilities(const char *zCap){
  static char *zDev = 0;







<
<







 







>



>





>
>
>
>
>

<
|
|
|
|
|
|
|
<




>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
|
>

|
|


|
|

>

<







294
295
296
297
298
299
300


301
302
303
304
305
306
307
...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
**
*/
void login_check_credentials(void){
  int uid = 0;                  /* User id */
  const char *zCookie;          /* Text of the login cookie */
  const char *zRemoteAddr;      /* IP address of the requestor */
  const char *zCap = 0;         /* Capability string */



  /* Only run this check once.  */
  if( g.userUid!=0 ) return;


  /* 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, 
................................................................................
          rTime, &zCookie[i], blob_buffer(&b)
      );
      blob_reset(&b);
    }
    sqlite3_snprintf(sizeof(g.zCsrfToken), g.zCsrfToken, "%.10s", zCookie);
  }

  /* If no user found yet, try to log in as "nobody" */
  if( uid==0 ){
    uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
    if( uid==0 ){
      /* If there is no user "nobody", then make one up - with no privileges */
      uid = -1;
      zCap = "";
    }
    strcpy(g.zCsrfToken, "none");
  }

  /* At this point, we know that uid!=0.  Find the privileges associated
  ** with user uid.
  */
  assert( uid!=0 );
  if( zCap==0 ){

    Stmt s;
    db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid);
    if( db_step(&s)==SQLITE_ROW ){
      g.zLogin = db_column_malloc(&s, 0);
      zCap = db_column_malloc(&s, 1);
    }
    db_finalize(&s);

    if( zCap==0 ){
      zCap = "";
    }
  }

  /* Set the global variables recording the userid and login.  The
  ** "nobody" user is a special case in that g.zLogin==0.
  */
  g.userUid = uid;
  if( g.zLogin && strcmp(g.zLogin,"nobody")==0 ){
    g.zLogin = 0;
  }

  /* Set the capabilities */
  login_set_capabilities(zCap);
  login_set_anon_nobody_capabilities();
}

/*
** Add the default privileges of users "nobody" and "anonymous" as appropriate
** for the user g.zLogin.
*/
void login_set_anon_nobody_capabilities(void){
  static int once = 1;
  if( g.zLogin && once ){
    const char *zCap;
    /* All logged-in users inherit privileges from "nobody" */
    zCap = db_text("", "SELECT cap FROM user WHERE login = 'nobody'");
    login_set_capabilities(zCap);
    if( strcmp(g.zLogin, "anonymous")!=0 ){
      /* All logged-in users inherit privileges from "anonymous" */
      zCap = db_text("", "SELECT cap FROM user WHERE login = 'anonymous'");
      login_set_capabilities(zCap);
    }
    once = 0;
  }

}

/*
** Set the global capability flags based on a capability string.
*/
void login_set_capabilities(const char *zCap){
  static char *zDev = 0;

Changes to src/xfer.c.

380
381
382
383
384
385
386
387
388

389




390
391
392
393
394
395
396
...
405
406
407
408
409
410
411





412
413
414
415
416
417
418
** If anything fails to check out, no changes are made to privileges.
**
** Signature generation on the client side is handled by the 
** http_exchange() routine.
*/
void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
  Stmt q;
  int rc;


  db_prepare(&q, "SELECT pw, cap, uid FROM user WHERE login=%B", pLogin);




  if( db_step(&q)==SQLITE_ROW ){
    Blob pw, combined, hash;
    blob_zero(&pw);
    db_ephemeral_blob(&q, 0, &pw);
    blob_zero(&combined);
    blob_copy(&combined, pNonce);
    blob_append(&combined, blob_buffer(&pw), blob_size(&pw));
................................................................................
      login_set_capabilities(zCap);
      g.userUid = db_column_int(&q, 2);
      g.zLogin = mprintf("%b", pLogin);
      g.zNonce = mprintf("%b", pNonce);
    }
  }
  db_finalize(&q);





}

/*
** Send the content of all files in the unsent table.
**
** This is really just an optimization.  If you clear the
** unsent table, all the right files will still get transferred.







|

>
|
>
>
>
>







 







>
>
>
>
>







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
** If anything fails to check out, no changes are made to privileges.
**
** Signature generation on the client side is handled by the 
** http_exchange() routine.
*/
void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
  Stmt q;
  int rc = -1;

  db_prepare(&q,
     "SELECT pw, cap, uid FROM user"
     " WHERE login=%B"
     "   AND length(pw)>0",
     pLogin
  );
  if( db_step(&q)==SQLITE_ROW ){
    Blob pw, combined, hash;
    blob_zero(&pw);
    db_ephemeral_blob(&q, 0, &pw);
    blob_zero(&combined);
    blob_copy(&combined, pNonce);
    blob_append(&combined, blob_buffer(&pw), blob_size(&pw));
................................................................................
      login_set_capabilities(zCap);
      g.userUid = db_column_int(&q, 2);
      g.zLogin = mprintf("%b", pLogin);
      g.zNonce = mprintf("%b", pNonce);
    }
  }
  db_finalize(&q);

  if( rc==0 ){
    /* If the login was successful. */
    login_set_anon_nobody_capabilities();
  }
}

/*
** Send the content of all files in the unsent table.
**
** This is really just an optimization.  If you clear the
** unsent table, all the right files will still get transferred.