1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
|
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
|
+
-
+
+
+
+
+
|
if( fossil_strcmp(g.zRepositoryName, "/")==0 ){
zBase++;
#if defined(_WIN32) || defined(__CYGWIN__)
if( sqlite3_strglob("/[a-zA-Z]:/*", zPathInfo)==0 ) i = 4;
#endif
}
while( 1 ){
size_t nBase = strlen(zBase);
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
zRepo = zToFree = mprintf("%s%.*s.fossil",zBase,i,zPathInfo);
if( g.fHttpTrace ){
@ <!-- Looking for repository named "%h(zRepo)" -->
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
}
/* For safety -- to prevent an attacker from accessing arbitrary disk
** files by sending a maliciously crafted request URI to a public
** server -- make sure the repository basename contains no
** characters other than alphanumerics, "/", "_", "-", and ".", and
** that "-" never occurs immediately after a "/" and that "." is always
** surrounded by two alphanumerics. Any character that does not
** satisfy these constraints is converted into "_".
*/
szFile = 0;
for(j=strlen(zBase)+1, k=0; zRepo[j] && k<i-1; j++, k++){
for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){
char c = zRepo[j];
if( fossil_isalnum(c) ) continue;
#if defined(_WIN32) || defined(__CYGWIN__)
/* Allow names to begin with "/X:/" on windows */
if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
continue;
}
#endif
if( c=='/' ) continue;
if( c=='_' ) continue;
if( c=='-' && zRepo[j-1]!='/' ) continue;
if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
continue;
}
if( c=='.' && strncmp(&zRepo[j-1],"/.well-known/",12)==0 && j==nBase+1){
/* We allow .well-known as the top-level directory for ACME */
continue;
}
/* If we reach this point, it means that the request URI contains
** an illegal character or character combination. Provoke a
** "Not Found" error. */
szFile = 1;
if( g.fHttpTrace ){
@ <!-- Unsafe pathname rejected: "%h(zRepo)" -->
|
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
|
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
|
-
+
|
** being delivered accidently. This is not intended to be a
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo, ExtFILE)
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo))
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo+nBase))
&& sqlite3_strglob("*.fossil*",zRepo)!=0
&& (zMimetype = mimetype_from_name(zRepo))!=0
&& strcmp(zMimetype, "application/x-fossil-artifact")!=0
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo), ExtFILE);
cgi_set_content_type(zMimetype);
|