Mercurial > hg > nginx
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; |