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

(-)conf/web.xml (+24 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
  <!--   hpkpMaxAgeSeconds   The max age value that should be used in the   -->
444
  <!--                       HPKP header. Negative values will be treated   -->
445
  <!--                       as zero. [0]                                   -->
446
  <!--                                                                      -->
447
  <!--   hpkpIncludeSubDomains                                              -->
448
  <!--                       Should the includeSubDomains parameter be      -->
449
  <!--                       included in the HPKP header. [false]           -->
450
  <!--                                                                      -->
451
  <!--   hpkpReportUri       The URI that should be used in the HPKP        -->
452
  <!--                       header's report URI directive. []              -->
453
  <!--                                                                      -->
454
  <!--   hpkpPins            A comma separated list of values specifying    -->
455
  <!--                       the HPKP pins. Values must occur in pairs. The -->
456
  <!--                       first value of each pair is the hash           -->
457
  <!--                       algorithm, and the second value is a sequence  -->
458
  <!--                       of Base64 digits representing an according     -->
459
  <!--                       SPKI fingerprint. Whitespace after each comma  -->
460
  <!--                       is allowed. If not specified, the directive    -->
461
  <!--                       will be omitted in the HPKP header. []         -->
462
  <!--                                                                      -->
439
  <!--   antiClickJackingEnabled                                            -->
463
  <!--   antiClickJackingEnabled                                            -->
440
  <!--                       Should the anti click-jacking header           -->
464
  <!--                       Should the anti click-jacking header           -->
441
  <!--                       X-Frame-Options be added to every response?    -->
465
  <!--                       X-Frame-Options be added to every response?    -->
(-)java/org/apache/catalina/filters/HttpHeaderSecurityFilter.java (-4 / +122 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 HpkpEnabled hpkpEnabled = HpkpEnabled.FALSE;
52
    private int hpkpMaxAgeSeconds = 0;
53
    private boolean hpkpIncludeSubDomains = false;
54
    private String hpkpReportUri = null;
55
    private String hpkpPins = null;
56
    private String hpkpHeaderValue;
57
48
    // Click-jacking protection
58
    // Click-jacking protection
49
    private static final String ANTI_CLICK_JACKING_HEADER_NAME = "X-Frame-Options";
59
    private static final String ANTI_CLICK_JACKING_HEADER_NAME = "X-Frame-Options";
50
    private boolean antiClickJackingEnabled = true;
60
    private boolean antiClickJackingEnabled = true;
Lines 74-79 Link Here
74
        }
84
        }
75
        hstsHeaderValue = hstsValue.toString();
85
        hstsHeaderValue = hstsValue.toString();
76
86
87
        // Build HPKP header value
88
        StringBuilder hpkpValue = new StringBuilder("max-age=");
89
        hpkpValue.append(hpkpMaxAgeSeconds);
90
        if (hpkpIncludeSubDomains) {
91
            hpkpValue.append("; includeSubDomains");
92
        }
93
        if (hpkpReportUri != null) {
94
            hpkpValue.append("; report-uri=\"");
95
            hpkpValue.append(hpkpReportUri);
96
            hpkpValue.append("\"");
97
        }
98
        if (hpkpPins != null) {
99
            String[] hpkpPinArray = hpkpPins.split(",\\s*");
100
            String hpkpHashType, hpkpHashValue;
101
            for (int i = 0; i < hpkpPinArray.length / 2; i++) {
102
                hpkpHashType = hpkpPinArray[2 * i];
103
                hpkpHashValue = hpkpPinArray[2 * i + 1];
104
                hpkpValue.append("; pin-");
105
                hpkpValue.append(hpkpHashType);
106
                hpkpValue.append("");
107
                hpkpValue.append("=\"");
108
                hpkpValue.append(hpkpHashValue);
109
                hpkpValue.append("\"");
110
            }
111
        }
112
        hpkpHeaderValue = hpkpValue.toString();
113
77
        // Anti click-jacking
114
        // Anti click-jacking
78
        StringBuilder cjValue = new StringBuilder(antiClickJackingOption.headerValue);
115
        StringBuilder cjValue = new StringBuilder(antiClickJackingOption.headerValue);
79
        if (antiClickJackingOption == XFrameOption.ALLOW_FROM) {
116
        if (antiClickJackingOption == XFrameOption.ALLOW_FROM) {
Lines 95-103 Link Here
95
                throw new ServletException(sm.getString("httpHeaderSecurityFilter.committed"));
132
                throw new ServletException(sm.getString("httpHeaderSecurityFilter.committed"));
96
            }
133
            }
97
134
98
            // HSTS
135
            if(request.isSecure()) {
99
            if (hstsEnabled && request.isSecure()) {
136
                // HSTS
100
                httpResponse.setHeader(HSTS_HEADER_NAME, hstsHeaderValue);
137
                if (hstsEnabled) {
138
                    httpResponse.setHeader(HSTS_HEADER_NAME, hstsHeaderValue);
139
                }
140
141
                // HPKP
142
                if (hpkpEnabled == HpkpEnabled.REPORT_ONLY) {
143
                    httpResponse.setHeader(HPKP_RO_HEADER_NAME, hpkpHeaderValue);
144
                } else if (hpkpEnabled == HpkpEnabled.TRUE) {
145
                    httpResponse.setHeader(HPKP_HEADER_NAME, hpkpHeaderValue);
146
                }
101
            }
147
            }
102
148
103
            // anti click-jacking
149
            // anti click-jacking
Lines 169-175 Link Here
169
    }
215
    }
170
216
171
217
218
    public HpkpEnabled getHpkpEnabled() {
219
        return hpkpEnabled;
220
    }
172
221
222
223
    public void setHpkpEnabled(String hpkpEnabled){
224
        this.hpkpEnabled = HpkpEnabled.parse(hpkpEnabled);
225
    }
226
227
228
    public int getHpkpMaxAgeSeconds() {
229
        return hpkpMaxAgeSeconds;
230
    }
231
232
233
    public void setHpkpMaxAgeSeconds(int hpkpMaxAgeSeconds) {
234
        if (hpkpMaxAgeSeconds < 0) {
235
            this.hpkpMaxAgeSeconds = 0;
236
        } else {
237
            this.hpkpMaxAgeSeconds = hpkpMaxAgeSeconds;
238
        }
239
    }
240
241
242
    public boolean isHpkpIncludeSubDomains() {
243
        return hpkpIncludeSubDomains;
244
    }
245
246
247
    public void setHpkpIncludeSubDomains(boolean hpkpIncludeSubDomains) {
248
        this.hpkpIncludeSubDomains = hpkpIncludeSubDomains;
249
    }
250
251
252
    public String getHpkpReportUri() {
253
        return this.hpkpReportUri;
254
    }
255
256
257
    public void setHpkpReportUri(String hpkpReportUri) {
258
        this.hpkpReportUri = hpkpReportUri;
259
    }
260
261
262
    public String getHpkpPins() {
263
        return this.hpkpPins;
264
    }
265
266
267
    public void setHpkpPins(String hpkpPins) {
268
        this.hpkpPins = hpkpPins;
269
    }
270
271
173
    public boolean isAntiClickJackingEnabled() {
272
    public boolean isAntiClickJackingEnabled() {
174
        return antiClickJackingEnabled;
273
        return antiClickJackingEnabled;
175
    }
274
    }
Lines 199-205 Link Here
199
    }
298
    }
200
299
201
300
202
203
    public String getAntiClickJackingUri() {
301
    public String getAntiClickJackingUri() {
204
        return antiClickJackingUri.toString();
302
        return antiClickJackingUri.toString();
205
    }
303
    }
Lines 250-253 Link Here
250
            return headerValue;
348
            return headerValue;
251
        }
349
        }
252
    }
350
    }
351
352
    private enum HpkpEnabled {
353
        TRUE,
354
        FALSE,
355
        REPORT_ONLY;
356
357
        public static HpkpEnabled parse(String value){
358
            switch(value.toLowerCase()){
359
                case "true" :
360
                    return TRUE;
361
                case "false" :
362
                    return FALSE;
363
                case "reportonly" :
364
                    return REPORT_ONLY;
365
                default:
366
                    throw new IllegalArgumentException(sm.getString(
367
                        "httpHeaderSecurityFilter.hpkpenabled.invalid", value));
368
            }
369
        }
370
    }
253
}
371
}
(-)java/org/apache/catalina/filters/LocalStrings.properties (+1 lines)
Lines 46-50 Link Here
46
46
47
httpHeaderSecurityFilter.committed=Unable to add HTTP headers since response is already committed on entry to the HTTP header security Filter
47
httpHeaderSecurityFilter.committed=Unable to add HTTP headers since response is already committed on entry to the HTTP header security Filter
48
httpHeaderSecurityFilter.clickjack.invalid=An invalid value [{0}] was specified for the anti click-jacking header
48
httpHeaderSecurityFilter.clickjack.invalid=An invalid value [{0}] was specified for the anti click-jacking header
49
httpHeaderSecurityFilter.hpkpenabled.invalid=An invalid value [{0}] was specified for the hpkpEnabled attribute
49
50
50
restCsrfPreventionFilter.invalidNonce=CSRF nonce validation failed
51
restCsrfPreventionFilter.invalidNonce=CSRF nonce validation failed
(-)webapps/docs/config/filter.xml (+38 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. there's three possible values, true, false and
909
        reportOnly (case insensitive), If not specified, the default value of
910
        <code>false</code> will be used.</p>
911
      </attribute>
912
913
      <attribute name="hpkpMaxAgeSeconds" required="false">
914
        <p>The max age value that should be used in the HPKP header. Negative
915
        values will be treated as zero. If not specified, the default value of
916
        <code>0</code> will be used.</p>
917
      </attribute>
918
919
      <attribute name="hpkpIncludeSubDomains" required="false">
920
        <p>Should the includeSubDomains parameter be included in the HSTS
921
        header. If not specified, the default value of <code>false</code> will
922
        be used.</p>
923
      </attribute>
924
925
      <attribute name="hpkpReportUri" required="false">
926
        <p>The URI that should be used in the HPKP header's report URI
927
        directive (<code>report-uri</code>). If not specified, the directive
928
        will be omitted in the HPKP header.</p>
929
      </attribute>
930
931
      <attribute name="hpkpPins" required="false">
932
        <p>A comma separated list of values specifying the HPKP pins. Values
933
        must occur in pairs. The first value of each pair is the hash
934
        algorithm (<code>sha256</code>), and the second value is a sequence of
935
        Base64 digits representing an according SPKI fingerprint. Whitespace
936
        after each comma is allowed. If not specified, the directive will be
937
        omitted in the HPKP header.</p>
938
      </attribute>
939
902
      <attribute name="antiClickJackingEnabled" required="false">
940
      <attribute name="antiClickJackingEnabled" required="false">
903
        <p>Should the anti click-jacking header (<code>X-Frame-Options</code>)
941
        <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
942
        be set on the response. Any anti click-jacking header already present

Return to bug 59179