Exemple #1
0
  /**
   * Method authenticate.
   *
   * @param username String
   * @param password String
   * @return boolean * @throws Exception
   */
  public boolean authenticate(String username, String password) throws Exception {
    try {
      ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, username);
      ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
      ctx.reconnect(connCtls);
    } catch (AuthenticationException e) {
      throw e;
    } catch (NamingException e) {
      throw e;
    }

    return true;
  }
  /**
   * Attempt authentication
   *
   * @param getPasswdFromSharedState boolean that tells this method whether to retrieve the password
   *     from the sharedState.
   * @exception LoginException if the authentication attempt fails.
   */
  private void attemptAuthentication(boolean getPasswdFromSharedState) throws LoginException {

    // first get the username and password
    getUsernamePassword(getPasswdFromSharedState);

    if (password == null || password.length == 0) {
      throw (LoginException) new FailedLoginException("No password was supplied");
    }

    String dn = "";

    if (authFirst || authOnly) {

      String id = replaceUsernameToken(identityMatcher, authcIdentity);

      // Prepare to bind using user's username and password
      ldapEnvironment.put(Context.SECURITY_CREDENTIALS, password);
      ldapEnvironment.put(Context.SECURITY_PRINCIPAL, id);

      if (debug) {
        System.out.println(
            "\t\t[LdapLoginModule] " + "attempting to authenticate user: "******"Cannot bind to LDAP server").initCause(e);
      }

      // Authentication has succeeded

      // Locate the user's distinguished name
      if (userFilter != null) {
        dn = findUserDN(ctx);
      } else {
        dn = id;
      }

    } else {

      try {
        // Connect to the LDAP server (using anonymous bind)
        ctx = new InitialLdapContext(ldapEnvironment, null);

      } catch (NamingException e) {
        throw (LoginException)
            new FailedLoginException("Cannot connect to LDAP server").initCause(e);
      }

      // Locate the user's distinguished name
      dn = findUserDN(ctx);

      try {

        // Prepare to bind using user's distinguished name and password
        ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
        ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
        ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);

        if (debug) {
          System.out.println(
              "\t\t[LdapLoginModule] " + "attempting to authenticate user: "******"Cannot bind to LDAP server").initCause(e);
      }
    }

    // Save input as shared state only if authentication succeeded
    if (storePass
        && !sharedState.containsKey(USERNAME_KEY)
        && !sharedState.containsKey(PASSWORD_KEY)) {
      sharedState.put(USERNAME_KEY, username);
      sharedState.put(PASSWORD_KEY, password);
    }

    // Create the user principals
    userPrincipal = new UserPrincipal(username);
    if (authzIdentity != null) {
      authzPrincipal = new UserPrincipal(authzIdentity);
    }

    try {

      ldapPrincipal = new LdapPrincipal(dn);

    } catch (InvalidNameException e) {
      if (debug) {
        System.out.println("\t\t[LdapLoginModule] " + "cannot create LdapPrincipal: bad DN");
      }
      throw (LoginException) new FailedLoginException("Cannot create LdapPrincipal").initCause(e);
    }
  }
    private LdapContext bind(
        String principalName, String password, SocketInfo server, Hashtable<String, String> props)
        throws NamingException {
      String ldapUrl = (FORCE_LDAPS ? "ldaps://" : "ldap://") + server + '/';
      String oldName = Thread.currentThread().getName();
      Thread.currentThread().setName("Connecting to " + ldapUrl + " : " + oldName);
      LOGGER.fine("Connecting to " + ldapUrl);
      try {
        props.put(Context.PROVIDER_URL, ldapUrl);
        props.put("java.naming.ldap.version", "3");

        customizeLdapProperties(props);

        LdapContext context = (LdapContext) LdapCtxFactory.getLdapCtxInstance(ldapUrl, props);

        if (!FORCE_LDAPS) {
          // try to upgrade to TLS if we can, but failing to do so isn't fatal
          // see http://download.oracle.com/javase/jndi/tutorial/ldap/ext/starttls.html
          try {
            StartTlsResponse rsp =
                (StartTlsResponse) context.extendedOperation(new StartTlsRequest());
            rsp.negotiate((SSLSocketFactory) TrustAllSocketFactory.getDefault());
            LOGGER.fine("Connection upgraded to TLS");
          } catch (NamingException e) {
            LOGGER.log(
                Level.FINE,
                "Failed to start TLS. Authentication will be done via plain-text LDAP",
                e);
            context.removeFromEnvironment("java.naming.ldap.factory.socket");
          } catch (IOException e) {
            LOGGER.log(
                Level.FINE,
                "Failed to start TLS. Authentication will be done via plain-text LDAP",
                e);
            context.removeFromEnvironment("java.naming.ldap.factory.socket");
          }
        }

        if (principalName == null || password == null || password.equals("")) {
          // anonymous bind. LDAP uses empty password as a signal to anonymous bind (RFC 2829 5.1),
          // which means it can never be the actual user password.
          context.addToEnvironment(Context.SECURITY_AUTHENTICATION, "none");
          LOGGER.fine("Binding anonymously to " + ldapUrl);
        } else {
          // authenticate after upgrading to TLS, so that the credential won't go in clear text
          context.addToEnvironment(Context.SECURITY_PRINCIPAL, principalName);
          context.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
          LOGGER.fine("Binding as " + principalName + " to " + ldapUrl);
        }

        // this is supposed to cause the LDAP bind operation with the server,
        // but I notice that AD may still accept this and yet fail to search later,
        // when I tried anonymous bind.
        // if I do specify a wrong credential, this seems to fail.
        context.reconnect(null);

        return context; // worked
      } finally {
        Thread.currentThread().setName(oldName);
      }
    }