<?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-00">
  <front>
    <title>Captive Portal Detection and Interaction</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="13" month="March" 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, determine the properties of the Captive Portal, and satisfy
        requirements for network access.
      </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, determine the properties of the Captive Portal,
        and satisfy requirements for network access.  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 three 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, and submitting proofs of meeting those requirements.
	In the third phase, the User Equipment is granted access to
	the protected network and can query the CAPPORT API Server for
	status.
      </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 Equiments 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.  The CAPPORT API Server
        responds with the current status of the User Equipment's
        access to the protected networks and any conditions
        requirements to gain access to the protected networks.  The
        User Equipment then submits proofs of satisfying the access
        requirements to the CAPPORT API Server.  The CAPPORT API Server
        again responds with the current status of the User Equipment
        and any additional requirements necessary to gain access to the
        protected network.  The second phase continues until all of
        the requirements are met; the CAPPORT API Server grants access
        to the protected network and responds with a status indicating
        the access.
      </t>
      <t>
        At any point in the second phase, the User Equipment MAY stop
        communicating over the CAPPORT protocol and instead direct a
        web browser to access the URL.  The web browser then becomes
        the agent for proving that the User Equipment meets the
        requirements for access to the protected networks.
      </t>
      <t>
        During the third phase, the User Equipment has access to the
        protected network.  The User Equipment may access the URL
        provided in the first phase to query the current status.
        The CAPPORT API Server responds with the current status of the
        User Equipment.  The CAPPORT API Server SHOULD respond with
        the current status of the User Equipment regardless of whether
        the User Equipment used the automated CAPPORT protocol or a
        web browser to complete the second phase.
      </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 shoudl provide, and User
	Equipment SHOULD obtain, the required URL using the DHCP
	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
	Methods 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="Fallback 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.
            If the User Equipment determines that it is unable to
            satisfy the conditions for network access, it SHOULD
            display this fallback 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 title="CAPPORT REST API DELETE URL"
                 anchor="DELETE_request">
          <t>
            The CAPPORT API Server SHOULD respond to HTTP DELETE
            requests to the provided URL that specify an Accept header
            value of "application/json" by revoking any network access
            to protected networks immediately.  The CAPPORT API Server
            MUST NOT allow any device other than the User Equipment
            to DELETE the network access of the User Equipment via
	    the CAPPORT API.
          </t>
          <t>
            The CAPPORT API Server MAY delete the session token
            (<xref target="json_session_token_object"/>) for this User
            Equipment as part of the DELETE request.
          </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 title="Condition Object" anchor="json_condition_object">
            <t>
              The condition object describes one of the conditions
              necessary for access to the protected network.  The
              CAPPORT API Server uses this object to express the
              requirements for User Equipment to access the protected
              network.  The User Equipment uses this object as proof
              that it has satisfied the corresponding requirement for
              access to the protected network.
            </t>
            <t>
              <figure suppress-title="false" >
                <artwork xml:space="preserve">
    $condition = {
      "id" : $uuid,
      "type" : string ? ,
      "requirement_details" : $requirement_details ? ,
      "satisfaction_details" : $satisfaction_details ?
    }
                </artwork>
              </figure>
            </t>
            
            <t>
              The condition object MUST include an 'id' key whose
              value is a UUID that uniquely identifies this condition.
              This ID will be used to match the client condition
              satisfactions with the server condition requirements.
            </t>
            <t>
              CAPPORT API Server responses MUST contain the 'type'
              key, whose value is a string that represents the type of
              condition that permits access to the network.
            </t>
            <t>
              CAPPORT API Server responses MUST contain the
              'requirement_details' key, whose value is the
              $requirement_details object.  The $requirement_details
              object details the requirements that the User Equipment
              must pass to gain access to the protected network.
            </t>
            <t>
              User Equipment requests MUST contain the
              'satisfaction_details' key, whose value is the
              $satisfaction_details object.  The $satisfaction
              _details object details the proof that the User
              Equipment has satisfied the conditions of access to the
              protected network.
            </t>
	  </section>
          <section title="Session Token Object" anchor="json_session_token_object">
            <t>
              The session_token object describes the CAPPORT session token.
            </t>
            <t>
              <figure suppress-title="false">
                <artwork xml:space="preserve">
    $session_token = "session_token" : base64
                </artwork>
              </figure>
            </t>
            <t>
              The session_token object MUST include a "session_token" 
              key whose value is a base64-encoded string of a 32-bit 
              session token. This token will be used as proposed in 
              <xref target="I-D.larose-capport-architecture"/>. The 
              CAPPORT API Server SHOULD send the same session token to 
              a given User Equipment in every response, until the User 
              Equipment DELETEs its network access 
              (<xref target="DELETE_request"/>). After a DELETE, the 
              CAPPORT API Server MAY generate a new session token if 
              the User Equipment makes a new request. 
            </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>
            and <xref target="json_session_token_object">session_token</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>
          <t>
            Subsequent CAPPORT requests will contain data to satisfy
            conditions to access protected networks.
          </t>

          <section title="Satisfaction Details Object"
                   anchor="json_satisfaction_details">
            <t>
              The satisfaction_details object details proof that the
              User Equipment has satisfied one of the conditions of
              access to a protected network.
            </t>
            <t>
            <figure>
              <artwork>
    $satisfaction_details = { // : any + }
              </artwork>
            </figure>
            </t>
            <t>
              Like
              the <xref target="json_requirement_details">requirement
              details</xref> in the CAPPORT API Server Response, the
              list of keys and values for this object will depend on
              the value of the 'type' key in
              the <xref target="json_condition_object">enclosing
              condition</xref>.  <xref target="condition_dictionary"/>
              contains conditions and their Satisfaction Details
              Objects.
            </t>
          </section>
        </section>
      
        <section title="CAPPORT API Server Response">
          <section title="Requirement Details Object" anchor="json_requirement_details">
            <t>
              The requirement_details object details the requirements
              of the Captive Portal Enforcement for access to a
              protected network.
            </t>
            <t>
              <figure>
                <artwork>
    $requirement_details = { // : any + }
                </artwork>
              </figure>
            </t>
            <t>
              Like
              the <xref target="json_satisfaction_details">satisfaction
              details</xref>, of the User Equipment Request, the list
              of keys and values for this object will depend on the
              value of the 'type' key in
              the <xref target="json_condition_object">enclosing
              condition</xref>.  <xref target="condition_dictionary"/>
              contains conditions and their Requirements Details
              Objects.
            </t>
          </section>
          
          
          <section title="Network State Object" anchor="json_network_state">
            <t>
              The network_state object details the current state of
              the User Equipment's 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 title="Network Access Conditions" anchor="condition_dictionary">
      <t>
        Captive Portal systems will have many conditions for access 
        to their protected networks. The conditions object is open 
        for use in expressing different conditions. Each condition 
        MUST define a "type" string, its requirement_details, and 
        its satisfaction_details. 
      </t>
      <section title="Terms and Conditions">
        <t>
          One common use of a Captive Portal is for the User to accept
          some terms and conditions for the network access.  This
          network access condition will communicate the terms and
          conditions to the User Equipment, and communicate their
          acceptance back to the CAPPORT API Server.
        </t>
        <t>
          For this network access condition, the condition object's
          'type' value MUST be "t&amp;c"
        </t>
        <t>
          This condition is satisfied by presenting an MD5 sum of 
          the terms and conditions document referenced by the 
          requirements. This has the property that the MD5 sum will 
          not change unless the terms and conditions document 
          itself changes. User Equipment MAY cache values and 
          submit a cached value for the MD5 sum preemptively 
          without retrieving the terms and conditions document. 
        </t>
        
        <section title="Requirements" anchor="json_t-n-c_requirements">
          <t>
            <figure>
              <artwork>
    $requirement_details = {
      "text" : string ?,
      "html" : string ?
    }
              </artwork>
            </figure>
          </t>
          <t>
            The requirement_details object for the Terms and
            Conditions network access condition MUST include the
            "text" key, whose value is a URL referencing the plaintext
            terms and conditions which govern the use of the protected
            network.
          </t>
          <t>
            The requirement_details object for the Terms and
            Conditions network access condition MUST include the
            "html" key, whose value is a URL referencing the
            HTML-fomatted terms and conditions which govern the use of
            the protected network.
          </t>
        </section>
        
        <section title="Satisfaction">
          <t>
            <figure>
              <artwork>
    $satisfaction_details = {
      "text" : string ?,
      "html" : string ?
    }
              </artwork>
            </figure>
          </t>
          <t>
            The satisfaction_details object for the Terms and
            Conditions network access condition MUST include one of
            "text" or "html" as a key.  The satisfaction_details MAY
            include both.</t>
          <t>
            The "text" key of the satisfaction_details object has a
            string value that is an MD5 sum of the document referred
            to by the URL provided in the
            <xref target="json_t-n-c_requirements">Requirement
            Details</xref> "text" key's value.
          </t>
          <t>
            The "html" key of the satisfaction_details object has a 
            string value that is an MD5 sum of the document referred 
            to by the URL provided in the <xref 
            target="json_t-n-c_requirements">Requirement 
            Details</xref> "html" key's value. 
          </t>
        </section>
      </section>
      
      <section title="Passcode">
        <t>
          Another common use of a captive portal is to have a user
          enter a passcode to gain access to the protected network.
          The Passcode network access condition will communicate the
          requirement for that passcode to the User Equipment and 
          satisfy the Captive Portal Enforcement that the User
          Equipment has the correct passcode.
        </t>
        
        <t>
          For the Passcode network access condition, the condition
          object's "type" value must be "passcode".
        </t>

        <section title="Requirements">
          <t>
            <figure>
              <artwork>
    $requirement_details = { }
              </artwork>
            </figure>
          </t>
          <t>
            The requirement_details object of the Passcode network
            access condition has no elements.
          </t>
        </section>
        
        <section title="Satisfaction">
          <t>
            <figure>
              <artwork>
    $satisfaction_details = {
      "passcode" : string
    }
              </artwork>
            </figure>
          </t>
          <t>
            The satisfaction_details object of the Passcode network
            access condition MUST include the "passcode" key, whose
            value is a string of the passcode that grants access to
            the protected network.
          </t>
        </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>
