@@ -28,87 +28,125 @@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2828*/
2929package com .jcraft .jsch .agentproxy .sshj ;
3030
31+ import com .hierynomus .sshj .key .KeyAlgorithm ;
32+ import com .hierynomus .sshj .key .KeyAlgorithms ;
3133import com .jcraft .jsch .agentproxy .AgentProxy ;
3234import com .jcraft .jsch .agentproxy .Identity ;
3335import net .schmizz .sshj .common .Buffer ;
36+ import net .schmizz .sshj .common .KeyType ;
3437import net .schmizz .sshj .common .Message ;
3538import net .schmizz .sshj .common .SSHPacket ;
3639import net .schmizz .sshj .transport .TransportException ;
3740import net .schmizz .sshj .userauth .UserAuthException ;
3841import net .schmizz .sshj .userauth .method .AbstractAuthMethod ;
39- import org .slf4j .Logger ;
40- import org .slf4j .LoggerFactory ;
42+
43+ import java .io .IOException ;
44+ import java .util .LinkedList ;
45+ import java .util .Queue ;
4146
4247/**
4348 * An AuthMethod for sshj authentication with an agent.
4449 */
4550public class AuthAgent extends AbstractAuthMethod {
46- protected final Logger log = LoggerFactory .getLogger (getClass ());
4751
48- /** The AgentProxy instance that is used for signing */
52+ /**
53+ * The AgentProxy instance that is used for signing
54+ */
4955 private final AgentProxy agentProxy ;
50- /** The identity from Agent */
56+ /**
57+ * The identity from Agent
58+ */
5159 private final Identity identity ;
52- /** The identity's key algorithm */
60+ /**
61+ * The identity's key algorithm
62+ */
5363 private final String algorithm ;
5464 private final String comment ;
5565
66+ private Queue <KeyAlgorithm > available ;
67+
68+ private final KeyType keyType ;
69+
5670 public AuthAgent (AgentProxy agentProxy , Identity identity ) throws Buffer .BufferException {
5771 super ("publickey" );
5872 this .agentProxy = agentProxy ;
5973 this .identity = identity ;
6074 this .comment = new String (identity .getComment ());
6175 this .algorithm = (new Buffer .PlainBuffer (identity .getBlob ())).readString ();
76+ this .keyType = KeyType .fromString (algorithm );
77+ }
78+
79+ private KeyAlgorithm getPublicKeyAlgorithm (KeyType keyType ) throws TransportException {
80+ if (available == null ) {
81+ available = new LinkedList <>(params .getTransport ().getClientKeyAlgorithms (keyType ));
82+ }
83+ return available .peek ();
6284 }
6385
64- /** Internal use. */
6586 @ Override
66- public void handle ( Message cmd , SSHPacket buf )
67- throws UserAuthException , TransportException {
68- if ( cmd == Message . USERAUTH_60 )
69- sendSignedReq ();
70- else
71- super . handle ( cmd , buf ) ;
87+ public boolean shouldRetry () {
88+ if ( available != null ) {
89+ available . poll ();
90+ return ! available . isEmpty ();
91+ }
92+ return false ;
7293 }
7394
7495 protected SSHPacket putPubKey (SSHPacket reqBuf )
7596 throws UserAuthException {
76- reqBuf
77- .putString (algorithm )
78- .putBytes (identity .getBlob ()).getCompactData ();
79- return reqBuf ;
97+ try {
98+ KeyAlgorithm ka = getPublicKeyAlgorithm (keyType );
99+ if (ka != null ) {
100+ reqBuf .putString (ka .getKeyAlgorithm ()).putBytes (identity .getBlob ()).getCompactData ();
101+ return reqBuf ;
102+ }
103+ } catch (IOException ioe ) {
104+ throw new UserAuthException ("No KeyAlgorithm configured for key " + keyType , ioe );
105+ }
106+ throw new UserAuthException ("No KeyAlgorithm configured for key " + keyType );
80107 }
81108
82- private SSHPacket putSig (SSHPacket reqBuf )
83- throws UserAuthException {
109+ private int getSignFlags (KeyAlgorithm algorithm ) {
110+ if (keyType == KeyType .RSA ) {
111+ if (KeyAlgorithms .RSASHA256 ().getName ().equals (algorithm .getKeyAlgorithm ())) {
112+ return AgentProxy .SSH_AGENT_RSA_SHA2_256 ;
113+ }
114+ if (KeyAlgorithms .RSASHA512 ().getName ().equals (algorithm .getKeyAlgorithm ())) {
115+ return AgentProxy .SSH_AGENT_RSA_SHA2_512 ;
116+ }
117+ }
118+ return 0 ;
119+ }
120+
121+ protected SSHPacket putSig (SSHPacket reqBuf )
122+ throws TransportException {
84123 final byte [] dataToSign = new Buffer .PlainBuffer ()
85124 .putString (params .getTransport ().getSessionID ())
86125 .putBuffer (reqBuf ) // & rest of the data for sig
87126 .getCompactData ();
88127
89- reqBuf .putBytes (agentProxy .sign (identity .getBlob (), dataToSign ));
128+ reqBuf .putBytes (agentProxy .sign (identity .getBlob (), dataToSign , getSignFlags ( getPublicKeyAlgorithm ( keyType )) ));
90129
91130 return reqBuf ;
92131 }
93132
94133 /**
95- * Send SSH_MSG_USERAUTH_REQUEST containing the signature.
96- *
97- * @throws UserAuthException
98- * @throws TransportException
134+ * Internal use.
99135 */
100- private void sendSignedReq ()
136+ @ Override
137+ public void handle (Message cmd , SSHPacket buf )
101138 throws UserAuthException , TransportException {
102- params .getTransport ().write (putSig (buildReq (true )));
139+ if (cmd == Message .USERAUTH_60 )
140+ sendSignedReq ();
141+ else
142+ super .handle (cmd , buf );
103143 }
104144
105145 /**
106146 * Builds SSH_MSG_USERAUTH_REQUEST packet.
107147 *
108148 * @param signed whether the request packet will contain signature
109- *
110149 * @return the {@link SSHPacket} containing the request packet
111- *
112150 * @throws UserAuthException
113151 */
114152 private SSHPacket buildReq (boolean signed )
@@ -117,7 +155,21 @@ private SSHPacket buildReq(boolean signed)
117155 return putPubKey (super .buildReq ().putBoolean (signed ));
118156 }
119157
120- /** Builds a feeler request (sans signature). */
158+ /**
159+ * Send SSH_MSG_USERAUTH_REQUEST containing the signature.
160+ *
161+ * @throws UserAuthException
162+ * @throws TransportException
163+ */
164+ private void sendSignedReq ()
165+ throws UserAuthException , TransportException {
166+ log .debug ("Key acceptable, sending signed request" );
167+ params .getTransport ().write (putSig (buildReq (true )));
168+ }
169+
170+ /**
171+ * Builds a feeler request (sans signature).
172+ */
121173 @ Override
122174 protected SSHPacket buildReq ()
123175 throws UserAuthException {
0 commit comments