Mercurial > hg > nginx
comparison src/http/ngx_http_request.c @ 4313:e7db97bfac25
Added support for IP-literal in the Host header and request line (ticket #1).
Additional parsing logic added to correctly handle RFC 3986 compliant IPv6 and
IPvFuture characters enclosed in square brackets.
The host validation was completely rewritten. The behavior for non IP literals
was changed in a more proper and safer way:
- Host part is now delimited either by the first colon or by the end of string
if there's no colon. Previously the last colon was used as delimiter which
allowed substitution of a port number in the $host variable.
(e.g. Host: 127.0.0.1:9000:80)
- Fixed stripping of the ending dot in the Host header when the host was also
followed by a port number.
(e.g. Host: nginx.com.:80)
- Fixed upper case characters detection. Previously it was broken which led to
wasting memory and CPU.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Mon, 28 Nov 2011 09:15:33 +0000 |
parents | ed922fb9d6c1 |
children | d620f497c50f |
comparison
equal
deleted
inserted
replaced
4312:0a8e51a16484 | 4313:e7db97bfac25 |
---|---|
1672 | 1672 |
1673 static ssize_t | 1673 static ssize_t |
1674 ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, | 1674 ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len, |
1675 ngx_uint_t alloc) | 1675 ngx_uint_t alloc) |
1676 { | 1676 { |
1677 u_char *h, ch; | 1677 u_char *h, ch; |
1678 size_t i, last; | 1678 size_t i, dot_pos, host_len; |
1679 ngx_uint_t dot; | 1679 |
1680 | 1680 enum { |
1681 last = len; | 1681 sw_usual = 0, |
1682 sw_literal, | |
1683 sw_rest | |
1684 } state; | |
1685 | |
1686 dot_pos = len; | |
1687 host_len = len; | |
1688 | |
1682 h = *host; | 1689 h = *host; |
1683 dot = 0; | 1690 |
1691 state = sw_usual; | |
1684 | 1692 |
1685 for (i = 0; i < len; i++) { | 1693 for (i = 0; i < len; i++) { |
1686 ch = h[i]; | 1694 ch = h[i]; |
1687 | 1695 |
1688 if (ch == '.') { | 1696 switch (ch) { |
1689 if (dot) { | 1697 |
1698 case '.': | |
1699 if (dot_pos == i - 1) { | |
1690 return 0; | 1700 return 0; |
1691 } | 1701 } |
1692 | 1702 dot_pos = i; |
1693 dot = 1; | 1703 break; |
1694 continue; | 1704 |
1695 } | 1705 case ':': |
1696 | 1706 if (state == sw_usual) { |
1697 dot = 0; | 1707 host_len = i; |
1698 | 1708 state = sw_rest; |
1699 if (ch == ':') { | 1709 } |
1700 last = i; | 1710 break; |
1701 continue; | 1711 |
1702 } | 1712 case '[': |
1703 | 1713 if (i == 0) { |
1704 if (ngx_path_separator(ch) || ch == '\0') { | 1714 state = sw_literal; |
1715 } | |
1716 break; | |
1717 | |
1718 case ']': | |
1719 if (state == sw_literal) { | |
1720 host_len = i + 1; | |
1721 state = sw_rest; | |
1722 } | |
1723 break; | |
1724 | |
1725 case '\0': | |
1705 return 0; | 1726 return 0; |
1706 } | 1727 |
1707 | 1728 default: |
1708 if (ch >= 'A' || ch < 'Z') { | 1729 |
1709 alloc = 1; | 1730 if (ngx_path_separator(ch)) { |
1710 } | 1731 return 0; |
1711 } | 1732 } |
1712 | 1733 |
1713 if (dot) { | 1734 if (ch >= 'A' && ch <= 'Z') { |
1714 last--; | 1735 alloc = 1; |
1736 } | |
1737 | |
1738 break; | |
1739 } | |
1740 } | |
1741 | |
1742 if (dot_pos == host_len - 1) { | |
1743 host_len--; | |
1715 } | 1744 } |
1716 | 1745 |
1717 if (alloc) { | 1746 if (alloc) { |
1718 *host = ngx_pnalloc(r->pool, last) ; | 1747 *host = ngx_pnalloc(r->pool, host_len); |
1719 if (*host == NULL) { | 1748 if (*host == NULL) { |
1720 return -1; | 1749 return -1; |
1721 } | 1750 } |
1722 | 1751 |
1723 ngx_strlow(*host, h, last); | 1752 ngx_strlow(*host, h, host_len); |
1724 } | 1753 } |
1725 | 1754 |
1726 return last; | 1755 return host_len; |
1727 } | 1756 } |
1728 | 1757 |
1729 | 1758 |
1730 static ngx_int_t | 1759 static ngx_int_t |
1731 ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) | 1760 ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) |