Skip to content

Commit 87d9615

Browse files
committed
Merge remote-tracking branch 'upstream/1.0' into 1.1
2 parents 77f3a63 + 1ac0038 commit 87d9615

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.neo4j.driver.v1.Logger;
3535
import org.neo4j.driver.internal.util.BytePrinter;
3636

37+
import static java.lang.String.format;
3738
import static org.neo4j.driver.internal.util.CertificateTool.X509CertToString;
3839

3940
/**
@@ -78,6 +79,8 @@ private void load() throws IOException
7879
return;
7980
}
8081

82+
assertKnownHostFileReadable();
83+
8184
BufferedReader reader = new BufferedReader( new FileReader( knownHosts ) );
8285
String line;
8386
while ( (line = reader.readLine()) != null )
@@ -108,12 +111,38 @@ private void saveTrustedHost( String fingerprint ) throws IOException
108111
logger.warn( "Adding %s as known and trusted certificate for %s.", fingerprint, serverId );
109112
createKnownCertFileIfNotExists();
110113

114+
assertKnownHostFileWritable();
111115
BufferedWriter writer = new BufferedWriter( new FileWriter( knownHosts, true ) );
112116
writer.write( serverId + " " + this.fingerprint );
113117
writer.newLine();
114118
writer.close();
115119
}
116120

121+
122+
private void assertKnownHostFileReadable() throws IOException
123+
{
124+
if( !knownHosts.canRead() )
125+
{
126+
throw new IOException( format(
127+
"Failed to load certificates from file %s as you have no read permissions to it.\n" +
128+
"Try configuring the Neo4j driver to use a file system location you do have read permissions to.",
129+
knownHosts.getAbsolutePath()
130+
) );
131+
}
132+
}
133+
134+
private void assertKnownHostFileWritable() throws IOException
135+
{
136+
if( !knownHosts.canWrite() )
137+
{
138+
throw new IOException( format(
139+
"Failed to write certificates to file %s as you have no write permissions to it.\n" +
140+
"Try configuring the Neo4j driver to use a file system location you do have write permissions to.",
141+
knownHosts.getAbsolutePath()
142+
) );
143+
}
144+
}
145+
117146
/*
118147
* Disallow all client connection to this client
119148
*/
@@ -141,7 +170,7 @@ public void checkServerTrusted( X509Certificate[] chain, String authType )
141170
}
142171
catch ( IOException e )
143172
{
144-
throw new CertificateException( String.format(
173+
throw new CertificateException( format(
145174
"Failed to save the server ID and the certificate received from the server to file %s.\n" +
146175
"Server ID: %s\nReceived cert:\n%s",
147176
knownHosts.getAbsolutePath(), serverId, X509CertToString( cert ) ), e );
@@ -151,7 +180,7 @@ public void checkServerTrusted( X509Certificate[] chain, String authType )
151180
{
152181
if ( !this.fingerprint.equals( cert ) )
153182
{
154-
throw new CertificateException( String.format(
183+
throw new CertificateException( format(
155184
"Unable to connect to neo4j at `%s`, because the certificate the server uses has changed. " +
156185
"This is a security feature to protect against man-in-the-middle attacks.\n" +
157186
"If you trust the certificate the server uses now, simply remove the line that starts with " +

driver/src/test/java/org/neo4j/driver/internal/security/TrustOnFirstUseTrustManagerTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.junit.rules.TemporaryFolder;
2626

2727
import java.io.File;
28+
import java.io.IOException;
2829
import java.io.PrintWriter;
2930
import java.security.cert.CertificateException;
3031
import java.security.cert.X509Certificate;
@@ -33,7 +34,9 @@
3334
import org.neo4j.driver.internal.net.BoltServerAddress;
3435
import org.neo4j.driver.v1.Logger;
3536

37+
import static org.hamcrest.CoreMatchers.containsString;
3638
import static org.junit.Assert.assertEquals;
39+
import static org.junit.Assert.assertThat;
3740
import static org.junit.Assert.assertTrue;
3841
import static org.junit.Assert.fail;
3942
import static org.mockito.Mockito.mock;
@@ -144,4 +147,55 @@ private String nextLine( Scanner reader )
144147
while ( line.trim().startsWith( "#" ) );
145148
return line;
146149
}
150+
151+
@Test
152+
public void shouldThrowMeaningfulExceptionIfHasNoReadPermissionToKnownHostFile() throws Throwable
153+
{
154+
// Given
155+
File knownHostFile = mock( File.class );
156+
when( knownHostFile.canRead() ).thenReturn( false );
157+
when( knownHostFile.exists() ).thenReturn( true );
158+
159+
// When & Then
160+
try
161+
{
162+
new TrustOnFirstUseTrustManager( new BoltServerAddress( knownServerIp, knownServerPort ), knownHostFile, null );
163+
fail( "Should have failed in load certs" );
164+
}
165+
catch( IOException e )
166+
{
167+
assertThat( e.getMessage(), containsString( "you have no read permissions to it" ) );
168+
}
169+
catch( Exception e )
170+
{
171+
fail( "Should not get any other error besides no permission to read" );
172+
}
173+
}
174+
175+
@Test
176+
public void shouldThrowMeaningfulExceptionIfHasNoWritePermissionToKnownHostFile() throws Throwable
177+
{
178+
// Given
179+
File knownHostFile = mock( File.class );
180+
when( knownHostFile.exists() ).thenReturn( false /*skip reading*/, true );
181+
when( knownHostFile.canWrite() ).thenReturn( false );
182+
183+
// When & Then
184+
try
185+
{
186+
TrustOnFirstUseTrustManager manager =
187+
new TrustOnFirstUseTrustManager( new BoltServerAddress( knownServerIp, knownServerPort ), knownHostFile, mock( Logger.class ) );
188+
manager.checkServerTrusted( new X509Certificate[]{ knownCertificate}, null );
189+
fail( "Should have failed in write to certs" );
190+
}
191+
catch( CertificateException e )
192+
{
193+
assertThat( e.getCause().getMessage(), containsString( "you have no write permissions to it" ) );
194+
}
195+
catch( Exception e )
196+
{
197+
e.printStackTrace();
198+
fail( "Should not get any other error besides no permission to write" );
199+
}
200+
}
147201
}

0 commit comments

Comments
 (0)