From 0e4e9054441493c8cb38d90a578293b3aa936e9b Mon Sep 17 00:00:00 2001 From: Wyatt Mogelson Date: Mon, 6 Jul 2026 12:03:41 -0500 Subject: [PATCH 1/6] fix: skip tls hostname verification when rejectUnauthorized is false rejectUnauthorized=false already skipped certificate chain validation but Java-WebSocket still enabled HTTPS endpoint identification, causing SAN mismatches to fail. overrides onSetSSLParameters to clear endpoint identification when rejectUnauthorized is false Signed-off-by: Wyatt Mogelson --- .../java/io/github/mapepire_ibmi/SqlJob.java | 10 +++++ .../io/github/mapepire_ibmi/ConnectTest.java | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/main/java/io/github/mapepire_ibmi/SqlJob.java b/src/main/java/io/github/mapepire_ibmi/SqlJob.java index a1f86f7..64c2357 100644 --- a/src/main/java/io/github/mapepire_ibmi/SqlJob.java +++ b/src/main/java/io/github/mapepire_ibmi/SqlJob.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; @@ -283,6 +284,15 @@ public void onMessage(String message) { } } + @Override + protected void onSetSSLParameters(SSLParameters sslParameters) { + if (db2Server.getRejectUnauthorized()) { + super.onSetSSLParameters(sslParameters); + } else { + sslParameters.setEndpointIdentificationAlgorithm(null); + } + } + @Override public void onClose(int code, String reason, boolean remote) { if (isTracingChannelData) { diff --git a/src/test/java/io/github/mapepire_ibmi/ConnectTest.java b/src/test/java/io/github/mapepire_ibmi/ConnectTest.java index d363b5f..e642efc 100644 --- a/src/test/java/io/github/mapepire_ibmi/ConnectTest.java +++ b/src/test/java/io/github/mapepire_ibmi/ConnectTest.java @@ -4,11 +4,15 @@ import static org.junit.jupiter.api.Assertions.assertThrowsExactly; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.net.InetAddress; import java.sql.SQLException; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import io.github.mapepire_ibmi.types.ConnectionResult; +import io.github.mapepire_ibmi.types.DaemonServer; class ConnectTest extends MapepireTest { @Test @@ -38,6 +42,41 @@ void invalidConnection() throws Exception { .contains("The application server rejected the connection.")); } + @Test + void rejectUnauthorizedFalseConnectsWhenCertificateDoesNotMatchHost() throws Exception { + DaemonServer creds = MapepireTest.getCreds(); + String mismatchedHost = InetAddress.getByName(creds.getHost()).getHostAddress(); + Assumptions.assumeTrue(!mismatchedHost.equals(creds.getHost())); + DaemonServer relaxedCreds = new DaemonServer( + mismatchedHost, creds.getPort(), creds.getUser(), creds.getPassword(), false); + SqlJob job = new SqlJob(); + ConnectionResult result = job.connect(relaxedCreds).get(); + job.close(); + assertTrue(result.getSuccess()); + assertTrue(result.getJob().contains("QZDASOINIT")); + } + + @Test + void rejectUnauthorizedTrueFailsWhenCertificateDoesNotMatchHost() throws Exception { + DaemonServer creds = MapepireTest.getCreds(); + String mismatchedHost = InetAddress.getByName(creds.getHost()).getHostAddress(); + Assumptions.assumeTrue(!mismatchedHost.equals(creds.getHost())); + + DaemonServer strictCreds = new DaemonServer( + mismatchedHost, creds.getPort(), creds.getUser(), creds.getPassword(), true, creds.getCa()); + + ExecutionException e = assertThrowsExactly(ExecutionException.class, () -> { + SqlJob job = new SqlJob(); + try { + job.connect(strictCreds).get(); + } finally { + job.close(); + } + }); + + assertTrue(e.getCause().getMessage().contains("No subject alternative")); + } + @Test void newJobOnSubsequentConnects() throws Exception { SqlJob job = new SqlJob(); From 6f0814fb1f01c351ca39d7a158bc048d91ad341e Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Fri, 17 Jul 2026 12:01:42 -0400 Subject: [PATCH 2/6] Move host to variable Signed-off-by: Sanjula Ganepola --- .../java/io/github/mapepire_ibmi/ConnectTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/java/io/github/mapepire_ibmi/ConnectTest.java b/src/test/java/io/github/mapepire_ibmi/ConnectTest.java index e642efc..db5d370 100644 --- a/src/test/java/io/github/mapepire_ibmi/ConnectTest.java +++ b/src/test/java/io/github/mapepire_ibmi/ConnectTest.java @@ -45,13 +45,16 @@ void invalidConnection() throws Exception { @Test void rejectUnauthorizedFalseConnectsWhenCertificateDoesNotMatchHost() throws Exception { DaemonServer creds = MapepireTest.getCreds(); - String mismatchedHost = InetAddress.getByName(creds.getHost()).getHostAddress(); - Assumptions.assumeTrue(!mismatchedHost.equals(creds.getHost())); + String host = creds.getHost(); + String mismatchedHost = InetAddress.getByName(host).getHostAddress(); + Assumptions.assumeTrue(!mismatchedHost.equals(host)); + DaemonServer relaxedCreds = new DaemonServer( mismatchedHost, creds.getPort(), creds.getUser(), creds.getPassword(), false); SqlJob job = new SqlJob(); ConnectionResult result = job.connect(relaxedCreds).get(); job.close(); + assertTrue(result.getSuccess()); assertTrue(result.getJob().contains("QZDASOINIT")); } @@ -59,8 +62,9 @@ void rejectUnauthorizedFalseConnectsWhenCertificateDoesNotMatchHost() throws Exc @Test void rejectUnauthorizedTrueFailsWhenCertificateDoesNotMatchHost() throws Exception { DaemonServer creds = MapepireTest.getCreds(); - String mismatchedHost = InetAddress.getByName(creds.getHost()).getHostAddress(); - Assumptions.assumeTrue(!mismatchedHost.equals(creds.getHost())); + String host = creds.getHost(); + String mismatchedHost = InetAddress.getByName(host).getHostAddress(); + Assumptions.assumeTrue(!mismatchedHost.equals(host)); DaemonServer strictCreds = new DaemonServer( mismatchedHost, creds.getPort(), creds.getUser(), creds.getPassword(), true, creds.getCa()); @@ -73,7 +77,6 @@ void rejectUnauthorizedTrueFailsWhenCertificateDoesNotMatchHost() throws Excepti job.close(); } }); - assertTrue(e.getCause().getMessage().contains("No subject alternative")); } From 142a5e18ed295e8c4e5333d92e7901e3d3b40f77 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Fri, 17 Jul 2026 12:23:04 -0400 Subject: [PATCH 3/6] Skip tests during maven build if PR from a fork Signed-off-by: Sanjula Ganepola --- .github/workflows/build.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c1aca0..deac9d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,14 @@ jobs: IBMI_PORT: ${{ secrets.IBMI_PORT }} - name: Build with Maven - run: mvn --batch-mode clean package --file pom.xml + env: + IBMI_HOST: ${{ secrets.IBMI_HOST }} + run: | + if [[ "$IBMI_HOST" == *.* ]]; then + mvn --batch-mode clean package --file pom.xml + else + mvn --batch-mode clean package --file pom.xml -DskipTests + fi - name: Update Dependency Graph uses: advanced-security/maven-dependency-submission-action@v4 From a0e3e3006d9cae196621c7c17ff92c22f4beeebc Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Fri, 17 Jul 2026 12:27:45 -0400 Subject: [PATCH 4/6] Add content write permission Signed-off-by: Sanjula Ganepola --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index deac9d2..a0c0228 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,6 +19,9 @@ jobs: environment: OSSBUILD + permissions: + contents: write + steps: - name: Checkout Repository uses: actions/checkout@v4 From 1c5a2a3b645592d32b3ac41ff84bb73922776573 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Fri, 17 Jul 2026 12:28:43 -0400 Subject: [PATCH 5/6] Move permissions Signed-off-by: Sanjula Ganepola --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0c0228..a9d566a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,9 @@ on: pull_request: branches: [ "main" ] +permissions: + contents: write + env: CONFIG_PROPERTIES: ./src/test/resources/config.properties CONFIG_PROPERTIES_SAMPLE: ./src/test/resources/config.properties.sample @@ -19,9 +22,6 @@ jobs: environment: OSSBUILD - permissions: - contents: write - steps: - name: Checkout Repository uses: actions/checkout@v4 From 339ca992f506ebaa14069d9c683b97cb9512b2a4 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Fri, 17 Jul 2026 12:34:29 -0400 Subject: [PATCH 6/6] Only run dependency graph on main Signed-off-by: Sanjula Ganepola --- .github/workflows/build.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a9d566a..5de6a3f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,9 +8,6 @@ on: pull_request: branches: [ "main" ] -permissions: - contents: write - env: CONFIG_PROPERTIES: ./src/test/resources/config.properties CONFIG_PROPERTIES_SAMPLE: ./src/test/resources/config.properties.sample @@ -58,4 +55,5 @@ jobs: fi - name: Update Dependency Graph + if: github.ref == 'refs/heads/main' uses: advanced-security/maven-dependency-submission-action@v4