Skip to content

Commit

Permalink
IFSFile CCSID fix, jdbcClient reflection fix, swap refactoring, (#220)
Browse files Browse the repository at this point in the history
Signed-off-by: John Eberhard <[email protected]>
  • Loading branch information
jeber-ibm authored Nov 22, 2024
1 parent f52014e commit 16dca80
Show file tree
Hide file tree
Showing 14 changed files with 547 additions and 404 deletions.
152 changes: 69 additions & 83 deletions src/main/java/com/ibm/as400/access/AS400FileImplNative.java

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/main/java/com/ibm/as400/access/AS400ImplProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void generateProfileToken(ProfileTokenCredential profileToken, String use
new boolean[] { true, false }, // indicate that 1st arg gets modified
true);
ProfileTokenCredential returnArg = (ProfileTokenCredential)rv.getArgument(0);
profileToken.setToken(returnArg.getToken());
profileToken.setToken(returnArg.getToken(),false);
return;
}
catch (InvocationTargetException e)
Expand All @@ -165,7 +165,7 @@ public void generateProfileToken(ProfileTokenCredential profileToken, String use
new boolean[] { true, false, false, false }, // indicate that 1st arg gets modified
true);
ProfileTokenCredential returnArg = (ProfileTokenCredential)rv.getArgument(0);
profileToken.setToken(returnArg.getToken());
profileToken.setToken(returnArg.getToken(),false);
return;
}
catch (InvocationTargetException e)
Expand Down
77 changes: 53 additions & 24 deletions src/main/java/com/ibm/as400/access/AS400ImplRemote.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ public class AS400ImplRemote implements AS400Impl
// Additional authentication factor. We have to hold on to it because it may be timed, and thus can be reused.
private byte[] additionalAuthFactor_;

// Profile handles used by swapTo / swapBack
private byte[] swapToPH_ = null;
private byte[] swapFromPH_ = null;

private static final String CLASSNAME = "com.ibm.as400.access.AS400ImplRemote";

static {
Expand Down Expand Up @@ -938,7 +942,7 @@ public void generateProfileToken(ProfileTokenCredential profileToken, String use
Trace.log(Trace.ERROR, "Start server failed with return code:", rcBytes);
throw AS400ImplRemote.returnSecurityException(reply.getRC(), null, userId_);
}

// [0]=factor, [1]=verification ID, [2]=remote ip address
Object[] additonalAuthInfo = getAdditionalAuthInfo(profileToken, null);

Expand All @@ -959,7 +963,13 @@ public void generateProfileToken(ProfileTokenCredential profileToken, String use
userId_);
}
try {
profileToken.setToken(rep.getProfileTokenBytes());
boolean enhancedProfileToken = false;
int vrm = (version_ != null) ? version_.getVersionReleaseModification() : getVRM();
if (vrm > 0x00070500 ) {
enhancedProfileToken = true; /* server always generates enhanced profile token */
}

profileToken.setToken(rep.getProfileTokenBytes(), enhancedProfileToken);
profileToken.setTokenCreator(ProfileTokenCredential.CREATOR_SIGNON_SERVER);
}
catch (PropertyVetoException e) {
Expand Down Expand Up @@ -1141,7 +1151,13 @@ else if (passwordLevel_ < 4)
}

try {
profileToken.setToken(rep.getProfileTokenBytes());
boolean enhancedProfileToken = false;
int vrm = (version_ != null) ? version_.getVersionReleaseModification() : getVRM();
if (vrm > 0x00070500 ) {
enhancedProfileToken = true; /* server always generates enhanced profile token */
}

profileToken.setToken(rep.getProfileTokenBytes(), enhancedProfileToken);
profileToken.setTokenCreator(ProfileTokenCredential.CREATOR_SIGNON_SERVER);
} catch (PropertyVetoException e) {
Trace.log(Trace.ERROR, e);
Expand Down Expand Up @@ -1503,7 +1519,15 @@ synchronized AS400Server getConnection(int service, int overridePort, boolean fo
authScheme = AS400.AUTHENTICATION_SCHEME_DDM_EUSERIDPWD;

userIDbytes = getEncryptedUserid(sharedKeyBytes, serverSeed);
ddmSubstitutePassword = getDdmEncryptedPassword(sharedKeyBytes, serverSeed);
if (credVault_.isEmpty() &&
!mustUseSuppliedProfile_
&& AS400.onAS400
&& AS400.currentUserAvailable()
&& userId_.equals(CurrentUser.getUserID(AS400.nativeVRM.getVersionReleaseModification()))) {
ddmSubstitutePassword = getPassword(clientSeed, serverSeed);
} else {
ddmSubstitutePassword = getDdmEncryptedPassword(sharedKeyBytes, serverSeed);
}
}
else
{
Expand Down Expand Up @@ -1818,7 +1842,7 @@ byte[] getPassword(byte[] clientSeed, byte[] serverSeed) throws AS400SecurityExc
&& userId_.equals(CurrentUser.getUserID(AS400.nativeVRM.getVersionReleaseModification())))
{
encryptedPassword = CurrentUser.getUserInfo(AS400.nativeVRM.getVersionReleaseModification(), clientSeed, serverSeed, userId_);
Trace.log(Trace.DIAGNOSTIC, " encrypted password retrieved");
Trace.log(Trace.DIAGNOSTIC, " encrypted password retrieved1");
}
else {
Trace.log(Trace.ERROR, "Password is null.");
Expand Down Expand Up @@ -2039,20 +2063,14 @@ private byte[] getEncryptedUserid(byte[] sharedPrivateKey, byte[] serverSeed) th
&& AS400.currentUserAvailable()
&& userId_.equals(CurrentUser.getUserID(AS400.nativeVRM.getVersionReleaseModification())))
{
// TODO:Think about what to do in this case
// encryptedPassword =
// CurrentUser.getUserInfo(AS400.nativeVRM.getVersionReleaseModification(),
// clientSeed, serverSeed, userId_);
Trace.log(Trace.DIAGNOSTIC, " encrypted password retrieved");
// For now throw exception
throw new AS400SecurityException(AS400SecurityException.PASSWORD_NOT_SET);
// Fall into code below
}
else {
Trace.log(Trace.ERROR, "Password is null.");
Trace.log(Trace.ERROR, "Password is null and unable to determine password at later time");
throw new AS400SecurityException(AS400SecurityException.PASSWORD_NOT_SET);
}
}
else

{
byte[] userIdEbcdic = SignonConverter.stringToByteArray(userId_);
if (PASSWORD_TRACE) {
Expand Down Expand Up @@ -3424,16 +3442,14 @@ public SignonInfo signon(String systemName, boolean systemNameLocal, String user

if (canUseNativeOptimization_)
{
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
// If -Xshareclasses is specified when using Java on an IBM i system
// then classes cannot be loaded when the profile is swapped. Load the classes before doing the swap.
Class x = BinaryConverter.class;
x = GregorianCalendar.class;
x = SignonInfo.class;
x = com.ibm.as400.access.NLSImplNative.class;
x = com.ibm.as400.access.NLSImplRemote.class;
boolean didSwap = swapTo(swapToPH, swapFromPH);
boolean didSwap = swapTo();
try
{
byte[] data = AS400ImplNative.signonNative(SignonConverter.stringToByteArray(userId));
Expand Down Expand Up @@ -3462,7 +3478,7 @@ public SignonInfo signon(String systemName, boolean systemNameLocal, String user
}
finally {
if (didSwap)
swapBack(swapToPH, swapFromPH);
swapBack();
}

return signonInfo_;
Expand Down Expand Up @@ -3649,7 +3665,7 @@ public SignonInfo skipSignon(String systemName, boolean systemNameLocal,
x = SignonInfo.class;
x = com.ibm.as400.access.NLSImplNative.class;
x = com.ibm.as400.access.NLSImplRemote.class;
boolean didSwap = swapTo(swapToPH, swapFromPH);
boolean didSwap = swapTo();
try {
byte[] data = AS400ImplNative.signonNative(SignonConverter
.stringToByteArray(userId));
Expand Down Expand Up @@ -3677,7 +3693,7 @@ public SignonInfo skipSignon(String systemName, boolean systemNameLocal,
throw mapNativeSecurityException(e);
} finally {
if (didSwap)
swapBack(swapToPH, swapFromPH);
swapBack();
}
}
else
Expand Down Expand Up @@ -4046,7 +4062,7 @@ private synchronized void signonDisconnect()
fireConnectEvent(false, AS400.SIGNON);
}

boolean swapTo(byte[] swapToPH, byte[] swapFromPH) throws AS400SecurityException, IOException
boolean swapTo() throws AS400SecurityException, IOException
{
if (AS400.onAS400
&& AS400.currentUserAvailable()
Expand All @@ -4058,6 +4074,11 @@ boolean swapTo(byte[] swapToPH, byte[] swapFromPH) throws AS400SecurityException
throw new AS400SecurityException(AS400SecurityException.PASSWORD_NOT_SET);
}

if (swapToPH_ != null || swapFromPH_ != null) {
Trace.log(Trace.ERROR, "Nested swapTo / swapBack calls.");
throw new AS400SecurityException(AS400SecurityException.UNKNOWN);
}

byte[] temp = credVault_.getClearCredential();
try
{
Expand All @@ -4067,7 +4088,12 @@ boolean swapTo(byte[] swapToPH, byte[] swapFromPH) throws AS400SecurityException
throw new AS400SecurityException(AS400SecurityException.SIGNON_CHAR_NOT_VALID);
}

AS400ImplNative.swapToNative(SignonConverter.stringToByteArray(userId_), temp, swapToPH, swapFromPH);
// Initialize the values before swapping.
// TODO: Need to change this code when we cache the swapToPH_ (and authenticate with the password once)
swapToPH_ = new byte[12];
swapFromPH_ = new byte[12];

AS400ImplNative.swapToNative(SignonConverter.stringToByteArray(userId_), temp, swapToPH_, swapFromPH_);
}
catch (NativeException e) {
throw mapNativeSecurityException(e);
Expand All @@ -4078,12 +4104,15 @@ boolean swapTo(byte[] swapToPH, byte[] swapFromPH) throws AS400SecurityException
return true;
}

void swapBack(byte[] swapToPH, byte[] swapFromPH) throws AS400SecurityException, IOException
void swapBack() throws AS400SecurityException, IOException
{
try {
AS400ImplNative.swapBackNative(swapToPH, swapFromPH);
AS400ImplNative.swapBackNative(swapToPH_, swapFromPH_);
} catch (NativeException e) {
throw mapNativeSecurityException(e);
} finally {
swapToPH_ = null;
swapFromPH_ = null;
}
}

Expand Down
48 changes: 24 additions & 24 deletions src/main/java/com/ibm/as400/access/BaseDataQueueImplNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public void setSystemAndPath(AS400Impl system, String path, String name, String
public void clear(byte[] key) throws AS400SecurityException, ErrorCompletingRequestException, IOException, IllegalObjectTypeException, InterruptedException, ObjectDoesNotExistException
{
// Call native method.
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
if (key == null)
Expand All @@ -65,7 +65,7 @@ public void clear(byte[] key) throws AS400SecurityException, ErrorCompletingRequ
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}
}

Expand All @@ -80,9 +80,9 @@ public void create(int maxEntryLength, String authority, boolean saveSenderInfor
byte[] commandBytes = converter_.stringToByteArray(command);

// Call native method.
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
createNative(commandBytes);
Expand All @@ -98,7 +98,7 @@ public void create(int maxEntryLength, String authority, boolean saveSenderInfor
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}
}

Expand All @@ -112,9 +112,9 @@ public void delete() throws AS400SecurityException, ErrorCompletingRequestExcept
byte[] commandBytes = converter_.stringToByteArray(command);

// Call native method.
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
deleteNative(commandBytes);
Expand All @@ -125,7 +125,7 @@ public void delete() throws AS400SecurityException, ErrorCompletingRequestExcept
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}
}

Expand All @@ -146,9 +146,9 @@ public DQReceiveRecord read(String search, int wait, boolean peek, byte[] key) t
System.arraycopy(key, 0, newKey, 0, key.length);
}

byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
DQQueryRecord qr = retrieveAttributes(key != null);
Expand All @@ -171,7 +171,7 @@ public DQReceiveRecord read(String search, int wait, boolean peek, byte[] key) t
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}
}

Expand All @@ -182,9 +182,9 @@ public DQQueryRecord retrieveAttributes(boolean keyed) throws AS400SecurityExcep
byte[] attributes = new byte[61];

// Call native method.
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
retrieveAttributesNative(libraryBytes_, queueNameBytes_, attributes);
Expand All @@ -195,7 +195,7 @@ public DQQueryRecord retrieveAttributes(boolean keyed) throws AS400SecurityExcep
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}

// Verify data queue type and set attribute.
Expand Down Expand Up @@ -239,9 +239,9 @@ else if (attributes[8] == (byte)0xD3) // LIFO.
// Key is null for non-keyed queues.
public void write(byte[] key, byte[] data) throws AS400SecurityException, ErrorCompletingRequestException, IOException, IllegalObjectTypeException, InterruptedException, ObjectDoesNotExistException
{
byte[] swapToPH = new byte[12];
byte[] swapFromPH = new byte[12];
boolean didSwap = system_.swapTo(swapToPH, swapFromPH);


boolean didSwap = system_.swapTo();
try
{
// Call native method.
Expand All @@ -260,7 +260,7 @@ public void write(byte[] key, byte[] data) throws AS400SecurityException, ErrorC
}
finally
{
if (didSwap) system_.swapBack(swapToPH, swapFromPH);
if (didSwap) system_.swapBack();
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/main/java/com/ibm/as400/access/IFSFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -1109,8 +1109,13 @@ public int getCCSID() throws IOException
if (impl_ == null)
chooseImpl();

if (!isFile())
return impl_.getCCSID();
if (!isFile()) {
if (exists()) {
return impl_.getCCSID();
} else {
return -1;
}
}

return impl_.getCCSID(true);
}
Expand Down
Loading

0 comments on commit 16dca80

Please sign in to comment.