-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Cargo built-in Git/SSH client doesn't support @cert-authority
#11577
Comments
Thanks for the beautiful issue report! The manual of OpenSSH As what aforementioned, there are at least a few independent tasks:
I would help mentor some of them, but for |
The certificate format is documented here. There is an implementation of ssh certificates in Rust, from the rust-crypto team, via the |
Cargo doesn't support the `@cert-authority` or `@revoked` markers in SSH Known Hosts files. The lines are silently ignored. If a user is depending on these lines to connect to a Git server via SSH, then their command line Git client will work, but Cargo will fail with an error that the host key doesn't match. This change adds a note explaining that Cargo doesn't support these markers and suggests that the user change their cargo configuration to fetch with the CLI client instead. Refs: rust-lang#11577
Thanks for the comments @weihanglo and @est31! I've added the links you each suggested into the main text of the Issue to make reading it less confusing. I've also switched from calling these lines directives (which seems to be wrong, I don't know where I got that from) to calling them markers. There's a small docs PR for the first task on the list ready too. |
@cert-authority
or @revoked
directives@cert-authority
or @revoked
markers
I don't think we want to close this issue, as the referenced PR was only for the first task. Or would you prefer to have separate issues for those? |
Reopen as we can continue tracking sub-tasks here #11577 (comment). Thanks for the suggestion :) |
The SSH `known_hosts` file parsing in Cargo did not previously support markers. Markers are modifiers on the lines (`@cert-authority` and `@revoked`) which denote special behavior for the details on that line. Lines were skipped entirely. This change adds support for the `@revoked` marker. This marker denotes that a key should be rejected outright. It is of limited use without `@cert-authority` marker support. However, if it is present in a user's `known_hosts` file, then Cargo definitely shouldn't accept that key and probably shouldn't suggest that the user add it to their `known_hosts` either. The change also adds support for detecting `@cert-authority` markers in `known_hosts` files. These lines cannot yet be used for host key verification, but if one is found for a matching host, the user will be informed that Cargo doesn't support `@cert-authority` markers in the error message. Additionally, the user will be advised to use the `net.git-fetch-with-cli` config option to use the command line git client for fetching crates from Git. Refs: rust-lang#11577
The SSH `known_hosts` file parsing in Cargo did not previously support markers. Markers are modifiers on the lines (`@cert-authority` and `@revoked`) which denote special behavior for the details on that line. Lines were skipped entirely. This silent skipping of marker lines can be confusing to a user, who sees that their command line Git/SSH client works for some repository, but Cargo reports that no host key is found. This change adds support for the `@revoked` marker. This marker denotes that a key should be rejected outright. It is of limited use without `@cert-authority` marker support. However, if it is present in a user's `known_hosts` file, then Cargo definitely shouldn't accept that key and probably shouldn't suggest that the user add it to their `known_hosts` either. The change also adds support for detecting `@cert-authority` markers in `known_hosts` files. These lines cannot yet be used for host key verification, but if one is found for a matching host, the user will be informed that Cargo doesn't support `@cert-authority` markers in the error message. Additionally, the user will be advised to use the `net.git-fetch-with-cli` config option to use the command line git client for fetching crates from Git. Refs: rust-lang#11577
The SSH `known_hosts` file parsing in Cargo did not previously support markers. Markers are modifiers on the lines (`@cert-authority` and `@revoked`) which denote special behavior for the details on that line. Lines were skipped entirely. This silent skipping of marker lines can be confusing to a user, who sees that their command line Git/SSH client works for some repository, but Cargo reports that no host key is found. This change adds support for the `@revoked` marker. This marker denotes that a key should be rejected outright. It is of limited use without `@cert-authority` marker support. However, if it is present in a user's `known_hosts` file, then Cargo definitely shouldn't accept that key and probably shouldn't suggest that the user add it to their `known_hosts` either. The change also adds support for detecting `@cert-authority` markers in `known_hosts` files. These lines cannot yet be used for host key verification, but if one is found for a matching host, the user will be informed that Cargo doesn't support `@cert-authority` markers in the error message. Additionally, the user will be advised to use the `net.git-fetch-with-cli` config option to use the command line git client for fetching crates from Git. Refs: rust-lang#11577
Add partial support for SSH known hosts markers ### What does this PR try to resolve? The SSH `known_hosts` file parsing in Cargo did not previously support markers. Markers are modifiers on the lines (``@cert-authority`` and ``@revoked`)` which denote special behavior for the details on that line. Lines were skipped entirely. This silent skipping of marker lines can be confusing to a user, who sees that their command line Git/SSH client works for some repository, but Cargo reports that no host key is found. This change adds support for the ``@revoked`` marker. This marker denotes that a key should be rejected outright. It is of limited use without ``@cert-authority`` marker support. However, if it is present in a user's `known_hosts` file, then Cargo definitely shouldn't accept that key and probably shouldn't suggest that the user add it to their `known_hosts` either. The change also adds support for detecting ``@cert-authority`` markers in `known_hosts` files. These lines cannot yet be used for host key verification, but if one is found for a matching host, the user will be informed that Cargo doesn't support ``@cert-authority`` markers in the error message. Additionally, the user will be advised to use the `net.git-fetch-with-cli` config option to use the command line git client for fetching crates from Git. Refs: #11577 ### How should we test and review this PR? The changes in this PR are covered by unit tests, all within `src/cargo/sources/git/known_hosts.rs`. Additionally, manual testing can be performed. For this you will need an OpenSSH server (it doesn't need to be a Git server). I'll assume that you have one running on your local machine at `127.0.0.1`. #### Setup 1. Create a new Cargo project and add the following line to `[dependencies]`: ```toml fake-crate = { git = "ssh://127.0.0.1/fake-crate.git" } ``` #### Test missing host key: `HostKeyNotFound` (existing functionality) 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Verify host key not present: `ssh 127.0.0.1`. SSH should tell you `The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.` 3. Run `cargo build` 4. Expect error from Cargo: `error: unknown SSH host key` #### Test ``@revoked`` key: `HostKeyRevoked` 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Add host key: `ssh 127.0.0.1` answer `yes` 3. Find all lines in `known_hosts` beginning with `127.0.0.1` (there may be multiple). 4. Add ``@revoked` ` to the beginning of all lines in (3) 5. Run `cargo build` 6. Expect error from Cargo: error: Key has been revoked for `127.0.0.1` #### Test `@cert-authority`` (not being supported): `HostHasOnlyCertAuthority` 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Run `cargo build` 3. Expect error from Cargo: `error: unknown SSH host key` 4. Check the line after ` The key to add is:` in the error message and copy the key type (e.g. `ecdsa-sha2-nistp256`) 5. Add a line to `known_hosts`: ``@cert-authority` 127.0.0.1 <key-type> AAAAB5Wm` (e.g. ``@cert-authority` 127.0.0.1 ecdsa-sha2-nistp256 AAAAB5Wm`) 7. Run `cargo build` 8. Expect error from Cargo: error: Found a ``@cert-authority`` marker for `127.0.0.1` ### Additional information Cargo doesn't currently support a few things when checking host keys. This may affect the testing described above. * Multiple host key types (OpenSSH negotiates the host key type and can support matching the one present in the `known_hosts` file even when it's not the preferred type of the server). * Wildcard matching of host patterns (there's a FIXME for this) More information about SSH known host markers can be found on #11577.
Add partial support for SSH known hosts markers ### What does this PR try to resolve? The SSH `known_hosts` file parsing in Cargo did not previously support markers. Markers are modifiers on the lines (``@cert-authority`` and ``@revoked`)` which denote special behavior for the details on that line. Lines were skipped entirely. This silent skipping of marker lines can be confusing to a user, who sees that their command line Git/SSH client works for some repository, but Cargo reports that no host key is found. This change adds support for the ``@revoked`` marker. This marker denotes that a key should be rejected outright. It is of limited use without ``@cert-authority`` marker support. However, if it is present in a user's `known_hosts` file, then Cargo definitely shouldn't accept that key and probably shouldn't suggest that the user add it to their `known_hosts` either. The change also adds support for detecting ``@cert-authority`` markers in `known_hosts` files. These lines cannot yet be used for host key verification, but if one is found for a matching host, the user will be informed that Cargo doesn't support ``@cert-authority`` markers in the error message. Additionally, the user will be advised to use the `net.git-fetch-with-cli` config option to use the command line git client for fetching crates from Git. Refs: rust-lang#11577 ### How should we test and review this PR? The changes in this PR are covered by unit tests, all within `src/cargo/sources/git/known_hosts.rs`. Additionally, manual testing can be performed. For this you will need an OpenSSH server (it doesn't need to be a Git server). I'll assume that you have one running on your local machine at `127.0.0.1`. #### Setup 1. Create a new Cargo project and add the following line to `[dependencies]`: ```toml fake-crate = { git = "ssh://127.0.0.1/fake-crate.git" } ``` #### Test missing host key: `HostKeyNotFound` (existing functionality) 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Verify host key not present: `ssh 127.0.0.1`. SSH should tell you `The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.` 3. Run `cargo build` 4. Expect error from Cargo: `error: unknown SSH host key` #### Test ``@revoked`` key: `HostKeyRevoked` 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Add host key: `ssh 127.0.0.1` answer `yes` 3. Find all lines in `known_hosts` beginning with `127.0.0.1` (there may be multiple). 4. Add ``@revoked` ` to the beginning of all lines in (3) 5. Run `cargo build` 6. Expect error from Cargo: error: Key has been revoked for `127.0.0.1` #### Test `@cert-authority`` (not being supported): `HostHasOnlyCertAuthority` 1. Back up your `known_hosts` file and then remove any lines for `127.0.0.1`. 2. Run `cargo build` 3. Expect error from Cargo: `error: unknown SSH host key` 4. Check the line after ` The key to add is:` in the error message and copy the key type (e.g. `ecdsa-sha2-nistp256`) 5. Add a line to `known_hosts`: ``@cert-authority` 127.0.0.1 <key-type> AAAAB5Wm` (e.g. ``@cert-authority` 127.0.0.1 ecdsa-sha2-nistp256 AAAAB5Wm`) 7. Run `cargo build` 8. Expect error from Cargo: error: Found a ``@cert-authority`` marker for `127.0.0.1` ### Additional information Cargo doesn't currently support a few things when checking host keys. This may affect the testing described above. * Multiple host key types (OpenSSH negotiates the host key type and can support matching the one present in the `known_hosts` file even when it's not the preferred type of the server). * Wildcard matching of host patterns (there's a FIXME for this) More information about SSH known host markers can be found on rust-lang#11577.
@cert-authority
or @revoked
markers@cert-authority
Edited: for remaining tasks, see #11577 (comment).
Problem
Cargo parses SSH known hosts file. From the Cargo book (https://doc.rust-lang.org/cargo/appendix/git-authentication.html#ssh-known-hosts):
However, there are some additional markers supported by at least some SSH clients (e.g. OpenSSH) to handle more complex cases than verifying a host via a single algorithm/key. The known ones are:
@cert-authority
@revoked
The Cargo SSH client doesn't support these directives. It is quite explicit about this in the code:
cargo/src/cargo/sources/git/known_hosts.rs
Lines 490 to 493 in 1cd6d38
With the release of Rust 1.66.1 and the fix for CVE-2022-46176 (security advisory), Cargo is now performing host key checking, which will lead to more users needing this functionality because single host key verification may not be practical.
Proposed Solution
The solution to this issue would be to implement the missing support for the
@cert-authority
or@revoked
markers.There is useful documentation on these markers from the OpenSSH project:
sshd
SSH_KNOWN_HOSTS FILE FORMAT: https://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT (from @weihanglo's comment)This issue can be mitigated by telling cargo to use the command line Git client (
net.git-fetch-with-cli = true
) as mentioned by @weihanglo on this Zulip thread: https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Cargo.20SSH.20host.20key.20verification.20with.20.40cert-authority.20linesAs mentioned on that thread, a good mitigation step would be to add some text to the Cargo book section on SSH Known Hosts to suggest that users try
net.git-fetch-with-cli = true
if they find that Cargo's SSH behaviour is different to what they expect or different to how their command line Git client behaves.Notes
Some further useful resources that I found related to creating an SSH Certificate Authority (CA) and then specifying it in the SSH Known Hosts file:
The text was updated successfully, but these errors were encountered: