Beispiel #1
0
  /**
   * Validate User
   *
   * @param ldapURL provider url - e.g. ldap://dc.compiere.org
   * @param domain domain name = e.g. compiere.org
   * @param userName user name - e.g. jjanke
   * @param password password
   * @return true if validated with ldap
   */
  public static boolean validate(String ldapURL, String domain, String userName, String password) {
    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    //	ldap://dc.compiere.org
    env.put(Context.PROVIDER_URL, ldapURL);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    //	[email protected]
    StringBuffer principal = new StringBuffer(userName).append("@").append(domain);
    env.put(Context.SECURITY_PRINCIPAL, principal.toString());
    env.put(Context.SECURITY_CREDENTIALS, password);
    //
    try {
      // Create the initial context
      InitialLdapContext ctx = new InitialLdapContext(env, null);
      //	DirContext ctx = new InitialDirContext(env);

      //	Test - Get the attributes
      Attributes answer = ctx.getAttributes("");

      // Print the answer
      if (false) dump(answer);
    } catch (AuthenticationException e) {
      log.info("Error: " + principal + " - " + e.getLocalizedMessage());
      return false;
    } catch (Exception e) {
      log.log(Level.SEVERE, ldapURL + " - " + principal, e);
      return false;
    }
    log.info("OK: " + principal);
    return true;
  } //	validate
 /**
  * Seeds the bound instance's local ads-truststore with a set of instance key-pair public key
  * certificates. The result is the instance will trust any instance posessing the private key
  * corresponding to one of the public-key certificates. This trust is necessary at least to
  * initialize replication, which uses the trusted certificate entries in the ads-truststore for
  * server authentication.
  *
  * @param ctx The bound instance.
  * @param keyEntryMap The set of valid (i.e., not tagged as compromised) instance key-pair
  *     public-key certificate entries in ADS represented as a map from keyID to public-key
  *     certificate (binary).
  * @throws NamingException in case an error occurs while updating the instance's ads-truststore
  *     via LDAP.
  */
 public static void seedAdsTrustStore(InitialLdapContext ctx, Map<String, byte[]> keyEntryMap)
     throws NamingException {
   /* TODO: this DN is declared in some core constants file. Create a
   constants file for the installer and import it into the core. */
   final Attribute oc = new BasicAttribute("objectclass");
   oc.add("top");
   oc.add("ds-cfg-instance-key");
   for (Map.Entry<String, byte[]> keyEntry : keyEntryMap.entrySet()) {
     final BasicAttributes keyAttrs = new BasicAttributes();
     keyAttrs.put(oc);
     final Attribute rdnAttr =
         new BasicAttribute(
             ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyEntry.getKey());
     keyAttrs.put(rdnAttr);
     keyAttrs.put(
         new BasicAttribute(
             ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName()
                 + ";binary",
             keyEntry.getValue()));
     final LdapName keyDn =
         new LdapName(
             (new StringBuilder(rdnAttr.getID()))
                 .append("=")
                 .append(Rdn.escapeValue(rdnAttr.get()))
                 .append(",")
                 .append(TRUSTSTORE_DN)
                 .toString());
     try {
       ctx.createSubcontext(keyDn, keyAttrs).close();
     } catch (NameAlreadyBoundException x) {
       ctx.destroySubcontext(keyDn);
       ctx.createSubcontext(keyDn, keyAttrs).close();
     }
   }
 }
  /* Return all groups for principal == null or all groups for which principal
   * is a member
   *
   */
  private Collection<BwGroup> getGroups(
      final DirConfigProperties dirProps, final BwPrincipal principal) throws CalFacadeException {
    LdapConfigProperties props = (LdapConfigProperties) dirProps;
    InitialLdapContext ctx = null;
    String member = null;

    if (principal != null) {
      if (principal.getKind() == WhoDefs.whoTypeUser) {
        member = getUserEntryValue(props, principal);
      } else if (principal.getKind() == WhoDefs.whoTypeGroup) {
        member = getGroupEntryValue(props, principal);
      }
    }

    try {
      ctx = createLdapInitContext(props);

      BasicAttributes matchAttrs = new BasicAttributes(true);

      if (member != null) {
        matchAttrs.put(props.getGroupMemberAttr(), member);
      }

      String[] idAttr = {props.getGroupIdAttr()};

      ArrayList<BwGroup> groups = new ArrayList<BwGroup>();
      NamingEnumeration response = ctx.search(props.getGroupContextDn(), matchAttrs, idAttr);
      while (response.hasMore()) {
        SearchResult sr = (SearchResult) response.next();
        Attributes attrs = sr.getAttributes();

        Attribute nmAttr = attrs.get(props.getGroupIdAttr());
        if (nmAttr.size() != 1) {
          throw new CalFacadeException("org.bedework.ldap.groups.multiple.result");
        }

        BwGroup group = new BwGroup();
        group.setAccount(nmAttr.get(0).toString());
        group.setPrincipalRef(makePrincipalUri(group.getAccount(), WhoDefs.whoTypeGroup));

        groups.add(group);
      }

      return groups;
    } catch (Throwable t) {
      if (debug) {
        error(t);
      }
      throw new CalFacadeException(t);
    } finally {
      // Close the context to release the connection
      if (ctx != null) {
        closeContext(ctx);
      }
    }
  }
  public boolean existsUser(String userId) {

    InitialLdapContext ctx = null;
    boolean exists = false;
    try {
      ctx = buildInitialLdapContext();

      String userContext = this.config.getProperty(USER_CTX);
      String userFilter = this.config.getProperty(USER_FILTER);
      String userAttrId = this.config.getProperty(USER_ATTR_ID, "uid");

      userFilter = userFilter.replaceAll("\\{0\\}", userId);

      if (logger.isDebugEnabled()) {
        logger.debug(
            "Seaching for user existence with filter " + userFilter + " on context " + userContext);
      }

      SearchControls constraints = new SearchControls();

      NamingEnumeration<SearchResult> result = ctx.search(userContext, userFilter, constraints);
      if (result.hasMore()) {

        SearchResult sr = result.next();
        Attribute ldapUserId = sr.getAttributes().get(userAttrId);

        if (ldapUserId.contains(userId)) {
          exists = true;
        }
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Entry in LDAP found and result of matching with given user id is " + exists);
        }
      }
      result.close();

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ctx != null) {
        try {
          ctx.close();
        } catch (NamingException e) {
          e.printStackTrace();
        }
      }
    }

    return exists;
  }
Beispiel #5
0
  public Iterator<OrganizationalEntity> getMembersForGroup(Group group) {
    InitialLdapContext ctx = null;
    List<OrganizationalEntity> memebers = new ArrayList<OrganizationalEntity>();
    try {
      ctx = buildInitialLdapContext();

      String roleContext = this.config.getProperty(ROLE_CTX);
      String roleFilter =
          this.config.getProperty(ROLE_MEMBERS_FILTER, this.config.getProperty(ROLE_FILTER));
      String roleAttrId = this.config.getProperty(MEMBER_ATTR_ID, "member");

      String entityId = group.getId();
      if (Boolean.parseBoolean(this.config.getProperty(IS_ENTITY_ID_DN, "false"))) {
        entityId = extractUserId(entityId, group);
      }

      roleFilter = roleFilter.replaceAll("\\{0\\}", entityId);

      SearchControls constraints = new SearchControls();
      String searchScope = this.config.getProperty(SEARCH_SCOPE);
      if (searchScope != null) {
        constraints.setSearchScope(parseSearchScope(searchScope));
      }

      NamingEnumeration<SearchResult> result = ctx.search(roleContext, roleFilter, constraints);
      while (result.hasMore()) {
        SearchResult sr = result.next();
        Attribute member = sr.getAttributes().get(roleAttrId);
        for (int i = 0; i < member.size(); i++) {
          User user = TaskModelProvider.getFactory().newUser();
          ((InternalOrganizationalEntity) user).setId(member.get(i).toString());
          memebers.add(user);
        }
      }
      result.close();

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ctx != null) {
        try {
          ctx.close();
        } catch (NamingException e) {
          e.printStackTrace();
        }
      }
    }
    return memebers.iterator();
  }
  private static void updateAdminConnectorConfiguration(
      ServerDescriptor desc, InitialLdapContext ctx, TopologyCacheFilter cacheFilter)
      throws NamingException {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(new String[] {"ds-cfg-listen-port", "objectclass"});
    String filter = "(objectclass=ds-cfg-administration-connector)";

    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> listeners = ctx.search(jndiName, filter, ctls);

    try {
      Integer adminConnectorPort = null;

      // we should have a single administration connector
      while (listeners.hasMore()) {
        SearchResult sr = listeners.next();
        String port = getFirstValue(sr, "ds-cfg-listen-port");
        adminConnectorPort = new Integer(port);
      }

      // Even if we have a single port, use an array to be consistent with
      // other protocols.
      ArrayList<Integer> adminPorts = new ArrayList<Integer>();
      ArrayList<Boolean> adminEnabled = new ArrayList<Boolean>();
      if (adminConnectorPort != null) {
        adminPorts.add(adminConnectorPort);
        adminEnabled.add(Boolean.TRUE);
      }
      desc.serverProperties.put(ServerProperty.ADMIN_PORT, adminPorts);
      desc.serverProperties.put(ServerProperty.ADMIN_ENABLED, adminEnabled);
    } finally {
      listeners.close();
    }
  }
  /**
   * Retrieve the input attributes from the Active Directory for the given search query
   *
   * <p>Method getAttributes.
   *
   * @param searchBase String
   * @return List<User>
   * @throws NamingException
   */
  private final List<User> getAttributes(String searchBase) throws NamingException {
    LOGGER.info(">> getAttributes()");

    NamingEnumeration<SearchResult> results =
        localInitialLdapContext.search(searchBase, searchFilter, searchctls);

    List<User> users = new ArrayList<User>();
    User user = null;

    while (results.hasMoreElements()) {
      user = new User();
      SearchResult searchResult = results.next();
      Attributes attrs = searchResult.getAttributes();

      if (attrs != null && attrs.size() != 0) {
        Attribute attribute = null;

        String[] retrieveAttributes = parameters.getRetrieveAttributes();
        String[] attributesValues = new String[retrieveAttributes.length];
        for (int i = 0; i < retrieveAttributes.length; i++) {
          attribute = attrs.get(retrieveAttributes[i]);
          if (attribute != null && attribute.get() != null) {
            if (!isNullOrEmpty(attribute.get().toString())) {
              attributesValues[i] = attribute.get().toString();
            }
          }
        }
        user.setAttributeValues(attributesValues);
      }
      users.add(user);
    }

    LOGGER.info("<< getAttributes()");
    return users;
  }
 /**
  * Method used to know if we are connected as administrator in a server with a given
  * InitialLdapContext.
  *
  * @param ctx the context.
  * @return <CODE>true</CODE> if we are connected and read the configuration and <CODE>false</CODE>
  *     otherwise.
  */
 public static boolean connectedAsAdministrativeUser(InitialLdapContext ctx) {
   boolean connectedAsAdministrativeUser = false;
   try {
     /*
      * Search for the config to check that it is the directory manager.
      */
     SearchControls searchControls = new SearchControls();
     searchControls.setSearchScope(SearchControls.OBJECT_SCOPE);
     searchControls.setReturningAttributes(new String[] {SchemaConstants.NO_ATTRIBUTES});
     NamingEnumeration<SearchResult> sr = ctx.search("cn=config", "objectclass=*", searchControls);
     try {
       while (sr.hasMore()) {
         sr.next();
       }
     } finally {
       try {
         sr.close();
       } catch (Exception ex) {
         LOG.log(Level.WARNING, "Unexpected error closing enumeration on cn=Config entry", ex);
       }
     }
     connectedAsAdministrativeUser = true;
   } catch (NamingException ne) {
     // Nothing to do.
   } catch (Throwable t) {
     throw new IllegalStateException("Unexpected throwable.", t);
   }
   return connectedAsAdministrativeUser;
 }
Beispiel #9
0
  public boolean hasEmail(Group group) {
    InitialLdapContext ctx = null;
    boolean exists = false;
    try {
      ctx = buildInitialLdapContext();

      String roleContext = this.config.getProperty(ROLE_CTX);
      String roleFilter = this.config.getProperty(ROLE_FILTER);
      String roleAttrId = this.config.getProperty(EMAIL_ATTR_ID, "mail");

      String entityId = group.getId();
      if (Boolean.parseBoolean(this.config.getProperty(IS_ENTITY_ID_DN, "false"))) {
        entityId = extractUserId(entityId, group);
      }

      roleFilter = roleFilter.replaceAll("\\{0\\}", entityId);

      SearchControls constraints = new SearchControls();
      String searchScope = this.config.getProperty(SEARCH_SCOPE);
      if (searchScope != null) {
        constraints.setSearchScope(parseSearchScope(searchScope));
      }

      NamingEnumeration<SearchResult> result = ctx.search(roleContext, roleFilter, constraints);
      if (result.hasMore()) {
        SearchResult sr = result.next();
        Attribute ldapGroupEmail = sr.getAttributes().get(roleAttrId);

        if (ldapGroupEmail != null && ldapGroupEmail.get() != null) {
          exists = true;
        }
      }
      result.close();

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ctx != null) {
        try {
          ctx.close();
        } catch (NamingException e) {
          e.printStackTrace();
        }
      }
    }
    return exists;
  }
 protected void safeClose(InitialLdapContext ic) {
   if (ic != null) {
     try {
       ic.close();
     } catch (NamingException e) {
     }
   }
 }
 private void closeContext(final InitialLdapContext ctx) {
   if (ctx != null) {
     try {
       ctx.close();
     } catch (Throwable t) {
     }
   }
 }
  public boolean existsGroup(String groupId) {

    InitialLdapContext ctx = null;
    boolean exists = false;
    try {
      ctx = buildInitialLdapContext();

      String roleContext = this.config.getProperty(ROLE_CTX);
      String roleFilter = this.config.getProperty(ROLE_FILTER);
      String roleAttrId = this.config.getProperty(ROLE_ATTR_ID, "cn");

      roleFilter = roleFilter.replaceAll("\\{0\\}", groupId);

      SearchControls constraints = new SearchControls();
      String searchScope = this.config.getProperty(SEARCH_SCOPE);
      if (searchScope != null) {
        constraints.setSearchScope(parseSearchScope(searchScope));
      }

      NamingEnumeration<SearchResult> result = ctx.search(roleContext, roleFilter, constraints);
      if (result.hasMore()) {
        SearchResult sr = result.next();
        Attribute ldapUserId = sr.getAttributes().get(roleAttrId);

        if (ldapUserId.contains(groupId)) {
          exists = true;
        }
      }
      result.close();

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ctx != null) {
        try {
          ctx.close();
        } catch (NamingException e) {
          e.printStackTrace();
        }
      }
    }

    return exists;
  }
 /**
  * Returns the password used in the provided InitialLdapContext.
  *
  * @param ctx the context to analyze.
  * @return the password used in the provided InitialLdapContext.
  */
 public static String getBindPassword(InitialLdapContext ctx) {
   String bindPwd = null;
   try {
     bindPwd = (String) ctx.getEnvironment().get(Context.SECURITY_CREDENTIALS);
   } catch (NamingException ne) {
     // This is really strange.  Seems like a bug somewhere.
     LOG.log(Level.WARNING, "Naming exception getting environment of " + ctx, ne);
   }
   return bindPwd;
 }
 /**
  * Returns the LDAP URL used in the provided InitialLdapContext.
  *
  * @param ctx the context to analyze.
  * @return the LDAP URL used in the provided InitialLdapContext.
  */
 public static String getLdapUrl(InitialLdapContext ctx) {
   String s = null;
   try {
     s = (String) ctx.getEnvironment().get(Context.PROVIDER_URL);
   } catch (NamingException ne) {
     // This is really strange.  Seems like a bug somewhere.
     LOG.log(Level.WARNING, "Naming exception getting environment of " + ctx, ne);
   }
   return s;
 }
 @Override
 public LdapContext getSystemLdapContext() throws NamingException {
   try {
     InitialLdapContext ictx = new InitialLdapContext();
     LdapContext ctx = (LdapContext) ictx.lookup(getLdapJndi());
     /* Glassfish does not pass through these properties, even though it is aware of them?
      * Without com.sun.jndi.ldap.LdapCtxFactory, authentication is NOT carried out
      */
     ctx.addToEnvironment(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
     ctx.addToEnvironment("java.naming.ldap.attributes.binary", "userPKCS12");
     if (logger.isDebugEnabled()) {
       String providerURL = (String) ctx.getEnvironment().get(Context.PROVIDER_URL);
       logger.debug("LDAP providerURL=" + providerURL);
     }
     return ctx;
   } catch (Exception ex) {
     throw new RuntimeException("Failed to lookup " + getLdapJndi(), ex);
   }
 }
 /**
  * Tells whether we are using StartTLS in the provided InitialLdapContext.
  *
  * @param ctx the context to analyze.
  * @return <CODE>true</CODE> if we are using StartTLS and <CODE>false</CODE> otherwise.
  */
 public static boolean isStartTLS(InitialLdapContext ctx) {
   boolean isStartTLS = false;
   try {
     isStartTLS = "true".equalsIgnoreCase((String) ctx.getEnvironment().get(STARTTLS_PROPERTY));
   } catch (NamingException ne) {
     // This is really strange.  Seems like a bug somewhere.
     LOG.log(Level.WARNING, "Naming exception getting environment of " + ctx, ne);
   }
   return isStartTLS;
 }
  /* Search for a group to ensure it exists
   *
   */
  private BwGroup findGroup(final DirConfigProperties dirProps, final String groupName)
      throws CalFacadeException {
    LdapConfigProperties props = (LdapConfigProperties) dirProps;
    InitialLdapContext ctx = null;

    try {
      ctx = createLdapInitContext(props);

      BasicAttributes matchAttrs = new BasicAttributes(true);

      matchAttrs.put(props.getGroupIdAttr(), groupName);

      String[] idAttr = {props.getGroupIdAttr()};

      BwGroup group = null;
      NamingEnumeration response = ctx.search(props.getGroupContextDn(), matchAttrs, idAttr);
      while (response.hasMore()) {
        //        SearchResult sr = (SearchResult)response.next();
        //        Attributes attrs = sr.getAttributes();

        if (group != null) {
          throw new CalFacadeException("org.bedework.ldap.groups.multiple.result");
        }

        group = new BwGroup();
        group.setAccount(groupName);
        group.setPrincipalRef(makePrincipalUri(groupName, WhoDefs.whoTypeGroup));
      }

      return group;
    } catch (Throwable t) {
      if (debug) {
        error(t);
      }
      throw new CalFacadeException(t);
    } finally {
      // Close the context to release the connection
      if (ctx != null) {
        closeContext(ctx);
      }
    }
  }
 public static SearchResult searchUnique(String searchFilter, InitialLdapContext ctx)
     throws IllegalStateException, NamingException {
   ctx.setRequestControls(null);
   SearchControls searchControls = new SearchControls();
   searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
   searchControls.setTimeLimit(1000);
   NamingEnumeration<?> namingEnum =
       ctx.search(MessagingServletConfig.ldapBaseDn, searchFilter, searchControls);
   if (namingEnum.hasMore()) {
     SearchResult result = (SearchResult) namingEnum.next();
     if (namingEnum.hasMore()) {
       throw new LimitExceededException(
           "search with filter " + searchFilter + " returned more than 1 result");
     }
     namingEnum.close();
     return result;
   } else {
     throw new NameNotFoundException("search with filter " + searchFilter + " returned no result");
   }
 }
  private static void updateLdapConfiguration(
      ServerDescriptor desc, InitialLdapContext ctx, TopologyCacheFilter cacheFilter)
      throws NamingException {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
          "ds-cfg-enabled",
          "ds-cfg-listen-address",
          "ds-cfg-listen-port",
          "ds-cfg-use-ssl",
          "ds-cfg-allow-start-tls",
          "objectclass"
        });
    String filter = "(objectclass=ds-cfg-ldap-connection-handler)";

    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> listeners = ctx.search(jndiName, filter, ctls);

    try {
      ArrayList<Integer> ldapPorts = new ArrayList<Integer>();
      ArrayList<Integer> ldapsPorts = new ArrayList<Integer>();
      ArrayList<Boolean> ldapEnabled = new ArrayList<Boolean>();
      ArrayList<Boolean> ldapsEnabled = new ArrayList<Boolean>();
      ArrayList<Boolean> startTLSEnabled = new ArrayList<Boolean>();

      desc.serverProperties.put(ServerProperty.LDAP_PORT, ldapPorts);
      desc.serverProperties.put(ServerProperty.LDAPS_PORT, ldapsPorts);
      desc.serverProperties.put(ServerProperty.LDAP_ENABLED, ldapEnabled);
      desc.serverProperties.put(ServerProperty.LDAPS_ENABLED, ldapsEnabled);
      desc.serverProperties.put(ServerProperty.STARTTLS_ENABLED, startTLSEnabled);

      while (listeners.hasMore()) {
        SearchResult sr = listeners.next();

        String port = getFirstValue(sr, "ds-cfg-listen-port");

        boolean isSecure = "true".equalsIgnoreCase(getFirstValue(sr, "ds-cfg-use-ssl"));

        boolean enabled = "true".equalsIgnoreCase(getFirstValue(sr, "ds-cfg-enabled"));
        if (isSecure) {
          ldapsPorts.add(new Integer(port));
          ldapsEnabled.add(enabled);
        } else {
          ldapPorts.add(new Integer(port));
          ldapEnabled.add(enabled);
          enabled = "true".equalsIgnoreCase(getFirstValue(sr, "ds-cfg-allow-start-tls"));
          startTLSEnabled.add(enabled);
        }
      }
    } finally {
      listeners.close();
    }
  }
Beispiel #20
0
  protected String searchLdap(
      String context, String filter, String attrId, OrganizationalEntity entity) {
    InitialLdapContext ctx = null;
    String result = null;
    try {
      ctx = buildInitialLdapContext();
      String entityId = entity.getId();
      if (Boolean.parseBoolean(this.config.getProperty(IS_ENTITY_ID_DN, "false"))) {
        entityId = extractUserId(entityId, entity);
      }
      filter = filter.replaceAll("\\{0\\}", entityId);

      SearchControls constraints = new SearchControls();
      String searchScope = this.config.getProperty(SEARCH_SCOPE);
      if (searchScope != null) {
        constraints.setSearchScope(parseSearchScope(searchScope));
      }

      NamingEnumeration<SearchResult> ldapResult = ctx.search(context, filter, constraints);
      if (ldapResult.hasMore()) {
        SearchResult sr = ldapResult.next();
        Attribute entry = sr.getAttributes().get(attrId);
        if (entry != null) {
          result = (String) entry.get();
        }
      }
      ldapResult.close();

    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (ctx != null) {
        try {
          ctx.close();
        } catch (NamingException e) {
          e.printStackTrace();
        }
      }
    }
    return result;
  }
 /**
  * Updates the instance key public-key certificate value of this context from the local truststore
  * of the instance bound by this context. Any current value of the certificate is overwritten. The
  * intent of this method is to retrieve the instance-key public-key certificate when this context
  * is bound to an instance, and cache it for later use in registering the instance into ADS.
  *
  * @param desc The map to update with the instance key-pair public-key certificate.
  * @param ctx The bound server instance.
  * @throws NamingException if unable to retrieve certificate from bound instance.
  */
 private static void updatePublicKeyCertificate(
     ServerDescriptor desc, InitialLdapContext ctx, TopologyCacheFilter filter)
     throws NamingException {
   /* TODO: this DN is declared in some core constants file. Create a constants
   file for the installer and import it into the core. */
   final String dnStr = "ds-cfg-key-id=ads-certificate,cn=ads-truststore";
   final LdapName dn = new LdapName(dnStr);
   for (int i = 0; i < 2; ++i) {
     /* If the entry does not exist in the instance's truststore backend, add
     it (which induces the CryptoManager to create the public-key
     certificate attribute), then repeat the search. */
     try {
       final SearchControls searchControls = new SearchControls();
       searchControls.setSearchScope(SearchControls.OBJECT_SCOPE);
       final String attrIDs[] = {"ds-cfg-public-key-certificate;binary"};
       searchControls.setReturningAttributes(attrIDs);
       final SearchResult certEntry =
           ctx.search(dn, "(objectclass=ds-cfg-instance-key)", searchControls).next();
       final Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]);
       if (null != certAttr) {
         /* attribute ds-cfg-public-key-certificate is a MUST in the schema */
         desc.serverProperties.put(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE, certAttr.get());
       }
       break;
     } catch (NameNotFoundException x) {
       if (0 == i) {
         /* Poke CryptoManager to initialize truststore. Note the special
         attribute in the request. */
         final Attributes attrs = new BasicAttributes();
         final Attribute oc = new BasicAttribute("objectclass");
         oc.add("top");
         oc.add("ds-cfg-self-signed-cert-request");
         attrs.put(oc);
         ctx.createSubcontext(dn, attrs).close();
       } else {
         throw x;
       }
     }
   }
 }
  @Override
  protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
    String authorizationHeader = getAuthzHeader(request);
    if (authorizationHeader == null || authorizationHeader.length() == 0) {
      // Create an empty authentication token since there is no
      // Authorization header.
      return createToken("", "", request, response);
    }

    if (log.isDebugEnabled()) {
      log.debug("Attempting to execute login with headers [" + authorizationHeader + "]");
    }

    String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request);
    if (prinCred == null || prinCred.length < 2) {
      // Create an authentication token with an empty password,
      // since one hasn't been provided in the request.
      String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0];
      return createToken(username, "", request, response);
    }

    String username = prinCred[0];
    String password = prinCred[1];
    String sf = SF.replace("{0}", username);
    try {
      AuthenticationToken at =
          new UsernamePasswordToken(MessagingServletConfig.ldapUser, MessagingServletConfig.ldapPw);
      InitialLdapContext ctx =
          (InitialLdapContext) jlc.getLdapContext(at.getPrincipal(), at.getCredentials());
      SearchResult result = searchUnique(sf, ctx);
      Attributes attrs = result.getAttributes();
      username =
          "******" + attrs.get("cn").get(0) + ",ou=gateways," + MessagingServletConfig.ldapBaseDn;
      ctx.close();
    } catch (IllegalStateException | NamingException e) {
      e.printStackTrace();
      log.warn(username + "not found in directory");
    }
    return createToken(username, password, request, response);
  }
  /**
   * Clones the provided InitialLdapContext and returns a connection using the same parameters.
   *
   * @param ctx the connection to be cloned.
   * @param timeout the timeout to establish the connection in milliseconds. Use {@code 0} to
   *     express no timeout.
   * @param trustManager the trust manager to be used to connect.
   * @param keyManager the key manager to be used to connect.
   * @return the new InitialLdapContext connected to the server.
   * @throws NamingException if there was an error creating the new connection.
   */
  public static InitialLdapContext cloneInitialLdapContext(
      final InitialLdapContext ctx, int timeout, TrustManager trustManager, KeyManager keyManager)
      throws NamingException {
    Hashtable<?, ?> env = ctx.getEnvironment();
    Control[] ctls = ctx.getConnectControls();
    Control[] newCtls = null;
    if (ctls != null) {
      newCtls = new Control[ctls.length];
      System.arraycopy(ctls, 0, newCtls, 0, ctls.length);
    }
    /* Contains the DirContext and the Exception if any */
    final Object[] pair = new Object[] {null, null};
    final Hashtable<?, ?> fEnv = env;
    final TrustManager fTrustManager = trustManager;
    final KeyManager fKeyManager = keyManager;
    final Control[] fNewCtls = newCtls;

    Thread t =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                try {
                  if (isSSL(ctx) || isStartTLS(ctx)) {
                    TrustedSocketFactory.setCurrentThreadTrustManager(fTrustManager, fKeyManager);
                  }
                  pair[0] = new InitialLdapContext(fEnv, fNewCtls);

                } catch (NamingException ne) {
                  pair[1] = ne;

                } catch (RuntimeException re) {
                  pair[1] = re;
                }
              }
            });
    return getInitialLdapContext(t, pair, timeout);
  }
 /**
  * Cleans up the contents of the ads truststore.
  *
  * @param ctx the bound instance.
  * @throws NamingException in case an error occurs while updating the instance's ads-truststore
  *     via LDAP.
  */
 public static void cleanAdsTrustStore(InitialLdapContext ctx) throws NamingException {
   try {
     SearchControls sc = new SearchControls();
     sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
     sc.setReturningAttributes(new String[] {SchemaConstants.NO_ATTRIBUTES});
     NamingEnumeration<SearchResult> ne =
         ctx.search(TRUSTSTORE_DN, "(objectclass=ds-cfg-instance-key)", sc);
     ArrayList<String> dnsToDelete = new ArrayList<String>();
     try {
       while (ne.hasMore()) {
         SearchResult sr = ne.next();
         dnsToDelete.add(sr.getName() + "," + TRUSTSTORE_DN);
       }
     } finally {
       ne.close();
     }
     for (String dn : dnsToDelete) {
       ctx.destroySubcontext(dn);
     }
   } catch (NameNotFoundException nnfe) {
     // Ignore
     LOG.log(Level.WARNING, "Error cleaning truststore: " + nnfe, nnfe);
   }
 }
  /**
   * @param ctx - the context to search from
   * @param user - the input username
   * @param credential - the bind credential
   * @param baseDN - base DN to search the ctx from
   * @param filter - the search filter string
   * @return the userDN string for the successful authentication
   * @throws NamingException
   */
  @SuppressWarnings("rawtypes")
  protected String bindDNAuthentication(
      InitialLdapContext ctx, String user, Object credential, String baseDN, String filter)
      throws NamingException {
    SearchControls constraints = new SearchControls();
    constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
    constraints.setTimeLimit(searchTimeLimit);
    String attrList[] = {distinguishedNameAttribute};
    constraints.setReturningAttributes(attrList);

    NamingEnumeration results = null;

    Object[] filterArgs = {user};
    results = ctx.search(baseDN, filter, filterArgs, constraints);
    if (results.hasMore() == false) {
      results.close();
      throw PicketBoxMessages.MESSAGES.failedToFindBaseContextDN(baseDN);
    }

    SearchResult sr = (SearchResult) results.next();
    String name = sr.getName();
    String userDN = null;
    Attributes attrs = sr.getAttributes();
    if (attrs != null) {
      Attribute dn = attrs.get(distinguishedNameAttribute);
      if (dn != null) {
        userDN = (String) dn.get();
      }
    }
    if (userDN == null) {
      if (sr.isRelative() == true) userDN = name + ("".equals(baseDN) ? "" : "," + baseDN);
      else throw PicketBoxMessages.MESSAGES.unableToFollowReferralForAuth(name);
    }

    safeClose(results);
    results = null;

    InitialLdapContext userCtx = constructInitialLdapContext(userDN, credential);
    safeClose(userCtx);

    return userDN;
  }
  /**
   * Returns the values of the ds-base-dn-entry count attributes for the given backend monitor entry
   * using the provided InitialLdapContext.
   *
   * @param ctx the InitialLdapContext to use to update the configuration.
   * @param backendID the id of the backend.
   * @return the values of the ds-base-dn-entry count attribute.
   * @throws NamingException if there was an error.
   */
  private static Set<String> getBaseDNEntryCount(InitialLdapContext ctx, String backendID)
      throws NamingException {
    LinkedHashSet<String> v = new LinkedHashSet<String>();
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
    ctls.setReturningAttributes(new String[] {"ds-base-dn-entry-count"});
    String filter = "(ds-backend-id=" + backendID + ")";

    LdapName jndiName = new LdapName("cn=monitor");
    NamingEnumeration<SearchResult> listeners = ctx.search(jndiName, filter, ctls);

    try {
      while (listeners.hasMore()) {
        SearchResult sr = listeners.next();

        v.addAll(getValues(sr, "ds-base-dn-entry-count"));
      }
    } finally {
      listeners.close();
    }
    return v;
  }
  private static void updateMiscellaneous(
      ServerDescriptor desc, InitialLdapContext ctx, TopologyCacheFilter cacheFilter)
      throws NamingException {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(new String[] {"ds-sync-generation-id"});
    String filter = "(|(objectclass=*)(objectclass=ldapsubentry))";

    LdapName jndiName = new LdapName("cn=schema");
    NamingEnumeration<SearchResult> listeners = ctx.search(jndiName, filter, ctls);

    try {
      while (listeners.hasMore()) {
        SearchResult sr = listeners.next();

        desc.serverProperties.put(
            ServerProperty.SCHEMA_GENERATION_ID, getFirstValue(sr, "ds-sync-generation-id"));
      }
    } finally {
      listeners.close();
    }
  }
  /* Find members for given group
   *
   */
  private void getGroupMembers(final DirConfigProperties dirProps, final BwGroup group)
      throws CalFacadeException {
    LdapConfigProperties props = (LdapConfigProperties) dirProps;
    InitialLdapContext ctx = null;

    try {
      ctx = createLdapInitContext(props);

      BasicAttributes matchAttrs = new BasicAttributes(true);

      matchAttrs.put(props.getGroupIdAttr(), group.getAccount());

      String[] memberAttr = {props.getGroupMemberAttr()};

      ArrayList<String> mbrs = null;

      boolean beenHere = false;

      NamingEnumeration response = ctx.search(props.getGroupContextDn(), matchAttrs, memberAttr);
      while (response.hasMore()) {
        SearchResult sr = (SearchResult) response.next();
        Attributes attrs = sr.getAttributes();

        if (beenHere) {
          throw new CalFacadeException("org.bedework.ldap.groups.multiple.result");
        }

        beenHere = true;

        Attribute membersAttr = attrs.get(props.getGroupMemberAttr());
        mbrs = new ArrayList<String>();

        for (int m = 0; m < membersAttr.size(); m++) {
          mbrs.add(membersAttr.get(m).toString());
        }
      }
      // LDAP We need a way to search recursively for groups.

      /* Search for each user in the group */
      String memberContext = props.getGroupMemberContextDn();
      String memberSearchAttr = props.getGroupMemberSearchAttr();
      String[] idAttr = {
        props.getGroupMemberUserIdAttr(), props.getGroupMemberGroupIdAttr(), "objectclass"
      };

      for (String mbr : mbrs) {
        if (memberContext != null) {
          matchAttrs = new BasicAttributes(true);

          matchAttrs.put(memberSearchAttr, mbr);

          response = ctx.search(memberContext, matchAttrs, idAttr);
        } else {
          response = ctx.search(memberContext, null, idAttr);
        }

        if (response.hasMore()) {
          SearchResult sr = (SearchResult) response.next();
          Attributes attrs = sr.getAttributes();

          Attribute ocsAttr = attrs.get("objectclass");
          String userOc = props.getUserObjectClass();
          String groupOc = props.getGroupObjectClass();
          boolean isGroup = false;

          for (int oci = 0; oci < ocsAttr.size(); oci++) {
            String oc = ocsAttr.get(oci).toString();
            if (userOc.equals(oc)) {
              break;
            }

            if (groupOc.equals(oc)) {
              isGroup = true;
              break;
            }
          }

          BwPrincipal p = null;
          Attribute attr;

          if (isGroup) {
            p = BwPrincipal.makeGroupPrincipal();

            attr = attrs.get(props.getGroupMemberGroupIdAttr());
          } else {
            p = BwPrincipal.makeUserPrincipal();

            attr = attrs.get(props.getGroupMemberUserIdAttr());
          }

          if (attr.size() != 1) {
            throw new CalFacadeException("org.bedework.ldap.groups.multiple.result");
          }

          p.setAccount(attr.get(0).toString());
          p.setPrincipalRef(makePrincipalUri(p.getAccount(), p.getKind()));
          group.addGroupMember(p);
        }
      }
    } catch (Throwable t) {
      if (debug) {
        error(t);
      }
      throw new CalFacadeException(t);
    } finally {
      // Close the context to release the connection
      if (ctx != null) {
        closeContext(ctx);
      }
    }

    /* Recursively fetch members of groups that are members. */

    for (BwGroup g : group.getGroups()) {
      getGroupMembers(props, g);
    }
  }
 /**
  * Close the connection.
  *
  * @throws Exception
  */
 public void shutdown() throws Exception {
   if (ldapContext != null) {
     ldapContext.close();
   }
 }
  private static void updateReplication(
      ServerDescriptor desc, InitialLdapContext ctx, TopologyCacheFilter cacheFilter)
      throws NamingException {
    boolean replicationEnabled = false;
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(new String[] {"ds-cfg-enabled"});
    String filter = "(objectclass=ds-cfg-synchronization-provider)";

    LdapName jndiName =
        new LdapName("cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config");
    NamingEnumeration<SearchResult> syncProviders = null;

    try {
      syncProviders = ctx.search(jndiName, filter, ctls);

      while (syncProviders.hasMore()) {
        SearchResult sr = syncProviders.next();

        if ("true".equalsIgnoreCase(getFirstValue(sr, "ds-cfg-enabled"))) {
          replicationEnabled = true;
        }
      }
    } catch (NameNotFoundException nse) {
      /* ignore */
    } finally {
      if (syncProviders != null) {
        syncProviders.close();
      }
    }
    desc.serverProperties.put(
        ServerProperty.IS_REPLICATION_ENABLED, replicationEnabled ? Boolean.TRUE : Boolean.FALSE);

    Set<String> allReplicationServers = new LinkedHashSet<String>();

    if (cacheFilter.searchBaseDNInformation()) {
      ctls = new SearchControls();
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
      ctls.setReturningAttributes(
          new String[] {"ds-cfg-base-dn", "ds-cfg-replication-server", "ds-cfg-server-id"});
      filter = "(objectclass=ds-cfg-replication-domain)";

      jndiName =
          new LdapName("cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config");

      syncProviders = null;
      try {
        syncProviders = ctx.search(jndiName, filter, ctls);

        while (syncProviders.hasMore()) {
          SearchResult sr = syncProviders.next();

          int id = Integer.parseInt(getFirstValue(sr, "ds-cfg-server-id"));
          Set<String> replicationServers = getValues(sr, "ds-cfg-replication-server");
          Set<String> dns = getValues(sr, "ds-cfg-base-dn");
          for (String dn : dns) {
            for (ReplicaDescriptor replica : desc.getReplicas()) {
              if (areDnsEqual(replica.getSuffix().getDN(), dn)) {
                replica.setReplicationId(id);
                // Keep the values of the replication servers in lower case
                // to make use of Sets as String simpler.
                LinkedHashSet<String> repServers = new LinkedHashSet<String>();
                for (String s : replicationServers) {
                  repServers.add(s.toLowerCase());
                }
                replica.setReplicationServers(repServers);
                allReplicationServers.addAll(repServers);
              }
            }
          }
        }
      } catch (NameNotFoundException nse) {
        /* ignore */
      } finally {
        if (syncProviders != null) {
          syncProviders.close();
        }
      }
    }

    ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
          "ds-cfg-replication-port", "ds-cfg-replication-server", "ds-cfg-replication-server-id"
        });
    filter = "(objectclass=ds-cfg-replication-server)";

    jndiName =
        new LdapName("cn=Multimaster " + "Synchronization,cn=Synchronization Providers,cn=config");

    desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER, Boolean.FALSE);
    NamingEnumeration<SearchResult> entries = null;
    try {
      entries = ctx.search(jndiName, filter, ctls);

      while (entries.hasMore()) {
        SearchResult sr = entries.next();

        desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER, Boolean.TRUE);
        String v = getFirstValue(sr, "ds-cfg-replication-port");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_PORT, Integer.parseInt(v));
        v = getFirstValue(sr, "ds-cfg-replication-server-id");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_ID, Integer.parseInt(v));
        Set<String> values = getValues(sr, "ds-cfg-replication-server");
        // Keep the values of the replication servers in lower case
        // to make use of Sets as String simpler.
        LinkedHashSet<String> repServers = new LinkedHashSet<String>();
        for (String s : values) {
          repServers.add(s.toLowerCase());
        }
        allReplicationServers.addAll(repServers);
        desc.serverProperties.put(
            ServerProperty.EXTERNAL_REPLICATION_SERVERS, allReplicationServers);
      }
    } catch (NameNotFoundException nse) {
      /* ignore */
    } finally {
      if (entries != null) {
        entries.close();
      }
    }

    boolean replicationSecure = false;
    if (replicationEnabled) {
      ctls = new SearchControls();
      ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
      ctls.setReturningAttributes(new String[] {"ds-cfg-ssl-encryption"});
      filter = "(objectclass=ds-cfg-crypto-manager)";

      jndiName = new LdapName("cn=Crypto Manager,cn=config");

      entries = ctx.search(jndiName, filter, ctls);

      try {
        while (entries.hasMore()) {
          SearchResult sr = entries.next();

          String v = getFirstValue(sr, "ds-cfg-ssl-encryption");
          replicationSecure = "true".equalsIgnoreCase(v);
        }
      } finally {
        entries.close();
      }
    }
    desc.serverProperties.put(
        ServerProperty.IS_REPLICATION_SECURE, replicationSecure ? Boolean.TRUE : Boolean.FALSE);
  }