diff --git a/src/main/java/com/ibm/as400/access/AS400FileImplNative.java b/src/main/java/com/ibm/as400/access/AS400FileImplNative.java index 7b5147cd..d6b5df31 100644 --- a/src/main/java/com/ibm/as400/access/AS400FileImplNative.java +++ b/src/main/java/com/ibm/as400/access/AS400FileImplNative.java @@ -82,9 +82,7 @@ public void close() { super.close(); //@C0A - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { synchronized(synch_open_close_) @@ -100,7 +98,7 @@ public void close() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -129,9 +127,7 @@ native void closeNtv(int handle) public void commit() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { // Commit transactions under commitment control. @@ -144,7 +140,7 @@ public void commit() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -268,7 +264,7 @@ else if (!msgs[0].getID().equals("CPC7301")) //@C2 if (converter_ == null) setConverter(); //@C2A //@C2 text80.setConverter(converter_); //@C2A srcRF.addFieldDescription(new CharacterFieldDescription(new AS400Text(80, system_.getCcsid()), "SRCDTA")); - Vector lines = new Vector(); // Contains DDS lines to write to source file + Vector lines = new Vector(); // Contains DDS lines to write to source file String line; // A single line of DDS source // Create line(s) for any file level keywords - file level keywords must precede // the line specifying the record format name. @@ -465,9 +461,7 @@ public void deleteCurrentRecord() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { byte[] optl = {0x00, SHR_READ_NORM_RLS, DATA_DTA_DTARCD, 0x08}; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { // Delete the current record. @@ -480,7 +474,7 @@ public void deleteCurrentRecord() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -512,9 +506,7 @@ public AS400Message[] execute(String cmd) // Note the execution of the command is synchronized on the static // variable synch_execute_ BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { synchronized(synch_execute_) @@ -524,7 +516,7 @@ public AS400Message[] execute(String cmd) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the message feedback data. @@ -671,9 +663,7 @@ public DDMS38OpenFeedback openFile(int openType, int bf, String access) byte[] ufcb = createUFCB(openType, bf, access, true); BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { synchronized(synch_open_close_) @@ -689,7 +679,7 @@ public DDMS38OpenFeedback openFile(int openType, int bf, String access) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the message feedback data. AS400Message[] msgs = parseMsgFeedback(data); @@ -946,9 +936,9 @@ public void positionCursorAfterLast() // Use force end of data. byte[] optl = { TYPE_GET_LAST, SHR_READ_NORM_RLS, DATA_NODTA_DTARCD, OPER_GET }; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { forceEndOfData(handle_, optl); @@ -960,7 +950,7 @@ public void positionCursorAfterLast() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -1002,9 +992,9 @@ public Record[] positionCursorAt(int type) BinaryConverter.shortToByteArray((short) blockingFactor_, ctll, 3); //@C0C ctll[5] = (byte)0xFF; // End of control list BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { data = @@ -1019,7 +1009,7 @@ public Record[] positionCursorAt(int type) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1063,9 +1053,9 @@ public void positionCursorBeforeFirst() // Use Force end of data to set the cursor. byte[] optl = { TYPE_GET_FIRST, SHR_READ_NORM_RLS, DATA_NODTA_DTARCD, OPER_GET }; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { forceEndOfData(handle_, optl); @@ -1077,7 +1067,7 @@ public void positionCursorBeforeFirst() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -1155,9 +1145,9 @@ public Record positionCursorToIndex(int index) ctll[25] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETD. @@ -1173,7 +1163,7 @@ public Record positionCursorToIndex(int index) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1370,9 +1360,9 @@ public Record positionCursorToKey(Object[] keys, ctll[28 + keyLength] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETK @@ -1388,7 +1378,7 @@ public Record positionCursorToKey(Object[] keys, } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1450,7 +1440,6 @@ public Record positionCursorToKey(byte[] keys, byte[] optl = { (byte)searchType, share, DATA_DTA_DTARCD, OPER_GETK }; // Determine the total length of all data in keyFields. - FieldDescription description; int keyLength = keys.length; // CTLL @@ -1497,9 +1486,9 @@ public Record positionCursorToKey(byte[] keys, ctll[28 + keyLength] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETK @@ -1515,7 +1504,7 @@ public Record positionCursorToKey(byte[] keys, } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1619,9 +1608,9 @@ public Record read(int index) ctll[25] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETD @@ -1637,7 +1626,7 @@ public Record read(int index) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1821,9 +1810,9 @@ public Record read(Object[] key, ctll[28 + keyLength] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETK. @@ -1839,7 +1828,7 @@ public Record read(Object[] key, } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -1898,7 +1887,6 @@ public Record read(byte[] key, byte[] optl = { (byte)searchType, share, DATA_DTA_DTARCD, OPER_GETK }; // Determine the total length of all data in keyFields. - FieldDescription description; int keyLength = key.length; // CTLL @@ -1945,9 +1933,9 @@ public Record read(byte[] key, ctll[28 + keyLength] = (byte) 0xff; BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GETK. @@ -1963,7 +1951,7 @@ public Record read(byte[] key, } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -2096,9 +2084,9 @@ public Record readRecord(int type) ctll[5] = (byte)0xFF; // End of control list BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // GET @@ -2114,7 +2102,7 @@ public Record readRecord(int type) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -2161,9 +2149,9 @@ public Record[] readRecords(int direction) int length = openFeedback_.getRecordIncrement() * blockingFactor_; //@C0C BytesWithOffset data = null; - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { data = @@ -2176,7 +2164,7 @@ public Record[] readRecords(int direction) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Parse the I/O feedback data. @@ -2212,9 +2200,9 @@ public Record[] readRecords(int direction) public void rollback() throws AS400Exception, AS400SecurityException, InterruptedException, IOException { - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // Rollback. @@ -2227,7 +2215,7 @@ public void rollback() } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -2306,9 +2294,9 @@ public void update(Record record) recordData[fieldOffset] = (record.isNullField(i))? (byte)0xF1 : (byte)0xF0; } - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // UPDAT @@ -2321,7 +2309,7 @@ public void update(Record record) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -2413,9 +2401,9 @@ public void write(Record[] records) { byte[] dataToWrite = new byte[offset + recordIncrement]; System.arraycopy(recordData, 0, dataToWrite, 0, dataToWrite.length); - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // PUT @@ -2428,14 +2416,12 @@ public void write(Record[] records) } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } else if (r == records.length || (r % blockingFactor_ == 0)) //@C0C { - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + boolean didSwap = system_.swapTo(); try { // PUT @@ -2448,7 +2434,7 @@ else if (r == records.length || (r % blockingFactor_ == 0)) //@C0C } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } // Reset the offset. diff --git a/src/main/java/com/ibm/as400/access/AS400ImplProxy.java b/src/main/java/com/ibm/as400/access/AS400ImplProxy.java index ad7f9aa3..b2e44888 100644 --- a/src/main/java/com/ibm/as400/access/AS400ImplProxy.java +++ b/src/main/java/com/ibm/as400/access/AS400ImplProxy.java @@ -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) @@ -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) diff --git a/src/main/java/com/ibm/as400/access/AS400ImplRemote.java b/src/main/java/com/ibm/as400/access/AS400ImplRemote.java index c97e75bd..a908f935 100644 --- a/src/main/java/com/ibm/as400/access/AS400ImplRemote.java +++ b/src/main/java/com/ibm/as400/access/AS400ImplRemote.java @@ -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 { @@ -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); @@ -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) { @@ -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); @@ -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 { @@ -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."); @@ -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) { @@ -3424,8 +3442,6 @@ 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; @@ -3433,7 +3449,7 @@ public SignonInfo signon(String systemName, boolean systemNameLocal, String user 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)); @@ -3462,7 +3478,7 @@ public SignonInfo signon(String systemName, boolean systemNameLocal, String user } finally { if (didSwap) - swapBack(swapToPH, swapFromPH); + swapBack(); } return signonInfo_; @@ -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)); @@ -3677,7 +3693,7 @@ public SignonInfo skipSignon(String systemName, boolean systemNameLocal, throw mapNativeSecurityException(e); } finally { if (didSwap) - swapBack(swapToPH, swapFromPH); + swapBack(); } } else @@ -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() @@ -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 { @@ -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); @@ -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; } } diff --git a/src/main/java/com/ibm/as400/access/BaseDataQueueImplNative.java b/src/main/java/com/ibm/as400/access/BaseDataQueueImplNative.java index 48ecc68c..c3fdcbc9 100644 --- a/src/main/java/com/ibm/as400/access/BaseDataQueueImplNative.java +++ b/src/main/java/com/ibm/as400/access/BaseDataQueueImplNative.java @@ -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) @@ -65,7 +65,7 @@ public void clear(byte[] key) throws AS400SecurityException, ErrorCompletingRequ } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -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); @@ -98,7 +98,7 @@ public void create(int maxEntryLength, String authority, boolean saveSenderInfor } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -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); @@ -125,7 +125,7 @@ public void delete() throws AS400SecurityException, ErrorCompletingRequestExcept } finally { - if (didSwap) system_.swapBack(swapToPH, swapFromPH); + if (didSwap) system_.swapBack(); } } @@ -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); @@ -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(); } } @@ -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); @@ -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. @@ -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. @@ -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(); } } diff --git a/src/main/java/com/ibm/as400/access/IFSFile.java b/src/main/java/com/ibm/as400/access/IFSFile.java index 135571f4..9dfd28fc 100644 --- a/src/main/java/com/ibm/as400/access/IFSFile.java +++ b/src/main/java/com/ibm/as400/access/IFSFile.java @@ -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); } diff --git a/src/main/java/com/ibm/as400/access/ProfileTokenImplNative.java b/src/main/java/com/ibm/as400/access/ProfileTokenImplNative.java index fcf0cf7a..45174ce4 100644 --- a/src/main/java/com/ibm/as400/access/ProfileTokenImplNative.java +++ b/src/main/java/com/ibm/as400/access/ProfileTokenImplNative.java @@ -57,34 +57,18 @@ public void destroy() throws DestroyFailedException if (Trace.isTraceOn()) Trace.log(Trace.INFORMATION, "Credential implementation destroyed >> " + toString()); } - @Deprecated - @Override - public byte[] generateToken(String uid, String pwd, int type, int timeoutInterval) throws RetrieveFailedException - { - if (pwd.length() > 10) - { - Trace.log(Trace.ERROR, "User profile password exceeds allowed length"); - throw new ExtendedIllegalArgumentException("password", ExtendedIllegalArgumentException.LENGTH_NOT_VALID); - } - - return nativeCreateToken(uid.toUpperCase(), pwd, type, timeoutInterval); - } - + /** * Generates and returns a new profile token based on * the provided information. * - * @deprecated As of V5R3, replaced - * by {@link #generateTokenExtended(String,String,int,int)} - * for password strings and {@link #generateToken(String,int,int,int)} - * for password special values. * * @param uid * The name of the user profile for which the token * is to be generated. * * @param pwd - * The user profile password or special value. + * The user profile password. * * @param type * The type of token. @@ -107,7 +91,6 @@ public byte[] generateToken(String uid, String pwd, int type, int timeoutInterva * If errors occur while generating the token. * */ - @Deprecated public byte[] generateToken(String uid, char[] pwd, int type, int timeoutInterval) throws RetrieveFailedException { if (pwd.length > 10) @@ -120,14 +103,33 @@ public byte[] generateToken(String uid, char[] pwd, int type, int timeoutInterva } @Override - public byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval) throws RetrieveFailedException { - return generateToken(uid, pwdSpecialValue, null, AuthenticationIndicator.APPLICATION_AUTHENTICATION, null, null, 0, null, 0, type, timeoutInterval); + public byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException { + return generateToken(uid, pwdSpecialValue, null, AuthenticationIndicator.APPLICATION_AUTHENTICATION, null, null, 0, null, 0, type, timeoutInterval, enhancedProfileToken); } + /** + * Generate a token using an ID and pwdSpecial value + * @param uid + * @param pwdSpecialValue + * @param additionalAuthenticationFactor + * @param authenticationIndicator + * @param verificationId + * @param remoteIpAddress + * @param remotePort + * @param localIpAddress + * @param localPort + * @param type + * @param timeoutInterval + * @param enhancedProfileToken -- input/output one element boolean array. On input if the first element is false, then an enhancedProfileToken will not be created. + * on output, the first element indicates if an enhancedProfileToken was created. + * @return + * @throws RetrieveFailedException + */ private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalAuthenticationFactor, int authenticationIndicator, String verificationId, String remoteIpAddress, int remotePort, String localIpAddress, int localPort, - int type, int timeoutInterval) throws RetrieveFailedException + int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException { + // Convert password special value from int to string String pwdSpecialVal; switch(pwdSpecialValue) @@ -147,18 +149,23 @@ private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalA // Call native method and return token bytes, we rely on the fact this class is only called if running on AS400. - if (!ProfileTokenCredential.useEnhancedProfileTokens() || AS400.nativeVRM.getVersionReleaseModification() <= 0x00070500) + if (!enhancedProfileToken[0] || !ProfileTokenCredential.useEnhancedProfileTokens() || AS400.nativeVRM.getVersionReleaseModification() <= 0x00070500) { + enhancedProfileToken[0]=false; /* Let the caller know this is NOT an enhanced profile token */ return nativeCreateTokenChar(uid.toUpperCase(), pwdSpecialVal.toCharArray(), type, timeoutInterval); - + } else { + enhancedProfileToken[0]=true; /* Let the caller know this is an enhanced profile token */ return EnhancedProfileTokenImplNative.nativeCreateTokenSpecialPassword(uid.toUpperCase(), pwdSpecialVal.toCharArray(), additionalAuthenticationFactor, authenticationIndicator, verificationId, remoteIpAddress, remotePort, localIpAddress, localPort, type, timeoutInterval); + } } @Override public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, ProfileTokenCredential profileTokenCred) throws RetrieveFailedException, PropertyVetoException { + boolean [] enhancedProfileToken = new boolean[1]; + enhancedProfileToken[0] = true; byte[] token = generateToken(uid, pwdSpecialValue, profileTokenCred.getAdditionalAuthenticationFactor(), profileTokenCred.getAuthenticationIndicator(), @@ -168,10 +175,11 @@ public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, Pro profileTokenCred.getLocalIPAddress(), profileTokenCred.getLocalPort(), profileTokenCred.getTokenType(), - profileTokenCred.getTimeoutInterval()); + profileTokenCred.getTimeoutInterval(), + enhancedProfileToken); try { - profileTokenCred.setToken(token); + profileTokenCred.setToken(token, enhancedProfileToken[0]); profileTokenCred.setTokenCreator(ProfileTokenCredential.CREATOR_NATIVE_API); } catch (PropertyVetoException e) @@ -189,68 +197,31 @@ public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, Pro return profileTokenCred; } - /** - * Generates and returns a new profile token based on - * the provided information using a password string. - * - * @deprecated Use {@link #generateTokenExtended(String,char[],int,int)} - * - * @param uid - * The name of the user profile for which the token - * is to be generated. - * - * @param pwd - * The user profile password (encoded). - * Special values are not supported by this method. - * - * @param type - * The type of token. - * Possible types are defined as fields on the - * ProfileTokenCredential class: - * - *

- * - * @param timeoutInterval - * The number of seconds to expiration. - * - * @return - * The token bytes. - * - * @exception RetrieveFailedException - * If errors occur while generating the token. - * - */ - @Deprecated - public byte[] generateTokenExtended(String uid, String pwd, int type, int timeoutInterval) throws RetrieveFailedException - { - char[] passwordChars = (pwd == null) ? null : pwd.toCharArray(); - - try { - return generateTokenExtended(uid, passwordChars, type, timeoutInterval); - } finally { - AS400Credential.clearArray(passwordChars); - } - } @Override - public byte[] generateTokenExtended(String uid, char [] pwd, int type, int timeoutInterval) throws RetrieveFailedException { - return generateTokenExtended(uid, pwd, null, null, null, 0, null, 0, type, timeoutInterval); + public byte[] generateTokenExtended(String uid, char [] pwd, int type, int timeoutInterval, boolean[] isEnhancedToken) throws RetrieveFailedException { + return generateTokenExtended(uid, pwd, null, null, null, 0, null, 0, type, timeoutInterval,isEnhancedToken); } private byte[] generateTokenExtended(String uid, char[] pwd, char[] additionalAuthenticationFactor, String verificationId, String remoteIpAddress, int remotePort, String localIpAddress, int localPort, - int type, int timeoutInterval) throws RetrieveFailedException + int type, int timeoutInterval, boolean[] isEnhancedToken) throws RetrieveFailedException { + if (Trace.isTraceOn()) { + String pwdInfo ="null"; + if (pwd != null) pwdInfo = "char["+pwd.length+"]"; + String aafInfo = "null"; + if (additionalAuthenticationFactor != null) aafInfo="char["+additionalAuthenticationFactor.length+"]"; + Trace.log(Trace.INFORMATION, this, "generateTokenExtended("+uid+","+pwdInfo+","+ + aafInfo+","+verificationId+","+remoteIpAddress+","+ + remotePort+","+localIpAddress+","+localPort+","+type+","+timeoutInterval+")"); + } AS400 sys = getCredential().getSystem(); // Determine if we are using enhanced profile tokens boolean useEPT = false; try { - useEPT = (ProfileTokenCredential.useEnhancedProfileTokens() && sys.getVRM() > 0x00070500); + useEPT = isEnhancedToken[0] && (ProfileTokenCredential.useEnhancedProfileTokens() && sys.getVRM() > 0x00070500); } catch (AS400SecurityException|IOException e) { Trace.log(Trace.ERROR, "Unexpected Exception: ", e); @@ -337,6 +308,10 @@ private byte[] generateTokenExtended(String uid, char[] pwd, char[] additionalAu // Input: Local port parmlist[18] = new ProgramParameter(BinaryConverter.intToByteArray(remotePort)); + + isEnhancedToken[0] = true; + } else { + isEnhancedToken[0] = false; } ProgramCall programCall = new ProgramCall(sys); @@ -362,14 +337,19 @@ private byte[] generateTokenExtended(String uid, char[] pwd, char[] additionalAu Trace.log(Trace.ERROR, "Unexpected Exception: ", e); throw new RetrieveFailedException(); } - - return parmlist[0].getOutputData(); + byte[] profileToken = parmlist[0].getOutputData(); + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION, this, "generateTokenExtended returned ",profileToken); + } + return profileToken; } @Override public ProfileTokenCredential generateTokenExtended(String uid, char[] password, ProfileTokenCredential profileTokenCred) throws RetrieveFailedException, PropertyVetoException { + boolean[] enhancedProfileToken = new boolean[1]; + enhancedProfileToken[0] = true; byte[] token = generateTokenExtended(uid, password, profileTokenCred.getAdditionalAuthenticationFactor(), profileTokenCred.getVerificationID(), @@ -378,10 +358,12 @@ public ProfileTokenCredential generateTokenExtended(String uid, char[] password, profileTokenCred.getLocalIPAddress(), profileTokenCred.getLocalPort(), profileTokenCred.getTokenType(), - profileTokenCred.getTimeoutInterval()); + profileTokenCred.getTimeoutInterval(), + enhancedProfileToken); + try { - profileTokenCred.setToken(token); + profileTokenCred.setToken(token,enhancedProfileToken[0]); profileTokenCred.setTokenCreator(ProfileTokenCredential.CREATOR_NATIVE_API); } catch (PropertyVetoException e) @@ -408,7 +390,11 @@ AS400Credential getCredential() { @Override public int getTimeToExpiration() throws RetrieveFailedException { - return nativeGetTimeToExpiration(((ProfileTokenCredential)getCredential()).getToken()); + byte[] token = ((ProfileTokenCredential)getCredential()).getToken(); + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION, this, "getTimeToExpiration token=", token); + } + return nativeGetTimeToExpiration(token); } @Override @@ -536,12 +522,16 @@ native void nativeSwap( @Override public void refresh() throws RefreshFailedException { - // Never called; ProfileTokenCredential relies exclusively on refresh(int, int). + // Never called; ProfileTokenCredential relies exclusively on refresh(int, int). + throw new NullPointerException("INVALID CODEPATH"); } @Override public byte[] refresh(int type, int timeoutInterval) throws RefreshFailedException { + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION,"refresh() called"); + } ProfileTokenCredential pt = ((ProfileTokenCredential)getCredential()); byte[] token = pt.getToken(); @@ -549,20 +539,32 @@ public byte[] refresh(int type, int timeoutInterval) throws RefreshFailedExcepti // to manipulate. byte[] bytes = new byte[ProfileTokenCredential.TOKEN_LENGTH]; System.arraycopy(token, 0, bytes, 0, bytes.length); - - if (!ProfileTokenCredential.useEnhancedProfileTokens() || AS400.nativeVRM.getVersionReleaseModification() <= 0x00070500) + + + if (!ProfileTokenCredential.useEnhancedProfileTokens() || AS400.nativeVRM.getVersionReleaseModification() <= 0x00070500) { + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION,this,"refresh input",token); + } + nativeRefreshToken(bytes, type, timeoutInterval); + } else { - // TODO AMRA - need to change native to throw proper exception try { - EnhancedProfileTokenImplNative.nativeCreateTokenFromToken(bytes, pt.getVerificationID(), pt.getRemoteIPAddress(), type, timeoutInterval); + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION,this,"calling createTokenFromtoken(bytes,"+pt.getVerificationID()+","+ + pt.getRemoteIPAddress()+","+type+","+timeoutInterval+")",token); + } + bytes = EnhancedProfileTokenImplNative.nativeCreateTokenFromToken(bytes, pt.getVerificationID(), pt.getRemoteIPAddress(), type, timeoutInterval); } catch (RetrieveFailedException e) { - Trace.log(Trace.ERROR, "Unexpected Exception: ", e); - throw new InternalErrorException(InternalErrorException.UNEXPECTED_EXCEPTION); + RefreshFailedException refreshFailed = new RefreshFailedException(e.getAS400MessageList()); + throw refreshFailed; } } + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION,this,"refresh output",token); + } return bytes; } @@ -591,8 +593,14 @@ public AS400Credential swap(boolean genRtnCr) throws SwapFailedException Trace.log(Trace.ERROR, "Unable to obtain current profile handle", e); } } - - nativeSwap(((ProfileTokenCredential)getCredential()).getToken()); + ProfileTokenCredential cred = (ProfileTokenCredential) getCredential(); + if (!cred.isEnhancedProfileToken()) { + nativeSwap(cred.getToken()); + } else { + EnhancedProfileTokenImplNative.nativeSwap(cred.getToken(), + cred.getVerificationID(), + cred.getRemoteIPAddress()); + } return ph; } } diff --git a/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java b/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java index 731a0c91..b3f3248a 100644 --- a/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java +++ b/src/main/java/com/ibm/as400/access/RemoteCommandImplNative.java @@ -375,9 +375,9 @@ public boolean runCommand(byte[] commandAsBytes, String commandAsString) throws private boolean runCommandOnThread(byte[] commandBytes, int messageOption, int ccsid) throws AS400SecurityException, ErrorCompletingRequestException, IOException, InterruptedException { - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); if (OFF_THREAD.equals(priorCallWasOnThread_)) if (Trace.traceOn_) Trace.log(Trace.DIAGNOSTIC, "Prior call was off-thread, but this call is on-thread, so different job."); @@ -427,7 +427,7 @@ private boolean runCommandOnThread(byte[] commandBytes, int messageOption, int c finally { if (didSwap) - system_.swapBack(swapToPH, swapFromPH); + system_.swapBack(); } } @@ -536,9 +536,9 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet Trace.log(Trace.DIAGNOSTIC, "Program parameter bytes:", programParameterStructure); Trace.log(Trace.DIAGNOSTIC, "Program parameters:", programParameters); } - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // Call native method. @@ -590,7 +590,7 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet finally { if (didSwap) - system_.swapBack(swapToPH, swapFromPH); + system_.swapBack(); } } else @@ -633,9 +633,9 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet Trace.log(Trace.DIAGNOSTIC, "Offset array:", offsetArray); Trace.log(Trace.DIAGNOSTIC, "Program parameters:", programParameters); } - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = system_.swapTo(swapToPH, swapFromPH); + + + boolean didSwap = system_.swapTo(); try { // Call native method. @@ -687,7 +687,7 @@ protected boolean runProgramOnThread(String library, String name, ProgramParamet finally { if (didSwap) - system_.swapBack(swapToPH, swapFromPH); + system_.swapBack(); } } } diff --git a/src/main/java/com/ibm/as400/access/UserSpaceImplNative.java b/src/main/java/com/ibm/as400/access/UserSpaceImplNative.java index 99b5313e..0019e21f 100644 --- a/src/main/java/com/ibm/as400/access/UserSpaceImplNative.java +++ b/src/main/java/com/ibm/as400/access/UserSpaceImplNative.java @@ -286,9 +286,9 @@ public void createZ(String domain, int length, boolean replace, String extendedA // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (create) "); @@ -309,7 +309,7 @@ public void createZ(String domain, int length, boolean replace, String extendedA } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } } @@ -431,9 +431,9 @@ public void deleteZ() // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (delete) "); @@ -454,7 +454,7 @@ public void deleteZ() } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } } @@ -551,9 +551,9 @@ protected int getAttributesZ(int valueToReturn) // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (get attrs) "); @@ -575,7 +575,7 @@ protected int getAttributesZ(int valueToReturn) } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } return(returnValue); } @@ -770,9 +770,9 @@ private int readData(byte dataBuffer[], int userSpaceOffset, int dataOffset, int BinaryConverter.intToByteArray(0, programParameters, length + 28); // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (read) "); @@ -800,7 +800,7 @@ private int readData(byte dataBuffer[], int userSpaceOffset, int dataOffset, int } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } return actualLength; @@ -932,9 +932,9 @@ else if (valueToSet == AUTO_EXTENDIBLE) // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (set attrs) "); @@ -956,7 +956,7 @@ else if (valueToSet == AUTO_EXTENDIBLE) } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } } @@ -1142,9 +1142,9 @@ else if (forceAuxiliary == 2) BinaryConverter.intToByteArray(0, programParameters, length + 29); // call the native method to carry out the request. - byte[] swapToPH = new byte[12]; - byte[] swapFromPH = new byte[12]; - boolean didSwap = ((AS400ImplRemote)system_).swapTo(swapToPH, swapFromPH); + + + boolean didSwap = ((AS400ImplRemote)system_).swapTo(); try { Trace.log(Trace.INFORMATION, "calling native method (write) "); @@ -1167,7 +1167,7 @@ else if (forceAuxiliary == 2) } finally { - if (didSwap) ((AS400ImplRemote)system_).swapBack(swapToPH, swapFromPH); + if (didSwap) ((AS400ImplRemote)system_).swapBack(); } } diff --git a/src/main/java/com/ibm/as400/access/jdbcClient/Main.java b/src/main/java/com/ibm/as400/access/jdbcClient/Main.java index 9d2768cb..b2ba0ea9 100644 --- a/src/main/java/com/ibm/as400/access/jdbcClient/Main.java +++ b/src/main/java/com/ibm/as400/access/jdbcClient/Main.java @@ -46,8 +46,10 @@ import java.sql.Types; import java.util.Collections; import java.util.Enumeration; +import java.util.HashSet; import java.util.Hashtable; import java.util.Vector; + import java.util.zip.CRC32; import javax.transaction.xa.XAException; @@ -2792,11 +2794,11 @@ private Object callMethod(String left, PrintStream printStreamForCallMethod) { // pre JDK 1.4 if (callObject != null) { - methods = callObject.getClass().getMethods(); + methods = getAllMethods(callObject.getClass()); } else { // Note: callClass cannot be null because of callObject != null || callClass != null condition above if (callClass != null) { - methods = callClass.getMethods(); + methods = getAllMethods(callClass); } else { methods = new Method[0]; } @@ -2807,8 +2809,9 @@ private Object callMethod(String left, PrintStream printStreamForCallMethod) { && (variable == null); m++) { int p = 0; int methodParameterCount = 0; - + if (methods[m].getName().equals(methodName)) { + methods[m].setAccessible(true); Class[] parameterTypes = methods[m].getParameterTypes(); String argsLeft = left; Object[] parameters = new Object[parameterTypes.length]; @@ -3119,7 +3122,22 @@ private Object callMethod(String left, PrintStream printStreamForCallMethod) { } } - private String getXACodeInfo(XAException e) { + /* Use both getMethods and getDeclared methods to return all methods for the object */ + private Method[] getAllMethods(Class class1) { + Method[] declaredMethods = class1.getDeclaredMethods(); + Method[] allMethods = class1.getMethods(); + + Method[] returnMethods = new Method[declaredMethods.length+allMethods.length]; + for (int i = 0; i < declaredMethods.length; i++) { + returnMethods[i] = declaredMethods[i]; + } + for (int i = 0; i < allMethods.length; i++) { + returnMethods[i+declaredMethods.length] = allMethods[i]; + } + return returnMethods; +} + +private String getXACodeInfo(XAException e) { int code = e.errorCode; switch (code) { case XAException.XA_HEURCOM: return "XA_HEURCOM : The transaction branch has been heuristically committed."; @@ -3438,16 +3456,16 @@ private void showMethods(String left, PrintStream out1) { if (callObject != null || callClass != null) { Method[] methods; if (callObject != null) { - methods = callObject.getClass().getMethods(); + methods = getAllMethods(callObject.getClass()); } else { // callClass cannot be null because of callObject != null || callClass != null condition above if (callClass != null) { - methods = callClass.getMethods(); + methods = getAllMethods(callClass); } else { methods = new Method[0]; } } - Vector methodVector = new Vector(); + HashSet hashSet = new HashSet(); for (int m = 0; (m < methods.length); m++) { String methodInfo; String returnClause; @@ -3467,8 +3485,9 @@ private void showMethods(String left, PrintStream out1) { methodInfo += parameterTypeName; } methodInfo += ")"+returnClause; - methodVector.addElement(methodInfo); + hashSet.add(methodInfo); } + Vector methodVector = new Vector(hashSet); Collections.sort(methodVector); Enumeration vectorEnum = methodVector.elements(); while (vectorEnum.hasMoreElements()) { diff --git a/src/main/java/com/ibm/as400/security/auth/ProfileTokenCredential.java b/src/main/java/com/ibm/as400/security/auth/ProfileTokenCredential.java index 80e05650..19139084 100644 --- a/src/main/java/com/ibm/as400/security/auth/ProfileTokenCredential.java +++ b/src/main/java/com/ibm/as400/security/auth/ProfileTokenCredential.java @@ -195,6 +195,7 @@ public final class ProfileTokenCredential extends AS400Credential implements AS4 // can tell the toolbox not to use enhanced profile tokens by setting // com.ibm.as400.access.AS400.useEnhancedProfileTokens property to false. private static boolean useEnhancedProfileTokens_ = true; + static { String property = System.getProperty("com.ibm.as400.access.AS400.useEnhancedProfileTokens"); if (property != null && property.toLowerCase().equals("false")) @@ -207,6 +208,9 @@ public final class ProfileTokenCredential extends AS400Credential implements AS4 private int type_ = TYPE_SINGLE_USE; private int timeoutInterval_ = 3600; + private boolean enhancedProfileToken_ = false; // We need to know if an enhanced profile + // was created. If so, a different native swap + // method is used. private String verificationID_ = DEFAULT_VERIFICATION_ID; private String localIPAddress_ = null; private String remoteIPAddress_ = null; @@ -303,7 +307,8 @@ public ProfileTokenCredential() * (i.e. previously created using the QSYGENPT system API). It is the * responsibility of the application to ensure the token attributes, such as the * tokenType and timeoutInterval, are consistent with the - * specified token value. + * specified token value. This deprecated method cannot be used with an + * enhanced profile token. * * @param system The system associated with the credential. * @@ -320,9 +325,43 @@ public ProfileTokenCredential() * * @param timeoutInterval The number of seconds to expiration, used as the * default value when the token is refreshed (1-3600). + * + * @deprecated Use the constructor with the enhancedProfileToken parameter + * */ + @Deprecated public ProfileTokenCredential(AS400 system, byte[] token, int tokenType, int timeoutInterval) { - this(system, token, tokenType, timeoutInterval, null, null, null, 0, null, 0); + this(system, token, tokenType, timeoutInterval, null, null, null, 0, null, 0, false); + } + + /** + * Constructs and initializes a ProfileTokenCredential object. + * + *

+ * This method allows a credential to be constructed based on an existing token + * (i.e. previously created using the QSYGENPT system API). It is the + * responsibility of the application to ensure the token attributes, such as the + * tokenType and timeoutInterval, are consistent with the + * specified token value. + * + * @param system The system associated with the credential. + * + * @param token The actual bytes for the token as it exists on the IBM + * i system. + * + * @param tokenType The type of token provided. Possible types are defined + * as fields on this class: + *

+ * + * @param timeoutInterval The number of seconds to expiration, used as the + * default value when the token is refreshed (1-3600). + */ + public ProfileTokenCredential(AS400 system, byte[] token, int tokenType, int timeoutInterval, boolean enhancedProfileToken) { + this(system, token, tokenType, timeoutInterval, null, null, null, 0, null, 0, enhancedProfileToken); } /** @@ -400,15 +439,17 @@ public ProfileTokenCredential(AS400 system, byte[] token, int tokenType, int tim * (Socket.getLocalPort). Otherwise, use 0 * if there is not an associated * connection. + * @param enhancedProfileToken Indicates if the token is an enhanced profile token. */ public ProfileTokenCredential(AS400 system, byte[] token, int tokenType, int timeoutInterval, char[] additionalAuthFactor, String verificationID, - String remoteIPAddress, int remotePort, String localIPAddress, int localPort) + String remoteIPAddress, int remotePort, String localIPAddress, int localPort, + boolean enhancedProfileToken) { this(); try { setSystem(system); - setToken(token); + setToken(token, enhancedProfileToken); setTokenType(tokenType); setTimeoutInterval(timeoutInterval); setAdditionalAuthenticationFactor(additionalAuthFactor); @@ -495,16 +536,16 @@ public synchronized byte[] getToken() if (token_ == null) return null; + byte[] rawBytes = decode(addr_, mask_, token_); if (Trace.isTraceOn()) { // Note: Calling this.hashCode causes recursion - Trace.log(Trace.INFORMATION, "ProfileTokenCredential@" + Integer.toHexString(this.superHashCode()) - + " getPrimitiveToken called"); + Trace.log(Trace.INFORMATION, this, " getPrimitiveToken returned", rawBytes); } // Return the raw bytes for the token represented by the credential, decoding // the value in memory. - return decode(addr_, mask_, token_); + return rawBytes; } /** @@ -686,8 +727,10 @@ public boolean isReusable() { * value in memory. * * @param bytes The token bytes. + * @param enchancedProfileToken. set to true if enhancedProfile token */ - private void primitiveSetToken(byte[] bytes) { + private void primitiveSetToken(byte[] bytes, boolean enhancedProfileToken) { + enhancedProfileToken_ = enhancedProfileToken; token_ = encode(addr_, mask_, bytes); } @@ -735,14 +778,15 @@ public void refresh() throws AS400SecurityException { */ public synchronized void refresh(int type, int timeoutInterval) throws AS400SecurityException { + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION, this, "refresh("+type+","+timeoutInterval); + } // Start The current thread (Refresh Agent thread) is blocked when it receives // the message not refreshing. while (noRefresh_) { if (Trace.isTraceOn()) - Trace.log(Trace.INFORMATION, "ProfileTokenCredential@" + Integer.toHexString(this.hashCode()) - + " refresh stuck because of noRefresh"); - + Trace.log(Trace.INFORMATION, this, " refresh stuck because of noRefresh"); try { wait(); } catch (InterruptedException e) { @@ -750,9 +794,6 @@ public synchronized void refresh(int type, int timeoutInterval) throws AS400Secu } } - if (Trace.isTraceOn()) - Trace.log(Trace.INFORMATION, - "ProfileTokenCredential@" + Integer.toHexString(this.hashCode()) + " refresh called"); // Check permissions checkAuthenticationPermission("refreshCredential"); @@ -775,18 +816,25 @@ public synchronized void refresh(int type, int timeoutInterval) throws AS400Secu // Refresh the credential byte[] old = getToken(); byte[] bytes = ((ProfileTokenImpl) getImpl()).refresh(type, timeoutInterval); - - primitiveSetToken(bytes); + // The token type is the same as before. The refresh doesn't need + // to know an enhanced profile token is being used. + primitiveSetToken(bytes, enhancedProfileToken_); type_ = type; timeoutInterval_ = timeoutInterval; fireRefreshed(); firePropertyChange("token", old, bytes); - if (Trace.isTraceOn()) + if (Trace.isTraceOn()) { + if (Trace.isTraceOn()) { + Trace.log(Trace.JDBC, this, "refresh() old ",old); + Trace.log(Trace.JDBC, this, "refresh() new ",bytes); + } + Trace.log(Trace.INFORMATION, - new StringBuffer("ProfileTokenCredential@" + Integer.toHexString(this.hashCode()) + new StringBuffer("ProfileTokenCredential@" + System.identityHashCode(this) + " Credential refreshed with type ").append(type).append(" and timeoutInterval = ") .append(timeoutInterval).append(" >> ").append(toString()).toString()); + } } /** @@ -830,6 +878,37 @@ public void setTimeoutInterval(int seconds) throws PropertyVetoException firePropertyChange("timeoutInterval", old, sec); } + /** + * Sets the actual bytes for the token as it exists on the IBM i system. + * + *

+ * This method allows a credential to be constructed based on an existing token + * (i.e. previously created using the QSYGENPT system API). It is the + * responsibility of the application to ensure the token attributes, such as the + * tokenType and timeoutInterval, are consistent with the + * specified token value. + * This method should only be called if the token is not an enhanced profile token. + * + *

+ * This property cannot be changed once a request initiates a connection for the + * object to the IBM i system (for example, refresh). + * + * @param bytes The token bytes. + * + * @exception PropertyVetoException If the change is vetoed. + * + * @exception ExtendedIllegalArgumentException If the provided value is not the + * correct length. + * + * @exception ExtendedIllegalStateException If the property cannot be changed + * due to the current state. + * + */ +@Deprecated + public synchronized void setToken(byte[] bytes) throws PropertyVetoException { + setToken(bytes, false); + } + /** * Sets the actual bytes for the token as it exists on the IBM i system. * @@ -845,6 +924,8 @@ public void setTimeoutInterval(int seconds) throws PropertyVetoException * object to the IBM i system (for example, refresh). * * @param bytes The token bytes. + * + * @param enhancedProfileToken Indicates if the token is an enhancedProfileToken * * @exception PropertyVetoException If the change is vetoed. * @@ -855,7 +936,7 @@ public void setTimeoutInterval(int seconds) throws PropertyVetoException * due to the current state. * */ - public synchronized void setToken(byte[] bytes) throws PropertyVetoException + public synchronized void setToken(byte[] bytes, boolean enhancedProfileToken) throws PropertyVetoException { // Validate state validatePropertyChange("token"); @@ -873,7 +954,7 @@ public synchronized void setToken(byte[] bytes) throws PropertyVetoException byte[] old = getToken(); fireVetoableChange("token", old, bytes); - primitiveSetToken(bytes); + primitiveSetToken(bytes, enhancedProfileToken); firePropertyChange("token", old, bytes); } @@ -1008,7 +1089,13 @@ public void setToken(String name, String password) throws PropertyVetoException, ProfileTokenImpl impl = (ProfileTokenImpl) getImplPrimitive(); // Generate and set the token value - setToken(impl.generateToken(name, password, getTokenType(), getTimeoutInterval())); + char[] passwordChars = password.toCharArray(); + byte[] newToken; + boolean[] extendedProfileToken = new boolean[1]; + extendedProfileToken[0]=true; + newToken = impl.generateTokenExtended(name, passwordChars, getTokenType(), getTimeoutInterval(), extendedProfileToken); + setToken(newToken,extendedProfileToken[0]); + Arrays.fill(passwordChars,'\0'); // If successful, all defining attributes are now set. // Set the impl for subsequent references. @@ -1332,6 +1419,18 @@ public void setTokenExtended(String name, String password) throws PropertyVetoEx */ public void setTokenExtended(String name, char[] password) throws PropertyVetoException, AS400SecurityException { + if (Trace.isTraceOn()) { + String passwordInfo = ""; + if (password != null) { + passwordInfo = "char["+password.length+"]"; + } else { + passwordInfo = "null"; + } + String nameInfo = ""; + if (name != null) nameInfo=name; + else nameInfo = "null"; + Trace.log(Trace.INFORMATION, "setTokenExtended("+nameInfo+","+passwordInfo+")"); + } // Validate state validatePropertySet("system", getSystem()); @@ -1397,6 +1496,9 @@ public void setTokenExtended(String name, char[] password) throws PropertyVetoEx public void setTokenType(int type) throws PropertyVetoException { // Validate state + if (Trace.isTraceOn()) { + Trace.log(Trace.INFORMATION, this, "setTokenType("+type+")"); + } validatePropertyChange("tokenType"); // Validate parms @@ -1757,4 +1859,14 @@ public void setTokenCreator(int tokenCreator) throws PropertyVetoException boolean isTokenSet() { return token_ != null; } + /** + * Return true if the profile token was created as an enhancedProfileToken + * This can only be set when the profile token is set. + * @return + */ + public boolean isEnhancedProfileToken() { + return enhancedProfileToken_; + } + + } diff --git a/src/main/java/com/ibm/as400/security/auth/ProfileTokenImpl.java b/src/main/java/com/ibm/as400/security/auth/ProfileTokenImpl.java index a2ce4b46..bedb12b8 100644 --- a/src/main/java/com/ibm/as400/security/auth/ProfileTokenImpl.java +++ b/src/main/java/com/ibm/as400/security/auth/ProfileTokenImpl.java @@ -32,38 +32,7 @@ public interface ProfileTokenImpl extends AS400CredentialImpl */ public final static String PW_STR_NOPWDCHK = "*NOPWDCHK "; - /** - * Generates and returns a new profile token based on the provided information. - * - * @deprecated As of V5R3, replaced by - * {@link #generateTokenExtended(String,char[],int,int)} for - * password strings and {@link #generateToken(String,int,int,int)} - * for password special values - * - * @param uid The name of the user profile for which the token is to - * be generated. - * - * @param pwd The user profile password (encoded). - * - * @param type The type of token. Possible types are defined as - * fields on the ProfileTokenCredential class: - *

- *

- * - * @param timeoutInterval The number of seconds to expiration. - * - * @return The token bytes. - * - * @exception RetrieveFailedException If errors occur while generating the - * token. - * - */ - byte[] generateToken(String uid, String pwd, int type, int timeoutInterval) throws RetrieveFailedException; - + /** * Generates and returns a new profile token based on the provided information * using a password special value. @@ -89,6 +58,9 @@ public interface ProfileTokenImpl extends AS400CredentialImpl *

* * @param timeoutInterval The number of seconds to expiration. + * + * @param enhancedProfileToken Input / output. On input, if true then an enhancedProfileToken will be generated if possible. + * On output, true if an enhancedProfileToken was generated. * * @return The token bytes. * @@ -96,7 +68,7 @@ public interface ProfileTokenImpl extends AS400CredentialImpl * token. * */ - byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval) throws RetrieveFailedException; + byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException; /** * Generates and returns a new profile token based on the provided information @@ -147,6 +119,10 @@ ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, ProfileTok *

* * @param timeoutInterval The number of seconds to expiration. + * + * @param enhancedProfileToken Input / output. On input, if true then an enhancedProfileToken will be generated if possible. + * On output, true if an enhancedProfileToken was generated. + * * @return The token bytes. * @@ -154,7 +130,7 @@ ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, ProfileTok * token. * */ - byte[] generateTokenExtended(String uid, char[] pwd, int type, int timeoutInterval) throws RetrieveFailedException; + byte[] generateTokenExtended(String uid, char[] pwd, int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException; /** * Generates and returns a new profile token based on a user profile, password, diff --git a/src/main/java/com/ibm/as400/security/auth/ProfileTokenImplRemote.java b/src/main/java/com/ibm/as400/security/auth/ProfileTokenImplRemote.java index 010167db..cc27a597 100644 --- a/src/main/java/com/ibm/as400/security/auth/ProfileTokenImplRemote.java +++ b/src/main/java/com/ibm/as400/security/auth/ProfileTokenImplRemote.java @@ -33,7 +33,6 @@ public void destroy() throws DestroyFailedException { @Deprecated - @Override public byte[] generateToken(String uid, String pwd, int type, int timeoutInterval) throws RetrieveFailedException { AS400 sys = getCredential().getSystem(); @@ -71,16 +70,16 @@ public byte[] generateToken(String uid, String pwd, int type, int timeoutInterva } @Override - public byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval) throws RetrieveFailedException + public byte[] generateToken(String uid, int pwdSpecialValue, int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException { - return generateToken(uid, pwdSpecialValue, null, AuthenticationIndicator.APPLICATION_AUTHENTICATION, - null, null, 0, null, 0, type, timeoutInterval); + return generateToken(uid, pwdSpecialValue, null, AuthenticationIndicator.APPLICATION_AUTHENTICATION, + null, null, 0, null, 0, type, timeoutInterval,enhancedProfileToken); } private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalAuthenticationFactor, int authenticationIndicator, String verificationId, String remoteIpAddress, int remotePort, - String localIpAddress, int localPort, int type, int timeoutInterval) throws RetrieveFailedException + String localIpAddress, int localPort, int type, int timeoutInterval, boolean[] enhancedProfileToken) throws RetrieveFailedException { // Convert password special value from enumerated int to String String pwd; @@ -105,7 +104,7 @@ private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalA // Determine if we are using enhanced profile tokens boolean useEPT = false; try { - useEPT = (ProfileTokenCredential.useEnhancedProfileTokens() && sys.getVRM() > 0x00070500); + useEPT = enhancedProfileToken[0] && (ProfileTokenCredential.useEnhancedProfileTokens() && sys.getVRM() > 0x00070500); } catch (AS400SecurityException|IOException e) { Trace.log(Trace.ERROR, "Unexpected Exception: ", e); @@ -217,7 +216,11 @@ private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalA catch (Exception e) { throw new RetrieveFailedException(); } - + if (useEPT) { + enhancedProfileToken[0] = true; + } else { + enhancedProfileToken[0] = false; + } return parmlist[0].getOutputData(); } @@ -225,6 +228,8 @@ private byte[] generateToken(String uid, int pwdSpecialValue, char[] additionalA public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, ProfileTokenCredential profileTokenCred) throws RetrieveFailedException, PropertyVetoException { + boolean[] enhancedProfileToken = new boolean[1]; + enhancedProfileToken[0] = true; byte[] token = generateToken(uid, pwdSpecialValue, profileTokenCred.getAdditionalAuthenticationFactor(), profileTokenCred.getAuthenticationIndicator(), @@ -234,10 +239,11 @@ public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, Pro profileTokenCred.getLocalIPAddress(), profileTokenCred.getLocalPort(), profileTokenCred.getTokenType(), - profileTokenCred.getTimeoutInterval()); + profileTokenCred.getTimeoutInterval(), + enhancedProfileToken); try { - profileTokenCred.setToken(token); + profileTokenCred.setToken(token, enhancedProfileToken[0]); profileTokenCred.setTokenCreator(ProfileTokenCredential.CREATOR_NATIVE_API); } catch (PropertyVetoException e) @@ -254,67 +260,11 @@ public ProfileTokenCredential generateToken(String uid, int pwdSpecialValue, Pro return profileTokenCred; } - /** - * Generates and returns a new profile token based on - * the provided information using a password string - *

- * This method is used for generating a token using - * a password string (vs a special value). - * - * @param uid - * The name of the user profile for which the token - * is to be generated. - * - * @param pwd - * The user profile password. - * Special values are not supported by this method. - * - * @param type - * The type of token. - * Possible types are defined as fields on the - * ProfileTokenCredential class: - *

- *

- * - * @param timeoutInterval - * The number of seconds to expiration. - * - * @return - * The token bytes. - * - * @exception RetrieveFailedException - * If errors occur while generating the token. - * - * @deprecated Use generateTokenExtended(String uid, char[] pwd, int type, - * int timeoutInterval) instead. - */ - @Deprecated - public byte[] generateTokenExtended(String uid, String pwd, int type, int timeoutInterval) throws RetrieveFailedException - { - // Use the AS400 object to obtain the token. - // This will obtain the token by interacting with the IBM i - // system signon server and avoid transmitting a cleartext password. - byte[] tkn = null; - try { - tkn = getCredential().getSystem().getProfileToken(uid, pwd, type, timeoutInterval).getToken(); - } - catch (AS400SecurityException se) { - throw new RetrieveFailedException(se.getReturnCode()); - } - catch (Exception e) { - AuthenticationSystem.handleUnexpectedException(e); - } - - return tkn; - } - - @Override - public byte[] generateTokenExtended(String uid, char[] pwd, int type, int timeoutInterval) throws RetrieveFailedException { - return generateTokenExtended(uid, pwd, null, null, null, 0, null, 0, type, timeoutInterval).getToken(); + + public byte[] generateTokenExtended(String uid, char[] pwd, int type, int timeoutInterval, boolean[] enhancedProfileToken ) throws RetrieveFailedException { + ProfileTokenCredential pt = generateTokenExtended(uid, pwd, null, null, null, 0, null, 0, type, timeoutInterval); + enhancedProfileToken[0] = pt.isEnhancedProfileToken(); + return pt.getToken(); } private ProfileTokenCredential generateTokenExtended(String uid, char[] password, char[] additionalAuthenticationFactor, @@ -344,7 +294,7 @@ private ProfileTokenCredential generateTokenExtended(String uid, char[] password public ProfileTokenCredential generateTokenExtended(String uid, char[] password, ProfileTokenCredential profileTokenCred) throws RetrieveFailedException, PropertyVetoException { - ProfileTokenCredential ptTemp = generateTokenExtended(uid, password, + ProfileTokenCredential ptTemp = generateTokenExtended(uid, password, profileTokenCred.getAdditionalAuthenticationFactor(), profileTokenCred.getVerificationID(), profileTokenCred.getRemoteIPAddress(), @@ -355,9 +305,9 @@ public ProfileTokenCredential generateTokenExtended(String uid, char[] password, profileTokenCred.getTimeoutInterval()); try { - profileTokenCred.setToken(ptTemp.getToken()); profileTokenCred.setTokenCreator(ptTemp.getTokenCreator()); profileTokenCred.setRemoteIPAddress(ptTemp.getRemoteIPAddress()); + profileTokenCred.setToken(ptTemp.getToken(),ptTemp.isEnhancedProfileToken()); } catch (PropertyVetoException e) { diff --git a/src/main/java/com/ibm/as400/security/auth/RefreshFailedException.java b/src/main/java/com/ibm/as400/security/auth/RefreshFailedException.java index 95e172bb..16c2e4af 100644 --- a/src/main/java/com/ibm/as400/security/auth/RefreshFailedException.java +++ b/src/main/java/com/ibm/as400/security/auth/RefreshFailedException.java @@ -43,7 +43,7 @@ public class RefreshFailedException extends AS400AuthenticationException { * with the exception. * */ -RefreshFailedException(AS400Message[] list) { +public RefreshFailedException(AS400Message[] list) { super(list); } /** diff --git a/src/main/java/com/ibm/as400/security/auth/Swapper.java b/src/main/java/com/ibm/as400/security/auth/Swapper.java index da9e6660..7fb75495 100644 --- a/src/main/java/com/ibm/as400/security/auth/Swapper.java +++ b/src/main/java/com/ibm/as400/security/auth/Swapper.java @@ -97,7 +97,7 @@ public static void swap(AS400 system, ProfileTokenCredential newCredential) thro if (system.canUseNativeOptimizations()) Trace.log(Trace.WARNING, "When running natively, swaps should be performed via ProfileTokenCredential.swap() instead of Swapper.swap()."); - swapToToken(system, newCredential.getToken()); + swapToToken(system, newCredential.getToken(), newCredential.isEnhancedProfileToken(),newCredential.getVerificationID(),newCredential.getRemoteIPAddress()); newCredential.fireSwapped(); } @@ -120,13 +120,13 @@ public static void swap(Connection connection, ProfileTokenCredential newCredent if (newCredential == null) throw new NullPointerException("newCredential"); - swapToToken(connection, newCredential.getToken()); + swapToToken(connection, newCredential.getToken(), newCredential.isEnhancedProfileToken(), newCredential.getVerificationID(), newCredential.getRemoteIPAddress()); newCredential.fireSwapped(); } /** * Swaps the profile, using the specified profile token. This method calls system API QSYSETP ("Set To Profile - * Token"). + * Token"). This method cannot be used with an enhanced profile token. *

* Note: This method is intended for use with remote connections only, and only swaps the profile used by * {@link com.ibm.as400.access.CommandCall CommandCall}, {@link com.ibm.as400.access.ProgramCall ProgramCall}, and @@ -142,6 +142,27 @@ public static void swap(Connection connection, ProfileTokenCredential newCredent * @see #swap(AS400, ProfileTokenCredential) **/ public static void swapToToken(AS400 system, byte[] token) throws AS400SecurityException, IOException + { + swapToToken(system, token, false, null,null); + } + /** + * Swaps the profile, using the specified profile token. This method calls system API QSYSETP ("Set To Profile + * Token"). If the profile token is enhanced, then the additional parameters are passed to QSYSETP. + *

+ * Note: This method is intended for use with remote connections only, and only swaps the profile used by + * {@link com.ibm.as400.access.CommandCall CommandCall}, {@link com.ibm.as400.access.ProgramCall ProgramCall}, and + * {@link com.ibm.as400.access.ServiceProgramCall ServiceProgramCall}. If your Java application is running + * "natively", that is, on-thread on the IBM i JVM, and you wish to swap the current thread to a different profile, + * use one of the swap() methods of {@link ProfileTokenCredential ProfileTokenCredential} instead of + * this method. + * + * @param system The IBM i system. + * @param token The bytes from {@link ProfileTokenCredential#getToken()} + * @exception AS400SecurityException If a security or authority error occurs. + * @exception IOException If an error occurs while communicating with the system. + * @see #swap(AS400, ProfileTokenCredential) + **/ + public static void swapToToken(AS400 system, byte[] token, boolean enhancedProfileToken, String verificationId, String remoteIpAddress) throws AS400SecurityException, IOException { if (system == null) throw new NullPointerException("system"); @@ -149,7 +170,23 @@ public static void swapToToken(AS400 system, byte[] token) throws AS400SecurityE throw new NullPointerException("token"); // API takes 2 parameters: A char(32) profile token and error code - ProgramParameter[] parmList = new ProgramParameter[2]; + ProgramParameter[] parmList ; + if (!enhancedProfileToken) { + parmList = new ProgramParameter[2]; + } else { + // API takes 3 additional parameters + /* Verification ID char(30) Input: verification ID */ + /* Remote IP address char * Input: remote IP addr */ + /* Remote IP address len int * Input: remote IP addr len */ + parmList = new ProgramParameter[5]; + if (verificationId == null) verificationId=""; + verificationId = verificationId+" "; + verificationId = verificationId.substring(0,30); + parmList[2] = new ProgramParameter(CharConverter.stringToByteArray(37, system,verificationId)); + parmList[3] = new ProgramParameter(CharConverter.stringToByteArray(37, system,remoteIpAddress)); + parmList[4] = new ProgramParameter(BinaryConverter.intToByteArray(remoteIpAddress.length())); + + } // Input: Profile token (32A) parmList[0] = new ProgramParameter(token); @@ -157,6 +194,7 @@ public static void swapToToken(AS400 system, byte[] token) throws AS400SecurityE // Input/Output: Error code parmList[1] = new ErrorCodeParameter(); + // Call the program ProgramCall pgm = new ProgramCall(system, "/QSYS.LIB/QSYSETPT.PGM", parmList); pgm.suggestThreadsafe(); // Run on-thread if possible; allows app to use disabled profile. @@ -185,7 +223,23 @@ public static void swapToToken(AS400 system, byte[] token) throws AS400SecurityE /** * Swaps the profile, using the specified profile token. This method uses SQL's call statement to pass - * the token to QSYSETPT. + * the token to QSYSETPT. The profile token cannot be an enhanced profile token + * + * @param connection A JDBC connection to the IBM i system. + * @param token The bytes from {@link ProfileTokenCredential#getToken()} + * @exception AS400SecurityException If a security or authority error occurs. + * @exception IOException If an error occurs while communicating with the system. + * @exception SQLException If the connection is not open, or an error occurs. + * @see #swap(Connection, ProfileTokenCredential) + **/ + public static void swapToToken(Connection connection, byte[] token) throws AS400SecurityException, IOException, SQLException { + swapToToken(connection, token, false, null,null); + } + + + /** + * Swaps the profile, using the specified profile token. This method uses SQL's call statement to pass + * the token to QSYSETPT. Additional parameters are passed if this is an enhanced profile token. * * @param connection A JDBC connection to the IBM i system. * @param token The bytes from {@link ProfileTokenCredential#getToken()} @@ -194,7 +248,7 @@ public static void swapToToken(AS400 system, byte[] token) throws AS400SecurityE * @exception SQLException If the connection is not open, or an error occurs. * @see #swap(Connection, ProfileTokenCredential) **/ - public static void swapToToken(Connection connection, byte[] token) throws AS400SecurityException, IOException, SQLException + public static void swapToToken(Connection connection, byte[] token, boolean enhancedProfileToken, String verificationId, String remoteIpAddress) throws AS400SecurityException, IOException, SQLException { if (connection == null) throw new NullPointerException("connection"); @@ -220,7 +274,11 @@ else if (unsignedByte < 16) sql.append(Integer.toHexString(unsignedByte).toUpperCase()); } - sql.append("', X'0000')"); + sql.append("', X'0000'"); + if (enhancedProfileToken) { + sql.append(", CAST('"+enhancedProfileToken+"' AS CHAR(30)),'"+remoteIpAddress+"',"+remoteIpAddress.length()); + } + sql.append(")"); Statement stmt = null; try