Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssh certificate authentication fails #153

Closed
WellRedPandit opened this issue Oct 16, 2014 · 26 comments
Closed

ssh certificate authentication fails #153

WellRedPandit opened this issue Oct 16, 2014 · 26 comments

Comments

@WellRedPandit
Copy link

sshj fails where openssh succeeds without a password using two files private-key and private-key-cert.pub. What am I coding wrongly with sshj?

(if sshj does not support certificate authentication, am willing to contribute, if pointed in the right direction...)

Test

object Sshj {
  def ping() = {
    val ssh = new SSHClient
    ssh.loadKnownHosts()
    ssh.connect("555.16.13.210", 26)
    try {
      ssh.authPublickey("root","~/.ssh/private-key")
      val session = ssh.startSession()
      try {
        val cmd = session.exec("ping -c 1 google.com")
        println(IOUtils.readFully(cmd.getInputStream()).toString())
        cmd.join(5, TimeUnit.SECONDS)
        println("\n** exit status: " + cmd.getExitStatus())
      } finally {
        session.close()
      }
    } finally {
      ssh.disconnect()
    }
  }
}

Scala REPL

scala> Sshj.ping
[INFO ] [15:05:15.179] [run-main-4] [n.schmizz.sshj.common.SecurityUtils] BouncyCastle already registered as a JCE provider
[WARN ] [15:05:15.195] [run-main-4] [net.schmizz.sshj.DefaultConfig] Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy
[INFO ] [15:05:15.232] [run-main-4] [n.s.sshj.transport.TransportImpl] Client identity string: SSH-2.0-SSHJ_0_9_0
[INFO ] [15:05:15.236] [run-main-4] [n.s.sshj.transport.TransportImpl] Server identity string: SSH-2.0-OpenSSH_5.9
[DEBUG] [15:05:15.237] [run-main-4] [net.schmizz.concurrent.Promise] Setting <<kex done>> to `null`
[DEBUG] [15:05:15.237] [run-main-4] [n.s.sshj.transport.KeyExchanger] Sending SSH_MSG_KEXINIT
[DEBUG] [15:05:15.248] [run-main-4] [net.schmizz.concurrent.Promise] Setting <<kexinit sent>> to `SOME`
[DEBUG] [15:05:15.249] [run-main-4] [net.schmizz.concurrent.Promise] Awaiting <<kex done>>
[DEBUG] [15:05:15.249] [reader] [n.s.sshj.transport.KeyExchanger] Received SSH_MSG_KEXINIT
[DEBUG] [15:05:15.251] [reader] [n.s.sshj.transport.KeyExchanger] Negotiated algorithms: [ kex=diffie-hellman-group14-sha1; sig=ssh-rsa; c2sCipher=aes128-ctr; s2cCipher=aes128-ctr; c2sMAC=hmac-sha1; s2cMAC=hmac-sha1; c2sComp=none; s2cComp=none ]
[DEBUG] [15:05:15.290] [reader] [net.schmizz.sshj.transport.kex.DHG14] Sending SSH_MSG_KEXDH_INIT
[DEBUG] [15:05:15.301] [reader] [n.s.sshj.transport.KeyExchanger] Received kex followup data
[DEBUG] [15:05:15.301] [reader] [net.schmizz.sshj.transport.kex.DHG14] Received SSH_MSG_KEXDH_REPLY
[DEBUG] [15:05:15.326] [reader] [n.s.sshj.transport.KeyExchanger] Trying to verify host key with net.schmizz.sshj.transport.verification.OpenSSHKnownHosts@576882e3
[DEBUG] [15:05:15.327] [reader] [n.s.sshj.transport.KeyExchanger] Sending SSH_MSG_NEWKEYS
[DEBUG] [15:05:15.327] [reader] [n.s.sshj.transport.KeyExchanger] Received SSH_MSG_NEWKEYS
[DEBUG] [15:05:15.328] [reader] [net.schmizz.concurrent.Promise] Setting <<kexinit sent>> to `null`
[DEBUG] [15:05:15.328] [reader] [net.schmizz.concurrent.Promise] Setting <<kex done>> to `SOME`
[DEBUG] [15:05:15.328] [run-main-4] [net.schmizz.sshj.SSHClient] Key exchange took 0.091 seconds
[DEBUG] [15:05:15.328] [run-main-4] [net.schmizz.sshj.SSHClient] Attempting to load key from: ~/.ssh/private-key
[DEBUG] [15:05:15.342] [run-main-4] [net.schmizz.concurrent.Promise] Setting <<service accept>> to `null`
[DEBUG] [15:05:15.343] [run-main-4] [n.s.sshj.transport.TransportImpl] Sending SSH_MSG_SERVICE_REQUEST for ssh-userauth
[DEBUG] [15:05:15.343] [run-main-4] [net.schmizz.concurrent.Promise] Awaiting <<service accept>>
[DEBUG] [15:05:15.373] [reader] [net.schmizz.concurrent.Promise] Setting <<service accept>> to `SOME`
[DEBUG] [15:05:15.374] [run-main-4] [n.s.sshj.transport.TransportImpl] Setting active service to ssh-userauth
[DEBUG] [15:05:15.375] [run-main-4] [net.schmizz.concurrent.Promise] Setting <<authenticated>> to `null`
[DEBUG] [15:05:15.375] [run-main-4] [n.schmizz.sshj.userauth.UserAuthImpl] Trying `publickey` auth...
[DEBUG] [15:05:15.376] [run-main-4] [n.s.s.userauth.method.AuthPublickey] Attempting authentication using PKCS8KeyFile{resource=[PrivateKeyFileResource] ~/.ssh/private-key}
[DEBUG] [15:05:15.437] [run-main-4] [net.schmizz.concurrent.Promise] Awaiting <<authenticated>>
[DEBUG] [15:05:15.441] [reader] [net.schmizz.concurrent.Promise] Setting <<authenticated>> to `false`
[DEBUG] [15:05:15.442] [run-main-4] [n.schmizz.sshj.userauth.UserAuthImpl] `publickey` auth failed
[INFO ] [15:05:15.443] [run-main-4] [n.s.sshj.transport.TransportImpl] Disconnected - BY_APPLICATION
[DEBUG] [15:05:15.443] [run-main-4] [n.schmizz.sshj.userauth.UserAuthImpl] Notified of net.schmizz.sshj.transport.TransportException: [BY_APPLICATION] Disconnected
[DEBUG] [15:05:15.443] [run-main-4] [n.s.sshj.transport.TransportImpl] Sending SSH_MSG_DISCONNECT: reason=[BY_APPLICATION], msg=[]
[DEBUG] [15:05:15.443] [run-main-4] [net.schmizz.concurrent.Promise] Setting <<transport close>> to `SOME`
[DEBUG] [15:05:15.444] [reader] [net.schmizz.sshj.transport.Reader] Stopping
net.schmizz.sshj.userauth.UserAuthException: Exhausted available authentication methods
  at net.schmizz.sshj.SSHClient.auth(SSHClient.java:217)
  at net.schmizz.sshj.SSHClient.authPublickey(SSHClient.java:316)
  at net.schmizz.sshj.SSHClient.authPublickey(SSHClient.java:365)
  at Sshj$.ping(basics.scala:59)
  ... 43 elided

OpenSSH

> ssh -v -p 26 -i ~/.ssh/private-key [email protected]
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to 555.16.13.210 [555.16.13.210] port 26.
debug1: Connection established.
debug1: identity file ~/.ssh/private-key type -1
debug1: ssh_rsa_verify: signature correct
debug1: identity file ~/.ssh/private-key-cert type 5
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.9
debug1: match: OpenSSH_5.9 pat OpenSSH_5* compat 0x0c000000
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 1c:e0:42:f3:af:6b:15:59:1c:19:8d:44:c8:f2:99:fb
debug1: Host '[555.16.13.210]:26' is known and matches the RSA host key.
debug1: Found key in ~/.ssh/known_hosts:1
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Offering RSA-CERT public key: ~/.ssh/private-key
debug1: Server accepts key: pkalg [email protected] blen 1150
debug1: ssh_rsa_verify: signature correct
debug1: key_parse_private2: missing begin marker
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
Authenticated to 555.16.13.210 ([555.16.13.210]:26).
debug1: channel 0: new [client-session]
debug1: Requesting [email protected]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
Last login: Thu Oct 16 14:47:53 2014 from 192.168.225.2
Unauthorized access to this system is not permitted.
User activity may be logged for auditing or other purposes.
UPS_FAKE=2
[14:48:15] #
@hierynomus
Copy link
Owner

Is it a PKCS8 format key file? Look at https://github.com/hierynomus/sshj/blob/master/src/main/java/net/schmizz/sshj/userauth/keyprovider/PKCS8KeyFile.java and associated test, and try load your data in the test, that would be a good first step.

@WellRedPandit
Copy link
Author

Thank you for looking into this! Otherwise - way over my head...

I don't think it's a PKCS8 format key file issue, but I did as you suggested: the type test passes, the keys test fails (I pushed my tests into this repo).

I believe this to be a certificate authentication issue, because for openssh to succeed (i.e. to log in or run a remote command without a password) it has to have two files in ~/.ssh:
private-v2-key
private-v2-key-cert.pub
and I can't find a way to tell sshj to use both...

Please do let me know if there is anything else I can do to help in troubleshooting this...

@hierynomus
Copy link
Owner

Could you also provide a sample certificate, or provide the commandline to build one with?

@WellRedPandit
Copy link
Author

Will try. I am just a user (given a key and a certificate; will try to hunt down those in the know).

@dkocher
Copy link
Contributor

dkocher commented Jan 13, 2015

For reference we are tracking issue #8371 that sounds similar.

@hierynomus
Copy link
Owner

@dkocher Sounds pretty similar indeed... From what I gather in that issue, you also have no key/certificate yet to reproduce this?

@dkocher
Copy link
Contributor

dkocher commented Jan 13, 2015

@hierynomus No, unfortunately not.

@WellRedPandit
Copy link
Author

@hierynomus To clarify: I do of course have a key and a certificate, but, unfortunately, can't share...

@hierynomus
Copy link
Owner

@WellRedPandit I got that 😉. But I would like to get my hands on a sample certificate that shows this behaviour so that we can fix it. Or the ssh-keygen commandline to obtain one.

@WellRedPandit
Copy link
Author

Got it. Will do my best. Our sysadmins are not very talkative :-(

@hierynomus
Copy link
Owner

@WellRedPandit Could you give me the header of both files? I mean the part between the dashes if you view the contents. From that I might already be able to deduce a lot on what's going wrong.

@WellRedPandit
Copy link
Author

@hierynomus Did ask. Lightning fast response: "Under no circumstances!!!" - sorry...
Will share what I can as soon as I know it myself.

@hierynomus
Copy link
Owner

The header of both files contains no private data, it merely indicates what kind of key it is, i.e.:

-----BEGIN RSA PRIVATE KEY-----

@WellRedPandit
Copy link
Author

This is what I see:

...-v2-key starts with:
-----BEGIN RSA PRIVATE KEY-----

...-v2-key-cert.pub starts with:
[email protected]

@hierynomus
Copy link
Owner

Ok, thx! Now I can finally find some stuff online using that string. You're using this method: http://blog.habets.pp.se/2011/07/OpenSSH-certificates

I need to look into that. It's pretty OpenSSH specific I think.

@WellRedPandit
Copy link
Author

Thanks for the link! Regrettable though... I hoped it was something more widespread and would be appreciated by many when added to your library... Anyway, if you do decide to give it a go, I'd be happy to test or otherwise help...

@hierynomus hierynomus added this to the v0.12.0 milestone Jan 23, 2015
@hierynomus hierynomus self-assigned this Jan 23, 2015
@hierynomus hierynomus removed this from the v0.12.0 milestone Jun 17, 2015
@graven
Copy link

graven commented Nov 9, 2015

Hey @hierynomus — wondering if you were doing any research into this matter. This is indeed an OpenSSH-specific feature, but amazingly powerful for any kind of secure automation. I did not see any certificate-based authentication methods in sshj code, what are your thoughts on adding this?

@hierynomus
Copy link
Owner

Currently not doing any specific research into adding it. Though it should definitely be possible to add.
As always PRs are welcome ;)

@Pratappatil1992
Copy link

Hello @hierynomus , I am facing issue while authenticate using Key file below is my code and stack trace of error. please help me out or tell me What am I coding wrongly with sshj?

Using below maven dependancy

        <dependency>
            <groupId>com.hierynomus</groupId>
            <artifactId>sshj</artifactId>
            <version>0.15.0</version>
        </dependency>

CODE

package com.infiverve.flint.ssh2;

import net.schmizz.sshj.DefaultConfig;
import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.common.IOUtils;
import net.schmizz.sshj.connection.channel.direct.Session;
import net.schmizz.sshj.connection.channel.direct.Session.Command;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
import java.io.IOException;

/** This examples demonstrates how a remote command can be executed. */
public class Test{

    public static void main(String... args)
            throws IOException {

            Session session = null;
            SSHClient sshClient = null;
            try {
                DefaultConfig defaultConfig = new DefaultConfig();
                sshClient = new SSHClient(defaultConfig);
                sshClient.addHostKeyVerifier(new PromiscuousVerifier());
                sshClient.connect("ec2-xx.xx.xx.xx.compute-1.amazonaws.com", 22);
                sshClient.setConnectTimeout(60000);
                sshClient.setTimeout(60000);
                KeyProvider loadKeys;
                loadKeys = sshClient.loadKeys("/home/pratap/flintcloud-test.pem");

                sshClient.authPublickey("ubuntu",loadKeys);
                session = sshClient.startSession();
                final Command cmd = session.exec("pwd");
                String result = IOUtils.readFully(cmd.getInputStream()).toString(); 
                System.out.println("RESULT "+result);

                session.close();

        } finally {
            sshClient.disconnect();
            session.close();
        }
    }

}

and stack trace of above code it is

net.schmizz.sshj.common.SSHException: No provider available for PKCS8 key file
    at net.schmizz.sshj.SSHClient.loadKeys(SSHClient.java:531)
    at net.schmizz.sshj.SSHClient.loadKeys(SSHClient.java:487)
    at com.infiverve.flint.ssh2.Ssh2ServiceHandler.onRequest(Ssh2ServiceHandler.java:83)
    at com.infiverve.flint.sdk.FlintConnectorRequestHandlerBase.handle(FlintConnectorRequestHandlerBase.java:48)
    at com.infiverve.flint.sdk.FlintConnectorRequestHandlerBase.handle(FlintConnectorRequestHandlerBase.java:9)
    at io.vertx.core.eventbus.impl.EventBusImpl$HandlerRegistration.handle(EventBusImpl.java:1108)
    at io.vertx.core.eventbus.impl.EventBusImpl.lambda$doReceive$189(EventBusImpl.java:755)
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$15(ContextImpl.java:314)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:357)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
    at java.lang.Thread.run(Thread.java:745)

@hierynomus
Copy link
Owner

Hi @Pratappatil1992, I actually don't know, the code looks fine. It's weird that it complains that it cannot find a provider for the PKCS8 key file, as that provider should be loaded for the DefaultConfig in your example. However the stacktrace you're showing does not come from the code snippet that you're showing. Are you sure that in your real code you're also instantiating with the DefaultConfig?

@Pratappatil1992
Copy link

Hello @hierynomus , Thanks for your respond, yes you are right the code snippet and stack-trace are different but I am using same code from where that stack-trace come and I also instantiating with the DefaultConfig in my real code.

@hierynomus
Copy link
Owner

@Pratappatil1992 Could you create a unit test using the SshFixture and a sample key file that exhibits the same behaviour. Then I'd be happy to fix it :)

@Pratappatil1992
Copy link

Okay @hierynomus , I will create unit test using SshFixture and let you know about it as soon as possible..

@kwart
Copy link

kwart commented Apr 20, 2016

We see sometimes the "Exhausted available authentication methods" exception when working with OpenStack through JClouds library. I've reported a new JClouds issue with more details in it: https://issues.apache.org/jira/browse/JCLOUDS-1103

@deeTEEcee
Copy link

deeTEEcee commented Aug 10, 2016

testing something similar to this, just that mine requires a password but just says "Exhausted available authentication methods"

hierynomus pushed a commit that referenced this issue Apr 14, 2017
#319)

* Add support for authentication with DSA & RSA user certificates (#153)

Updates:

- KeyType.java - add support for two certificate key types
    [email protected]
    [email protected]

- Buffer.java - allow uint64s that overflow Long.MAX_VALUE, otherwise
  we break on certificates with serial numbers greater Long.MAX_VALUE

- OpenSSHKeyFile, KeyProviderUtil - prefer public key files that end
  "-cert.pub" if they exist

Added new class Certificate, which represents certificate key

Reference:

https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD

* Use BigInteger for certificate serial numbers, address Codacy issues

* Address code review concerns
@hierynomus
Copy link
Owner

SHould be fixed with the merge of #319

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants