Skip to content

Commit 82c9553

Browse files
author
Zhen Li
authored
Merge pull request #268 from nigelsmall/1.1-trust
Deprecate TOFU, add TRUST_ALL and remove E_NON_LOCAL
2 parents 365d2a5 + d1eedaf commit 82c9553

18 files changed

+190
-139
lines changed

driver/src/main/java/org/neo4j/driver/internal/RoutingDriver.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.neo4j.driver.internal.spi.ConnectionPool;
2727
import org.neo4j.driver.internal.util.Clock;
2828
import org.neo4j.driver.v1.AccessMode;
29+
import org.neo4j.driver.v1.Config;
2930
import org.neo4j.driver.v1.Logging;
3031
import org.neo4j.driver.v1.Session;
3132
import org.neo4j.driver.v1.exceptions.ClientException;
@@ -34,6 +35,16 @@
3435

3536
public class RoutingDriver extends BaseDriver
3637
{
38+
// Verify that a security plan is compatible with this driver, throwing an exception if not
39+
private static SecurityPlan verifiedSecurityPlan( SecurityPlan securityPlan )
40+
{
41+
if ( !securityPlan.isRoutingCompatible() )
42+
{
43+
throw new IllegalArgumentException( "The chosen security plan is not compatible with a routing driver" );
44+
}
45+
return securityPlan;
46+
}
47+
3748
private final LoadBalancer loadBalancer;
3849

3950
public RoutingDriver(
@@ -45,7 +56,7 @@ public RoutingDriver(
4556
Clock clock,
4657
Logging logging )
4758
{
48-
super( contract, securityPlan, logging );
59+
super( contract, verifiedSecurityPlan( securityPlan ), logging );
4960
this.loadBalancer = new LoadBalancer( settings, clock, log, connections, seedAddress );
5061
}
5162

driver/src/main/java/org/neo4j/driver/internal/net/BoltServerAddress.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,4 @@ public int port()
136136
return port;
137137
}
138138

139-
/**
140-
* Determine whether or not this address refers to the local machine. This
141-
* will generally be true for "localhost" or "127.x.x.x".
142-
*
143-
* @return true if local, false otherwise
144-
*/
145-
public boolean isLocal()
146-
{
147-
try
148-
{
149-
// confirmed to work as desired with both "localhost" and "127.x.x.x"
150-
return InetAddress.getByName( host ).isLoopbackAddress();
151-
}
152-
catch ( UnknownHostException e )
153-
{
154-
// if it's unknown, it's not local so we can safely return false
155-
return false;
156-
}
157-
}
158139
}

driver/src/main/java/org/neo4j/driver/internal/net/SocketClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ public static ByteChannel create( BoltServerAddress address, SecurityPlan securi
294294

295295
if (securityPlan.requiresEncryption())
296296
{
297-
channel = new TLSSocketChannel( address, securityPlan, soChannel, logger );
297+
channel = TLSSocketChannel.create( address, securityPlan, soChannel, logger );
298298
}
299299
else
300300
{

driver/src/main/java/org/neo4j/driver/internal/security/SecurityPlan.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@
4141
*/
4242
public class SecurityPlan
4343
{
44-
public static SecurityPlan forSignedCertificates( File certFile )
44+
public static SecurityPlan forAllCertificates() throws GeneralSecurityException, IOException
45+
{
46+
SSLContext sslContext = SSLContext.getInstance( "TLS" );
47+
sslContext.init( new KeyManager[0], new TrustManager[]{new TrustAllTrustManager()}, null );
48+
49+
return new SecurityPlan( true, sslContext, true );
50+
}
51+
52+
public static SecurityPlan forCustomCASignedCertificates( File certFile )
4553
throws GeneralSecurityException, IOException
4654
{
4755
// A certificate file is specified so we will load the certificates in the file
@@ -59,44 +67,53 @@ public static SecurityPlan forSignedCertificates( File certFile )
5967
SSLContext sslContext = SSLContext.getInstance( "TLS" );
6068
sslContext.init( new KeyManager[0], trustManagerFactory.getTrustManagers(), null );
6169

62-
return new SecurityPlan( true, sslContext);
70+
return new SecurityPlan( true, sslContext, true );
6371
}
6472

65-
public static SecurityPlan forSystemCertificates() throws NoSuchAlgorithmException, KeyStoreException
73+
public static SecurityPlan forSystemCASignedCertificates() throws NoSuchAlgorithmException, KeyStoreException
6674
{
67-
return new SecurityPlan( true, SSLContext.getDefault() );
75+
return new SecurityPlan( true, SSLContext.getDefault(), true );
6876
}
6977

70-
78+
@Deprecated
7179
public static SecurityPlan forTrustOnFirstUse( File knownHosts, BoltServerAddress address, Logger logger )
7280
throws IOException, KeyManagementException, NoSuchAlgorithmException
7381
{
7482
SSLContext sslContext = SSLContext.getInstance( "TLS" );
7583
sslContext.init( new KeyManager[0], new TrustManager[]{new TrustOnFirstUseTrustManager( address, knownHosts, logger )}, null );
7684

77-
return new SecurityPlan( true, sslContext);
85+
return new SecurityPlan( true, sslContext, false );
7886
}
7987

8088
public static SecurityPlan insecure()
8189
{
82-
return new SecurityPlan( false, null );
90+
return new SecurityPlan( false, null, true );
8391
}
8492

8593
private final boolean requiresEncryption;
8694
private final SSLContext sslContext;
95+
private final boolean routingCompatible;
8796

88-
private SecurityPlan( boolean requiresEncryption, SSLContext sslContext)
97+
private SecurityPlan( boolean requiresEncryption, SSLContext sslContext, boolean routingCompatible )
8998
{
9099
this.requiresEncryption = requiresEncryption;
91100
this.sslContext = sslContext;
101+
this.routingCompatible = routingCompatible;
92102
}
93103

94104
public boolean requiresEncryption()
95105
{
96106
return requiresEncryption;
97107
}
98108

109+
public boolean isRoutingCompatible()
110+
{
111+
return routingCompatible;
112+
}
99113

100-
public SSLContext sslContext() {return sslContext;}
114+
public SSLContext sslContext()
115+
{
116+
return sslContext;
117+
}
101118

102119
}

driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
import java.io.IOException;
2222
import java.nio.ByteBuffer;
2323
import java.nio.channels.ByteChannel;
24-
import java.security.GeneralSecurityException;
25-
import javax.net.ssl.KeyManager;
26-
import javax.net.ssl.SSLContext;
2724
import javax.net.ssl.SSLEngine;
2825
import javax.net.ssl.SSLEngineResult;
2926
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@@ -32,9 +29,6 @@
3229
import org.neo4j.driver.internal.net.BoltServerAddress;
3330
import org.neo4j.driver.v1.Logger;
3431
import org.neo4j.driver.internal.util.BytePrinter;
35-
import org.neo4j.driver.internal.util.BytePrinter;
36-
import org.neo4j.driver.v1.Config.TrustStrategy;
37-
import org.neo4j.driver.v1.Logger;
3832
import org.neo4j.driver.v1.exceptions.ClientException;
3933

4034
import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
@@ -67,32 +61,23 @@ public class TLSSocketChannel implements ByteChannel
6761

6862
private static final ByteBuffer DUMMY_BUFFER = ByteBuffer.allocate( 0 );
6963

70-
public TLSSocketChannel( BoltServerAddress address, SecurityPlan securityPlan, ByteChannel channel, Logger logger )
71-
throws GeneralSecurityException, IOException
72-
{
73-
this( channel, logger, createSSLEngine( address, securityPlan.sslContext() ) );
74-
}
75-
76-
public TLSSocketChannel( ByteChannel channel, Logger logger, SSLEngine sslEngine ) throws GeneralSecurityException, IOException
64+
public static TLSSocketChannel create( BoltServerAddress address, SecurityPlan securityPlan, ByteChannel channel, Logger logger )
65+
throws IOException
7766
{
78-
this(channel, logger, sslEngine,
79-
ByteBuffer.allocate( sslEngine.getSession().getApplicationBufferSize() ),
80-
ByteBuffer.allocate( sslEngine.getSession().getPacketBufferSize() ),
81-
ByteBuffer.allocate( sslEngine.getSession().getApplicationBufferSize() ),
82-
ByteBuffer.allocate( sslEngine.getSession().getPacketBufferSize() ) );
67+
SSLEngine sslEngine = securityPlan.sslContext().createSSLEngine( address.host(), address.port() );
68+
sslEngine.setUseClientMode( true );
69+
return new TLSSocketChannel( channel, logger, sslEngine );
8370
}
8471

85-
TLSSocketChannel( ByteChannel channel, Logger logger, SSLEngine sslEngine,
86-
ByteBuffer plainIn, ByteBuffer cipherIn, ByteBuffer plainOut, ByteBuffer cipherOut )
87-
throws GeneralSecurityException, IOException
72+
public TLSSocketChannel( ByteChannel channel, Logger logger, SSLEngine sslEngine ) throws IOException
8873
{
8974
this.logger = logger;
9075
this.channel = channel;
9176
this.sslEngine = sslEngine;
92-
this.plainIn = plainIn;
93-
this.cipherIn = cipherIn;
94-
this.plainOut = plainOut;
95-
this.cipherOut = cipherOut;
77+
this.plainIn = ByteBuffer.allocate( sslEngine.getSession().getApplicationBufferSize() );
78+
this.cipherIn = ByteBuffer.allocate( sslEngine.getSession().getPacketBufferSize() );
79+
this.plainOut = ByteBuffer.allocate( sslEngine.getSession().getApplicationBufferSize() );
80+
this.cipherOut = ByteBuffer.allocate( sslEngine.getSession().getPacketBufferSize() );
9681
runHandshake();
9782
}
9883

@@ -353,18 +338,6 @@ static int bufferCopy( ByteBuffer from, ByteBuffer to )
353338
return maxTransfer;
354339
}
355340

356-
/**
357-
* Create SSLEngine with the SSLContext just created.
358-
* @param address the host to connect to
359-
* @param sslContext the current ssl context
360-
*/
361-
private static SSLEngine createSSLEngine( BoltServerAddress address, SSLContext sslContext )
362-
{
363-
SSLEngine sslEngine = sslContext.createSSLEngine( address.host(), address.port() );
364-
sslEngine.setUseClientMode( true );
365-
return sslEngine;
366-
}
367-
368341
@Override
369342
public int read( ByteBuffer dst ) throws IOException
370343
{
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) 2002-2016 "Neo Technology,"
3+
* Network Engine for Objects in Lund AB [http://neotechnology.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
package org.neo4j.driver.internal.security;
21+
22+
import java.security.cert.CertificateException;
23+
import java.security.cert.X509Certificate;
24+
import javax.net.ssl.X509TrustManager;
25+
26+
public class TrustAllTrustManager implements X509TrustManager
27+
{
28+
public void checkClientTrusted( X509Certificate[] chain, String authType ) throws CertificateException
29+
{
30+
throw new CertificateException( "All client connections to this client are forbidden." );
31+
}
32+
33+
public void checkServerTrusted( X509Certificate[] chain, String authType ) throws CertificateException
34+
{
35+
// all fine, pass through
36+
}
37+
38+
public X509Certificate[] getAcceptedIssuers()
39+
{
40+
return new X509Certificate[0];
41+
}
42+
}

driver/src/main/java/org/neo4j/driver/v1/Config.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@
2727
import org.neo4j.driver.internal.net.pooling.PoolSettings;
2828
import org.neo4j.driver.v1.util.Immutable;
2929

30-
import static java.lang.System.getProperty;
31-
import static org.neo4j.driver.v1.Config.TrustStrategy.trustOnFirstUse;
30+
import static org.neo4j.driver.v1.Config.TrustStrategy.trustAllCertificates;
3231

3332
/**
3433
* A configuration class to config driver properties.
@@ -168,9 +167,8 @@ public static class ConfigBuilder
168167
private Logging logging = new JULogging( Level.INFO );
169168
private int maxIdleConnectionPoolSize = PoolSettings.DEFAULT_MAX_IDLE_CONNECTION_POOL_SIZE;
170169
private long idleTimeBeforeConnectionTest = PoolSettings.DEFAULT_IDLE_TIME_BEFORE_CONNECTION_TEST;
171-
private EncryptionLevel encryptionLevel = EncryptionLevel.REQUIRED_NON_LOCAL;
172-
private TrustStrategy trustStrategy = trustOnFirstUse(
173-
new File( getProperty( "user.home" ), ".neo4j" + File.separator + "known_hosts" ) );
170+
private EncryptionLevel encryptionLevel = EncryptionLevel.REQUIRED;
171+
private TrustStrategy trustStrategy = trustAllCertificates();
174172
private RetryLogic retryLogic = RetryLogic.DEFAULT_RETRY_LOGIC;
175173
private int routingFailureLimit = 1;
176174
private long routingRetryDelayMillis = 5_000;
@@ -371,10 +369,6 @@ public enum EncryptionLevel
371369
/** With this level, the driver will only connect to the server if it can do it without encryption. */
372370
NONE,
373371

374-
/** With this level, the driver will only connect to the server without encryption if local but with
375-
* encryption otherwise. */
376-
REQUIRED_NON_LOCAL,
377-
378372
/** With this level, the driver will only connect to the server it if can do it with encryption. */
379373
REQUIRED
380374
}
@@ -386,10 +380,16 @@ public static class TrustStrategy
386380
{
387381
public enum Strategy
388382
{
383+
@Deprecated
389384
TRUST_ON_FIRST_USE,
385+
390386
@Deprecated
391387
TRUST_SIGNED_CERTIFICATES,
388+
389+
TRUST_ALL_CERTIFICATES,
390+
392391
TRUST_CUSTOM_CA_SIGNED_CERTIFICATES,
392+
393393
TRUST_SYSTEM_CA_SIGNED_CERTIFICATES
394394
}
395395

@@ -445,11 +445,26 @@ public static TrustStrategy trustCustomCertificateSignedBy( File certFile )
445445
return new TrustStrategy( Strategy.TRUST_CUSTOM_CA_SIGNED_CERTIFICATES, certFile );
446446
}
447447

448+
/**
449+
*
450+
* @return
451+
*/
448452
public static TrustStrategy trustSystemCertificates()
449453
{
450454
return new TrustStrategy( Strategy.TRUST_SYSTEM_CA_SIGNED_CERTIFICATES );
451455
}
452456

457+
/**
458+
*
459+
* @return
460+
*
461+
* @since 1.1
462+
*/
463+
public static TrustStrategy trustAllCertificates()
464+
{
465+
return new TrustStrategy( Strategy.TRUST_ALL_CERTIFICATES );
466+
}
467+
453468
/**
454469
* Automatically trust a Neo4j instance the first time we see it - but fail to connect if its encryption certificate ever changes.
455470
* This is similar to the mechanism used in SSH, and protects against man-in-the-middle attacks that occur after the initial setup of your application.
@@ -463,7 +478,10 @@ public static TrustStrategy trustSystemCertificates()
463478
*
464479
* @param knownHostsFile a file where known certificates are stored.
465480
* @return an authentication config
481+
*
482+
* @deprecated in 1.1 in favour of {@link #trustAllCertificates()}
466483
*/
484+
@Deprecated
467485
public static TrustStrategy trustOnFirstUse( File knownHostsFile )
468486
{
469487
return new TrustStrategy( Strategy.TRUST_ON_FIRST_USE, knownHostsFile );

0 commit comments

Comments
 (0)