From 7d084970a4a79586a4ce5adc4d2695305f4c773b Mon Sep 17 00:00:00 2001 From: John Eberhard Date: Thu, 20 Jun 2024 13:35:12 -0500 Subject: [PATCH] Determine JDBC system version when port number specified Signed-off-by: John Eberhard --- src/main/java/com/ibm/as400/access/AS400.java | 18 +++++++++- .../java/com/ibm/as400/access/AS400Impl.java | 4 ++- .../com/ibm/as400/access/AS400ImplProxy.java | 5 +++ .../com/ibm/as400/access/AS400ImplRemote.java | 35 +++++++++++++++--- .../as400/access/AS400JDBCConnectionImpl.java | 2 +- .../com/ibm/as400/access/AS400JDBCDriver.java | 36 ++++++++++++++++++- .../com/ibm/as400/access/JobCCSIDNative.java | 2 +- .../java/com/ibm/as400/access/PortMapper.java | 4 +-- .../as400/access/RemoteCommandImplNative.java | 14 ++++---- .../as400/access/RemoteCommandImplRemote.java | 6 ++-- .../com/ibm/as400/access/ServerVersion.java | 8 ++++- .../java/com/ibm/as400/access/SignonInfo.java | 6 ++++ 12 files changed, 117 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/ibm/as400/access/AS400.java b/src/main/java/com/ibm/as400/access/AS400.java index acffabcaa..fe9ad551a 100644 --- a/src/main/java/com/ibm/as400/access/AS400.java +++ b/src/main/java/com/ibm/as400/access/AS400.java @@ -2958,7 +2958,21 @@ public int getVRM() throws AS400SecurityException, IOException return vrm; } - + /** + * Sets the VRM for the object, creating a signonInfo as needed + * + */ + protected void setVRM(int v, int r, int m) { + if (signonInfo_ == null) { + signonInfo_ = new SignonInfo((v << 16 ) + (r << 8) + m); + } else { + signonInfo_.version.setVersionReleaseModification((v << 16) + (r << 8) + m); + } + if (impl_ != null) { + impl_.setVRM(v,r,m); + } + + } /** Initialize conversion table for the given CCSID. The default EBCDIC to unicode converters are not shipped with some browsers. This method can be used to check and download converters if they are not available locally. @param ccsid the CCSID for the conversion table to initialize. @@ -5332,6 +5346,8 @@ public void setEnabledCipherSuites(String[] suites) newCipherSuites = suites; } } + + // ======== END ================= // Previous chunk of code moved from SecureAS400 diff --git a/src/main/java/com/ibm/as400/access/AS400Impl.java b/src/main/java/com/ibm/as400/access/AS400Impl.java index 7198d4ced..979f101c3 100644 --- a/src/main/java/com/ibm/as400/access/AS400Impl.java +++ b/src/main/java/com/ibm/as400/access/AS400Impl.java @@ -97,6 +97,8 @@ interface AS400Impl SignonInfo skipSignon(String systemName, boolean systemNameLocal, String userId_, CredentialVault tempVault, String gssName) throws AS400SecurityException, IOException; - String getSystemName(); + String getSystemName(); + /* Set the VRM for the object. Only set for the remote Impl */ + void setVRM(int v, int r, int m); } diff --git a/src/main/java/com/ibm/as400/access/AS400ImplProxy.java b/src/main/java/com/ibm/as400/access/AS400ImplProxy.java index b81eed2d5..6f51bffae 100644 --- a/src/main/java/com/ibm/as400/access/AS400ImplProxy.java +++ b/src/main/java/com/ibm/as400/access/AS400ImplProxy.java @@ -418,4 +418,9 @@ public int getBidiStringType(){ public String getSystemName() { return connection_.getSystemName(); } + + @Override + public void setVRM(int v, int r, int m) { + // Does nothing for the proxy class + } } diff --git a/src/main/java/com/ibm/as400/access/AS400ImplRemote.java b/src/main/java/com/ibm/as400/access/AS400ImplRemote.java index 77b8dd41c..51c995585 100644 --- a/src/main/java/com/ibm/as400/access/AS400ImplRemote.java +++ b/src/main/java/com/ibm/as400/access/AS400ImplRemote.java @@ -1554,9 +1554,19 @@ synchronized AS400Server getConnection(int service, int overridePort, boolean fo SocketContainer socketContainer = null; if (connectViaHCS) { + if (HCSAuthdServer_ == null) - generateHCSServerDaemon(skipSignonServer); - + try { + generateHCSServerDaemon(skipSignonServer,overridePort); + } catch (Exception ex) { + // If we specified a port number and got an exception, + // then ignore the error from the HCS. + if (overridePort > 0) { + HCSAuthdServer_ = null; + } else { + throw ex; + } + } if (HCSAuthdServer_ == null) { connectViaHCS = false; @@ -1876,7 +1886,7 @@ synchronized AS400Server getConnection(int service, int overridePort, boolean fo return server; } - synchronized private void generateHCSServerDaemon(boolean skipSignonServer) throws AS400SecurityException, IOException + synchronized private void generateHCSServerDaemon(boolean skipSignonServer, int overridePort) throws AS400SecurityException, IOException { if (HCSAuthdServer_ != null) return; @@ -1888,7 +1898,7 @@ synchronized private void generateHCSServerDaemon(boolean skipSignonServer) thro try { socketContainer = PortMapper.getServerSocket( - (systemNameLocal_) ? "localhost" : systemName_, AS400.HOSTCNN, -1, + (systemNameLocal_) ? "localhost" : systemName_, AS400.HOSTCNN, overridePort, useSSLConnection_, socketProperties_, mustUseNetSockets_); connectionID = socketContainer.hashCode(); @@ -1910,6 +1920,7 @@ synchronized private void generateHCSServerDaemon(boolean skipSignonServer) thro AS400XChgRandSeedReplyDS xChgReply = new AS400XChgRandSeedReplyDS(); if (Trace.traceOn_) xChgReply.setConnectionID(connectionID); + xChgReply.read(inStream); if (xChgReply.getRC() != 0) @@ -1986,11 +1997,15 @@ synchronized private void generateHCSServerDaemon(boolean skipSignonServer) thro HCSAuthdServer_ = new AS400NoThreadServer(this, AS400.HOSTCNN, socketContainer, jobString); } - catch (ConnectException e) + catch (ConnectException e) { forceDisconnect(e, HCSAuthdServer_, socketContainer); HCSAuthdServer_ = null; } + catch (java.net.SocketException e) { + forceDisconnect(e, HCSAuthdServer_, socketContainer); + HCSAuthdServer_ = null; + } catch (IOException | AS400SecurityException | RuntimeException e) { forceDisconnect(e, HCSAuthdServer_, socketContainer); @@ -5181,4 +5196,14 @@ private static byte[] generateSha512Protected(byte[] bytes, byte[] token, return protectedPassword; } //@AF2 End + +@Override +public void setVRM(int v, int r, int m) { + if (signonInfo_ == null) { + signonInfo_ = new SignonInfo((v << 16) + (r << 8) + m); + } else { + signonInfo_.version.setVersionReleaseModification((v << 16) + (r << 8) + m); + } + +} } \ No newline at end of file diff --git a/src/main/java/com/ibm/as400/access/AS400JDBCConnectionImpl.java b/src/main/java/com/ibm/as400/access/AS400JDBCConnectionImpl.java index c92a36c0d..d4581bad5 100644 --- a/src/main/java/com/ibm/as400/access/AS400JDBCConnectionImpl.java +++ b/src/main/java/com/ibm/as400/access/AS400JDBCConnectionImpl.java @@ -4384,7 +4384,7 @@ else if (lobThreshold >= 15728640) // @E6A JDTrace.logInformation(this, "True auto-commit supported = true"); JDTrace.logInformation(this, "128 byte column names supported = true"); JDTrace.logInformation(this, "128 length schema names supported = true"); - JDTrace.logInformation(this, "client support 0x04000000 set"); + JDTrace.logInformation(this, "client support 0x04000000 boolean"); JDTrace.logInformation(this, "client support 0x02000000 multiple SQLCAs"); } diff --git a/src/main/java/com/ibm/as400/access/AS400JDBCDriver.java b/src/main/java/com/ibm/as400/access/AS400JDBCDriver.java index 3e24cb21a..3934bb6a4 100644 --- a/src/main/java/com/ibm/as400/access/AS400JDBCDriver.java +++ b/src/main/java/com/ibm/as400/access/AS400JDBCDriver.java @@ -20,9 +20,11 @@ import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; +import java.sql.ResultSet; import java.sql.SQLException; /* ifdef JDBC40 */ import java.sql.SQLFeatureNotSupportedException; +import java.sql.Statement; import java.util.logging.Logger; /* endif */ import java.util.Properties; @@ -1447,7 +1449,14 @@ public boolean jdbcCompliant () //@B6A -- This logic was formerly in the initializeConnection() method. private Connection prepareConnection(AS400 as400, JDDataSourceURL dataSourceUrl, - JDProperties jdProperties) + JDProperties jdProperties) throws SQLException { + return prepareConnection(as400,dataSourceUrl, jdProperties, false); + } + + + private Connection prepareConnection(AS400 as400, JDDataSourceURL dataSourceUrl, + JDProperties jdProperties, + boolean vrmSet) throws SQLException { @@ -1548,6 +1557,31 @@ private Connection prepareConnection(AS400 as400, JDDataSourceURL dataSourceUrl, throw sqlex; } } + // + // If the signon server was skipped, we need to manually determine the release + // This is important for boolean support + // + if (as400.skipSignonServer & ! vrmSet) { + try { + Statement s = connection.createStatement(); + ResultSet rs = s.executeQuery("SELECT OS_VERSION,OS_RELEASE FROM SYSIBMADM.ENVSYSINFO"); + if (rs.next()) { + int version = rs.getInt(1); + int release = rs.getInt(2); + as400.setVRM(version,release,0); + } + rs.close(); + s.close(); + } catch (SQLException sqlex) { + // Log and ignore + } + // + // Connect again to get the correct settings + // This didn't work!!!! TODO; + // + connection.close(); + return prepareConnection(as400,dataSourceUrl, jdProperties, true); + } return connection; } diff --git a/src/main/java/com/ibm/as400/access/JobCCSIDNative.java b/src/main/java/com/ibm/as400/access/JobCCSIDNative.java index 4a7500cd4..02628bd84 100644 --- a/src/main/java/com/ibm/as400/access/JobCCSIDNative.java +++ b/src/main/java/com/ibm/as400/access/JobCCSIDNative.java @@ -30,7 +30,7 @@ static int retrieveCcsid() throws ErrorCompletingRequestException { try { - if (AS400.nativeVRM.vrm_ < 0x00050300) + if (AS400.nativeVRM.getVersionReleaseModification() < 0x00050300) { return new NLSImplNative().ccsidNative(); } diff --git a/src/main/java/com/ibm/as400/access/PortMapper.java b/src/main/java/com/ibm/as400/access/PortMapper.java index 7a877f4ee..8c39383b6 100644 --- a/src/main/java/com/ibm/as400/access/PortMapper.java +++ b/src/main/java/com/ibm/as400/access/PortMapper.java @@ -119,7 +119,7 @@ private static boolean canUseUnixSocket(String systemName, int service, boolean { if (AS400.onAS400 && unixSocketAvailable && !mustUseNetSockets && service != AS400.FILE && (systemName.equalsIgnoreCase("localhost") || systemName.equalsIgnoreCase("ipv6-localhost"))) { - if (service == AS400.DATABASE && AS400.nativeVRM.vrm_ < 0x00060100) return false; + if (service == AS400.DATABASE && AS400.nativeVRM.getVersionReleaseModification() < 0x00060100) return false; return true; } return false; @@ -142,7 +142,7 @@ static SocketContainer getServerSocket(String systemName, try { if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Starting a local socket to " + serviceName); - sc = AS400.nativeVRM.vrm_ < 0x00050400 ? (SocketContainer)AS400.loadImpl("com.ibm.as400.access.SocketContainerUnix") : (SocketContainer)AS400.loadImpl("com.ibm.as400.access.SocketContainerUnix2"); + sc = AS400.nativeVRM.getVersionReleaseModification()< 0x00050400 ? (SocketContainer)AS400.loadImpl("com.ibm.as400.access.SocketContainerUnix") : (SocketContainer)AS400.loadImpl("com.ibm.as400.access.SocketContainerUnix2"); if (sc != null) { sc.setProperties(null, serviceName, null, 0, null); diff --git a/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java b/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java index d556ab22a..2e96c2f7b 100644 --- a/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java +++ b/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java @@ -62,9 +62,9 @@ protected void openOnThread() throws AS400SecurityException, ErrorCompletingRequ { converter_ = ConverterImplRemote.getConverter(system_.getCcsid(), system_); } - if (AS400.nativeVRM.vrm_ >= 0x00050300) + if (AS400.nativeVRM.getVersionReleaseModification()>= 0x00050300) { - if (AS400.nativeVRM.vrm_ >= 0x00060100) + if (AS400.nativeVRM.getVersionReleaseModification()>= 0x00060100) { serverDataStreamLevel_ = 10; if (unicodeConverter_ == null) { @@ -345,7 +345,7 @@ private boolean runCommandOnThread(String command, int messageOption, boolean cu } if (!currentlyOpeningOnThisThread) openOnThread(); - if (AS400.nativeVRM.vrm_ >= 0x00060100) + if (AS400.nativeVRM.getVersionReleaseModification()>= 0x00060100) { return runCommandOnThread(unicodeConverter_.stringToByteArray(command), messageOption, 1200); } @@ -382,7 +382,7 @@ private boolean runCommandOnThread(byte[] commandBytes, int messageOption, int c try { if (Trace.traceOn_) Trace.log(Trace.INFORMATION, "Invoking native method."); - if (AS400.nativeVRM.vrm_ < 0x00050300) + if (AS400.nativeVRM.getVersionReleaseModification()< 0x00050300) { try { @@ -405,7 +405,7 @@ private boolean runCommandOnThread(byte[] commandBytes, int messageOption, int c { try { - byte[] replyBytes = AS400.nativeVRM.vrm_ < 0x00060100 ? runCommandNativeV5R3(commandBytes, messageOption) : NativeMethods.runCommand(commandBytes, ccsid, messageOption); + byte[] replyBytes = AS400.nativeVRM.getVersionReleaseModification()< 0x00060100 ? runCommandNativeV5R3(commandBytes, messageOption) : NativeMethods.runCommand(commandBytes, ccsid, messageOption); if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Native reply bytes:", replyBytes); // Get info from reply. @@ -479,7 +479,7 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet // Run the program on-thread. if (!currentlyOpeningOnThisThread) openOnThread(); - if (AS400.nativeVRM.vrm_ < 0x00050300) + if (AS400.nativeVRM.getVersionReleaseModification()< 0x00050300) { // Create a "call program" request, and write it as raw bytes to a byte array. // Set up the buffer that contains the program to call. The buffer contains three items: @@ -640,7 +640,7 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet { // Call native method. if (Trace.traceOn_) Trace.log(Trace.INFORMATION, "Invoking native method."); - byte[] replyBytes = AS400.nativeVRM.vrm_ < 0x00060100 ? runProgramNativeV5R3(nameBytes, libraryBytes, parameterList.length, offsetArray, programParameters, messageOption) : NativeMethods.runProgram(nameBytes, libraryBytes, parameterList.length, offsetArray, programParameters, messageOption); + byte[] replyBytes = AS400.nativeVRM.getVersionReleaseModification()< 0x00060100 ? runProgramNativeV5R3(nameBytes, libraryBytes, parameterList.length, offsetArray, programParameters, messageOption) : NativeMethods.runProgram(nameBytes, libraryBytes, parameterList.length, offsetArray, programParameters, messageOption); if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Native reply bytes:", replyBytes); // Reset the message list. diff --git a/src/main/java/com/ibm/as400/access/RemoteCommandImplRemote.java b/src/main/java/com/ibm/as400/access/RemoteCommandImplRemote.java index 83fd447ab..ffa52986f 100644 --- a/src/main/java/com/ibm/as400/access/RemoteCommandImplRemote.java +++ b/src/main/java/com/ibm/as400/access/RemoteCommandImplRemote.java @@ -229,8 +229,8 @@ public int getThreadsafeIndicator(String command) throws AS400SecurityException, // If the command is not a proxy command, retrieve information for the specified command. //@A1A int numParms; - if ((AS400.nativeVRM.vrm_ >= 0x00060100) || - (AS400.nativeVRM.vrm_ >= 0x00050400 && !system_.isMissingPTF())) { + if ((AS400.nativeVRM.getVersionReleaseModification()>= 0x00060100) || + (AS400.nativeVRM.getVersionReleaseModification()>= 0x00050400 && !system_.isMissingPTF())) { numParms = 6; // @A1C - added support for proxy commands } else numParms = 5; @@ -252,7 +252,7 @@ public int getThreadsafeIndicator(String command) throws AS400SecurityException, { // If the exception is "MCH0802: Total parameters passed does not match number required" and we're running to V5R4, that means that the user hasn't applied PTF SI29629. In that case, we will re-issue the program call, minus the new "follow proxy chain" parameter. if (numParms > 5 && - AS400.nativeVRM.vrm_ < 0x00060100 && AS400.nativeVRM.vrm_ >= 0x00050400 && + AS400.nativeVRM.getVersionReleaseModification()< 0x00060100 && AS400.nativeVRM.getVersionReleaseModification()>= 0x00050400 && messageList_[messageList_.length - 1].getID().equals("MCH0802")) { if (Trace.traceOn_) Trace.log(Trace.WARNING, "PTF SI29629 is not installed: (MCH0802) " + messageList_[messageList_.length - 1].getText()); diff --git a/src/main/java/com/ibm/as400/access/ServerVersion.java b/src/main/java/com/ibm/as400/access/ServerVersion.java index 613cc66af..48b77b408 100644 --- a/src/main/java/com/ibm/as400/access/ServerVersion.java +++ b/src/main/java/com/ibm/as400/access/ServerVersion.java @@ -20,7 +20,7 @@ class ServerVersion implements Serializable private static final String copyright = "Copyright (C) 1997-2000 International Business Machines Corporation and others."; static final long serialVersionUID = 4L; - int vrm_; + private int vrm_; // Create a version object. // @param int version/release/modification. High 16 bits represent version next 8 bits represent release, low 8 bits represent modification. Thus Version 3, release 1, modification level 0 is 0x00030100. @@ -56,4 +56,10 @@ int getVersionReleaseModification() { return vrm_; } + + void setVersionReleaseModification(int vrm) + { + vrm_ = vrm; + } + } diff --git a/src/main/java/com/ibm/as400/access/SignonInfo.java b/src/main/java/com/ibm/as400/access/SignonInfo.java index e03040d22..45af29fdc 100644 --- a/src/main/java/com/ibm/as400/access/SignonInfo.java +++ b/src/main/java/com/ibm/as400/access/SignonInfo.java @@ -30,4 +30,10 @@ class SignonInfo implements Serializable // Note: not maintained as com.ibm.as400.security.auth.ProfileToken. Class is currently not available in proxy environments, so don't want to force instantiation during signon. Object profileToken; String userId; + + SignonInfo() { } + + SignonInfo(int vrm) { + version = new ServerVersion(vrm); + } }