diff --git a/CHANGELOG.md b/CHANGELOG.md index 502ac6b..9014705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.9.21: Exporting cipher and algo variables + +This release exports cipher and algo variables for consumption in modules that need to interact with SSH. + ## 0.9.20: Adding connectionId This release adds the connectionId field to the log messages that were missing it. @@ -172,58 +176,3 @@ We are also adding the `connectionID` parameter. This parameter was previously g ## 0.9.0: Initial version (November 8, 2020) This is the initial version of the SSH server library. - -### Using this library - -This library provides a friendlier way to handle SSH requests than with the built-in SSH library. As a primary entry -point you will need to create and run the SSH server: - -```go -// Create the server. See the description below for parameters. -server, err := sshserver.New( - cfg, - handler, - logger, -) -if err != nil { - // Handle configuration errors - log.Fatalf("%v", err) -} - -defer func() { - // The Run method will run the server and return when the server is shut down. - // We are running this in a goroutine so the shutdown below can proceed after a minute. - if err := server.Run(); err != nil { - // Handle errors while running the server - } -}() - -time.Sleep(60 * time.Second) - -// Shut down the server. Pass a context to indicate how long the server should wait -// for existing connections to finish. This function will return when the server -// has stopped. -server.Shutdown( - context.WithTimeout( - context.Background(), - 30 * time.Second, - ), -) -``` - -The `cfg` variable will be a `Config` structure as described in [config.go](config.go). - -The `handler` variable must be an implementation of the [`Handler` interface described in handler.go](handler.go). - -The `logger` variable needs to be an instance of the `Logger` interface from [github.com/containerssh/log](https://github.com/containerssh/log). - -### Implementing a handler - -The handler interface consists of multiple parts: - -- The `Handler` is the main handler for the application providing several hooks for events. On new connections the `OnNetworkConnection` method is called, which must return a `NetworkConnectionHandler` -- The `NetworkConnectionHandler` is a handler for network connections before the SSH handshake is complete. It is called to perform authentication and return an `SSHConnectionHandler` when the authentication is successful. -- The `SSHConnectionHandler` is responsible for handling an individual SSH connection. Most importantly, it is responsible for providing a `SessionChannelHandler` when a new session channel is requested by the client. -- The `SessionChannelHandler` is responsible for an individual session channel (single program execution). It provides several hooks for setting up and running the program. Once the program execution is complete the channel is closed. You must, however, keep handling requests (e.g. window size change) during program execution. - -A sample implementation can be found in the [test code](server_impl.go) at the bottom of the file. \ No newline at end of file diff --git a/CODES.md b/CODES.md index 8faea6d..6ce6449 100644 --- a/CODES.md +++ b/CODES.md @@ -2,7 +2,7 @@ | Code | Explanation | |------|-------------| -| `SSH_ALREADY_RUNNING` | The SSH serverImpl is already running and has been started again. This is a bug, please report it. | +| `SSH_ALREADY_RUNNING` | The SSH server is already running and has been started again. This is a bug, please report it. | | `SSH_AUTH_FAILED` | The user has provided invalid credentials. | | `SSH_AUTH_SUCCESSFUL` | The user has provided valid credentials and is now authenticated. | | `SSH_AUTH_UNAVAILABLE` | The user has requested an authentication method that is currently unavailable. | diff --git a/CipherList.go b/CipherList.go index f488b29..396a8d4 100644 --- a/CipherList.go +++ b/CipherList.go @@ -17,7 +17,7 @@ func (c CipherList) Validate() error { return nil } -// GetCipherNames returns a list of cipher names. +// StringList returns a list of cipher names. func (c CipherList) StringList() []string { ciphers := make([]string, len(c)) for i, v := range c { diff --git a/Config.go b/Config.go index 20f5bd0..ec36c24 100644 --- a/Config.go +++ b/Config.go @@ -91,7 +91,7 @@ func (cfg *Config) LoadHostKeys() ([]ssh.Signer, error) { } keyType := private.PublicKey().Type() - if err := HostKeyAlgo(keyType).Validate(); err != nil { + if err := KeyAlgo(keyType).Validate(); err != nil { return nil, fmt.Errorf("unsupported host key algorithm %s on host key %d", keyType, index) } hostKeys = append(hostKeys, private) diff --git a/HostKeyAlgo.go b/HostKeyAlgo.go deleted file mode 100644 index c910251..0000000 --- a/HostKeyAlgo.go +++ /dev/null @@ -1,45 +0,0 @@ -package sshserver - -import ( - "fmt" -) - -var supportedHostKeyAlgos = []stringer{ - HostKeyAlgoSSHRSACertv01, HostKeyAlgoSSHDSSCertv01, HostKeyAlgoECDSASHA2NISTp256Certv01, - HostKeyAlgoECDSASHA2NISTp384Certv01, HostKeyAlgoECDSASHA2NISTp521Certv01, HostKeyAlgoSSHED25519Certv01, - HostKeyAlgoSSHRSA, HostKeyAlgoSSHDSS, HostKeyAlgoSSHED25519, -} - -// HostKeyAlgo are supported host key algorithms. -type HostKeyAlgo string - -// HostKeyAlgo are supported host key algorithms. -const ( - HostKeyAlgoSSHRSACertv01 HostKeyAlgo = "ssh-rsa-cert-v01@openssh.com" - HostKeyAlgoSSHDSSCertv01 HostKeyAlgo = "ssh-dss-cert-v01@openssh.com" - HostKeyAlgoECDSASHA2NISTp256Certv01 HostKeyAlgo = "ecdsa-sha2-nistp256-cert-v01@openssh.com" - HostKeyAlgoECDSASHA2NISTp384Certv01 HostKeyAlgo = "ecdsa-sha2-nistp384-cert-v01@openssh.com" - HostKeyAlgoECDSASHA2NISTp521Certv01 HostKeyAlgo = "ecdsa-sha2-nistp521-cert-v01@openssh.com" - HostKeyAlgoSSHED25519Certv01 HostKeyAlgo = "ssh-ed25519-cert-v01@openssh.com" - HostKeyAlgoSSHRSA HostKeyAlgo = "ssh-rsa" - HostKeyAlgoSSHDSS HostKeyAlgo = "ssh-dss" - HostKeyAlgoSSHED25519 HostKeyAlgo = "ssh-ed25519" -) - -// String creates a string representation. -func (h HostKeyAlgo) String() string { - return string(h) -} - -// Validate checks if a given host key algorithm is valid. -func (h HostKeyAlgo) Validate() error { - if h == "" { - return fmt.Errorf("empty host key algorithm") - } - for _, algo := range supportedHostKeyAlgos { - if algo == h { - return nil - } - } - return fmt.Errorf("unsupported host key algorithm: %s", h) -} diff --git a/KeyAlgo.go b/KeyAlgo.go new file mode 100644 index 0000000..076f6a9 --- /dev/null +++ b/KeyAlgo.go @@ -0,0 +1,45 @@ +package sshserver + +import ( + "fmt" +) + +var supportedHostKeyAlgos = []stringer{ + KeyAlgoSSHRSACertv01, KeyAlgoSSHDSSCertv01, KeyAlgoECDSASHA2NISTp256Certv01, + KeyAlgoECDSASHA2NISTp384Certv01, KeyAlgoECDSASHA2NISTp521Certv01, KeyAlgoSSHED25519Certv01, + KeyAlgoSSHRSA, KeyAlgoSSHDSS, KeyAlgoSSHED25519, +} + +// KeyAlgo are supported key algorithms. +type KeyAlgo string + +// KeyAlgo are supported key algorithms. +const ( + KeyAlgoSSHRSACertv01 KeyAlgo = "ssh-rsa-cert-v01@openssh.com" + KeyAlgoSSHDSSCertv01 KeyAlgo = "ssh-dss-cert-v01@openssh.com" + KeyAlgoECDSASHA2NISTp256Certv01 KeyAlgo = "ecdsa-sha2-nistp256-cert-v01@openssh.com" + KeyAlgoECDSASHA2NISTp384Certv01 KeyAlgo = "ecdsa-sha2-nistp384-cert-v01@openssh.com" + KeyAlgoECDSASHA2NISTp521Certv01 KeyAlgo = "ecdsa-sha2-nistp521-cert-v01@openssh.com" + KeyAlgoSSHED25519Certv01 KeyAlgo = "ssh-ed25519-cert-v01@openssh.com" + KeyAlgoSSHRSA KeyAlgo = "ssh-rsa" + KeyAlgoSSHDSS KeyAlgo = "ssh-dss" + KeyAlgoSSHED25519 KeyAlgo = "ssh-ed25519" +) + +// String creates a string representation. +func (h KeyAlgo) String() string { + return string(h) +} + +// Validate checks if a given key algorithm is valid. +func (h KeyAlgo) Validate() error { + if h == "" { + return fmt.Errorf("empty host key algorithm") + } + for _, algo := range supportedHostKeyAlgos { + if algo == h { + return nil + } + } + return fmt.Errorf("unsupported host key algorithm: %s", h) +} diff --git a/KeyAlgoList.go b/KeyAlgoList.go new file mode 100644 index 0000000..d2e6fd8 --- /dev/null +++ b/KeyAlgoList.go @@ -0,0 +1,30 @@ +package sshserver + +import ( + "fmt" +) + +// KeyAlgoList is a list of key algorithms. +type KeyAlgoList []KeyAlgo + +// Validate validates the list of ciphers to contain only supported items. +func (h KeyAlgoList) Validate() error { + if len(h) == 0 { + return fmt.Errorf("host key algorithm list cannot be empty") + } + for _, algo := range h { + if err := algo.Validate(); err != nil { + return err + } + } + return nil +} + +// StringList returns a list of cipher names. +func (h KeyAlgoList) StringList() []string { + algos := make([]string, len(h)) + for i, v := range h { + algos[i] = v.String() + } + return algos +}