Re: JSON headers

"Poul-Henning Kamp" <phk@phk.freebsd.dk> Sun, 10 July 2016 22:24 UTC

Return-Path: <ietf-http-wg-request+bounce-httpbisa-archive-bis2juki=lists.ie@listhub.w3.org>
X-Original-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Delivered-To: ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id E914612D0B0 for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Sun, 10 Jul 2016 15:24:54 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -8.208
X-Spam-Level:
X-Spam-Status: No, score=-8.208 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.001, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.287, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bGDqMBc2e8Kd for <ietfarch-httpbisa-archive-bis2Juki@ietfa.amsl.com>; Sun, 10 Jul 2016 15:24:53 -0700 (PDT)
Received: from frink.w3.org (frink.w3.org [128.30.52.56]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id E078B12D119 for <httpbisa-archive-bis2Juki@lists.ietf.org>; Sun, 10 Jul 2016 15:24:52 -0700 (PDT)
Received: from lists by frink.w3.org with local (Exim 4.80) (envelope-from <ietf-http-wg-request@listhub.w3.org>) id 1bMN5m-0003LH-6q for ietf-http-wg-dist@listhub.w3.org; Sun, 10 Jul 2016 22:20:50 +0000
Resent-Date: Sun, 10 Jul 2016 22:20:50 +0000
Resent-Message-Id: <E1bMN5m-0003LH-6q@frink.w3.org>
Received: from maggie.w3.org ([128.30.52.39]) by frink.w3.org with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from <phk@phk.freebsd.dk>) id 1bMN5i-0003KZ-9H for ietf-http-wg@listhub.w3.org; Sun, 10 Jul 2016 22:20:46 +0000
Received: from phk.freebsd.dk ([130.225.244.222]) by maggie.w3.org with esmtp (Exim 4.80) (envelope-from <phk@phk.freebsd.dk>) id 1bMN5f-0004qX-OQ for ietf-http-wg@w3.org; Sun, 10 Jul 2016 22:20:45 +0000
Received: from critter.freebsd.dk (unknown [192.168.55.3]) by phk.freebsd.dk (Postfix) with ESMTP id 00C7B273B3; Sun, 10 Jul 2016 22:20:20 +0000 (UTC)
Received: from critter.freebsd.dk (localhost [127.0.0.1]) by critter.freebsd.dk (8.15.2/8.15.2) with ESMTP id u6AMKIDM005940; Sun, 10 Jul 2016 22:20:18 GMT (envelope-from phk@phk.freebsd.dk)
To: Julian Reschke <julian.reschke@gmx.de>
cc: Yanick Rochon <yanick.rochon@gmail.com>, Phil Hunt <phil.hunt@oracle.com>, HTTP Working Group <ietf-http-wg@w3.org>
In-reply-to: <176d58df-debf-e660-edf7-7d686c926ef6@gmx.de>
From: Poul-Henning Kamp <phk@phk.freebsd.dk>
References: <74180.1468000149@critter.freebsd.dk> <A17D3EFD-A935-4971-BCF6-DC9D38302CAD@oracle.com> <564a72e8-b9d3-1f9c-5982-48f2b07272e5@greenbytes.de> <3924.1468137899@critter.freebsd.dk> <683f5f58-6046-d9fb-cc75-d0ab3890ce23@greenbytes.de> <4105.1468141779@critter.freebsd.dk> <5cdf0fa8-063c-7eaa-a9e3-fb6db7417254@gmx.de> <4213.1468143913@critter.freebsd.dk> <94e4a5c2-3465-fef3-6221-d9f4fcccb5fa@gmx.de> <4324.1468145426@critter.freebsd.dk> <CAB0No9kf6gje3Tc+impphV5tUHjksCkL1PJ1YAgNjXO+tLq=XA@mail.gmail.com> <176d58df-debf-e660-edf7-7d686c926ef6@gmx.de>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <5938.1468189218.1@critter.freebsd.dk>
Content-Transfer-Encoding: quoted-printable
Date: Sun, 10 Jul 2016 22:20:18 +0000
Message-ID: <5939.1468189218@critter.freebsd.dk>
Received-SPF: none client-ip=130.225.244.222; envelope-from=phk@phk.freebsd.dk; helo=phk.freebsd.dk
X-W3C-Hub-Spam-Status: No, score=-6.0
X-W3C-Hub-Spam-Report: AWL=-0.804, BAYES_00=-1.9, RP_MATCHES_RCVD=-1.287, W3C_AA=-1, W3C_WL=-1
X-W3C-Scan-Sig: maggie.w3.org 1bMN5f-0004qX-OQ 55c53b6e34c6dc8ed900ac20bb680ead
X-Original-To: ietf-http-wg@w3.org
Subject: Re: JSON headers
Archived-At: <http://www.w3.org/mid/5939.1468189218@critter.freebsd.dk>
Resent-From: ietf-http-wg@w3.org
X-Mailing-List: <ietf-http-wg@w3.org> archive/latest/31865
X-Loop: ietf-http-wg@w3.org
Resent-Sender: ietf-http-wg-request@w3.org
Precedence: list
List-Id: <ietf-http-wg.w3.org>
List-Help: <http://www.w3.org/Mail/>
List-Post: <mailto:ietf-http-wg@w3.org>
List-Unsubscribe: <mailto:ietf-http-wg-request@w3.org?subject=unsubscribe>

--------
In message <176d58df-debf-e660-edf7-7d686c926ef6@gmx.de>, Julian Reschke writes
:

>It seems you are confusing several issues here: multiple header field 
>instances in the HTTP message, and duplicate member names in a JSON 
>object. These are completely orthogonal issues.

Uhm, no?

They only become orthogonal if whoever specifies the JSON header
takes great care to make that happen.

Allowing split headers forces all headers to be defined as JSON
lists, which means we're knee-capping header-designers from the get go.

Take this RFC7231 example:

	Accept: text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c

If we allow split headers for JSON, this can only be defined as JSON list,
in order that it can also be sent as:

	Accept: <JSON for "text/plain; q=0.5">
	Accept: <JSON for "text/html">
	Accept: <JSON for "text/x-dvi; q=0.8">
	Accept: <JSON for "text/x-c">

But that leaves it to the application writer to spot and detect and
handle this degenerate case from a lazy sender:

	Accept: <JSON for "text/plain; q=0.5">
	Accept: <JSON for "text/html">
	Accept: <JSON for "text/x-dvi; q=0.8">
	Accept: <JSON for "text/x-c">
	Accept: <JSON for "text/plain; q=0.0">

It's even more complicated for a proxy sender which wants to
modify the text/plain priority:  It needs to spot both copies
and change them both (or delete one of them).

(It seems to me that there is a class of smuggling attacks
where the proxy sees q=0.5 and the server q=0.0, which
RFC7231 does not seem address at all?)

If we instead, as I propose, require that JSON headers *never* be
split, then it becomes both possible and rather obviously smarter
to define this header as a JSON object, keyed by the media type:

	Accept: { 					\
		"text/plain": <JSON for "q=0.5">,	\
		"text/html": <JSON for no parameter>,	\
		"text-xdvi": <JSON for "q=0.8">,	\
		"text/x-c": <JSON for no parameter>	\
	}

A sender wishing to modify the priority, just sets the
corresponding JSON object using the native languages
JSON facility:

	req.accept["text/plain"] = <JSON for "q=0">

The receiver can then simply load the JSON as JSON, and the
application does not have to explicitly check for duplicate
media types, but can simply look up "text/plain" in the
JSON object.

So what happens if the sender sends bad JSON anyway ?

	Accept: { 					\
		"text/plain": <JSON for "q=0.5">,	\
		"text/html": <JSON for no parameter>,	\
		"text-xdvi": <JSON for "q=0.8">,	\
		"text/x-c": <JSON for no parameter>	\
		"text/plain": <JSON for "q=0.0">,	\
	}

Well, RFC7159 says:

	4. Objects

	[...]The names within an object SHOULD be unique.

	An object whose names are all unique is interoperable in
	the sense that all software implementations receiving that
	object will agree on the name-value mappings.  When the
	names within an object are not unique, the behavior of
	software that receives such an object is unpredictable.
	Many implementations report the last name/value pair only.
	Other implementations report an error or fail to parse the
	object, and some implementations report all of the name/value
	pairs, including duplicates.

In other words:  Don't do that.

What really happens is this:  We just opened another door to the
exact same smuggling attack as I mentioned above.

But this time we can shut them all with one single line of text:

	"Duplicate keys in JSON objects SHALL cause and be treated
	as connection failure."

So all in all, split JSON headers would be a really bad idea.

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.