aboutsummaryrefslogtreecommitdiff
path: root/lib/ssh/client.go
AgeCommit message (Collapse)Author
2026-03-27lib/ssh: set client config HostKeyAlgorithms from known_hosts filesShulhan
There is an issue with current SSH client implementation. Given a single host public key in the known_hosts file, host ssh-ed25519 key... Calling ssh.Dial(`tcp`, "host", ...) will return an error knownhosts: key mismatch from [handshakeTransport.enterKeyExchange], because only key "mlkem768x25519-sha256" is checked on the client side. This changes add DB interface for knownhosts that have two methods: - HostKeyAlgorithms: return the host key that matches in known_hosts based on the "host" name or address for [ssh.ClientConfig.HostKeyAlgorithms]. - HostKeyCallback: return the ssh.HostKeyCallback for [ssh.ClientConfig.HostKeyCallback].
2025-02-04all: remove the nolint tagsShulhan
The "nolint" tag is used to ignore lines from being processed by golangci-lint. Since we are not using golangci-lint anymore, now and in the future, those lines can be removed.
2024-12-28lib/ssh: implement Run with contextShulhan
Instead of depends on fork of crypto with CL that needs [proposal], implement them in here so we can update crypto to the latest release. [proposal]: https://go-review.googlesource.com/c/crypto/+/552435
2024-03-09lib: move package "ssh/config" to "lib/sshconfig"Shulhan
Previously the "ssh/config" is used by the parent package "ssh" and "ssh/sftp" which is break the rule of package layer (the top package should be imported by sub package, not the other way around).
2024-03-05all: comply with linter recommendations #3Shulhan
For HTTP server that use TLS, set the minimum TLS version and ReadHeaderTimeout to mitigate slowloris attack. For HTTP client or server that parameterize the use of InsecureSkipVerify, annotate the line with "nolint:gosec" to allow the code pass the check. Library that still use sha1, in example in DKIM and TOTP, skip the warnings by annotating the line with "nolint:gosec". A pointer variable now allocated their address before assigning its value. Any error that returned now wrapped using "%w". Also, replace error checking using [errors.Is] or [errors.As] instead of using equal or not-equal operators. In "lib/http", replace any usage of "math/rand" with "crypto/rand". Any call of [math/big.Rat.SetString] now annotated with "nolint:gosec" since its false positive, the issue has been fixed in Go >= 1.17.7. Any switch case that does not cover the rest of the possible values now handled by adding the cases or by replacing the "default" case with the rest of values.
2024-03-05all: comply with linter recommendations #2Shulhan
HTTP request now implicitly create request with context. Any false positive related to not closing HTTP response body has been annotated with "nolint:bodyclose". In the example code, use consistent "// Output:" comment format, by prefixing with single space. Any comment on code now also prefixing with single space. An error returned without variables now use [errors.New] instead of [fmt.Errorf]. Any error returned using [fmt.Errorf] now wrapped using "%w" instead of "%s". Also, replace error checking using [errors.Is] or [errors.As], instead of using equal/not-equal operator. Any statement like "x = x OP y" now replaced with "x OP= y". Also, swap statement is simplified using "x, y = y, x". Any switch statement with single case now replaced with if-condition. Any call to defer on function or program that call [os.Exit], now replaced by calling the deferred function directly. Any if-else condition now replaced with switch statement, if possible.
2024-03-02all: move the repository to "git.sr.ht/~shulhan/pakakeh.go"Shulhan
There are several reasons that why we move from github.com. First, related to the name of package. We accidentally name the package with "share" a common word in English that does not reflect the content of repository. By moving to other repository, we can rename it to better and unique name, in this "pakakeh.go". Pakakeh is Minang word for tools, and ".go" suffix indicate that the repository related to Go programming language. Second, supporting open source. The new repository is hosted under sourcehut.org, the founder is known to support open source, and all their services are licensed under AGPL, unlike GitHub that are closed sources. Third, regarding GitHub CoPilot. The GitHub Terms of Service [1], allow any public content that are hosted there granted them to parse the content. On one side, GitHub helps and flourish the open source, but on another side have an issues regarding scraping the copyleft license [2]. [1]: https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#4-license-grant-to-us [2]: https://githubcopilotinvestigation.com
2023-12-22lib/ssh: add parameter context to Execute methodShulhan
This changes require the fork of our golang.org/x/crypto.
2023-12-17lib/ssh: implement method Output on ClientShulhan
The Output method run the command and return its standard output and error as is. Any other error beside standard error, like connection, will be returned as error.
2023-11-18lib/crypto: add support for reading passphrase using SSH_ASKPASSShulhan
If the library failed to changes os.Stdin to raw, it will try to use a program defined in SSH_ASKPASS environment variable. The SSH_ASKPASS is controlled by environment SSH_ASKPASS_REQUIRE. - If SSH_ASKPASS_REQUIRE is empty the passphrase will read from terminal first, if not possible then using SSH_ASKPASS program. - If SSH_ASKPASS_REQUIRE is set to "never" the passphrase will read from terminal only. - If SSH_ASKPASS_REQUIRE is set to "prefer", the passphrase will read using SSH_ASKPASS program not from terminal, but require DISPLAY environment to be set. - If SSH_ASKPASS_REQUIRE is set to "force", the passphrase will read using SSH_ASKPASS program not from terminal, without checking DISPLAY environment. This changes affect the [ssh.NewClientInteractive] indirectly.
2023-09-27lib/ssh: fix missing error check from previous changes 8d0720f6Shulhan
2023-09-26go.mod: remove replace directive for golang.org/x/cryptoShulhan
Using replace directive does not works well if we install binary using "go install". One of the case that we found is when user installing awwan [1] that use "share" module [2] with replace directive, the binary is not build with git.sr.ht/~shulhan/go-x-crypto. /Users/xxx/go/bin/awwan: go1.21.0 path git.sr.ht/~shulhan/awwan/cmd/awwan mod git.sr.ht/~shulhan/awwan v0.7.1-0.20230925173020-40b9fe9b854c h1:629djcSfqM8ITX+CtgGyrybPnKQPpwJ/EceN967bKps= dep git.sr.ht/~shulhan/asciidoctor-go v0.5.0 h1:TfcAjv+7EwBZ83ef8OhX9vfQ4vRFcaJh0P1XXgbsJv0= dep git.sr.ht/~shulhan/ciigo v0.10.0 h1:s1SJ3/NzBcbOLmEZ4z1Cx9Vf7ZdDIvm45b7KMCZKzEY= dep github.com/evanw/esbuild v0.19.3 h1:foPr0xwQM3lBWKBtscauTN9FrmJzRDVI2+EGOs82H/I= dep github.com/shuLhan/share v0.49.2-0.20230923081600-77c41ce992e6 h1:REQDC2UKLaWT1WGd/Iw/rfKLkXb7vtKtyObkeZeHZRk= dep github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA= dep github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc= dep golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= dep golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= dep golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= dep golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= dep gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= build -buildmode=exe build -compiler=gc build DefaultGODEBUG=panicnil=1 build CGO_ENABLED=1 build CGO_CFLAGS= build CGO_CPPFLAGS= build CGO_CXXFLAGS= build CGO_LDFLAGS= build GOARCH=arm64 build GOOS=darwin This changes require use to modify lib/cryto and lib/ssh that depends on our patches. [1] https://git.sr.ht/~shulhan/awwan [2] https://github.com/shuLhan/share/commit/77c41ce992e6
2023-09-24lib/ssh: store and use the connected identity file for ScpPut and ScpGetShulhan
Previously, the ScpPut and ScpGet use the first IdentityFile in section to use in "-i" argument. This is not correct If the section contains two or more IdentityFile and the one that can connect are the last one, the ScpPut and ScpGet method may return an error when executing the "scp" command.
2023-09-24lib/ssh: add method Close to ClientShulhan
The Close method close the client connection and release all resources.
2023-09-24lib/ssh: rename internal field cfg to sectionShulhan
The ssh Client have two configurations, one configuration for Dial from parent package crypto/ssh.ClientConfig and one from lib/ssh/config.Section. In order to distinguish it better, we change the second configuration from "cfg" to "section".
2023-09-20lib/ssh: replace LoadPrivateKeyInteractive with the one from lib/cryptoShulhan
2023-09-11lib/ssh: remove unused field configHostKeyCallback in ClientShulhan
2023-08-29lib/ssh: use UserKnownHostFile from configuration in NewClientInteractiveShulhan
Previously, the ssh Client always use InsecureIgnoreHostKey in HostKeyCallback. This may post security issue, like man-in-the-middle attack, since we did not check the server host key with one of key that known by client from UserKnownHostFile (for example ~/.ssh/known_hosts). This changes use the SSH section UserKnownHostFile from configuration (default to ~/.ssh/known_hosts) to check if the server host key is valid. The NewClientInteractive will return an error, "key is unknown", if host key not exist in UserKnownHostFile or "key is mismatch" if host key not match with one registered in UserKnownHostFile. This changes depends on patch of golang.org/x/crypto [1] that has not reviewed yet, so we need to replace it with one that contains the patch. [1] https://go-review.googlesource.com/c/crypto/+/523555
2023-07-26lib/ssh: refactoring NewClientFromConfig, renamed to NewClientInteractiveShulhan
Previously, the NewClientInteractive blindly use the signers from Section.Signers. If one of the IdentityFile valid, it will add all the keys in IdentityFile to SSH agent. In this changes we try each IdentityFile independently. If the key is valid, client connected to remote machine, then only that key will be added to SSH agent. While at it we also rename the method to NewClientInteractive to indicate that the function will prompt for passphrase if one of the IdentityFile is encrypted.
2023-07-26ssh/config: refactoring, simplify the Section fieldsShulhan
Instead of storing each Section value in separate field, store them inside a map, Field. This reduce the size of Section and simplify adding or getting the key that we are not supported but maybe usable by user in the future. This changes introduce several new methods as replacement of field: * CASignatureAlgorithms: a method that return list of signature algorithms that Section set or the default * CanonicalDomains: a method that return CanonicalDomains set in Section * CanonicalizePermittedCNames: return the permitted CNAMEs set in Section, from KeyCanonicalizePermittedCNames. * CertificateFile: return list of certificate file * Environments: return system and/or custom environment that will be passed to remote machine. The key and value is derived from "SendEnv" and "SetEnv". * FieldBool: return field value as boolean * FieldInt: return the field value as int * Hostname: return the Hostname in this Section * IdentityAgent: return the path to SSH agent socket to be used * Port: return the remote machine port * User: return the remote user name * Set: set the Field using key and value
2023-02-25all: access embedded field or methods using the type nameShulhan
This is for clarity in the code, better to be explicit by typing where the field or methods come from.
2022-10-20lib/ssh: add private key to agent once client connected successfullyShulhan
In NewClientFromConfig, if Client connect using IdentityFile instead of agent and its success, we add the private key to agent directly. Unfortunately, since we did not know which key is being negotiated, we add all private keys parsed from IdentityFile.
2022-10-20ssh/config: change the method GenerateSigners to SignersShulhan
This is to make the method compatible with ssh.PublicKeysCallback. Each parsed and unsigned IdentityFile is stored in field PrivateKeys, replacing the Signers field (which is conflict with method names).
2022-10-19lib/ssh: try both ssh agent and IdentityFileYoufu Zhang
If ~/.ssh/config contains a Host section with IdentityFile directive specified and SSH_AUTH_SOCK environment variable is also set, but ssh_config section does not specify "IdentityAgent none" explicitly, the NewClientFromConfig returns an error saying NewClient: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain. This changes fix this by dialing remote server twice. Fix #1
2022-05-09all: reformat all codes using gofmt 1.19 (the Go tip)Shulhan
2021-11-06lib/ssh: use agent defined by config or from environment variableShulhan
Previously, we only check the environment variable SSH_AUTH_SOCK to decide whether the client identity will fetched from agent or from private key file. This changes use the GetIdentityAgent from config Section to derive the path to unix socket. It will return an empty string if the IdentityAgent is set to "none" in the Section or when SSH_AUTH_SOCK is not exist or empty.
2021-08-15lib/ssh: add method to set session output and errorShulhan
Previously, all of the SSH output and error goes to os.Stdout and os.Stderr. This changes add method SetSessionOutputError to change the output and error for future remote execution.
2021-07-05lib/ssh: rename method Get to ScpGet and Put to ScpPutShulhan
This changes is to make clear that the methods to copy the files, either from local or from remote, is using the "scp" through exec package, not using the native SSH file transfer protocol. While at it, use consistent log prefix for error message.
2021-07-05lib/ssh: embed the ssh.Client into Client instead of as fieldShulhan
This will allow seamless integration with the x/crypto/ssh Client type.
2021-07-05lib/ssh: rename the NewClient function to NewClientFromConfigShulhan
This is to differentiate it with x/crypto ssh package that have the same function name.
2021-07-05lib/ssh: move the config parser to subpackage "config"Shulhan
There are two reasons for moving to sub-package. First, the code for parsing the ssh_config(5) take almost 99% of the lines in the ssh package. Second, in case we want to submit the code to upstream, golang.org/x/crypto, we need the package to be independent, less external dependencies as possible.
2021-04-11ssh: check for empty private key file on Get and PutShulhan
If the private key file is empty, skip it for being added as parameter of scp command. This is to prevent warning message on user side.
2021-04-06ssh: use the SSH agent to authenticate on NewClientShulhan
Previously, the client use the IdentityFile on ConfigSection to authenticate with the remote SSH server. In case the IdentityFile is encrypted with passphrase, each time NewClient is invoked it will ask for passphrase. To minimize inputing the passphrase, we check if current use run the SSH agent through SSH_AUTH_SOCK environment variable and use the agent to generate signers. This method need manual key added by user to SSH agent before calling NewClient to make it works.
2021-04-05ssh: ask for passphrase if private key is encrypted on generateSignersShulhan
In case the private key defined in IdentityFile is encrypted, prompt for the passphrase on the screen and read it from stdin using term.ReadPassword(). This changes also remove call to generateSigners on postConfig(), instead invoke it from NewClient() to minimize multiple calls to generateSigners().
2020-06-06all: use default linter optionsShulhan
2020-04-26ssh: replace the ClientConfig with ConfigSectionShulhan
Now that the Config can parse Host and required fields (User, Hostname, Port, and IdentityFile), we can use the ConfigSection to be passed to parameter when creating new Client.
2020-02-13dns,ssh: suppress linter false-positive warnings reported by "gosec"Shulhan
2019-06-14all: fix nolint formatShulhan
The valid syntax to suppress linter warnings is "//nolint:<name>" with no space between comment and "nolint" and between ":". Also, we move the placement of nolint directive to the top of statements for multiple nolint in the same scope. While at it, fix and supress some linter warnings.
2019-06-13ssh/client: add recursive option for Get and Put commandsShulhan
2019-06-03ssh: add field Environments in client's configShulhan
The field Environments contains system environment variables that will be passed to Execute.
2019-05-25ssh: package ssh provide a wrapper to golang.org/x/crypto/sshShulhan
This package provide a simple client initialization with additional methods to copy file from local or remote using scp.