0001: /*
0002:
0003: Derby - Class org.apache.derbyTesting.functionTests.tests.derbynet.testSecMec
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derbyTesting.functionTests.tests.derbynet;
0023:
0024: import java.sql.Connection;
0025: import java.sql.ResultSet;
0026: import java.sql.PreparedStatement;
0027: import java.sql.CallableStatement;
0028: import java.sql.Statement;
0029: import java.sql.SQLException;
0030: import java.sql.DriverManager;
0031: import javax.sql.DataSource;
0032: import javax.sql.ConnectionPoolDataSource;
0033: import javax.sql.PooledConnection;
0034:
0035: import org.apache.derby.tools.JDBCDisplayUtil;
0036: import org.apache.derby.tools.ij;
0037: import org.apache.derby.drda.NetworkServerControl;
0038: import org.apache.derbyTesting.functionTests.util.TestUtil;
0039: import java.io.*;
0040: import java.net.InetAddress;
0041: import java.util.Hashtable;
0042: import java.util.Properties;
0043:
0044: import java.lang.reflect.*;
0045:
0046: /**
0047: * This class tests the security mechanisms supported by Network Server
0048: * Network server supports SECMEC_EUSRIDPWD, SECMEC_USRIDPWD, SECMEC_USRIDONL
0049: * and SECMEC_USRSSBPWD.
0050: *
0051: * -----------------------------------------------------------------
0052: * Security Mechanism | secmec codepoint value | User friendly name
0053: * -----------------------------------------------------------------
0054: * USRIDONL | 0x04 | USER_ONLY_SECURITY
0055: * USRIDPWD | 0x03 | CLEAR_TEXT_PASSWORD_SECURITY
0056: * EUSRIDPWD | 0x09 | ENCRYPTED_USER_AND_PASSWORD_SECURITY
0057: * USRSSBPWD | 0x08 | STRONG_PASSWORD_SUBSTITUTE_SECURITY
0058: * -----------------------------------------------------------------
0059: *
0060: * Key points:
0061: * 1)Server and client support encrypted userid/password (EUSRIDPWD) via the
0062: * use of Diffie Helman key-agreement protocol - however current Open Group DRDA
0063: * specifications imposes small prime and base generator values (256 bits) that
0064: * prevents other JCE's to be used as java cryptography providers - typical
0065: * minimum security requirements is usually of 1024 bits (512-bit absolute
0066: * minimum) when using DH key-agreement protocol to generate a session key.
0067: *
0068: * (Reference: DDM manual, page 281 and 282. Section: Generating the shared
0069: * private key. DRDA's diffie helman agreed public values for prime are 256
0070: * bits. The spec gives the public values for the prime, generator and the size
0071: * of exponent required for DH . These values must be used as is to generate a
0072: * shared private key.)
0073: *
0074: * Encryption is done using JCE. Hence JCE support of the necessary algorithm is
0075: * required for a particular security mechanism to work. Thus even though the
0076: * server and client have code to support EUSRIDPWD, this security mechanism
0077: * will not work in all JVMs.
0078: *
0079: * JVMs where support for DH(32byte prime) is not available and thus EUSRIDPWD
0080: * wont work are Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and IBM JVM (versions
0081: * 1.3.1 and some old versions of 1.4.2 (in 2004) )
0082: *
0083: * JVMs where support for DH(32bytes prime) is available and thus EUSRIDPWD will
0084: * work are IBM JVM [versions 1.4.1, later versions of 1.4.2 (from 2005), 1.5]
0085: *
0086: * #2) JCC 2.6 client does some automatic upgrade of security mechanism in one
0087: * case. Logic is as follows:
0088: * If client sends USRIDPWD to server and server rejects this
0089: * and says it accepts only EUSRIDPWD, in that case JCC 2.6 will upgrade the
0090: * security mechanism to EUSRIDPWD and retry the request with EUSRIDPWD.
0091: * This switching will also override the security mechanism specified by user.
0092: * Thus if JCC client is running with Sun JVM 1.4.2 and even though Sun JCE
0093: * does not have support for algorithms needed for EUSRIDPWD, the JCC client
0094: * will still try to switch to EUSRIDPWD and throw an exception with
0095: * ClassNotFoundException for the IBM JCE.
0096: *
0097: * - Default security mechanism is USRIDPWD(0x03)
0098: * - If securityMechanism is not explicitly specified on connection request
0099: * and if no user specified, an exception is thrown - Null userid not supported
0100: * - If securityMechanism is not explicitly specified on connection request,
0101: * and if no password is specified, an exception is thrown - null password not supported
0102: * If securityMechanism is explicitly specified to be USRIDONL, then a password
0103: * is not required. But in other cases (EUSRIDPWD, USRIDPWD, USRSSBPWD) if
0104: * password is null, an exception with the message 'a null password not valid'
0105: * will be thrown.
0106: * - On datasource, setting a security mechanism works. It also allows a security
0107: * mechanism of USRIDONL to be set on datasource unlike jcc 2.4.
0108: *
0109: * #3)JCC 2.4 client behavior
0110: * Default security mechanism used is USRIDPWD (0x03)
0111: * If securityMechanism is not explicitly specified on connection request,
0112: * and if no user is specified, an exception is thrown. - Null userid not supported.
0113: * If securityMechanism is not explicitly specified on connection request,
0114: * and if no password is specified, an exception is thrown - null password not supported
0115: * If security mechanism is specified, jcc client will not override the security mechanism.
0116: * If securityMechanism is explicitly specified to be USRIDONL, then a password
0117: * is not required. But in other cases (EUSRIDPWD,USRIDPWD) if password is null
0118: * - an exception with the message 'a null password not valid' will be thrown.
0119: * On datasource, setting a security mechanism does not work (bug). It defaults
0120: * to USRIDPWD. Setting a value of USRIDONL or EUSRIDPWD does not seem to have
0121: * an effect.
0122: *
0123: * #4) Note, if server restricts the client connections based on security mechanism
0124: * by setting derby.drda.securityMechanism, in that case the clients will see an
0125: * error similar to this
0126: * "Connection authorization failure occurred. Reason: security mechanism not supported"
0127: *
0128: * #5) USRSSBPWD - Strong password substitute is only supported starting from
0129: * Apache Derby 10.2.
0130: * NOTE: USRSSBPWD only works with the derby network client driver for now.
0131: * ----
0132: */
0133: public class testSecMec extends dataSourcePermissions_net {
0134: // Need this to keep track of database has been created or not
0135: // to avoid case of DERBY-300
0136: private static boolean dbNotCreated = true;
0137:
0138: // values for derby.drda.securityMechanism property
0139: private static String[] derby_drda_securityMechanism = {
0140: null, //not set
0141: "USER_ONLY_SECURITY", "CLEAR_TEXT_PASSWORD_SECURITY",
0142: "ENCRYPTED_USER_AND_PASSWORD_SECURITY",
0143: "STRONG_PASSWORD_SUBSTITUTE_SECURITY", "INVALID_VALUE", "" };
0144:
0145: // possible interesting combinations with respect to security mechanism
0146: // upgrade logic for user attribute
0147: private static String[] USER_ATTRIBUTE = { "calvin", null };
0148:
0149: // possible interesting combinations with respect to security mechanism
0150: // upgrade logic for password attribute
0151: private static String[] PWD_ATTRIBUTE = { "hobbes", null };
0152:
0153: private static int NETWORKSERVER_PORT;
0154:
0155: private static NetworkServerControl networkServer = null;
0156:
0157: private static FileOutputStream serverOutput;
0158:
0159: public static void main(String[] args) throws Exception {
0160: // Load harness properties.
0161: ij.getPropertyArg(args);
0162:
0163: String hostName = TestUtil.getHostName();
0164: if (hostName.equals("localhost"))
0165: NETWORKSERVER_PORT = 20000;
0166: else
0167: NETWORKSERVER_PORT = 1527;
0168:
0169: // "runTest()" is going to try to connect to the database through
0170: // the server at port NETWORKSERVER_PORT. Thus, we have to
0171: // start the server on that port before calling runTest.
0172:
0173: try {
0174: TestUtil.loadDriver();
0175: } catch (Exception e) {
0176: e.printStackTrace();
0177: }
0178:
0179: String fileName = System.getProperty("derby.system.home", "")
0180: + "serverConsoleOutput.log";
0181: serverOutput = new FileOutputStream(fileName);
0182:
0183: // Start server with a specific value for derby.drda.securityMechanism
0184: // and run tests. Note connections will be successful or not depending on
0185: // derby.drda.securityMechanism property specified on the server (DERBY-928)
0186: // @see
0187: // org.apache.derby.iapi.reference.Property#DRDA_PROP_SECURITYMECHANISM
0188: for (int i = 0; i < derby_drda_securityMechanism.length; i++) {
0189: if (derby_drda_securityMechanism[i] != null)
0190: System.setProperty("derby.drda.securityMechanism",
0191: derby_drda_securityMechanism[i]);
0192:
0193: System.out
0194: .println("----------------------------------------------");
0195: System.out
0196: .println("Testing with derby.drda.securityMechanism="
0197: + System
0198: .getProperty("derby.drda.securityMechanism"));
0199: // Start the NetworkServer on another thread, unless it's a remote host
0200: if (hostName.equals("localhost")) {
0201: try {
0202: networkServer = new NetworkServerControl(
0203: InetAddress.getByName(hostName),
0204: NETWORKSERVER_PORT);
0205: networkServer.start(new PrintWriter(serverOutput));
0206: } catch (Exception e) {
0207: if (derby_drda_securityMechanism[i]
0208: .equals("INVALID_VALUE")
0209: || derby_drda_securityMechanism[i]
0210: .equals("")) {
0211: System.out.println("EXPECTED EXCEPTION "
0212: + e.getMessage());
0213: continue;
0214: }
0215: // if server jvm does not support EUSRIDPWD, an exception
0216: // will be raised when server is started with
0217: // derby.drda.securityMechanism=ENCRYPTED_USER_AND_PASSWORD_SECURITY
0218: System.out.println("EXCEPTION " + e.getMessage());
0219: continue;
0220: }
0221:
0222: // Wait for the NetworkServer to start. As part of DERBY-1793
0223: // changed the wait from 60 to 120, which increased the maximum
0224: // to 120 pings with a wait of 500 ms between each ping.
0225: if (!isServerStarted(networkServer, 120)) {
0226: System.out
0227: .println("FAIL: Server failed to respond to ping - ending test");
0228:
0229: break;
0230: }
0231: }
0232:
0233: // Now, go ahead and run the test.
0234: try {
0235: testSecMec tester = new testSecMec();
0236: // Now run the test, note connections will be successful or
0237: // throw an exception depending on derby.drda.securityMechanism
0238: // property specified on the server
0239: tester.runTest();
0240:
0241: } catch (Exception e) {
0242: // if we catch an exception of some sort, we need to make sure to
0243: // close our streams before returning; otherwise, we can get
0244: // hangs in the harness. SO, catching all exceptions here keeps
0245: // us from exiting before closing the necessary streams.
0246: System.out
0247: .println("FAIL - Exiting due to unexpected error: "
0248: + e.getMessage());
0249: e.printStackTrace();
0250: }
0251:
0252: // Shutdown the server.
0253: if (hostName.equals("localhost")) {
0254:
0255: networkServer.shutdown();
0256: // how do we do this with the new api?
0257: //networkServer.join();
0258: Thread.sleep(5000);
0259:
0260: }
0261:
0262: // Now we want to test
0263: }
0264: System.out.println("Completed testSecMec");
0265:
0266: serverOutput.close();
0267: }
0268:
0269: // Indicates userid/encrypted password security mechanism.
0270: static final short SECMEC_EUSRIDPWD = 0x09;
0271:
0272: // Indicates userid only security mechanism.
0273: static final short SECMEC_USRIDONL = 0x04;
0274:
0275: // Indicates userid/encrypted password security mechanism.
0276: static final short SECMEC_USRENCPWD = 0x07;
0277:
0278: // Indicates userid/new password security mechanism.
0279: static final short SECMEC_USRIDNWPWD = 0x05;
0280:
0281: // Indicates userid/password security mechanism.
0282: static final short SECMEC_USRIDPWD = 0x03;
0283:
0284: // Indicates strong password substitute security mechanism.
0285: static final short SECMEC_USRSSBPWD = 0x08;
0286:
0287: // client and server recognize these secmec values
0288: private static short[] SECMEC_ATTRIBUTE = { SECMEC_USRIDONL,
0289: SECMEC_USRIDPWD, SECMEC_EUSRIDPWD, SECMEC_USRSSBPWD };
0290:
0291: /**
0292: * Test cases for security mechanism
0293: * ---------------------------------------------------------------
0294: * T1 - default , no user PASS (for derbyclient)
0295: * T2 - user only PASS (for derbyclient)
0296: * T3 - user,password PASS (only for derbynet)
0297: * T4 - user,password, security mechanism not set FAIL
0298: * T5 - user,password, security mechanism set to SECMEC_EUSRIDPWD PASS/FAIL
0299: * (Fails with Sun JVM as EUSRIDPWD secmec cannot be used)
0300: * T6 - user, security mechanism set to SECMEC_USRIDONL PASS
0301: * T7 - user,password, security mechanism set to SECMEC_USRENCPWD FAIL
0302: * Test with datasource as well as DriverManager
0303: * T8 - user,password security mechanism set to SECMEC_USRIDONL PASS
0304: * T9 - user,password security mechanism set to SECMEC_USRSSBPWD PASS
0305: * Test with datasource as well as DriverManager
0306: * Note, that with DERBY928, the pass/fail for the connections
0307: * will depend on the security mechanism specified at the server by property
0308: * derby.drda.securityMechanism. Please check out the following html file
0309: * http://issues.apache.org/jira/secure/attachment/12322971/Derby928_Table_SecurityMechanisms..htm
0310: * for a combination of url/security mechanisms and the expected results
0311: */
0312: protected void runTest() {
0313: // Test cases with get connection via drivermanager and using
0314: // different security mechanisms.
0315: // Network server supports SECMEC_USRIDPWD, SECMEC_USRIDONL,
0316: // SECMEC_EUSRIDPWD and USRSSBPWD (derby network client only)
0317: System.out
0318: .println("Checking security mechanism authentication with DriverManager");
0319:
0320: // DERBY-300; Creation of SQLWarning on a getConnection causes hang on
0321: // 131 vms when server and client are in same vm.
0322: // To avoid hitting this case with 1.3.1 vms, dont try to send create=true
0323: // if database is already created as otherwise it will lead to a SQLWarning
0324: if (dbNotCreated) {
0325: getConnectionUsingDriverManager(getJDBCUrl(
0326: "wombat;create=true",
0327: "user=neelima;password=lee;securityMechanism="
0328: + SECMEC_USRIDPWD), "T4:");
0329: dbNotCreated = false;
0330: } else
0331: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0332: "user=neelima;password=lee;securityMechanism="
0333: + SECMEC_USRIDPWD), "T4:");
0334: getConnectionUsingDriverManager(getJDBCUrl("wombat", null),
0335: "T1:");
0336: getConnectionUsingDriverManager(
0337: getJDBCUrl("wombat", "user=max"), "T2:");
0338: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0339: "user=neelima;password=lee"), "T3:");
0340:
0341: // Please note: EUSRIDPWD security mechanism in DRDA uses Diffie-Helman for generation of shared keys.
0342: // The spec specifies the prime to use for DH which is 32 bytes and this needs to be used as is.
0343: // Sun JCE does not support a prime of 32 bytes for Diffie Helman and some
0344: // older versions of IBM JCE ( 1.4.2) also do not support it.
0345: // Hence the following call to get connection might not be successful when
0346: // client is running in JVM where the JCE does not support the DH (32 byte prime)
0347: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0348: "user=neelima;password=lee;securityMechanism="
0349: + SECMEC_EUSRIDPWD), "T5:");
0350: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0351: "user=neelima;securityMechanism=" + SECMEC_USRIDONL),
0352: "T6:");
0353:
0354: // disable as ibm142 and sun jce doesnt support DH prime of 32 bytes
0355: //getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_USRENCPWD),"T7:");
0356: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0357: "user=neelima;password=lee;securityMechanism="
0358: + SECMEC_USRIDONL), "T8:");
0359: // Test strong password substitute DRDA security mechanism (only works with DerbyClient driver right now)
0360: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0361: "user=neelima;password=lee;securityMechanism="
0362: + SECMEC_USRSSBPWD), "T9:");
0363:
0364: getConnectionUsingDataSource();
0365:
0366: // regression test for DERBY-1080
0367: testDerby1080();
0368:
0369: // test for DERBY-962
0370: testAllCombinationsOfUserPasswordSecMecInput();
0371:
0372: // test USRSSBPWD (DERBY-528) with Derby BUILTIN authentication scheme
0373: // both with none and USRSSBPWD specified DRDA SecMec upon
0374: // starting the network server.
0375: String serverSecurityMechanism = System
0376: .getProperty("derby.drda.securityMechanism");
0377:
0378: if ((serverSecurityMechanism == null)
0379: || (serverSecurityMechanism
0380: .equals("STRONG_PASSWORD_SUBSTITUTE_SECURITY"))) {
0381: testUSRSSBPWD_with_BUILTIN();
0382: }
0383: }
0384:
0385: /**
0386: * Get connection from datasource and also set security mechanism
0387: */
0388: public void getConnectionUsingDataSource() {
0389: // bug in jcc, throws error with null password
0390: //testSecurityMechanism("sarah",null,new Short(SECMEC_USRIDONL),"SECMEC_USRIDONL:");
0391: testSecurityMechanism("john", "sarah", new Short(
0392: SECMEC_USRIDPWD), "SECMEC_USRIDPWD:");
0393:
0394: // Possible bug in JCC, hence disable this test for JCC framework only
0395: // the security mechanism when set on JCC datasource does not seem to
0396: // have an effect. JCC driver is sending a secmec of 3( USRIDPWD) to
0397: // the server even though the security mechanism on datasource is set to
0398: // EUSRIDPWD (9)
0399: if (!TestUtil.isJCCFramework()) {
0400: // Please note: EUSRIDPWD security mechanism in DRDA uses Diffie-Helman for generation of shared keys.
0401: // The spec specifies the prime to use for DH which is 32 bytes and this needs to be used as is.
0402: // Sun JCE does not support a prime of 32 bytes for Diffie Helman and some
0403: // older versions of IBM JCE ( 1.4.2) also do not support it.
0404: // Hence the following call to get connection might not be successful when
0405: // client is running in JVM where the JCE does not support the DH (32 byte prime)
0406: testSecurityMechanism("john", "sarah", new Short(
0407: SECMEC_EUSRIDPWD), "SECMEC_EUSRIDPWD:");
0408: // JCC does not support USRSSBPWD security mechanism
0409: testSecurityMechanism("john", "sarah", new Short(
0410: SECMEC_USRSSBPWD), "SECMEC_USRSSBPWD:");
0411: }
0412: }
0413:
0414: public void testSecurityMechanism(String user, String password,
0415: Short secmec, String msg) {
0416: Connection conn;
0417: String securityMechanismProperty = "SecurityMechanism";
0418: Class[] argType = { Short.TYPE };
0419: String methodName = TestUtil
0420: .getSetterName(securityMechanismProperty);
0421: Object[] args = new Short[1];
0422: args[0] = secmec;
0423:
0424: try {
0425: DataSource ds = getDS("wombat", user, password);
0426: Method sh = ds.getClass().getMethod(methodName, argType);
0427: sh.invoke(ds, args);
0428: conn = ds.getConnection();
0429: conn.close();
0430: System.out.println(msg + " OK");
0431: } catch (SQLException sqle) {
0432: // Exceptions expected in certain cases depending on JCE used for
0433: // running the test. hence printing message instead of stack traces
0434: // here.
0435: System.out.println(msg
0436: + "EXCEPTION testSecurityMechanism() "
0437: + sqle.getMessage());
0438: dumpSQLException(sqle.getNextException());
0439: } catch (Exception e) {
0440: System.out.println("UNEXPECTED EXCEPTION!!!" + msg);
0441: e.printStackTrace();
0442: }
0443: }
0444:
0445: public void getConnectionUsingDriverManager(String dbUrl, String msg) {
0446: try {
0447: DriverManager.getConnection(dbUrl);
0448: System.out.println(msg + " " + dbUrl);
0449: } catch (SQLException sqle) {
0450: // Ideally - we would print stack trace of nested SQLException for
0451: // any unexpected exception.
0452: // But in this testcase, one test can give an exception in one JCE
0453: // implementation and in some JCE's the test can pass.
0454: // Hence printing the messages instead of stack traces.
0455: System.out.println(msg + " " + dbUrl + " - EXCEPTION "
0456: + sqle.getMessage());
0457: dumpSQLException(sqle.getNextException());
0458: }
0459: }
0460:
0461: /**
0462: * Test different interesting combinations of user,password, security mechanism
0463: * for testing security mechanism upgrade logic. This test has been added
0464: * as part of DERBY-962. Two things have been fixed in DERBY-962, affects
0465: * only client behavior.
0466: *
0467: * 1)Upgrade logic should not override security mechanism if it has been
0468: * explicitly set in connection request (either via DriverManager or
0469: * using DataSource)
0470: *
0471: * 2)Upgrade security mechanism to a more secure one , ie preferably
0472: * to encrypted userid and password if the JVM in which the client is
0473: * running has support for it.
0474: *
0475: * Details are:
0476: * If security mechanism is not specified as part of the connection request,
0477: * then client will do an automatic switching (upgrade) of
0478: * security mechanism to use. The logic is as follows :
0479: * if password is available, and if the JVM in which the client is running
0480: * supports EUSRIDPWD mechanism, in that case also, USRIDPWD security mechanism is
0481: * used.
0482: * if password is available, and if the JVM in which the client is running
0483: * does not support EUSRIDPWD mechanism, in that case the client will then
0484: * default to USRIDPWD.
0485: * Also see DERBY-962 http://issues.apache.org/jira/browse/DERBY-962
0486: * <BR>
0487: * To understand which JVMs support EUSRIDPWD or not, please see class level
0488: * comments (#1)
0489: * <BR>
0490: * The expected output from this test will depend on the following
0491: * -- the client behavior (JCC 2.4, JCC2.6 or derby client).For the derby client,
0492: * the table below represents what security mechanism the client will send
0493: * to server.
0494: * -- See class level comments (#2,#3) to understand the JCC2.6 and JCC2.4
0495: * behavior
0496: * -- Note: in case of derby client, if no user is specified, user defaults to APP.
0497: * -- Will depend on if the server has been started with derby.drda.securityMechanism
0498: * and to the value it is set to. See main method to check if server is using the
0499: * derby.drda.securityMechanism to restrict client connections based on
0500: * security mechanism.
0501: *
0502: TABLE with all different combinations of userid, password,
0503: security mechanism of derby client that is covered by this testcase if test
0504: is run against IBM15 and JDK15.
0505:
0506: IBM15 supports eusridpwd, whereas SunJDK15 doesnt support EUSRIDPWD
0507:
0508: Security Mechanisms supported by derby server and client
0509: ====================================================================
0510: |SecMec |codepoint value| User friendly name |
0511: ====================================================================
0512: |USRIDONL | 0x04 | USER_ONLY_SECURITY |
0513: |USRIDPWD | 0x03 | CLEAR_TEXT_PASSWORD_SECURITY |
0514: |EUSRIDPWD | 0x09 | ENCRYPTED_USER_AND_PASSWORD_SECURITY|
0515: |USRSSBPWD | 0x08 | STRONG_PASSWORD_SUBSTITUTE_SECURITY |
0516: =====================================================================
0517: Explanation of columns in table.
0518:
0519: a) Connection request specifies a user or not.
0520: Note: if no user is specified, client defaults to APP
0521: b) Connection request specifies a password or not
0522: c) Connection request specifies securityMechanism or not. the valid
0523: values are 4(USRIDONL), 3(USRIDPWD), 9(EUSRIDPWD) and 8(USRSSBPWD).
0524: d) support eusridpwd means whether this client jvm supports encrypted userid/
0525: password security mechanism or not. A value of Y means it supports
0526: and N means no.
0527: The next three columns specify what the client sends to the server
0528: e) Does client send user information
0529: f) Does client send password information
0530: g) What security mechanism value (secmec value) is sent to server.
0531:
0532: SecMec refers to securityMechanism.
0533: Y means yes, N means No, - or blank means not specified.
0534: Err stands for error.
0535: Err(1) stands for null password not supported
0536: Err(2) stands for case when the JCE does not support encrypted userid and
0537: password security mechanism.
0538: ----------------------------------------------------------------
0539: | url connection | support | Client sends to Server |
0540: |User |Pwd |secmec |eusridpwd |User Pwd SecMec |
0541: |#a |#b |#c |#d |#e #f #g |
0542: |---------------------------------------------------------------|
0543: =================================================================
0544: |SecMec not specified on connection request
0545: =================================================================
0546: |Y |Y |- |Y |Y Y 3 |
0547: |----------------------------------------------------------------
0548: | |Y |- |Y |Y Y 3 |
0549: -----------------------------------------------------------------
0550: |Y | |- |Y |Y N 4 |
0551: -----------------------------------------------------------------
0552: | | |- |Y |Y N 4 |
0553: =================================================================
0554: |Y |Y |- |N |Y Y 3 |
0555: |----------------------------------------------------------------
0556: | |Y |- |N |Y Y 3 |
0557: -----------------------------------------------------------------
0558: |Y | |- |N |Y N 4 |
0559: -----------------------------------------------------------------
0560: | | |- |N |Y N 4 |
0561: =================================================================
0562: SecMec specified to 3 (clear text userid and password)
0563: =================================================================
0564: |Y |Y |3 |Y |Y Y 3 |
0565: |----------------------------------------------------------------
0566: | |Y |3 |Y |Y Y 3 |
0567: -----------------------------------------------------------------
0568: |Y | |3 |Y |- - Err1 |
0569: -----------------------------------------------------------------
0570: | | |3 |Y |- - Err1 |
0571: =================================================================
0572: |Y |Y |3 |N |Y Y 3 |
0573: |----------------------------------------------------------------
0574: | |Y |3 |N |Y Y 3 |
0575: -----------------------------------------------------------------
0576: |Y | |3 |N |- - Err1 |
0577: -----------------------------------------------------------------
0578: | | |3 |N |- - Err1 |
0579: =================================================================
0580: SecMec specified to 9 (encrypted userid/password)
0581: =================================================================
0582: |Y |Y |9 |Y |Y Y 9 |
0583: |----------------------------------------------------------------
0584: | |Y |9 |Y |Y Y 9 |
0585: -----------------------------------------------------------------
0586: |Y | |9 |Y | - - Err1 |
0587: -----------------------------------------------------------------
0588: | | |9 |Y | - - Err1 |
0589: =================================================================
0590: |Y |Y |9 |N | - - Err2 |
0591: |----------------------------------------------------------------
0592: | |Y |9 |N | - - Err2 |
0593: -----------------------------------------------------------------
0594: |Y | |9 |N | - - Err1 |
0595: -----------------------------------------------------------------
0596: | | |9 |N | - - Err1 |
0597: =================================================================
0598: SecMec specified to 4 (userid only security)
0599: =================================================================
0600: |Y |Y |4 |Y |Y N 4 |
0601: |----------------------------------------------------------------
0602: | |Y |4 |Y |Y N 4 |
0603: -----------------------------------------------------------------
0604: |Y | |4 |Y |Y N 4 |
0605: -----------------------------------------------------------------
0606: | | |4 |Y |Y N 4 |
0607: =================================================================
0608: |Y |Y |4 |N |Y N 4 |
0609: |----------------------------------------------------------------
0610: | |Y |4 |N |Y N 4 |
0611: -----------------------------------------------------------------
0612: |Y | |4 |N |Y N 4 |
0613: -----------------------------------------------------------------
0614: | | |4 |N |Y N 4 |
0615: =================================================================
0616: SecMec specified to 8 (strong password substitute)
0617: =================================================================
0618: |Y |Y |8 |Y |Y Y 8 |
0619: |----------------------------------------------------------------
0620: | |Y |8 |Y |Y Y 8 |
0621: -----------------------------------------------------------------
0622: |Y | |8 |Y | - - Err1 |
0623: -----------------------------------------------------------------
0624: | | |8 |Y | - - Err1 |
0625: =================================================================
0626: |Y |Y |8 |N | - Y 8 |
0627: |----------------------------------------------------------------
0628: | |Y |8 |N | - Y 8 |
0629: -----------------------------------------------------------------
0630: |Y | |8 |N | - - Err1 |
0631: -----------------------------------------------------------------
0632: | | |8 |N | - - Err1 |
0633: =================================================================
0634: */
0635: public void testAllCombinationsOfUserPasswordSecMecInput() {
0636: // Try following combinations:
0637: // user { null, user attribute given}
0638: // password {null, pwd specified}
0639: // securityMechanism attribute specified and not specified.
0640: // try with different security mechanism values - {encrypted
0641: // useridpassword, userid only, clear text userid &password)
0642: String urlAttributes = null;
0643:
0644: System.out
0645: .println("******testAllCombinationsOfUserPasswordsSecMecInput***");
0646: for (int k = 0; k < USER_ATTRIBUTE.length; k++) {
0647: for (int j = 0; j < PWD_ATTRIBUTE.length; j++) {
0648: urlAttributes = "";
0649: if (USER_ATTRIBUTE[k] != null)
0650: urlAttributes += "user=" + USER_ATTRIBUTE[k] + ";";
0651: if (PWD_ATTRIBUTE[j] != null)
0652: urlAttributes += "password=" + PWD_ATTRIBUTE[j]
0653: + ";";
0654:
0655: // removing the last semicolon that we added here, because
0656: // on call to getJDBCUrl in dataSourcePermissions_net, another
0657: // semicolon will get added for jcc and jcc will not like it.
0658: if (urlAttributes.length() >= 1)
0659: urlAttributes = urlAttributes.substring(0,
0660: urlAttributes.length() - 1);
0661:
0662: // case - do not specify securityMechanism explicitly in the url
0663: // get connection via driver manager and datasource.
0664: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0665: urlAttributes), "Test:");
0666: getDataSourceConnection(USER_ATTRIBUTE[k],
0667: PWD_ATTRIBUTE[j], "TEST_DS(" + urlAttributes
0668: + ")");
0669:
0670: for (int i = 0; i < SECMEC_ATTRIBUTE.length; i++) {
0671: // case - specify securityMechanism attribute in url
0672: // get connection using DriverManager
0673: getConnectionUsingDriverManager(getJDBCUrl(
0674: "wombat", urlAttributes
0675: + ";securityMechanism="
0676: + SECMEC_ATTRIBUTE[i]), "#");
0677: // case - specify security mechanism on datasource
0678: testSecurityMechanism(USER_ATTRIBUTE[k],
0679: PWD_ATTRIBUTE[j], new Short(
0680: SECMEC_ATTRIBUTE[i]), "TEST_DS ("
0681: + urlAttributes
0682: + ",securityMechanism="
0683: + SECMEC_ATTRIBUTE[i] + ")");
0684: }
0685: }
0686: }
0687: }
0688:
0689: /**
0690: * Helper method to get connection from datasource and to print
0691: * the exceptions if any when getting a connection. This method
0692: * is used in testAllCombinationsOfUserPasswordSecMecInput.
0693: * For explanation of exceptions that might arise in this method,
0694: * please check testAllCombinationsOfUserPasswordSecMecInput
0695: * javadoc comment.
0696: * get connection from datasource
0697: * @param user username
0698: * @param password password
0699: * @param msg message to print for testcase
0700: */
0701: public void getDataSourceConnection(String user, String password,
0702: String msg) {
0703: Connection conn;
0704: try {
0705: // get connection via datasource without setting securityMechanism
0706: DataSource ds = getDS("wombat", user, password);
0707: conn = ds.getConnection();
0708: conn.close();
0709: System.out.println(msg + " OK");
0710: } catch (SQLException sqle) {
0711: // Exceptions expected in certain case hence printing message
0712: // instead of stack traces here.
0713: // - For cases when userid is null or password is null and
0714: // by default JCC does not allow a null password or null userid.
0715: // - For case when JVM does not support EUSRIDPWD and JCC 2.6 tries
0716: // to do autoswitching of security mechanism.
0717: // - For case if server doesnt accept connection with this security
0718: // mechanism
0719: // - For case when client driver does support USRSSBPWD security
0720: // mechanism
0721: System.out.println(msg
0722: + "EXCEPTION getDataSourceConnection() "
0723: + sqle.getMessage());
0724: dumpSQLException(sqle.getNextException());
0725: } catch (Exception e) {
0726: System.out.println("UNEXPECTED EXCEPTION!!!" + msg);
0727: e.printStackTrace();
0728: }
0729: }
0730:
0731: /**
0732: * Dump SQLState and message for the complete nested chain of SQLException
0733: * @param sqle SQLException whose complete chain of exceptions is
0734: * traversed and sqlstate and message is printed out
0735: */
0736: public static void dumpSQLException(SQLException sqle) {
0737: while (sqle != null) {
0738: System.out.println("SQLSTATE(" + sqle.getSQLState() + "): "
0739: + sqle.getMessage());
0740: sqle = sqle.getNextException();
0741: }
0742: }
0743:
0744: /**
0745: * Test a deferred connection reset. When connection pooling is done
0746: * and connection is reset, the client sends EXCSAT,ACCSEC and followed
0747: * by SECCHK and ACCRDB. Test if the security mechanism related information
0748: * is correctly reset or not. This method was added to help simulate regression
0749: * test for DERBY-1080. It is called from testDerby1080
0750: * @param user username
0751: * @param password password for connection
0752: * @param secmec security mechanism for datasource
0753: * @throws Exception
0754: */
0755: public void testSecMecWithConnPooling(String user, String password,
0756: Short secmec) throws Exception {
0757: System.out.println("withConnectionPooling");
0758: Connection conn;
0759: String securityMechanismProperty = "SecurityMechanism";
0760: Class[] argType = { Short.TYPE };
0761: String methodName = TestUtil
0762: .getSetterName(securityMechanismProperty);
0763: Object[] args = new Short[1];
0764: args[0] = secmec;
0765:
0766: ConnectionPoolDataSource cpds = getCPDS("wombat", user,
0767: password);
0768:
0769: // call setSecurityMechanism with secmec.
0770: Method sh = cpds.getClass().getMethod(methodName, argType);
0771: sh.invoke(cpds, args);
0772:
0773: // simulate case when connection will be re-used by getting
0774: // a connection, closing it and then the next call to
0775: // getConnection will re-use the previous connection.
0776: PooledConnection pc = cpds.getPooledConnection();
0777: conn = pc.getConnection();
0778: conn.close();
0779: conn = pc.getConnection();
0780: test(conn);
0781: conn.close();
0782: System.out.println("OK");
0783: }
0784:
0785: /**
0786: * Test a connection by executing a sample query
0787: * @param conn database connection
0788: * @throws Exception if there is any error
0789: */
0790: public void test(Connection conn) throws Exception {
0791:
0792: Statement stmt = null;
0793: ResultSet rs = null;
0794: try {
0795: // To test our connection, we will try to do a select from the system catalog tables
0796: stmt = conn.createStatement();
0797: rs = stmt
0798: .executeQuery("select count(*) from sys.systables");
0799: while (rs.next())
0800: System.out.println(" query ok ");
0801:
0802: } catch (SQLException sqle) {
0803: System.out
0804: .println("SQLException when querying on the database connection; "
0805: + sqle);
0806: throw sqle;
0807: } finally {
0808: if (rs != null)
0809: rs.close();
0810: if (stmt != null)
0811: stmt.close();
0812: }
0813: }
0814:
0815: /**
0816: * This is a regression test for DERBY-1080 - where some variables required
0817: * only for the EUSRIDPWD security mechanism case were not getting reset on
0818: * connection re-use and resulting in protocol error. This also applies to
0819: * USRSSBPWD security mechanism.
0820: *
0821: * Read class level comments (#1) to understand what is specified by drda
0822: * spec for EUSRIDPWD.
0823: * <br>
0824: * Encryption is done using JCE. Hence JCE support of the necessary
0825: * algorithm is required for EUSRIDPWD security mechanism to work. Thus
0826: * even though the server and client have code to support EUSRIDPWD, this
0827: * security mechanism will not work in all JVMs.
0828: *
0829: * JVMs where support for DH(32byte prime) is not available and thus EUSRIDPWD
0830: * wont work are Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and
0831: * IBM JVM (versions 1.3.1 and some old versions of 1.4.2 (in 2004) )
0832: *
0833: * Expected behavior for this test:
0834: * If no regression has occurred, this test should work OK, given the
0835: * expected exception in following cases:
0836: * 1) When EUSRIDPWD is not supported in JVM the test is running, a CNFE
0837: * with initializing EncryptionManager will happen. This will happen for
0838: * Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and
0839: * IBM JVM (versions 1.3.1 and some old versions of 1.4.2 (in 2004) )
0840: * For JCC clients, error message is
0841: * "java.lang.ClassNotFoundException is caught when initializing
0842: * EncryptionManager 'IBMJCE'"
0843: * For derby client, the error message is
0844: * "Security exception encountered, see next exception for details."
0845: * 2)If server does not accept EUSRIDPWD security mechanism from clients,then
0846: * error message will be "Connection authorization failure
0847: * occurred. Reason: security mechanism not supported"
0848: * Note: #2 can happen if server is started with derby.drda.securityMechanism
0849: * and thus restricts what security mechanisms the client can connect with.
0850: * This will happen for the test run when derby.drda.securityMechanism is set and
0851: * to some valid value other than ENCRYPTED_USER_AND_PASSWORD_SECURITY.
0852: * <br>
0853: * See RunTest where this method is called to test for regression for DERBY-1080.
0854: * Also see main method to check if server is using the derby.drda.securityMechanism to
0855: * restrict client connections based on security mechanism.
0856: */
0857: public void testDerby1080() {
0858: try {
0859: System.out.println("Test DERBY-1080");
0860: // simulate connection re-set using connection pooling on a pooled datasource
0861: // set security mechanism to use encrypted userid and password.
0862: testSecMecWithConnPooling("peter", "neelima", new Short(
0863: SECMEC_EUSRIDPWD));
0864: } catch (SQLException sqle) {
0865: // Exceptions expected in certain case hence printing message instead of stack traces
0866: // here.
0867: // - For cases where the jvm does not support EUSRIDPWD.
0868: // - For case if server doesnt accept connection with this security mechanism
0869: // Please see javadoc comments for this test method for more details of expected
0870: // exceptions.
0871: System.out.println("DERBY-1080 EXCEPTION () "
0872: + sqle.getMessage());
0873: dumpSQLException(sqle.getNextException());
0874: } catch (Exception e) {
0875: System.out.println("UNEXPECTED EXCEPTION!!!");
0876: e.printStackTrace();
0877: }
0878:
0879: }
0880:
0881: /**
0882: * Test SECMEC_USRSSBPWD with derby BUILTIN authentication turned ON.
0883: *
0884: * We want to test a combination of USRSSBPWD with BUILTIN as password
0885: * substitute is only supported with NONE or BUILTIN Derby authentication
0886: * scheme right now (DERBY-528).
0887: *
0888: * @throws Exception if there an unexpected error
0889: */
0890: public void testUSRSSBPWD_with_BUILTIN() {
0891: // Turn on Derby BUILTIN authentication and attempt connecting
0892: // with USRSSBPWD security mechanism.
0893: System.out
0894: .println("Test USRSSBPWD_with_BUILTIN - derby.drda.securityMechanism="
0895: + System
0896: .getProperty("derby.drda.securityMechanism"));
0897:
0898: try {
0899: System.out
0900: .println("Turning ON Derby BUILTIN authentication");
0901: Connection conn = getConnectionWithSecMec("neelima", "lee",
0902: new Short(SECMEC_USRSSBPWD));
0903: if (conn == null)
0904: return; // Exception would have been raised
0905:
0906: // Turn on BUILTIN authentication
0907: CallableStatement cs = conn
0908: .prepareCall("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
0909:
0910: cs.setString(1, "derby.user.neelima");
0911: cs.setString(2, "lee");
0912: cs.execute();
0913:
0914: cs.setString(1, "derby.connection.requireAuthentication");
0915: cs.setString(2, "true");
0916: cs.execute();
0917:
0918: cs.close();
0919: cs = null;
0920:
0921: conn.close();
0922:
0923: // Shutdown 'wombat' database for BUILTIN
0924: // authentication to take effect the next time it is
0925: // booted - derby.connection.requireAuthentication is a
0926: // static property.
0927: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0928: "user=neelima;password=lee;shutdown=true;securityMechanism="
0929: + SECMEC_USRSSBPWD), "USRSSBPWD (T0):");
0930:
0931: // Now test some connection(s) with SECMEC_USRSSBPWD
0932: // via DriverManager and Datasource
0933: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0934: "user=neelima;password=lee;securityMechanism="
0935: + SECMEC_USRSSBPWD),
0936: "USRSSBPWD + BUILTIN (T1):");
0937: testSecurityMechanism("neelima", "lee", new Short(
0938: SECMEC_USRSSBPWD),
0939: "TEST_DS - USRSSBPWD + BUILTIN (T2):");
0940: // Attempting to connect with some invalid user
0941: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0942: "user=invalid;password=user;securityMechanism="
0943: + SECMEC_USRSSBPWD),
0944: "USRSSBPWD + BUILTIN (T3):");
0945: testSecurityMechanism("invalid", "user", new Short(
0946: SECMEC_USRSSBPWD),
0947: "TEST_DS - USRSSBPWD + BUILTIN (T4):");
0948:
0949: System.out
0950: .println("Turning OFF Derby BUILTIN authentication");
0951: conn = getConnectionWithSecMec("neelima", "lee", new Short(
0952: SECMEC_USRSSBPWD));
0953:
0954: if (conn == null)
0955: return; // Exception would have been raised
0956:
0957: // Turn off BUILTIN authentication
0958: cs = conn
0959: .prepareCall("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
0960:
0961: cs.setString(1, "derby.connection.requireAuthentication");
0962: cs.setString(2, "false");
0963: cs.execute();
0964:
0965: cs.close();
0966: cs = null;
0967: conn.close();
0968:
0969: // Shutdown 'wombat' database for BUILTIN authentication
0970: // to take effect the next time it is booted
0971: getConnectionUsingDriverManager(getJDBCUrl("wombat",
0972: "user=neelima;password=lee;shutdown=true;securityMechanism="
0973: + SECMEC_USRSSBPWD),
0974: "USRSSBPWD + BUILTIN (T5):");
0975: } catch (Exception e) {
0976: System.out
0977: .println("FAIL: testUSRSSBPWD_with_BUILTIN(). Unexpected Exception "
0978: + e.getMessage());
0979: e.printStackTrace();
0980: }
0981: }
0982:
0983: public Connection getConnectionWithSecMec(String user,
0984: String password, Short secMec) {
0985: Connection conn = null;
0986: String securityMechanismProperty = "SecurityMechanism";
0987: Class[] argType = { Short.TYPE };
0988: String methodName = TestUtil
0989: .getSetterName(securityMechanismProperty);
0990: Object[] args = new Short[1];
0991: args[0] = secMec;
0992:
0993: try {
0994: DataSource ds = getDS("wombat", user, password);
0995: Method sh = ds.getClass().getMethod(methodName, argType);
0996: sh.invoke(ds, args);
0997: conn = ds.getConnection();
0998: } catch (SQLException sqle) {
0999: // Exceptions expected in certain cases depending on JCE used for
1000: // running the test. hence printing message instead of stack traces
1001: // here.
1002: System.out.println("EXCEPTION getConnectionWithSecMec() "
1003: + sqle.getMessage());
1004: dumpSQLException(sqle.getNextException());
1005: } catch (Exception e) {
1006: System.out
1007: .println("UNEXPECTED EXCEPTION!!! getConnectionWithSecMec() - "
1008: + secMec);
1009: e.printStackTrace();
1010: }
1011:
1012: return conn;
1013: }
1014: }
|