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

com.sshtools.common.ssh.components.ComponentManager Maven / Gradle / Ivy

/**
 * (c) 2002-2021 JADAPTIVE Limited. All Rights Reserved.
 *
 * This file is part of the Maverick Synergy Java SSH API.
 *
 * Maverick Synergy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Maverick Synergy 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Maverick Synergy.  If not, see .
 */
package com.sshtools.common.ssh.components;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;

import com.sshtools.common.logger.Log;
import com.sshtools.common.ssh.SecurityLevel;
import com.sshtools.common.ssh.SshException;
import com.sshtools.common.ssh.components.jce.JCEComponentManager;
import com.sshtools.common.util.IOUtils;

/**
 * 

* An abstract class that manages the components used by the SSH API. All * algorithm implementations are obtained through a single provider. One * concrete implementation is provided, the * {@link com.sshtools.common.ssh.components.jce.JCEComponentManager} that uses the * Java runtime JCE provider(s) algorithm implementations. *

* * @author Lee David Painter * */ public abstract class ComponentManager { private static boolean enableNoneCipher = false; private static boolean enableNoneMac = false; protected static boolean enableCbc = false; Set disabledAlgorithms = new HashSet(); Map>> cachedExternalComponents = new HashMap<>(); protected ComponentManager() { disabledAlgorithms.add("ssh-dss"); } public void disableAlgorithm(String algorithm) { disabledAlgorithms.add(algorithm); } public boolean isDisabled(String algorithm) { return disabledAlgorithms.contains(algorithm); } public void enableAlgorithm(String algorithm) { disabledAlgorithms.remove(algorithm); } public static boolean isEnableNoneCipher() { return enableNoneCipher; } public static void setEnableNoneCipher(boolean enableNoneCipher) { ComponentManager.enableNoneCipher = enableNoneCipher; } public static boolean isEnableNoneMac() { return enableNoneMac; } public static void setEnableNoneMac(boolean enableNoneCipher) { ComponentManager.enableNoneMac = enableNoneCipher; } public static void enableCBCCiphers() { enableCbc = true; } public static void disableCBCCiphers() { enableCbc = false; } protected static ComponentManager instance; ComponentFactory ssh1ciphersSC; ComponentFactory ssh2ciphersSC; ComponentFactory ssh1ciphersCS; ComponentFactory ssh2ciphersCS; ComponentFactory hmacsCS; ComponentFactory hmacsSC; ComponentFactory publickeys; ComponentFactory digests; static Object lock = new Object(); /** * Get the installed component manager. Don't want to initialize this at * class load time, so use a singleton instead. Initialized on the first * call to getInstance. * * @return ComponentManager */ public static ComponentManager getInstance() { synchronized (lock) { if (instance != null) { return instance; } try { instance = new JCEComponentManager(); instance.init(); return instance; } catch (Throwable e) { throw new RuntimeException( "Unable to locate a cryptographic provider", e); } } } public static ComponentManager getDefaultInstance() { return getInstance(); } public static void reset() { synchronized (lock) { instance = null; getInstance(); } } protected void init() throws SshException { if(Log.isInfoEnabled()) Log.info("Initializing SSH2 server->client ciphers"); ssh2ciphersSC = new ComponentFactory(this); initializeSsh2CipherFactory(ssh2ciphersSC); if (enableNoneCipher) { ssh2ciphersSC.add("none", NoneCipher.class); if(Log.isInfoEnabled()) Log.info(" none will be a supported cipher"); } if(Log.isInfoEnabled()) Log.info("Initializing SSH2 client->server ciphers"); ssh2ciphersCS = new ComponentFactory(this); initializeSsh2CipherFactory(ssh2ciphersCS); if (enableNoneCipher) { ssh2ciphersCS.add("none", NoneCipher.class); if(Log.isInfoEnabled()) Log.info(" none will be a supported cipher"); } if(Log.isInfoEnabled()) Log.info("Initializing SSH2 server->client HMACs"); hmacsSC = new ComponentFactory(this); initializeHmacFactory(hmacsSC); if (enableNoneMac) { hmacsSC.add("none", NoneHmac.class); if(Log.isInfoEnabled()) Log.info(" none will be a supported hmac"); } if(Log.isInfoEnabled()) Log.info("Initializing SSH2 client->server HMACs"); hmacsCS = new ComponentFactory(this); initializeHmacFactory(hmacsCS); if (enableNoneMac) { hmacsCS.add("none", NoneHmac.class); if(Log.isInfoEnabled()) Log.info(" none will be a supported hmac"); } if(Log.isInfoEnabled()) Log.info("Initializing public keys"); publickeys = new ComponentFactory(this); initializePublicKeyFactory(publickeys); if(Log.isInfoEnabled()) Log.info("Initializing digests"); digests = new ComponentFactory(this); initializeDigestFactory(digests); if(Log.isInfoEnabled()) Log.info("Initializing Secure Random Number Generator"); getRND().nextInt(); } /** * Initialize the SSH2 cipher factory. These ciphers are exclusively used by * the SSH2 implementation. * * @param ciphers */ protected abstract void initializeSsh2CipherFactory(ComponentFactory ciphers); /** * Initialize the SSH2 HMAC factory. * * @param hmacs */ protected abstract void initializeHmacFactory(ComponentFactory hmacs); /** * Initialize the public key factory. * * @param publickeys */ protected abstract void initializePublicKeyFactory( ComponentFactory publickeys); /** * Initialize the digest factory. * * @param digests */ protected abstract void initializeDigestFactory(ComponentFactory digests); /** * Overide the installed component manager with an alternative * implementation. * * @param instance */ public static void setInstance(ComponentManager instance) { synchronized (lock) { ComponentManager.instance = instance; } } /** * The supported SSH1 ciphers. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedSsh1CiphersSC() { return (ComponentFactory) ssh1ciphersSC.clone(); } /** * The supported SSH1 ciphers. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedSsh1CiphersCS() { return (ComponentFactory) ssh1ciphersCS.clone(); } /** * The supported SSH2 ciphers. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedSsh2CiphersSC() { return (ComponentFactory) ssh2ciphersSC.clone(); } /** * The supported SSH2 ciphers. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedSsh2CiphersCS() { return (ComponentFactory) ssh2ciphersCS.clone(); } /** * The supported SSH2 Hmacs. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedHMacsSC() { return (ComponentFactory) hmacsSC.clone(); } /** * The supported SSH2 Hmacs. * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedHMacsCS() { return (ComponentFactory) hmacsCS.clone(); } /** * The supported public keys * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedPublicKeys() { return (ComponentFactory) publickeys.clone(); } /** * The supported digests * * @return AbstractComponentFactory */ @SuppressWarnings("unchecked") public ComponentFactory supportedDigests() { return (ComponentFactory) digests.clone(); } /** * Generate an RSA public/private pair. * * @param bits * @param version * @return SshKeyPair * @throws SshException */ public abstract SshKeyPair generateRsaKeyPair(int bits, int version) throws SshException; /** * Generate a new ECDSA key pair. * * @param bits * @return * @throws SshException */ public abstract SshKeyPair generateEcdsaKeyPair(int bits) throws SshException; public abstract SshKeyPair generateEd25519KeyPair() throws SshException; /** * Create an instance of an RSA public key. * * @param modulus * @param publicExponent * @param version * @return SshRsaPublicKey * @throws SshException */ public abstract SshRsaPublicKey createRsaPublicKey(BigInteger modulus, BigInteger publicExponent) throws SshException; /** * Create an instance of an SSH2 RSA public key. * * @return SshRsaPublicKey * @throws SshException */ public abstract SshRsaPublicKey createSsh2RsaPublicKey() throws SshException; /** * Create an instance of an RSA private key. * * @param modulus * @param privateExponent * @return SshRsaPrivateKey * @throws SshException */ public abstract SshRsaPrivateKey createRsaPrivateKey(BigInteger modulus, BigInteger privateExponent) throws SshException; /** * Create an instance of an RSA co-effecient private key. * * @param modulus * @param publicExponent * @param privateExponent * @param primeP * @param primeQ * @param crtCoefficient * @return SshRsaPrivateCrtKey * @throws SshException */ public abstract SshRsaPrivateCrtKey createRsaPrivateCrtKey( BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger primeP, BigInteger primeQ, BigInteger crtCoefficient) throws SshException; /** * Create an instance of an RSA co-efficent private key. * * @param modulus * @param publicExponent * @param privateExponent * @param primeP * @param primeQ * @param primeExponentP * @param primeExponentQ * @param crtCoefficient * @return SshRsaPrivateCrtKey * @throws SshException */ public abstract SshRsaPrivateCrtKey createRsaPrivateCrtKey( BigInteger modulus, BigInteger publicExponent, BigInteger privateExponent, BigInteger primeP, BigInteger primeQ, BigInteger primeExponentP, BigInteger primeExponentQ, BigInteger crtCoefficient) throws SshException; /** * Generate a new DSA public/private key pair. * * @param bits * @return SshKeyPair * @throws SshException */ public abstract SshKeyPair generateDsaKeyPair(int bits) throws SshException; /** * Create an instance of a DSA public key. * * @param p * @param q * @param g * @param y * @return SshDsaPublicKey * @throws SshException */ public abstract SshDsaPublicKey createDsaPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y) throws SshException; /** * Create an uninitialized instance of a DSA public key * * @return SshDsaPublicKey */ public abstract SshDsaPublicKey createDsaPublicKey(); /** * Create an instance of a DSA private key. * * @param p * @param q * @param g * @param x * @param y * @return SshDsaPrivateKey * @throws SshException */ public abstract SshDsaPrivateKey createDsaPrivateKey(BigInteger p, BigInteger q, BigInteger g, BigInteger x, BigInteger y) throws SshException; /** * Get the secure random number generator. * * @return SshSecureRandomGenerator * @throws SshException */ public abstract SshSecureRandomGenerator getRND() throws SshException; public Digest getDigest(String name) throws SshException { return digests.getInstance(name); } @SuppressWarnings("unchecked") public void loadExternalComponents(String componentFile, ComponentFactory componentFactory) { Map> cachedComponents = cachedExternalComponents.get(componentFile); if(Objects.isNull(cachedComponents)) { cachedComponents = new HashMap<>(); try { Enumeration e = getClass().getClassLoader().getResources(componentFile); while(e.hasMoreElements()) { InputStream in = null; try { in = e.nextElement().openStream(); if(Objects.isNull(in)) { Log.info("No further components to add"); return; } Properties properties = new Properties(); properties.load(in); for(Object alg : properties.keySet()) { String clz = properties.getProperty(alg.toString()); try { Class componenetClz = (Class) Class.forName(clz); cachedComponents.put(alg.toString(), componenetClz); } catch (ClassNotFoundException ex) { Log.error("Cannot find class {} for algorithm {}", clz, alg); } } cachedExternalComponents.put(componentFile, cachedComponents); } catch(IOException ex) { Log.error("Error processing {}", ex, componentFile); } finally { IOUtils.closeStream(in); } } } catch(Throwable ex) { Log.error("Error processing {}", ex, componentFile); } } for(Map.Entry> e : cachedComponents.entrySet()) { componentFactory.add(e.getKey(), (Class) e.getValue()); } } public void setMinimumSecurityLevel(SecurityLevel securityLevel) throws SshException { if(Log.isInfoEnabled()) { Log.info("Configuring {} Security", securityLevel.name()); } setMinimumSecurityLevel(securityLevel, ssh2ciphersCS, "Client->Server Ciphers"); setMinimumSecurityLevel(securityLevel, ssh2ciphersSC, "Server->Client Ciphers"); setMinimumSecurityLevel(securityLevel, hmacsCS, "Client->Server Macs"); setMinimumSecurityLevel(securityLevel, hmacsSC, "Server->Client Macs"); setMinimumSecurityLevel(securityLevel, publickeys, "Public Keys"); // if (clientKeyexchanges.hasComponents()) { // setMinimumSecurityLevel(securityLevel, clientKeyexchanges, "Client->Server KEX"); // } // if (serverKeyexchanges.hasComponents()) { // setMinimumSecurityLevel(securityLevel, serverKeyexchanges, "Server->Client KEX"); // } } private void setMinimumSecurityLevel(SecurityLevel securityLevel, ComponentFactory componentFactory, String name) throws SshException { if(Log.isInfoEnabled()) { Log.info("Configuring {}", name); } componentFactory.configureSecurityLevel(securityLevel); if(Log.isInfoEnabled()) { Log.info(componentFactory.list("")); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy