From b2950f8409ee93ffb9c6e7a9d993c478b2eeba09 Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 6 Jul 2006 21:47:51 +0000 Subject: [PATCH] Refuse all requests without a protocol field with a 400 Implement a function to say "400" with. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@360 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache.h | 5 +- varnish-cache/bin/varnishd/cache_fetch.c | 2 +- varnish-cache/bin/varnishd/cache_http.c | 59 ++++++++++----------- varnish-cache/bin/varnishd/cache_pool.c | 7 ++- varnish-cache/bin/varnishd/cache_response.c | 54 +++++++++++++++++++ 5 files changed, 94 insertions(+), 33 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache.h b/varnish-cache/bin/varnishd/cache.h index ac699553..e3083ca9 100644 --- a/varnish-cache/bin/varnishd/cache.h +++ b/varnish-cache/bin/varnishd/cache.h @@ -182,7 +182,7 @@ int http_HdrIs(struct http *hp, const char *hdr, const char *val); int http_GetTail(struct http *hp, unsigned len, char **b, char **e); int http_GetURL(struct http *hp, char **b); void http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *func, void *arg); -void http_Dissect(struct http *sp, int fd, int rr); +int http_Dissect(struct http *sp, int fd, int rr); enum http_build { Build_Pipe, Build_Pass, @@ -217,6 +217,9 @@ void VSL(enum shmlogtag tag, unsigned id, const char *fmt, ...); #endif extern struct varnish_stats *VSL_stats; +/* cache_response.c */ +void RES_Error(struct worker *w, struct sess *sp, int error, const char *msg); + /* cache_vcl.c */ void RelVCL(struct VCL_conf *vc); struct VCL_conf *GetVCL(void); diff --git a/varnish-cache/bin/varnishd/cache_fetch.c b/varnish-cache/bin/varnishd/cache_fetch.c index 685b7483..6055259a 100644 --- a/varnish-cache/bin/varnishd/cache_fetch.c +++ b/varnish-cache/bin/varnishd/cache_fetch.c @@ -265,7 +265,7 @@ FetchSession(struct worker *w, struct sess *sp) http_RecvHead(hp, fd, w->eb, NULL, NULL); event_base_loop(w->eb, 0); time(&sp->t_resp); - http_Dissect(hp, fd, 2); + assert(http_Dissect(hp, fd, 2) == 0); body = RFC2616_cache_policy(sp, hp); diff --git a/varnish-cache/bin/varnishd/cache_http.c b/varnish-cache/bin/varnishd/cache_http.c index f5ea9065..795d4c12 100644 --- a/varnish-cache/bin/varnishd/cache_http.c +++ b/varnish-cache/bin/varnishd/cache_http.c @@ -205,7 +205,7 @@ http_GetStatus(struct http *hp) /*--------------------------------------------------------------------*/ -void +int http_Dissect(struct http *hp, int fd, int rr) { char *p, *q, *r; @@ -216,7 +216,7 @@ http_Dissect(struct http *hp, int fd, int rr) for (p = hp->s ; isspace(*p); p++) continue; if (rr == 1) { - /* First, isolate and possibly identify request type */ + /* First, the request type (GET/HEAD etc) */ hp->req = p; for (; isalpha(*p); p++) ; @@ -224,31 +224,34 @@ http_Dissect(struct http *hp, int fd, int rr) *p++ = '\0'; /* Next find the URI */ - while (isspace(*p)) + while (isspace(*p) && *p != '\n') p++; + if (*p == '\n') + return (400); hp->url = p; while (!isspace(*p)) p++; VSLR(SLT_URL, fd, hp->url, p); - if (*p != '\n') { - *p++ = '\0'; + if (*p == '\n') + return (400); + *p++ = '\0'; - /* Finally, look for protocol, if any */ - while (isspace(*p) && *p != '\n') - p++; - if (*p != '\n') { - hp->proto = p; - while (!isspace(*p)) - p++; - if (*p != '\n') - *p++ = '\0'; - while (isspace(*p) && *p != '\n') - p++; - } - } + /* Finally, look for protocol */ + while (isspace(*p) && *p != '\n') + p++; + if (*p == '\n') + return (400); + hp->proto = p; + while (!isspace(*p)) + p++; + VSLR(SLT_Protocol, fd, hp->proto, p); + if (*p != '\n') + *p++ = '\0'; + while (isspace(*p) && *p != '\n') + p++; + if (*p != '\n') + return (400); *p++ = '\0'; - if (hp->proto != NULL) - VSLR(SLT_Protocol, fd, hp->proto, p); } else { /* First, protocol */ hp->proto = p; @@ -304,6 +307,7 @@ http_Dissect(struct http *hp, int fd, int rr) if (hp->t != r) printf("hp->t %p r %p\n", hp->t, r); assert(hp->t == r); + return (0); } /*--------------------------------------------------------------------*/ @@ -390,6 +394,7 @@ http_RecvHead(struct http *hp, int fd, struct event_base *eb, http_callback_f *f assert(hp != NULL); assert(hp->v <= hp->e); assert(hp->t <= hp->v); + if (0) VSL(SLT_Debug, fd, "Recv t %u v %u", hp->t - hp->s, hp->v - hp->s); if (hp->t > hp->s && hp->t < hp->v) { l = hp->v - hp->t; @@ -460,21 +465,15 @@ http_BuildSbuf(int fd, enum http_build mode, struct sbuf *sb, struct http *hp) sbuf_cat(sb, hp->req); sbuf_cat(sb, " "); sbuf_cat(sb, hp->url); - if (hp->proto != NULL) { - sbuf_cat(sb, " "); - sbuf_cat(sb, hp->proto); - } + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->proto); sup = 2; break; case Build_Fetch: sbuf_cat(sb, "GET "); sbuf_cat(sb, hp->url); - if (hp->proto != NULL) { - sbuf_cat(sb, " "); - sbuf_cat(sb, hp->proto); - } else { - sbuf_cat(sb, " HTTP/1.1"); - } + sbuf_cat(sb, " "); + sbuf_cat(sb, hp->proto); sup = 1; break; default: diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index 78dfb50a..a8826b1f 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -84,7 +84,11 @@ CacheWorker(void *priv) sp->vcl = GetVCL(); AZ(pthread_mutex_unlock(&sessmtx)); - http_Dissect(sp->http, sp->fd, 1); + done = http_Dissect(sp->http, sp->fd, 1); + if (done != 0) { + RES_Error(&w, sp, done, NULL); + goto out; + } sp->backend = sp->vcl->backend[0]; @@ -121,6 +125,7 @@ CacheWorker(void *priv) vca_close_session(sp, "not HTTP/1.1"); } +out: AZ(pthread_mutex_lock(&sessmtx)); RelVCL(sp->vcl); sp->vcl = NULL; diff --git a/varnish-cache/bin/varnishd/cache_response.c b/varnish-cache/bin/varnishd/cache_response.c index ea3664fd..3d250c69 100644 --- a/varnish-cache/bin/varnishd/cache_response.c +++ b/varnish-cache/bin/varnishd/cache_response.c @@ -1,3 +1,57 @@ /* * $Id$ */ + +#include /* XXX: for NULL ?? */ +#include +#include +#include + +#include "libvarnish.h" +#include "sbuf.h" +#include "cache.h" + + +/*--------------------------------------------------------------------*/ + +void +RES_Error(struct worker *w, struct sess *sp, int error, const char *msg) +{ + char buf[40]; + + if (msg == NULL) { + switch (error) { + case 400: msg = "Bad Request"; break; + default: msg = "HTTP request error"; break; + } + } + + sbuf_clear(w->sb); + sbuf_printf(w->sb, "HTTP/1.1 %03d %s\r\n", error, msg); + TIM_format(sp->t_req, buf); + sbuf_printf(w->sb, "Date: %s\r\n", buf); + sbuf_cat(w->sb, + "Server: Varnish\r\n" + "Connection: close\r\n" + "content-Type: text/html; charset=iso-8859-1\r\n" + "\r\n" + "\r\n" + "\r\n" + " \r\n"); + sbuf_printf(w->sb, " %03d %s\r\n", error, msg); + sbuf_cat(w->sb, + " \r\n" + " \r\n"); + sbuf_printf(w->sb, "

Error %03d %s

\r\n", error, msg); + sbuf_cat(w->sb, + " Your HTTP protocol request did not make sense.\r\n" + "

\r\n" + " \r\n" + " Varnish\r\n" + " \r\n" + "\r\n"); + sbuf_finish(w->sb); + vca_write(sp, sbuf_data(w->sb), sbuf_len(w->sb)); + vca_flush(sp); + vca_close_session(sp, msg); +} -- 2.39.5