/* * 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. *
* 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. *
* 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. } }