(Request request, Response response)
| 212 | |
| 213 | |
| 214 | @Override |
| 215 | public void invoke(Request request, Response response) throws IOException, ServletException { |
| 216 | /* |
| 217 | * Known behaviours of reverse proxies that are handled by the processing below: - mod_header converts the '\n' |
| 218 | * into ' ' - nginx converts the '\n' into multiple ' ' - nginx ssl_client_escaped_cert uses "uri component" |
| 219 | * escaping, keeping only ALPHA, DIGIT, "-", ".", "_", "~" |
| 220 | * |
| 221 | * The code assumes that the trimmed header value starts with '-----BEGIN CERTIFICATE-----' and ends with |
| 222 | * '-----END CERTIFICATE-----'. |
| 223 | * |
| 224 | * Note: As long as the BEGIN marker and the rest of the content are on separate lines, the CertificateFactory |
| 225 | * is tolerant of any additional whitespace. |
| 226 | */ |
| 227 | String headerValue; |
| 228 | String headerEscapedValue = mygetHeader(request, sslClientEscapedCertHeader); |
| 229 | if (headerEscapedValue != null) { |
| 230 | headerValue = UDecoder.URLDecode(headerEscapedValue, null); |
| 231 | } else { |
| 232 | headerValue = mygetHeader(request, sslClientCertHeader); |
| 233 | } |
| 234 | if (headerValue != null) { |
| 235 | headerValue = headerValue.trim(); |
| 236 | if (headerValue.length() > 27) { |
| 237 | String body = headerValue.substring(27); |
| 238 | String header = "-----BEGIN CERTIFICATE-----\n"; |
| 239 | String strcerts = header.concat(body); |
| 240 | ByteArrayInputStream bais = new ByteArrayInputStream(strcerts.getBytes(StandardCharsets.ISO_8859_1)); |
| 241 | X509Certificate[] jsseCerts = null; |
| 242 | String providerName = (String) request.getConnector().getProperty("clientCertProvider"); |
| 243 | try { |
| 244 | CertificateFactory cf; |
| 245 | if (providerName == null) { |
| 246 | cf = CertificateFactory.getInstance("X.509"); |
| 247 | } else { |
| 248 | cf = CertificateFactory.getInstance("X.509", providerName); |
| 249 | } |
| 250 | X509Certificate cert = (X509Certificate) cf.generateCertificate(bais); |
| 251 | jsseCerts = new X509Certificate[1]; |
| 252 | jsseCerts[0] = cert; |
| 253 | } catch (java.security.cert.CertificateException e) { |
| 254 | log.warn(sm.getString("sslValve.certError", strcerts), e); |
| 255 | } catch (NoSuchProviderException e) { |
| 256 | log.error(sm.getString("sslValve.invalidProvider", providerName), e); |
| 257 | } |
| 258 | request.setAttribute(Globals.CERTIFICATES_ATTR, jsseCerts); |
| 259 | } |
| 260 | } |
| 261 | headerValue = mygetHeader(request, sslSecureProtocolHeader); |
| 262 | if (headerValue != null) { |
| 263 | request.setAttribute(Globals.SECURE_PROTOCOL_ATTR, headerValue); |
| 264 | } |
| 265 | headerValue = mygetHeader(request, sslCipherHeader); |
| 266 | if (headerValue != null) { |
| 267 | request.setAttribute(Globals.CIPHER_SUITE_ATTR, headerValue); |
| 268 | } |
| 269 | headerValue = mygetHeader(request, sslSessionIdHeader); |
| 270 | if (headerValue != null) { |
| 271 | request.setAttribute(Globals.SSL_SESSION_ID_ATTR, headerValue); |
nothing calls this directly
no test coverage detected