Path: blob/master/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java
41155 views
/*1* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import com.sun.jndi.ldap.LdapURL;2425import javax.naming.Context;26import javax.naming.NamingEnumeration;27import javax.naming.NamingException;28import javax.naming.directory.Attribute;29import javax.naming.directory.Attributes;30import javax.naming.directory.DirContext;31import javax.naming.directory.SearchResult;32import java.io.FileNotFoundException;33import java.io.PrintStream;34import java.net.ServerSocket;35import java.nio.file.Files;36import java.nio.file.Path;37import java.nio.file.Paths;38import java.util.Enumeration;39import java.util.Hashtable;40import java.util.Vector;4142public class LDAPTestUtils {43public static final String TEST_LDAP_SERVER_THREAD = "test.ldap.server.thread";44public static final int CERTS_LOOKUP_MAX_DEPTH = 4;4546protected static boolean debug = true;4748/*49* Process command line arguments and return properties in a Hashtable.50*/51public static Hashtable<Object, Object> initEnv(String testname,52String[] args) {53return initEnv(null, testname, args, false);54}5556public static Hashtable<Object, Object> initEnv(ServerSocket socket,57String testname, String[] args, boolean authInfo) {58return initEnv(socket, null, testname, args, authInfo);59}6061public static Hashtable<Object, Object> initEnv(ServerSocket socket, String providerUrl,62String testname, String[] args, boolean authInfo) {6364Hashtable<Object, Object> env = new Hashtable<>();65String root = "o=IMC,c=US";66String vendor = "Vendor1";67String client = "Client1";68String realm = "";69Vector<String> refs = new Vector<>();7071// set defaults for some JNDI properties72env.put(Context.INITIAL_CONTEXT_FACTORY,73"com.sun.jndi.ldap.LdapCtxFactory");7475if (authInfo) {76env.put(Context.SECURITY_AUTHENTICATION, "simple");77env.put(Context.SECURITY_PRINCIPAL, "cn=admin,o=IMC,c=US");78env.put(Context.SECURITY_CREDENTIALS, "secret99");79}8081env.put("root", root);82env.put("vendor", vendor);83env.put("client", client);8485boolean traceEnable = false;86for (int i = 0; i < args.length; i++) {87if (args[i].equals("-D") && (args.length > i + 1)) {88extractProperty(args[++i], env);89} else if (args[i].startsWith("-D")) {90extractProperty(args[i].substring(2), env);91} else if (args[i].equals("-referral") && (args.length > i + 1)) {92refs.addElement(args[++i]);93} else if (args[i].equals("-trace")) {94traceEnable = true;95}96}9798env.put("disabled.realm", realm);99100if (refs.size() > 0) {101env.put("referrals", refs);102}103104if (traceEnable) {105enableLDAPTrace(env, testname);106} else {107if (socket != null) {108env.put(TEST_LDAP_SERVER_THREAD,109startLDAPServer(socket, getCaptureFile(testname)));110String url = providerUrl != null ? providerUrl :111"ldap://localhost:" + socket.getLocalPort();112env.put("java.naming.provider.url", url);113} else {114// for tests which run against remote server or no server115// required116debug("Skip local LDAP Server creation "117+ "since ServerSocket is null");118}119}120121return env;122}123124/*125* Clean-up the directory context.126*/127public static void cleanup(DirContext ctx) {128if (ctx != null) {129try {130ctx.close();131} catch (NamingException e) {132// ignore133}134}135}136137/*138* Clean-up the sub context.139*/140public static void cleanupSubcontext(DirContext ctx, String name) {141if (ctx != null) {142try {143ctx.destroySubcontext(name);144} catch (NamingException ne) {145// ignore146}147}148}149150/*151* Assemble a distinguished name from the base components and the152* namespace root.153*154* The components are prefixed with 'dc=' if the root is a DC-style name.155* Otherwise they are prefixed with 'ou='.156*/157public static String buildDN(String[] bases, String root) {158159StringBuilder dn = new StringBuilder();160String prefix;161162if (!root.contains("dc=")) {163prefix = "ou=";164} else {165prefix = "dc=";166}167168for (String base : bases) {169dn.append(prefix).append(base).append(",");170}171172return dn.append(root).toString();173}174175/*176* Scan the results to confirm that the expected name is present.177*/178public static int checkResult(NamingEnumeration results, String name)179throws NamingException {180181return checkResult(results, new String[] { name }, null);182}183184/*185* Scan the results to confirm that the expected names and attributes186* are present.187*/188public static int checkResult(NamingEnumeration results, String[] names,189Attributes attrs) throws NamingException {190191int found = 0;192193while (results != null && results.hasMore()) {194195SearchResult entry = (SearchResult) results.next();196String entryDN = entry.getName();197198debug(">>> received: " + entryDN);199200if (entry.isRelative()) {201entryDN = entryDN.toLowerCase(); // normalize202} else {203LdapURL url = new LdapURL(entryDN); // extract DN204entryDN = url.getDN().toLowerCase(); // normalize205}206207for (String name : names) {208if ((entryDN.contains(name.toLowerCase())) || (entryDN209.equalsIgnoreCase(name))) {210211debug(">>> checked results: found '" + name + "'");212213if (attrs == null || foundAttributes(entry, attrs)) {214found++;215break;216}217}218}219}220221debug(">>> checked results: found " + found222+ " entries that meet the criteria.");223224return found;225}226227/*228* Confirm that the attributes are present in the entry.229*/230public static boolean foundAttributes(SearchResult entry, Attributes attrs)231throws NamingException {232233Attributes eattrs = entry.getAttributes();234int found = 0;235236if ((eattrs == null) || (attrs == null)) {237return false;238}239240for (NamingEnumeration ne = attrs.getAll(); ne.hasMoreElements(); ) {241242Attribute attr = (Attribute) ne.next();243244if (equalsIgnoreCase(eattrs.get(attr.getID()), attr)) {245found++;246} else {247debug(">>> foundAttributes: no match for " + attr.getID());248}249}250debug(">>> foundAttributes: found " + found + " attributes");251return (found == attrs.size());252}253254public static Thread startLDAPServer(ServerSocket serverSocket,255String fileName) {256if (serverSocket == null) {257throw new RuntimeException("Error: failed to create LDAPServer "258+ "since ServerSocket is null");259}260261if (!Files.exists(Paths.get(fileName))) {262throw new RuntimeException(263"Error: failed to create LDAPServer, not found ldap "264+ "cache file " + fileName);265}266267Thread thread = new Thread(() -> {268try {269new test.LDAPServer(serverSocket, fileName);270} catch (Exception e) {271System.out.println("Warning: LDAP server running with issue");272e.printStackTrace();273}274});275276thread.start();277return thread;278}279280private static boolean equalsIgnoreCase(Attribute received,281Attribute expected) {282283if (received == null || !received.getID()284.equalsIgnoreCase(expected.getID())) {285return false;286}287288try {289290Enumeration expectedVals = expected.getAll();291Object obj;292while (expectedVals.hasMoreElements()) {293obj = expectedVals.nextElement();294if (!received.contains(obj)) {295if (!(obj instanceof String)) {296return false;297}298if (!received.contains(((String) obj).toLowerCase())) {299return false;300}301}302}303304} catch (NamingException e) {305return false;306}307308return true;309}310311private static void extractProperty(String propString,312Hashtable<Object, Object> env) {313int index;314315if ((index = propString.indexOf('=')) > 0) {316env.put(propString.substring(0, index),317propString.substring(index + 1));318} else {319throw new RuntimeException(320"Failed to extract test args property from " + propString);321}322}323324private static void enableLDAPTrace(Hashtable<Object, Object> env,325String testname) {326try {327PrintStream outStream = new PrintStream(getCaptureFile(testname));328env.put("com.sun.jndi.ldap.trace.ber", outStream);329} catch (FileNotFoundException e) {330throw new RuntimeException(331"Error: failed to enable ldap trace: " + e.getMessage(), e);332}333}334335private static String getCaptureFile(String testname) {336return Paths.get(System.getProperty("test.src"))337.resolve(testname + ".ldap").toString();338}339340public static void debug(Object object) {341if (debug) {342System.out.println(object);343}344}345346public static String findCertsHome(int depth) {347Path path = Paths.get(System.getProperty("test.src", "."))348.toAbsolutePath();349for (int i = depth; i >= 0; i--) {350Path homePath = path.resolve("certs");351if (Files.exists(homePath) && Files.isDirectory(homePath)) {352return homePath.toString();353}354355path = path.getParent();356if (path == null) {357break;358}359}360361return System.getProperty("test.src", ".");362}363}364365366