View | Details | Raw Unified | Return to bug 59179
Collapse All | Expand All

(-)conf/web.xml (+27 lines)
Lines 436-441 Link Here
436
  <!--                       Should the includeSubDomains parameter be      -->
436
  <!--                       Should the includeSubDomains parameter be      -->
437
  <!--                       included in the HSTS header.                   -->
437
  <!--                       included in the HSTS header.                   -->
438
  <!--                                                                      -->
438
  <!--                                                                      -->
439
  <!--   hpkpEnabled         Should the HTTP Public Key Pinning (HPKP)      -->
440
  <!--                       header be added to the response? See RFC 7469  -->
441
  <!--                       for more information on HPKP. [false]          -->
442
  <!--                                                                      -->
443
  <!--   hpkpReportOnly      Should a HPKP "report only" header be set      -->
444
  <!--                       instead of a HPKP "enforcing" header? [false]  -->
445
  <!--                                                                      -->
446
  <!--   hpkpMaxAgeSeconds   The max age value that should be used in the   -->
447
  <!--                       HPKP header. Negative values will be treated   -->
448
  <!--                       as zero. [0]                                   -->
449
  <!--                                                                      -->
450
  <!--   hpkpIncludeSubDomains                                              -->
451
  <!--                       Should the includeSubDomains parameter be      -->
452
  <!--                       included in the HPKP header. [false]           -->
453
  <!--                                                                      -->
454
  <!--   hpkpReportUri       The URI that should be used in the HPKP        -->
455
  <!--                       header's report URI directive. []              -->
456
  <!--                                                                      -->
457
  <!--   hpkpPins            A comma separated list of values specifying    -->
458
  <!--                       the HPKP pins. Values must occur in pairs. The -->
459
  <!--                       first value of each pair is the hash           -->
460
  <!--                       algorithm, and the second value is a sequence  -->
461
  <!--                       of Base64 digits representing an according     -->
462
  <!--                       SPKI fingerprint. Whitespace after each comma  -->
463
  <!--                       is allowed. If not specified, the directive    -->
464
  <!--                       will be omitted in the HPKP header. []         -->
465
  <!--                                                                      -->
439
  <!--   antiClickJackingEnabled                                            -->
466
  <!--   antiClickJackingEnabled                                            -->
440
  <!--                       Should the anti click-jacking header           -->
467
  <!--                       Should the anti click-jacking header           -->
441
  <!--                       X-Frame-Options be added to every response?    -->
468
  <!--                       X-Frame-Options be added to every response?    -->
(-)java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java (+110 lines)
Lines 45-50 Link Here
45
    private boolean hstsIncludeSubDomains = false;
45
    private boolean hstsIncludeSubDomains = false;
46
    private String hstsHeaderValue;
46
    private String hstsHeaderValue;
47
47
48
    // HPKP
49
    private static final String HPKP_HEADER_NAME = "Public-Key-Pins";
50
    private static final String HPKP_RO_HEADER_NAME = "Public-Key-Pins-Report-Only";
51
    private boolean hpkpEnabled = false;
52
    private boolean hpkpReportOnly = false;
53
    private int hpkpMaxAgeSeconds = 0;
54
    private boolean hpkpIncludeSubDomains = false;
55
    private String hpkpReportUri = null;
56
    private String hpkpPins = null;
57
    private String hpkpHeaderValue;
58
48
    // Click-jacking protection
59
    // Click-jacking protection
49
    private static final String ANTI_CLICK_JACKING_HEADER_NAME = "X-Frame-Options";
60
    private static final String ANTI_CLICK_JACKING_HEADER_NAME = "X-Frame-Options";
50
    private boolean antiClickJackingEnabled = true;
61
    private boolean antiClickJackingEnabled = true;
Lines 74-79 Link Here
74
        }
85
        }
75
        hstsHeaderValue = hstsValue.toString();
86
        hstsHeaderValue = hstsValue.toString();
76
87
88
        // Build HPKP header value
89
        StringBuilder hpkpValue = new StringBuilder("max-age=");
90
        hpkpValue.append(hpkpMaxAgeSeconds);
91
        if (hpkpIncludeSubDomains) {
92
            hpkpValue.append("; includeSubDomains");
93
        }
94
        if (hpkpReportUri != null) {
95
            hpkpValue.append("; report-uri=\"");
96
            hpkpValue.append(hpkpReportUri);
97
            hpkpValue.append("\"");
98
        }
99
        if (hpkpPins != null) {
100
            String[] hpkpPinArray = hpkpPins.split(",\\s*");
101
            String hpkpHashType, hpkpHashValue;
102
            for (int i = 0; i < hpkpPinArray.length / 2; i++) {
103
                hpkpHashType = hpkpPinArray[2 * i];
104
                hpkpHashValue = hpkpPinArray[2 * i + 1];
105
                hpkpValue.append("; pin-");
106
                hpkpValue.append(hpkpHashType);
107
                hpkpValue.append("");
108
                hpkpValue.append("=\"");
109
                hpkpValue.append(hpkpHashValue);
110
                hpkpValue.append("\"");
111
            }
112
        }
113
        hpkpHeaderValue = hpkpValue.toString();
114
77
        // Anti click-jacking
115
        // Anti click-jacking
78
        StringBuilder cjValue = new StringBuilder(antiClickJackingOption.headerValue);
116
        StringBuilder cjValue = new StringBuilder(antiClickJackingOption.headerValue);
79
        if (antiClickJackingOption == XFrameOption.ALLOW_FROM) {
117
        if (antiClickJackingOption == XFrameOption.ALLOW_FROM) {
Lines 100-105 Link Here
100
                httpResponse.setHeader(HSTS_HEADER_NAME, hstsHeaderValue);
138
                httpResponse.setHeader(HSTS_HEADER_NAME, hstsHeaderValue);
101
            }
139
            }
102
140
141
            // HPKP
142
            if (hpkpEnabled && request.isSecure()) {
143
                if (hpkpReportOnly) {
144
                    httpResponse.setHeader(HPKP_RO_HEADER_NAME, hpkpHeaderValue);
145
                } else {
146
                    httpResponse.setHeader(HPKP_HEADER_NAME, hpkpHeaderValue);
147
                }
148
            }
149
103
            // anti click-jacking
150
            // anti click-jacking
104
            if (antiClickJackingEnabled) {
151
            if (antiClickJackingEnabled) {
105
                httpResponse.setHeader(ANTI_CLICK_JACKING_HEADER_NAME, antiClickJackingHeaderValue);
152
                httpResponse.setHeader(ANTI_CLICK_JACKING_HEADER_NAME, antiClickJackingHeaderValue);
Lines 169-175 Link Here
169
    }
216
    }
170
217
171
218
219
    public boolean isHpkpEnabled() {
220
        return hpkpEnabled;
221
    }
172
222
223
224
    public void setHpkpEnabled(boolean hpkpEnabled) {
225
        this.hpkpEnabled = hpkpEnabled;
226
    }
227
228
229
    public boolean isHpkpReportOnly() {
230
        return hpkpReportOnly;
231
    }
232
233
234
    public void setHpkpReportOnly(boolean hpkpReportOnly) {
235
        this.hpkpReportOnly = hpkpReportOnly;
236
    }
237
238
239
    public int getHpkpMaxAgeSeconds() {
240
        return hpkpMaxAgeSeconds;
241
    }
242
243
244
    public void setHpkpMaxAgeSeconds(int hpkpMaxAgeSeconds) {
245
        if (hpkpMaxAgeSeconds < 0) {
246
            this.hpkpMaxAgeSeconds = 0;
247
        } else {
248
            this.hpkpMaxAgeSeconds = hpkpMaxAgeSeconds;
249
        }
250
    }
251
252
253
    public boolean isHpkpIncludeSubDomains() {
254
        return hpkpIncludeSubDomains;
255
    }
256
257
258
    public void setHpkpIncludeSubDomains(boolean hpkpIncludeSubDomains) {
259
        this.hpkpIncludeSubDomains = hpkpIncludeSubDomains;
260
    }
261
262
263
    public String getHpkpReportUri() {
264
        return this.hpkpReportUri;
265
    }
266
267
268
    public void setHpkpReportUri(String hpkpReportUri) {
269
        this.hpkpReportUri = hpkpReportUri;
270
    }
271
272
273
    public String getHpkpPins() {
274
        return this.hpkpPins;
275
    }
276
277
278
    public void setHpkpPins(String hpkpPins) {
279
        this.hpkpPins = hpkpPins;
280
    }
281
282
173
    public boolean isAntiClickJackingEnabled() {
283
    public boolean isAntiClickJackingEnabled() {
174
        return antiClickJackingEnabled;
284
        return antiClickJackingEnabled;
175
    }
285
    }
(-)webapps/docs/config/filter.xml (+45 lines)
Lines 899-904 Link Here
899
        be used.</p>
899
        be used.</p>
900
      </attribute>
900
      </attribute>
901
901
902
      <attribute name="hpkpEnabled" required="false">
903
        <p>Will an HTTP Public Key Pinning (HPKP) header (either
904
        <code>Public-Key-Pins</code> or
905
        <code>Public-Key-Pins-Report-Only</code>) be set on the response for
906
        secure requests. Any HPKP header already present will be replaced. See
907
        <a href="http://tools.ietf.org/html/rfc7469">RFC 7469</a> for further
908
        details of HPKP. If not specified, the default value of
909
        <code>false</code> will be used.</p>
910
      </attribute>
911
912
      <attribute name="hpkpReportOnly" required="false">
913
        <p>Will a HPKP "report only" header
914
        (<code>Public-Key-Pins-Report-Only</code>) be set instead of a HPKP
915
        "enforcing" header (<code>Public-Key-Pins</code>). If not specified,
916
        the default value of <code>false</code> will be used.
917
        </p>
918
      </attribute>
919
920
      <attribute name="hpkpMaxAgeSeconds" required="false">
921
        <p>The max age value that should be used in the HPKP header. Negative
922
        values will be treated as zero. If not specified, the default value of
923
        <code>0</code> will be used.</p>
924
      </attribute>
925
926
      <attribute name="hpkpIncludeSubDomains" required="false">
927
        <p>Should the includeSubDomains parameter be included in the HSTS
928
        header. If not specified, the default value of <code>false</code> will
929
        be used.</p>
930
      </attribute>
931
932
      <attribute name="hpkpReportUri" required="false">
933
        <p>The URI that should be used in the HPKP header's report URI
934
        directive (<code>report-uri</code>). If not specified, the directive
935
        will be omitted in the HPKP header.</p>
936
      </attribute>
937
938
      <attribute name="hpkpPins" required="false">
939
        <p>A comma separated list of values specifying the HPKP pins. Values
940
        must occur in pairs. The first value of each pair is the hash
941
        algorithm (<code>sha256</code>), and the second value is a sequence of
942
        Base64 digits representing an according SPKI fingerprint. Whitespace
943
        after each comma is allowed. If not specified, the directive will be
944
        omitted in the HPKP header.</p>
945
      </attribute>
946
902
      <attribute name="antiClickJackingEnabled" required="false">
947
      <attribute name="antiClickJackingEnabled" required="false">
903
        <p>Should the anti click-jacking header (<code>X-Frame-Options</code>)
948
        <p>Should the anti click-jacking header (<code>X-Frame-Options</code>)
904
        be set on the response. Any anti click-jacking header already present
949
        be set on the response. Any anti click-jacking header already present

Return to bug 59179