KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > tests > derbynet > testSecMec


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.tests.derbynet.testSecMec
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.tests.derbynet;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.ResultSet JavaDoc;
26 import java.sql.PreparedStatement JavaDoc;
27 import java.sql.CallableStatement JavaDoc;
28 import java.sql.Statement JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.sql.DriverManager JavaDoc;
31 import javax.sql.DataSource JavaDoc;
32 import javax.sql.ConnectionPoolDataSource JavaDoc;
33 import javax.sql.PooledConnection JavaDoc;
34
35 import org.apache.derby.tools.JDBCDisplayUtil;
36 import org.apache.derby.tools.ij;
37 import org.apache.derby.drda.NetworkServerControl;
38 import org.apache.derbyTesting.functionTests.util.TestUtil;
39 import java.io.*;
40 import java.net.InetAddress JavaDoc;
41 import java.util.Hashtable JavaDoc;
42 import java.util.Properties JavaDoc;
43
44 import java.lang.reflect.*;
45
46 /**
47  * This class tests the security mechanisms supported by Network Server
48  * Network server supports SECMEC_EUSRIDPWD, SECMEC_USRIDPWD, SECMEC_USRIDONL
49  * and SECMEC_USRSSBPWD.
50  *
51  * -----------------------------------------------------------------
52  * Security Mechanism | secmec codepoint value | User friendly name
53  * -----------------------------------------------------------------
54  * USRIDONL | 0x04 | USER_ONLY_SECURITY
55  * USRIDPWD | 0x03 | CLEAR_TEXT_PASSWORD_SECURITY
56  * EUSRIDPWD | 0x09 | ENCRYPTED_USER_AND_PASSWORD_SECURITY
57  * USRSSBPWD | 0x08 | STRONG_PASSWORD_SUBSTITUTE_SECURITY
58  * -----------------------------------------------------------------
59  *
60  * Key points:
61  * 1)Server and client support encrypted userid/password (EUSRIDPWD) via the
62  * use of Diffie Helman key-agreement protocol - however current Open Group DRDA
63  * specifications imposes small prime and base generator values (256 bits) that
64  * prevents other JCE's to be used as java cryptography providers - typical
65  * minimum security requirements is usually of 1024 bits (512-bit absolute
66  * minimum) when using DH key-agreement protocol to generate a session key.
67  *
68  * (Reference: DDM manual, page 281 and 282. Section: Generating the shared
69  * private key. DRDA's diffie helman agreed public values for prime are 256
70  * bits. The spec gives the public values for the prime, generator and the size
71  * of exponent required for DH . These values must be used as is to generate a
72  * shared private key.)
73  *
74  * Encryption is done using JCE. Hence JCE support of the necessary algorithm is
75  * required for a particular security mechanism to work. Thus even though the
76  * server and client have code to support EUSRIDPWD, this security mechanism
77  * will not work in all JVMs.
78  *
79  * JVMs where support for DH(32byte prime) is not available and thus EUSRIDPWD
80  * wont work are Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and IBM JVM (versions
81  * 1.3.1 and some old versions of 1.4.2 (in 2004) )
82  *
83  * JVMs where support for DH(32bytes prime) is available and thus EUSRIDPWD will
84  * work are IBM JVM [versions 1.4.1, later versions of 1.4.2 (from 2005), 1.5]
85  *
86  * #2) JCC 2.6 client does some automatic upgrade of security mechanism in one
87  * case. Logic is as follows:
88  * If client sends USRIDPWD to server and server rejects this
89  * and says it accepts only EUSRIDPWD, in that case JCC 2.6 will upgrade the
90  * security mechanism to EUSRIDPWD and retry the request with EUSRIDPWD.
91  * This switching will also override the security mechanism specified by user.
92  * Thus if JCC client is running with Sun JVM 1.4.2 and even though Sun JCE
93  * does not have support for algorithms needed for EUSRIDPWD, the JCC client
94  * will still try to switch to EUSRIDPWD and throw an exception with
95  * ClassNotFoundException for the IBM JCE.
96  *
97  * - Default security mechanism is USRIDPWD(0x03)
98  * - If securityMechanism is not explicitly specified on connection request
99  * and if no user specified, an exception is thrown - Null userid not supported
100  * - If securityMechanism is not explicitly specified on connection request,
101  * and if no password is specified, an exception is thrown - null password not supported
102  * If securityMechanism is explicitly specified to be USRIDONL, then a password
103  * is not required. But in other cases (EUSRIDPWD, USRIDPWD, USRSSBPWD) if
104  * password is null, an exception with the message 'a null password not valid'
105  * will be thrown.
106  * - On datasource, setting a security mechanism works. It also allows a security
107  * mechanism of USRIDONL to be set on datasource unlike jcc 2.4.
108  *
109  * #3)JCC 2.4 client behavior
110  * Default security mechanism used is USRIDPWD (0x03)
111  * If securityMechanism is not explicitly specified on connection request,
112  * and if no user is specified, an exception is thrown. - Null userid not supported.
113  * If securityMechanism is not explicitly specified on connection request,
114  * and if no password is specified, an exception is thrown - null password not supported
115  * If security mechanism is specified, jcc client will not override the security mechanism.
116  * If securityMechanism is explicitly specified to be USRIDONL, then a password
117  * is not required. But in other cases (EUSRIDPWD,USRIDPWD) if password is null
118  * - an exception with the message 'a null password not valid' will be thrown.
119  * On datasource, setting a security mechanism does not work (bug). It defaults
120  * to USRIDPWD. Setting a value of USRIDONL or EUSRIDPWD does not seem to have
121  * an effect.
122  *
123  * #4) Note, if server restricts the client connections based on security mechanism
124  * by setting derby.drda.securityMechanism, in that case the clients will see an
125  * error similar to this
126  * "Connection authorization failure occurred. Reason: security mechanism not supported"
127  *
128  * #5) USRSSBPWD - Strong password substitute is only supported starting from
129  * Apache Derby 10.2.
130  * NOTE: USRSSBPWD only works with the derby network client driver for now.
131  * ----
132  */

133 public class testSecMec extends dataSourcePermissions_net
134 {
135     // Need this to keep track of database has been created or not
136
// to avoid case of DERBY-300
137
private static boolean dbNotCreated = true;
138
139     // values for derby.drda.securityMechanism property
140
private static String JavaDoc[] derby_drda_securityMechanism = { null, //not set
141
"USER_ONLY_SECURITY", "CLEAR_TEXT_PASSWORD_SECURITY",
142             "ENCRYPTED_USER_AND_PASSWORD_SECURITY",
143             "STRONG_PASSWORD_SUBSTITUTE_SECURITY", "INVALID_VALUE", "" };
144
145     // possible interesting combinations with respect to security mechanism
146
// upgrade logic for user attribute
147
private static String JavaDoc[] USER_ATTRIBUTE = {"calvin",null};
148  
149     // possible interesting combinations with respect to security mechanism
150
// upgrade logic for password attribute
151
private static String JavaDoc[] PWD_ATTRIBUTE = {"hobbes",null};
152
153     private static int NETWORKSERVER_PORT;
154
155     private static NetworkServerControl networkServer = null;
156     
157     private static FileOutputStream serverOutput;
158
159     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
160         // Load harness properties.
161
ij.getPropertyArg(args);
162         
163         String JavaDoc hostName = TestUtil.getHostName();
164         if (hostName.equals("localhost"))
165             NETWORKSERVER_PORT = 20000;
166         else
167             NETWORKSERVER_PORT = 1527;
168
169         // "runTest()" is going to try to connect to the database through
170
// the server at port NETWORKSERVER_PORT. Thus, we have to
171
// start the server on that port before calling runTest.
172

173         try {
174             TestUtil.loadDriver();
175         } catch (Exception JavaDoc e) {
176             e.printStackTrace();
177         }
178         
179         String JavaDoc fileName = System.getProperty( "derby.system.home", "")
180                 + "serverConsoleOutput.log";
181         serverOutput = new FileOutputStream(fileName);
182            
183         // Start server with a specific value for derby.drda.securityMechanism
184
// and run tests. Note connections will be successful or not depending on
185
// derby.drda.securityMechanism property specified on the server (DERBY-928)
186
// @see
187
// org.apache.derby.iapi.reference.Property#DRDA_PROP_SECURITYMECHANISM
188
for ( int i = 0; i < derby_drda_securityMechanism.length; i++)
189         {
190             if (derby_drda_securityMechanism[i]!=null)
191                 System.setProperty("derby.drda.securityMechanism",derby_drda_securityMechanism[i]);
192             
193             System.out.println("----------------------------------------------");
194             System.out.println("Testing with derby.drda.securityMechanism="+
195                     System.getProperty("derby.drda.securityMechanism"));
196             // Start the NetworkServer on another thread, unless it's a remote host
197
if (hostName.equals("localhost"))
198             {
199                 try
200                 {
201                     networkServer = new NetworkServerControl(InetAddress.getByName(hostName),NETWORKSERVER_PORT);
202                     networkServer.start(new PrintWriter(serverOutput));
203                 }catch(Exception JavaDoc e)
204                 {
205                     if ( derby_drda_securityMechanism[i].equals("INVALID_VALUE")||
206                             derby_drda_securityMechanism[i].equals(""))
207                     {
208                         System.out.println("EXPECTED EXCEPTION "+ e.getMessage());
209                         continue;
210                     }
211                     // if server jvm does not support EUSRIDPWD, an exception
212
// will be raised when server is started with
213
// derby.drda.securityMechanism=ENCRYPTED_USER_AND_PASSWORD_SECURITY
214
System.out.println("EXCEPTION " +e.getMessage());
215                     continue;
216                 }
217                 
218                 // Wait for the NetworkServer to start. As part of DERBY-1793
219
// changed the wait from 60 to 120, which increased the maximum
220
// to 120 pings with a wait of 500 ms between each ping.
221
if (!isServerStarted(networkServer, 120)) {
222                     System.out.println(
223                         "FAIL: Server failed to respond to ping - ending test");
224
225                     break;
226                 }
227             }
228             
229             // Now, go ahead and run the test.
230
try {
231                 testSecMec tester =
232                     new testSecMec();
233                 // Now run the test, note connections will be successful or
234
// throw an exception depending on derby.drda.securityMechanism
235
// property specified on the server
236
tester.runTest();
237                 
238             } catch (Exception JavaDoc e) {
239                 // if we catch an exception of some sort, we need to make sure to
240
// close our streams before returning; otherwise, we can get
241
// hangs in the harness. SO, catching all exceptions here keeps
242
// us from exiting before closing the necessary streams.
243
System.out.println("FAIL - Exiting due to unexpected error: " +
244                         e.getMessage());
245                 e.printStackTrace();
246             }
247             
248             // Shutdown the server.
249
if (hostName.equals("localhost"))
250             {
251                 
252                 networkServer.shutdown();
253                 // how do we do this with the new api?
254
//networkServer.join();
255
Thread.sleep(5000);
256                 
257             }
258
259             // Now we want to test
260
}
261         System.out.println("Completed testSecMec");
262
263         serverOutput.close();
264     }
265     
266     // Indicates userid/encrypted password security mechanism.
267
static final short SECMEC_EUSRIDPWD = 0x09;
268
269     // Indicates userid only security mechanism.
270
static final short SECMEC_USRIDONL = 0x04;
271
272     // Indicates userid/encrypted password security mechanism.
273
static final short SECMEC_USRENCPWD = 0x07;
274
275     // Indicates userid/new password security mechanism.
276
static final short SECMEC_USRIDNWPWD = 0x05;
277
278     // Indicates userid/password security mechanism.
279
static final short SECMEC_USRIDPWD = 0x03;
280
281     // Indicates strong password substitute security mechanism.
282
static final short SECMEC_USRSSBPWD = 0x08;
283       
284     // client and server recognize these secmec values
285
private static short[] SECMEC_ATTRIBUTE = {
286                 SECMEC_USRIDONL,
287                 SECMEC_USRIDPWD,
288                 SECMEC_EUSRIDPWD,
289                 SECMEC_USRSSBPWD
290     };
291
292     /**
293      * Test cases for security mechanism
294      * ---------------------------------------------------------------
295      * T1 - default , no user PASS (for derbyclient)
296      * T2 - user only PASS (for derbyclient)
297      * T3 - user,password PASS (only for derbynet)
298      * T4 - user,password, security mechanism not set FAIL
299      * T5 - user,password, security mechanism set to SECMEC_EUSRIDPWD PASS/FAIL
300      * (Fails with Sun JVM as EUSRIDPWD secmec cannot be used)
301      * T6 - user, security mechanism set to SECMEC_USRIDONL PASS
302      * T7 - user,password, security mechanism set to SECMEC_USRENCPWD FAIL
303      * Test with datasource as well as DriverManager
304      * T8 - user,password security mechanism set to SECMEC_USRIDONL PASS
305      * T9 - user,password security mechanism set to SECMEC_USRSSBPWD PASS
306      * Test with datasource as well as DriverManager
307      * Note, that with DERBY928, the pass/fail for the connections
308      * will depend on the security mechanism specified at the server by property
309      * derby.drda.securityMechanism. Please check out the following html file
310      * http://issues.apache.org/jira/secure/attachment/12322971/Derby928_Table_SecurityMechanisms..htm
311      * for a combination of url/security mechanisms and the expected results
312      */

313     protected void runTest()
314     {
315         // Test cases with get connection via drivermanager and using
316
// different security mechanisms.
317
// Network server supports SECMEC_USRIDPWD, SECMEC_USRIDONL,
318
// SECMEC_EUSRIDPWD and USRSSBPWD (derby network client only)
319
System.out.println("Checking security mechanism authentication with DriverManager");
320         
321         // DERBY-300; Creation of SQLWarning on a getConnection causes hang on
322
// 131 vms when server and client are in same vm.
323
// To avoid hitting this case with 1.3.1 vms, dont try to send create=true
324
// if database is already created as otherwise it will lead to a SQLWarning
325
if ( dbNotCreated )
326         {
327             getConnectionUsingDriverManager(getJDBCUrl("wombat;create=true","user=neelima;password=lee;securityMechanism="+SECMEC_USRIDPWD),"T4:");
328             dbNotCreated = false;
329         }
330         else
331             getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_USRIDPWD),"T4:");
332         getConnectionUsingDriverManager(getJDBCUrl("wombat",null),"T1:");
333         getConnectionUsingDriverManager(getJDBCUrl("wombat","user=max"),"T2:");
334         getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee"),"T3:");
335
336         // Please note: EUSRIDPWD security mechanism in DRDA uses Diffie-Helman for generation of shared keys.
337
// The spec specifies the prime to use for DH which is 32 bytes and this needs to be used as is.
338
// Sun JCE does not support a prime of 32 bytes for Diffie Helman and some
339
// older versions of IBM JCE ( 1.4.2) also do not support it.
340
// Hence the following call to get connection might not be successful when
341
// client is running in JVM where the JCE does not support the DH (32 byte prime)
342
getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_EUSRIDPWD),"T5:");
343         getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;securityMechanism="+SECMEC_USRIDONL),"T6:");
344                 
345                 // disable as ibm142 and sun jce doesnt support DH prime of 32 bytes
346
//getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_USRENCPWD),"T7:");
347
getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_USRIDONL),"T8:");
348         // Test strong password substitute DRDA security mechanism (only works with DerbyClient driver right now)
349
getConnectionUsingDriverManager(getJDBCUrl("wombat","user=neelima;password=lee;securityMechanism="+SECMEC_USRSSBPWD),"T9:");
350
351         getConnectionUsingDataSource();
352
353         // regression test for DERBY-1080
354
testDerby1080();
355
356         // test for DERBY-962
357
testAllCombinationsOfUserPasswordSecMecInput();
358
359         // test USRSSBPWD (DERBY-528) with Derby BUILTIN authentication scheme
360
// both with none and USRSSBPWD specified DRDA SecMec upon
361
// starting the network server.
362
String JavaDoc serverSecurityMechanism =
363             System.getProperty("derby.drda.securityMechanism");
364
365         if ((serverSecurityMechanism == null) ||
366             (serverSecurityMechanism.equals(
367                         "STRONG_PASSWORD_SUBSTITUTE_SECURITY")))
368         {
369             testUSRSSBPWD_with_BUILTIN();
370         }
371     }
372
373     /**
374      * Get connection from datasource and also set security mechanism
375      */

376     public void getConnectionUsingDataSource()
377     {
378         // bug in jcc, throws error with null password
379
//testSecurityMechanism("sarah",null,new Short(SECMEC_USRIDONL),"SECMEC_USRIDONL:");
380
testSecurityMechanism("john","sarah",new Short JavaDoc(SECMEC_USRIDPWD),"SECMEC_USRIDPWD:");
381                 
382         // Possible bug in JCC, hence disable this test for JCC framework only
383
// the security mechanism when set on JCC datasource does not seem to
384
// have an effect. JCC driver is sending a secmec of 3( USRIDPWD) to
385
// the server even though the security mechanism on datasource is set to
386
// EUSRIDPWD (9)
387
if (!TestUtil.isJCCFramework())
388         {
389             // Please note: EUSRIDPWD security mechanism in DRDA uses Diffie-Helman for generation of shared keys.
390
// The spec specifies the prime to use for DH which is 32 bytes and this needs to be used as is.
391
// Sun JCE does not support a prime of 32 bytes for Diffie Helman and some
392
// older versions of IBM JCE ( 1.4.2) also do not support it.
393
// Hence the following call to get connection might not be successful when
394
// client is running in JVM where the JCE does not support the DH (32 byte prime)
395
testSecurityMechanism("john","sarah",new Short JavaDoc(SECMEC_EUSRIDPWD),"SECMEC_EUSRIDPWD:");
396             // JCC does not support USRSSBPWD security mechanism
397
testSecurityMechanism("john","sarah",new Short JavaDoc(SECMEC_USRSSBPWD),"SECMEC_USRSSBPWD:");
398         }
399     }
400
401     public void testSecurityMechanism(String JavaDoc user, String JavaDoc password,Short JavaDoc secmec,String JavaDoc msg)
402     {
403         Connection JavaDoc conn;
404         String JavaDoc securityMechanismProperty = "SecurityMechanism";
405         Class JavaDoc[] argType = { Short.TYPE };
406         String JavaDoc methodName = TestUtil.getSetterName(securityMechanismProperty);
407         Object JavaDoc[] args = new Short JavaDoc[1];
408         args[0] = secmec;
409
410         try {
411             DataSource JavaDoc ds = getDS("wombat", user,password);
412             Method sh = ds.getClass().getMethod(methodName, argType);
413             sh.invoke(ds, args);
414             conn = ds.getConnection();
415             conn.close();
416             System.out.println(msg +" OK");
417         }
418         catch (SQLException JavaDoc sqle)
419         {
420             // Exceptions expected in certain cases depending on JCE used for
421
// running the test. hence printing message instead of stack traces
422
// here.
423
System.out.println(msg +"EXCEPTION testSecurityMechanism() " + sqle.getMessage());
424             dumpSQLException(sqle.getNextException());
425         }
426         catch (Exception JavaDoc e)
427         {
428             System.out.println("UNEXPECTED EXCEPTION!!!" +msg);
429             e.printStackTrace();
430         }
431     }
432
433     public void getConnectionUsingDriverManager(String JavaDoc dbUrl, String JavaDoc msg)
434     {
435         try
436         {
437             DriverManager.getConnection(dbUrl);
438             System.out.println(msg +" "+dbUrl );
439         }
440         catch(SQLException JavaDoc sqle)
441         {
442             // Ideally - we would print stack trace of nested SQLException for
443
// any unexpected exception.
444
// But in this testcase, one test can give an exception in one JCE
445
// implementation and in some JCE's the test can pass.
446
// Hence printing the messages instead of stack traces.
447
System.out.println(msg +" "+dbUrl +" - EXCEPTION "+ sqle.getMessage());
448             dumpSQLException(sqle.getNextException());
449         }
450     }
451
452     /**
453      * Test different interesting combinations of user,password, security mechanism
454      * for testing security mechanism upgrade logic. This test has been added
455      * as part of DERBY-962. Two things have been fixed in DERBY-962, affects
456      * only client behavior.
457      *
458      * 1)Upgrade logic should not override security mechanism if it has been
459      * explicitly set in connection request (either via DriverManager or
460      * using DataSource)
461      *
462      * 2)Upgrade security mechanism to a more secure one , ie preferably
463      * to encrypted userid and password if the JVM in which the client is
464      * running has support for it.
465      *
466      * Details are:
467      * If security mechanism is not specified as part of the connection request,
468      * then client will do an automatic switching (upgrade) of
469      * security mechanism to use. The logic is as follows :
470      * if password is available, and if the JVM in which the client is running
471      * supports EUSRIDPWD mechanism, in that case also, USRIDPWD security mechanism is
472      * used.
473      * if password is available, and if the JVM in which the client is running
474      * does not support EUSRIDPWD mechanism, in that case the client will then
475      * default to USRIDPWD.
476      * Also see DERBY-962 http://issues.apache.org/jira/browse/DERBY-962
477      * <BR>
478      * To understand which JVMs support EUSRIDPWD or not, please see class level
479      * comments (#1)
480      * <BR>
481      * The expected output from this test will depend on the following
482      * -- the client behavior (JCC 2.4, JCC2.6 or derby client).For the derby client,
483      * the table below represents what security mechanism the client will send
484      * to server.
485      * -- See class level comments (#2,#3) to understand the JCC2.6 and JCC2.4
486      * behavior
487      * -- Note: in case of derby client, if no user is specified, user defaults to APP.
488      * -- Will depend on if the server has been started with derby.drda.securityMechanism
489      * and to the value it is set to. See main method to check if server is using the
490      * derby.drda.securityMechanism to restrict client connections based on
491      * security mechanism.
492      *
493      TABLE with all different combinations of userid, password,
494      security mechanism of derby client that is covered by this testcase if test
495      is run against IBM15 and JDK15.
496           
497      IBM15 supports eusridpwd, whereas SunJDK15 doesnt support EUSRIDPWD
498      
499      Security Mechanisms supported by derby server and client
500      ====================================================================
501      |SecMec |codepoint value| User friendly name |
502      ====================================================================
503      |USRIDONL | 0x04 | USER_ONLY_SECURITY |
504      |USRIDPWD | 0x03 | CLEAR_TEXT_PASSWORD_SECURITY |
505      |EUSRIDPWD | 0x09 | ENCRYPTED_USER_AND_PASSWORD_SECURITY|
506      |USRSSBPWD | 0x08 | STRONG_PASSWORD_SUBSTITUTE_SECURITY |
507      =====================================================================
508      Explanation of columns in table.
509      
510      a) Connection request specifies a user or not.
511      Note: if no user is specified, client defaults to APP
512      b) Connection request specifies a password or not
513      c) Connection request specifies securityMechanism or not. the valid
514      values are 4(USRIDONL), 3(USRIDPWD), 9(EUSRIDPWD) and 8(USRSSBPWD).
515      d) support eusridpwd means whether this client jvm supports encrypted userid/
516      password security mechanism or not. A value of Y means it supports
517      and N means no.
518      The next three columns specify what the client sends to the server
519      e) Does client send user information
520      f) Does client send password information
521      g) What security mechanism value (secmec value) is sent to server.
522      
523      SecMec refers to securityMechanism.
524      Y means yes, N means No, - or blank means not specified.
525      Err stands for error.
526      Err(1) stands for null password not supported
527      Err(2) stands for case when the JCE does not support encrypted userid and
528      password security mechanism.
529      ----------------------------------------------------------------
530      | url connection | support | Client sends to Server |
531      |User |Pwd |secmec |eusridpwd |User Pwd SecMec |
532      |#a |#b |#c |#d |#e #f #g |
533      |---------------------------------------------------------------|
534      =================================================================
535      |SecMec not specified on connection request
536      =================================================================
537      |Y |Y |- |Y |Y Y 3 |
538      |----------------------------------------------------------------
539      | |Y |- |Y |Y Y 3 |
540      -----------------------------------------------------------------
541      |Y | |- |Y |Y N 4 |
542      -----------------------------------------------------------------
543      | | |- |Y |Y N 4 |
544      =================================================================
545      |Y |Y |- |N |Y Y 3 |
546      |----------------------------------------------------------------
547      | |Y |- |N |Y Y 3 |
548      -----------------------------------------------------------------
549      |Y | |- |N |Y N 4 |
550      -----------------------------------------------------------------
551      | | |- |N |Y N 4 |
552      =================================================================
553      SecMec specified to 3 (clear text userid and password)
554      =================================================================
555      |Y |Y |3 |Y |Y Y 3 |
556      |----------------------------------------------------------------
557      | |Y |3 |Y |Y Y 3 |
558      -----------------------------------------------------------------
559      |Y | |3 |Y |- - Err1 |
560      -----------------------------------------------------------------
561      | | |3 |Y |- - Err1 |
562      =================================================================
563      |Y |Y |3 |N |Y Y 3 |
564      |----------------------------------------------------------------
565      | |Y |3 |N |Y Y 3 |
566      -----------------------------------------------------------------
567      |Y | |3 |N |- - Err1 |
568      -----------------------------------------------------------------
569      | | |3 |N |- - Err1 |
570      =================================================================
571      SecMec specified to 9 (encrypted userid/password)
572      =================================================================
573      |Y |Y |9 |Y |Y Y 9 |
574      |----------------------------------------------------------------
575      | |Y |9 |Y |Y Y 9 |
576      -----------------------------------------------------------------
577      |Y | |9 |Y | - - Err1 |
578      -----------------------------------------------------------------
579      | | |9 |Y | - - Err1 |
580      =================================================================
581      |Y |Y |9 |N | - - Err2 |
582      |----------------------------------------------------------------
583      | |Y |9 |N | - - Err2 |
584      -----------------------------------------------------------------
585      |Y | |9 |N | - - Err1 |
586      -----------------------------------------------------------------
587      | | |9 |N | - - Err1 |
588      =================================================================
589      SecMec specified to 4 (userid only security)
590      =================================================================
591      |Y |Y |4 |Y |Y N 4 |
592      |----------------------------------------------------------------
593      | |Y |4 |Y |Y N 4 |
594      -----------------------------------------------------------------
595      |Y | |4 |Y |Y N 4 |
596      -----------------------------------------------------------------
597      | | |4 |Y |Y N 4 |
598      =================================================================
599      |Y |Y |4 |N |Y N 4 |
600      |----------------------------------------------------------------
601      | |Y |4 |N |Y N 4 |
602      -----------------------------------------------------------------
603      |Y | |4 |N |Y N 4 |
604      -----------------------------------------------------------------
605      | | |4 |N |Y N 4 |
606      =================================================================
607      SecMec specified to 8 (strong password substitute)
608      =================================================================
609      |Y |Y |8 |Y |Y Y 8 |
610      |----------------------------------------------------------------
611      | |Y |8 |Y |Y Y 8 |
612      -----------------------------------------------------------------
613      |Y | |8 |Y | - - Err1 |
614      -----------------------------------------------------------------
615      | | |8 |Y | - - Err1 |
616      =================================================================
617      |Y |Y |8 |N | - Y 8 |
618      |----------------------------------------------------------------
619      | |Y |8 |N | - Y 8 |
620      -----------------------------------------------------------------
621      |Y | |8 |N | - - Err1 |
622      -----------------------------------------------------------------
623      | | |8 |N | - - Err1 |
624      =================================================================
625      */

626     public void testAllCombinationsOfUserPasswordSecMecInput() {
627         // Try following combinations:
628
// user { null, user attribute given}
629
// password {null, pwd specified}
630
// securityMechanism attribute specified and not specified.
631
// try with different security mechanism values - {encrypted
632
// useridpassword, userid only, clear text userid &password)
633
String JavaDoc urlAttributes = null;
634
635         System.out.println("******testAllCombinationsOfUserPasswordsSecMecInput***");
636         for (int k = 0; k < USER_ATTRIBUTE.length; k++) {
637             for (int j = 0; j < PWD_ATTRIBUTE.length; j++) {
638                 urlAttributes = "";
639                 if (USER_ATTRIBUTE[k] != null)
640                     urlAttributes += "user=" + USER_ATTRIBUTE[k] +";";
641                 if (PWD_ATTRIBUTE[j] != null)
642                     urlAttributes += "password=" + PWD_ATTRIBUTE[j] +";";
643                
644                 // removing the last semicolon that we added here, because
645
// on call to getJDBCUrl in dataSourcePermissions_net, another
646
// semicolon will get added for jcc and jcc will not like it.
647
if (urlAttributes.length() >= 1)
648                     urlAttributes = urlAttributes.substring(0,urlAttributes.length()-1);
649
650                 // case - do not specify securityMechanism explicitly in the url
651
// get connection via driver manager and datasource.
652
getConnectionUsingDriverManager(getJDBCUrl("wombat",
653                         urlAttributes), "Test:");
654                 getDataSourceConnection(USER_ATTRIBUTE[k],PWD_ATTRIBUTE[j],
655                         "TEST_DS("+urlAttributes+")");
656                 
657                 for (int i = 0; i < SECMEC_ATTRIBUTE.length; i++) {
658                     // case - specify securityMechanism attribute in url
659
// get connection using DriverManager
660
getConnectionUsingDriverManager(getJDBCUrl("wombat",
661                             urlAttributes + ";securityMechanism="
662                                     + SECMEC_ATTRIBUTE[i]), "#");
663                     // case - specify security mechanism on datasource
664
testSecurityMechanism(USER_ATTRIBUTE[k],PWD_ATTRIBUTE[j],
665                             new Short JavaDoc(SECMEC_ATTRIBUTE[i]),"TEST_DS ("+urlAttributes+
666                             ",securityMechanism="+SECMEC_ATTRIBUTE[i]+")");
667                 }
668             }
669         }
670     }
671
672     /**
673      * Helper method to get connection from datasource and to print
674      * the exceptions if any when getting a connection. This method
675      * is used in testAllCombinationsOfUserPasswordSecMecInput.
676      * For explanation of exceptions that might arise in this method,
677      * please check testAllCombinationsOfUserPasswordSecMecInput
678      * javadoc comment.
679      * get connection from datasource
680      * @param user username
681      * @param password password
682      * @param msg message to print for testcase
683      */

684     public void getDataSourceConnection(String JavaDoc user, String JavaDoc password,String JavaDoc msg)
685     {
686         Connection JavaDoc conn;
687         try {
688             // get connection via datasource without setting securityMechanism
689
DataSource JavaDoc ds = getDS("wombat", user, password);
690             conn = ds.getConnection();
691             conn.close();
692             System.out.println(msg + " OK");
693         }
694         catch (SQLException JavaDoc sqle)
695         {
696             // Exceptions expected in certain case hence printing message
697
// instead of stack traces here.
698
// - For cases when userid is null or password is null and
699
// by default JCC does not allow a null password or null userid.
700
// - For case when JVM does not support EUSRIDPWD and JCC 2.6 tries
701
// to do autoswitching of security mechanism.
702
// - For case if server doesnt accept connection with this security
703
// mechanism
704
// - For case when client driver does support USRSSBPWD security
705
// mechanism
706
System.out.println(msg + "EXCEPTION getDataSourceConnection() " + sqle.getMessage());
707             dumpSQLException(sqle.getNextException());
708         }
709         catch (Exception JavaDoc e)
710         {
711             System.out.println("UNEXPECTED EXCEPTION!!!" + msg);
712             e.printStackTrace();
713         }
714     }
715
716     /**
717      * Dump SQLState and message for the complete nested chain of SQLException
718      * @param sqle SQLException whose complete chain of exceptions is
719      * traversed and sqlstate and message is printed out
720      */

721     public static void dumpSQLException(SQLException JavaDoc sqle)
722     {
723         while ( sqle != null)
724         {
725             System.out.println("SQLSTATE("+sqle.getSQLState()+"): " + sqle.getMessage());
726             sqle = sqle.getNextException();
727         }
728     }
729
730     /**
731      * Test a deferred connection reset. When connection pooling is done
732      * and connection is reset, the client sends EXCSAT,ACCSEC and followed
733      * by SECCHK and ACCRDB. Test if the security mechanism related information
734      * is correctly reset or not. This method was added to help simulate regression
735      * test for DERBY-1080. It is called from testDerby1080
736      * @param user username
737      * @param password password for connection
738      * @param secmec security mechanism for datasource
739      * @throws Exception
740      */

741     public void testSecMecWithConnPooling(String JavaDoc user, String JavaDoc password,
742             Short JavaDoc secmec) throws Exception JavaDoc
743     {
744         System.out.println("withConnectionPooling");
745         Connection JavaDoc conn;
746         String JavaDoc securityMechanismProperty = "SecurityMechanism";
747         Class JavaDoc[] argType = { Short.TYPE };
748         String JavaDoc methodName = TestUtil.getSetterName(securityMechanismProperty);
749         Object JavaDoc[] args = new Short JavaDoc[1];
750         args[0] = secmec;
751         
752         ConnectionPoolDataSource JavaDoc cpds = getCPDS("wombat", user,password);
753         
754         // call setSecurityMechanism with secmec.
755
Method sh = cpds.getClass().getMethod(methodName, argType);
756         sh.invoke(cpds, args);
757         
758         // simulate case when connection will be re-used by getting
759
// a connection, closing it and then the next call to
760
// getConnection will re-use the previous connection.
761
PooledConnection JavaDoc pc = cpds.getPooledConnection();
762         conn = pc.getConnection();
763         conn.close();
764         conn = pc.getConnection();
765         test(conn);
766         conn.close();
767         System.out.println("OK");
768     }
769
770     /**
771      * Test a connection by executing a sample query
772      * @param conn database connection
773      * @throws Exception if there is any error
774      */

775     public void test(Connection JavaDoc conn)
776         throws Exception JavaDoc
777     {
778
779       Statement JavaDoc stmt = null;
780       ResultSet JavaDoc rs = null;
781       try
782       {
783         // To test our connection, we will try to do a select from the system catalog tables
784
stmt = conn.createStatement();
785         rs = stmt.executeQuery("select count(*) from sys.systables");
786         while(rs.next())
787             System.out.println(" query ok ");
788
789       }
790       catch(SQLException JavaDoc sqle)
791       {
792           System.out.println("SQLException when querying on the database connection; "+ sqle);
793           throw sqle;
794       }
795       finally
796       {
797           if(rs != null)
798             rs.close();
799           if(stmt != null)
800             stmt.close();
801       }
802     }
803     
804     /**
805      * This is a regression test for DERBY-1080 - where some variables required
806      * only for the EUSRIDPWD security mechanism case were not getting reset on
807      * connection re-use and resulting in protocol error. This also applies to
808      * USRSSBPWD security mechanism.
809      *
810      * Read class level comments (#1) to understand what is specified by drda
811      * spec for EUSRIDPWD.
812      * <br>
813      * Encryption is done using JCE. Hence JCE support of the necessary
814      * algorithm is required for EUSRIDPWD security mechanism to work. Thus
815      * even though the server and client have code to support EUSRIDPWD, this
816      * security mechanism will not work in all JVMs.
817      *
818      * JVMs where support for DH(32byte prime) is not available and thus EUSRIDPWD
819      * wont work are Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and
820      * IBM JVM (versions 1.3.1 and some old versions of 1.4.2 (in 2004) )
821      *
822      * Expected behavior for this test:
823      * If no regression has occurred, this test should work OK, given the
824      * expected exception in following cases:
825      * 1) When EUSRIDPWD is not supported in JVM the test is running, a CNFE
826      * with initializing EncryptionManager will happen. This will happen for
827      * Sun JVM (versions 1.3.1,1.4.1,1.4.2,1.5) and
828      * IBM JVM (versions 1.3.1 and some old versions of 1.4.2 (in 2004) )
829      * For JCC clients, error message is
830      * "java.lang.ClassNotFoundException is caught when initializing
831      * EncryptionManager 'IBMJCE'"
832      * For derby client, the error message is
833      * "Security exception encountered, see next exception for details."
834      * 2)If server does not accept EUSRIDPWD security mechanism from clients,then
835      * error message will be "Connection authorization failure
836      * occurred. Reason: security mechanism not supported"
837      * Note: #2 can happen if server is started with derby.drda.securityMechanism
838      * and thus restricts what security mechanisms the client can connect with.
839      * This will happen for the test run when derby.drda.securityMechanism is set and
840      * to some valid value other than ENCRYPTED_USER_AND_PASSWORD_SECURITY.
841      * <br>
842      * See RunTest where this method is called to test for regression for DERBY-1080.
843      * Also see main method to check if server is using the derby.drda.securityMechanism to
844      * restrict client connections based on security mechanism.
845      */

846     public void testDerby1080()
847     {
848         try
849         {
850             System.out.println("Test DERBY-1080");
851             // simulate connection re-set using connection pooling on a pooled datasource
852
// set security mechanism to use encrypted userid and password.
853
testSecMecWithConnPooling("peter","neelima",new Short JavaDoc(SECMEC_EUSRIDPWD));
854         }
855         catch (SQLException JavaDoc sqle)
856         {
857             // Exceptions expected in certain case hence printing message instead of stack traces
858
// here.
859
// - For cases where the jvm does not support EUSRIDPWD.
860
// - For case if server doesnt accept connection with this security mechanism
861
// Please see javadoc comments for this test method for more details of expected
862
// exceptions.
863
System.out.println("DERBY-1080 EXCEPTION () " + sqle.getMessage());
864             dumpSQLException(sqle.getNextException());
865         }
866         catch (Exception JavaDoc e)
867         {
868             System.out.println("UNEXPECTED EXCEPTION!!!" );
869             e.printStackTrace();
870         }
871
872     }
873
874     /**
875      * Test SECMEC_USRSSBPWD with derby BUILTIN authentication turned ON.
876      *
877      * We want to test a combination of USRSSBPWD with BUILTIN as password
878      * substitute is only supported with NONE or BUILTIN Derby authentication
879      * scheme right now (DERBY-528).
880      *
881      * @throws Exception if there an unexpected error
882      */

883     public void testUSRSSBPWD_with_BUILTIN()
884     {
885         // Turn on Derby BUILTIN authentication and attempt connecting
886
// with USRSSBPWD security mechanism.
887
System.out.println(
888             "Test USRSSBPWD_with_BUILTIN - derby.drda.securityMechanism=" +
889             System.getProperty("derby.drda.securityMechanism"));
890
891         try
892         {
893             System.out.println("Turning ON Derby BUILTIN authentication");
894             Connection JavaDoc conn =
895                 getConnectionWithSecMec("neelima", "lee",
896                                         new Short JavaDoc(SECMEC_USRSSBPWD));
897             if (conn == null)
898                 return; // Exception would have been raised
899

900             // Turn on BUILTIN authentication
901
CallableStatement JavaDoc cs =
902                 conn.prepareCall(
903                         "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
904             
905             cs.setString(1, "derby.user.neelima");
906             cs.setString(2, "lee");
907             cs.execute();
908             
909             cs.setString(1, "derby.connection.requireAuthentication");
910             cs.setString(2, "true");
911             cs.execute();
912
913             cs.close();
914             cs = null;
915
916             conn.close();
917
918             // Shutdown 'wombat' database for BUILTIN
919
// authentication to take effect the next time it is
920
// booted - derby.connection.requireAuthentication is a
921
// static property.
922
getConnectionUsingDriverManager(getJDBCUrl(
923                 "wombat","user=neelima;password=lee;shutdown=true;securityMechanism=" +
924                 SECMEC_USRSSBPWD),"USRSSBPWD (T0):");
925
926             // Now test some connection(s) with SECMEC_USRSSBPWD
927
// via DriverManager and Datasource
928
getConnectionUsingDriverManager(getJDBCUrl(
929                 "wombat","user=neelima;password=lee;securityMechanism=" +
930                 SECMEC_USRSSBPWD),"USRSSBPWD + BUILTIN (T1):");
931             testSecurityMechanism("neelima","lee",new Short JavaDoc(SECMEC_USRSSBPWD),
932                                   "TEST_DS - USRSSBPWD + BUILTIN (T2):");
933             // Attempting to connect with some invalid user
934
getConnectionUsingDriverManager(getJDBCUrl(
935                 "wombat","user=invalid;password=user;securityMechanism=" +
936                 SECMEC_USRSSBPWD),"USRSSBPWD + BUILTIN (T3):");
937             testSecurityMechanism("invalid","user",new Short JavaDoc(SECMEC_USRSSBPWD),
938                                   "TEST_DS - USRSSBPWD + BUILTIN (T4):");
939
940             System.out.println("Turning OFF Derby BUILTIN authentication");
941             conn = getConnectionWithSecMec("neelima", "lee",
942                                            new Short JavaDoc(SECMEC_USRSSBPWD));
943
944             if (conn == null)
945                 return; // Exception would have been raised
946

947             // Turn off BUILTIN authentication
948
cs = conn.prepareCall(
949                 "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
950             
951             cs.setString(1, "derby.connection.requireAuthentication");
952             cs.setString(2, "false");
953             cs.execute();
954
955             cs.close();
956             cs = null;
957             conn.close();
958
959             // Shutdown 'wombat' database for BUILTIN authentication
960
// to take effect the next time it is booted
961
getConnectionUsingDriverManager(getJDBCUrl(
962                 "wombat","user=neelima;password=lee;shutdown=true;securityMechanism=" +
963                 SECMEC_USRSSBPWD),"USRSSBPWD + BUILTIN (T5):");
964         }
965         catch (Exception JavaDoc e)
966         {
967             System.out.println(
968                 "FAIL: testUSRSSBPWD_with_BUILTIN(). Unexpected Exception " +
969                 e.getMessage());
970             e.printStackTrace();
971         }
972     }
973     
974     public Connection JavaDoc getConnectionWithSecMec(String JavaDoc user,
975                                               String JavaDoc password,
976                                               Short JavaDoc secMec)
977     {
978         Connection JavaDoc conn = null;
979         String JavaDoc securityMechanismProperty = "SecurityMechanism";
980         Class JavaDoc[] argType = { Short.TYPE };
981         String JavaDoc methodName = TestUtil.getSetterName(securityMechanismProperty);
982         Object JavaDoc[] args = new Short JavaDoc[1];
983         args[0] = secMec;
984
985         try {
986             DataSource JavaDoc ds = getDS("wombat", user, password);
987             Method sh = ds.getClass().getMethod(methodName, argType);
988             sh.invoke(ds, args);
989             conn = ds.getConnection();
990         }
991         catch (SQLException JavaDoc sqle)
992         {
993             // Exceptions expected in certain cases depending on JCE used for
994
// running the test. hence printing message instead of stack traces
995
// here.
996
System.out.println("EXCEPTION getConnectionWithSecMec() " + sqle.getMessage());
997             dumpSQLException(sqle.getNextException());
998         }
999         catch (Exception JavaDoc e)
1000        {
1001            System.out.println(
1002                    "UNEXPECTED EXCEPTION!!! getConnectionWithSecMec() - " +
1003                    secMec);
1004            e.printStackTrace();
1005        }
1006
1007        return conn;
1008    }
1009}
1010
Popular Tags