/*
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* 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
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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
*
*
* Portions Copyright 2006 Sun Microsystems, Inc.
*/
package org.opends.server.tools;
import java.net.Socket;
import java.util.ArrayList;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Reader;
import org.opends.server.protocols.asn1.ASN1Sequence;
import org.opends.server.protocols.asn1.ASN1Writer;
import org.opends.server.protocols.ldap.BindRequestProtocolOp;
import org.opends.server.protocols.ldap.BindResponseProtocolOp;
import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp;
import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.protocols.ldap.UnbindRequestProtocolOp;
import org.opends.server.types.DN;
import static org.opends.server.extensions.ExtensionsConstants.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
* This program provides a utility that uses the LDAP password modify extended
* operation to change the password for a user. It exposes the three primary
* options available for this operation, which are:
*
*
* - The user identity whose password should be changed.
* - The current password for the user.
* - The new password for the user.
*
*
* All of these are optional components that may be included or omitted from the
* request.
*/
public class LDAPPasswordModify
{
/**
* Parses the command-line arguments, establishes a connection to the
* Directory Server, sends the password modify request, and reads the
* response.
*
* @param args The command-line arguments provided to this program.
*/
public static void main(String[] args)
{
// Define default values for all the configurable arguments.
boolean provideDNForAuthzID = false;
boolean provideOldPW = false;
int ldapPort = 389;
String authzID = null;
String bindDN = null;
String bindPW = null;
String ldapHost = "127.0.0.1";
String newPassword = null;
String oldPassword = null;
if (args.length == 0)
{
displayUsage();
return;
}
// Iterate through and process the command-line arguments.
for (int i=0; i < args.length; i++)
{
if (args[i].equals("-h"))
{
ldapHost = args[++i];
}
else if (args[i].equals("-p"))
{
ldapPort = Integer.parseInt(args[++i]);
}
else if (args[i].equals("-D"))
{
bindDN = args[++i];
}
else if (args[i].equals("-w"))
{
bindPW = args[++i];
}
else if (args[i].equals("-a"))
{
authzID = args[++i];
}
else if (args[i].equals("-A"))
{
provideDNForAuthzID = true;
}
else if (args[i].equals("-o"))
{
oldPassword = args[++i];
}
else if (args[i].equals("-O"))
{
provideOldPW = true;
}
else if (args[i].equals("-n"))
{
newPassword = args[++i];
}
else if (args[i].equals("-H"))
{
displayUsage();
return;
}
else
{
System.err.println("ERROR: Invalid argument \"" + args[i] + "\"");
displayUsage();
System.exit(1);
}
}
// Make sure that all the required arguments were provided.
if (provideOldPW)
{
if ((bindPW == null) || (bindPW.length() == 0))
{
System.err.println("ERROR: The -O argument was used but no bind " +
"password was provided.");
displayUsage();
System.exit(1);
}
else
{
oldPassword = bindPW;
}
}
if (provideDNForAuthzID)
{
if ((bindDN == null) || (bindDN.length() == 0))
{
System.err.println("ERROR: The -A argument was used but no bind DN " +
"was provided.");
displayUsage();
System.exit(1);
}
else
{
authzID = "dn:" + bindDN;
}
}
// Perform the necessary bootstrapping of the Directory Server code.
DirectoryServer.bootstrapClient();
// Establish a connection to the Directory Server.
ASN1Reader reader = null;
ASN1Writer writer = null;
try
{
Socket socket = new Socket(ldapHost, ldapPort);
reader = new ASN1Reader(socket);
writer = new ASN1Writer(socket);
}
catch (Exception e)
{
System.err.println("ERROR: Unable to connect to the Directory Server " +
ldapHost + ":" + ldapPort + ":");
e.printStackTrace();
System.exit(1);
}
// Send the LDAP bind request if appropriate.
if ((bindDN != null) && (bindDN.length() > 0) && (bindPW != null) &&
(bindPW.length() > 0))
{
BindRequestProtocolOp bindRequest =
new BindRequestProtocolOp(new ASN1OctetString(bindDN), 3,
new ASN1OctetString(bindPW));
LDAPMessage requestMessage = new LDAPMessage(1, bindRequest);
try
{
writer.writeElement(requestMessage.encode());
}
catch (Exception e)
{
System.err.println("ERROR: Could not send the bind request to the " +
"server:");
e.printStackTrace();
try
{
reader.close();
writer.close();
} catch (Exception e2) {}
System.exit(1);
}
LDAPMessage responseMessage = null;
try
{
ASN1Sequence responseSequence = reader.readElement().decodeAsSequence();
responseMessage = LDAPMessage.decode(responseSequence);
}
catch (Exception e)
{
System.err.println("ERROR: Could not read the bind response from " +
"the server:");
e.printStackTrace();
try
{
reader.close();
writer.close();
} catch (Exception e2) {}
System.exit(1);
}
BindResponseProtocolOp bindResponse =
responseMessage.getBindResponseProtocolOp();
int resultCode = bindResponse.getResultCode();
if (resultCode != LDAPResultCode.SUCCESS)
{
System.err.println("ERROR: Bind failed with result code " +
resultCode);
String errorMessage = bindResponse.getErrorMessage();
if ((errorMessage != null) && (errorMessage.length() > 0))
{
System.err.println("Error Message: " + errorMessage);
}
DN matchedDN = bindResponse.getMatchedDN();
if (matchedDN != null)
{
System.err.println("Matched DN: " + matchedDN.toString());
}
try
{
requestMessage = new LDAPMessage(2, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e) {}
try
{
reader.close();
writer.close();
} catch (Exception e) {}
System.exit(resultCode);
}
}
// Construct the password modify request.
ArrayList requestElements = new ArrayList(3);
if (authzID != null)
{
requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_USER_ID,
authzID));
}
if (oldPassword != null)
{
requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_OLD_PASSWORD,
oldPassword));
}
if (newPassword != null)
{
requestElements.add(new ASN1OctetString(TYPE_PASSWORD_MODIFY_NEW_PASSWORD,
newPassword));
}
ASN1OctetString requestValue =
new ASN1OctetString(new ASN1Sequence(requestElements).encode());
ExtendedRequestProtocolOp extendedRequest =
new ExtendedRequestProtocolOp(OID_PASSWORD_MODIFY_REQUEST,
requestValue);
LDAPMessage requestMessage = new LDAPMessage(2, extendedRequest);
// Send the request to the server and read the response.
try
{
writer.writeElement(requestMessage.encode());
}
catch (Exception e)
{
System.err.println("ERROR: Could not send password modify request:");
e.printStackTrace();
try
{
requestMessage = new LDAPMessage(2, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e2) {}
try
{
reader.close();
writer.close();
} catch (Exception e2) {}
System.exit(1);
}
// Read the response from the server.
LDAPMessage responseMessage = null;
try
{
ASN1Sequence responseSequence = reader.readElement().decodeAsSequence();
responseMessage = LDAPMessage.decode(responseSequence);
}
catch (Exception e)
{
System.err.println("ERROR: Could not read password modify response:");
e.printStackTrace();
try
{
requestMessage = new LDAPMessage(2, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e2) {}
try
{
reader.close();
writer.close();
} catch (Exception e2) {}
System.exit(1);
}
// Make sure that the response was acceptable.
ExtendedResponseProtocolOp extendedResponse =
responseMessage.getExtendedResponseProtocolOp();
int resultCode = extendedResponse.getResultCode();
if (resultCode != LDAPResultCode.SUCCESS)
{
System.err.println("ERROR: Password modify failed with result code " +
resultCode);
String errorMessage = extendedResponse.getErrorMessage();
if ((errorMessage != null) && (errorMessage.length() > 0))
{
System.err.println("Error Message: " + errorMessage);
}
DN matchedDN = extendedResponse.getMatchedDN();
if (matchedDN != null)
{
System.err.println("Matched DN: " + matchedDN.toString());
}
try
{
requestMessage = new LDAPMessage(3, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e) {}
try
{
reader.close();
writer.close();
} catch (Exception e) {}
System.exit(resultCode);
}
System.out.println("The user's password was successfully modified.");
// See if the response included a generated password.
ASN1OctetString responseValue = extendedResponse.getValue();
if (responseValue != null)
{
try
{
ASN1Sequence responseSequence =
ASN1Sequence.decodeAsSequence(responseValue.value());
for (ASN1Element e : responseSequence.elements())
{
if (e.getType() == TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD)
{
String generatedPassword = e.decodeAsOctetString().stringValue();
System.out.println("The generated password was: " +
generatedPassword);
}
else
{
throw new Exception("ERROR: Unrecognized response value type " +
byteToHex(e.getType()));
}
}
}
catch (Exception e)
{
System.err.println("ERROR: Could not decode response value to " +
"determine the generated password:");
e.printStackTrace();
try
{
requestMessage = new LDAPMessage(2, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e2) {}
try
{
reader.close();
writer.close();
} catch (Exception e2) {}
System.exit(1);
}
}
// Unbind from the server and close the connection.
try
{
requestMessage = new LDAPMessage(3, new UnbindRequestProtocolOp());
writer.writeElement(requestMessage.encode());
}
catch (Exception e) {}
try
{
reader.close();
writer.close();
} catch (Exception e) {}
}
/**
* Displays usage information for this program.
*/
public static void displayUsage()
{
System.err.println("USAGE: java LDAPPasswordModify {options}");
System.err.println(" where {options} include:");
System.err.println("-h {ldapHost} -- The Directory Server address");
System.err.println("-p {ldapPort} -- The Directory Server port");
System.err.println("-D {bindDN} -- The bind DN");
System.err.println("-w {bindPW} -- The bind password");
System.err.println("-a {authzID} -- The authorization ID");
System.err.println("-A -- Use bind DN as authorization ID");
System.err.println("-o {oldPWD} -- The old password");
System.err.println("-O -- Use bind password as old password");
System.err.println("-n {newPWD} -- The new password");
System.err.println("-H -- Display this usage information");
}
}