src/main/java/com/trilead/ssh2/auth/AuthenticationManager.java
File `AuthenticationManager.java` has 418 lines of code (exceeds 250 allowed). Consider refactoring. package com.trilead.ssh2.auth; import com.trilead.ssh2.crypto.keys.Ed25519PrivateKey;import com.trilead.ssh2.crypto.keys.Ed25519PublicKey;import com.trilead.ssh2.signature.RSASHA256Verify;import com.trilead.ssh2.signature.RSASHA512Verify;import java.io.IOException;import java.security.KeyPair;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.interfaces.DSAPublicKey;import java.security.interfaces.ECPublicKey;import java.security.interfaces.RSAPublicKey;import java.util.Set;import java.util.Vector; import com.trilead.ssh2.InteractiveCallback;import com.trilead.ssh2.crypto.PEMDecoder;import com.trilead.ssh2.packets.PacketServiceAccept;import com.trilead.ssh2.packets.PacketServiceRequest;import com.trilead.ssh2.packets.PacketUserauthBanner;import com.trilead.ssh2.packets.PacketUserauthFailure;import com.trilead.ssh2.packets.PacketUserauthInfoRequest;import com.trilead.ssh2.packets.PacketUserauthInfoResponse;import com.trilead.ssh2.packets.PacketUserauthRequestInteractive;import com.trilead.ssh2.packets.PacketUserauthRequestNone;import com.trilead.ssh2.packets.PacketUserauthRequestPassword;import com.trilead.ssh2.packets.PacketUserauthRequestPublicKey;import com.trilead.ssh2.packets.Packets;import com.trilead.ssh2.packets.TypesWriter;import com.trilead.ssh2.signature.DSASHA1Verify;import com.trilead.ssh2.signature.ECDSASHA2Verify;import com.trilead.ssh2.signature.Ed25519Verify;import com.trilead.ssh2.signature.RSASHA1Verify;import com.trilead.ssh2.signature.SSHSignature;import com.trilead.ssh2.transport.MessageHandler;import com.trilead.ssh2.transport.TransportManager; /** * AuthenticationManager. * * @author Christian Plattner, plattner@trilead.com * @version $Id: AuthenticationManager.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $ */public class AuthenticationManager implements MessageHandler{ TransportManager tm; Vector packets = new Vector(); boolean connectionClosed = false; String banner; String[] remainingMethods = new String[0]; boolean isPartialSuccess = false; boolean authenticated = false; boolean initDone = false; public AuthenticationManager(TransportManager tm) { this.tm = tm; } boolean methodPossible(String methName) { if (remainingMethods == null) return false; Identical blocks of code found in 2 locations. Consider refactoring. for (int i = 0; i < remainingMethods.length; i++) { if (remainingMethods[i].compareTo(methName) == 0) return true; } return false; } byte[] deQueue() throws IOException { synchronized (packets) { while (packets.size() == 0) { if (connectionClosed) throw new IOException("The connection is closed.", tm.getReasonClosedCause()); try { packets.wait(); } catch (InterruptedException ign) { } } /* This sequence works with J2ME */ byte[] res = (byte[]) packets.firstElement(); packets.removeElementAt(0); return res; } } byte[] getNextMessage() throws IOException { while (true) { byte[] msg = deQueue(); if (msg[0] != Packets.SSH_MSG_USERAUTH_BANNER) return msg; PacketUserauthBanner sb = new PacketUserauthBanner(msg, 0, msg.length); banner = sb.getBanner(); } } public String[] getRemainingMethods(String user) throws IOException { initialize(user); return remainingMethods; } public boolean getPartialSuccess() { return isPartialSuccess; } Method `initialize` has 27 lines of code (exceeds 25 allowed). Consider refactoring. private boolean initialize(String user) throws IOException { if (!initDone) { tm.registerMessageHandler(this, 0, 255); PacketServiceRequest sr = new PacketServiceRequest("ssh-userauth"); tm.sendMessage(sr.getPayload()); PacketUserauthRequestNone urn = new PacketUserauthRequestNone("ssh-connection", user); tm.sendMessage(urn.getPayload()); byte[] msg = getNextMessage(); new PacketServiceAccept(msg, 0, msg.length); msg = getNextMessage(); initDone = true; Identical blocks of code found in 2 locations. Consider refactoring. if (msg[0] == Packets.SSH_MSG_USERAUTH_SUCCESS) { authenticated = true; tm.removeMessageHandler(this, 0, 255); return true; } Identical blocks of code found in 2 locations. Consider refactoring. if (msg[0] == Packets.SSH_MSG_USERAUTH_FAILURE) { PacketUserauthFailure puf = new PacketUserauthFailure(msg, 0, msg.length); remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); return false; } throw new IOException("Unexpected SSH message (type " + msg[0] + ")"); } return authenticated; } public boolean authenticatePublicKey(String user, char[] PEMPrivateKey, String password, SecureRandom rnd) throws IOException { KeyPair pair = PEMDecoder.decode(PEMPrivateKey, password); return authenticatePublicKey(user, pair, rnd); } public boolean authenticatePublicKey(String user, KeyPair pair, SecureRandom rnd) throws IOException { return authenticatePublicKey(user, pair, rnd, null); } public boolean authenticatePublicKey(String user, SignatureProxy signatureProxy) throws IOException { return authenticatePublicKey(user, null, null, signatureProxy); } Method `authenticatePublicKey` has 136 lines of code (exceeds 25 allowed). Consider refactoring.
Method `authenticatePublicKey` has a Cognitive Complexity of 34 (exceeds 5 allowed). Consider refactoring. public boolean authenticatePublicKey(String user, KeyPair pair, SecureRandom rnd, SignatureProxy signatureProxy) throws IOException { PrivateKey privateKey = null; PublicKey publicKey = null; if (pair != null) { privateKey = pair.getPrivate(); publicKey = pair.getPublic(); } if (signatureProxy != null) { publicKey = signatureProxy.getPublicKey(); } try { initialize(user); if (!methodPossible("publickey")) throw new IOException("Authentication method publickey not supported by the server at this stage."); if (publicKey instanceof DSAPublicKey) { SSHSignature s = DSASHA1Verify.get(); byte[] pk_enc = s.encodePublicKey(publicKey); byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, DSASHA1Verify.ID_SSH_DSS, pk_enc); byte[] ds_enc;Identical blocks of code found in 2 locations. Consider refactoring. if (signatureProxy != null) { ds_enc = signatureProxy.sign(msg, SignatureProxy.SHA1); } else { ds_enc = s.generateSignature(msg, privateKey, rnd); } PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, DSASHA1Verify.ID_SSH_DSS, pk_enc, ds_enc); tm.sendMessage(ua.getPayload()); } else if (publicKey instanceof RSAPublicKey) { byte[] pk_enc = RSASHA1Verify.get().encodePublicKey(publicKey); String pk_algorithm; // Servers support different hash algorithms for RSA keys // https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-12 Set<String> algsAccepted = tm.getExtensionInfo().getSignatureAlgorithmsAccepted(); final byte[] rsa_sig_enc; if (algsAccepted.contains(RSASHA512Verify.get().getKeyFormat())) { SSHSignature s = RSASHA512Verify.get(); pk_algorithm = s.getKeyFormat(); byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, pk_algorithm, pk_enc);Identical blocks of code found in 2 locations. Consider refactoring. if (signatureProxy != null) { rsa_sig_enc = signatureProxy.sign(msg, SignatureProxy.SHA512); } else { rsa_sig_enc = s.generateSignature(msg, privateKey, rnd); } } else if (algsAccepted.contains(RSASHA256Verify.ID_RSA_SHA_2_256)) { pk_algorithm = RSASHA256Verify.ID_RSA_SHA_2_256; byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, pk_algorithm, pk_enc); Identical blocks of code found in 2 locations. Consider refactoring. if (signatureProxy != null) { rsa_sig_enc = signatureProxy.sign(msg, SignatureProxy.SHA256); } else { rsa_sig_enc = RSASHA256Verify.get().generateSignature(msg, privateKey, rnd); } } else { pk_algorithm = "ssh-rsa"; byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, pk_algorithm, pk_enc);Identical blocks of code found in 2 locations. Consider refactoring. if (signatureProxy != null) { rsa_sig_enc = signatureProxy.sign(msg, SignatureProxy.SHA1); } else { // Server always accepts RSA with SHA1 rsa_sig_enc = RSASHA1Verify.get().generateSignature(msg, privateKey, rnd); } } PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, pk_algorithm, pk_enc, rsa_sig_enc); tm.sendMessage(ua.getPayload()); } else if (publicKey instanceof ECPublicKey) { ECPublicKey ecPublicKey = (ECPublicKey) publicKey; ECDSASHA2Verify verifier = ECDSASHA2Verify.getVerifierForKey(ecPublicKey); final String algo = verifier.getKeyFormat(); byte[] pk_enc = verifier.encodePublicKey(ecPublicKey); byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, algo, pk_enc); byte[] ec_sig_enc; if (signatureProxy != null) { ec_sig_enc = signatureProxy.sign(msg, ECDSASHA2Verify.getDigestAlgorithmForParams(ecPublicKey)); } else { ec_sig_enc = verifier.generateSignature(msg, privateKey, rnd); } PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, algo, pk_enc, ec_sig_enc); tm.sendMessage(ua.getPayload()); } else if (publicKey instanceof Ed25519PublicKey) { final String algo = Ed25519Verify.ED25519_ID; byte[] pk_enc = Ed25519Verify.get().encodePublicKey(publicKey); byte[] msg = this.generatePublicKeyUserAuthenticationRequest(user, algo, pk_enc); byte[] ed_sig_enc; if (signatureProxy != null) { ed_sig_enc = signatureProxy.sign(msg, SignatureProxy.SHA512); } else { Ed25519PrivateKey pk = (Ed25519PrivateKey) privateKey; ed_sig_enc = Ed25519Verify.get().generateSignature(msg, pk, rnd); } PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, algo, pk_enc, ed_sig_enc); tm.sendMessage(ua.getPayload()); } else { throw new IOException("Unknown public key type."); } byte[] ar = getNextMessage(); return isAuthenticationSuccessful(ar); } catch (IOException e) { e.printStackTrace(); tm.close(e, false); throw new IOException("Publickey authentication failed.", e); } } public boolean authenticateNone(String user) throws IOException { try { initialize(user); return authenticated; } catch (IOException e) { tm.close(e, false); throw new IOException("None authentication failed.", e); } } public boolean authenticatePassword(String user, String pass) throws IOException { try { initialize(user); if (!methodPossible("password")) throw new IOException("Authentication method password not supported by the server at this stage."); PacketUserauthRequestPassword ua = new PacketUserauthRequestPassword("ssh-connection", user, pass); tm.sendMessage(ua.getPayload()); byte[] ar = getNextMessage(); return isAuthenticationSuccessful(ar); } catch (IOException e) { tm.close(e, false); throw new IOException("Password authentication failed.", e); } } Method `authenticateInteractive` has 41 lines of code (exceeds 25 allowed). Consider refactoring.
Method `authenticateInteractive` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring. public boolean authenticateInteractive(String user, String[] submethods, InteractiveCallback cb) throws IOException { try { initialize(user); if (!methodPossible("keyboard-interactive")) throw new IOException( "Authentication method keyboard-interactive not supported by the server at this stage."); if (submethods == null) submethods = new String[0]; PacketUserauthRequestInteractive ua = new PacketUserauthRequestInteractive("ssh-connection", user, submethods); tm.sendMessage(ua.getPayload()); while (true) { byte[] ar = getNextMessage(); if (ar[0] == Packets.SSH_MSG_USERAUTH_INFO_REQUEST) { PacketUserauthInfoRequest pui = new PacketUserauthInfoRequest(ar, 0, ar.length); String[] responses; try { responses = cb.replyToChallenge(pui.getName(), pui.getInstruction(), pui.getNumPrompts(), pui .getPrompt(), pui.getEcho()); } catch (Exception e) { throw new IOException("Exception in callback.", e); } if (responses == null) throw new IOException("Your callback may not return NULL!"); PacketUserauthInfoResponse puir = new PacketUserauthInfoResponse(responses); tm.sendMessage(puir.getPayload()); continue; } return isAuthenticationSuccessful(ar); } } catch (IOException e) { tm.close(e, false); throw new IOException("Keyboard-interactive authentication failed.", e); } } public void handleMessage(byte[] msg, int msglen) throws IOException { synchronized (packets) { if (msg == null) { connectionClosed = true; } else { byte[] tmp = new byte[msglen]; System.arraycopy(msg, 0, tmp, 0, msglen); packets.addElement(tmp); } packets.notifyAll(); if (packets.size() > 5) { connectionClosed = true; throw new IOException("Error, peer is flooding us with authentication packets."); } } } private boolean isAuthenticationSuccessful(byte[] ar) throws IOException {Identical blocks of code found in 2 locations. Consider refactoring. if (ar[0] == Packets.SSH_MSG_USERAUTH_SUCCESS) { authenticated = true; tm.removeMessageHandler(this, 0, 255); return true; } Identical blocks of code found in 2 locations. Consider refactoring. if (ar[0] == Packets.SSH_MSG_USERAUTH_FAILURE) { PacketUserauthFailure puf = new PacketUserauthFailure(ar, 0, ar.length); remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); return false; } throw new IOException("Unexpected SSH message (type " + ar[0] + ")"); } private byte[] generatePublicKeyUserAuthenticationRequest(String user, String algorithm, byte[] publicKeyEncoded) { TypesWriter tw = new TypesWriter(); { byte[] H = tm.getSessionIdentifier(); tw.writeString(H, 0, H.length); tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); tw.writeString(user); tw.writeString("ssh-connection"); tw.writeString("publickey"); tw.writeBoolean(true); tw.writeString(algorithm); tw.writeString(publicKeyEncoded, 0, publicKeyEncoded.length); } return tw.getBytes(); }}