/**
   * after a user has successfully logged in we want to build an access object for use in the
   * scheduling system
   *
   * @param String username
   * @param String group a group name to check for username in (via memberUid string)
   * @return boolean yes or no in the group
   * @throws NamingException when the search fails by DN this will be thrown
   */
  private boolean userInGroup(String username, String group) throws NamingException {
    // assume they are not
    boolean inGroup = false;

    // Specify the attributes to match
    Attributes matchAttrs = new BasicAttributes(true); // ignore attribute name case
    // set the common name for the group using defined prefix ie 'cn' or 'ou'
    matchAttrs.put(
        new BasicAttribute(
            this.GROUPS_LOC.substring(0, this.GROUPS_LOC.indexOf("=")),
            group)); // named group for access rights

    // Search for objects that have those matching attributes in the specified group location
    NamingEnumeration answer = ctx.search(this.GROUPS_LOC + this.BASE_DN, matchAttrs);

    // search for that user id in the member list
    while (answer.hasMore()) {
      SearchResult sr = (SearchResult) answer.next();
      if ((sr.getAttributes().get("memberuid").toString()).indexOf(username) >= 0) {
        // this user is in the specified group
        inGroup = true;
      }
    }
    System.err.println(username + " in " + group + ": " + new Boolean(inGroup).toString());
    return inGroup;
  }
  /* goodG2B() - use goodsource and badsink */
  public void goodG2B_sink(String data, HttpServletRequest request, HttpServletResponse response)
      throws Throwable {

    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext ctx = new InitialDirContext(env);

    String search =
        "(cn=" + data + ")"; /* POTENTIAL FLAW: unsanitized data from untrusted source */

    NamingEnumeration<SearchResult> answer = ctx.search("", search, null);
    while (answer.hasMore()) {
      SearchResult sr = answer.next();
      Attributes a = sr.getAttributes();
      NamingEnumeration<?> attrs = a.getAll();
      while (attrs.hasMore()) {
        Attribute attr = (Attribute) attrs.next();
        NamingEnumeration<?> values = attr.getAll();
        while (values.hasMore()) {
          response.getWriter().println(" Value: " + values.next().toString());
        }
      }
    }
  }
  /* uses badsource and badsink - see how tools report flaws that don't always occur */
  public void bad(HttpServletRequest request, HttpServletResponse response) throws Throwable {
    String data;
    if (IO.static_returns_t_or_f()) {
      Logger log_bad = Logger.getLogger("local-logger");
      data = ""; /* init data */
      /* retrieve the property */
      Properties props = new Properties();
      FileInputStream finstr = null;
      try {
        finstr = new FileInputStream("../common/config.properties");
        props.load(finstr);
        data = props.getProperty("data");
      } catch (IOException ioe) {
        log_bad.warning("Error with stream reading");
      } finally {
        /* clean up stream reading objects */
        try {
          if (finstr != null) {
            finstr.close();
          }
        } catch (IOException ioe) {
          log_bad.warning("Error closing buffread");
        }
      }
    } else {

      java.util.logging.Logger log_good = java.util.logging.Logger.getLogger("local-logger");

      /* FIX: Use a hardcoded string */
      data = "foo";
    }

    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext ctx = new InitialDirContext(env);

    String search =
        "(cn=" + data + ")"; /* POTENTIAL FLAW: unsanitized data from untrusted source */

    NamingEnumeration<SearchResult> answer = ctx.search("", search, null);
    while (answer.hasMore()) {
      SearchResult sr = answer.next();
      Attributes a = sr.getAttributes();
      NamingEnumeration<?> attrs = a.getAll();
      while (attrs.hasMore()) {
        Attribute attr = (Attribute) attrs.next();
        NamingEnumeration<?> values = attr.getAll();
        while (values.hasMore()) {
          response.getWriter().println(" Value: " + values.next().toString());
        }
      }
    }
  }
  /* goodG2B1() - use goodsource and badsink by changing IO.staticTrue to IO.staticFalse */
  private void goodG2B1() throws Throwable {
    String data;
    if (IO.staticFalse) {
      /* INCIDENTAL: CWE 561 Dead Code, the code below will never run
       * but ensure data is inititialized before the Sink to avoid compiler errors */
      data = null;
    } else {

      /* FIX: Use a hardcoded string */
      data = "foo";
    }

    Hashtable<String, String> environmentHashTable = new Hashtable<String, String>();
    environmentHashTable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    environmentHashTable.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext directoryContext = null;

    try {
      directoryContext = new InitialDirContext(environmentHashTable);
      /* POTENTIAL FLAW: data concatenated into LDAP search, which could result in LDAP Injection */
      String search = "(cn=" + data + ")";

      NamingEnumeration<SearchResult> answer = directoryContext.search("", search, null);
      while (answer.hasMore()) {
        SearchResult searchResult = answer.next();
        Attributes attributes = searchResult.getAttributes();
        NamingEnumeration<?> allAttributes = attributes.getAll();
        while (allAttributes.hasMore()) {
          Attribute attribute = (Attribute) allAttributes.next();
          NamingEnumeration<?> allValues = attribute.getAll();
          while (allValues.hasMore()) {
            IO.writeLine(" Value: " + allValues.next().toString());
          }
        }
      }
    } catch (NamingException exceptNaming) {
      IO.logger.log(Level.WARNING, "The LDAP service was not found or login failed.", exceptNaming);
    } finally {
      if (directoryContext != null) {
        try {
          directoryContext.close();
        } catch (NamingException exceptNaming) {
          IO.logger.log(Level.WARNING, "Error closing DirContext", exceptNaming);
        }
      }
    }
  }
  public void bad() throws Throwable {
    String data;

    badPrivate = true;
    data = bad_source();

    Hashtable<String, String> environmentHashTable = new Hashtable<String, String>();
    environmentHashTable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    environmentHashTable.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext directoryContext = null;

    try {
      directoryContext = new InitialDirContext(environmentHashTable);
      /* POTENTIAL FLAW: data concatenated into LDAP search, which could result in LDAP Injection */
      String search = "(cn=" + data + ")";

      NamingEnumeration<SearchResult> answer = directoryContext.search("", search, null);
      while (answer.hasMore()) {
        SearchResult searchResult = answer.next();
        Attributes attributes = searchResult.getAttributes();
        NamingEnumeration<?> allAttributes = attributes.getAll();
        while (allAttributes.hasMore()) {
          Attribute attribute = (Attribute) allAttributes.next();
          NamingEnumeration<?> allValues = attribute.getAll();
          while (allValues.hasMore()) {
            IO.writeLine(" Value: " + allValues.next().toString());
          }
        }
      }
    } catch (NamingException exceptNaming) {
      IO.logger.log(Level.WARNING, "The LDAP service was not found or login failed.", exceptNaming);
    } finally {
      if (directoryContext != null) {
        try {
          directoryContext.close();
        } catch (NamingException exceptNaming) {
          IO.logger.log(Level.WARNING, "Error closing DirContext", exceptNaming);
        }
      }
    }
  }
  /* goodG2B() - use goodsource and badsink by changing the "if" so that
  both branches use the GoodSource */
  private void goodG2B(HttpServletRequest request, HttpServletResponse response) throws Throwable {
    String data;
    if (IO.static_returns_t_or_f()) {
      java.util.logging.Logger log_good = java.util.logging.Logger.getLogger("local-logger");
      /* FIX: Use a hardcoded string */
      data = "foo";
    } else {

      java.util.logging.Logger log_good = java.util.logging.Logger.getLogger("local-logger");

      /* FIX: Use a hardcoded string */
      data = "foo";
    }

    Hashtable<String, String> env = new Hashtable<String, String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext ctx = new InitialDirContext(env);

    String search =
        "(cn=" + data + ")"; /* POTENTIAL FLAW: unsanitized data from untrusted source */

    NamingEnumeration<SearchResult> answer = ctx.search("", search, null);
    while (answer.hasMore()) {
      SearchResult sr = answer.next();
      Attributes a = sr.getAttributes();
      NamingEnumeration<?> attrs = a.getAll();
      while (attrs.hasMore()) {
        Attribute attr = (Attribute) attrs.next();
        NamingEnumeration<?> values = attr.getAll();
        while (values.hasMore()) {
          response.getWriter().println(" Value: " + values.next().toString());
        }
      }
    }
  }
  /**
   * Search for the user's entry. Determine the distinguished name of the user's entry and
   * optionally an authorization identity for the user.
   *
   * @param ctx an LDAP context to use for the search
   * @return the user's distinguished name or an empty string if none was found.
   * @exception LoginException if the user's entry cannot be found.
   */
  private String findUserDN(LdapContext ctx) throws LoginException {

    String userDN = "";

    // Locate the user's LDAP entry
    if (userFilter != null) {
      if (debug) {
        System.out.println(
            "\t\t[LdapLoginModule] " + "searching for entry belonging to user: "******"\t\t[LdapLoginModule] " + "cannot search for entry belonging to user: "******"Cannot find user's LDAP entry");
    }

    try {
      NamingEnumeration results =
          ctx.search("", replaceUsernameToken(filterMatcher, userFilter), constraints);

      // Extract the distinguished name of the user's entry
      // (Use the first entry if more than one is returned)
      if (results.hasMore()) {
        SearchResult entry = (SearchResult) results.next();

        // %%% - use the SearchResult.getNameInNamespace method
        //        available in JDK 1.5 and later.
        //        (can remove call to constraints.setReturningObjFlag)
        userDN = ((Context) entry.getObject()).getNameInNamespace();

        if (debug) {
          System.out.println("\t\t[LdapLoginModule] found entry: " + userDN);
        }

        // Extract a value from user's authorization identity attribute
        if (authzIdentityAttr != null) {
          Attribute attr = entry.getAttributes().get(authzIdentityAttr);
          if (attr != null) {
            Object val = attr.get();
            if (val instanceof String) {
              authzIdentity = (String) val;
            }
          }
        }

        results.close();

      } else {
        // Bad username
        if (debug) {
          System.out.println("\t\t[LdapLoginModule] user's entry " + "not found");
        }
      }

    } catch (NamingException e) {
      // ignore
    }

    if (userDN.equals("")) {
      throw (LoginException) new FailedLoginException("Cannot find user's LDAP entry");
    } else {
      return userDN;
    }
  }
  /* uses badsource and badsink */
  public void bad() throws Throwable {
    String data;
    if (IO.staticTrue) {
      data = ""; /* Initialize data */
      /* Read data using a listening tcp connection */
      {
        ServerSocket listener = null;
        Socket socket = null;
        BufferedReader readerBuffered = null;
        InputStreamReader readerInputStream = null;
        /* Read data using a listening tcp connection */
        try {
          listener = new ServerSocket(39543);
          socket = listener.accept();
          /* read input from socket */
          readerInputStream = new InputStreamReader(socket.getInputStream(), "UTF-8");
          readerBuffered = new BufferedReader(readerInputStream);
          /* POTENTIAL FLAW: Read data using a listening tcp connection */
          data = readerBuffered.readLine();
        } catch (IOException exceptIO) {
          IO.logger.log(Level.WARNING, "Error with stream reading", exceptIO);
        } finally {
          /* Close stream reading objects */
          try {
            if (readerBuffered != null) {
              readerBuffered.close();
            }
          } catch (IOException exceptIO) {
            IO.logger.log(Level.WARNING, "Error closing BufferedReader", exceptIO);
          }

          try {
            if (readerInputStream != null) {
              readerInputStream.close();
            }
          } catch (IOException exceptIO) {
            IO.logger.log(Level.WARNING, "Error closing InputStreamReader", exceptIO);
          }

          /* Close socket objects */
          try {
            if (socket != null) {
              socket.close();
            }
          } catch (IOException exceptIO) {
            IO.logger.log(Level.WARNING, "Error closing Socket", exceptIO);
          }

          try {
            if (listener != null) {
              listener.close();
            }
          } catch (IOException exceptIO) {
            IO.logger.log(Level.WARNING, "Error closing ServerSocket", exceptIO);
          }
        }
      }
    } else {
      /* INCIDENTAL: CWE 561 Dead Code, the code below will never run
       * but ensure data is inititialized before the Sink to avoid compiler errors */
      data = null;
    }

    Hashtable<String, String> environmentHashTable = new Hashtable<String, String>();
    environmentHashTable.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    environmentHashTable.put(Context.PROVIDER_URL, "ldap://localhost:389");
    DirContext directoryContext = null;

    try {
      directoryContext = new InitialDirContext(environmentHashTable);
      /* POTENTIAL FLAW: data concatenated into LDAP search, which could result in LDAP Injection */
      String search = "(cn=" + data + ")";

      NamingEnumeration<SearchResult> answer = directoryContext.search("", search, null);
      while (answer.hasMore()) {
        SearchResult searchResult = answer.next();
        Attributes attributes = searchResult.getAttributes();
        NamingEnumeration<?> allAttributes = attributes.getAll();
        while (allAttributes.hasMore()) {
          Attribute attribute = (Attribute) allAttributes.next();
          NamingEnumeration<?> allValues = attribute.getAll();
          while (allValues.hasMore()) {
            IO.writeLine(" Value: " + allValues.next().toString());
          }
        }
      }
    } catch (NamingException exceptNaming) {
      IO.logger.log(Level.WARNING, "The LDAP service was not found or login failed.", exceptNaming);
    } finally {
      if (directoryContext != null) {
        try {
          directoryContext.close();
        } catch (NamingException exceptNaming) {
          IO.logger.log(Level.WARNING, "Error closing DirContext", exceptNaming);
        }
      }
    }
  }