ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: implicit *LWS ?



On Wed, Oct 06, 2010 at 05:42:29PM +0400, Maxim Dounin wrote:
> > 
> > то есть nginx при проксировании обрезал весь контент поля начиная с CRLF.
> > 
> > То же самое происходит если пытаться передавать запрос на fastcgi backend,
> > в параметре HTTP_ACCEPT я вижу только text/plain, text/html, но не */*.
> > С другими хидерами происходит то же самое - как только встречается LWS - 
> > поле "обрезается", что для proxy_pass, что для fastcgi_pass. 
> > 
> > Вопрос: это бага или фича ? Если фича - обойти как-нибудь можно ? 
> 
> Это фича, LWS не поддерживаются, да и в HTTPbis они deprecated.

thanks. 
Хотя, jimho, не поддерживать deprecated и not recommended headers - это 
все-таки нарушение robustness principle (be liberal in what you accept). 

> Если очень нужно чтобы заработало вот прям здесь и сейчас - 
> где-то в районе nginx@ пробегал патч, но он ужасненький:

"Он хуже, он просто кю!". 

> http://nginx.org/pipermail/nginx/2010-September/022608.html

См. аттач. Это пока "концепт-кар", толком не оттестированный, но, jimho, 
более правильный. 
Куда пришлось залезть: 
а) изменить state-машину парсера заголовков для проверки LWS, 
с добавлением (новой) точки выхода - incomplete (в случаях когда
буфера не хватает для read-ahead)
б) изменить логику чтения запроса, разрешив чтение в случае когда
буферизовано менее двух байт. 

> А что за чудо генерит такие запросы?

Одно доморощенное чудо когда-то решило, что User-Agent стоит 
разбить на две строки, "ведь это ж rfc!!" :) А когда встал вопрос
о том, а можем ли мы делать content-switching по версии агента - 
эта грабель и вылезла.

-- 
In theory, there is no difference between theory and practice. 
But, in practice, there is. 

--- src/http/ngx_http_parse.c.orig      2010-10-06 21:37:13.000000000 +0400
+++ src/http/ngx_http_parse.c   2010-10-07 15:48:33.000000000 +0400
@@ -909,11 +909,38 @@
                 break;
             case CR:
                 r->header_end = p;
-                state = sw_almost_done;
+                if ( p + 2 >= b->last ) 
+                    goto incomplete;
+                if (p[1] == LF) { 
+                    if (p[2] == ' ' || p[2] == '\t') { 
+                        /* Linear whitespace, changing CRLF into SP SP */
+                        p[0] = p[1] = ' ';
+                        p+=2;
+                        state = sw_space_after_value; 
+                        continue;
+                    } else { 
+                        /* Normal single-line header */
+                        p++;
+                        goto done;
+                    }
+                } else { 
+                    return NGX_HTTP_PARSE_INVALID_HEADER;
+                };
                 break;
             case LF:
                 r->header_end = p;
-                goto done;
+                if ( p + 1 >= b->last ) 
+                    goto incomplete;
+                if ( p[1] == ' ' || p[1] == '\t' ) { 
+                    /* Linear whitespace, changing LF to SP */
+                    p[0] = ' ';
+                    state = sw_space_after_value; 
+                    p++;
+                    continue;
+                } else { 
+                    /* Normal, non-linear */
+                    goto done;
+                };
             }
             break;
 
@@ -923,9 +950,36 @@
             case ' ':
                 break;
             case CR:
-                state = sw_almost_done;
+                if (p + 2 >= b->last) 
+                    goto incomplete;
+
+                if (p[1] == LF) { 
+                    if (p[2] == ' ' || p[2] == '\t') { 
+                        /* Linear whitespace, changing CRLF into SP SP */
+                        p[0] = p[1] = ' ';
+                        p+=2;
+                        continue;
+                    } else { 
+                        /* Normal single-line header */
+                        p++;
+                        goto done;
+                    }
+                } else { 
+                    return NGX_HTTP_PARSE_INVALID_HEADER;
+                };
                 break;
             case LF:
+                if ( p + 1 >= b->last ) 
+                    goto incomplete;
+                if ( p[1] == ' ' || p[1] == '\t' ) { 
+                    /* Linear whitespace, changing LF to SP */
+                    p[0] = ' ';
+                    p++;
+                    continue;
+                } else { 
+                    /* Normal, non-linear */
+                    goto done;
+                };
                 goto done;
             default:
                 state = sw_value;
@@ -967,6 +1021,8 @@
         }
     }
 
+incomplete:
+
     b->pos = p;
     r->state = state;
     r->header_hash = hash;
--- src/http/ngx_http_request.c.orig    2010-10-06 21:39:33.000000000 +0400
+++ src/http/ngx_http_request.c 2010-10-07 16:02:22.000000000 +0400
@@ -1118,7 +1118,9 @@
 
     n = r->header_in->last - r->header_in->pos;
 
-    if (n > 0) {
+    /* Return immediately only in case there are more than two bytes 
+     * buffered, else LWS readahead will not be able to complete */
+    if (n > 2) {
         return n;
     }
 
@@ -1126,6 +1128,10 @@
         n = c->recv(c, r->header_in->last,
                     r->header_in->end - r->header_in->last);
     } else {
+        n = r->header_in->last - r->header_in->pos;
+        if (n > 0) { 
+            return n;
+        } 
         n = NGX_AGAIN;
     }
 
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://nginx.org/mailman/listinfo/nginx-ru


 




Copyright © Lexa Software, 1996-2009.