| New file |
| | |
| | | /* |
| | | * CDDL HEADER START |
| | | * |
| | | * The contents of this file are subject to the terms of the |
| | | * Common Development and Distribution License, Version 1.0 only |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | * If applicable, add the following below this CDDL HEADER, with the |
| | | * fields enclosed by brackets "[]" replaced with your own identifying |
| | | * information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | | * |
| | | * Copyright 2013 ForgeRock AS |
| | | * |
| | | */ |
| | | |
| | | package org.forgerock.opendj.examples; |
| | | |
| | | import org.forgerock.opendj.ldap.Connection; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.ErrorResultException; |
| | | import org.forgerock.opendj.ldap.LDAPConnectionFactory; |
| | | import org.forgerock.opendj.ldap.LDAPOptions; |
| | | import org.forgerock.opendj.ldap.ModificationType; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SSLContextBuilder; |
| | | import org.forgerock.opendj.ldap.TrustManagers; |
| | | import org.forgerock.opendj.ldap.requests.ModifyRequest; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import java.nio.charset.Charset; |
| | | import java.security.GeneralSecurityException; |
| | | |
| | | /** |
| | | * This command-line client demonstrates how to reset a user password in |
| | | * Microsoft Active Directory. |
| | | * <p> |
| | | * The client takes as arguments the host and port of the Active Directory |
| | | * server, a flag indicating whether this is a self-reset (user changing own |
| | | * password) or an administrative reset (administrator changing a password), |
| | | * the DN and password of the user performing the reset, and target user DN |
| | | * and new user password. |
| | | */ |
| | | public final class PasswordResetForAD { |
| | | |
| | | /** |
| | | * Reset a user password in Microsoft Active Directory. |
| | | * <p> |
| | | * The connection should be LDAPS, not LDAP, in order to perform the |
| | | * modification. |
| | | * |
| | | * @param args The command line arguments: host, port, "admin"|"self", |
| | | * DN, password, targetDN, newPassword |
| | | */ |
| | | public static void main(final String[] args) { |
| | | // --- JCite main --- |
| | | if (args.length != 7) { |
| | | System.err.println("Usage: host port \"admin\"|\"self\" DN " |
| | | + "password targetDN newPassword"); |
| | | System.err.println("For example: ad.example.com 636 admin " |
| | | + "cn=administrator,cn=Users,DC=ad,DC=example,DC=com " |
| | | + "Secret123 cn=testuser,cn=Users,DC=ad,DC=example,DC=com " |
| | | + "NewP4s5w0rd"); |
| | | System.exit(1); |
| | | } |
| | | final String host = args[0]; |
| | | final int port = Integer.parseInt(args[1]); |
| | | final String mode = args[2]; |
| | | final String bindDN = args[3]; |
| | | final String bindPassword = args[4]; |
| | | final String targetDN = args[5]; |
| | | final String newPassword = args[6]; |
| | | |
| | | Connection connection = null; |
| | | try { |
| | | final LDAPConnectionFactory factory = |
| | | new LDAPConnectionFactory(host, port, getTrustAllOptions()); |
| | | connection = factory.getConnection(); |
| | | connection.bind(bindDN, bindPassword.toCharArray()); |
| | | |
| | | ModifyRequest request = |
| | | Requests.newModifyRequest(DN.valueOf(targetDN)); |
| | | String passwordAttribute = "unicodePwd"; |
| | | |
| | | if (mode.equalsIgnoreCase("admin")) { |
| | | // Request modify, replacing the password with the new. |
| | | |
| | | request.addModification( |
| | | ModificationType.REPLACE, |
| | | passwordAttribute, |
| | | encodePassword(newPassword) |
| | | ); |
| | | } else if (mode.equalsIgnoreCase("self")) { |
| | | // Request modify, deleting the old password, adding the new. |
| | | |
| | | // The default password policy for Active Directory domain |
| | | // controller systems sets minimum password age to 1 (day). |
| | | // If you get a constraint violation error when trying this |
| | | // example, set this minimum password age to 0 by executing |
| | | // cmd.exe as Administrator and entering the following |
| | | // command at the prompt: |
| | | // |
| | | // net accounts /MINPWAGE:0 |
| | | |
| | | request.addModification( |
| | | ModificationType.DELETE, |
| | | passwordAttribute, |
| | | encodePassword(bindPassword) |
| | | ); |
| | | request.addModification( |
| | | ModificationType.ADD, |
| | | passwordAttribute, |
| | | encodePassword(newPassword) |
| | | ); |
| | | } else { |
| | | System.err.println("Mode must be admin or self, not " + mode); |
| | | System.exit(1); |
| | | } |
| | | |
| | | connection.modify(request); |
| | | |
| | | System.out.println("Successfully changed password for " |
| | | + targetDN + " to " + newPassword + "."); |
| | | } catch (final ErrorResultException e) { |
| | | System.err.println(e.getMessage()); |
| | | System.exit(e.getResult().getResultCode().intValue()); |
| | | } catch (final GeneralSecurityException e) { |
| | | System.err.println(e.getMessage()); |
| | | System.exit(ResultCode.CLIENT_SIDE_CONNECT_ERROR.intValue()); |
| | | } finally { |
| | | if (connection != null) { |
| | | connection.close(); |
| | | } |
| | | } |
| | | // --- JCite main --- |
| | | } |
| | | |
| | | // --- JCite encodePassword --- |
| | | /** |
| | | * Encode new password in UTF-16LE format for use with Active Directory. |
| | | * |
| | | * @param password String representation of the password |
| | | * @return Byte array containing encoded password |
| | | */ |
| | | public static byte[] encodePassword(final String password) { |
| | | return ("\"" + password + "\"").getBytes(Charset.forName("UTF-16LE")); |
| | | } |
| | | // --- JCite encodePassword --- |
| | | |
| | | /** |
| | | * For SSL the connection factory needs SSL context options. This |
| | | * implementation simply trusts all server certificates. |
| | | */ |
| | | private static LDAPOptions getTrustAllOptions() throws GeneralSecurityException { |
| | | LDAPOptions lo = new LDAPOptions(); |
| | | SSLContext sslContext = |
| | | new SSLContextBuilder().setTrustManager(TrustManagers.trustAll()) |
| | | .getSSLContext(); |
| | | lo.setSSLContext(sslContext); |
| | | return lo; |
| | | } |
| | | |
| | | /** |
| | | * Constructor not used. |
| | | */ |
| | | private PasswordResetForAD() { |
| | | // Not used. |
| | | } |
| | | } |