/** contact the ldap server and attempt to authenticate */
    protected boolean ldapAuthenticate(String netid, String password, Context context) {
      if (!password.equals("")) {

        LdapContext ctx = null;
        StartTlsResponse startTLSResponse = null;

        // Set up environment for creating initial context
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url);

        try {
          if (useTLS) {
            ctx = new InitialLdapContext(env, null);
            // start TLS
            startTLSResponse = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());

            startTLSResponse.negotiate();

            // perform simple client authentication
            ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
            ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, netid);
            ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password);
            ctx.addToEnvironment(javax.naming.Context.AUTHORITATIVE, "true");
            ctx.addToEnvironment(javax.naming.Context.REFERRAL, "follow");
            // dummy operation to check if authentication has succeeded
            ctx.getAttributes("");
          } else if (!useTLS) {
            // Authenticate
            env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "Simple");
            env.put(javax.naming.Context.SECURITY_PRINCIPAL, netid);
            env.put(javax.naming.Context.SECURITY_CREDENTIALS, password);
            env.put(javax.naming.Context.AUTHORITATIVE, "true");
            env.put(javax.naming.Context.REFERRAL, "follow");

            // Try to bind
            ctx = new InitialLdapContext(env, null);
          }
        } catch (NamingException | IOException e) {
          // something went wrong (like wrong password) so return false
          log.warn(LogManager.getHeader(context, "ldap_authentication", "type=failed_auth " + e));
          return false;
        } finally {
          // Close the context when we're done
          try {
            if (startTLSResponse != null) {
              startTLSResponse.close();
            }
            if (ctx != null) {
              ctx.close();
            }
          } catch (NamingException | IOException e) {
          }
        }
      } else {
        return false;
      }

      return true;
    }
Exemple #2
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;
  }
 @Override
 public LdapContext getLdapContext(Object principal, Object credentials) throws NamingException {
   LdapContext ctx = getSystemLdapContext();
   ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, principal);
   ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);
   try {
     // AUTHENTICATE CREDENTIALS BY CREATING AN INITIAL LDAP CONTEXT
     new InitialLdapContext(ctx.getEnvironment(), null);
   } catch (AuthenticationException ex) {
     throw new AuthenticationException("Access denied: " + principal);
   }
   return ctx;
 }
    private ProxyLdapContext(Hashtable env) throws NamingException {
      final Map<String, Object> savedEnv = new HashMap<String, Object>();
      for (final String key :
          Arrays.asList(
              Context.SECURITY_AUTHENTICATION,
              Context.SECURITY_CREDENTIALS,
              Context.SECURITY_PRINCIPAL,
              Context.SECURITY_PROTOCOL)) {
        final Object entry = env.remove(key);
        if (entry != null) {
          savedEnv.put(key, entry);
        }
      }
      delegate = new InitialLdapContext(env, null);
      tls = (StartTlsResponse) delegate.extendedOperation(new StartTlsRequest());
      tls.setHostnameVerifier(
          new HostnameVerifier() {

            @Override
            public boolean verify(String hostname, SSLSession session) {
              return true;
            }
          });
      try {
        final SSLSession negotiate = tls.negotiate();
        Logger.getLogger(this.getClass().getCanonicalName())
            .fine("LDAP is now using " + negotiate.getProtocol());
      } catch (final IOException e) {
        throw new NamingException(e.getMessage());
      }
      for (final Map.Entry<String, Object> savedEntry : savedEnv.entrySet()) {
        delegate.addToEnvironment(savedEntry.getKey(), savedEntry.getValue());
      }
    }
 @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);
   }
 }
  /**
   * 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);
      }
    }
    protected String getDNOfUser(
        String adminUser, String adminPassword, Context context, String netid) {
      // The resultant DN
      String resultDN;

      // The search scope to use (default to 0)
      int ldap_search_scope_value = 0;
      try {
        ldap_search_scope_value = Integer.parseInt(ldap_search_scope.trim());
      } catch (NumberFormatException e) {
        // Log the error if it has been set but is invalid
        if (ldap_search_scope != null) {
          log.warn(
              LogManager.getHeader(
                  context, "ldap_authentication", "invalid search scope: " + ldap_search_scope));
        }
      }

      // Set up environment for creating initial context
      Hashtable<String, String> env = new Hashtable<String, String>();
      env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url);

      LdapContext ctx = null;
      StartTlsResponse startTLSResponse = null;

      try {
        if ((adminUser != null)
            && (!adminUser.trim().equals(""))
            && (adminPassword != null)
            && (!adminPassword.trim().equals(""))) {
          if (useTLS) {
            ctx = new InitialLdapContext(env, null);
            // start TLS
            startTLSResponse = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());

            startTLSResponse.negotiate();

            // perform simple client authentication
            ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
            ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, adminUser);
            ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword);
          } else {
            // Use admin credentials for search// Authenticate
            env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
            env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser);
            env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword);

            // Create initial context
            ctx = new InitialLdapContext(env, null);
          }
        } else {
          // Use anonymous authentication
          env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "none");
        }

        Attributes matchAttrs = new BasicAttributes(true);
        matchAttrs.put(new BasicAttribute(ldap_id_field, netid));

        // look up attributes
        try {
          SearchControls ctrls = new SearchControls();
          ctrls.setSearchScope(ldap_search_scope_value);

          String searchName = "";
          if (useTLS) {
            searchName = ldap_search_context;
          } else {
            searchName = ldap_provider_url + ldap_search_context;
          }
          NamingEnumeration<SearchResult> answer =
              ctx.search(searchName, "(&({0}={1}))", new Object[] {ldap_id_field, netid}, ctrls);

          while (answer.hasMoreElements()) {
            SearchResult sr = answer.next();
            if (StringUtils.isEmpty(ldap_search_context)) {
              resultDN = sr.getName();
            } else {
              resultDN = (sr.getName() + "," + ldap_search_context);
            }

            String attlist[] = {
              ldap_email_field,
              ldap_givenname_field,
              ldap_surname_field,
              ldap_phone_field,
              ldap_group_field
            };
            Attributes atts = sr.getAttributes();
            Attribute att;

            if (attlist[0] != null) {
              att = atts.get(attlist[0]);
              if (att != null) {
                ldapEmail = (String) att.get();
              }
            }

            if (attlist[1] != null) {
              att = atts.get(attlist[1]);
              if (att != null) {
                ldapGivenName = (String) att.get();
              }
            }

            if (attlist[2] != null) {
              att = atts.get(attlist[2]);
              if (att != null) {
                ldapSurname = (String) att.get();
              }
            }

            if (attlist[3] != null) {
              att = atts.get(attlist[3]);
              if (att != null) {
                ldapPhone = (String) att.get();
              }
            }

            if (attlist[4] != null) {
              att = atts.get(attlist[4]);
              if (att != null) {
                ldapGroup = (String) att.get();
              }
            }

            if (answer.hasMoreElements()) {
              // Oh dear - more than one match
              // Ambiguous user, can't continue

            } else {
              log.debug(LogManager.getHeader(context, "got DN", resultDN));
              return resultDN;
            }
          }
        } catch (NamingException e) {
          // if the lookup fails go ahead and create a new record for them because the
          // authentication
          // succeeded
          log.warn(
              LogManager.getHeader(context, "ldap_attribute_lookup", "type=failed_search " + e));
        }
      } catch (NamingException | IOException e) {
        log.warn(LogManager.getHeader(context, "ldap_authentication", "type=failed_auth " + e));
      } finally {
        // Close the context when we're done
        try {
          if (startTLSResponse != null) {
            startTLSResponse.close();
          }
          if (ctx != null) {
            ctx.close();
          }
        } catch (NamingException | IOException e) {
        }
      }

      // No DN match found
      return null;
    }