# Set up an SSH client in 5 minutes

SSHD is designed to easily allow setting up and using an SSH client in a few simple steps. The client needs to be configured
and then started before it can be used to connect to an SSH server. There are a few simple steps for creating a client
instance - for more details refer to the `SshClient` class.

## Creating an instance of the `SshClient` class

This is simply done by calling

```java

SshClient client = SshClient.setUpDefaultClient();

```

The call will create an instance with a default configuration suitable for most use cases - including ciphers,
compression, MACs, key exchanges, signatures, etc... If your code requires some special configuration, one can
look at the code for `setUpDefaultClient` and `checkConfig` as a reference for available options and configure
the SSH client the way you need.

## Set up client side security

The SSH client contains some security related configuration that one needs to consider

### `ServerKeyVerifier`

`client.setServerKeyVerifier(...);` sets up the server key verifier. As part of the SSH connection initialization
protocol, the server proves its "identity" by presenting a public key. The client can examine the key (e.g., present
it to the user via some UI) and decide whether to trust the server and continue with the connection setup. By default
the client is initialized with an `AcceptAllServerKeyVerifier` that simply logs a warning that an un-verified server
key was accepted. There are other out-of-the-box verifiers available in the code:

* `RejectAllServerKeyVerifier` - rejects all server key - usually used in tests or as a fallback verifier if none
of it predecesors validated the server key

* `RequiredServerKeyVerifier` - accepts only **one** specific server key (similar to certificate pinning for SSL)

* `KnownHostsServerKeyVerifier` - uses the [known_hosts](https://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#Public_Keys_from_other_Hosts_.E2.80.93_.7E.2F.ssh.2Fknown_hosts)
file to validate the server key. One can use this class + some existing code to **update** the file when new servers are detected and their keys are accepted.

Of course, one can implement the verifier in whatever other manner is suitable for the specific code needs.

### `ClientIdentityLoader/KeyPairProvider`

One can set up the public/private keys to be used in case a password-less authentication is needed. By default, the client is configured to automatically
detect and use the identity files residing in the user's *~/.ssh* folder (e.g., *id_rsa*, *id_ecdsa*) and present them as part of the authentication process.
**Note:** if the identity files are encrypted via a password, one must configure a `FilePasswordProvider` so that the code can decrypt them before using
and presenting them to the server as part of the authentication process. Reading key files in PEM format (including encrypted ones) is supported by default
for the standard keys and formats. Using additional non-standard special features requires that the [Bouncy Castle](https://www.bouncycastle.org/) supporting
artifacts be available in the code's classpath.

#### Loading key files

In order to use password-less authentication the user needs to provide one or more `KeyPair`-s that are used to "prove" the client's identity for
the server. The code supports most if not all of the currently used key file formats. See `SshKeyDumpMain` class for example of how to load files - basically:

```java
    KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser();
    Collection<KeyPair> keys = loader.loadKeyPairs(null, filePath, passwordProvider);
```

For *PUTTY* key files one needs to include the *sshd-putty* module and use a different loader:

```java
    Collection<KeyPair> keys = PuttyKeyUtils.DEFAULT_INSTANCE.loadKeyPairs(null, filePath, passwordProvider);
```

**Note:** reminder - a user's "identity" is the file that contains the **private** key - there is no need to provide the public key file since the
private key either already contains the public key in it, or it can be easily calculated from the private one.

Once the keys are loaded, one simply needs to provide them to the client session:

```java
    try (ClientSession session = ...estblish initial session...) {
        for (KeyPair kp : keys) {
            session.addKeyIdentity(kp);
        }
        
        session.auth().await(...);
    }
```

Instead of doing this on every session, it is possible to load the keys only **once** and then wrap them inside a `KeyIdentityProvider`
that is setup during *SshClient* setup:

```java
    Collection<KeyPair> keys = ...load the keys ...
    SshClient client = ...setup client...
    client.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keys));
    client.start();
```

The provided keys will be used for **all* the sessions - *Note:*

* One can **add** key identities to specific sessions.

* A similar effect can be achiveved for **passwords**  by registering a `PasswordIdentityProvider` with the *SshClient*, and
thus forego the need to provide the password repeatedly for each session. In this context, one can go even one step forward
and provide a **combined** `AuthenticationIdentitiesProvider` that provides **both** passwords and key pairs. Both type of providers
are invoked with the established `SessionContext` so the user can actually pick which mechanism to use, what password/key to
use according to the server's identity.

#### Providing passwords for encrypted key files

The `FilePasswordProvider` is required for all private key files that are encrypted and being loaded (not just the "identity" ones). If the user
knows ahead of time that the file being currently decoded is not encrypted, a *null* provider may be used (if the file turns out to be encrypted
though an exception will be thrown in this case).

The `FilePasswordProvider`has support for a **retry mechanism** via its `handleDecodeAttemptResult`. When the code detects an encrypted private key,
it will start a loop where it prompts for the password, attempts to decode the key using the provided password and then informs the provider of
the outcome - success or failure. If failure is signaled, then the provider can decide whether to retry using a new password, abort (with exception)
or ignore. If the provider chooses to ignore the failure, then the code will make a best effort to proceed without the (undecoded) key.

The invoked methods are provided with a `NamedResource` that provides an indication of the key source "name" that is being attempted. This name
can be used in order to prompt the user interactively and provide a useful "hint" as to the password that needs to be provided. Furthermore, the
vast majority of the provided `NamedResource`-s also implement `IoResource` - which means that the code can find out what type of resource
is being attempted - e.g., a file [Path](https://docs.oracle.com/javase/8/docs/api/index.html?java/nio/file/Path.html),
a [URL](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html), a [URI](https://docs.oracle.com/javase/8/docs/api/java/net/URI.html),
etc. - and modify it's behavior accordingly.

#### OpenSSH file format support

The code supports [OpenSSH](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?rev=1.1&content-type=text/x-cvsweb-markup)
formatted files without any specific extra artifacts (although for reading _ed25519_ keys one needs to add the _EdDSA_ support artifacts). For
**encrypted** files only the the `bcrypt` key derivation function (KDF) is [currently supported](https://issues.apache.org/jira/browse/SSHD-708).
In this context, the maximum allowed number of rounds has been set to ~255 in order to protect the decryption process from
malformed or malicious data. However, since the protocol allows for 2^31 values, it is possible to modify the default by
calling `BCryptKdfOptions#setMaxAllowedRounds()` **programmatically** at any time - please note that

* The setting is **global** - i.e., affects all decryption attempts from then on and not just for the current SSH session or thread.

* The setting value is never allowed to be non-positive - any attempt to set such a value programmatically
throws an exception.

The usual _OpenSSH_ default seems to be 16, but users can ask for more (or less) by generating an encrypted key via
[`ssh-keygen -a NNN`](http://man7.org/linux/man-pages/man1/ssh-keygen.1.html). However, this comes at a cost:

>> -a rounds
>>
>>    When saving a private key this option specifies the number of
>>    KDF (key derivation function) rounds used.  Higher numbers
>>    result in slower passphrase verification

Various discussions on the net seem to indicate that 64 is the value at which many computers start to slow down noticeably, so
our default limit seems quite suitable (and beyond) for most cases we are likely to encounter "in the wild".

### `UserInteraction`

This interface is required for full support of `keyboard-interactive` authentication protocol as described in [RFC-4252 section 9](https://tools.ietf.org/html/rfc4252#section-9).
The client can handle a simple password request from the server, but if more complex challenge-response interaction is required, then this interface must be
provided - including support for `SSH_MSG_USERAUTH_PASSWD_CHANGEREQ` as described in [RFC 4252 section 8](https://tools.ietf.org/html/rfc4252#section-8).

While [RFC-4256](https://tools.ietf.org/html/rfc4256) support is the primary purpose of this interface, it can also be used to retrieve the server's
welcome banner as described in [RFC 4252 section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4) as well as its initial identification string
as described in [RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2).

In this context, regardless of whether such interaction is configured, the default implementation for the client side contains code
that attempts to auto-detect a password prompt. If it detects it, then it attempts to use one of the registered passwords (if any) as
the interactive response to the server's challenge - (see client-side implementation of `UserAuthKeyboardInteractive#useCurrentPassword`
method). Basically, detection occurs by checking if the server sent **exactly one** challenge with no requested echo, and the challenge
string looks like `"... password ...:"` (**Note:** the auto-detection and password prompt detection patterns are configurable).

This interface can also be used to easily implement interactive password request from user for the `password` authentication protocol
as described in [RFC-4252 section 8](https://tools.ietf.org/html/rfc4252#section-8) via the `resolveAuthPasswordAttempt` method.

```java
/**
 * Invoked during password authentication when no more pre-registered passwords are available
 *
 * @param  session The {@link ClientSession} through which the request was received
 * @return The password to use - {@code null} signals no more passwords available
 * @throws Exception if failed to handle the request - <B>Note:</B> may cause session termination
 */
String resolveAuthPasswordAttempt(ClientSession session) throws Exception;
```

The interface can also be used to implement interactive key based authentication as described in [RFC-4252 section 7](https://tools.ietf.org/html/rfc4252#section-7)
via the `resolveAuthPublicKeyIdentityAttempt` method.

```java
/**
 * Invoked during public key authentication when no more pre-registered keys are available
 *
 * @param  session   The {@link ClientSession} through which the request was received
 * @return           The {@link KeyPair} to use - {@code null} signals no more keys available
 * @throws Exception if failed to handle the request - <B>Note:</B> may cause session termination
 */
KeyPair resolveAuthPublicKeyIdentityAttempt(ClientSession session) throws Exception;
```

## Using the `SshClient` to connect to a server

Once the `SshClient` instance is properly configured it needs to be `start()`-ed in order to connect to a server.
**Note:** one can use a single `SshClient` instance to connnect to multiple servers as well as modifying the default
configuration (ciphers, MACs, keys, etc.) on a per-session manner (see more in the *Advanced usage* section).
Furthermore, one can change almost any configured `SshClient` parameter - although its influence on currently established
sessions depends on the actual changed configuration. Here is how a typical usage would look like

```java
SshClient client = SshClient.setUpDefaultClient();
// override any default configuration...
client.setSomeConfiguration(...);
client.setOtherConfiguration(...);
client.start();

    // using the client for multiple sessions...
    try (ClientSession session = client.connect(user, host, port)
                .verify(...timeout...)
                .getSession()) {
        session.addPasswordIdentity(...password..); // for password-based authentication
        // or
        session.addPublicKeyIdentity(...key-pair...); // for password-less authentication
        // Note: can add BOTH password AND public key identities - depends on the client/server security setup

        session.auth().verify(...timeout...);
        // start using the session to run commands, do SCP/SFTP, create local/remote port forwarding, etc...
    }

    // NOTE: this is just an example - one can open multiple concurrent sessions using the same client.
    //      No need to close the previous session before establishing a new one
    try (ClientSession anotherSession = client.connect(otherUser, otherHost, port)
                .verify(...timeout...)
                .getSession()) {
        anotherSession.addPasswordIdentity(...password..); // for password-based authentication
        anotherSession.addPublicKeyIdentity(...key-pair...); // for password-less authentication
        anotherSession.auth().verify(...timeout...);
        // start using the session to run commands, do SCP/SFTP, create local/remote port forwarding, etc...
    }

// exiting in an orderly fashion once the code no longer needs to establish SSH session
// NOTE: this can/should be done when the application exits.
client.stop();

```

## Configuring the protocol exchange phase

[RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2) does not specify when the client/server should send
their respective identification strings. All it states is that these strings must be available before KEX stage since they
participate in it. By default, the client sends its identification string immediately upon session being established. However,
this can be modified so that the client waits for the server's identification before sending its own.

```java
SshClient client = ...setup client...
PropertyResolverUtils.updateProperty(
   client, CoreModuleProperties.SEND_IMMEDIATE_IDENTIFICATION.getName(), false);
client.start();

```

A similar configuration can be applied to sending the initial `SSH_MSG_KEXINIT` message - i.e., the client can be configured
to wait until the server's identification is received before sending the message. This is done in order to allow clients to
customize the KEX phase according to the parsed server identification.

```java
SshClient client = ...setup client...
PropertyResolverUtils.updateProperty(
   client, CoreModuleProperties.SEND_IMMEDIATE_KEXINIT.getName(), false);
client.start();

```

**Note:** if immediate sending of the client's identification is disabled, `SSH_MSG_KEXINIT` message sending is also
automatically delayed until after the server's identification is received.

A viable configuration might be to send the client's identification immediately, but delay the client's `SSH_MSG_KEXINIT`
message sending until the server's identification is received so that the client can customize the session based on the
server's identity. This is a more likely configuration then delaying the client's own identification in order to be able
to cope with port multiplexors such as [sslh](http://www.rutschle.net/tech/sslh/README.html). Such multiplexors usually
require that the client send an initial packet immediately after connection is established so that they can analyze it
and route it to the correct server (_ssh_ in this case). If we delay the client's identification, then obviously no server
identification will ever be received since the multiplexor does not know how to route the connection.

## Keeping the session alive while no traffic

The client-side implementation supports several mechanisms for maintaining the session alive as far as the **server** is concerned
regardless of the user's own traffic:

* Sending `SSH_MSG_IGNORE` messages every once in a while.

    This mechanism is along the lines of [PUTTY null packets configuration](https://patrickmn.com/aside/how-to-keep-alive-ssh-sessions/).
    It generates small [`SSH_MSG_IGNORE`](https://tools.ietf.org/html/rfc4253#section-11.2) messages. The way to set this mechanism
    up is via the `setSessionHeartbeat` API.

    *Note:* the same effect can also be achieved by setting the relevant properties documented in `SessionHeartbeatController`, but
    it is highly recommended to use the API - unless one needs to control these properties **externally** via `-Dxxx` JVM options.

* Sending `keepalive@...` [global requests](https://tools.ietf.org/html/rfc4254#section-4).

    The feature is controlled via the `CoreModuleProperties#HEARTBEAT_REQUEST` and `HEARTBEAT_INTERVAL` properties - see the relevant
    documentation for these features. The simplest way to activate this feature is to set the `HEARTBEAT_INTERVAL` property value
    to the **milliseconds** value of the requested heartbeat interval.

    This configuration only ensures that the **server** does not terminate the session due to no traffic. If the
    incoming traffic from the server may also suffer from long "quiet" periods, one runs the risk of a **client** time-out. In order
    to avoid this, it is possible to activate the `wantReply` option for the global request. This way, there is bound to be some
    packet response (even if failure - which will be ignored by the heartbeat code). In order to activate this option one needs to
    set the `HEARTBEAT_REPLY_WAIT` property value to a **positive** value specifying the number of **milliseconds** the client is
    willing to wait for the server's reply to the global request.

* Customized user code

    In order to support customized user code for this feature, the `ReservedSessionMessagesHandler` can be used to
    implement any kind of user-defined heartbeat. *Note:* if the user configured such a mechanism, then the
    `sendReservedHeartbeat` method **must** be implemented since the default throws `UnsupportedOperationException`
    which will cause the session to be terminated the 1st time the method is invoked.

**Note(s):**

* Mechanisms are disabled by default - they need to be activated explicitly.

* Mechanisms can be activated either on the `SshClient` (for **global** setup) and/or
the `ClientSession` (for specific session configuration).

* The `keepalive@,,,,` mechanism **supersedes** the other mechanisms if activated.

    * If specified timeout expires for the `wantReply` option then session will be **closed**.

    * *Any* response - including [`SSH_MSH_REQUEST_FAILURE`](https://tools.ietf.org/html/rfc4254#page-4)
    is considered a "good" response for the heartbeat request. In this context, a special patch
    has been introduced in [SSHD-968](https://issues.apache.org/jira/browse/SSHD-968) that converts
    an `SSH_MSG_UNIMPLEMENTED` response to such a global request into a `SSH_MSH_REQUEST_FAILURE`
    since some servers have been found that violate the standard and reply with it to the request.

* When using the CLI, these options can be configured using the following `-o key=value` properties:

    * `ClientAliveInterval` - if positive the defines the heartbeat interval in **seconds**.

    * `ClientAliveUseNullPackets` - *true* if use the `SSH_MSG_IGNORE` mechanism, *false* if use global request (default).

    * `ClientAliveReplyWait` - if positive, then activates the `wantReply` mechanism and specific the expected
    response timeout in **seconds**.

## Running a command or opening a shell

### Running a single non-interactive command

```java
try (OutputStream stdout = ...create/obtain output stream...;
     OutputStream stderr = ...create/obtain output stream...;
     ClientChannel channel = session.createExecChannel(command)) {
    channel.setOut(stdout);
    channel.setErr(stderr);
    channel.open().verify(...some timeout...);
    // Wait (forever) for the channel to close - signalling command finished
    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
}

// Parse/handle the command's output/error streams
```

If all one needs is to run a non-interactive command and then look at its string output, one can use several of the
available *ClientSession#executeRemoteCommand* overloaded methods.

### Running an interactive command/shell

If one needs to parse the command/shell output and then respond by sending the correct input, the code must use **separate** thread(s)
to read the STDOUT/STDERR and provide STDIN input. These threads must be up and running *before* opening the channel since data may start
to pour in even before the *await/verify* call returns. If this data is not consumed at a reasonable pace, then channel may block and eventually
even disconnect. Thus the thread(s) using the streams must be ready beforehand.


```java
// The same code can be used when opening a ChannelExec in order to run a single interactive command
try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) {
    channel.setIn(...stdin...);
    channel.setOut(...stdout...);
    channel.setErr(...stderr...);
    ...spawn the servicing thread(s)....
    try {
        channel.open().verify(...some timeout...);
        // Wait (forever) for the channel to close - signalling shell exited
        channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
    } finally {
        // ... stop the pumping threads ...
    }
}

```

In such cases it is recommended to use the inverted streams in the relevant threads


```java
// The same code can be used when opening a ChannelExec in order to run a single interactive command
try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) {
    try {
        channel.open().verify(...some timeout...);
        
        spawnStdinThread(channel.getInvertedIn());
        spawnStdoutThread(channel.getInvertedOut());
        spawnStderrThread(channel.getInvertedErr());

        // Wait (forever) for the channel to close - signalling shell exited
        channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
    } finally {
        // ... stop the pumping threads ...
    }
}

```

### Redirecting STDERR stream to STDOUT

One can use a combined STDOUT/STDERR stream instead of separate ones:

```java

///////////////////////// Non-interactive ///////////////////////////////

try (OutputStream mergedOutput = ...create/obtain output stream...;
     ClientChannel channel = session.createExecChannel(command)) {
    channel.setOut(mergedOutput);
    channel.redirectErrorStream(true);
    channel.open().verify(...some timeout...);
    // Wait (forever) for the channel to close - signalling command finished
    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
}

// Parse/handle the combined output/error streams

////////////////////////// Interactive ////////////////////////////////////

try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) {
    try {
        channel.redirectErrorStream(true);
        
        channel.open().verify(...some timeout...);
        
        spawnStdinThread(channel.getInvertedIn());
        spawnCombinedOutputThread(channel.getInvertedOut());

        // Wait (forever) for the channel to close - signalling shell exited
        channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L);
    } finally {
        // ... stop the pumping threads ...
    }
}
```

**Note:** the call to *redirectErrorStream* must occur **before** channel is opened. Calling it afterwards has no effect - i.e.,
the last state before opening the stream determines the channel's behavior.

### PTY configuration

When running a command or opening a shell, there is an extra concern regarding the PTY configuration and/or the
reported environment variables. By default, unless specific instructions are provided, the code uses some internal
defaults - which however, might not be adequate for the specific client/server.

```java
// In order to override the PTY and/or environment
Map<String, ?> env = ...some environment...
PtyChannelConfiguration ptyConfig = ...some configuration...
try (ClientChannel channel = session.createShellChannel(ptyConfig, env)) {
    ... same code as before ...
}
```


One possible source of PTY configuration is code that provides some default initializations based on the detected O/S
type - `PtyChannelConfigurationMutator#setupSensitiveDefaultPtyConfiguration`. Of course, the user may use whatever other
considerations when opening such a channel.

**Caveat Emptor:** If the detected O/S type is Unix/Linux, then the `setupSensitiveDefaultPtyConfiguration` code issues an `stty` command
and parses the results (see `SttySupport` class). Since this involves using `System#exec` it is a source of concern as it may hang, throw
an exception, provide corrupted data, etc...
