summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Plazas <kekun.plazas@laposte.net>2016-03-29 13:30:27 +0200
committerAdrien Plazas <kekun.plazas@laposte.net>2016-06-02 09:49:49 +0200
commite039b824f93212b87262fc8e7c5cab6bbeaa3ddb (patch)
treefaabdb5bcf35957d233489d9427802700b611ae3
parent69be2af0edd92909c3be5ed76d1f63a25cf34ac8 (diff)
downloadlibsoup-wip/aplazas/hsts.tar.gz
Add SoupHstsEnforcerwip/aplazas/hsts
This is a WIP. Add the SoupSessionFeature SoupHstsEnforcer to allow a session to support HSTS (RFC 6797). This also adds SoupHstsPolicy and an early version of SoupHstsEnforcerDb.
-rw-r--r--docs/specs/README1
-rw-r--r--docs/specs/rfc6797.txt2579
-rw-r--r--libsoup/Makefile.am7
-rw-r--r--libsoup/soup-hsts-enforcer-db.c314
-rw-r--r--libsoup/soup-hsts-enforcer-db.h45
-rw-r--r--libsoup/soup-hsts-enforcer-private.h14
-rw-r--r--libsoup/soup-hsts-enforcer.c602
-rw-r--r--libsoup/soup-hsts-enforcer.h53
-rw-r--r--libsoup/soup-hsts-policy.c479
-rw-r--r--libsoup/soup-hsts-policy.h59
-rw-r--r--libsoup/soup-types.h2
-rw-r--r--libsoup/soup.h3
12 files changed, 4158 insertions, 0 deletions
diff --git a/docs/specs/README b/docs/specs/README
index 0dee62d0..e498a22e 100644
--- a/docs/specs/README
+++ b/docs/specs/README
@@ -11,3 +11,4 @@ rfc2817 - Upgrading to TLS Within HTTP/1.1
rfc2818 - HTTP Over TLS
rfc2965 - HTTP State Management Mechanism (allegedly obsoletes 2109)
rfc3986 - Uniform Resource Identifiers (URI): Generic Syntax
+rfc6797 - HTTP Strict Transport Security (HSTS)
diff --git a/docs/specs/rfc6797.txt b/docs/specs/rfc6797.txt
new file mode 100644
index 00000000..c4e689fb
--- /dev/null
+++ b/docs/specs/rfc6797.txt
@@ -0,0 +1,2579 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF) J. Hodges
+Request for Comments: 6797 PayPal
+Category: Standards Track C. Jackson
+ISSN: 2070-1721 Carnegie Mellon University
+ A. Barth
+ Google, Inc.
+ November 2012
+
+
+ HTTP Strict Transport Security (HSTS)
+
+Abstract
+
+ This specification defines a mechanism enabling web sites to declare
+ themselves accessible only via secure connections and/or for users to
+ be able to direct their user agent(s) to interact with given sites
+ only over secure connections. This overall policy is referred to as
+ HTTP Strict Transport Security (HSTS). The policy is declared by web
+ sites via the Strict-Transport-Security HTTP response header field
+ and/or by other means, such as user agent configuration, for example.
+
+Status of This Memo
+
+ This is an Internet Standards Track document.
+
+ This document is a product of the Internet Engineering Task Force
+ (IETF). It represents the consensus of the IETF community. It has
+ received public review and has been approved for publication by the
+ Internet Engineering Steering Group (IESG). Further information on
+ Internet Standards is available in Section 2 of RFC 5741.
+
+ Information about the current status of this document, any errata,
+ and how to provide feedback on it may be obtained at
+ http://www.rfc-editor.org/info/rfc6797.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 1]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+Copyright Notice
+
+ 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.
+
+Table of Contents
+
+ 1. Introduction ....................................................4
+ 1.1. Organization of This Specification .........................6
+ 1.2. Document Conventions .......................................6
+ 2. Overview ........................................................6
+ 2.1. Use Cases ..................................................6
+ 2.2. HTTP Strict Transport Security Policy Effects ..............6
+ 2.3. Threat Model ...............................................6
+ 2.3.1. Threats Addressed ...................................7
+ 2.3.1.1. Passive Network Attackers ..................7
+ 2.3.1.2. Active Network Attackers ...................7
+ 2.3.1.3. Web Site Development and Deployment Bugs ...8
+ 2.3.2. Threats Not Addressed ...............................8
+ 2.3.2.1. Phishing ...................................8
+ 2.3.2.2. Malware and Browser Vulnerabilities ........8
+ 2.4. Requirements ...............................................9
+ 2.4.1. Overall Requirement .................................9
+ 2.4.1.1. Detailed Core Requirements .................9
+ 2.4.1.2. Detailed Ancillary Requirements ...........10
+ 3. Conformance Criteria ...........................................10
+ 4. Terminology ....................................................11
+ 5. HSTS Mechanism Overview ........................................13
+ 5.1. HSTS Host Declaration .....................................13
+ 5.2. HSTS Policy ...............................................13
+ 5.3. HSTS Policy Storage and Maintenance by User Agents ........14
+ 5.4. User Agent HSTS Policy Enforcement ........................14
+ 6. Syntax .........................................................14
+ 6.1. Strict-Transport-Security HTTP Response Header Field ......15
+ 6.1.1. The max-age Directive ..............................16
+ 6.1.2. The includeSubDomains Directive ....................16
+ 6.2. Examples ..................................................16
+
+
+
+
+Hodges, et al. Standards Track [Page 2]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ 7. Server Processing Model ........................................17
+ 7.1. HTTP-over-Secure-Transport Request Type ...................17
+ 7.2. HTTP Request Type .........................................18
+ 8. User Agent Processing Model ....................................18
+ 8.1. Strict-Transport-Security Response Header Field
+ Processing ................................................19
+ 8.1.1. Noting an HSTS Host - Storage Model ................20
+ 8.2. Known HSTS Host Domain Name Matching ......................20
+ 8.3. URI Loading and Port Mapping ..............................21
+ 8.4. Errors in Secure Transport Establishment ..................22
+ 8.5. HTTP-Equiv <Meta> Element Attribute .......................22
+ 8.6. Missing Strict-Transport-Security Response Header Field ...23
+ 9. Constructing an Effective Request URI ..........................23
+ 9.1. ERU Fundamental Definitions ...............................23
+ 9.2. Determining the Effective Request URI .....................24
+ 9.2.1. Effective Request URI Examples .....................24
+ 10. Domain Name IDNA-Canonicalization .............................25
+ 11. Server Implementation and Deployment Advice ...................26
+ 11.1. Non-Conformant User Agent Considerations .................26
+ 11.2. HSTS Policy Expiration Time Considerations ...............26
+ 11.3. Using HSTS in Conjunction with Self-Signed Public-Key
+ Certificates .............................................27
+ 11.4. Implications of includeSubDomains ........................28
+ 11.4.1. Considerations for Offering Unsecured HTTP
+ Services at Alternate Ports or Subdomains of an
+ HSTS Host ........................................28
+ 11.4.2. Considerations for Offering Web Applications at
+ Subdomains of an HSTS Host .......................29
+ 12. User Agent Implementation Advice ..............................30
+ 12.1. No User Recourse .........................................30
+ 12.2. User-Declared HSTS Policy ................................30
+ 12.3. HSTS Pre-Loaded List .....................................31
+ 12.4. Disallow Mixed Security Context Loads ....................31
+ 12.5. HSTS Policy Deletion .....................................31
+ 13. Internationalized Domain Names for Applications (IDNA):
+ Dependency and Migration ......................................32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 3]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ 14. Security Considerations .......................................32
+ 14.1. Underlying Secure Transport Considerations ...............32
+ 14.2. Non-Conformant User Agent Implications ...................33
+ 14.3. Ramifications of HSTS Policy Establishment Only over
+ Error-Free Secure Transport ..............................33
+ 14.4. The Need for includeSubDomains ...........................34
+ 14.5. Denial of Service ........................................35
+ 14.6. Bootstrap MITM Vulnerability .............................36
+ 14.7. Network Time Attacks .....................................37
+ 14.8. Bogus Root CA Certificate Phish plus DNS Cache
+ Poisoning Attack .........................................37
+ 14.9. Creative Manipulation of HSTS Policy Store ...............37
+ 14.10. Internationalized Domain Names ..........................38
+ 15. IANA Considerations ...........................................39
+ 16. References ....................................................39
+ 16.1. Normative References .....................................39
+ 16.2. Informative References ...................................40
+ Appendix A. Design Decision Notes .................................44
+ Appendix B. Differences between HSTS Policy and Same-Origin
+ Policy ................................................45
+ Appendix C. Acknowledgments .......................................46
+
+1. Introduction
+
+ HTTP [RFC2616] may be used over various transports, typically the
+ Transmission Control Protocol (TCP). However, TCP does not provide
+ channel integrity protection, confidentiality, or secure host
+ identification. Thus, the Secure Sockets Layer (SSL) protocol
+ [RFC6101] and its successor, Transport Layer Security (TLS) [RFC5246]
+ were developed in order to provide channel-oriented security and are
+ typically layered between application protocols and TCP. [RFC2818]
+ specifies how HTTP is layered onto TLS and defines the Uniform
+ Resource Identifier (URI) scheme of "https" (in practice, however,
+ HTTP user agents (UAs) typically use either TLS or SSL3, depending
+ upon a combination of negotiation with the server and user
+ preferences).
+
+ UAs employ various local security policies with respect to the
+ characteristics of their interactions with web resources, depending
+ on (in part) whether they are communicating with a given web
+ resource's host using HTTP or HTTP-over-Secure-Transport. For
+ example, cookies ([RFC6265]) may be flagged as Secure. UAs are to
+ send such Secure cookies to their addressed host only over a secure
+ transport. This is in contrast to non-Secure cookies, which are
+ returned to the host regardless of transport (although subject to
+ other rules).
+
+
+
+
+
+Hodges, et al. Standards Track [Page 4]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ UAs typically announce to their users any issues with secure
+ connection establishment, such as being unable to validate a TLS
+ server certificate trust chain, or if a TLS server certificate is
+ expired, or if a TLS host's domain name appears incorrectly in the
+ TLS server certificate (see Section 3.1 of [RFC2818]). Often, UAs
+ enable users to elect to continue to interact with a web resource's
+ host in the face of such issues. This behavior is sometimes referred
+ to as "click(ing) through" security [GoodDhamijaEtAl05]
+ [SunshineEgelmanEtAl09]; thus, it can be described as "click-through
+ insecurity".
+
+ A key vulnerability enabled by click-through insecurity is the
+ leaking of any cookies the web resource may be using to manage a
+ user's session. The threat here is that an attacker could obtain the
+ cookies and then interact with the legitimate web resource while
+ impersonating the user.
+
+ Jackson and Barth proposed an approach, in [ForceHTTPS], to enable
+ web resources to declare that any interactions by UAs with the web
+ resource must be conducted securely and that any issues with
+ establishing a secure transport session are to be treated as fatal
+ and without direct user recourse. The aim is to prevent click-
+ through insecurity and address other potential threats.
+
+ This specification embodies and refines the approach proposed in
+ [ForceHTTPS]. For example, rather than using a cookie to convey
+ policy from a web resource's host to a UA, it defines an HTTP
+ response header field for this purpose. Additionally, a web
+ resource's host may declare its policy to apply to the entire domain
+ name subtree rooted at its host name. This enables HTTP Strict
+ Transport Security (HSTS) to protect so-called "domain cookies",
+ which are applied to all subdomains of a given web resource's host
+ name.
+
+ This specification also incorporates notions from [JacksonBarth2008]
+ in that policy is applied on an "entire-host" basis: it applies to
+ HTTP (only) over any TCP port of the issuing host.
+
+ Note that the policy defined by this specification is distinctly
+ different than the "same-origin policy" defined in "The Web Origin
+ Concept" [RFC6454]. These differences are summarized in Appendix B.
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 5]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+1.1. Organization of This Specification
+
+ This specification begins with an overview of the use cases, policy
+ effects, threat models, and requirements for HSTS (in Section 2).
+ Then, Section 3 defines conformance requirements. Section 4 defines
+ terminology relevant to this document. The HSTS mechanism itself is
+ formally specified in Sections 5 through 15.
+
+1.2. Document Conventions
+
+ NOTE: This is a note to the reader. These are points that should be
+ expressly kept in mind and/or considered.
+
+2. Overview
+
+ This section discusses the use cases, summarizes the HSTS Policy, and
+ continues with a discussion of the threat model, non-addressed
+ threats, and derived requirements.
+
+2.1. Use Cases
+
+ The high-level use case is a combination of:
+
+ o Web browser user wishes to interact with various web sites (some
+ arbitrary, some known) in a secure fashion.
+
+ o Web site deployer wishes to offer their site in an explicitly
+ secure fashion for their own, as well as their users', benefit.
+
+2.2. HTTP Strict Transport Security Policy Effects
+
+ The effects of the HSTS Policy, as applied by a conformant UA in
+ interactions with a web resource host wielding such policy (known as
+ an HSTS Host), are summarized as follows:
+
+ 1. UAs transform insecure URI references to an HSTS Host into secure
+ URI references before dereferencing them.
+
+ 2. The UA terminates any secure transport connection attempts upon
+ any and all secure transport errors or warnings.
+
+2.3. Threat Model
+
+ HSTS is concerned with three threat classes: passive network
+ attackers, active network attackers, and imperfect web developers.
+ However, it is explicitly not a remedy for two other classes of
+ threats: phishing and malware. Threats that are addressed, as well
+ as threats that are not addressed, are briefly discussed below.
+
+
+
+Hodges, et al. Standards Track [Page 6]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ Readers may wish to refer to Section 2 of [ForceHTTPS] for details as
+ well as relevant citations.
+
+2.3.1. Threats Addressed
+
+2.3.1.1. Passive Network Attackers
+
+ When a user browses the web on a local wireless network (e.g., an
+ 802.11-based wireless local area network) a nearby attacker can
+ possibly eavesdrop on the user's unencrypted Internet Protocol-based
+ connections, such as HTTP, regardless of whether or not the local
+ wireless network itself is secured [BeckTews09]. Freely available
+ wireless sniffing toolkits (e.g., [Aircrack-ng]) enable such passive
+ eavesdropping attacks, even if the local wireless network is
+ operating in a secure fashion. A passive network attacker using such
+ tools can steal session identifiers/cookies and hijack the user's web
+ session(s) by obtaining cookies containing authentication credentials
+ [ForceHTTPS]. For example, there exist widely available tools, such
+ as Firesheep (a web browser extension) [Firesheep], that enable their
+ wielder to obtain other local users' session cookies for various web
+ applications.
+
+ To mitigate such threats, some web sites support, but usually do not
+ force, access using end-to-end secure transport -- e.g., signaled
+ through URIs constructed with the "https" scheme [RFC2818]. This can
+ lead users to believe that accessing such services using secure
+ transport protects them from passive network attackers.
+ Unfortunately, this is often not the case in real-world deployments,
+ as session identifiers are often stored in non-Secure cookies to
+ permit interoperability with versions of the service offered over
+ insecure transport ("Secure cookies" are those cookies containing the
+ "Secure" attribute [RFC6265]). For example, if the session
+ identifier for a web site (an email service, say) is stored in a
+ non-Secure cookie, it permits an attacker to hijack the user's
+ session if the user's UA makes a single insecure HTTP request to the
+ site.
+
+2.3.1.2. Active Network Attackers
+
+ A determined attacker can mount an active attack, either by
+ impersonating a user's DNS server or, in a wireless network, by
+ spoofing network frames or offering a similarly named evil twin
+ access point. If the user is behind a wireless home router, an
+ attacker can attempt to reconfigure the router using default
+ passwords and other vulnerabilities. Some sites, such as banks, rely
+ on end-to-end secure transport to protect themselves and their users
+ from such active attackers. Unfortunately, browsers allow their
+ users to easily opt out of these protections in order to be usable
+
+
+
+Hodges, et al. Standards Track [Page 7]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ for sites that incorrectly deploy secure transport, for example by
+ generating and self-signing their own certificates (without also
+ distributing their certification authority (CA) certificate to their
+ users' browsers).
+
+2.3.1.3. Web Site Development and Deployment Bugs
+
+ The security of an otherwise uniformly secure site (i.e., all of its
+ content is materialized via "https" URIs) can be compromised
+ completely by an active attacker exploiting a simple mistake, such as
+ the loading of a cascading style sheet or a SWF (Shockwave Flash)
+ movie over an insecure connection (both cascading style sheets and
+ SWF movies can script the embedding page, to the surprise of many web
+ developers, plus some browsers do not issue so-called "mixed content
+ warnings" when SWF files are embedded via insecure connections).
+ Even if the site's developers carefully scrutinize their login page
+ for "mixed content", a single insecure embedding anywhere on the
+ overall site compromises the security of their login page because an
+ attacker can script (i.e., control) the login page by injecting code
+ (e.g., a script) into another, insecurely loaded, site page.
+
+ NOTE: "Mixed content" as used above (see also Section 5.3 in
+ [W3C.REC-wsc-ui-20100812]) refers to the notion termed "mixed
+ security context" in this specification and should not be
+ confused with the same "mixed content" term used in the
+ context of markup languages such as XML and HTML.
+
+2.3.2. Threats Not Addressed
+
+2.3.2.1. Phishing
+
+ Phishing attacks occur when an attacker solicits authentication
+ credentials from the user by hosting a fake site located on a
+ different domain than the real site, perhaps driving traffic to the
+ fake site by sending a link in an email message. Phishing attacks
+ can be very effective because users find it difficult to distinguish
+ the real site from a fake site. HSTS is not a defense against
+ phishing per se; rather, it complements many existing phishing
+ defenses by instructing the browser to protect session integrity and
+ long-lived authentication tokens [ForceHTTPS].
+
+2.3.2.2. Malware and Browser Vulnerabilities
+
+ Because HSTS is implemented as a browser security mechanism, it
+ relies on the trustworthiness of the user's system to protect the
+ session. Malicious code executing on the user's system can
+ compromise a browser session, regardless of whether HSTS is used.
+
+
+
+
+Hodges, et al. Standards Track [Page 8]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+2.4. Requirements
+
+ This section identifies and enumerates various requirements derived
+ from the use cases and the threats discussed above and also lists the
+ detailed core requirements that HTTP Strict Transport Security
+ addresses, as well as ancillary requirements that are not directly
+ addressed.
+
+2.4.1. Overall Requirement
+
+ o Minimize, for web browser users and web site deployers, the risks
+ that are derived from passive and active network attackers, web
+ site development and deployment bugs, and insecure user actions.
+
+2.4.1.1. Detailed Core Requirements
+
+ These core requirements are derived from the overall requirement and
+ are addressed by this specification.
+
+ 1. Web sites need to be able to declare to UAs that they should be
+ accessed using a strict security policy.
+
+ 2. Web sites need to be able to instruct UAs that contact them
+ insecurely to do so securely.
+
+ 3. UAs need to retain persistent data about web sites that signal
+ strict security policy enablement, for time spans declared by the
+ web sites. Additionally, UAs need to cache the "freshest" strict
+ security policy information, in order to allow web sites to
+ update the information.
+
+ 4. UAs need to rewrite all insecure UA "http" URI loads to use the
+ "https" secure scheme for those web sites for which secure policy
+ is enabled.
+
+ 5. Web site administrators need to be able to signal strict security
+ policy application to subdomains of higher-level domains for
+ which strict security policy is enabled, and UAs need to enforce
+ such policy.
+
+ For example, both example.com and foo.example.com could set
+ policy for bar.foo.example.com.
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 9]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ 6. UAs need to disallow security policy application to peer domains,
+ and/or higher-level domains, by domains for which strict security
+ policy is enabled.
+
+ For example, neither bar.foo.example.com nor foo.example.com can
+ set policy for example.com, nor can bar.foo.example.com set
+ policy for foo.example.com. Also, foo.example.com cannot set
+ policy for sibling.example.com.
+
+ 7. UAs need to prevent users from "clicking through" security
+ warnings. Halting connection attempts in the face of secure
+ transport exceptions is acceptable. See also Section 12.1 ("No
+ User Recourse").
+
+ NOTE: A means for uniformly securely meeting the first core
+ requirement above is not specifically addressed by this
+ specification (see Section 14.6 ("Bootstrap MITM
+ Vulnerability")). It may be addressed by a future revision of
+ this specification or some other specification. Note also
+ that there are means by which UA implementations may more
+ fully meet the first core requirement; see Section 12 ("User
+ Agent Implementation Advice").
+
+2.4.1.2. Detailed Ancillary Requirements
+
+ These ancillary requirements are also derived from the overall
+ requirement. They are not normatively addressed in this
+ specification but could be met by UA implementations at their
+ implementor's discretion, although meeting these requirements may be
+ complex.
+
+ 1. Disallow "mixed security context" loads (see Section 2.3.1.3).
+
+ 2. Facilitate user declaration of web sites for which strict
+ security policy is enabled, regardless of whether the sites
+ signal HSTS Policy.
+
+3. Conformance Criteria
+
+ This specification is written for hosts and user agents.
+
+ A conformant host is one that implements all the requirements listed
+ in this specification that are applicable to hosts.
+
+ A conformant user agent is one that implements all the requirements
+ listed in this specification that are applicable to user agents.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 10]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ 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].
+
+4. Terminology
+
+ Terminology is defined in this section.
+
+ ASCII case-insensitive comparison:
+
+ means comparing two strings exactly, codepoint for codepoint,
+ except that the characters in the range U+0041 .. U+005A (i.e.,
+ LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) and the
+ corresponding characters in the range U+0061 .. U+007A (i.e.,
+ LATIN SMALL LETTER A to LATIN SMALL LETTER Z) are considered to
+ also match. See [Unicode] for details.
+
+ codepoint:
+
+ is a colloquial contraction of Code Point, which is any value in
+ the Unicode codespace; that is, the range of integers from 0 to
+ 10FFFF(hex) [Unicode].
+
+ domain name:
+
+ is also referred to as "DNS name" and is defined in [RFC1035] to
+ be represented outside of the DNS protocol itself (and
+ implementations thereof) as a series of labels separated by dots,
+ e.g., "example.com" or "yet.another.example.org". In the context
+ of this specification, domain names appear in that portion of a
+ URI satisfying the reg-name production in "Appendix A. Collected
+ ABNF for URI" in [RFC3986], and the host component from the Host
+ HTTP header field production in Section 14.23 of [RFC2616].
+
+ NOTE: The domain names appearing in actual URI instances and
+ matching the aforementioned production components may or
+ may not be a fully qualified domain name.
+
+ domain name label:
+
+ is that portion of a domain name appearing "between the dots",
+ i.e., consider "foo.example.com": "foo", "example", and "com" are
+ all domain name labels.
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 11]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ Effective Request URI:
+
+ is a URI, identifying the target resource, that can be inferred by
+ an HTTP host for any given HTTP request it receives. Such
+ inference is necessary because HTTP requests often do not contain
+ a complete "absolute" URI identifying the target resource. See
+ Section 9 ("Constructing an Effective Request URI").
+
+ HTTP Strict Transport Security:
+
+ is the overall name for the combined UA- and server-side security
+ policy defined by this specification.
+
+ HTTP Strict Transport Security Host:
+
+ is a conformant host implementing the HTTP server aspects of the
+ HSTS Policy. This means that an HSTS Host returns the
+ "Strict-Transport-Security" HTTP response header field in its HTTP
+ response messages sent over secure transport.
+
+ HTTP Strict Transport Security Policy:
+
+ is the name of the combined overall UA- and server-side facets of
+ the behavior defined in this specification.
+
+ HSTS:
+
+ See HTTP Strict Transport Security.
+
+ HSTS Host:
+
+ See HTTP Strict Transport Security Host.
+
+ HSTS Policy:
+
+ See HTTP Strict Transport Security Policy.
+
+ Known HSTS Host:
+
+ is an HSTS Host for which the UA has an HSTS Policy in effect;
+ i.e., the UA has noted this host as a Known HSTS Host. See
+ Section 8.1.1 ("Noting an HSTS Host - Storage Model") for
+ particulars.
+
+ Local policy:
+
+ comprises policy rules that deployers specify and that are often
+ manifested as configuration settings.
+
+
+
+Hodges, et al. Standards Track [Page 12]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ MITM:
+
+ is an acronym for "man in the middle". See "man-in-the-middle
+ attack" in [RFC4949].
+
+ Request URI:
+
+ is the URI used to cause a UA to issue an HTTP request message.
+ See also "Effective Request URI".
+
+ UA:
+
+ is an acronym for "user agent". For the purposes of this
+ specification, a UA is an HTTP client application typically
+ actively manipulated by a user [RFC2616].
+
+ unknown HSTS Host:
+
+ is an HSTS Host that the user agent has not noted.
+
+5. HSTS Mechanism Overview
+
+ This section provides an overview of the mechanism by which an HSTS
+ Host conveys its HSTS Policy to UAs and how UAs process the HSTS
+ Policies received from HSTS Hosts. The mechanism details are
+ specified in Sections 6 through 15.
+
+5.1. HSTS Host Declaration
+
+ An HTTP host declares itself an HSTS Host by issuing to UAs an HSTS
+ Policy, which is represented by and conveyed via the
+ Strict-Transport-Security HTTP response header field over secure
+ transport (e.g., TLS). Upon error-free receipt and processing of
+ this header by a conformant UA, the UA regards the host as a Known
+ HSTS Host.
+
+5.2. HSTS Policy
+
+ An HSTS Policy directs UAs to communicate with a Known HSTS Host only
+ over secure transport and specifies policy retention time duration.
+
+ HSTS Policy explicitly overrides the UA processing of URI references,
+ user input (e.g., via the "location bar"), or other information that,
+ in the absence of HSTS Policy, might otherwise cause UAs to
+ communicate insecurely with the Known HSTS Host.
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 13]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ An HSTS Policy may contain an optional directive -- includeSubDomains
+ -- specifying that this HSTS Policy also applies to any hosts whose
+ domain names are subdomains of the Known HSTS Host's domain name.
+
+5.3. HSTS Policy Storage and Maintenance by User Agents
+
+ UAs store and index HSTS Policies based strictly upon the domain
+ names of the issuing HSTS Hosts.
+
+ This means that UAs will maintain the HSTS Policy of any given HSTS
+ Host separately from any HSTS Policies issued by any other HSTS Hosts
+ whose domain names are superdomains or subdomains of the given HSTS
+ Host's domain name. Only the given HSTS Host can update or can cause
+ deletion of its issued HSTS Policy. It accomplishes this by sending
+ Strict-Transport-Security HTTP response header fields to UAs with new
+ values for policy time duration and subdomain applicability. Thus,
+ UAs cache the "freshest" HSTS Policy information on behalf of an HSTS
+ Host. Specifying a zero time duration signals the UA to delete the
+ HSTS Policy (including any asserted includeSubDomains directive) for
+ that HSTS Host. See Section 8.1 ("Strict-Transport-Security Response
+ Header Field Processing") for details. Additionally, Section 6.2
+ presents examples of Strict-Transport-Security HTTP response header
+ fields.
+
+5.4. User Agent HSTS Policy Enforcement
+
+ When establishing an HTTP connection to a given host, however
+ instigated, the UA examines its cache of Known HSTS Hosts to see if
+ there are any with domain names that are superdomains of the given
+ host's domain name. If any are found, and of those if any have the
+ includeSubDomains directive asserted, then HSTS Policy applies to the
+ given host. Otherwise, HSTS Policy applies to the given host only if
+ the given host is itself known to the UA as an HSTS Host. See
+ Section 8.3 ("URI Loading and Port Mapping") for details.
+
+6. Syntax
+
+ This section defines the syntax of the Strict-Transport-Security HTTP
+ response header field and its directives, and presents some examples.
+
+ Section 7 ("Server Processing Model") then details how hosts employ
+ this header field to declare their HSTS Policy, and Section 8 ("User
+ Agent Processing Model") details how user agents process the header
+ field and apply the HSTS Policy.
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 14]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+6.1. Strict-Transport-Security HTTP Response Header Field
+
+ The Strict-Transport-Security HTTP response header field (STS header
+ field) indicates to a UA that it MUST enforce the HSTS Policy in
+ regards to the host emitting the response message containing this
+ header field.
+
+ The ABNF (Augmented Backus-Naur Form) syntax for the STS header field
+ is given below. It is based on the Generic Grammar defined in
+ Section 2 of [RFC2616] (which includes a notion of "implied linear
+ whitespace", also known as "implied *LWS").
+
+ Strict-Transport-Security = "Strict-Transport-Security" ":"
+ [ directive ] *( ";" [ directive ] )
+
+ directive = directive-name [ "=" directive-value ]
+ directive-name = token
+ directive-value = token | quoted-string
+
+ where:
+
+ token = <token, defined in [RFC2616], Section 2.2>
+ quoted-string = <quoted-string, defined in [RFC2616], Section 2.2>
+
+ The two directives defined in this specification are described below.
+ The overall requirements for directives are:
+
+ 1. The order of appearance of directives is not significant.
+
+ 2. All directives MUST appear only once in an STS header field.
+ Directives are either optional or required, as stipulated in
+ their definitions.
+
+ 3. Directive names are case-insensitive.
+
+ 4. UAs MUST ignore any STS header field containing directives, or
+ other header field value data, that does not conform to the
+ syntax defined in this specification.
+
+ 5. If an STS header field contains directive(s) not recognized by
+ the UA, the UA MUST ignore the unrecognized directives, and if
+ the STS header field otherwise satisfies the above requirements
+ (1 through 4), the UA MUST process the recognized directives.
+
+ Additional directives extending the semantic functionality of the STS
+ header field can be defined in other specifications, with a registry
+ (having an IANA policy definition of IETF Review [RFC5226]) defined
+ for them at such time.
+
+
+
+Hodges, et al. Standards Track [Page 15]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ NOTE: Such future directives will be ignored by UAs implementing
+ only this specification, as well as by generally
+ non-conforming UAs. See Section 14.2 ("Non-Conformant User
+ Agent Implications") for further discussion.
+
+6.1.1. The max-age Directive
+
+ The REQUIRED "max-age" directive specifies the number of seconds,
+ after the reception of the STS header field, during which the UA
+ regards the host (from whom the message was received) as a Known HSTS
+ Host. See also Section 8.1.1 ("Noting an HSTS Host - Storage
+ Model"). The delta-seconds production is specified in [RFC2616].
+
+ The syntax of the max-age directive's REQUIRED value (after
+ quoted-string unescaping, if necessary) is defined as:
+
+ max-age-value = delta-seconds
+
+ delta-seconds = <1*DIGIT, defined in [RFC2616], Section 3.3.2>
+
+ NOTE: A max-age value of zero (i.e., "max-age=0") signals the UA to
+ cease regarding the host as a Known HSTS Host, including the
+ includeSubDomains directive (if asserted for that HSTS Host).
+ See also Section 8.1 ("Strict-Transport-Security Response
+ Header Field Processing").
+
+6.1.2. The includeSubDomains Directive
+
+ The OPTIONAL "includeSubDomains" directive is a valueless directive
+ which, if present (i.e., it is "asserted"), signals the UA that the
+ HSTS Policy applies to this HSTS Host as well as any subdomains of
+ the host's domain name.
+
+6.2. Examples
+
+ The HSTS header field below stipulates that the HSTS Policy is to
+ remain in effect for one year (there are approximately 31536000
+ seconds in a year), and the policy applies only to the domain of the
+ HSTS Host issuing it:
+
+ Strict-Transport-Security: max-age=31536000
+
+ The HSTS header field below stipulates that the HSTS Policy is to
+ remain in effect for approximately six months and that the policy
+ applies to the domain of the issuing HSTS Host and all of its
+ subdomains:
+
+ Strict-Transport-Security: max-age=15768000 ; includeSubDomains
+
+
+
+Hodges, et al. Standards Track [Page 16]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ The max-age directive value can optionally be quoted:
+
+ Strict-Transport-Security: max-age="31536000"
+
+ The HSTS header field below indicates that the UA must delete the
+ entire HSTS Policy associated with the HSTS Host that sent the header
+ field:
+
+ Strict-Transport-Security: max-age=0
+
+ The HSTS header field below has exactly the same effect as the one
+ immediately above because the includeSubDomains directive's presence
+ in the HSTS header field is ignored when max-age is zero:
+
+ Strict-Transport-Security: max-age=0; includeSubDomains
+
+7. Server Processing Model
+
+ This section describes the processing model that HSTS Hosts
+ implement. The model comprises two facets: the first being the
+ processing rules for HTTP request messages received over a secure
+ transport (TLS [RFC5246] or SSL [RFC6101]; see also Section 14.1
+ ("Underlying Secure Transport Considerations")), and the second being
+ the processing rules for HTTP request messages received over
+ non-secure transports, such as TCP.
+
+7.1. HTTP-over-Secure-Transport Request Type
+
+ When replying to an HTTP request that was conveyed over a secure
+ transport, an HSTS Host SHOULD include in its response message an STS
+ header field that MUST satisfy the grammar specified above in
+ Section 6.1 ("Strict-Transport-Security HTTP Response Header Field").
+ If an STS header field is included, the HSTS Host MUST include only
+ one such header field.
+
+ Establishing a given host as a Known HSTS Host, in the context of a
+ given UA, MAY be accomplished over HTTP, which is in turn running
+ over secure transport, by correctly returning (per this
+ specification) at least one valid STS header field to the UA. Other
+ mechanisms, such as a client-side pre-loaded Known HSTS Host list,
+ MAY also be used; e.g., see Section 12 ("User Agent Implementation
+ Advice").
+
+ NOTE: Including the STS header field is stipulated as a "SHOULD" in
+ order to accommodate various server- and network-side caches
+ and load-balancing configurations where it may be difficult to
+ uniformly emit STS header fields on behalf of a given HSTS
+ Host.
+
+
+
+Hodges, et al. Standards Track [Page 17]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+7.2. HTTP Request Type
+
+ If an HSTS Host receives an HTTP request message over a non-secure
+ transport, it SHOULD send an HTTP response message containing a
+ status code indicating a permanent redirect, such as status code 301
+ (Section 10.3.2 of [RFC2616]), and a Location header field value
+ containing either the HTTP request's original Effective Request URI
+ (see Section 9 ("Constructing an Effective Request URI")) altered as
+ necessary to have a URI scheme of "https", or a URI generated
+ according to local policy with a URI scheme of "https".
+
+ NOTE: The above behavior is a "SHOULD" rather than a "MUST" due to:
+
+ * Risks in server-side non-secure-to-secure redirects
+ [OWASP-TLSGuide].
+
+ * Site deployment characteristics. For example, a site that
+ incorporates third-party components may not behave correctly
+ when doing server-side non-secure-to-secure redirects in the
+ case of being accessed over non-secure transport but does
+ behave correctly when accessed uniformly over secure transport.
+ The latter is the case given an HSTS-capable UA that has
+ already noted the site as a Known HSTS Host (by whatever means,
+ e.g., prior interaction or UA configuration).
+
+ An HSTS Host MUST NOT include the STS header field in HTTP responses
+ conveyed over non-secure transport.
+
+8. User Agent Processing Model
+
+ This section describes the HTTP Strict Transport Security processing
+ model for UAs. There are several facets to the model, enumerated by
+ the following subsections.
+
+ This processing model assumes that the UA implements IDNA2008
+ [RFC5890], or possibly IDNA2003 [RFC3490], as noted in Section 13
+ ("Internationalized Domain Names for Applications (IDNA): Dependency
+ and Migration"). It also assumes that all domain names manipulated
+ in this specification's context are already IDNA-canonicalized as
+ outlined in Section 10 ("Domain Name IDNA-Canonicalization") prior to
+ the processing specified in this section.
+
+ NOTE: [RFC3490] is referenced due to its ongoing relevance to
+ actual deployments for the foreseeable future.
+
+ The above assumptions mean that this processing model also
+ specifically assumes that appropriate IDNA and Unicode validations
+ and character list testing have occurred on the domain names, in
+
+
+
+Hodges, et al. Standards Track [Page 18]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ conjunction with their IDNA-canonicalization, prior to the processing
+ specified in this section. See the IDNA-specific security
+ considerations in Section 14.10 ("Internationalized Domain Names")
+ for rationale and further details.
+
+8.1. Strict-Transport-Security Response Header Field Processing
+
+ If an HTTP response, received over a secure transport, includes an
+ STS header field, conforming to the grammar specified in Section 6.1
+ ("Strict-Transport-Security HTTP Response Header Field"), and there
+ are no underlying secure transport errors or warnings (see
+ Section 8.4), the UA MUST either:
+
+ o Note the host as a Known HSTS Host if it is not already so noted
+ (see Section 8.1.1 ("Noting an HSTS Host - Storage Model")),
+
+ or
+
+ o Update the UA's cached information for the Known HSTS Host if
+ either or both of the max-age and includeSubDomains header field
+ value tokens are conveying information different than that already
+ maintained by the UA.
+
+ The max-age value is essentially a "time to live" value relative
+ to the reception time of the STS header field.
+
+ If the max-age header field value token has a value of zero, the
+ UA MUST remove its cached HSTS Policy information (including the
+ includeSubDomains directive, if asserted) if the HSTS Host is
+ known, or the UA MUST NOT note this HSTS Host if it is not yet
+ known.
+
+ If a UA receives more than one STS header field in an HTTP
+ response message over secure transport, then the UA MUST process
+ only the first such header field.
+
+ Otherwise:
+
+ o If an HTTP response is received over insecure transport, the UA
+ MUST ignore any present STS header field(s).
+
+ o The UA MUST ignore any STS header fields not conforming to the
+ grammar specified in Section 6.1 ("Strict-Transport-Security HTTP
+ Response Header Field").
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 19]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+8.1.1. Noting an HSTS Host - Storage Model
+
+ If the substring matching the host production from the Request-URI
+ (of the message to which the host responded) syntactically matches
+ the IP-literal or IPv4address productions from Section 3.2.2 of
+ [RFC3986], then the UA MUST NOT note this host as a Known HSTS Host.
+
+ Otherwise, if the substring does not congruently match a Known HSTS
+ Host's domain name, per the matching procedure specified in
+ Section 8.2 ("Known HSTS Host Domain Name Matching"), then the UA
+ MUST note this host as a Known HSTS Host, caching the HSTS Host's
+ domain name and noting along with it the expiry time of this
+ information, as effectively stipulated per the given max-age value,
+ as well as whether the includeSubDomains directive is asserted or
+ not. See also Section 11.2 ("HSTS Policy Expiration Time
+ Considerations").
+
+ The UA MUST NOT modify the expiry time or the includeSubDomains
+ directive of any superdomain matched Known HSTS Host.
+
+ A Known HSTS Host is "expired" if its cache entry has an expiry date
+ in the past. The UA MUST evict all expired Known HSTS Hosts from its
+ cache if, at any time, an expired Known HSTS Host exists in the
+ cache.
+
+8.2. Known HSTS Host Domain Name Matching
+
+ A given domain name may match a Known HSTS Host's domain name in one
+ or both of two fashions: a congruent match, or a superdomain match.
+ Alternatively, there may be no match.
+
+ The steps below determine whether there are any matches, and if so,
+ of which fashion:
+
+ Compare the given domain name with the domain name of each of the
+ UA's unexpired Known HSTS Hosts. For each Known HSTS Host's
+ domain name, the comparison is done with the given domain name
+ label-by-label (comparing only labels) using an ASCII case-
+ insensitive comparison beginning with the rightmost label, and
+ continuing right-to-left. See also Section 2.3.2.4 of [RFC5890].
+
+ * Superdomain Match
+
+ If a label-for-label match between an entire Known HSTS Host's
+ domain name and a right-hand portion of the given domain name
+ is found, then this Known HSTS Host's domain name is a
+ superdomain match for the given domain name. There could be
+ multiple superdomain matches for a given domain name.
+
+
+
+Hodges, et al. Standards Track [Page 20]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ For example:
+
+ Given domain name (DN): qaz.bar.foo.example.com
+
+ Superdomain matched
+ Known HSTS Host DN: bar.foo.example.com
+
+ Superdomain matched
+ Known HSTS Host DN: foo.example.com
+
+
+ * Congruent Match
+
+ If a label-for-label match between a Known HSTS Host's domain
+ name and the given domain name is found -- i.e., there are no
+ further labels to compare -- then the given domain name
+ congruently matches this Known HSTS Host.
+
+ For example:
+
+ Given domain name: foo.example.com
+
+ Congruently matched
+ Known HSTS Host DN: foo.example.com
+
+
+ * Otherwise, if no matches are found, the given domain name does
+ not represent a Known HSTS Host.
+
+8.3. URI Loading and Port Mapping
+
+ Whenever the UA prepares to "load" (also known as "dereference") any
+ "http" URI [RFC3986] (including when following HTTP redirects
+ [RFC2616]), the UA MUST first determine whether a domain name is
+ given in the URI and whether it matches a Known HSTS Host, using
+ these steps:
+
+ 1. Extract from the URI any substring described by the host
+ component of the authority component of the URI.
+
+ 2. If the substring is null, then there is no match with any Known
+ HSTS Host.
+
+ 3. Else, if the substring is non-null and syntactically matches the
+ IP-literal or IPv4address productions from Section 3.2.2 of
+ [RFC3986], then there is no match with any Known HSTS Host.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 21]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ 4. Otherwise, the substring is a given domain name, which MUST be
+ matched against the UA's Known HSTS Hosts using the procedure in
+ Section 8.2 ("Known HSTS Host Domain Name Matching").
+
+ 5. If, when performing domain name matching any superdomain match
+ with an asserted includeSubDomains directive is found, or, if no
+ superdomain matches with asserted includeSubDomains directives
+ are found and a congruent match is found (with or without an
+ asserted includeSubDomains directive), then before proceeding
+ with the load:
+
+ The UA MUST replace the URI scheme with "https" [RFC2818], and
+
+ if the URI contains an explicit port component of "80", then
+ the UA MUST convert the port component to be "443", or
+
+ if the URI contains an explicit port component that is not
+ equal to "80", the port component value MUST be preserved;
+ otherwise,
+
+ if the URI does not contain an explicit port component, the UA
+ MUST NOT add one.
+
+ NOTE: These steps ensure that the HSTS Policy applies to HTTP
+ over any TCP port of an HSTS Host.
+
+ NOTE: In the case where an explicit port is provided (and to a
+ lesser extent with subdomains), it is reasonably likely that
+ there is actually an HTTP (i.e., non-secure) server running on
+ the specified port and that an HTTPS request will thus fail
+ (see item 6 in Appendix A ("Design Decision Notes")).
+
+8.4. Errors in Secure Transport Establishment
+
+ When connecting to a Known HSTS Host, the UA MUST terminate the
+ connection (see also Section 12 ("User Agent Implementation Advice"))
+ if there are any errors, whether "warning" or "fatal" or any other
+ error level, with the underlying secure transport. For example, this
+ includes any errors found in certificate validity checking that UAs
+ employ, such as via Certificate Revocation Lists (CRLs) [RFC5280], or
+ via the Online Certificate Status Protocol (OCSP) [RFC2560], as well
+ as via TLS server identity checking [RFC6125].
+
+8.5. HTTP-Equiv <Meta> Element Attribute
+
+ UAs MUST NOT heed http-equiv="Strict-Transport-Security" attribute
+ settings on <meta> elements [W3C.REC-html401-19991224] in received
+ content.
+
+
+
+Hodges, et al. Standards Track [Page 22]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+8.6. Missing Strict-Transport-Security Response Header Field
+
+ If a UA receives HTTP responses from a Known HSTS Host over a secure
+ channel but the responses are missing the STS header field, the UA
+ MUST continue to treat the host as a Known HSTS Host until the
+ max-age value for the knowledge of that Known HSTS Host is reached.
+ Note that the max-age value could be effectively infinite for a given
+ Known HSTS Host. For example, this would be the case if the Known
+ HSTS Host is part of a pre-configured list that is implemented such
+ that the list entries never "age out".
+
+9. Constructing an Effective Request URI
+
+ This section specifies how an HSTS Host must construct the Effective
+ Request URI for a received HTTP request.
+
+ HTTP requests often do not carry an absoluteURI for the target
+ resource; instead, the URI needs to be inferred from the Request-URI,
+ Host header field, and connection context ([RFC2616], Sections 3.2.1,
+ 5.1.2, and 5.2). The result of this process is called the "effective
+ request URI (ERU)". The "target resource" is the resource identified
+ by the effective request URI.
+
+9.1. ERU Fundamental Definitions
+
+ The first line of an HTTP request message, Request-Line, is specified
+ by the following ABNF from [RFC2616], Section 5.1:
+
+ Request-Line = Method SP Request-URI SP HTTP-Version CRLF
+
+ The Request-URI, within the Request-Line, is specified by the
+ following ABNF from [RFC2616], Section 5.1.2:
+
+ Request-URI = "*" | absoluteURI | abs_path | authority
+
+ The Host request header field is specified by the following ABNF from
+ [RFC2616], Section 14.23:
+
+ Host = "Host" ":" host [ ":" port ]
+
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 23]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+9.2. Determining the Effective Request URI
+
+ If the Request-URI is an absoluteURI, then the effective request URI
+ is the Request-URI.
+
+ If the Request-URI uses the abs_path form or the asterisk form, and
+ the Host header field is present, then the effective request URI is
+ constructed by concatenating:
+
+ o the scheme name: "http" if the request was received over an
+ insecure TCP connection, or "https" when received over a TLS/
+ SSL-secured TCP connection, and
+
+ o the octet sequence "://", and
+
+ o the host, and the port (if present), from the Host header field,
+ and
+
+ o the Request-URI obtained from the Request-Line, unless the
+ Request-URI is just the asterisk "*".
+
+ If the Request-URI uses the abs_path form or the asterisk form, and
+ the Host header field is not present, then the effective request URI
+ is undefined.
+
+ Otherwise, when Request-URI uses the authority form, the effective
+ request URI is undefined.
+
+ Effective request URIs are compared using the rules described in
+ [RFC2616] Section 3.2.3, except that empty path components MUST NOT
+ be treated as equivalent to an absolute path of "/".
+
+9.2.1. Effective Request URI Examples
+
+ Example 1: the effective request URI for the message
+
+ GET /pub/WWW/TheProject.html HTTP/1.1
+ Host: www.example.org:8080
+
+ (received over an insecure TCP connection) is "http", plus "://",
+ plus the authority component "www.example.org:8080", plus the
+ request-target "/pub/WWW/TheProject.html". Thus, it is
+ "http://www.example.org:8080/pub/WWW/TheProject.html".
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 24]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ Example 2: the effective request URI for the message
+
+ OPTIONS * HTTP/1.1
+ Host: www.example.org
+
+ (received over an SSL/TLS secured TCP connection) is "https", plus
+ "://", plus the authority component "www.example.org". Thus, it is
+ "https://www.example.org".
+
+10. Domain Name IDNA-Canonicalization
+
+ An IDNA-canonicalized domain name is the output string generated by
+ the following steps. The input is a putative domain name string
+ ostensibly composed of any combination of "A-labels", "U-labels", and
+ "NR-LDH labels" (see Section 2 of [RFC5890]) concatenated using some
+ separator character (typically ".").
+
+ 1. Convert the input putative domain name string to an order-
+ preserving sequence of individual label strings.
+
+ 2. When implementing IDNA2008, convert, validate, and test each
+ A-label and U-label found among the sequence of individual label
+ strings, using the procedures defined in Sections 5.3 through 5.5
+ of [RFC5891].
+
+ Otherwise, when implementing IDNA2003, convert each label using
+ the "ToASCII" conversion in Section 4 of [RFC3490] (see also the
+ definition of "equivalence of labels" in Section 2 of [RFC3490]).
+
+ 3. If no errors occurred during the foregoing step, concatenate all
+ the labels in the sequence, in order, into a string, separating
+ each label from the next with a %x2E (".") character. The
+ resulting string, known as an IDNA-canonicalized domain name, is
+ appropriate for use in the context of Section 8 ("User Agent
+ Processing Model").
+
+ Otherwise, errors occurred. The input putative domain name
+ string was not successfully IDNA-canonicalized. Invokers of this
+ procedure should attempt appropriate error recovery.
+
+ See also Sections 13 ("Internationalized Domain Names for
+ Applications (IDNA): Dependency and Migration") and 14.10
+ ("Internationalized Domain Names") of this specification for further
+ details and considerations.
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 25]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+11. Server Implementation and Deployment Advice
+
+ This section is non-normative.
+
+11.1. Non-Conformant User Agent Considerations
+
+ Non-conformant UAs ignore the Strict-Transport-Security header field;
+ thus, non-conformant user agents do not address the threats described
+ in Section 2.3.1 ("Threats Addressed"). Please refer to Section 14.2
+ ("Non-Conformant User Agent Implications") for further discussion.
+
+11.2. HSTS Policy Expiration Time Considerations
+
+ Server implementations and deploying web sites need to consider
+ whether they are setting an expiry time that is a constant value into
+ the future, or whether they are setting an expiry time that is a
+ fixed point in time.
+
+ The "constant value into the future" approach can be accomplished by
+ constantly sending the same max-age value to UAs.
+
+ For example, a max-age value of 7776000 seconds is 90 days:
+
+ Strict-Transport-Security: max-age=7776000
+
+ Note that each receipt of this header by a UA will require the UA to
+ update its notion of when it must delete its knowledge of this Known
+ HSTS Host.
+
+ The "fixed point in time" approach can be accomplished by sending
+ max-age values that represent the remaining time until the desired
+ expiry time. This would require the HSTS Host to send a newly
+ calculated max-age value in each HTTP response.
+
+ A consideration here is whether a deployer wishes to have the
+ signaled HSTS Policy expiry time match that for the web site's domain
+ certificate.
+
+ Additionally, server implementers should consider employing a default
+ max-age value of zero in their deployment configuration systems.
+ This will require deployers to willfully set max-age in order to have
+ UAs enforce the HSTS Policy for their host and will protect them from
+ inadvertently enabling HSTS with some arbitrary non-zero duration.
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 26]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+11.3. Using HSTS in Conjunction with Self-Signed Public-Key
+ Certificates
+
+ If all four of the following conditions are true...
+
+ o a web site/organization/enterprise is generating its own secure
+ transport public-key certificates for web sites, and
+
+ o that organization's root certification authority (CA) certificate
+ is not typically embedded by default in browser and/or operating
+ system CA certificate stores, and
+
+ o HSTS Policy is enabled on a host identifying itself using a
+ certificate signed by the organization's CA (i.e., a "self-signed
+ certificate"), and
+
+ o this certificate does not match a usable TLS certificate
+ association (as defined by Section 4 of the TLSA protocol
+ specification [RFC6698]),
+
+ ...then secure connections to that site will fail, per the HSTS
+ design. This is to protect against various active attacks, as
+ discussed above.
+
+ However, if said organization wishes to employ its own CA, and self-
+ signed certificates, in concert with HSTS, it can do so by deploying
+ its root CA certificate to its users' browsers or operating system CA
+ root certificate stores. It can also, in addition or instead,
+ distribute to its users' browsers the end-entity certificate(s) for
+ specific hosts. There are various ways in which this can be
+ accomplished (details are out of scope for this specification). Once
+ its root CA certificate is installed in the browsers, it may employ
+ HSTS Policy on its site(s).
+
+ Alternatively, that organization can deploy the TLSA protocol; all
+ browsers that also use TLSA will then be able to trust the
+ certificates identified by usable TLS certificate associations as
+ denoted via TLSA.
+
+ NOTE: Interactively distributing root CA certificates to users,
+ e.g., via email, and having the users install them, is
+ arguably training the users to be susceptible to a possible
+ form of phishing attack. See Section 14.8 ("Bogus Root CA
+ Certificate Phish plus DNS Cache Poisoning Attack"). Thus,
+ care should be taken in the manner in which such certificates
+ are distributed and installed on users' systems and browsers.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 27]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+11.4. Implications of includeSubDomains
+
+ The includeSubDomains directive has practical implications meriting
+ careful consideration; two example scenarios are:
+
+ o An HSTS Host offers unsecured HTTP-based services on alternate
+ ports or at various subdomains of its HSTS Host domain name.
+
+ o Distinct web applications are offered at distinct subdomains of an
+ HSTS Host, such that UAs often interact directly with these
+ subdomain web applications without having necessarily interacted
+ with a web application offered at the HSTS Host's domain name (if
+ any).
+
+ The sections below discuss each of these scenarios in turn.
+
+11.4.1. Considerations for Offering Unsecured HTTP Services at
+ Alternate Ports or Subdomains of an HSTS Host
+
+ For example, certification authorities often offer their CRL
+ distribution and OCSP services [RFC2560] over plain HTTP, and
+ sometimes at a subdomain of a publicly available web application that
+ may be secured by TLS/SSL. For example, <https://ca.example.com/> is
+ a publicly available web application for "Example CA", a
+ certification authority. Customers use this web application to
+ register their public keys and obtain certificates. "Example CA"
+ generates certificates for customers containing
+ <http://crl-and-ocsp.ca.example.com/> as the value for the "CRL
+ Distribution Points" and "Authority Information Access:OCSP"
+ certificate fields.
+
+ If ca.example.com were to issue an HSTS Policy with the
+ includeSubDomains directive, then HTTP-based user agents implementing
+ HSTS that have interacted with the ca.example.com web application
+ would fail to retrieve CRLs and fail to check OCSP for certificates,
+ because these services are offered over plain HTTP.
+
+ In this case, Example CA can either:
+
+ o not use the includeSubDomains directive, or
+
+ o ensure that HTTP-based services offered at subdomains of
+ ca.example.com are also uniformly offered over TLS/SSL, or
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 28]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ o offer plain HTTP-based services at a different domain name, e.g.,
+ crl-and-ocsp.ca.example.NET, or
+
+ o utilize an alternative approach to distributing certificate status
+ information, obviating the need to offer CRL distribution and OCSP
+ services over plain HTTP (e.g., the "Certificate Status Request"
+ TLS extension [RFC6066], often colloquially referred to as "OCSP
+ Stapling").
+
+ NOTE: The above points are expressly only an example and do not
+ purport to address all the involved complexities. For
+ instance, there are many considerations -- on the part of CAs,
+ certificate deployers, and applications (e.g., browsers) --
+ involved in deploying an approach such as "OCSP Stapling".
+ Such issues are out of scope for this specification.
+
+11.4.2. Considerations for Offering Web Applications at Subdomains of
+ an HSTS Host
+
+ In this scenario, an HSTS Host declares an HSTS Policy with an
+ includeSubDomains directive, and there also exist distinct web
+ applications offered at distinct subdomains of the HSTS Host such
+ that UAs often interact directly with these subdomain web
+ applications without having necessarily interacted with the HSTS
+ Host. In such a case, the UAs will not receive or enforce the HSTS
+ Policy.
+
+ For example, the HSTS Host is "example.com", and it is configured to
+ emit the STS header field with the includeSubDomains directive.
+ However, example.com's actual web application is addressed at
+ "www.example.com", and example.com simply redirects user agents to
+ "https://www.example.com/".
+
+ If the STS header field is only emitted by "example.com" but UAs
+ typically bookmark -- and links (from anywhere on the web) are
+ typically established to -- "www.example.com", and "example.com" is
+ not contacted directly by all user agents in some non-zero percentage
+ of interactions, then some number of UAs will not note "example.com"
+ as an HSTS Host, and some number of users of "www.example.com" will
+ be unprotected by HSTS Policy.
+
+ To address this, HSTS Hosts should be configured such that the STS
+ header field is emitted directly at each HSTS Host domain or
+ subdomain name that constitutes a well-known "entry point" to one's
+ web application(s), whether or not the includeSubDomains directive is
+ employed.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 29]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ Thus, in our example, if the STS header field is emitted from both
+ "example.com" and "www.example.com", this issue will be addressed.
+ Also, if there are any other well-known entry points to web
+ applications offered by "example.com", such as "foo.example.com",
+ they should also be configured to emit the STS header field.
+
+12. User Agent Implementation Advice
+
+ This section is non-normative.
+
+ In order to provide users and web sites more effective protection, as
+ well as controls for managing their UA's caching of HSTS Policy, UA
+ implementers should consider including features such as the
+ following:
+
+12.1. No User Recourse
+
+ Failing secure connection establishment on any warnings or errors
+ (per Section 8.4 ("Errors in Secure Transport Establishment")) should
+ be done with "no user recourse". This means that the user should not
+ be presented with a dialog giving her the option to proceed. Rather,
+ it should be treated similarly to a server error where there is
+ nothing further the user can do with respect to interacting with the
+ target web application, other than wait and retry.
+
+ Essentially, "any warnings or errors" means anything that would cause
+ the UA implementation to announce to the user that something is not
+ entirely correct with the connection establishment.
+
+ Not doing this, i.e., allowing user recourse such as "clicking
+ through warning/error dialogs", is a recipe for a man-in-the-middle
+ attack. If a web application issues an HSTS Policy, then it is
+ implicitly opting into the "no user recourse" approach, whereby all
+ certificate errors or warnings cause a connection termination, with
+ no chance to "fool" users into making the wrong decision and
+ compromising themselves.
+
+12.2. User-Declared HSTS Policy
+
+ A user-declared HSTS Policy is the ability for users to explicitly
+ declare a given domain name as representing an HSTS Host, thus
+ seeding it as a Known HSTS Host before any actual interaction with
+ it. This would help protect against the bootstrap MITM vulnerability
+ as discussed in Section 14.6 ("Bootstrap MITM Vulnerability").
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 30]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ NOTE: Such a feature is difficult to get right on a per-site basis.
+ See the discussion of "rewrite rules" in Section 5.5 of
+ [ForceHTTPS]. For example, arbitrary web sites may not
+ materialize all their URIs using the "https" scheme and thus
+ could "break" if a UA were to attempt to access the site
+ exclusively using such URIs. Also note that this feature
+ would complement, but is independent of, an "HSTS pre-loaded
+ list" feature (see Section 12.3).
+
+12.3. HSTS Pre-Loaded List
+
+ An HSTS pre-loaded list is a facility whereby web site administrators
+ can have UAs pre-configured with HSTS Policy for their site(s) by the
+ UA vendor(s) -- a so-called "pre-loaded list" -- in a manner similar
+ to how root CA certificates are embedded in browsers "at the
+ factory". This would help protect against the bootstrap MITM
+ vulnerability (Section 14.6).
+
+ NOTE: Such a facility would complement a "user-declared HSTS Policy"
+ feature (Section 12.2).
+
+12.4. Disallow Mixed Security Context Loads
+
+ "Mixed security context" loads happen when a web application
+ resource, fetched by the UA over a secure transport, subsequently
+ causes the fetching of one or more other resources without using
+ secure transport. This is also generally referred to as "mixed
+ content" loads (see Section 5.3 ("Mixed Content") in
+ [W3C.REC-wsc-ui-20100812]) but should not be confused with the same
+ "mixed content" term that is also used in the context of markup
+ languages such as XML and HTML.
+
+ NOTE: In order to provide behavioral uniformity across UA
+ implementations, the notion of mixed security context will
+ require further standardization work, e.g., to define the
+ term(s) more clearly and to define specific behaviors with
+ respect to it.
+
+12.5. HSTS Policy Deletion
+
+ HSTS Policy deletion is the ability to delete a UA's cached HSTS
+ Policy on a per-HSTS Host basis.
+
+ NOTE: Adding such a feature should be done very carefully in both
+ the user interface and security senses. Deleting a cache
+ entry for a Known HSTS Host should be a very deliberate and
+ well-considered act -- it shouldn't be something that users
+ get used to doing as a matter of course: e.g., just "clicking
+
+
+
+Hodges, et al. Standards Track [Page 31]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ through" in order to get work done. Also, implementations
+ need to guard against allowing an attacker to inject code,
+ e.g., ECMAscript, into the UA that silently and
+ programmatically removes entries from the UA's cache of Known
+ HSTS Hosts.
+
+13. Internationalized Domain Names for Applications (IDNA): Dependency
+ and Migration
+
+ Textual domain names on the modern Internet may contain one or more
+ "internationalized" domain name labels. Such domain names are
+ referred to as "internationalized domain names" (IDNs). The
+ specification suites defining IDNs and the protocols for their use
+ are named "Internationalized Domain Names for Applications (IDNA)".
+ At this time, there are two such specification suites: IDNA2008
+ [RFC5890] and its predecessor IDNA2003 [RFC3490].
+
+ IDNA2008 obsoletes IDNA2003, but there are differences between the
+ two specifications, and thus there can be differences in processing
+ (e.g., converting) domain name labels that have been registered under
+ one from those registered under the other. There will be a
+ transition period of some time during which IDNA2003-based domain
+ name labels will exist in the wild. In order to facilitate their
+ IDNA transition, user agents SHOULD implement IDNA2008 [RFC5890] and
+ MAY implement [RFC5895] (see also Section 7 of [RFC5894]) or [UTS46].
+ If a user agent does not implement IDNA2008, the user agent MUST
+ implement IDNA2003.
+
+14. Security Considerations
+
+ This specification concerns the expression, conveyance, and
+ enforcement of the HSTS Policy. The overall HSTS Policy threat
+ model, including addressed and unaddressed threats, is given in
+ Section 2.3 ("Threat Model").
+
+ Additionally, the sections below discuss operational ramifications of
+ the HSTS Policy, provide feature rationale, discuss potential HSTS
+ Policy misuse, and highlight some known vulnerabilities in the HSTS
+ Policy regime.
+
+14.1. Underlying Secure Transport Considerations
+
+ This specification is fashioned to be independent of the secure
+ transport underlying HTTP. However, the threat analysis and
+ requirements in Section 2 ("Overview") in fact presume TLS or SSL as
+ the underlying secure transport. Thus, employment of HSTS in the
+ context of HTTP running over some other secure transport protocol
+ would require assessment of that secure transport protocol's security
+
+
+
+Hodges, et al. Standards Track [Page 32]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ model in conjunction with the specifics of how HTTP is layered over
+ it in order to assess HSTS's subsequent security properties in that
+ context.
+
+14.2. Non-Conformant User Agent Implications
+
+ Non-conformant user agents ignore the Strict-Transport-Security
+ header field; thus, non-conformant user agents do not address the
+ threats described in Section 2.3.1 ("Threats Addressed").
+
+ This means that the web application and its users wielding
+ non-conformant UAs will be vulnerable to both of the following:
+
+ o Passive network attacks due to web site development and deployment
+ bugs:
+
+ For example, if the web application contains any insecure
+ references (e.g., "http") to the web application server, and if
+ not all of its cookies are flagged as "Secure", then its
+ cookies will be vulnerable to passive network sniffing and,
+ potentially, subsequent misuse of user credentials.
+
+ o Active network attacks:
+
+ For example, if an attacker is able to place a "man in the
+ middle", secure transport connection attempts will likely yield
+ warnings to the user, but without HSTS Policy being enforced,
+ the present common practice is to allow the user to "click
+ through" and proceed. This renders the user and possibly the
+ web application open to abuse by such an attacker.
+
+ This is essentially the status quo for all web applications and their
+ users in the absence of HSTS Policy. Since web application providers
+ typically do not control the type or version of UAs their web
+ applications interact with, the implication is that HSTS Host
+ deployers must generally exercise the same level of care to avoid web
+ site development and deployment bugs (see Section 2.3.1.3) as they
+ would if they were not asserting HSTS Policy.
+
+14.3. Ramifications of HSTS Policy Establishment Only over Error-Free
+ Secure Transport
+
+ The user agent processing model defined in Section 8 ("User Agent
+ Processing Model") stipulates that a host is initially noted as a
+ Known HSTS Host, or that updates are made to a Known HSTS Host's
+ cached information, only if the UA receives the STS header field over
+ a secure transport connection having no underlying secure transport
+ errors or warnings.
+
+
+
+Hodges, et al. Standards Track [Page 33]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ The rationale behind this is that if there is a "man in the middle"
+ (MITM) -- whether a legitimately deployed proxy or an illegitimate
+ entity -- it could cause various mischief (see also Appendix A
+ ("Design Decision Notes") item 3, as well as Section 14.6 ("Bootstrap
+ MITM Vulnerability")); for example:
+
+ o Unauthorized notation of the host as a Known HSTS Host,
+ potentially leading to a denial-of-service situation if the host
+ does not uniformly offer its services over secure transport (see
+ also Section 14.5 ("Denial of Service")).
+
+ o Resetting the time to live for the host's designation as a Known
+ HSTS Host by manipulating the max-age header field parameter value
+ that is returned to the UA. If max-age is returned as zero, this
+ will cause the host to cease being regarded as a Known HSTS Host
+ by the UA, leading to either insecure connections to the host or
+ possibly denial of service if the host delivers its services only
+ over secure transport.
+
+ However, this means that if a UA is "behind" a MITM non-transparent
+ TLS proxy -- within a corporate intranet, for example -- and
+ interacts with an unknown HSTS Host beyond the proxy, the user could
+ possibly be presented with the legacy secure connection error
+ dialogs. Even if the risk is accepted and the user "clicks through",
+ the host will not be noted as an HSTS Host. Thus, as long as the UA
+ is behind such a proxy, the user will be vulnerable and will possibly
+ be presented with the legacy secure connection error dialogs for
+ as-yet unknown HSTS Hosts.
+
+ Once the UA successfully connects to an unknown HSTS Host over error-
+ free secure transport, the host will be noted as a Known HSTS Host.
+ This will result in the failure of subsequent connection attempts
+ from behind interfering proxies.
+
+ The above discussion relates to the recommendation in Section 12
+ ("User Agent Implementation Advice") that the secure connection be
+ terminated with "no user recourse" whenever there are warnings and
+ errors and the host is a Known HSTS Host. Such a posture protects
+ users from "clicking through" security warnings and putting
+ themselves at risk.
+
+14.4. The Need for includeSubDomains
+
+ Without the includeSubDomains directive, a web application would not
+ be able to adequately protect so-called "domain cookies" (even if
+ these cookies have their "Secure" flag set and thus are conveyed only
+ on secure channels). These are cookies the web application expects
+ UAs to return to any and all subdomains of the web application.
+
+
+
+Hodges, et al. Standards Track [Page 34]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ For example, suppose example.com represents the top-level DNS name
+ for a web application. Further suppose that this cookie is set for
+ the entire example.com domain, i.e., it is a "domain cookie", and it
+ has its Secure flag set. Suppose example.com is a Known HSTS Host
+ for this UA, but the includeSubDomains directive is not set.
+
+ Now, if an attacker causes the UA to request a subdomain name that is
+ unlikely to already exist in the web application, such as
+ "https://uxdhbpahpdsf.example.com/", but that the attacker has
+ managed to register in the DNS and point at an HTTP server under the
+ attacker's control, then:
+
+ 1. The UA is unlikely to already have an HSTS Policy established for
+ "uxdhbpahpdsf.example.com".
+
+ 2. The HTTP request sent to uxdhbpahpdsf.example.com will include
+ the Secure-flagged domain cookie.
+
+ 3. If "uxdhbpahpdsf.example.com" returns a certificate during TLS
+ establishment, and the user "clicks through" any warning that
+ might be presented (it is possible, but not certain, that one may
+ obtain a requisite certificate for such a domain name such that a
+ warning may or may not appear), then the attacker can obtain the
+ Secure-flagged domain cookie that's ostensibly being protected.
+
+ Without the "includeSubDomains" directive, HSTS is unable to protect
+ such Secure-flagged domain cookies.
+
+14.5. Denial of Service
+
+ HSTS could be used to mount certain forms of Denial-of-Service (DoS)
+ attacks against web sites. A DoS attack is an attack in which one or
+ more network entities target a victim entity and attempt to prevent
+ the victim from doing useful work. This section discusses such
+ scenarios in terms of HSTS, though this list is not exhaustive. See
+ also [RFC4732] for a discussion of overall Internet DoS
+ considerations.
+
+ o Web applications available over HTTP
+
+ There is an opportunity for perpetrating DoS attacks with web
+ applications (or critical portions of them) that are available
+ only over HTTP without secure transport, if attackers can cause
+ UAs to set HSTS Policy for such web applications' host(s).
+
+ This is because once the HSTS Policy is set for a web
+ application's host in a UA, the UA will only use secure transport
+ to communicate with the host. If the host is not using secure
+
+
+
+Hodges, et al. Standards Track [Page 35]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ transport or is not using it for critical portions of its web
+ application, then the web application will be rendered unusable
+ for the UA's user.
+
+ NOTE: This is a use case for UAs to offer an "HSTS Policy
+ deletion" feature as noted in Section 12.5 ("HSTS Policy
+ Deletion").
+
+ An HSTS Policy can be set for a victim host in various ways:
+
+ * If the web application has an HTTP response splitting
+ vulnerability [CWE-113] (which can be abused in order to
+ facilitate "HTTP header injection").
+
+ * If an attacker can spoof a redirect from an insecure victim
+ site, e.g., <http://example.com/> to <https://example.com/>,
+ where the latter is attacker-controlled and has an apparently
+ valid certificate. In this situation, the attacker can then
+ set an HSTS Policy for example.com and also for all subdomains
+ of example.com.
+
+ * If an attacker can convince users to manually configure HSTS
+ Policy for a victim host. This assumes that their UAs offer
+ such a capability (see Section 12 ("User Agent Implementation
+ Advice")). Alternatively, if such UA configuration is
+ scriptable, then an attacker can cause UAs to execute his
+ script and set HSTS Policies for whichever desired domains.
+
+ o Inadvertent use of includeSubDomains
+
+ The includeSubDomains directive instructs UAs to automatically
+ regard all subdomains of the given HSTS Host as Known HSTS Hosts.
+ If any such subdomains do not support properly configured secure
+ transport, then they will be rendered unreachable from such UAs.
+
+14.6. Bootstrap MITM Vulnerability
+
+ Bootstrap MITM (man-in-the-middle) vulnerability is a vulnerability
+ that users and HSTS Hosts encounter in the situation where the user
+ manually enters, or follows a link, to an unknown HSTS Host using an
+ "http" URI rather than an "https" URI. Because the UA uses an
+ insecure channel in the initial attempt to interact with the
+ specified server, such an initial interaction is vulnerable to
+ various attacks (see Section 5.3 of [ForceHTTPS]).
+
+ NOTE: There are various features/facilities that UA implementations
+ may employ in order to mitigate this vulnerability. Please
+ see Section 12 ("User Agent Implementation Advice").
+
+
+
+Hodges, et al. Standards Track [Page 36]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+14.7. Network Time Attacks
+
+ Active network attacks can subvert network time protocols (such as
+ the Network Time Protocol (NTP) [RFC5905]) -- making HSTS less
+ effective against clients that trust NTP or lack a real time clock.
+ Network time attacks are beyond the scope of this specification.
+ Note that modern operating systems use NTP by default. See also
+ Section 2.10 of [RFC4732].
+
+14.8. Bogus Root CA Certificate Phish plus DNS Cache Poisoning Attack
+
+ An attacker could conceivably obtain users' login credentials
+ belonging to a victim HSTS-protected web application via a bogus root
+ CA certificate phish plus DNS cache poisoning attack.
+
+ For example, the attacker could first convince users of a victim web
+ application (which is protected by HSTS Policy) to install the
+ attacker's version of a root CA certificate purporting (falsely) to
+ represent the CA of the victim web application. This might be
+ accomplished by sending the users a phishing email message with a
+ link to such a certificate, which their browsers may offer to install
+ if clicked on.
+
+ Then, if the attacker can perform an attack on the users' DNS
+ servers, (e.g., via cache poisoning) and turn on HSTS Policy for
+ their fake web application, the affected users' browsers would access
+ the attacker's web application rather than the legitimate web
+ application.
+
+ This type of attack leverages vectors that are outside of the scope
+ of HSTS. However, the feasibility of such threats can be mitigated
+ by including in a web application's overall deployment approach
+ appropriate employment, in addition to HSTS, of security facilities
+ such as DNS Security Extensions [RFC4033], plus techniques to block
+ email phishing and fake certificate injection.
+
+14.9. Creative Manipulation of HSTS Policy Store
+
+ Since an HSTS Host may select its own host name and subdomains
+ thereof, and this information is cached in the HSTS Policy store of
+ conforming UAs, it is possible for those who control one or more HSTS
+ Hosts to encode information into domain names they control and cause
+ such UAs to cache this information as a matter of course in the
+ process of noting the HSTS Host. This information can be retrieved
+ by other hosts through cleverly constructed and loaded web resources,
+ causing the UA to send queries to (variations of) the encoded domain
+ names. Such queries can reveal whether the UA had previously visited
+ the original HSTS Host (and subdomains).
+
+
+
+Hodges, et al. Standards Track [Page 37]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ Such a technique could potentially be abused as yet another form of
+ "web tracking" [WebTracking].
+
+14.10. Internationalized Domain Names
+
+ Internet security relies in part on the DNS and the domain names it
+ hosts. Domain names are used by users to identify and connect to
+ Internet hosts and other network resources. For example, Internet
+ security is compromised if a user entering an internationalized
+ domain name (IDN) is connected to different hosts based on different
+ interpretations of the IDN.
+
+ The processing models specified in this specification assume that the
+ domain names they manipulate are IDNA-canonicalized, and that the
+ canonicalization process correctly performed all appropriate IDNA and
+ Unicode validations and character list testing per the requisite
+ specifications (e.g., as noted in Section 10 ("Domain Name IDNA-
+ Canonicalization")). These steps are necessary in order to avoid
+ various potentially compromising situations.
+
+ In brief, examples of issues that could stem from lack of careful and
+ consistent Unicode and IDNA validations include unexpected processing
+ exceptions, truncation errors, and buffer overflows, as well as
+ false-positive and/or false-negative domain name matching results.
+ Any of the foregoing issues could possibly be leveraged by attackers
+ in various ways.
+
+ Additionally, IDNA2008 [RFC5890] differs from IDNA2003 [RFC3490] in
+ terms of disallowed characters and character mapping conventions.
+ This situation can also lead to false-positive and/or false-negative
+ domain name matching results, resulting in, for example, users
+ possibly communicating with unintended hosts or not being able to
+ reach intended hosts.
+
+ For details, refer to the Security Considerations sections of
+ [RFC5890], [RFC5891], and [RFC3490], as well as the specifications
+ they normatively reference. Additionally, [RFC5894] provides
+ detailed background and rationale for IDNA2008 in particular, as well
+ as IDNA and its issues in general, and should be consulted in
+ conjunction with the former specifications.
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 38]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+15. IANA Considerations
+
+ Below is the Internet Assigned Numbers Authority (IANA) Permanent
+ Message Header Field registration information per [RFC3864].
+
+ Header field name: Strict-Transport-Security
+ Applicable protocol: http
+ Status: standard
+ Author/Change controller: IETF
+ Specification document(s): this one
+
+16. References
+
+16.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
+ Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
+ Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
+
+ [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications (IDNA)",
+ RFC 3490, March 2003.
+
+ [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration
+ Procedures for Message Header Fields", BCP 90, RFC 3864,
+ September 2004.
+
+ [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifier (URI): Generic Syntax", STD 66,
+ RFC 3986, January 2005.
+
+ [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
+ (TLS) Protocol Version 1.2", RFC 5246, August 2008.
+
+ [RFC5890] Klensin, J., "Internationalized Domain Names for
+ Applications (IDNA): Definitions and Document Framework",
+ RFC 5890, August 2010.
+
+ [RFC5891] Klensin, J., "Internationalized Domain Names in
+ Applications (IDNA): Protocol", RFC 5891, August 2010.
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 39]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ [RFC5895] Resnick, P. and P. Hoffman, "Mapping Characters for
+ Internationalized Domain Names in Applications
+ (IDNA) 2008", RFC 5895, September 2010.
+
+ [RFC6698] Hoffman, P. and J. Schlyter, "The DNS-Based Authentication
+ of Named Entities (DANE) Transport Layer Security (TLS)
+ Protocol: TLSA", RFC 6698, August 2012.
+
+ [UTS46] Davis, M. and M. Suignard, "Unicode IDNA Compatibility
+ Processing", Unicode Technical Standard #46,
+ <http://unicode.org/reports/tr46/>.
+
+ [Unicode] The Unicode Consortium, "The Unicode Standard",
+ <http://www.unicode.org/versions/latest/>.
+
+ [W3C.REC-html401-19991224]
+ Raggett, D., Le Hors, A., and I. Jacobs, "HTML 4.01
+ Specification", World Wide Web Consortium Recommendation
+ REC-html401-19991224, December 1999,
+ <http://www.w3.org/TR/1999/REC-html401-19991224/>.
+
+16.2. Informative References
+
+ [Aircrack-ng]
+ d'Otreppe, T., "Aircrack-ng", Accessed: 11-Jul-2010,
+ <http://www.aircrack-ng.org/>.
+
+ [BeckTews09]
+ Beck, M. and E. Tews, "Practical Attacks Against WEP and
+ WPA", Second ACM Conference on Wireless Network
+ Security Zurich, Switzerland, 2009,
+ <http://dl.acm.org/citation.cfm?id=1514286>.
+
+ [CWE-113] "CWE-113: Improper Neutralization of CRLF Sequences in
+ HTTP Headers ('HTTP Response Splitting')", Common Weakness
+ Enumeration <http://cwe.mitre.org/>, The Mitre
+ Corporation <http://www.mitre.org/>,
+ <http://cwe.mitre.org/data/definitions/113.html>.
+
+ [Firesheep]
+ Various, "Firesheep", Wikipedia Online, ongoing, <https://
+ secure.wikimedia.org/wikipedia/en/w/
+ index.php?title=Firesheep&oldid=517474182>.
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 40]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ [ForceHTTPS]
+ Jackson, C. and A. Barth, "ForceHTTPS: Protecting High-
+ Security Web Sites from Network Attacks", In Proceedings
+ of the 17th International World Wide Web Conference
+ (WWW2008) , 2008,
+ <https://crypto.stanford.edu/forcehttps/>.
+
+ [GoodDhamijaEtAl05]
+ Good, N., Dhamija, R., Grossklags, J., Thaw, D.,
+ Aronowitz, S., Mulligan, D., and J. Konstan, "Stopping
+ Spyware at the Gate: A User Study of Privacy, Notice and
+ Spyware", In Proceedings of Symposium On Usable Privacy
+ and Security (SOUPS) Pittsburgh, PA, USA, July 2005,
+ <http://www.law.berkeley.edu/files/
+ Spyware_at_the_Gate.pdf>.
+
+ [HTTP1_1-UPD]
+ Fielding, R., Ed., and J. Reschke, Ed., "Hypertext
+ Transfer Protocol (HTTP/1.1): Message Syntax and Routing",
+ Work in Progress, October 2012.
+
+ [JacksonBarth2008]
+ Jackson, C. and A. Barth, "Beware of Finer-Grained
+ Origins", Web 2.0 Security and Privacy Workshop, Oakland,
+ CA, USA, 2008,
+ <http://seclab.stanford.edu/websec/origins/fgo.pdf>.
+
+ [OWASP-TLSGuide]
+ Coates, M., Wichers, D., Boberski, M., and T. Reguly,
+ "Transport Layer Protection Cheat Sheet",
+ Accessed: 11-Jul-2010, <http://www.owasp.org/index.php/
+ Transport_Layer_Protection_Cheat_Sheet>.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2560] Myers, M., Ankney, R., Malpani, A., Galperin, S., and C.
+ Adams, "X.509 Internet Public Key Infrastructure Online
+ Certificate Status Protocol - OCSP", RFC 2560, June 1999.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4732] Handley, M., Rescorla, E., and IAB, "Internet Denial-of-
+ Service Considerations", RFC 4732, December 2006.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 41]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ [RFC4949] Shirey, R., "Internet Security Glossary, Version 2",
+ RFC 4949, August 2007.
+
+ [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 5226,
+ May 2008.
+
+ [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
+ Housley, R., and W. Polk, "Internet X.509 Public Key
+ Infrastructure Certificate and Certificate Revocation List
+ (CRL) Profile", RFC 5280, May 2008.
+
+ [RFC5894] Klensin, J., "Internationalized Domain Names for
+ Applications (IDNA): Background, Explanation, and
+ Rationale", RFC 5894, August 2010.
+
+ [RFC5905] Mills, D., Martin, J., Burbank, J., and W. Kasch, "Network
+ Time Protocol Version 4: Protocol and Algorithms
+ Specification", RFC 5905, June 2010.
+
+ [RFC6066] Eastlake, D., "Transport Layer Security (TLS) Extensions:
+ Extension Definitions", RFC 6066, January 2011.
+
+ [RFC6101] Freier, A., Karlton, P., and P. Kocher, "The Secure
+ Sockets Layer (SSL) Protocol Version 3.0", RFC 6101,
+ August 2011.
+
+ [RFC6125] Saint-Andre, P. and J. Hodges, "Representation and
+ Verification of Domain-Based Application Service Identity
+ within Internet Public Key Infrastructure Using X.509
+ (PKIX) Certificates in the Context of Transport Layer
+ Security (TLS)", RFC 6125, March 2011.
+
+ [RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265,
+ April 2011.
+
+ [RFC6454] Barth, A., "The Web Origin Concept", RFC 6454,
+ December 2011.
+
+ [SunshineEgelmanEtAl09]
+ Sunshine, J., Egelman, S., Almuhimedi, H., Atri, N., and
+ L. Cranor, "Crying Wolf: An Empirical Study of SSL Warning
+ Effectiveness", In Proceedings of 18th USENIX Security
+ Symposium Montreal, Canada, August 2009, <http://
+ www.usenix.org/events/sec09/tech/full_papers/
+ sunshine.pdf>.
+
+
+
+
+
+Hodges, et al. Standards Track [Page 42]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+ [W3C.REC-wsc-ui-20100812]
+ Roessler, T. and A. Saldhana, "Web Security Context: User
+ Interface Guidelines", World Wide Web Consortium
+ Recommendation REC-wsc-ui-20100812, August 2010,
+ <http://www.w3.org/TR/2010/REC-wsc-ui-20100812>.
+
+ [WebTracking]
+ Schmucker, N., "Web Tracking", SNET2 Seminar Paper
+ - Summer Term, 2011, <http://www.snet.tu-berlin.de/
+ fileadmin/fg220/courses/SS11/snet-project/
+ web-tracking_schmuecker.pdf>.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 43]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+Appendix A. Design Decision Notes
+
+ This appendix documents various design decisions.
+
+ 1. Cookies aren't appropriate for HSTS Policy expression, as they
+ are potentially mutable (while stored in the UA); therefore, an
+ HTTP header field is employed.
+
+ 2. We chose to not attempt to specify how "mixed security context
+ loads" (also known as "mixed content loads") are handled, due to
+ UA implementation considerations as well as classification
+ difficulties.
+
+ 3. An HSTS Host may update UA notions of HSTS Policy via new HSTS
+ header field parameter values. We chose to have UAs honor the
+ "freshest" information received from a server because there is
+ the chance of a web site sending out an erroneous HSTS Policy,
+ such as a multi-year max-age value, and/or an incorrect
+ includeSubDomains directive. If the HSTS Host couldn't correct
+ such errors over protocol, it would require some form of
+ annunciation to users and manual intervention on the users' part,
+ which could be a non-trivial problem for both web application
+ providers and their users.
+
+ 4. HSTS Hosts are identified only via domain names -- explicit IP
+ address identification of all forms is excluded. This is for
+ simplification and also is in recognition of various issues with
+ using direct IP address identification in concert with PKI-based
+ security.
+
+ 5. The max-age approach of having the HSTS Host provide a simple
+ integer number of seconds for a cached HSTS Policy time-to-live
+ value, as opposed to an approach of stating an expiration time in
+ the future, was chosen for various reasons. Amongst the reasons
+ are no need for clock synchronization, no need to define date and
+ time value syntaxes (specification simplicity), and
+ implementation simplicity.
+
+ 6. In determining whether port mapping was to be employed, the
+ option of merely refusing to dereference any URL with an explicit
+ port was considered. It was felt, though, that the possibility
+ that the URI to be dereferenced is incorrect (and there is indeed
+ a valid HTTPS server at that port) is worth the small cost of
+ possibly wasted HTTPS fetches to HTTP servers.
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 44]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+Appendix B. Differences between HSTS Policy and Same-Origin Policy
+
+ HSTS Policy has the following primary characteristics:
+
+ HSTS Policy stipulates requirements for the security
+ characteristics of UA-to-host connection establishment, on a
+ per-host basis.
+
+ Hosts explicitly declare HSTS Policy to UAs. Conformant UAs are
+ obliged to implement hosts' declared HSTS Policies.
+
+ HSTS Policy is conveyed over protocol from the host to the UA.
+
+ The UA maintains a cache of Known HSTS Hosts.
+
+ UAs apply HSTS Policy whenever making an HTTP connection to a
+ Known HSTS Host, regardless of host port number; i.e., it applies
+ to all ports on a Known HSTS Host. Hosts are unable to affect
+ this aspect of HSTS Policy.
+
+ Hosts may optionally declare that their HSTS Policy applies to all
+ subdomains of their host domain name.
+
+ In contrast, the Same-Origin Policy (SOP) [RFC6454] has the following
+ primary characteristics:
+
+ An origin is the scheme, host, and port of a URI identifying a
+ resource.
+
+ A UA may dereference a URI, thus loading a representation of the
+ resource the URI identifies. UAs label resource representations
+ with their origins, which are derived from their URIs.
+
+ The SOP refers to a collection of principles, implemented within
+ UAs, governing the isolation of and communication between resource
+ representations within the UA, as well as resource
+ representations' access to network resources.
+
+ In summary, although both HSTS Policy and SOP are enforced by UAs,
+ HSTS Policy is optionally declared by hosts and is not origin-based,
+ while the SOP applies to all resource representations loaded from all
+ hosts by conformant UAs.
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 45]
+
+RFC 6797 HTTP Strict Transport Security (HSTS) November 2012
+
+
+Appendix C. Acknowledgments
+
+ The authors thank Devdatta Akhawe, Michael Barrett, Ben Campbell,
+ Tobias Gondrom, Paul Hoffman, Murray Kucherawy, Barry Leiba, James
+ Manger, Alexey Melnikov, Haevard Molland, Yoav Nir, Yngve N.
+ Pettersen, Laksh Raghavan, Marsh Ray, Julian Reschke, Eric Rescorla,
+ Tom Ritter, Peter Saint-Andre, Brian Smith, Robert Sparks, Maciej
+ Stachowiak, Sid Stamm, Andy Steingrubl, Brandon Sterne, Martin
+ Thomson, Daniel Veditz, and Jan Wrobel, as well as all the websec
+ working group participants and others for their various reviews and
+ helpful contributions.
+
+ Thanks to Julian Reschke for his elegant rewriting of the effective
+ request URI text, which he did when incorporating the ERU notion into
+ the updates to HTTP/1.1 [HTTP1_1-UPD]. Subsequently, the ERU text in
+ this spec was lifted from Julian's work in the updated HTTP/1.1
+ (part 1) specification and adapted to the [RFC2616] ABNF.
+
+Authors' Addresses
+
+ Jeff Hodges
+ PayPal
+ 2211 North First Street
+ San Jose, California 95131
+ US
+
+ EMail: Jeff.Hodges@PayPal.com
+
+
+ Collin Jackson
+ Carnegie Mellon University
+
+ EMail: collin.jackson@sv.cmu.edu
+
+
+ Adam Barth
+ Google, Inc.
+
+ EMail: ietf@adambarth.com
+ URI: http://www.adambarth.com/
+
+
+
+
+
+
+
+
+
+
+
+Hodges, et al. Standards Track [Page 46]
+
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index 4a0db8e2..cead4d18 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -47,6 +47,9 @@ soup_headers = \
soup-date.h \
soup-form.h \
soup-headers.h \
+ soup-hsts-enforcer.h \
+ soup-hsts-enforcer-db.h \
+ soup-hsts-policy.h \
soup-logger.h \
soup-message.h \
soup-message-body.h \
@@ -158,6 +161,10 @@ libsoup_2_4_la_SOURCES = \
soup-filter-input-stream.h \
soup-form.c \
soup-headers.c \
+ soup-hsts-enforcer.c \
+ soup-hsts-enforcer-db.c \
+ soup-hsts-enforcer-private.h \
+ soup-hsts-policy.c \
soup-init.c \
soup-io-stream.h \
soup-io-stream.c \
diff --git a/libsoup/soup-hsts-enforcer-db.c b/libsoup/soup-hsts-enforcer-db.c
new file mode 100644
index 00000000..319f118d
--- /dev/null
+++ b/libsoup/soup-hsts-enforcer-db.c
@@ -0,0 +1,314 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-hsts-enforcer-db.c: database-based HSTS policy storage
+ *
+ * Using soup-cookie-jar-db as template
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <sqlite3.h>
+
+#include "soup-hsts-enforcer-db.h"
+#include "soup-hsts-enforcer-private.h"
+#include "soup.h"
+
+/**
+ * SECTION:soup-hsts-enforcer-db
+ * @short_description: Database-based HSTS Enforcer
+ *
+ * #SoupHstsEnforcerDB is a #SoupHstsEnforcer that reads HSTS policies from
+ * and writes them to a sqlite database.
+ **/
+
+enum {
+ PROP_0,
+
+ PROP_FILENAME,
+
+ LAST_PROP
+};
+
+typedef struct {
+ char *filename;
+ sqlite3 *db;
+} SoupHstsEnforcerDBPrivate;
+
+#define SOUP_HSTS_ENFORCER_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_HSTS_ENFORCER_DB, SoupHstsEnforcerDBPrivate))
+
+G_DEFINE_TYPE (SoupHstsEnforcerDB, soup_hsts_enforcer_db, SOUP_TYPE_HSTS_ENFORCER)
+
+static void load (SoupHstsEnforcer *hsts_enforcer);
+
+static void
+soup_hsts_enforcer_db_init (SoupHstsEnforcerDB *db)
+{
+}
+
+static void
+soup_hsts_enforcer_db_finalize (GObject *object)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (object);
+
+ g_free (priv->filename);
+ g_clear_pointer (&priv->db, sqlite3_close);
+
+ G_OBJECT_CLASS (soup_hsts_enforcer_db_parent_class)->finalize (object);
+}
+
+static void
+soup_hsts_enforcer_db_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ priv->filename = g_value_dup_string (value);
+ load (SOUP_HSTS_ENFORCER (object));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+soup_hsts_enforcer_db_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, priv->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * soup_hsts_enforcer_db_new:
+ * @filename: the filename to read to/write from, or %NULL
+ *
+ * Creates a #SoupHstsEnforcerDB.
+ *
+ * @filename will be read in at startup to create an initial set of HSTS
+ * policies. Changes to the policies will be written to @filename when the
+ * 'changed' signal is emitted from the HSTS enforcer.
+ *
+ * Return value: the new #SoupHstsEnforcer
+ *
+ * Since: 2.54
+ **/
+SoupHstsEnforcer *
+soup_hsts_enforcer_db_new (const char *filename)
+{
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ return g_object_new (SOUP_TYPE_HSTS_ENFORCER_DB,
+ SOUP_HSTS_ENFORCER_DB_FILENAME, filename,
+ NULL);
+}
+
+#define QUERY_ALL "SELECT id, host, expiry, includeSubDomains FROM soup_hsts_policies;"
+#define CREATE_TABLE "CREATE TABLE soup_hsts_policies (id INTEGER PRIMARY KEY, host TEXT UNIQUE, expiry INTEGER, includeSubDomains INTEGER)"
+#define QUERY_INSERT "INSERT OR REPLACE INTO soup_hsts_policies VALUES((SELECT id FROM soup_hsts_policies WHERE host=%Q), %Q, %d, %d);"
+#define QUERY_DELETE "DELETE FROM soup_hsts_policies WHERE host=%Q;"
+
+enum {
+ COL_ID,
+ COL_HOST,
+ COL_EXPIRY,
+ COL_SUB_DOMAINS,
+ N_COL,
+};
+
+static int
+callback (void *data, int argc, char **argv, char **colname)
+{
+ SoupHstsPolicy *policy = NULL;
+ SoupHstsEnforcer *hsts_enforcer = SOUP_HSTS_ENFORCER (data);
+
+ char *host;
+ gulong expire_time;
+ time_t now;
+ SoupDate *expires;
+ gboolean include_sub_domains = FALSE;
+
+ now = time (NULL);
+
+ host = argv[COL_HOST];
+ expire_time = strtoul (argv[COL_EXPIRY], NULL, 10);
+
+ if (now >= expire_time)
+ return 0;
+
+ expires = soup_date_new_from_time_t (expire_time);
+ include_sub_domains = (g_strcmp0 (argv[COL_SUB_DOMAINS], "1") == 0);
+
+ policy = soup_hsts_policy_new (host, expires, include_sub_domains);
+
+ if (policy)
+ soup_hsts_enforcer_set_policy (hsts_enforcer, policy);
+ else
+ soup_date_free (expires);
+
+ return 0;
+}
+
+static void
+try_create_table (sqlite3 *db)
+{
+ char *error = NULL;
+
+ if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) {
+ g_warning ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+}
+
+static void
+exec_query_with_try_create_table (sqlite3 *db,
+ const char *sql,
+ int (*callback)(void*,int,char**,char**),
+ void *argument)
+{
+ char *error = NULL;
+ gboolean try_create = TRUE;
+
+try_exec:
+ if (sqlite3_exec (db, sql, callback, argument, &error)) {
+ if (try_create) {
+ try_create = FALSE;
+ try_create_table (db);
+ sqlite3_free (error);
+ error = NULL;
+ goto try_exec;
+ } else {
+ g_warning ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+ }
+}
+
+/* Follows sqlite3 convention; returns TRUE on error */
+static gboolean
+open_db (SoupHstsEnforcer *hsts_enforcer)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (hsts_enforcer);
+
+ char *error = NULL;
+
+ if (sqlite3_open (priv->filename, &priv->db)) {
+ sqlite3_close (priv->db);
+ priv->db = NULL;
+ g_warning ("Can't open %s", priv->filename);
+ return TRUE;
+ }
+
+ if (sqlite3_exec (priv->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) {
+ g_warning ("Failed to execute query: %s", error);
+ sqlite3_free (error);
+ }
+
+ return FALSE;
+}
+
+static void
+load (SoupHstsEnforcer *hsts_enforcer)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (hsts_enforcer);
+
+ if (priv->db == NULL) {
+ if (open_db (hsts_enforcer))
+ return;
+ }
+
+ exec_query_with_try_create_table (priv->db, QUERY_ALL, callback, hsts_enforcer);
+}
+
+static void
+soup_hsts_enforcer_db_changed (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *old_policy,
+ SoupHstsPolicy *new_policy)
+{
+ SoupHstsEnforcerDBPrivate *priv =
+ SOUP_HSTS_ENFORCER_DB_GET_PRIVATE (hsts_enforcer);
+ char *query;
+
+ if (priv->db == NULL) {
+ if (open_db (hsts_enforcer))
+ return;
+ }
+
+ if (old_policy && !new_policy) {
+ query = sqlite3_mprintf (QUERY_DELETE,
+ old_policy->domain);
+ exec_query_with_try_create_table (priv->db, query, NULL, NULL);
+ sqlite3_free (query);
+ }
+
+ /* Insert the new policy or update the existing one. */
+ if (new_policy && new_policy->expires) {
+ gulong expires;
+
+ expires = (gulong)soup_date_to_time_t (new_policy->expires);
+ query = sqlite3_mprintf (QUERY_INSERT,
+ new_policy->domain,
+ new_policy->domain,
+ expires,
+ new_policy->include_sub_domains);
+ exec_query_with_try_create_table (priv->db, query, NULL, NULL);
+ sqlite3_free (query);
+ }
+}
+
+static gboolean
+soup_hsts_enforcer_db_is_persistent (SoupHstsEnforcer *hsts_enforcer)
+{
+ return TRUE;
+}
+
+static void
+soup_hsts_enforcer_db_class_init (SoupHstsEnforcerDBClass *db_class)
+{
+ SoupHstsEnforcerClass *hsts_enforcer_class =
+ SOUP_HSTS_ENFORCER_CLASS (db_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (db_class);
+
+ g_type_class_add_private (db_class, sizeof (SoupHstsEnforcerDBPrivate));
+
+ hsts_enforcer_class->is_persistent = soup_hsts_enforcer_db_is_persistent;
+ hsts_enforcer_class->changed = soup_hsts_enforcer_db_changed;
+
+ object_class->finalize = soup_hsts_enforcer_db_finalize;
+ object_class->set_property = soup_hsts_enforcer_db_set_property;
+ object_class->get_property = soup_hsts_enforcer_db_get_property;
+
+ /**
+ * SOUP_HSTS_ENFORCER_DB_FILENAME:
+ *
+ * Alias for the #SoupHstsEnforcerDB:filename property. (The
+ * HSTS policy storage filename.)
+ **/
+ g_object_class_install_property (
+ object_class, PROP_FILENAME,
+ g_param_spec_string (SOUP_HSTS_ENFORCER_DB_FILENAME,
+ "Filename",
+ "HSTS policy storage filename",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
diff --git a/libsoup/soup-hsts-enforcer-db.h b/libsoup/soup-hsts-enforcer-db.h
new file mode 100644
index 00000000..38f56e76
--- /dev/null
+++ b/libsoup/soup-hsts-enforcer-db.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifndef SOUP_HSTS_ENFORCER_DB_H
+#define SOUP_HSTS_ENFORCER_DB_H 1
+
+#include <libsoup/soup-hsts-enforcer.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_HSTS_ENFORCER_DB (soup_hsts_enforcer_db_get_type ())
+#define SOUP_HSTS_ENFORCER_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_HSTS_ENFORCER_DB, SoupHstsEnforcerDB))
+#define SOUP_HSTS_ENFORCER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_HSTS_ENFORCER_DB, SoupHstsEnforcerDBClass))
+#define SOUP_IS_HSTS_ENFORCER_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_HSTS_ENFORCER_DB))
+#define SOUP_IS_HSTS_ENFORCER_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_HSTS_ENFORCER_DB))
+#define SOUP_HSTS_ENFORCER_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_HSTS_ENFORCER_DB, SoupHstsEnforcerDBClass))
+
+typedef struct {
+ SoupHstsEnforcer parent;
+
+} SoupHstsEnforcerDB;
+
+typedef struct {
+ SoupHstsEnforcerClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_libsoup_reserved1) (void);
+ void (*_libsoup_reserved2) (void);
+ void (*_libsoup_reserved3) (void);
+ void (*_libsoup_reserved4) (void);
+} SoupHstsEnforcerDBClass;
+
+#define SOUP_HSTS_ENFORCER_DB_FILENAME "filename"
+
+SOUP_AVAILABLE_IN_2_42
+GType soup_hsts_enforcer_db_get_type (void);
+
+SOUP_AVAILABLE_IN_2_42
+SoupHstsEnforcer *soup_hsts_enforcer_db_new (const char *filename);
+
+G_END_DECLS
+
+#endif /* SOUP_HSTS_ENFORCER_DB_H */
diff --git a/libsoup/soup-hsts-enforcer-private.h b/libsoup/soup-hsts-enforcer-private.h
new file mode 100644
index 00000000..274d0560
--- /dev/null
+++ b/libsoup/soup-hsts-enforcer-private.h
@@ -0,0 +1,14 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifndef SOUP_HSTS_ENFORCER_PRIVATE_H
+#define SOUP_HSTS_ENFORCER_PRIVATE_H 1
+
+#include <libsoup/soup-types.h>
+
+void soup_hsts_enforcer_set_policy (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *policy);
+
+#endif /* SOUP_HSTS_ENFORCER_PRIVATE_H */
diff --git a/libsoup/soup-hsts-enforcer.c b/libsoup/soup-hsts-enforcer.c
new file mode 100644
index 00000000..8f3cf2b7
--- /dev/null
+++ b/libsoup/soup-hsts-enforcer.c
@@ -0,0 +1,602 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-hsts-enforcer.c: HTTP Strict Transport Security implementation
+ *
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+/* TODO Use only internationalized domain names */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "soup-hsts-enforcer.h"
+#include "soup-hsts-enforcer-private.h"
+#include "soup.h"
+
+/**
+ * SECTION:soup-hsts-enforcer
+ * @short_description: Automatic HSTS enforcing for SoupSession
+ *
+ * A #SoupHstsEnforcer stores HSTS policies and enforce them when
+ * required.
+ * #SoupHstsEnforcer implements #SoupSessionFeature, so you can add a
+ * HSTS enforcer to a session with soup_session_add_feature() or
+ * soup_session_add_feature_by_type().
+ *
+ * When the #SoupSession the #SoupHstsEnforcer is attached to sends a
+ * message, the #SoupHstsEnforcer will ask for a redirection to HTTPS if
+ * the destination is a known HSTS host and is contacted over an insecure
+ * transport protocol (HTTP).
+ *
+ * Note that the base #SoupHstsEnforcer class does not support any form
+ * of long-term HSTS policy persistence.
+ **/
+
+static void soup_hsts_enforcer_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
+
+G_DEFINE_TYPE_WITH_CODE (SoupHstsEnforcer, soup_hsts_enforcer, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
+ soup_hsts_enforcer_session_feature_init))
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+typedef struct {
+ GHashTable *host_policies;
+ GHashTable *session_policies;
+} SoupHstsEnforcerPrivate;
+#define SOUP_HSTS_ENFORCER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_HSTS_ENFORCER, SoupHstsEnforcerPrivate))
+
+static void
+soup_hsts_enforcer_init (SoupHstsEnforcer *hsts_enforcer)
+{
+ SoupHstsEnforcerPrivate *priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+
+ priv->host_policies = g_hash_table_new_full (soup_str_case_hash,
+ soup_str_case_equal,
+ g_free, NULL);
+
+ priv->session_policies = g_hash_table_new_full (soup_str_case_hash,
+ soup_str_case_equal,
+ g_free, NULL);
+}
+
+static void
+soup_hsts_enforcer_finalize (GObject *object)
+{
+ SoupHstsEnforcerPrivate *priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (object);
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, priv->host_policies);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ soup_hsts_policy_free (value);
+ g_hash_table_destroy (priv->host_policies);
+
+ g_hash_table_iter_init (&iter, priv->session_policies);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ soup_hsts_policy_free (value);
+ g_hash_table_destroy (priv->session_policies);
+
+ G_OBJECT_CLASS (soup_hsts_enforcer_parent_class)->finalize (object);
+}
+
+static gboolean
+soup_hsts_enforcer_real_is_persistent (SoupHstsEnforcer *hsts_enforcer)
+{
+ return FALSE;
+}
+
+static void
+soup_hsts_enforcer_class_init (SoupHstsEnforcerClass *hsts_enforcer_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (hsts_enforcer_class);
+
+ g_type_class_add_private (hsts_enforcer_class, sizeof (SoupHstsEnforcerPrivate));
+
+ object_class->finalize = soup_hsts_enforcer_finalize;
+
+ hsts_enforcer_class->is_persistent = soup_hsts_enforcer_real_is_persistent;
+
+ /**
+ * SoupHstsEnforcer::changed:
+ * @hsts_enforcer: the #SoupHstsEnforcer
+ * @old_policy: the old #SoupHstsPolicy value
+ * @new_policy: the new #SoupHstsPolicy value
+ *
+ * Emitted when @hsts_enforcer changes. If a policy has been added,
+ * @new_policy will contain the newly-added policy and
+ * @old_policy will be %NULL. If a policy has been deleted,
+ * @old_policy will contain the to-be-deleted policy and
+ * @new_policy will be %NULL. If a policy has been changed,
+ * @old_policy will contain its old value, and @new_policy its
+ * new value.
+ **/
+ signals[CHANGED] =
+ g_signal_new ("changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (SoupHstsEnforcerClass, changed),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 2,
+ SOUP_TYPE_HSTS_POLICY | G_SIGNAL_TYPE_STATIC_SCOPE,
+ SOUP_TYPE_HSTS_POLICY | G_SIGNAL_TYPE_STATIC_SCOPE);
+}
+
+/**
+ * soup_hsts_enforcer_new:
+ *
+ * Creates a new #SoupHstsEnforcer. The base #SoupHstsEnforcer class does
+ * not support persistent storage of HSTS policies; use a subclass for
+ * that.
+ *
+ * Returns: a new #SoupHstsEnforcer
+ *
+ * Since: 2.54
+ **/
+SoupHstsEnforcer *
+soup_hsts_enforcer_new (void)
+{
+ return g_object_new (SOUP_TYPE_HSTS_ENFORCER, NULL);
+}
+
+static void
+soup_hsts_enforcer_changed (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *old, SoupHstsPolicy *new)
+{
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+
+ g_assert_true (old || new);
+
+ g_signal_emit (hsts_enforcer, signals[CHANGED], 0, old, new);
+}
+
+static void
+soup_hsts_enforcer_remove_expired_host_policies (SoupHstsEnforcer *hsts_enforcer)
+{
+ SoupHstsEnforcerPrivate *priv;
+ SoupHstsPolicy *policy;
+ GList *domains, *p;
+ const char *domain;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+
+ /* Remove all the expired policies as soon as one is encountered as required by the RFC. */
+ domains = g_hash_table_get_keys (priv->host_policies);
+ for (p = domains; p; p = p->next ) {
+ domain = (const char *) p->data;
+ policy = g_hash_table_lookup (priv->host_policies, domain);
+ if (policy && soup_hsts_policy_is_expired (policy)) {
+ g_hash_table_remove (priv->host_policies, domain);
+ soup_hsts_enforcer_changed (hsts_enforcer, policy, NULL);
+ soup_hsts_policy_free (policy);
+ }
+ }
+ g_list_free (domains);
+}
+
+static void
+soup_hsts_enforcer_remove_host_policy (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ SoupHstsEnforcerPrivate *priv;
+ SoupHstsPolicy *policy;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+ g_return_if_fail (domain != NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+
+ policy = g_hash_table_lookup (priv->host_policies, domain);
+
+ g_assert_nonnull (policy);
+
+ g_hash_table_remove (priv->host_policies, domain);
+ soup_hsts_enforcer_changed (hsts_enforcer, policy, NULL);
+ soup_hsts_policy_free (policy);
+
+ soup_hsts_enforcer_remove_expired_host_policies (hsts_enforcer);
+}
+
+static void
+soup_hsts_enforcer_replace_policy (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *new_policy)
+{
+ SoupHstsEnforcerPrivate *priv;
+ GHashTable *policies;
+ SoupHstsPolicy *old_policy;
+ const gchar *domain;
+ gboolean is_permanent;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+ g_return_if_fail (new_policy != NULL);
+
+ g_assert_false (soup_hsts_policy_is_expired (new_policy));
+
+ domain = soup_hsts_policy_get_domain (new_policy);
+ is_permanent = soup_hsts_policy_is_permanent (new_policy);
+
+ g_return_if_fail (domain != NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+ policies = is_permanent ? priv->session_policies :
+ priv->host_policies;
+
+ old_policy = g_hash_table_lookup (policies, domain);
+
+ g_assert_nonnull (old_policy);
+
+ g_hash_table_remove (policies, domain);
+ g_hash_table_insert (policies, g_strdup (domain), new_policy);
+ if (!is_permanent && !soup_hsts_policy_equal (old_policy, new_policy))
+ soup_hsts_enforcer_changed (hsts_enforcer, old_policy, new_policy);
+ soup_hsts_policy_free (old_policy);
+
+ soup_hsts_enforcer_remove_expired_host_policies (hsts_enforcer);
+}
+
+static void
+soup_hsts_enforcer_insert_policy (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *policy)
+{
+ SoupHstsEnforcerPrivate *priv;
+ GHashTable *policies;
+ const gchar *domain;
+ gboolean is_permanent;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+ g_return_if_fail (policy != NULL);
+
+ g_assert_false (soup_hsts_policy_is_expired (policy));
+
+ domain = soup_hsts_policy_get_domain (policy);
+ is_permanent = soup_hsts_policy_is_permanent (policy);
+
+ g_return_if_fail (domain != NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+ policies = is_permanent ? priv->session_policies :
+ priv->host_policies;
+
+ g_assert_false (g_hash_table_contains (policies, domain));
+
+ g_hash_table_insert (policies, g_strdup (domain), policy);
+ if (!is_permanent)
+ soup_hsts_enforcer_changed (hsts_enforcer, NULL, policy);
+}
+
+/**
+ * soup_hsts_enforcer_set_policy:
+ * @hsts_enforcer: a #SoupHstsEnforcer
+ * @policy: (transfer full): the policy of the HSTS host
+ *
+ * Sets @domain's HSTS policy to @policy. If @policy is expired, any
+ * existing HSTS policy for this host will be removed instead. If a policy
+ * exited for this host, it will be replaced. Otherwise, the new policy
+ * will be inserted.
+ *
+ * This steals @policy.
+ *
+ * Since: 2.54
+ **/
+void
+soup_hsts_enforcer_set_policy (SoupHstsEnforcer *hsts_enforcer,
+ SoupHstsPolicy *policy)
+{
+ SoupHstsEnforcerPrivate *priv;
+ GHashTable *policies;
+ const gchar *domain;
+ gboolean is_permanent;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+ g_return_if_fail (policy != NULL);
+
+ domain = soup_hsts_policy_get_domain (policy);
+ is_permanent = soup_hsts_policy_is_permanent (policy);
+
+ g_return_if_fail (domain != NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+ policies = is_permanent ? priv->session_policies :
+ priv->host_policies;
+
+ if (!is_permanent && soup_hsts_policy_is_expired (policy)) {
+ soup_hsts_enforcer_remove_host_policy (hsts_enforcer, domain);
+ soup_hsts_policy_free (policy);
+ return;
+ }
+
+ if (g_hash_table_contains (policies, domain))
+ soup_hsts_enforcer_replace_policy (hsts_enforcer, policy);
+ else
+ soup_hsts_enforcer_insert_policy (hsts_enforcer, policy);
+}
+
+static SoupHstsPolicy *
+soup_hsts_enforcer_get_host_policy (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ SoupHstsEnforcerPrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), NULL);
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+
+ return g_hash_table_lookup (priv->host_policies, domain);
+}
+
+static SoupHstsPolicy *
+soup_hsts_enforcer_get_session_policy (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ SoupHstsEnforcerPrivate *priv;
+
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), NULL);
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ priv = SOUP_HSTS_ENFORCER_GET_PRIVATE (hsts_enforcer);
+
+ return g_hash_table_lookup (priv->session_policies, domain);
+}
+
+/**
+ * soup_hsts_enforcer_set_session_policy:
+ * @hsts_enforcer: a #SoupHstsEnforcer
+ * @domain: policy domain or hostname
+ * @include_sub_domains: %TRUE if the policy applies on sub domains
+ *
+ * Sets a session policy@domain's HSTS policy to @policy. If @policy is expired, any
+ * existing HSTS policy for this host will be removed instead. If a policy
+ * exited for this host, it will be replaced. Otherwise, the new policy
+ * will be inserted.
+ *
+ * Since: 2.54
+ **/
+void
+soup_hsts_enforcer_set_session_policy (SoupHstsEnforcer *hsts_enforcer,
+ const char *domain,
+ gboolean include_sub_domains)
+{
+ SoupHstsPolicy *policy;
+
+ g_return_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer));
+ g_return_if_fail (domain != NULL);
+
+ policy = soup_hsts_policy_new_permanent (domain, include_sub_domains);
+ soup_hsts_enforcer_set_policy (hsts_enforcer, policy);
+}
+
+static gboolean
+soup_hsts_enforcer_is_valid_host (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ SoupHstsPolicy *policy;
+
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), FALSE);
+ g_return_val_if_fail (domain != NULL, FALSE);
+
+ if (soup_hsts_enforcer_get_session_policy (hsts_enforcer, domain))
+ return TRUE;
+
+ policy = soup_hsts_enforcer_get_host_policy (hsts_enforcer, domain);
+ if (policy)
+ return !soup_hsts_policy_is_expired (policy);
+
+ return FALSE;
+}
+
+static gboolean
+soup_hsts_enforcer_host_includes_sub_domains (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ SoupHstsPolicy *policy;
+ gboolean include_sub_domains = FALSE;
+
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), FALSE);
+ g_return_val_if_fail (domain != NULL, FALSE);
+
+ policy = soup_hsts_enforcer_get_session_policy (hsts_enforcer, domain);
+ if (policy)
+ include_sub_domains |= soup_hsts_policy_includes_sub_domains (policy);
+
+ policy = soup_hsts_enforcer_get_host_policy (hsts_enforcer, domain);
+ if (policy)
+ include_sub_domains |= soup_hsts_policy_includes_sub_domains (policy);
+
+ return include_sub_domains;
+}
+
+static inline const gchar*
+super_domain_of (const gchar *domain)
+{
+ const gchar *iter = domain;
+
+ g_return_val_if_fail (domain != NULL, NULL);
+
+ for (; *iter != '\0' && *iter != '.' ; iter++);
+ for (; *iter == '.' ; iter++);
+
+ if (*iter == '\0')
+ return NULL;
+
+ return iter;
+}
+
+static gboolean
+soup_hsts_enforcer_must_enforce_secure_transport (SoupHstsEnforcer *hsts_enforcer,
+ const gchar *domain)
+{
+ const gchar *super_domain = domain;
+
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), FALSE);
+ g_return_val_if_fail (domain != NULL, FALSE);
+
+ if (soup_hsts_enforcer_is_valid_host (hsts_enforcer, domain))
+ return TRUE;
+
+ while ((super_domain = super_domain_of (super_domain)) != NULL) {
+ if (soup_hsts_enforcer_host_includes_sub_domains (hsts_enforcer, super_domain) &&
+ soup_hsts_enforcer_is_valid_host (hsts_enforcer, super_domain))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Processes the 'Strict-Transport-Security' field of a message's response header. */
+static void
+soup_hsts_enforcer_process_sts_header (SoupHstsEnforcer *hsts_enforcer,
+ SoupMessage *msg)
+{
+ SoupHstsPolicy *policy;
+ SoupURI *uri;
+
+ g_return_if_fail (hsts_enforcer != NULL);
+ g_return_if_fail (msg != NULL);
+
+ /* TODO if connection error or warnings received, do nothing. */
+
+ /* TODO if header received on hazardous connection, do nothing. */
+
+ uri = soup_message_get_uri (msg);
+
+ g_return_if_fail (uri != NULL);
+
+ policy = soup_hsts_policy_new_from_response (msg);
+
+ g_return_if_fail (policy != NULL);
+
+ soup_hsts_enforcer_set_policy (hsts_enforcer, policy);
+}
+
+/* Enforces HTTPS when demanded. */
+static gboolean
+soup_hsts_enforcer_should_redirect_to_https (SoupHstsEnforcer *hsts_enforcer,
+ SoupMessage *msg)
+{
+ SoupURI *uri;
+ const gchar *domain;
+
+ g_return_val_if_fail (hsts_enforcer != NULL, FALSE);
+ g_return_val_if_fail (msg != NULL, FALSE);
+
+ uri = soup_message_get_uri (msg);
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ // HSTS secures only HTTP connections.
+ if (uri->scheme != SOUP_URI_SCHEME_HTTP)
+ return FALSE;
+
+ domain = soup_uri_get_host (uri);
+
+ g_return_val_if_fail (domain != NULL, FALSE);
+
+ return soup_hsts_enforcer_must_enforce_secure_transport (hsts_enforcer, domain);
+}
+
+static void
+redirect_to_https (SoupMessage *msg)
+{
+ SoupURI *src_uri, *dst_uri;
+ char *dst;
+
+ src_uri = soup_message_get_uri (msg);
+
+ dst_uri = soup_uri_copy (src_uri);
+ soup_uri_set_scheme (dst_uri, SOUP_URI_SCHEME_HTTPS);
+ dst = soup_uri_to_string (dst_uri, FALSE);
+ soup_uri_free (dst_uri);
+
+ soup_message_set_redirect (msg, 301, dst);
+ g_free (dst);
+}
+
+static void
+process_sts_header (SoupMessage *msg, gpointer user_data)
+{
+ SoupHstsEnforcer *hsts_enforcer = SOUP_HSTS_ENFORCER (user_data);
+
+ g_return_if_fail (hsts_enforcer != NULL);
+ g_return_if_fail (msg != NULL);
+
+ soup_hsts_enforcer_process_sts_header (hsts_enforcer, msg);
+}
+
+static void
+soup_hsts_enforcer_request_queued (SoupSessionFeature *feature,
+ SoupSession *session,
+ SoupMessage *msg)
+{
+ SoupHstsEnforcer *hsts_enforcer = SOUP_HSTS_ENFORCER (feature);
+ SoupURI *uri;
+ const char *scheme;
+
+ g_return_if_fail (hsts_enforcer != NULL);
+ g_return_if_fail (msg != NULL);
+
+ uri = soup_message_get_uri (msg);
+
+ g_return_if_fail (uri != NULL);
+
+ scheme = soup_uri_get_scheme (uri);
+
+ if (scheme == SOUP_URI_SCHEME_HTTP) {
+ if (soup_hsts_enforcer_should_redirect_to_https (hsts_enforcer, msg))
+ redirect_to_https (msg);
+ }
+ else if (scheme == SOUP_URI_SCHEME_HTTPS) {
+ soup_message_add_header_handler (msg, "got-headers",
+ "Strict-Transport-Security",
+ G_CALLBACK (process_sts_header),
+ hsts_enforcer);
+ }
+}
+
+static void
+soup_hsts_enforcer_request_unqueued (SoupSessionFeature *feature,
+ SoupSession *session,
+ SoupMessage *msg)
+{
+ g_signal_handlers_disconnect_by_func (msg, process_sts_header, feature);
+}
+
+static void
+soup_hsts_enforcer_session_feature_init (SoupSessionFeatureInterface *feature_interface,
+ gpointer interface_data)
+{
+ feature_interface->request_queued = soup_hsts_enforcer_request_queued;
+ feature_interface->request_unqueued = soup_hsts_enforcer_request_unqueued;
+}
+
+/**
+ * soup_hsts_enforcer_is_persistent:
+ * @hsts_enforcer: a #SoupHstsEnforcer
+ *
+ * Gets whether @hsts_enforcer stores policies persistenly.
+ *
+ * Returns: %TRUE if @hsts_enforcer storage is persistent or %FALSE otherwise.
+ *
+ * Since: 2.54
+ **/
+gboolean
+soup_hsts_enforcer_is_persistent (SoupHstsEnforcer *hsts_enforcer)
+{
+ g_return_val_if_fail (SOUP_IS_HSTS_ENFORCER (hsts_enforcer), FALSE);
+
+ return SOUP_HSTS_ENFORCER_GET_CLASS (hsts_enforcer)->is_persistent (hsts_enforcer);
+}
diff --git a/libsoup/soup-hsts-enforcer.h b/libsoup/soup-hsts-enforcer.h
new file mode 100644
index 00000000..1253e234
--- /dev/null
+++ b/libsoup/soup-hsts-enforcer.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifndef SOUP_HSTS_ENFORCER_H
+#define SOUP_HSTS_ENFORCER_H 1
+
+#include <libsoup/soup-types.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_HSTS_ENFORCER (soup_hsts_enforcer_get_type ())
+#define SOUP_HSTS_ENFORCER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_HSTS_ENFORCER, SoupHstsEnforcer))
+#define SOUP_HSTS_ENFORCER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_HSTS_ENFORCER, SoupHstsEnforcerClass))
+#define SOUP_IS_HSTS_ENFORCER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_HSTS_ENFORCER))
+#define SOUP_IS_HSTS_ENFORCER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_HSTS_ENFORCER))
+#define SOUP_HSTS_ENFORCER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_HSTS_ENFORCER, SoupHstsEnforcerClass))
+
+struct _SoupHstsEnforcer {
+ GObject parent;
+
+};
+
+typedef struct {
+ GObjectClass parent_class;
+
+ gboolean (*is_persistent) (SoupHstsEnforcer *hsts_enforcer);
+
+ /* signals */
+ void (*changed) (SoupHstsEnforcer *jar,
+ SoupHstsPolicy *old_policy,
+ SoupHstsPolicy *new_policy);
+
+ /* Padding for future expansion */
+ void (*_libsoup_reserved1) (void);
+ void (*_libsoup_reserved2) (void);
+} SoupHstsEnforcerClass;
+
+SOUP_AVAILABLE_IN_2_54
+GType soup_hsts_enforcer_get_type (void);
+SOUP_AVAILABLE_IN_2_54
+SoupHstsEnforcer *soup_hsts_enforcer_new (void);
+SOUP_AVAILABLE_IN_2_54
+gboolean soup_hsts_enforcer_is_persistent (SoupHstsEnforcer *hsts_enforcer);
+
+SOUP_AVAILABLE_IN_2_54
+void soup_hsts_enforcer_set_session_policy (SoupHstsEnforcer *hsts_enforcer,
+ const char *domain,
+ gboolean include_sub_domains);
+G_END_DECLS
+
+#endif /* SOUP_HSTS_ENFORCER_H */
diff --git a/libsoup/soup-hsts-policy.c b/libsoup/soup-hsts-policy.c
new file mode 100644
index 00000000..e2989dbb
--- /dev/null
+++ b/libsoup/soup-hsts-policy.c
@@ -0,0 +1,479 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-hsts-policy.c
+ *
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "soup-hsts-policy.h"
+#include "soup.h"
+
+/**
+ * SECTION:soup-hsts-policy
+ * @short_description: HTTP Strict Transport Security policies
+ * @see_also: #SoupHstsEnforcer
+ *
+ * #SoupHstsPolicy implements HTTP policies, as described by <ulink
+ * url="http://tools.ietf.org/html/rfc6797">RFC 6797</ulink>.
+ *
+ * To have a #SoupSession handle HSTS policies for your appliction
+ * automatically, use a #SoupHstsEnforcer.
+ **/
+
+/**
+ * SoupHstsPolicy:
+ * @domain: the "domain" attribute, or else the hostname that the
+ * policy came from.
+ * @expires: the policy expiration time, or %NULL for a session policy
+ * @include_sub_domains: %TRUE if the policy applies on sub domains
+ *
+ * An HTTP Strict Transport Security policy.
+ *
+ * @domain give the host or domain that this policy belongs to and applies
+ * on.
+ *
+ * @expires will be non-%NULL if the policy has been set by the host and
+ * hence has an expiry time. If @expires is %NULL, it indicates that the
+ * policy is a session policy set by the user agent.
+ *
+ * If @include_sub_domains is set, the strict transport security policy
+ * must also be enforced on all subdomains of @domain.
+ *
+ * Since: 2.54
+ **/
+
+G_DEFINE_BOXED_TYPE (SoupHstsPolicy, soup_hsts_policy, soup_hsts_policy_copy, soup_hsts_policy_free)
+
+/**
+ * soup_hsts_policy_copy:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Copies @policy.
+ *
+ * Return value: a copy of @policy
+ *
+ * Since: 2.54
+ **/
+SoupHstsPolicy *
+soup_hsts_policy_copy (SoupHstsPolicy *policy)
+{
+ SoupHstsPolicy *copy = g_slice_new0 (SoupHstsPolicy);
+
+ copy->domain = g_strdup (policy->domain);
+ copy->expires = policy->expires ? soup_date_copy(policy->expires)
+ : NULL;
+ copy->include_sub_domains = policy->include_sub_domains;
+
+ return copy;
+}
+
+/**
+ * soup_hsts_policy_equal:
+ * @policy1: a #SoupCookie
+ * @policy2: a #SoupCookie
+ *
+ * Tests if @policy1 and @policy2 are equal.
+ *
+ * Note that currently, this does not check that the cookie domains
+ * match. This may change in the future.
+ *
+ * Return value: whether the cookies are equal.
+ *
+ * Since: 2.24
+ */
+gboolean
+soup_hsts_policy_equal (SoupHstsPolicy *policy1, SoupHstsPolicy *policy2)
+{
+ g_return_val_if_fail (policy1, FALSE);
+ g_return_val_if_fail (policy2, FALSE);
+
+ if (strcmp (policy1->domain, policy2->domain))
+ return FALSE;
+
+ if (policy1->include_sub_domains != policy2->include_sub_domains)
+ return FALSE;
+
+ if ((policy1->expires && !policy2->expires) ||
+ (!policy1->expires && policy2->expires))
+ return FALSE;
+
+ if (policy1->expires && policy2->expires &&
+ soup_date_to_time_t (policy1->expires) !=
+ soup_date_to_time_t (policy2->expires))
+ return FALSE;
+
+ return TRUE;
+}
+
+static inline const char *
+skip_lws (const char *s)
+{
+ while (g_ascii_isspace (*s))
+ s++;
+ return s;
+}
+
+static inline const char *
+unskip_lws (const char *s, const char *start)
+{
+ while (s > start && g_ascii_isspace (*(s - 1)))
+ s--;
+ return s;
+}
+
+#define is_attr_ender(ch) ((ch) < ' ' || (ch) == ';' || (ch) == ',' || (ch) == '=')
+#define is_value_ender(ch) ((ch) < ' ' || (ch) == ';')
+
+static char *
+parse_value (const char **val_p, gboolean copy)
+{
+ const char *start, *end, *p;
+ char *value;
+
+ p = *val_p;
+ if (*p == '=')
+ p++;
+ start = skip_lws (p);
+ for (p = start; !is_value_ender (*p); p++)
+ ;
+ end = unskip_lws (p, start);
+
+ if (copy)
+ value = g_strndup (start, end - start);
+ else
+ value = NULL;
+
+ *val_p = p;
+ return value;
+}
+
+static SoupHstsPolicy *
+parse_one_policy (const char *header, SoupURI *origin)
+{
+ const char *start, *end, *p;
+ gboolean has_value;
+ long max_age = -1;
+ gboolean include_sub_domains = FALSE;
+
+ g_return_val_if_fail (origin == NULL || origin->host, NULL);
+
+ p = start = skip_lws (header);
+
+ /* Parse directives */
+ do {
+ if (*p == ';')
+ p++;
+
+ start = skip_lws (p);
+ for (p = start; !is_attr_ender (*p); p++)
+ ;
+ end = unskip_lws (p, start);
+
+ has_value = (*p == '=');
+#define MATCH_NAME(name) ((end - start == strlen (name)) && !g_ascii_strncasecmp (start, name, end - start))
+
+ if (MATCH_NAME ("max-age") && has_value) {
+ char *max_age_str, *max_age_end;
+
+ /* Repeated directives make the policy invalid. */
+ if (max_age >= 0)
+ goto fail;
+
+ max_age_str = parse_value (&p, TRUE);
+ max_age = strtol (max_age_str, &max_age_end, 10);
+ g_free (max_age_str);
+
+ if (*max_age_end == '\0') {
+ /* Invalid 'max-age' directive makes the policy invalid. */
+ if (max_age < 0)
+ goto fail;
+ }
+ } else if (MATCH_NAME ("includeSubDomains")) {
+ /* Repeated directives make the policy invalid. */
+ if (include_sub_domains)
+ goto fail;
+
+ /* The 'includeSubDomains' directive can't have a value. */
+ if (has_value)
+ goto fail;
+
+ include_sub_domains = TRUE;
+ } else {
+ /* Unknown directives must be skipped. */
+ if (has_value)
+ parse_value (&p, FALSE);
+ }
+ } while (*p == ';');
+
+ /* No 'max-age' directive makes the policy invalid. */
+ if (max_age < 0)
+ goto fail;
+
+ return soup_hsts_policy_new_with_max_age (origin->host, max_age,
+ include_sub_domains);
+
+fail:
+ return NULL;
+}
+
+/**
+ * Return value: %TRUE if the hostname is suitable for an HSTS host, %FALSE
+ * otherwise.
+ **/
+static gboolean
+is_hostname_valid (const char *hostname)
+{
+ if (!hostname)
+ return FALSE;
+
+ /* Hostnames must have at least one '.'
+ */
+ if (!strchr (hostname, '.'))
+ return FALSE;
+
+ /* IP addresses are not valid hostnames, only domain names are.
+ */
+ if (g_hostname_is_ip_address (hostname))
+ return FALSE;
+
+ /* The hostname should be a valid domain name.
+ */
+ return TRUE;
+}
+
+/**
+ * soup_hsts_policy_new:
+ * @domain: policy domain or hostname
+ * @expires: (transfer full): the expiry date of the policy
+ * @include_sub_domains: %TRUE if the policy applies on sub domains
+ *
+ * Creates a new #SoupHstsPolicy with the given attributes.
+ *
+ * @domain is a domain on which the strict transport security policy
+ * represented by this object must be enforced.
+ *
+ * @expires is the date and time when the policy should be considered
+ * expired.
+ *
+ * If @include_sub_domains is %TRUE, the strict transport security policy
+ * must also be enforced on all subdomains of @domain.
+ *
+ * Return value: a new #SoupHstsPolicy.
+ *
+ * Since: 2.54
+ **/
+SoupHstsPolicy *
+soup_hsts_policy_new (const char *domain, SoupDate *expires,
+ gboolean include_sub_domains)
+{
+ SoupHstsPolicy *policy;
+
+ g_return_val_if_fail (is_hostname_valid (domain), NULL);
+
+ policy = g_slice_new0 (SoupHstsPolicy);
+ policy->domain = g_strdup (domain);
+ policy->expires = expires;
+ policy->include_sub_domains = include_sub_domains;
+
+ return policy;
+}
+
+/**
+ * soup_hsts_policy_new_with_max_age:
+ * @domain: policy domain or hostname
+ * @max_age: max age of the policy
+ * @include_sub_domains: %TRUE if the policy applies on sub domains
+ *
+ * Creates a new #SoupHstsPolicy with the given attributes.
+ *
+ * @domain is a domain on which the strict transport security policy
+ * represented by this object must be enforced.
+ *
+ * @max_age is used to set the "expires" attribute on the policy; pass
+ * SOUP_HSTS_POLICY_MAX_AGE_PAST for an already-expired policy, or a
+ * lifetime in seconds.
+ *
+ * If @include_sub_domains is %TRUE, the strict transport security policy
+ * must also be enforced on all subdomains of @domain.
+ *
+ * Return value: a new #SoupHstsPolicy.
+ *
+ * Since: 2.54
+ **/
+SoupHstsPolicy *
+soup_hsts_policy_new_with_max_age (const char *domain, int max_age,
+ gboolean include_sub_domains)
+{
+ SoupDate *expires;
+ SoupHstsPolicy *policy;
+
+ g_return_val_if_fail (is_hostname_valid (domain), NULL);
+ g_return_val_if_fail (max_age >= 0, NULL);
+
+ if (max_age == SOUP_HSTS_POLICY_MAX_AGE_PAST) {
+ /* Use a date way in the past, to protect against
+ * clock skew.
+ */
+ expires = soup_date_new (1970, 1, 1, 0, 0, 0);
+ } else
+ expires = soup_date_new_from_now (max_age);
+
+ policy = soup_hsts_policy_new (domain, expires, include_sub_domains);
+
+ if (!policy)
+ soup_date_free (expires);
+
+ return policy;
+}
+
+/**
+ * soup_hsts_policy_new_permanent:
+ * @domain: policy domain or hostname
+ * @include_sub_domains: %TRUE if the policy applies on sub domains
+ *
+ * Creates a new #SoupHstsPolicy with the given attributes.
+ *
+ * @domain is a domain on which the strict transport security policy
+ * represented by this object must be enforced.
+ *
+ * If @include_sub_domains is %TRUE, the strict transport security policy
+ * must also be enforced on all subdomains of @domain.
+ *
+ * Return value: a new #SoupHstsPolicy.
+ *
+ * Since: 2.54
+ **/
+SoupHstsPolicy *
+soup_hsts_policy_new_permanent (const char *domain,
+ gboolean include_sub_domains)
+{
+ return soup_hsts_policy_new (domain, NULL, include_sub_domains);
+}
+
+/**
+ * soup_hsts_policy_new_from_response:
+ * @msg: a #SoupMessage containing a "Strict-Transport-Security" response
+ * header
+ *
+ * Parses @msg's first "Strict-Transport-Security" response header and
+ * returns a #SoupHstsPolicy, or %NULL if no valid
+ * "Strict-Transport-Security" response header was found.
+ *
+ * Return value: (nullable): a new #SoupHstsPolicy, or %NULL if no valid
+ * "Strict-Transport-Security" response header was found.
+ *
+ * Since: 2.54
+ **/
+SoupHstsPolicy *
+soup_hsts_policy_new_from_response (SoupMessage *msg)
+{
+ SoupURI *origin;
+ const char *name, *value;
+ SoupMessageHeadersIter iter;
+
+ soup_message_headers_iter_init (&iter, msg->response_headers);
+ while (soup_message_headers_iter_next (&iter, &name, &value)) {
+ if (g_ascii_strcasecmp (name, "Strict-Transport-Security") != 0)
+ continue;
+
+ origin = soup_message_get_uri (msg);
+ return parse_one_policy (value, origin);
+ }
+
+ return NULL;
+}
+
+/**
+ * soup_hsts_policy_get_domain:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Gets @policy's domain.
+ *
+ * Return value: @policy's domain.
+ *
+ * Since: 2.54
+ **/
+const char *
+soup_hsts_policy_get_domain (SoupHstsPolicy *policy)
+{
+ return policy->domain;
+}
+
+/**
+ * soup_hsts_policy_is_expired:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Gets whether @policy is expired.
+ *
+ * Permanent policies never expire.
+ *
+ * Return value: whether @policy is expired.
+ *
+ * Since: 2.54
+ **/
+gboolean
+soup_hsts_policy_is_expired (SoupHstsPolicy *policy)
+{
+ return policy->expires && soup_date_is_past (policy->expires);
+}
+
+/**
+ * soup_hsts_policy_includes_sub_domains:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Gets whether @policy include its sub-domains.
+ *
+ * Return value: whether @policy include its sub-domains.
+ *
+ * Since: 2.54
+ **/
+gboolean
+soup_hsts_policy_includes_sub_domains (SoupHstsPolicy *policy)
+{
+ return policy->include_sub_domains;
+}
+
+/**
+ * soup_hsts_policy_is_permanent:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Gets whether @policy is permanent (not expirable).
+ *
+ * A permanent policy never expires and should not be saved by a persistent
+ * #SoupHstsEnforcer so the user agent can control them.
+ *
+ * Return value: whether @policy is permanent.
+ *
+ * Since: 2.54
+ **/
+gboolean
+soup_hsts_policy_is_permanent (SoupHstsPolicy *policy)
+{
+ return !policy->expires;
+}
+
+/**
+ * soup_hsts_policy_free:
+ * @policy: a #SoupHstsPolicy
+ *
+ * Frees @policy.
+ *
+ * Since: 2.54
+ **/
+void
+soup_hsts_policy_free (SoupHstsPolicy *policy)
+{
+ g_return_if_fail (policy != NULL);
+
+ g_free (policy->domain);
+ g_clear_pointer (&policy->expires, soup_date_free);
+
+ g_slice_free (SoupHstsPolicy, policy);
+}
diff --git a/libsoup/soup-hsts-policy.h b/libsoup/soup-hsts-policy.h
new file mode 100644
index 00000000..8492d4a9
--- /dev/null
+++ b/libsoup/soup-hsts-policy.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ */
+
+#ifndef SOUP_HSTS_POLICY_H
+#define SOUP_HSTS_POLICY_H 1
+
+#include <libsoup/soup-types.h>
+
+G_BEGIN_DECLS
+
+struct _SoupHstsPolicy {
+ char *domain;
+ SoupDate *expires;
+ gboolean include_sub_domains;
+};
+
+SOUP_AVAILABLE_IN_2_54
+GType soup_hsts_policy_get_type (void);
+#define SOUP_TYPE_HSTS_POLICY (soup_hsts_policy_get_type())
+
+#define SOUP_HSTS_POLICY_MAX_AGE_PAST (0)
+
+SOUP_AVAILABLE_IN_2_54
+SoupHstsPolicy *soup_hsts_policy_new (const char *domain,
+ SoupDate *expiry_date,
+ gboolean include_sub_domains);
+SOUP_AVAILABLE_IN_2_54
+SoupHstsPolicy *soup_hsts_policy_new_with_max_age (const char *domain,
+ int max_age,
+ gboolean include_sub_domains);
+SOUP_AVAILABLE_IN_2_54
+SoupHstsPolicy *soup_hsts_policy_new_permanent (const char *domain,
+ gboolean include_sub_domains);
+SOUP_AVAILABLE_IN_2_54
+SoupHstsPolicy *soup_hsts_policy_new_from_response (SoupMessage *msg);
+
+SOUP_AVAILABLE_IN_2_54
+SoupHstsPolicy *soup_hsts_policy_copy (SoupHstsPolicy *policy);
+SOUP_AVAILABLE_IN_2_54
+gboolean soup_hsts_policy_equal (SoupHstsPolicy *policy1,
+ SoupHstsPolicy *policy2);
+
+SOUP_AVAILABLE_IN_2_54
+const char *soup_hsts_policy_get_domain (SoupHstsPolicy *policy);
+SOUP_AVAILABLE_IN_2_54
+gboolean soup_hsts_policy_is_expired (SoupHstsPolicy *policy);
+SOUP_AVAILABLE_IN_2_54
+gboolean soup_hsts_policy_includes_sub_domains (SoupHstsPolicy *policy);
+SOUP_AVAILABLE_IN_2_54
+gboolean soup_hsts_policy_is_permanent (SoupHstsPolicy *policy);
+
+SOUP_AVAILABLE_IN_2_54
+void soup_hsts_policy_free (SoupHstsPolicy *policy);
+
+G_END_DECLS
+
+#endif /* SOUP_HSTS_POLICY_H */
diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h
index e020de7d..5bd5b285 100644
--- a/libsoup/soup-types.h
+++ b/libsoup/soup-types.h
@@ -19,6 +19,8 @@ typedef struct _SoupAuthDomain SoupAuthDomain;
typedef struct _SoupCookie SoupCookie;
typedef struct _SoupCookieJar SoupCookieJar;
typedef struct _SoupDate SoupDate;
+typedef struct _SoupHstsEnforcer SoupHstsEnforcer;
+typedef struct _SoupHstsPolicy SoupHstsPolicy;
typedef struct _SoupMessage SoupMessage;
typedef struct _SoupRequest SoupRequest;
typedef struct _SoupRequestHTTP SoupRequestHTTP;
diff --git a/libsoup/soup.h b/libsoup/soup.h
index 6bedb624..711cccb4 100644
--- a/libsoup/soup.h
+++ b/libsoup/soup.h
@@ -29,6 +29,9 @@ extern "C" {
#include <libsoup/soup-enum-types.h>
#include <libsoup/soup-form.h>
#include <libsoup/soup-headers.h>
+#include <libsoup/soup-hsts-enforcer.h>
+#include <libsoup/soup-hsts-enforcer-db.h>
+#include <libsoup/soup-hsts-policy.h>
#include <libsoup/soup-logger.h>
#include <libsoup/soup-message.h>
#include <libsoup/soup-method.h>