All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.as400.security.auth.Swapper Maven / Gradle / Ivy

The newest version!
////////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                                 
//                                                                             
// Filename: ProfileTokenCredential.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 2009-2009 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.security.auth;

import com.ibm.as400.access.*;
import java.io.IOException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;
import java.sql.SQLWarning;

/**
 * Provides utility methods to perform credential swaps for existing remote connections. The methods in this class allow
 * you to do work under a different user, providing you've obtained a {@link ProfileTokenCredential
 * ProfileTokenCredential} probably from {@link com.ibm.as400.access.AS400#getProfileToken(String,String)
 * AS400.getProfileToken()}.
 * 

* Comparison with the swap() methods of ProfileTokenCredential: * *

* The swap() methods of this class have as one of their arguments either an AS400 object or a Connection * object. The contract of these methods is to swap the profile in use for a specified connection. Here is the * usage pattern: * *

 AS400 conn1 = new AS400(sysName, userID, password);
 ProfileTokenCredential myCred = new ProfileTokenCredential(....);
 Swapper.swap(conn1, myCred);
 // conn1 is now running under the new (swapped-to) profile
 * 
* *

* In constrast, the contract of the swap() methods of class {@link ProfileTokenCredential * ProfileTokenCredential} is to swap the profile in use for the current thread of execution. They don't swap * the profile in use for a specific AS400 object, but rather for any subsequently-created AS400 objects. Here * is the usage pattern: * *

 AS400 conn1 = new AS400();
 ProfileTokenCredential myCred = new ProfileTokenCredential(....);
 myCred.swap();
 AS400 conn2 = new AS400();  // conn2 is running under the swapped-to profile.
 // conn1 is still running under the original profile.
 * 
* *

* The Swapper.swap() methods are useful for swapping credentials for existing remote connections. The * ProfileTokenCredential.swap() methods are useful for swapping the current thread of execution when * running natively in an IBM i JVM. *

* This class is mostly based on a prototype contributed by Steve Johnson-Evers. **/ public class Swapper { // Prevent instantiation of this class. private Swapper() { } /** * Swaps the profile on the specified system. This method calls system API QSYSETP ("Set To 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 * {@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 remote IBM i system. * @param newCredential The credential to use for the swap. * @exception AS400SecurityException If a security or authority error occurs. * @exception IOException If an error occurs while communicating with the system. * @see ProfileTokenCredential#swap() * @see ProfileTokenCredential#swap(boolean) **/ public static void swap(AS400 system, ProfileTokenCredential newCredential) throws AS400SecurityException, IOException { if (system == null) throw new NullPointerException("system"); if (newCredential == null) throw new NullPointerException("newCredential"); // If running natively, suggest the use of ProfileTokenCredential.swap() instead. 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(), newCredential.isEnhancedProfileToken(),newCredential.getVerificationID(),newCredential.getRemoteIPAddress()); newCredential.fireSwapped(); } /** * Swaps the profile on the specified JDBC connection. This method calls system API QSYSETP ("Set To Profile * Token"). * * @param connection A JDBC connection to the IBM i system. Must be an instance of * {@link com.ibm.as400.access.AS400JDBCConnection} or * {@link com.ibm.as400.access.AS400JDBCConnectionHandle}. * @param newCredential The credential to use for the swap. * @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. **/ public static void swap(Connection connection, ProfileTokenCredential newCredential) throws AS400SecurityException, IOException, SQLException { if (connection == null) throw new NullPointerException("connection"); if (newCredential == null) throw new NullPointerException("newCredential"); 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"). 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 * {@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) 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"); if (token == null) throw new NullPointerException("token"); // API takes 2 parameters: A char(32) profile token and error code 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); // 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. try { if (!pgm.run()) throw new SwapFailedException(pgm.getMessageList()); /// TBD experiment AS400Message[] msgs = pgm.getMessageList(); if (msgs != null && msgs.length != 0) { System.out.println("Messages returned from QSYSETPT:"); /// for (int i = 0; i < msgs.length; i++) { System.out.println(msgs[i].toString()); } } } catch (AS400SecurityException|RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } /** * Swaps the profile, using the specified profile token. This method uses SQL's call statement to pass * 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()} * @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, boolean enhancedProfileToken, String verificationId, String remoteIpAddress) throws AS400SecurityException, IOException, SQLException { if (connection == null) throw new NullPointerException("connection"); if (token == null) throw new NullPointerException("token"); // Note: Since we _always_ submit our JDBC requests via the Database Server, we don't really have a "Toolbox // native" mode when using a JDBC connection. So the swap should behave the same, whether the Java app is // running remotely or natively on IBM i. StringBuffer sql = new StringBuffer(80); sql.append("CALL QSYS"); sql.append(connection.getMetaData().getCatalogSeparator()); sql.append("QSYSETPT (X'"); for (int i = 0; i < token.length; i++) { int unsignedByte = token[i]; if (unsignedByte < 0) unsignedByte = 256 + unsignedByte; else if (unsignedByte < 16) sql.append('0'); sql.append(Integer.toHexString(unsignedByte).toUpperCase()); } sql.append("', X'0000'"); if (enhancedProfileToken) { sql.append(", CAST('"+enhancedProfileToken+"' AS CHAR(30)),'"+remoteIpAddress+"',"+remoteIpAddress.length()); } sql.append(")"); Statement stmt = null; try { stmt = connection.createStatement(); stmt.execute(sql.toString()); /// TBD: Check stmt for returned messages, warnings, etc SQLWarning warning = stmt.getWarnings(); if (warning != null) System.out.println("SQLWarning: " + warning.getErrorCode() + ": " + warning.getSQLState()); /// } finally { if (stmt != null) { try { stmt.close(); } catch (Exception e) { if (Trace.isTraceOn()) Trace.log(Trace.ERROR, "Error while closing statement", e); } } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy