comparison src/http/ngx_http_parse.c @ 122:d25a1d6034f1 NGINX_0_3_8

nginx 0.3.8 *) Security: nginx now checks URI got from a backend in "X-Accel-Redirect" header line or in SSI file for the "/../" paths and zeroes. *) Change: nginx now does not treat the empty user name in the "Authorization" header line as valid one. *) Feature: the "ssl_session_timeout" directives of the ngx_http_ssl_module and ngx_imap_ssl_module. *) Feature: the "auth_http_header" directive of the ngx_imap_auth_http_module. *) Feature: the "add_header" directive. *) Feature: the ngx_http_realip_module. *) Feature: the new variables to use in the "log_format" directive: $bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri, $request_time, $request_length, $upstream_status, $upstream_response_time, $gzip_ratio, $uid_got, $uid_set, $connection, $pipe, and $msec. The parameters in the "%name" form will be canceled soon. *) Change: now the false variable values in the "if" directive are the empty string "" and string starting with "0". *) Bugfix: while using proxied or FastCGI-server nginx may leave connections and temporary files with client requests in open state. *) Bugfix: the worker processes did not flush the buffered logs on graceful exit. *) Bugfix: if the request URI was changes by the "rewrite" directive and the request was proxied in location given by regular expression, then the incorrect request was transferred to backend; bug appeared in 0.2.6. *) Bugfix: the "expires" directive did not remove the previous "Expires" header. *) Bugfix: nginx may stop to accept requests if the "rtsig" method and several worker processes were used. *) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in SSI commands. *) Bugfix: if the response was ended just after the SSI command and gzipping was used, then the response did not transferred complete or did not transferred at all.
author Igor Sysoev <http://sysoev.ru>
date Wed, 09 Nov 2005 00:00:00 +0300
parents 8ad297c88dcb
children 12acc273e340
comparison
equal deleted inserted replaced
121:737953b238a4 122:d25a1d6034f1
761 761
762 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 762 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
763 "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u); 763 "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u);
764 764
765 switch (state) { 765 switch (state) {
766
766 case sw_usual: 767 case sw_usual:
767 switch(ch) { 768 switch(ch) {
768 #if (NGX_WIN32) 769 #if (NGX_WIN32)
769 case '\\': 770 case '\\':
770 r->uri_ext = NULL; 771 r->uri_ext = NULL;
808 809
809 case sw_slash: 810 case sw_slash:
810 switch(ch) { 811 switch(ch) {
811 #if (NGX_WIN32) 812 #if (NGX_WIN32)
812 case '\\': 813 case '\\':
813 break;
814 #endif 814 #endif
815 case '/': 815 case '/':
816 break; 816 break;
817 case '.': 817 case '.':
818 state = sw_dot; 818 state = sw_dot;
835 835
836 case sw_dot: 836 case sw_dot:
837 switch(ch) { 837 switch(ch) {
838 #if (NGX_WIN32) 838 #if (NGX_WIN32)
839 case '\\': 839 case '\\':
840 /* fall through */
841 #endif 840 #endif
842 case '/': 841 case '/':
843 state = sw_slash; 842 state = sw_slash;
844 u--; 843 u--;
845 break; 844 break;
864 863
865 case sw_dot_dot: 864 case sw_dot_dot:
866 switch(ch) { 865 switch(ch) {
867 #if (NGX_WIN32) 866 #if (NGX_WIN32)
868 case '\\': 867 case '\\':
869 /* fall through */
870 #endif 868 #endif
871 case '/': 869 case '/':
872 state = sw_slash; 870 state = sw_slash;
873 u -= 4; 871 u -= 4;
874 if (u < r->uri.data) { 872 if (u < r->uri.data) {
921 break; 919 break;
922 case '%': 920 case '%':
923 quoted_state = state; 921 quoted_state = state;
924 state = sw_quoted; 922 state = sw_quoted;
925 break; 923 break;
924 case '?':
925 r->args_start = p;
926 goto done;
926 default: 927 default:
927 state = sw_usual; 928 state = sw_usual;
928 *u++ = ch; 929 *u++ = ch;
929 break; 930 break;
930 } 931 }
997 } 998 }
998 999
999 r->uri_ext = NULL; 1000 r->uri_ext = NULL;
1000 1001
1001 return NGX_OK; 1002 return NGX_OK;
1003 }
1004
1005
1006 ngx_int_t
1007 ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
1008 ngx_str_t *args, ngx_uint_t *flags)
1009 {
1010 u_char ch, *p;
1011 size_t len;
1012
1013 len = uri->len;
1014 p = uri->data;
1015
1016 if (len == 0 || p[0] == '?') {
1017 goto unsafe;
1018 }
1019
1020 if (p[0] == '.' && len == 3 && p[1] == '.' && (p[2] == '/'
1021 #if (NGX_WIN32)
1022 || p[2] == '\\'
1023 #endif
1024 ))
1025 {
1026 goto unsafe;
1027 }
1028
1029 for ( /* void */ ; len; len--) {
1030
1031 ch = *p++;
1032
1033 if (ch == '?') {
1034 args->len = len - 1;
1035 args->data = p;
1036 uri->len -= len;
1037
1038 return NGX_OK;
1039 }
1040
1041 if (ch == '\0') {
1042 *flags |= NGX_HTTP_ZERO_IN_URI;
1043 continue;
1044 }
1045
1046 if (ch != '/'
1047 #if (NGX_WIN32)
1048 && ch != '\\'
1049 #endif
1050 )
1051 {
1052 continue;
1053 }
1054
1055 if (len > 2) {
1056
1057 /* detect "/../" */
1058
1059 if (p[2] == '/') {
1060 goto unsafe;
1061 }
1062
1063 #if (NGX_WIN32)
1064
1065 if (p[2] == '\\') {
1066 goto unsafe;
1067 }
1068
1069 if (len > 3) {
1070
1071 /* detect "/.../" */
1072
1073 if (p[3] == '/' || p[3] == '\\') {
1074 goto unsafe;
1075 }
1076 }
1077 #endif
1078 }
1079 }
1080
1081 return NGX_OK;
1082
1083 unsafe:
1084
1085 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1086 "unsafe URI \"%V\" was detected", uri);
1087
1088 return NGX_ERROR;
1002 } 1089 }
1003 1090
1004 1091
1005 ngx_int_t 1092 ngx_int_t
1006 ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name, 1093 ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
1057 value->data = start; 1144 value->data = start;
1058 1145
1059 return i; 1146 return i;
1060 1147
1061 skip: 1148 skip:
1149
1062 while (start < end) { 1150 while (start < end) {
1063 ch = *start++; 1151 ch = *start++;
1064 if (ch == ';' || ch == ',') { 1152 if (ch == ';' || ch == ',') {
1065 break; 1153 break;
1066 } 1154 }