comparison src/http/ngx_http_parse.c @ 5491:74bfa803a5aa

Teach ngx_http_parse_unsafe_uri() how to unescape URIs. This fixes handling of escaped URIs in X-Accel-Redirect (ticket #316), SSI (ticket #240), and DAV.
author Ruslan Ermilov <ru@nginx.com>
date Mon, 23 Dec 2013 18:12:00 +0400
parents b141a7627ac6
children bd91f286ee0a
comparison
equal deleted inserted replaced
5490:b141a7627ac6 5491:74bfa803a5aa
1778 1778
1779 ngx_int_t 1779 ngx_int_t
1780 ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, 1780 ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
1781 ngx_str_t *args, ngx_uint_t *flags) 1781 ngx_str_t *args, ngx_uint_t *flags)
1782 { 1782 {
1783 u_char ch, *p; 1783 u_char ch, *p, *src, *dst;
1784 size_t len; 1784 size_t len;
1785 ngx_uint_t quoted;
1785 1786
1786 len = uri->len; 1787 len = uri->len;
1787 p = uri->data; 1788 p = uri->data;
1789 quoted = 0;
1788 1790
1789 if (len == 0 || p[0] == '?') { 1791 if (len == 0 || p[0] == '?') {
1790 goto unsafe; 1792 goto unsafe;
1791 } 1793 }
1792 1794
1798 1800
1799 for ( /* void */ ; len; len--) { 1801 for ( /* void */ ; len; len--) {
1800 1802
1801 ch = *p++; 1803 ch = *p++;
1802 1804
1805 if (ch == '%') {
1806 quoted = 1;
1807 continue;
1808 }
1809
1803 if (usual[ch >> 5] & (1 << (ch & 0x1f))) { 1810 if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
1804 continue; 1811 continue;
1805 } 1812 }
1806 1813
1807 if (ch == '?') { 1814 if (ch == '?') {
1808 args->len = len - 1; 1815 args->len = len - 1;
1809 args->data = p; 1816 args->data = p;
1810 uri->len -= len; 1817 uri->len -= len;
1811 1818
1812 return NGX_OK; 1819 break;
1813 } 1820 }
1814 1821
1815 if (ch == '\0') { 1822 if (ch == '\0') {
1816 goto unsafe; 1823 goto unsafe;
1817 } 1824 }
1822 1829
1823 if (p[0] == '.' && p[1] == '.' 1830 if (p[0] == '.' && p[1] == '.'
1824 && (len == 3 || ngx_path_separator(p[2]))) 1831 && (len == 3 || ngx_path_separator(p[2])))
1825 { 1832 {
1826 goto unsafe; 1833 goto unsafe;
1834 }
1835 }
1836 }
1837
1838 if (quoted) {
1839 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1840 "escaped URI: \"%V\"", uri);
1841
1842 src = uri->data;
1843
1844 dst = ngx_pnalloc(r->pool, uri->len);
1845 if (dst == NULL) {
1846 return NGX_ERROR;
1847 }
1848
1849 uri->data = dst;
1850
1851 ngx_unescape_uri(&dst, &src, uri->len, 0);
1852
1853 uri->len = dst - uri->data;
1854
1855 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1856 "unescaped URI: \"%V\"", uri);
1857
1858 len = uri->len;
1859 p = uri->data;
1860
1861 if (p[0] == '.' && len > 1 && p[1] == '.'
1862 && (len == 2 || ngx_path_separator(p[2])))
1863 {
1864 goto unsafe;
1865 }
1866
1867 for ( /* void */ ; len; len--) {
1868
1869 ch = *p++;
1870
1871 if (ch == '\0') {
1872 goto unsafe;
1873 }
1874
1875 if (ngx_path_separator(ch) && len > 2) {
1876
1877 /* detect "/../" and "/.." */
1878
1879 if (p[0] == '.' && p[1] == '.'
1880 && (len == 3 || ngx_path_separator(p[2])))
1881 {
1882 goto unsafe;
1883 }
1827 } 1884 }
1828 } 1885 }
1829 } 1886 }
1830 1887
1831 return NGX_OK; 1888 return NGX_OK;