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)