Exemplo n.º 1
0
static void
http_swallow_body(struct http *hp, char * const *hh, int body)
{
	char *p, *q;
	int i, l, ll;


	ll = 0;
	p = http_find_header(hh, "content-length");
	if (p != NULL) {
		l = strtoul(p, NULL, 0);
		hp->body = hp->rxbuf + hp->prxbuf;
		http_rxchar(hp, l);
		vtc_dump(hp->vl, 4, "body", hp->body);
		sprintf(hp->bodylen, "%d", l);
		return;
	}
	p = http_find_header(hh, "transfer-encoding");
	if (p != NULL && !strcmp(p, "chunked")) {
		hp->body = hp->rxbuf + hp->prxbuf;
		while (1) {
			l = hp->prxbuf;
			do
				http_rxchar(hp, 1);
			while (hp->rxbuf[hp->prxbuf - 1] != '\n');
			vtc_dump(hp->vl, 4, "len", hp->rxbuf + l);
			i = strtoul(hp->rxbuf + l, &q, 16);
			assert(q != hp->rxbuf + l);
			assert(*q == '\0' || vct_islws(*q));
			hp->prxbuf = l;
			if (i > 0) {
				ll += i;
				http_rxchar(hp, i);
				vtc_dump(hp->vl, 4, "chunk", hp->rxbuf + l);
			}
			l = hp->prxbuf;
			http_rxchar(hp, 2);
			assert(vct_iscrlf(hp->rxbuf[l]));
			assert(vct_iscrlf(hp->rxbuf[l + 1]));
			hp->prxbuf = l;
			hp->rxbuf[l] = '\0';
			if (i == 0)
				break;
		}
		vtc_dump(hp->vl, 4, "body", hp->body);
		sprintf(hp->bodylen, "%d", ll);
		return;
	}
	if (body) {
		hp->body = hp->rxbuf + hp->prxbuf;
		do  {
			i = http_rxchar_eof(hp, 1);
			ll += i;
		} while (i > 0);
		vtc_dump(hp->vl, 4, "rxeof", hp->body);
	}
	sprintf(hp->bodylen, "%d", ll);
}
Exemplo n.º 2
0
static int
http_rxchunk(struct http *hp)
{
	char *q;
	int l, i;

	l = hp->prxbuf;
	do
		(void)http_rxchar(hp, 1, 0);
	while (hp->rxbuf[hp->prxbuf - 1] != '\n');
	vtc_dump(hp->vl, 4, "len", hp->rxbuf + l, -1);
	i = strtoul(hp->rxbuf + l, &q, 16);
	bprintf(hp->chunklen, "%d", i);
	if ((q == hp->rxbuf + l) ||
		(*q != '\0' && !vct_islws(*q))) {
		vtc_log(hp->vl, hp->fatal, "chunked fail %02x @ %d",
		    *q, q - (hp->rxbuf + l));
	}
	assert(q != hp->rxbuf + l);
	assert(*q == '\0' || vct_islws(*q));
	hp->prxbuf = l;
	if (i > 0) {
		(void)http_rxchar(hp, i, 0);
		vtc_dump(hp->vl, 4, "chunk",
		    hp->rxbuf + l, i);
	}
	l = hp->prxbuf;
	(void)http_rxchar(hp, 2, 0);
	if(!vct_iscrlf(hp->rxbuf[l]))
		vtc_log(hp->vl, hp->fatal,
		    "Wrong chunk tail[0] = %02x",
		    hp->rxbuf[l] & 0xff);
	if(!vct_iscrlf(hp->rxbuf[l + 1]))
		vtc_log(hp->vl, hp->fatal,
		    "Wrong chunk tail[1] = %02x",
		    hp->rxbuf[l + 1] & 0xff);
	hp->prxbuf = l;
	hp->rxbuf[l] = '\0';
	return (i);
}
Exemplo n.º 3
0
static uint16_t
http1_splitline(struct http *hp, struct http_conn *htc, const int *hf,
    unsigned maxhdr)
{
	char *p;
	int i;

	assert(hf == HTTP1_Req || hf == HTTP1_Resp);
	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	assert(htc->rxbuf_e >= htc->rxbuf_b);

	AZ(hp->hd[hf[0]].b);
	AZ(hp->hd[hf[1]].b);
	AZ(hp->hd[hf[2]].b);

	/* Skip leading LWS */
	for (p = htc->rxbuf_b ; vct_islws(*p); p++)
		continue;
	hp->hd[hf[0]].b = p;

	/* First field cannot contain SP or CTL */
	for (; !vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[hf[0]].e = p;
	assert(Tlen(hp->hd[hf[0]]));
	*p++ = '\0';

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[hf[1]].b = p;

	/* Second field cannot contain LWS or CTL */
	for (; !vct_islws(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[hf[1]].e = p;
	if (!Tlen(hp->hd[hf[1]]))
		return (400);
	*p++ = '\0';

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[hf[2]].b = p;

	/* Third field is optional and cannot contain CTL except TAB */
	for (; !vct_iscrlf(p); p++) {
		if (vct_isctl(*p) && !vct_issp(*p)) {
			hp->hd[hf[2]].b = NULL;
			return (400);
		}
	}
	hp->hd[hf[2]].e = p;

	/* Skip CRLF */
	i = vct_skipcrlf(p);
	*p = '\0';
	p += i;

	return (http1_dissect_hdrs(hp, p, htc, maxhdr));
}
Exemplo n.º 4
0
static uint16_t
http1_dissect_hdrs(struct http *hp, char *p, struct http_conn *htc,
    unsigned maxhdr)
{
	char *q, *r;

	assert(p > htc->rxbuf_b);
	assert(p <= htc->rxbuf_e);
	hp->nhd = HTTP_HDR_FIRST;
	hp->conds = 0;
	r = NULL;		/* For FlexeLint */
	for (; p < htc->rxbuf_e; p = r) {

		/* Find end of next header */
		q = r = p;
		if (vct_iscrlf(p))
			break;
		while (r < htc->rxbuf_e) {
			if (!vct_isctl(*r) || vct_issp(*r)) {
				r++;
				continue;
			}
			if (!vct_iscrlf(r)) {
				VSLb(hp->vsl, SLT_BogoHeader,
				    "Header has ctrl char 0x%02x", *r);
				return (400);
			}
			q = r;
			assert(r < htc->rxbuf_e);
			r += vct_skipcrlf(r);
			if (r >= htc->rxbuf_e)
				break;
			if (vct_iscrlf(r))
				break;
			/* If line does not continue: got it. */
			if (!vct_issp(*r))
				break;

			/* Clear line continuation LWS to spaces */
			while (vct_islws(*q))
				*q++ = ' ';
		}

		if (q - p > maxhdr) {
			VSLb(hp->vsl, SLT_BogoHeader, "Header too long: %.*s",
			    (int)(q - p > 20 ? 20 : q - p), p);
			return (400);
		}

		/* Empty header = end of headers */
		if (p == q)
			break;

		if (vct_islws(*p)) {
			VSLb(hp->vsl, SLT_BogoHeader,
			    "1st header has white space: %.*s",
			    (int)(q - p > 20 ? 20 : q - p), p);
			return (400);
		}

		if ((p[0] == 'i' || p[0] == 'I') &&
		    (p[1] == 'f' || p[1] == 'F') &&
		    p[2] == '-')
			hp->conds = 1;

		while (q > p && vct_issp(q[-1]))
			q--;
		*q = '\0';

		if (strchr(p, ':') == NULL) {
			VSLb(hp->vsl, SLT_BogoHeader, "Header without ':' %.*s",
			    (int)(q - p > 20 ? 20 : q - p), p);
			return (400);
		}

		if (hp->nhd < hp->shd) {
			hp->hdf[hp->nhd] = 0;
			hp->hd[hp->nhd].b = p;
			hp->hd[hp->nhd].e = q;
			hp->nhd++;
		} else {
			VSLb(hp->vsl, SLT_BogoHeader, "Too many headers: %.*s",
			    (int)(q - p > 20 ? 20 : q - p), p);
			return (400);
		}
	}
	if (p < htc->rxbuf_e)
		p += vct_skipcrlf(p);
	HTC_RxPipeline(htc, p);
	htc->rxbuf_e = p;
	return (0);
}
Exemplo n.º 5
0
static void
http_splitheader(struct http *hp, int req)
{
	char *p, *q, **hh;
	int n;
	char buf[20];

	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	if (req) {
		memset(hp->req, 0, sizeof hp->req);
		hh = hp->req;
	} else {
		memset(hp->resp, 0, sizeof hp->resp);
		hh = hp->resp;
	}

	n = 0;
	p = hp->rxbuf;

	/* REQ/PROTO */
	while (vct_islws(*p))
		p++;
	hh[n++] = p;
	while (!vct_islws(*p))
		p++;
	assert(!vct_iscrlf(*p));
	*p++ = '\0';

	/* URL/STATUS */
	while (vct_issp(*p))		/* XXX: H space only */
		p++;
	assert(!vct_iscrlf(*p));
	hh[n++] = p;
	while (!vct_islws(*p))
		p++;
	if (vct_iscrlf(*p)) {
		hh[n++] = NULL;
		q = p;
		p += vct_skipcrlf(p);
		*q = '\0';
	} else {
		*p++ = '\0';
		/* PROTO/MSG */
		while (vct_issp(*p))		/* XXX: H space only */
			p++;
		hh[n++] = p;
		while (!vct_iscrlf(*p))
			p++;
		q = p;
		p += vct_skipcrlf(p);
		*q = '\0';
	}
	assert(n == 3);

	while (*p != '\0') {
		assert(n < MAX_HDR);
		if (vct_iscrlf(*p))
			break;
		hh[n++] = p++;
		while (*p != '\0' && !vct_iscrlf(*p))
			p++;
		q = p;
		p += vct_skipcrlf(p);
		*q = '\0';
	}
	p += vct_skipcrlf(p);
	assert(*p == '\0');

	for (n = 0; n < 3 || hh[n] != NULL; n++) {
		sprintf(buf, "http[%2d] ", n);
		vtc_dump(hp->vl, 4, buf, hh[n], -1);
	}
}
Exemplo n.º 6
0
static uint16_t
http_splitline(struct worker *w, int fd, struct http *hp,
    const struct http_conn *htc, int h1, int h2, int h3)
{
	char *p, *q;

	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);

	/* XXX: Assert a NUL at rx.e ? */
	Tcheck(htc->rxbuf);

	/* Skip leading LWS */
	for (p = htc->rxbuf.b ; vct_islws(*p); p++)
		continue;

	/* First field cannot contain SP, CRLF or CTL */
	q = p;
	for (; !vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h1].b = q;
	hp->hd[h1].e = p;

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}

	/* Second field cannot contain LWS or CTL */
	q = p;
	for (; !vct_islws(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h2].b = q;
	hp->hd[h2].e = p;

	if (!Tlen(hp->hd[h2]))
		return (413);

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}

	/* Third field is optional and cannot contain CTL */
	q = p;
	if (!vct_iscrlf(*p)) {
		for (; !vct_iscrlf(*p); p++)
			if (!vct_issep(*p) && vct_isctl(*p))
				return (400);
	}
	hp->hd[h3].b = q;
	hp->hd[h3].e = p;

	/* Skip CRLF */
	p += vct_skipcrlf(p);

	*hp->hd[h1].e = '\0';
	WSLH(w, fd, hp, h1);

	*hp->hd[h2].e = '\0';
	WSLH(w, fd, hp, h2);

	if (hp->hd[h3].e != NULL) {
		*hp->hd[h3].e = '\0';
		WSLH(w, fd, hp, h3);
	}

	return (http_dissect_hdrs(w, hp, fd, p, htc));
}
Exemplo n.º 7
0
static uint16_t
http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p,
    const struct http_conn *htc)
{
	char *q, *r;
	txt t = htc->rxbuf;

	if (*p == '\r')
		p++;

	hp->nhd = HTTP_HDR_FIRST;
	hp->conds = 0;
	r = NULL;		/* For FlexeLint */
	for (; p < t.e; p = r) {

		/* Find end of next header */
		q = r = p;
		while (r < t.e) {
			if (!vct_iscrlf(*r)) {
				r++;
				continue;
			}
			q = r;
			assert(r < t.e);
			r += vct_skipcrlf(r);
			if (r >= t.e)
				break;
			/* If line does not continue: got it. */
			if (!vct_issp(*r))
				break;

			/* Clear line continuation LWS to spaces */
			while (vct_islws(*q))
				*q++ = ' ';
		}

		if (q - p > htc->maxhdr) {
			VSC_C_main->losthdr++;
			WSL(w, SLT_LostHeader, fd, "%.*s",
			    q - p > 20 ? 20 : q - p, p);
			return (413);
		}

		/* Empty header = end of headers */
		if (p == q)
			break;

		if ((p[0] == 'i' || p[0] == 'I') &&
		    (p[1] == 'f' || p[1] == 'F') &&
		    p[2] == '-')
			hp->conds = 1;

		while (q > p && vct_issp(q[-1]))
			q--;
		*q = '\0';

		if (hp->nhd < hp->shd) {
			hp->hdf[hp->nhd] = 0;
			hp->hd[hp->nhd].b = p;
			hp->hd[hp->nhd].e = q;
			WSLH(w, fd, hp, hp->nhd);
			hp->nhd++;
		} else {
			VSC_C_main->losthdr++;
			WSL(w, SLT_LostHeader, fd, "%.*s",
			    q - p > 20 ? 20 : q - p, p);
			return (413);
		}
	}
	return (0);
}
Exemplo n.º 8
0
static uint16_t
htc_splitline(struct http *hp, const struct http_conn *htc, int req)
{
	char *p;
	int h1, h2, h3;

	CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
	Tcheck(htc->rxbuf);

	if (req) {
		h1 = HTTP_HDR_METHOD;
		h2 = HTTP_HDR_URL;
		h3 = HTTP_HDR_PROTO;
	} else {
		h1 = HTTP_HDR_PROTO;
		h2 = HTTP_HDR_STATUS;
		h3 = HTTP_HDR_RESPONSE;
	}

	/* Skip leading LWS */
	for (p = htc->rxbuf.b ; vct_islws(*p); p++)
		continue;
	hp->hd[h1].b = p;

	/* First field cannot contain SP or CTL */
	for (; !vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h1].e = p;
	assert(Tlen(hp->hd[h1]));

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h2].b = p;

	/* Second field cannot contain LWS or CTL */
	for (; !vct_islws(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h2].e = p;

	if (!Tlen(hp->hd[h2]))
		return (400);

	/* Skip SP */
	for (; vct_issp(*p); p++) {
		if (vct_isctl(*p))
			return (400);
	}
	hp->hd[h3].b = p;

	/* Third field is optional and cannot contain CTL except TAB */
	for (; !vct_iscrlf(p); p++) {
		if (vct_isctl(*p) && !vct_issp(*p)) {
			hp->hd[h3].b = NULL;
			return (400);
		}
	}
	hp->hd[h3].e = p;

	/* Skip CRLF */
	p += vct_skipcrlf(p);

	*hp->hd[h1].e = '\0';
	*hp->hd[h2].e = '\0';

	if (hp->hd[h3].e != NULL)
		*hp->hd[h3].e = '\0';

	return (htc_dissect_hdrs(hp, p, htc));
}