Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ public String getDbType() {

public void setDbType(String dbType) {
this.dbType = dbType;
applyDbType(defaultDriverConfig);
if (!CollectionUtils.isEmpty(driverConfigList)) {
driverConfigList.forEach(this::applyDbType);
}
}

public String getName() {
Expand Down Expand Up @@ -202,6 +206,7 @@ public DriverConfig getDefaultDriverConfig() {

public void setDefaultDriverConfig(DriverConfig defaultDriverConfig) {
this.defaultDriverConfig = defaultDriverConfig;
applyDbType(defaultDriverConfig);
}

public List<DriverConfig> getDriverConfigList() {
Expand All @@ -211,12 +216,22 @@ public List<DriverConfig> getDriverConfigList() {
public void setDriverConfigList(List<DriverConfig> driverConfigList) {
this.driverConfigList = driverConfigList;
if (!CollectionUtils.isEmpty(driverConfigList)) {
DriverConfig selectedDefault = null;
for (DriverConfig driverConfig : driverConfigList) {
if (driverConfig.isDefaultDriver()) {
this.defaultDriverConfig = driverConfig;
break;
applyDbType(driverConfig);
if (driverConfig.isDefaultDriver() && selectedDefault == null) {
selectedDefault = driverConfig;
}
}
if (selectedDefault != null) {
this.defaultDriverConfig = selectedDefault;
}
}
}

private void applyDbType(DriverConfig driverConfig) {
if (driverConfig != null && StringUtils.isBlank(driverConfig.getDbType())) {
driverConfig.setDbType(dbType);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -187,7 +188,12 @@ public String copyDrivers(List<String> driverPaths) {
exists = false;
break;
}
File target = new File(JdbcDriverConstants.DRIVER_LIB_PATH + file.getName());
File target;
try {
target = new File(JdbcDriverConstants.createDriverLibDirectory(), file.getName());
} catch (IOException e) {
throw new UncheckedIOException("Unable to create JDBC driver directory", e);
}
FileUtil.copyFile(file, target, StandardCopyOption.REPLACE_EXISTING);
driverNames.append(file.getName()).append(",");
}
Expand Down Expand Up @@ -249,7 +255,7 @@ public void deleteUnreferencedDriverJars(String jdbcDriver) {
if (StringUtils.isBlank(jar) || isJarReferenced(jar)) {
continue;
}
File file = new File(JdbcDriverConstants.DRIVER_LIB_PATH + jar);
File file = new File(JdbcDriverConstants.getDriverLibPath() + jar);
if (file.exists()) {
try {
FileUtil.del(file);
Expand Down Expand Up @@ -300,7 +306,7 @@ private boolean driverExists(DriverConfig driverConfig) {
return false;
}
for (String jarPath : driverConfig.getJdbcDriver().split(",")) {
File file = new File(JdbcDriverConstants.DRIVER_LIB_PATH + jarPath);
File file = new File(JdbcDriverConstants.getDriverLibPath() + jarPath);
if (!file.exists()) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ai.chat2db.community.domain.core.impl.db;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

class DbJdbcDriverServiceImplDriverCopyTest {

@TempDir
private Path temporaryDirectory;

@Test
void copyDriversCreatesDirectoryUnderTheCurrentUserHome() throws Exception {
String originalHome = System.getProperty("user.home");
String originalRuntimeMode = System.getProperty("chat2db.runtime.mode");
byte[] driverBytes = "custom-driver".getBytes(StandardCharsets.UTF_8);
Path source = temporaryDirectory.resolve("custom-driver.jar");
Files.write(source, driverBytes);
Path initializedHome = temporaryDirectory.resolve("initialized-home");
Path activeHome = temporaryDirectory.resolve("active-home");
try {
System.setProperty("chat2db.runtime.mode", "community");
System.setProperty("user.home", initializedHome.toString());
DbJdbcDriverServiceImpl service = new DbJdbcDriverServiceImpl();

System.setProperty("user.home", activeHome.toString());
Path target = activeHome.resolve(".chat2db-community").resolve("jdbc-lib")
.resolve("custom-driver.jar");
assertFalse(Files.exists(target.getParent()));

assertEquals("custom-driver.jar", service.copyDrivers(List.of(source.toString())));
assertArrayEquals(driverBytes, Files.readAllBytes(target));
} finally {
restoreProperty("user.home", originalHome);
restoreProperty("chat2db.runtime.mode", originalRuntimeMode);
}
}

private void restoreProperty(String name, String value) {
if (value == null) {
System.clearProperty(name);
} else {
System.setProperty(name, value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package ai.chat2db.spi.sql;

import ai.chat2db.community.domain.api.config.DriverConfig;
import ai.chat2db.community.domain.api.model.request.datasource.DbDataSourcePreConnectRequest;
import ai.chat2db.community.tools.constant.JdbcDriverConstants;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.sql.Connection;
import java.sql.DriverPropertyInfo;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;

class HsqldbTrustedDriverDownloadTest {

private static final String HSQLDB_JAR = "hsqldb-2.7.3.jar";
private static final String HSQLDB_DRIVER_CLASS = "org.hsqldb.jdbc.JDBCDriver";
private static final String TRUSTED_HSQLDB_URL =
"https://repo1.maven.org/maven2/org/hsqldb/hsqldb/2.7.3/hsqldb-2.7.3.jar";
private static final String MALICIOUS_URL = "http://127.0.0.1:1/hsqldb-2.7.3.jar";

@TempDir
private Path temporaryDirectory;

@Test
void preConnectRequestCannotOverrideTheTrustedDriverDownloadUrl() {
DriverConfig requestDriver = new DriverConfig();
requestDriver.setJdbcDriver(HSQLDB_JAR);
requestDriver.setJdbcDriverClass(HSQLDB_DRIVER_CLASS);
requestDriver.setDownloadJdbcDriverUrls(List.of(MALICIOUS_URL));
DbDataSourcePreConnectRequest request = new DbDataSourcePreConnectRequest();
request.setType("HSQLDB");
request.setDriverConfig(requestDriver);

List<String> selectedUrls = JdbcDriverManager.resolveTrustedDownloadUrls(
request.getType(), request.getDriverConfig());

assertEquals(List.of(TRUSTED_HSQLDB_URL), selectedUrls);
assertFalse(selectedUrls.contains(MALICIOUS_URL));
}

@Test
void requestThatDoesNotExactlyMatchBuiltInDriverGetsNoTrustedUrls() {
DriverConfig requestDriver = new DriverConfig();
requestDriver.setJdbcDriver(HSQLDB_JAR);
requestDriver.setJdbcDriverClass("attacker.Driver");
requestDriver.setDownloadJdbcDriverUrls(List.of(MALICIOUS_URL));

assertEquals(List.of(), JdbcDriverManager.resolveTrustedDownloadUrls("HSQLDB", requestDriver));
}

@Test
void legacyPublicApisKeepUsingTheTrustedBuiltInDriverConfig() throws Exception {
String originalHome = System.getProperty("user.home");
String originalRuntimeMode = System.getProperty("chat2db.runtime.mode");
DriverConfig builtInDriver = Chat2DBContext.getDefaultDriverConfig("HSQLDB");
try {
System.setProperty("chat2db.runtime.mode", "community");
System.setProperty("user.home", temporaryDirectory.toString());
Path sourceJar = Path.of(new URI(org.hsqldb.jdbc.JDBCDriver.class.getProtectionDomain()
.getCodeSource().getLocation().toString()));
Path targetJar = JdbcDriverConstants.createDriverLibDirectory().toPath().resolve(HSQLDB_JAR);
Files.copy(sourceJar, targetJar, StandardCopyOption.REPLACE_EXISTING);
JdbcDriverManager.unload(HSQLDB_JAR);

assertEquals("HSQLDB", builtInDriver.getDbType());
assertEquals(List.of(TRUSTED_HSQLDB_URL), JdbcDriverManager.resolveTrustedDownloadUrls(
builtInDriver.getDbType(), builtInDriver));
assertNotNull(JdbcDriverManager.getClassLoader(builtInDriver).loadClass(HSQLDB_DRIVER_CLASS));
DriverPropertyInfo[] properties = JdbcDriverManager.getProperty(builtInDriver);
assertNotNull(properties);
try (Connection connection = JdbcDriverManager.getConnection(
"jdbc:hsqldb:mem:legacy_driver_api;shutdown=true", builtInDriver)) {
assertFalse(connection.isClosed());
}
} finally {
JdbcDriverManager.unload(HSQLDB_JAR);
restoreProperty("user.home", originalHome);
restoreProperty("chat2db.runtime.mode", originalRuntimeMode);
}
}

private void restoreProperty(String name, String value) {
if (value == null) {
System.clearProperty(name);
} else {
System.setProperty(name, value);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public Connection getConnection(ConnectInfo connectInfo) {
driverConfig = Chat2DBContext.getDefaultDriverConfig(connectInfo.getDbType());
}
connection = JdbcDriverManager.getConnection(url, connectInfo.getUser(), connectInfo.getPassword(),
driverConfig, connectInfo.getExtendMap());
connectInfo.getDbType(), driverConfig, connectInfo.getExtendMap());

} catch (Exception e1) {
close(connection, session, ssh);
Expand Down
Loading
Loading