Fossil SCM
Relax constraints on PATHINFO names such that the "fossil ui /" command can be used if some repositories have non-ASCII filenames. Response to [forum:/forumpost/ec3ab5b1f5|forum post ec3ab5b1f5].
Commit
362a7b7c9de817d1f8079b1bfccac55f336f30a54a57c4d34b26962f31a0c7bc
Parent
df86fa33571d6c4…
1 file changed
+29
-10
+29
-10
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1702,10 +1702,17 @@ | ||
| 1702 | 1702 | |
| 1703 | 1703 | g.zPhase = "process_one_web_page"; |
| 1704 | 1704 | #if !defined(_WIN32) |
| 1705 | 1705 | signal(SIGSEGV, sigsegv_handler); |
| 1706 | 1706 | #endif |
| 1707 | + | |
| 1708 | + /* Decode %HH escapes in PATHINFO */ | |
| 1709 | + if( strchr(zPathInfo,'%') ){ | |
| 1710 | + char *z = fossil_strdup(zPathInfo); | |
| 1711 | + dehttpize(z); | |
| 1712 | + zPathInfo = z; | |
| 1713 | + } | |
| 1707 | 1714 | |
| 1708 | 1715 | /* Handle universal query parameters */ |
| 1709 | 1716 | if( PB("utc") ){ |
| 1710 | 1717 | g.fTimeFormat = 1; |
| 1711 | 1718 | }else if( PB("localtime") ){ |
| @@ -1757,32 +1764,44 @@ | ||
| 1757 | 1764 | @ <!-- Looking for repository named "%h(zRepo)" --> |
| 1758 | 1765 | fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo); |
| 1759 | 1766 | } |
| 1760 | 1767 | |
| 1761 | 1768 | |
| 1762 | - /* For safety -- to prevent an attacker from accessing arbitrary disk | |
| 1763 | - ** files by sending a maliciously crafted request URI to a public | |
| 1764 | - ** server -- make sure the repository basename contains no | |
| 1765 | - ** characters other than alphanumerics, "/", "_", "-", and ".", and | |
| 1766 | - ** that "-" never occurs immediately after a "/" and that "." is always | |
| 1767 | - ** surrounded by two alphanumerics. Any character that does not | |
| 1768 | - ** satisfy these constraints is converted into "_". | |
| 1769 | - */ | |
| 1769 | + /* Restrictions on the URI for security: | |
| 1770 | + ** | |
| 1771 | + ** 1. Reject characters that are not ASCII alphanumerics, | |
| 1772 | + ** "-", "_", ".", "/", or unicode (above ASCII). | |
| 1773 | + ** In other words: No ASCII punctuation or control characters | |
| 1774 | + ** other than "-", "_", "." and "/". | |
| 1775 | + ** 2. Exception to rule 1: Allow /X:/ where X is any ASCII | |
| 1776 | + ** alphabetic character at the beginning of the name on windows. | |
| 1777 | + ** 3. "-" may not occur immediately after "/" | |
| 1778 | + ** 4. "." may not be adjacent to another "." or to "/" | |
| 1779 | + ** | |
| 1780 | + ** Any character does not satisfy these constraints a Not Found | |
| 1781 | + ** error is returned. | |
| 1782 | + */ | |
| 1770 | 1783 | szFile = 0; |
| 1771 | 1784 | for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){ |
| 1772 | 1785 | char c = zRepo[j]; |
| 1773 | - if( fossil_isalnum(c) ) continue; | |
| 1786 | + if( c>='a' && c<='z' ) continue; | |
| 1787 | + if( c>='A' && c<='Z' ) continue; | |
| 1788 | + if( c>='0' && c<='9' ) continue; | |
| 1789 | + if( (c&0x80)==0x80 ) continue; | |
| 1774 | 1790 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 1775 | 1791 | /* Allow names to begin with "/X:/" on windows */ |
| 1776 | 1792 | if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){ |
| 1777 | 1793 | continue; |
| 1778 | 1794 | } |
| 1779 | 1795 | #endif |
| 1780 | 1796 | if( c=='/' ) continue; |
| 1781 | 1797 | if( c=='_' ) continue; |
| 1782 | 1798 | if( c=='-' && zRepo[j-1]!='/' ) continue; |
| 1783 | - if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){ | |
| 1799 | + if( c=='.' | |
| 1800 | + && zRepo[j-1]!='.' && zRepo[j-1]!='/' | |
| 1801 | + && zRepo[j+1]!='.' && zRepo[j+1]!='/' | |
| 1802 | + ){ | |
| 1784 | 1803 | continue; |
| 1785 | 1804 | } |
| 1786 | 1805 | if( c=='.' && g.fAllowACME && j==(int)nBase+1 |
| 1787 | 1806 | && strncmp(&zRepo[j-1],"/.well-known/",12)==0 |
| 1788 | 1807 | ){ |
| 1789 | 1808 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1702,10 +1702,17 @@ | |
| 1702 | |
| 1703 | g.zPhase = "process_one_web_page"; |
| 1704 | #if !defined(_WIN32) |
| 1705 | signal(SIGSEGV, sigsegv_handler); |
| 1706 | #endif |
| 1707 | |
| 1708 | /* Handle universal query parameters */ |
| 1709 | if( PB("utc") ){ |
| 1710 | g.fTimeFormat = 1; |
| 1711 | }else if( PB("localtime") ){ |
| @@ -1757,32 +1764,44 @@ | |
| 1757 | @ <!-- Looking for repository named "%h(zRepo)" --> |
| 1758 | fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo); |
| 1759 | } |
| 1760 | |
| 1761 | |
| 1762 | /* For safety -- to prevent an attacker from accessing arbitrary disk |
| 1763 | ** files by sending a maliciously crafted request URI to a public |
| 1764 | ** server -- make sure the repository basename contains no |
| 1765 | ** characters other than alphanumerics, "/", "_", "-", and ".", and |
| 1766 | ** that "-" never occurs immediately after a "/" and that "." is always |
| 1767 | ** surrounded by two alphanumerics. Any character that does not |
| 1768 | ** satisfy these constraints is converted into "_". |
| 1769 | */ |
| 1770 | szFile = 0; |
| 1771 | for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){ |
| 1772 | char c = zRepo[j]; |
| 1773 | if( fossil_isalnum(c) ) continue; |
| 1774 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 1775 | /* Allow names to begin with "/X:/" on windows */ |
| 1776 | if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){ |
| 1777 | continue; |
| 1778 | } |
| 1779 | #endif |
| 1780 | if( c=='/' ) continue; |
| 1781 | if( c=='_' ) continue; |
| 1782 | if( c=='-' && zRepo[j-1]!='/' ) continue; |
| 1783 | if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){ |
| 1784 | continue; |
| 1785 | } |
| 1786 | if( c=='.' && g.fAllowACME && j==(int)nBase+1 |
| 1787 | && strncmp(&zRepo[j-1],"/.well-known/",12)==0 |
| 1788 | ){ |
| 1789 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1702,10 +1702,17 @@ | |
| 1702 | |
| 1703 | g.zPhase = "process_one_web_page"; |
| 1704 | #if !defined(_WIN32) |
| 1705 | signal(SIGSEGV, sigsegv_handler); |
| 1706 | #endif |
| 1707 | |
| 1708 | /* Decode %HH escapes in PATHINFO */ |
| 1709 | if( strchr(zPathInfo,'%') ){ |
| 1710 | char *z = fossil_strdup(zPathInfo); |
| 1711 | dehttpize(z); |
| 1712 | zPathInfo = z; |
| 1713 | } |
| 1714 | |
| 1715 | /* Handle universal query parameters */ |
| 1716 | if( PB("utc") ){ |
| 1717 | g.fTimeFormat = 1; |
| 1718 | }else if( PB("localtime") ){ |
| @@ -1757,32 +1764,44 @@ | |
| 1764 | @ <!-- Looking for repository named "%h(zRepo)" --> |
| 1765 | fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo); |
| 1766 | } |
| 1767 | |
| 1768 | |
| 1769 | /* Restrictions on the URI for security: |
| 1770 | ** |
| 1771 | ** 1. Reject characters that are not ASCII alphanumerics, |
| 1772 | ** "-", "_", ".", "/", or unicode (above ASCII). |
| 1773 | ** In other words: No ASCII punctuation or control characters |
| 1774 | ** other than "-", "_", "." and "/". |
| 1775 | ** 2. Exception to rule 1: Allow /X:/ where X is any ASCII |
| 1776 | ** alphabetic character at the beginning of the name on windows. |
| 1777 | ** 3. "-" may not occur immediately after "/" |
| 1778 | ** 4. "." may not be adjacent to another "." or to "/" |
| 1779 | ** |
| 1780 | ** Any character does not satisfy these constraints a Not Found |
| 1781 | ** error is returned. |
| 1782 | */ |
| 1783 | szFile = 0; |
| 1784 | for(j=nBase+1, k=0; zRepo[j] && k<i-1; j++, k++){ |
| 1785 | char c = zRepo[j]; |
| 1786 | if( c>='a' && c<='z' ) continue; |
| 1787 | if( c>='A' && c<='Z' ) continue; |
| 1788 | if( c>='0' && c<='9' ) continue; |
| 1789 | if( (c&0x80)==0x80 ) continue; |
| 1790 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 1791 | /* Allow names to begin with "/X:/" on windows */ |
| 1792 | if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){ |
| 1793 | continue; |
| 1794 | } |
| 1795 | #endif |
| 1796 | if( c=='/' ) continue; |
| 1797 | if( c=='_' ) continue; |
| 1798 | if( c=='-' && zRepo[j-1]!='/' ) continue; |
| 1799 | if( c=='.' |
| 1800 | && zRepo[j-1]!='.' && zRepo[j-1]!='/' |
| 1801 | && zRepo[j+1]!='.' && zRepo[j+1]!='/' |
| 1802 | ){ |
| 1803 | continue; |
| 1804 | } |
| 1805 | if( c=='.' && g.fAllowACME && j==(int)nBase+1 |
| 1806 | && strncmp(&zRepo[j-1],"/.well-known/",12)==0 |
| 1807 | ){ |
| 1808 |