diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jndi/JndiException.java b/hibernate-core/src/main/java/org/hibernate/engine/jndi/JndiException.java index 0d28b6632f..d18076e596 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jndi/JndiException.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jndi/JndiException.java @@ -22,4 +22,14 @@ public class JndiException extends HibernateException { public JndiException(String message, Throwable cause) { super( message, cause ); } + + /** + * Constructs a JndiException + * + * @param message Message explaining the exception condition + */ + public JndiException(String message) { + super( message ); + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jndi/internal/JndiServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jndi/internal/JndiServiceImpl.java index d336338d75..a6d29916a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jndi/internal/JndiServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jndi/internal/JndiServiceImpl.java @@ -6,6 +6,8 @@ */ package org.hibernate.engine.jndi.internal; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Hashtable; import java.util.Map; import java.util.Set; @@ -113,6 +115,16 @@ final class JndiServiceImpl implements JndiService { } private Name parseName(String jndiName, Context context) { + try { + final URI uri = new URI( jndiName ); + final String scheme = uri.getScheme(); + if ( scheme != null && (! "java".equals( scheme ) ) ) { + throw new JndiException( "JNDI lookups for scheme '" + scheme + "' are not allowed" ); + } + } + catch (URISyntaxException e) { + //Ok + } try { return context.getNameParser( "" ).parse( jndiName ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/service/internal/JndiServiceImplTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/service/internal/JndiServiceImplTest.java new file mode 100644 index 0000000000..65a717d53c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/service/internal/JndiServiceImplTest.java @@ -0,0 +1,48 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.orm.test.service.internal; + +import java.util.HashMap; + +import org.hibernate.engine.jndi.JndiException; +import org.hibernate.engine.jndi.internal.JndiServiceInitiator; +import org.hibernate.engine.jndi.spi.JndiService; + +import org.junit.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Checks protocol restrictions being applied on the JNDI lookup capabilities + * of the default JndiService implementation. + */ +public class JndiServiceImplTest { + + private final JndiService jndiService = JndiServiceInitiator.INSTANCE.initiateService( new HashMap(), null ); + + @Test + public void rejectNonLocalProtocols() { + final JndiException ldapException = assertThrows( JndiException.class, + () -> jndiService.locate( + "ldap://yourserver/something" ) + ); + assertEquals( "JNDI lookups for scheme 'ldap' are not allowed", ldapException.getMessage() ); + } + + @Test + public void javaLookupIsAttempted() { + //The "java" scheme is allowed to be used; it will also fail as we didn't setup a full JNDI context + //in this test, but we can verify it's been attempted by checking the error message. + final JndiException javaLookupException = assertThrows( JndiException.class, + () -> jndiService.locate( + "java:comp/env/jdbc/MyDatasource" ) + ); + assertEquals( "Error parsing JNDI name [java:comp/env/jdbc/MyDatasource]", javaLookupException.getMessage() ); + } + +}