Fossil

Check-in [e8b15ad642]
Login

Check-in [e8b15ad642]

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

Overview
Comment:A new approach to sub-repos in which a specific user for the subrepo is specified in the CONFIG table entry.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | sub-repos
Files: files | file ages | folders
SHA1: e8b15ad642a681c4681cfa0ff7bac07535dcd883
User & Date: drh 2011-03-28 22:29:30.302
Original Comment: A new approach to sub-repos in which a specific user for the subrepo is specified in the CONFIG table entry.
Context
2011-03-28
22:47
Merge the sub-repo capability into trunk. ... (check-in: ab4882588e user: drh tags: trunk)
22:29
A new approach to sub-repos in which a specific user for the subrepo is specified in the CONFIG table entry. ... (Closed-Leaf check-in: e8b15ad642 user: drh tags: sub-repos)
21:46
Fixes to the capability reduction on subrepositories. ... (check-in: 4b545a8a02 user: drh tags: sub-repos)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/login.c.
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
      default:   rc = 0;             break;
    }
  }
  return rc;
}

/*
** For every character in zCap between 'a' and 'z' set a byte in seen[].
*/
static void setCap(const char *zCap, char *seen){
  int c;
  if( zCap ){
    while( (c = *(zCap++))!=0 ){
      if( c>='a' && c<='z' ) seen[c-'a'] = 1;
    }
  }
}

/*
** Remove privileges such that previleges are restricted to the
** set given in the argument.
*/
void login_restrict_capabilities(const char *zAllowed){
  char zNew[30];
  char seen[26];
  int nNew = 0;
  int i;

  /* Compute the intersection of current settings with zAllowed[] and
  ** store the result in zNew[]
  */
  memset(seen, 0, sizeof(seen));
  setCap(zAllowed, seen);
  if( seen['v'-'a'] ){
    char *z = db_text(0, "SELECT cap FROM user WHERE login='developer'");
    setCap(z, seen);
    fossil_free(z);
  }
  if( seen['u'-'a'] ){
    char *z = db_text(0, "SELECT cap FROM user WHERE login='reader'");
    setCap(z, seen);
    fossil_free(z);
  }
  seen['u'-'a'] = 0;
  seen['v'-'a'] = 0;
  for(i=0; i<sizeof(seen); i++){
    char c = i+'a';
    if( seen[i] && login_has_capability(&c,1) ) zNew[nNew++] = i+'a';
  }
  zNew[nNew] = 0;

  /* Turn off all capabilities */
  g.okSetup = 0;
  g.okAdmin = 0;
  g.okDelete = 0;
  g.okPassword = 0;
  g.okQuery = 0;
  g.okWrite = 0;
  g.okRead = 0;







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

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







629
630
631
632
633
634
635










636



637
638




639









640













641
642
643
644
645
646
647
648
      default:   rc = 0;             break;
    }
  }
  return rc;
}

/*










** Change the login to zUser.



*/
void login_as_user(const char *zUser){




  char *zCap = "";   /* New capabilities */























  /* Turn off all capabilities from prior logins */
  g.okSetup = 0;
  g.okAdmin = 0;
  g.okDelete = 0;
  g.okPassword = 0;
  g.okQuery = 0;
  g.okWrite = 0;
  g.okRead = 0;
697
698
699
700
701
702
703














704
705
706
707
708
709
710
711
712
  g.okWrTkt = 0;
  g.okAttach = 0;
  g.okTktFmt = 0;
  g.okRdAddr = 0;
  g.okZip = 0;
  g.okPrivate = 0;















  /* Set the reduced capabilities */
  login_set_capabilities(zNew);
  login_anon_once = 1;
  login_set_anon_nobody_capabilities();
}

/*
** Call this routine when the credential check fails.  It causes
** a redirect to the "login" page.







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







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  g.okWrTkt = 0;
  g.okAttach = 0;
  g.okTktFmt = 0;
  g.okRdAddr = 0;
  g.okZip = 0;
  g.okPrivate = 0;

  /* Set the global variables recording the userid and login.  The
  ** "nobody" user is a special case in that g.zLogin==0.
  */
  g.userUid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUser);
  if( g.userUid==0 ){
    zUser = 0;
    g.userUid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
  }
  if( g.userUid ){
    zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", g.userUid);
  }
  if( fossil_strcmp(zUser,"nobody")==0 ) zUser = 0;
  g.zLogin = fossil_strdup(zUser);

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

/*
** Call this routine when the credential check fails.  It causes
** a redirect to the "login" page.
Changes to src/main.c.
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012

1013
1014
1015
1016
1017
1018
1019
      zPath[i] = 0;
      g.zExtra = &zPath[i+1];

      /* Look for sub-repositories.  A sub-repository is another repository
      ** that accepts the login credentials of the current repository.  A
      ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
      ** where NAME is the first component of the path.  The value of the
      ** the CONFIG entries is the string "CAP:FILENAME" where CAP is the
      ** maximum capability string and FILENAME is the new repository 
      ** filename. 
      */
      zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
                         g.zPath);
      if( zAltRepo ){
        int nHost;
        int jj;
        char *zInheritCap = zAltRepo;
        login_check_credentials();
        for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){}
        if( zAltRepo[jj]==':' ){
          zAltRepo[jj] = 0;
          zAltRepo += jj+1;
        }else{
          zInheritCap = "";
        }
        if( zAltRepo[0]!='/' ){
          zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
          file_simplify_name(zAltRepo, -1);
        }
        db_close(1);
        db_open_repository(zAltRepo);
        login_restrict_capabilities(zInheritCap);

        zPath += i;
        nHost = g.zTop - g.zBaseURL;
        g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
        g.zTop = g.zBaseURL + nHost;
        continue;
      }
    }else{







|
|
|






|






|







|
>







981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
      zPath[i] = 0;
      g.zExtra = &zPath[i+1];

      /* Look for sub-repositories.  A sub-repository is another repository
      ** that accepts the login credentials of the current repository.  A
      ** subrepository is identified by a CONFIG table entry "subrepo:NAME"
      ** where NAME is the first component of the path.  The value of the
      ** the CONFIG entries is the string "USER:FILENAME" where USER is the
      ** USER name to log in as in the subrepository and FILENAME is the
      ** repository filename. 
      */
      zAltRepo = db_text(0, "SELECT value FROM config WHERE name='subrepo:%q'",
                         g.zPath);
      if( zAltRepo ){
        int nHost;
        int jj;
        char *zUser = zAltRepo;
        login_check_credentials();
        for(jj=0; zAltRepo[jj] && zAltRepo[jj]!=':'; jj++){}
        if( zAltRepo[jj]==':' ){
          zAltRepo[jj] = 0;
          zAltRepo += jj+1;
        }else{
          zUser = "nobody";
        }
        if( zAltRepo[0]!='/' ){
          zAltRepo = mprintf("%s/../%s", g.zRepositoryName, zAltRepo);
          file_simplify_name(zAltRepo, -1);
        }
        db_close(1);
        db_open_repository(zAltRepo);
        login_as_user(zUser);
        g.okPassword = 0;
        zPath += i;
        nHost = g.zTop - g.zBaseURL;
        g.zBaseURL = mprintf("%z/%s", g.zBaseURL, g.zPath);
        g.zTop = g.zBaseURL + nHost;
        continue;
      }
    }else{