<?xml version="1.0"?>
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
        <!ENTITY rfc7749 PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7749.xml'>
        <!ENTITY rfc7710 PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7710.xml'>
        <!ENTITY rfc2119 PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml'>
        <!ENTITY rfc7159 PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.7159.xml'>
        <!ENTITY cparch PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.larose-capport-architecture.xml'>
        <!ENTITY jcr    PUBLIC '' 'http://xml2rfc.ietf.org/public/rfc/bibxml-ids/reference.I-D.newton-json-content-rules.xml'>
        ]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc strict="yes"?>
<?rfc toc="yes"?>
<?rfc tocompact="yes"?>
<?rfc tocdepth="6"?>
<?rfc symrefs="yes"?>
<?rfc sortrefs="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="no"?>

<rfc category="info" docName="draft-donnelly-capport-detection-02">
  <front>
    <title>Captive Portal (CAPPORT) API</title>

    <author initials="M." surname="Donnelly" fullname="Mark Donnelly">
      <organization>Painless Security</organization>
      <address>
        <postal>
          <street>14 Summer Street, Suite 202</street>
          <city>Malden</city>
          <region>MA</region>
          <code>02148</code>
          <country>USA</country>
        </postal>
        <phone></phone>
        <email>mark@painless-security.com</email>
        <uri>http://www.painless-security.com</uri>
      </address>
    </author>

    <author initials="M." surname="Cullen" fullname="Margaret Cullen">
      <organization>Painless Security</organization>
      <address>
        <postal>
          <street>14 Summer Street, Suite 202</street>
          <city>Malden</city>
          <region>MA</region>
          <code>02148</code>
          <country>USA</country>
        </postal>
        <phone>+1 781 405-7464</phone>
        <email>margaret@painless-security.com</email>
        <uri>http://www.painless-security.com</uri>
      </address>
    </author>

    <date day="3" month="July" year="2017"/>

    <area>ART</area>

    <workgroup>Captive Portal WG</workgroup>

    <abstract>
      <t>
        This document describes an HTTP API that allows User Equipment
        to detect the existence of a Captive Portal on the local
        network and determine the properties of the Captive Portal.
      </t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">
      <t>
        This document describes a HyperText Transfer Protocol (HTTP)
        Application Program Interface (API) that allows User Equipment
        to detect the existence of a Captive Portal (CAPPORT) on the
        local network and determine the properties of the Captive
        Portal. The API defined in this document has been designed
        to meet the requirements of the CAPPORT API, as discussed in
        the CAPPORT Architecture
        <xref target="I-D.larose-capport-architecture"/>.
      </t>
    </section>

    <section title="Requirements Notation">
      <t>
        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<xref target="RFC2119"/>.
      </t>
    </section>

    <section title="Workflow">
      <t>
        The CAPPORT protocol consists of two phases. In the first
        phase User Equipment acquires an IP address and determines
        the URL of the local CAPPORT API Server, if any. The second phase
        consists of the User Equipment querying the CAPPORT
        API Server for the requirements for accessing its protected
        networks.
      </t>
      <t>
        During the first phase, User Equipment uses the Dynamic Host
        Configuration Protocol (DHCP) or IPv6 Router Advertisements
        (RAs) to acquire an IP address and to determine the URL for the
        local CAPPORT API Server. This details for the first phase are
        described in RFC 7710<xref target="RFC7710"/>, and the rest
        of this document assumes that the User Equipments already has
        a URL to reach the CAPPORT API Server.
      </t>
      <t>
        The second phase begins with the User Equipment accessing the
        URL provided in the first phase with JSON content type. The
        CAPPORT API Server responds with the current status of the
        User Equipment's access to the protected networks.
      </t>
      <t>
        The User Equipment SHOULD request the same URL with an HTML
        content type to start the process to gain access to the
        Captive Portal.
      </t>
    </section>

    <section title="Use of the DHCP Captive-Portal Option">
      <t>
        As decribed above, to use the CAPPORT API, User Equipment
        needs a URL that can be used to reach the CAPPORT API Server.
        DHCP Servers and IPv6 Routers SHOULD provide, and User
        Equipment SHOULD obtain, the required URL using the
        DCHP Captive-Portal Option or the IPv6 RA Captive-Portal
        Option, as described in <xref target="RFC7710"/>.
      </t>
      <t>
        To provide backwards compatibility with the original use of
        the DHCP and RA options described in RFC7710, the CAPPORT API
        defined in this document is exclusively accessed using HTTP
        with an Accept header value of "application/json".
        Captive Portals that implement the CAPPORT API SHOULD respond to
        an HTTP GET that has an Accept header of "text/html" with HTML
        content that, when displayed in a web browser, will allow the
        user to interactively meet the Captive Portal requirements for
        network access.
      </t>
    </section>

    <section title="CAPPORT API">
      <t>
        This section defines the CAPPORT API.
      </t>
      <section title="URLs and HTTP Methods">
        <t>
          This section describes the URLs that can be used to
          access the CAPPORT API.
        </t>
        <section title="Associating User Equipment with its URL">
          <t>
            The CAPPORT API Server SHOULD associate an incoming
            request with a particular User Equipment consistently.
            [TODO: specify how this would happen.]
          </t>
        </section>

        <section title="Interactive URL">
          <t>
            The CAPPORT API Server SHOULD respond to HTTP GET requests
            to the provided URL that specify an Accept header value of
            "text/html" with HTML content instead of this protocol.
            When the User Equipment wants to
            satisfy the conditions for network access, it SHOULD
            display this interactive URL in a web browser to allow the
            user to complete the network access outside of this
            protocol.
          </t>
        </section>

        <section title="CAPPORT API POST URL"
                 anchor="i_didnt_mean_to_scream_that_title_but_its_all_acronyms">
          <t>
            The CAPPORT API Server SHOULD respond to HTTP POST
            requests to the provided URL that specify an Accept header
            value of "application/json" with the CAPPORT API
            protocol.
          </t>
        </section>

      </section>

      <section title="JSON Data Structures">
        <t>
          The CAPPORT API data structures are specified in JavaScript
          Object Notation (JSON)<xref target="RFC7159"/>. This
          document specifies the structure of the JSON structures
          and message using the JSON Content Rules (JCR) defined in
          draft-newton-json-content-rules
          <xref target="I-D.newton-json-content-rules"/>.
        </t>
        <section title="CAPPORT Common Elements">
          <t>
            This section describes structures that are shared between
            requests and responses.
          </t>

          <section title="Toplevel Object" anchor="json_toplevel_object">
            <t>
              The CAPPORT API will contain JSON-formatted data. The
              toplevel object contains a networks object whose
              value is an array of zero or more network objects.
            </t>
            <t>
              <figure>
                <artwork xml:space="preserve">
    $toplevel = {
      $networks ,
      $session_token ?
    }
                </artwork>
              </figure>
            </t>
            <t>
              The toplevel object MUST contain a networks object.
            </t>
            <t>
              The CAPPORT API Server responses MUST contain a
              session_token object. The session-token
              object contains a session token which will be used in
              ICMP requests as discussed in RFC 7710.
            </t>
            <t>
              <spanx>QUESTION:</spanx>
              Should the session token just be
              provided by the server, or should it be negotiated
              between the client and server using something like a DH
              exchange?
            </t>
          </section>

          <section title="Networks Object" anchor="json_networks_object">
            <t>
              The networks object represents the list of networks
              being acted on in this CAPPORT session.
            </t>
            <t>
              <figure>
                <artwork xml:space="preserve">
    $networks = {
      ( "DEFAULT" || // ) = $network +
    }
                </artwork>
              </figure>
            </t>
            <t>
              The networks object is a JSON object whose keys are
              network names and whose values are network objects.
              Thus a single response could be used in gaining access
              to multiple protected networks at once. The first
              request to the CAPPORT API Server will contain no
              networks, and acts as a discovery request.
            </t>
            <t>
              The CAPPORT API Server SHOULD use the special name
              DEFAULT for one network that provides access to the
              greater Internet.
            </t>
          </section>

          <section title="Network Object" anchor="json_network_object">
            <t>
              The network object represents a network protected by the
              Captive Portal.
            </t>
            <t>
              <figure>
                <artwork xml:space="preserve">
    $network = {
      "conditions" : [ $condition + ] ,
      "state" : $network_state ? ,
      "details" : $network_details ?
    }
                </artwork>
              </figure>
            </t>
            <t>
              The network object MUST contain a 'conditions' key whose
              value is an array of one or more $condition objects,
              which represent the unmet conditions for gaining access
              to this network. The conditions object SHOULD NOT
              contain conditions that have already been met.
            </t>
            <t>
              CAPPORT API Server responses MUST contain the 'state'
              key, whose value is the $network_state object, which
              represents the state of access that the User Equipment
              has to the network.
            </t>
            <t>
              CAPPORT API Server responses SHOULD contain the
              'details' key, whose value is the $network_details
              object, which provides relevant information about the
              network.
            </t>
          </section>

        </section>

        <!--
          ** User Equipment Requests to the CAPPORT API Server
          -->
        <section title="User Equipment Request">
          <t>
            For the initial CAPPORT request from the User Equipment,
            the JSON object will consist of
            the <xref target="json_toplevel_object">toplevel
            object
          </xref> with its
            required
            <xref target="json_networks_object">networks</xref>
            objects. The networks object will contain no networks,
            and the session_token object will be empty. This acts as a
            discovery request.
          </t>
          <t>
            <figure align="center" anchor="capport_request_initial">
              <artwork>
                {
                "networks" : {}
                "session-token" : ""
                }
              </artwork>
            </figure>
          </t>

          <section title="CAPPORT API Server Response">

            <section title="Network State Object" anchor="json_network_state">
              <t>
                The network_state object details the current state of
                the User Equipment access to the protected network.
              </t>
              <t>
                <figure>
                  <artwork>
                    $network_state = {
                    "permitted" : boolean ,
                    "expires" : datetime ? ,
                    "bytes_remaining" : integer ?
                    }
                  </artwork>
                </figure>
              </t>

              <t>
                The network_state object MUST contain the "permitted"
                key, whose boolean value indicates whether the User
                Equipment is permitted to access the protected network.
              </t>
              <t>
                The network_state object SHOULD contain the "expires"
                key if the access to the protected network will expire
                at a known time in the future. The value is a datetime
                object of the time the access will expire. If there is
                not a known expiration time, the key SHOULD be omitted.
              </t>
              <t>
                The network_state object SHOULD contain the
                "bytes_remaining" key if the access to the protected
                network will expire after the User Equipment transfers a
                known number of bytes. The value is an integer of the
                number of bytes remaining. If there is not a known limit
                for this User Equipment, the key MAY be omitted or
                its value MAY be -1.
              </t>
            </section>
          </section>
        </section>
      </section>
    </section>

    <section title="IANA Considerations">
      <t>
        This document does not require any IANA allocations. Please
        remove this section before RFC publication.
      </t>
    </section>

    <section title="Security Considerations">
      <t>
        The CAPPORT API described in this document is intended to
        automate a process that is currently accomplished by a user
        filling out a HTML form in a Web Browser. Therefore, this
        mechanism should meet the requirement of being no less secure
        than presenting the user with a HTML form for completion in a
        Web Browser, and submitting that form to a Captive Portal.
      </t>
      <t>
        TBD: Provide complete security requirements and analysis.
      </t>
      <section title="Privacy Considerations">
        <t>
          Information passed in this protocol may include a user's
          personal information, such as a full name and credit card
          details. Therefore, it is important that CAPPORT API
          Servers do not allow access to the CAPPORT API over
          unecrypted sessions.
        </t>
      </section>
    </section>

    <section title="Acknowledgements">
      <t>
        This document was written using xml2rfc, as described in
        <xref target="RFC7749"/>
      </t>
    </section>
  </middle>

  <back>
    <references title="Normative References">
      &rfc2119;
      &rfc7710;
      &rfc7159;
      &cparch;
      &jcr;
    </references>
    <references title="Informative References">
      &rfc7749;
    </references>
  </back>
</rfc>
