P2PSIP | M.P.H. Petit-Huguenin |
Internet-Draft | Impedance Mismatch |
Intended status: Standards Track | October 22, 2012 |
Expires: April 23, 2013 |
Configuration of Access Control Policy in REsource LOcation And Discovery (RELOAD) Base Protocol
draft-petithuguenin-p2psip-access-control-05
This document describes an extension to the REsource LOcation And Discovery (RELOAD) base protocol to distribute the code of new Access Control Policies without having to upgrade the RELOAD implementations in an overlay.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at http:/⁠/⁠datatracker.ietf.org/⁠drafts/⁠current/⁠.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on April 23, 2013.
Copyright (c) 2012 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http:/⁠/⁠trustee.ietf.org/⁠license-⁠info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
This document may not be modified, and derivative works of it may not be created, except to format it for publication as an RFC or to translate it into languages other than English.
The RELOAD base protocol specifies an Access Control Policy as "defin[ing] whether a request from a given node to operate on a given value should succeed or fail." The paragraph continues saying that "[i]t is anticipated that only a small number of generic access control policies are required", but there is indications that this assumption will not hold. On all the RELOAD Usages defined in other documents than the RELOAD base protocol, roughly 50% defines a new Access Control Policy.
The problem with a new Access Control Policy is that, because it is executed when a Store request is processed, it needs to be implemented by all the peers and so requires an upgrade of the software. This is something that is probably not possible in large overlays or on overlays using different implementations. For this reason, this document proposes an extension to the RELOAD configuration document that permits to transport the code of a new Access Control Policy to each peer.
This extension defines a new element <access-control-code> that can be optionally added to a <configuration> element in the configuration document. The <access-control-code> element contains ECMAScript [ECMA-262] code that will be called for each StoredData object that use this access control policy. The code receives four parameters, corresponding to the Resource-ID, Signature, Kind and StoredDataValue of the value to store. The code returns true or false to signal to the implementation if the request should succeed or fail.
For example the USER-MATCH Access Control Policy defined in the base protocol could be redefined by inserting the following code in an <access-control-code> element:
return resource.equalsHash(signer.user_name.bytes());
The <kind> parameters are also passed to the code, so the NODE-MULTIPLE Access Control Policy could be implemented like this:
for (var i = 0; i < kind.max_node_multiple; i++) { if (resource.equalsHash(signer.node_id, i.width(4))) { return true; } } return false;
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] .
"SHOULD", "SHOULD NOT", "RECOMMENDED", and "NOT RECOMMENDED" are appropriate when valid exceptions to a general requirement are known to exist or appear to exist, and it is infeasible or impractical to enumerate all of them. However, they should not be interpreted as permitting implementors to fail to implement the general requirement when such failure would result in interoperability failure.
A peer receiving a configuration document containing one or more <access-control-code> elements, either by retrieving it from the configuration server or in a ConfigUpdateReq message, MUST reject this configuration if is not is not signed or if the signature verification fails.
The Compact Relax NG Grammar for this element is:
namespace acp = "http://implementers.org/access-control" parameter &= element acp:access-control-code { attribute name { xsd:string }, xsd:base64Binary }?
The "name" attribute defines the access control policy and can then be used in a <kind> element as if it was defined by IANA.
If the <access-control-code> element is present in the namespace allocated to this specification, and the Access Control Policy is not natively implemented, then the code inside the element MUST be called for each DataValue found in a received StoreReq for a Kind that is defined with this access control policy. The content of the <access-control-code> element MUST be decoded using the base64 [RFC4648] encoding, uncompressed using gzip [RFC1952] then converted to characters using UTF-8. <access-control-code> elements that are not encoded using UTF-8, compressed with gzip or finally converted to the base64 format MUST be ignored. For each call to the code, the following ECMAScript objects, properties and functions MUST be available:
The properties SHOULD NOT be modifiable or deletable and if they are, modifying or deleting them MUST NOT modify or delete the equivalent internal values (in other words, the code cannot be used to modify the elements that will be stored).
The value returned by the code is evaluated to true or false, according to the ECMAScript rules. If the return value of one of the call to the code is evaluated to false, then the StoreReq fails, the state MUST be rolled back and an Error_Forbidden MUST be returned.
Because the configuration document containing the ECMAScript code is under the responsability of the same entity that will sign it, using a scripting language does not introduce any additional risk if the RELOAD implementers follow the rules in this document (no side effect when modifying the parameters, only base classes of ECMAScript implemented, etc...). It is even possible to deal with less than perfect implementations as long as they do not accept a configuration file that is not signed correctly. One way for the signer to enforce this would be to deliberately send in a ConfigUpdate an incorrectly signed version of the configuration file and blacklist all the nodes that accepted it in a newly issued configuration file.
By permitting multiple overlay implementations to interoperate inside one overlay, RELOAD helps build overlays that are not only resistant to hardware or communication failures, but also to programmer errors. Distributing the access control policy code inside the configuration document reintroduces this single point of failure. To mitigate this problem, new access control policies should be implemented natively as soon as possible, but if all implementations uses the script as a blueprint for the native code, an hidden bug can be duplicated. This is why developers should implement new access control policies from the normative text instead of using the code. That is anyway probably not legal under most copyright laws so to help developers do the right thing the code in the configuration is obfuscated by compressing and encoding it as a base64 character string.
If this document is accepted as a standard track document this section will request an URN in the "XML Namespaces" class of the "IETF XML Registry" from IANA. Until this is done, implementions should use the following URN:
http://implementers.org/access-control
[RFC1952] | Deutsch, P., "GZIP file format specification version 4.3", RFC 1952, May 1996. |
[RFC2119] | Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. |
[RFC4648] | Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006. |
[I-D.ietf-p2psip-base] | Jennings, C, Lowekamp, B, Rescorla, E, Baset, S and H Schulzrinne, "REsource LOcation And Discovery (RELOAD) Base Protocol", Internet-Draft draft-ietf-p2psip-base-22, July 2012. |
[ECMA-262] | Ecma, , "ECMAScript Language Specification 3rd Edition", December 2009. |
[I-D.ietf-p2psip-service-discovery] | Maenpaa, J and G Camarillo, "Service Discovery Usage for REsource LOcation And Discovery (RELOAD)", Internet-Draft draft-ietf-p2psip-service-discovery-06, October 2012. |
[I-D.petithuguenin-vipr-reload-usage] | Petit-Huguenin, M, Rosenberg, J and C Jennings, "A Usage of Resource Location and Discovery (RELOAD) for Public Switched Telephone Network (PSTN) Verification", Internet-Draft draft-petithuguenin-vipr-reload-usage-04, March 2012. |
[I-D.ietf-p2psip-share] | Knauf, A, Schmidt, T, Hege, G and M Waehlisch, "A Usage for Shared Resources in RELOAD (ShaRe)", Internet-Draft draft-ietf-p2psip-share-00, October 2012. |
This section shows the ECMAScript code that could be used to implement the standard Access Control Policies defined in [I-D.ietf-p2psip-base] .
String.prototype['bytes'] = function () { var bytes = []; for (var i = 0; i < this.length; i++) { bytes[i] = this.charCodeAt(i); } return bytes; }; return resource.equalsHash(entry.signer.user_name.bytes());
return resource.equalsHash(entry.signer.node_id);
String.prototype['bytes'] = function () { var bytes = []; for (var i = 0; i < this.length; i++) { bytes[i] = this.charCodeAt(i); } return bytes; }; var equals = function (a, b) { if (a.length !== b.length) return false; for (var i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; }; return resource.equalsHash(entry.signer.user_name.bytes()) && equals(entry.key, entry.signer.node_id);
Number.prototype['width'] = function (w) { var bytes = []; for (var i = 0; i < w; i++) { bytes[i] = (this >>> ((w - i - 1) * 8)) & 255; } return bytes; }; for (var i = 0; i < kind.max_node_multiple; i++) { if (resource.equalsHash(entry.signer.node_id, i.width(4))) { return true; } } return false;
[I-D.ietf-p2psip-service-discovery] defines a specific Access Control Policy (NODE-ID-MATCH) that need to access the content of the entry to be written. If implemented as specified by this document, the ECMAScript code would look something like this:
/* Insert here the code from http://jsfromhell.com/classes/bignumber */ var toBigNumber = function (node_id) { var bignum = new BigNumber(0); for (var i = 0; i < node_id.length; i++) { bignum = bignum.multiply(256).add(node_id[i]); } return bignum; }; var checkIntervals = function (node_id, level, node, factor) { var size = new BigNumber(2).pow(128); var node = toBigNumber(node_id); for (var f = 0; f < factor; f++) { var temp = size.multiply(new BigNumber(f) .pow(new BigNumber(level).negate())); var min = temp.multiply(node.add(new BigNumber(f) .divide(factor))); var max = temp.multiply(node.add(new BigNumber(f + 1) .divide(factor))); if (node.compare(min) === -1 || node.compare(max) == 1 || node.compare(max) == 0) return false; } return true; }; var equals = function (a, b) { if (a.length !== b.length) return false; for (var i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; }; var level = function (value) { var length = value[16] * 256 + value[17]; return value[18 + length] * 256 + value[18 + length + 1]; }; var node = function (value) { var length = value[16] * 256 + value[17]; return value[18 + length + 2] * 256 + value[18 + length + 3]; }; var namespace = function (value) { var length = value[16] * 256 + value[17]; return String.fromCharCode.apply(null, value.slice(18, length + 18)); }; var branching_factor = kind.evaluate('/branching-factor', 'redir', 'urn:ietf:params:xml:ns:p2p:redir'); return equals(entry.key, entry.signer.node_id) && (!entry.exists || checkIntervals(entry.key, level(entry.value), node(entry.value), branching_factor)) && (!entry.exists || resource.equalsHash(namespace(entry.value), level(entry.value), node(entry.value)));
Note that the code for the BigNumber object was removed from this example, as the licensing terms are unclear. The code is available at http://jsfromhell.com/classes/bignumber .
[I-D.petithuguenin-vipr-reload-usage] defines a specific Access Control Policy. If implemented as specified by this document, the ECMAScript code would look something like this:
var equals = function (a, b) { if (a.length !== b.length) return false; for (var i = 0; i < a.length; i++) { if (a[i] !== b[i]) return false; } return true; }; var length = configuration.node_id_length; return equals(entry.key.slice(0, length), entry.value.slice(4, length + 4)) && equals(entry.key.slice(0, length), entry.signer.node_id);
[I-D.ietf-p2psip-share] defines a new Access Control Policies, USER-CHAIN-ACL. If implemented as specified by this document, the ECMAScript code would look something like this:
var pattern = kind.evaluate('/share:pattern', 'share', 'urn:ietf:params:xml:ns:p2p:config-share'); var username = entry.signer.user_name.match(/^([^@]+)@(.+)$/); var new_pattern = new RegExp( pattern.replace('$USER', username[1]) .replace('$DOMAIN', username[2])); var length = entry.value[0] * 256 + entry.value[1]; var resource_name = String.fromCharCode.apply(null, entry.value.slice(2, length + 2)); return new_pattern.test(resource_name);\n"));
[[Note: the code is incomplete]]
This section must be removed before publication as an RFC.