All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.unboundid.ldap.sdk.unboundidds.tools.GenerateTOTPSharedSecret Maven / Gradle / Ivy

Go to download

The UnboundID LDAP SDK for Java is a fast, comprehensive, and easy-to-use Java API for communicating with LDAP directory servers and performing related tasks like reading and writing LDIF, encoding and decoding data using base64 and ASN.1 BER, and performing secure communication. This package contains the Standard Edition of the LDAP SDK, which is a complete, general-purpose library for communicating with LDAPv3 directory servers.

There is a newer version: 7.0.1
Show newest version
/*
 * Copyright 2016-2018 Ping Identity Corporation
 * All Rights Reserved.
 */
/*
 * Copyright (C) 2016-2018 Ping Identity Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (GPLv2 only)
 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
package com.unboundid.ldap.sdk.unboundidds.tools;



import java.io.BufferedReader;
import java.io.FileReader;
import java.io.OutputStream;
import java.util.LinkedHashMap;

import com.unboundid.ldap.sdk.ExtendedResult;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.Version;
import com.unboundid.ldap.sdk.unboundidds.extensions.
            GenerateTOTPSharedSecretExtendedRequest;
import com.unboundid.ldap.sdk.unboundidds.extensions.
            GenerateTOTPSharedSecretExtendedResult;
import com.unboundid.ldap.sdk.unboundidds.extensions.
            RevokeTOTPSharedSecretExtendedRequest;
import com.unboundid.util.Debug;
import com.unboundid.util.LDAPCommandLineTool;
import com.unboundid.util.PasswordReader;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import com.unboundid.util.args.ArgumentException;
import com.unboundid.util.args.ArgumentParser;
import com.unboundid.util.args.BooleanArgument;
import com.unboundid.util.args.FileArgument;
import com.unboundid.util.args.StringArgument;

import static com.unboundid.ldap.sdk.unboundidds.tools.ToolMessages.*;



/**
 * This class provides a tool that can be used to generate a TOTP shared secret
 * for a user.  That shared secret may be used to generate TOTP authentication
 * codes for the purpose of authenticating with the UNBOUNDID-TOTP SASL
 * mechanism, or as a form of step-up authentication for external applications
 * using the validate TOTP password extended operation.
 * 
*
* NOTE: This class, and other classes within the * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only * supported for use against Ping Identity, UnboundID, and * Nokia/Alcatel-Lucent 8661 server products. These classes provide support * for proprietary functionality or for external specifications that are not * considered stable or mature enough to be guaranteed to work in an * interoperable way with other types of LDAP servers. *
*/ @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) public final class GenerateTOTPSharedSecret extends LDAPCommandLineTool { // Indicates that the tool should interactively prompt for the static password // for the user for whom the TOTP secret is to be generated. private BooleanArgument promptForUserPassword = null; // Indicates that the tool should revoke all existing TOTP shared secrets for // the user. private BooleanArgument revokeAll = null; // The path to a file containing the static password for the user for whom the // TOTP secret is to be generated. private FileArgument userPasswordFile = null; // The username for the user for whom the TOTP shared secret is to be // generated. private StringArgument authenticationID = null; // The TOTP shared secret to revoke. private StringArgument revoke = null; // The static password for the user for whom the TOTP shared sec ret is to be // generated. private StringArgument userPassword = null; /** * Invokes the tool with the provided set of arguments. * * @param args The command-line arguments provided to this program. */ public static void main(final String... args) { final ResultCode resultCode = main(System.out, System.err, args); if (resultCode != ResultCode.SUCCESS) { System.exit(resultCode.intValue()); } } /** * Invokes the tool with the provided set of arguments. * * @param out The output stream to use for standard out. It may be * {@code null} if standard out should be suppressed. * @param err The output stream to use for standard error. It may be * {@code null} if standard error should be suppressed. * @param args The command-line arguments provided to this program. * * @return A result code with the status of the tool processing. Any result * code other than {@link ResultCode#SUCCESS} should be considered a * failure. */ public static ResultCode main(final OutputStream out, final OutputStream err, final String... args) { final GenerateTOTPSharedSecret tool = new GenerateTOTPSharedSecret(out, err); return tool.runTool(args); } /** * Creates a new instance of this tool with the provided arguments. * * @param out The output stream to use for standard out. It may be * {@code null} if standard out should be suppressed. * @param err The output stream to use for standard error. It may be * {@code null} if standard error should be suppressed. */ public GenerateTOTPSharedSecret(final OutputStream out, final OutputStream err) { super(out, err); } /** * {@inheritDoc} */ @Override() public String getToolName() { return "generate-totp-shared-secret"; } /** * {@inheritDoc} */ @Override() public String getToolDescription() { return INFO_GEN_TOTP_SECRET_TOOL_DESC.get(); } /** * {@inheritDoc} */ @Override() public String getToolVersion() { return Version.NUMERIC_VERSION_STRING; } /** * {@inheritDoc} */ @Override() public boolean supportsInteractiveMode() { return true; } /** * {@inheritDoc} */ @Override() public boolean defaultsToInteractiveMode() { return true; } /** * {@inheritDoc} */ @Override() public boolean supportsPropertiesFile() { return true; } /** * {@inheritDoc} */ @Override() protected boolean supportsOutputFile() { return true; } /** * {@inheritDoc} */ @Override() protected boolean supportsAuthentication() { return true; } /** * {@inheritDoc} */ @Override() protected boolean defaultToPromptForBindPassword() { return true; } /** * {@inheritDoc} */ @Override() protected boolean supportsSASLHelp() { return true; } /** * {@inheritDoc} */ @Override() protected boolean includeAlternateLongIdentifiers() { return true; } /** * {@inheritDoc} */ @Override() protected boolean logToolInvocationByDefault() { return true; } /** * {@inheritDoc} */ @Override() public void addNonLDAPArguments(final ArgumentParser parser) throws ArgumentException { // Create the authentication ID argument, which will identify the target // user. authenticationID = new StringArgument(null, "authID", true, 1, INFO_GEN_TOTP_SECRET_PLACEHOLDER_AUTH_ID.get(), INFO_GEN_TOTP_SECRET_DESCRIPTION_AUTH_ID.get()); authenticationID.addLongIdentifier("authenticationID", true); authenticationID.addLongIdentifier("auth-id", true); authenticationID.addLongIdentifier("authentication-id", true); parser.addArgument(authenticationID); // Create the arguments that may be used to obtain the static password for // the target user. userPassword = new StringArgument(null, "userPassword", false, 1, INFO_GEN_TOTP_SECRET_PLACEHOLDER_USER_PW.get(), INFO_GEN_TOTP_SECRET_DESCRIPTION_USER_PW.get( authenticationID.getIdentifierString())); userPassword.setSensitive(true); userPassword.addLongIdentifier("user-password", true); parser.addArgument(userPassword); userPasswordFile = new FileArgument(null, "userPasswordFile", false, 1, null, INFO_GEN_TOTP_SECRET_DESCRIPTION_USER_PW_FILE.get( authenticationID.getIdentifierString()), true, true, true, false); userPasswordFile.addLongIdentifier("user-password-file", true); parser.addArgument(userPasswordFile); promptForUserPassword = new BooleanArgument(null, "promptForUserPassword", INFO_GEN_TOTP_SECRET_DESCRIPTION_PROMPT_FOR_USER_PW.get( authenticationID.getIdentifierString())); promptForUserPassword.addLongIdentifier("prompt-for-user-password", true); parser.addArgument(promptForUserPassword); // Create the arguments that may be used to revoke shared secrets rather // than generate them. revoke = new StringArgument(null, "revoke", false, 1, INFO_GEN_TOTP_SECRET_PLACEHOLDER_SECRET.get(), INFO_GEN_TOTP_SECRET_DESCRIPTION_REVOKE.get()); parser.addArgument(revoke); revokeAll = new BooleanArgument(null, "revokeAll", 1, INFO_GEN_TOTP_SECRET_DESCRIPTION_REVOKE_ALL.get()); revokeAll.addLongIdentifier("revoke-all", true); parser.addArgument(revokeAll); // At most one of the userPassword, userPasswordFile, and // promptForUserPassword arguments must be present. parser.addExclusiveArgumentSet(userPassword, userPasswordFile, promptForUserPassword); // If any of the userPassword, userPasswordFile, or promptForUserPassword // arguments is present, then the authenticationID argument must also be // present. parser.addDependentArgumentSet(userPassword, authenticationID); parser.addDependentArgumentSet(userPasswordFile, authenticationID); parser.addDependentArgumentSet(promptForUserPassword, authenticationID); // At most one of the revoke and revokeAll arguments may be provided. parser.addExclusiveArgumentSet(revoke, revokeAll); } /** * {@inheritDoc} */ @Override() public ResultCode doToolProcessing() { // Establish a connection to the Directory Server. final LDAPConnection conn; try { conn = getConnection(); } catch (final LDAPException le) { Debug.debugException(le); wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_CANNOT_CONNECT.get( StaticUtils.getExceptionMessage(le))); return le.getResultCode(); } try { // Get the authentication ID and static password to include in the // request. final String authID = authenticationID.getValue(); final byte[] staticPassword; if (userPassword.isPresent()) { staticPassword = StaticUtils.getBytes(userPassword.getValue()); } else if (userPasswordFile.isPresent()) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(userPasswordFile.getValue())); staticPassword = StaticUtils.getBytes(reader.readLine()); } catch (final Exception e) { Debug.debugException(e); wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_CANNOT_READ_PW_FROM_FILE.get( userPasswordFile.getValue().getAbsolutePath(), StaticUtils.getExceptionMessage(e))); return ResultCode.LOCAL_ERROR; } finally { if (reader != null) { try { reader.close(); } catch (final Exception e) { Debug.debugException(e); } } } } else if (promptForUserPassword.isPresent()) { try { getOut().print(INFO_GEN_TOTP_SECRET_ENTER_PW.get(authID)); staticPassword = PasswordReader.readPassword(); } catch (final Exception e) { Debug.debugException(e); wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_CANNOT_READ_PW_FROM_STDIN.get( StaticUtils.getExceptionMessage(e))); return ResultCode.LOCAL_ERROR; } } else { staticPassword = null; } // Create and send the appropriate request based on whether we should // generate or revoke a TOTP shared secret. ExtendedResult result; if (revoke.isPresent()) { final RevokeTOTPSharedSecretExtendedRequest request = new RevokeTOTPSharedSecretExtendedRequest(authID, staticPassword, revoke.getValue()); try { result = conn.processExtendedOperation(request); } catch (final LDAPException le) { Debug.debugException(le); result = new ExtendedResult(le); } if (result.getResultCode() == ResultCode.SUCCESS) { wrapOut(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, INFO_GEN_TOTP_SECRET_REVOKE_SUCCESS.get(revoke.getValue())); } else { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_REVOKE_FAILURE.get(revoke.getValue())); } } else if (revokeAll.isPresent()) { final RevokeTOTPSharedSecretExtendedRequest request = new RevokeTOTPSharedSecretExtendedRequest(authID, staticPassword, null); try { result = conn.processExtendedOperation(request); } catch (final LDAPException le) { Debug.debugException(le); result = new ExtendedResult(le); } if (result.getResultCode() == ResultCode.SUCCESS) { wrapOut(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, INFO_GEN_TOTP_SECRET_REVOKE_ALL_SUCCESS.get()); } else { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_REVOKE_ALL_FAILURE.get()); } } else { final GenerateTOTPSharedSecretExtendedRequest request = new GenerateTOTPSharedSecretExtendedRequest(authID, staticPassword); try { result = conn.processExtendedOperation(request); } catch (final LDAPException le) { Debug.debugException(le); result = new ExtendedResult(le); } if (result.getResultCode() == ResultCode.SUCCESS) { wrapOut(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, INFO_GEN_TOTP_SECRET_GEN_SUCCESS.get( ((GenerateTOTPSharedSecretExtendedResult) result). getTOTPSharedSecret())); } else { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_GEN_FAILURE.get()); } } // If the result is a failure result, then present any additional details // to the user. if (result.getResultCode() != ResultCode.SUCCESS) { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_RESULT_CODE.get( String.valueOf(result.getResultCode()))); final String diagnosticMessage = result.getDiagnosticMessage(); if (diagnosticMessage != null) { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_DIAGNOSTIC_MESSAGE.get(diagnosticMessage)); } final String matchedDN = result.getMatchedDN(); if (matchedDN != null) { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_MATCHED_DN.get(matchedDN)); } for (final String referralURL : result.getReferralURLs()) { wrapErr(0, StaticUtils.TERMINAL_WIDTH_COLUMNS, ERR_GEN_TOTP_SECRET_REFERRAL_URL.get(referralURL)); } } return result.getResultCode(); } finally { conn.close(); } } /** * {@inheritDoc} */ @Override() public LinkedHashMap getExampleUsages() { final LinkedHashMap examples = new LinkedHashMap<>(StaticUtils.computeMapCapacity(2)); examples.put( new String[] { "--hostname", "ds.example.com", "--port", "389", "--authID", "u:john.doe", "--promptForUserPassword", }, INFO_GEN_TOTP_SECRET_GEN_EXAMPLE.get()); examples.put( new String[] { "--hostname", "ds.example.com", "--port", "389", "--authID", "u:john.doe", "--userPasswordFile", "password.txt", "--revokeAll" }, INFO_GEN_TOTP_SECRET_REVOKE_ALL_EXAMPLE.get()); return examples; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy