From d24c8a2337ffae3dc1658e0a08726836d25f587c Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 19 Nov 2018 17:09:49 +0100 Subject: [PATCH] WEB-35225 Invalid built-in server certificate when using https Following extensions were added: 'san=dns:localhost,dns:*.localhost,dns:*.dev,dns:*.local' ECC key is not used instead of RSA. --- .../src/org/jetbrains/io/cert.cet | Bin 0 -> 90 bytes .../src/org/jetbrains/io/cert.jceks | Bin 0 -> 600 bytes .../src/org/jetbrains/io/cert.jks | Bin 2300 -> 0 bytes .../io/PortUnificationServerHandler.java | 59 ++++++++---------- 4 files changed, 27 insertions(+), 32 deletions(-) create mode 100644 platform/built-in-server/src/org/jetbrains/io/cert.cet create mode 100644 platform/built-in-server/src/org/jetbrains/io/cert.jceks delete mode 100644 platform/built-in-server/src/org/jetbrains/io/cert.jks diff --git a/platform/built-in-server/src/org/jetbrains/io/cert.cet b/platform/built-in-server/src/org/jetbrains/io/cert.cet new file mode 100644 index 0000000000000000000000000000000000000000..525c8c82b8bcc6386d5561ddcc712b94420eb03b GIT binary patch literal 90 zcmZQzU|?{cC};?z7=aiBKr|cC12F;ZI}xY= literal 0 HcmV?d00001 diff --git a/platform/built-in-server/src/org/jetbrains/io/cert.jceks b/platform/built-in-server/src/org/jetbrains/io/cert.jceks new file mode 100644 index 0000000000000000000000000000000000000000..448327db98e8687fd5fc96a9fcf6a7a4288605bd GIT binary patch literal 600 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 diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java index 1f7e0e20998d..5e105d5376a4 100644 --- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java +++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.io; import com.intellij.openapi.diagnostic.Logger; @@ -22,40 +8,49 @@ import io.netty.channel.*; import io.netty.handler.codec.compression.ZlibCodecFactory; import io.netty.handler.codec.compression.ZlibWrapper; import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedWriteHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.ide.BinaryRequestHandler; import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import java.io.InputStream; import java.security.KeyStore; import java.security.Security; import java.util.UUID; @ChannelHandler.Sharable class PortUnificationServerHandler extends Decoder { - // keytool -genkey -keyalg RSA -alias selfsigned -keystore cert.jks -storepass jetbrains -validity 10000 -keysize 2048 + // https://stackoverflow.com/questions/33827789/self-signed-certificate-dnsname-components-must-begin-with-a-letter + // https://github.com/kaikramer/keystore-explorer (use cert.cet as cert ext template) + // keytool -genkey -keyalg EC -keysize 256 -alias selfsigned -keystore cert.jks -storepass jetbrains -validity 10000 -ext 'san=dns:localhost,dns:*.localhost,dns:*.dev,dns:*.local' @SuppressWarnings("SpellCheckingInspection") - private static final AtomicNotNullLazyValue SSL_SERVER_CONTEXT = new AtomicNotNullLazyValue() { + private static final AtomicNotNullLazyValue SSL_SERVER_CONTEXT = new AtomicNotNullLazyValue() { @NotNull @Override - protected SSLContext compute() { + protected SslContext compute() { String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); if (algorithm == null) { algorithm = "SunX509"; } try { - KeyStore ks = KeyStore.getInstance("JKS"); - char[] password = "jetbrains".toCharArray(); - ks.load(getClass().getResourceAsStream("cert.jks"), password); - KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); - kmf.init(ks, password); - SSLContext serverContext = SSLContext.getInstance("TLS"); - serverContext.init(kmf.getKeyManagers(), null, null); - return serverContext; + KeyStore ks = KeyStore.getInstance("JCEKS"); + char[] password = "jb".toCharArray(); + String keyStoreResourceName = "cert.jceks"; + InputStream keyStoreData = getClass().getResourceAsStream(keyStoreResourceName); + if (keyStoreData == null) { + throw new RuntimeException("Cannot find " + keyStoreResourceName); + } + + ks.load(keyStoreData, password); + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm); + keyManagerFactory.init(ks, password); + return SslContextBuilder.forServer(keyManagerFactory) + .build(); } catch (Exception e) { throw new RuntimeException(e); @@ -79,17 +74,17 @@ class PortUnificationServerHandler extends Decoder { } @Override - protected void messageReceived(@NotNull ChannelHandlerContext context, @NotNull ByteBuf input) throws Exception { + protected void messageReceived(@NotNull ChannelHandlerContext context, @NotNull ByteBuf input) { ByteBuf buffer = getBufferIfSufficient(input, 5, context); if (buffer != null) { decode(context, buffer); } } - protected void decode(@NotNull ChannelHandlerContext context, @NotNull ByteBuf buffer) throws Exception { + protected void decode(@NotNull ChannelHandlerContext context, @NotNull ByteBuf buffer) { ChannelPipeline pipeline = context.pipeline(); if (detectSsl && SslHandler.isEncrypted(buffer)) { - SSLEngine engine = SSL_SERVER_CONTEXT.getValue().createSSLEngine(); + SSLEngine engine = SSL_SERVER_CONTEXT.getValue().newEngine(context.alloc()); engine.setUseClientMode(false); pipeline.addLast(new SslHandler(engine), new ChunkedWriteHandler(), new PortUnificationServerHandler(delegatingHttpRequestHandler, false, detectGzip)); @@ -139,7 +134,7 @@ class PortUnificationServerHandler extends Decoder { } @Override - public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext context, Throwable cause) { NettyUtil.logAndClose(cause, Logger.getInstance(BuiltInServer.class), context.channel()); } @@ -160,7 +155,7 @@ class PortUnificationServerHandler extends Decoder { private static final int UUID_LENGTH = 16; @Override - protected void messageReceived(@NotNull ChannelHandlerContext context, @NotNull ByteBuf input) throws Exception { + protected void messageReceived(@NotNull ChannelHandlerContext context, @NotNull ByteBuf input) { ByteBuf buffer = getBufferIfSufficient(input, UUID_LENGTH, context); if (buffer == null) { return;