test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java
changeset 48852 478e198da84b
child 57345 ff884a2f247b
equal deleted inserted replaced
48851:1d8f882f2b2f 48852:478e198da84b
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 import com.sun.jndi.ldap.LdapURL;
       
    25 
       
    26 import javax.naming.Context;
       
    27 import javax.naming.NamingEnumeration;
       
    28 import javax.naming.NamingException;
       
    29 import javax.naming.directory.Attribute;
       
    30 import javax.naming.directory.Attributes;
       
    31 import javax.naming.directory.DirContext;
       
    32 import javax.naming.directory.SearchResult;
       
    33 import java.io.FileNotFoundException;
       
    34 import java.io.PrintStream;
       
    35 import java.net.ServerSocket;
       
    36 import java.nio.file.Files;
       
    37 import java.nio.file.Path;
       
    38 import java.nio.file.Paths;
       
    39 import java.util.Enumeration;
       
    40 import java.util.Hashtable;
       
    41 import java.util.Vector;
       
    42 
       
    43 public class LDAPTestUtils {
       
    44     public static final String TEST_LDAP_SERVER_THREAD = "test.ldap.server.thread";
       
    45     public static final int CERTS_LOOKUP_MAX_DEPTH = 4;
       
    46 
       
    47     protected static boolean debug = true;
       
    48 
       
    49     /*
       
    50      * Process command line arguments and return properties in a Hashtable.
       
    51      */
       
    52     public static Hashtable<Object, Object> initEnv(String testname,
       
    53             String[] args) {
       
    54         return initEnv(null, testname, args, false);
       
    55     }
       
    56 
       
    57     public static Hashtable<Object, Object> initEnv(ServerSocket socket,
       
    58             String testname, String[] args, boolean authInfo) {
       
    59 
       
    60         Hashtable<Object, Object> env = new Hashtable<>();
       
    61         String root = "o=IMC,c=US";
       
    62         String vendor = "Vendor1";
       
    63         String client = "Client1";
       
    64         String realm = "";
       
    65         Vector<String> refs = new Vector<>();
       
    66 
       
    67         // set defaults for some JNDI properties
       
    68         env.put(Context.INITIAL_CONTEXT_FACTORY,
       
    69                 "com.sun.jndi.ldap.LdapCtxFactory");
       
    70 
       
    71         if (authInfo) {
       
    72             env.put(Context.SECURITY_AUTHENTICATION, "simple");
       
    73             env.put(Context.SECURITY_PRINCIPAL, "cn=admin,o=IMC,c=US");
       
    74             env.put(Context.SECURITY_CREDENTIALS, "secret99");
       
    75         }
       
    76 
       
    77         env.put("root", root);
       
    78         env.put("vendor", vendor);
       
    79         env.put("client", client);
       
    80 
       
    81         boolean traceEnable = false;
       
    82         for (int i = 0; i < args.length; i++) {
       
    83             if (args[i].equals("-D") && (args.length > i + 1)) {
       
    84                 extractProperty(args[++i], env);
       
    85             } else if (args[i].startsWith("-D")) {
       
    86                 extractProperty(args[i].substring(2), env);
       
    87             } else if (args[i].equals("-referral") && (args.length > i + 1)) {
       
    88                 refs.addElement(args[++i]);
       
    89             } else if (args[i].equals("-trace")) {
       
    90                 traceEnable = true;
       
    91             }
       
    92         }
       
    93 
       
    94         env.put("disabled.realm", realm);
       
    95 
       
    96         if (refs.size() > 0) {
       
    97             env.put("referrals", refs);
       
    98         }
       
    99 
       
   100         if (traceEnable) {
       
   101             enableLDAPTrace(env, testname);
       
   102         } else {
       
   103             if (socket != null) {
       
   104                 env.put(TEST_LDAP_SERVER_THREAD,
       
   105                         startLDAPServer(socket, getCaptureFile(testname)));
       
   106                 env.put("java.naming.provider.url",
       
   107                         "ldap://localhost:" + socket.getLocalPort());
       
   108             } else {
       
   109                 // for tests which run against remote server or no server
       
   110                 // required
       
   111                 debug("Skip local LDAP Server creation "
       
   112                         + "since ServerSocket is null");
       
   113             }
       
   114         }
       
   115 
       
   116         return env;
       
   117     }
       
   118 
       
   119     /*
       
   120      * Clean-up the directory context.
       
   121      */
       
   122     public static void cleanup(DirContext ctx) {
       
   123         if (ctx != null) {
       
   124             try {
       
   125                 ctx.close();
       
   126             } catch (NamingException e) {
       
   127                 // ignore
       
   128             }
       
   129         }
       
   130     }
       
   131 
       
   132     /*
       
   133      * Clean-up the sub context.
       
   134      */
       
   135     public static void cleanupSubcontext(DirContext ctx, String name) {
       
   136         if (ctx != null) {
       
   137             try {
       
   138                 ctx.destroySubcontext(name);
       
   139             } catch (NamingException ne) {
       
   140                 // ignore
       
   141             }
       
   142         }
       
   143     }
       
   144 
       
   145     /*
       
   146      * Assemble a distinguished name from the base components and the
       
   147      * namespace root.
       
   148      *
       
   149      * The components are prefixed with 'dc=' if the root is a DC-style name.
       
   150      * Otherwise they are prefixed with 'ou='.
       
   151      */
       
   152     public static String buildDN(String[] bases, String root) {
       
   153 
       
   154         StringBuilder dn = new StringBuilder();
       
   155         String prefix;
       
   156 
       
   157         if (!root.contains("dc=")) {
       
   158             prefix = "ou=";
       
   159         } else {
       
   160             prefix = "dc=";
       
   161         }
       
   162 
       
   163         for (String base : bases) {
       
   164             dn.append(prefix).append(base).append(",");
       
   165         }
       
   166 
       
   167         return dn.append(root).toString();
       
   168     }
       
   169 
       
   170     /*
       
   171      * Scan the results to confirm that the expected name is present.
       
   172      */
       
   173     public static int checkResult(NamingEnumeration results, String name)
       
   174             throws NamingException {
       
   175 
       
   176         return checkResult(results, new String[] { name }, null);
       
   177     }
       
   178 
       
   179     /*
       
   180      * Scan the results to confirm that the expected names and attributes
       
   181      * are present.
       
   182      */
       
   183     public static int checkResult(NamingEnumeration results, String[] names,
       
   184             Attributes attrs) throws NamingException {
       
   185 
       
   186         int found = 0;
       
   187 
       
   188         while (results != null && results.hasMore()) {
       
   189 
       
   190             SearchResult entry = (SearchResult) results.next();
       
   191             String entryDN = entry.getName();
       
   192 
       
   193             debug(">>> received: " + entryDN);
       
   194 
       
   195             if (entry.isRelative()) {
       
   196                 entryDN = entryDN.toLowerCase(); // normalize
       
   197             } else {
       
   198                 LdapURL url = new LdapURL(entryDN); // extract DN
       
   199                 entryDN = url.getDN().toLowerCase(); // normalize
       
   200             }
       
   201 
       
   202             for (String name : names) {
       
   203                 if ((entryDN.contains(name.toLowerCase())) || (entryDN
       
   204                         .equalsIgnoreCase(name))) {
       
   205 
       
   206                     debug(">>> checked results: found '" + name + "'");
       
   207 
       
   208                     if (attrs == null || foundAttributes(entry, attrs)) {
       
   209                         found++;
       
   210                         break;
       
   211                     }
       
   212                 }
       
   213             }
       
   214         }
       
   215 
       
   216         debug(">>> checked results: found " + found
       
   217                 + " entries that meet the criteria.");
       
   218 
       
   219         return found;
       
   220     }
       
   221 
       
   222     /*
       
   223      * Confirm that the attributes are present in the entry.
       
   224      */
       
   225     public static boolean foundAttributes(SearchResult entry, Attributes attrs)
       
   226             throws NamingException {
       
   227 
       
   228         Attributes eattrs = entry.getAttributes();
       
   229         int found = 0;
       
   230 
       
   231         if ((eattrs == null) || (attrs == null)) {
       
   232             return false;
       
   233         }
       
   234 
       
   235         for (NamingEnumeration ne = attrs.getAll(); ne.hasMoreElements(); ) {
       
   236 
       
   237             Attribute attr = (Attribute) ne.next();
       
   238 
       
   239             if (equalsIgnoreCase(eattrs.get(attr.getID()), attr)) {
       
   240                 found++;
       
   241             } else {
       
   242                 debug(">>> foundAttributes: no match for " + attr.getID());
       
   243             }
       
   244         }
       
   245         debug(">>> foundAttributes: found " + found + " attributes");
       
   246         return (found == attrs.size());
       
   247     }
       
   248 
       
   249     public static Thread startLDAPServer(ServerSocket serverSocket,
       
   250             String fileName) {
       
   251         if (serverSocket == null) {
       
   252             throw new RuntimeException("Error: failed to create LDAPServer "
       
   253                     + "since ServerSocket is null");
       
   254         }
       
   255 
       
   256         if (!Files.exists(Paths.get(fileName))) {
       
   257             throw new RuntimeException(
       
   258                     "Error: failed to create LDAPServer, not found ldap "
       
   259                             + "cache file " + fileName);
       
   260         }
       
   261 
       
   262         Thread thread = new Thread(() -> {
       
   263             try {
       
   264                 new test.LDAPServer(serverSocket, fileName);
       
   265             } catch (Exception e) {
       
   266                 System.out.println("Warning: LDAP server running with issue");
       
   267                 e.printStackTrace();
       
   268             }
       
   269         });
       
   270 
       
   271         thread.start();
       
   272         return thread;
       
   273     }
       
   274 
       
   275     private static boolean equalsIgnoreCase(Attribute received,
       
   276             Attribute expected) {
       
   277 
       
   278         if (received == null || !received.getID()
       
   279                 .equalsIgnoreCase(expected.getID())) {
       
   280             return false;
       
   281         }
       
   282 
       
   283         try {
       
   284 
       
   285             Enumeration expectedVals = expected.getAll();
       
   286             Object obj;
       
   287             while (expectedVals.hasMoreElements()) {
       
   288                 obj = expectedVals.nextElement();
       
   289                 if (!received.contains(obj)) {
       
   290                     if (!(obj instanceof String)) {
       
   291                         return false;
       
   292                     }
       
   293                     if (!received.contains(((String) obj).toLowerCase())) {
       
   294                         return false;
       
   295                     }
       
   296                 }
       
   297             }
       
   298 
       
   299         } catch (NamingException e) {
       
   300             return false;
       
   301         }
       
   302 
       
   303         return true;
       
   304     }
       
   305 
       
   306     private static void extractProperty(String propString,
       
   307             Hashtable<Object, Object> env) {
       
   308         int index;
       
   309 
       
   310         if ((index = propString.indexOf('=')) > 0) {
       
   311             env.put(propString.substring(0, index),
       
   312                     propString.substring(index + 1));
       
   313         } else {
       
   314             throw new RuntimeException(
       
   315                     "Failed to extract test args property from " + propString);
       
   316         }
       
   317     }
       
   318 
       
   319     private static void enableLDAPTrace(Hashtable<Object, Object> env,
       
   320             String testname) {
       
   321         try {
       
   322             PrintStream outStream = new PrintStream(getCaptureFile(testname));
       
   323             env.put("com.sun.jndi.ldap.trace.ber", outStream);
       
   324         } catch (FileNotFoundException e) {
       
   325             throw new RuntimeException(
       
   326                     "Error: failed to enable ldap trace: " + e.getMessage(), e);
       
   327         }
       
   328     }
       
   329 
       
   330     private static String getCaptureFile(String testname) {
       
   331         return Paths.get(System.getProperty("test.src"))
       
   332                 .resolve(testname + ".ldap").toString();
       
   333     }
       
   334 
       
   335     public static void debug(Object object) {
       
   336         if (debug) {
       
   337             System.out.println(object);
       
   338         }
       
   339     }
       
   340 
       
   341     public static String findCertsHome(int depth) {
       
   342         Path path = Paths.get(System.getProperty("test.src", "."))
       
   343                 .toAbsolutePath();
       
   344         for (int i = depth; i >= 0; i--) {
       
   345             Path homePath = path.resolve("certs");
       
   346             if (Files.exists(homePath) && Files.isDirectory(homePath)) {
       
   347                 return homePath.toString();
       
   348             }
       
   349 
       
   350             path = path.getParent();
       
   351             if (path == null) {
       
   352                 break;
       
   353             }
       
   354         }
       
   355 
       
   356         return System.getProperty("test.src", ".");
       
   357     }
       
   358 }