rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood9c2798c424a409410b30e7f9da0bfdac9a167fb9
{
"request": "trigger",
"version": 1,
"event_type": "patch",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "125cf15c7b6b29b221419633b5ad80bde0dbc963",
"author": {
"id": "did:key:z6MkothxPrYqWhwG72VQWsXALXZVsxBFuA4vkyUWnrrZjCPc",
"alias": null
},
"title": "Use `ssh-agent-lib` instead of `radicle-ssh` for SSH agent features",
"state": {
"status": "draft",
"conflicts": []
},
"before": "ce99f7e7e45ac22104434c6094ac2fe410a8970d",
"after": "9c2798c424a409410b30e7f9da0bfdac9a167fb9",
"commits": [
"9c2798c424a409410b30e7f9da0bfdac9a167fb9"
],
"target": "6cfed884bf37cba1e0d8e97fa8b0e94df4a04b1f",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "125cf15c7b6b29b221419633b5ad80bde0dbc963",
"author": {
"id": "did:key:z6MkothxPrYqWhwG72VQWsXALXZVsxBFuA4vkyUWnrrZjCPc",
"alias": null
},
"description": "Note that this patch is a *work in progress* and also a testing ground\nfor me. I hope I won't break radicle as I try to submit it :)\n\nSigned-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>",
"base": "ce99f7e7e45ac22104434c6094ac2fe410a8970d",
"oid": "9c2798c424a409410b30e7f9da0bfdac9a167fb9",
"timestamp": 1718195535
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "f4939526-fcc5-452f-9677-6e12e8d4e259"
},
"info_url": "https://cci.rad.levitte.org//f4939526-fcc5-452f-9677-6e12e8d4e259.html"
}
Started at: 2025-10-21 19:34:15.952841+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW added
✓ Remote-tracking branch cloudhead@z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW/master created for z6MktaNvN1KVFMkSRAiN4qK5yvX1zuEEaseeX5sffhzPZRZW
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz added
✓ Remote-tracking branch erikli@z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz/master created for z6MkgFq6z5fkF2hioLLSNu1zP2qEL1aHXHZzGH1FLFGAnBGz
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/f4939526-fcc5-452f-9677-6e12e8d4e259/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 125 issues · 15 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 125cf15c7b6b29b221419633b5ad80bde0dbc963
✓ Switched to branch patch/125cf15 at revision 125cf15
✓ Branch patch/125cf15 setup to track rad/patches/125cf15c7b6b29b221419633b5ad80bde0dbc963
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 9c2798c424a409410b30e7f9da0bfdac9a167fb9
HEAD is now at 9c2798c4 Use `ssh-agent-lib` instead of `radicle-ssh` for SSH agent features
Exit code: 0
$ git show 9c2798c424a409410b30e7f9da0bfdac9a167fb9
commit 9c2798c424a409410b30e7f9da0bfdac9a167fb9
Author: Wiktor Kwapisiewicz <wiktor@metacode.biz>
Date: Wed Jun 12 14:12:24 2024 +0200
Use `ssh-agent-lib` instead of `radicle-ssh` for SSH agent features
Note that this patch is a *work in progress* and also a testing ground
for me. I hope I won't break radicle as I try to submit it :)
Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
diff --git a/Cargo.lock b/Cargo.lock
index be29bfe2..26484c17 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -113,47 +113,48 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.13"
+version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
+ "is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.0.2"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.2"
+version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
@@ -161,9 +162,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.82"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "arc-swap"
@@ -179,9 +180,9 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "autocfg"
-version = "1.2.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "base-x"
@@ -322,9 +323,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.0.95"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
+checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
dependencies = [
"jobserver",
"libc",
@@ -386,9 +387,9 @@ dependencies = [
[[package]]
name = "colorchoice"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "colored"
@@ -423,27 +424,27 @@ dependencies = [
[[package]]
name = "crc32fast"
-version = "1.4.0"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
-version = "0.5.12"
+version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.19"
+version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-bigint"
@@ -483,6 +484,33 @@ dependencies = [
"cipher",
]
+[[package]]
+name = "curve25519-dalek"
+version = "4.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
+dependencies = [
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "digest",
+ "fiat-crypto",
+ "platforms",
+ "rustc_version",
+ "subtle",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
+
[[package]]
name = "cypheraddr"
version = "0.4.0"
@@ -521,15 +549,15 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
+checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "data-encoding-macro"
-version = "0.1.14"
+version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e"
+checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639"
dependencies = [
"data-encoding",
"data-encoding-macro-internal",
@@ -537,9 +565,9 @@ dependencies = [
[[package]]
name = "data-encoding-macro-internal"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3"
+checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f"
dependencies = [
"data-encoding",
"syn 1.0.109",
@@ -582,6 +610,17 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "displaydoc"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
+
[[package]]
name = "dyn-clone"
version = "1.0.17"
@@ -595,7 +634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfd533a2fc01178c738c99412ae1f7e1ad2cb37c2e14bfd87e9d4618171c825"
dependencies = [
"ct-codecs",
- "ed25519",
+ "ed25519 1.5.3",
"getrandom",
]
@@ -622,11 +661,32 @@ dependencies = [
"signature 1.6.4",
]
+[[package]]
+name = "ed25519"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
+dependencies = [
+ "signature 2.2.0",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "2.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519 2.2.3",
+ "sha2",
+ "subtle",
+]
+
[[package]]
name = "either"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
+checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]]
name = "elliptic-curve"
@@ -655,9 +715,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -665,9 +725,9 @@ dependencies = [
[[package]]
name = "escargot"
-version = "0.5.10"
+version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f474c6844cbd04e783d0f25757583db4f491770ca618bedf2fb01815fc79939"
+checksum = "650eb5f6eeda986377996e9ed570cbc20cc16d30440696f82f129c863e4e3e83"
dependencies = [
"log",
"once_cell",
@@ -695,9 +755,9 @@ dependencies = [
[[package]]
name = "fastrand"
-version = "2.0.2"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
name = "ff"
@@ -709,6 +769,12 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
[[package]]
name = "filetime"
version = "0.2.23"
@@ -717,15 +783,15 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall",
+ "redox_syscall 0.4.1",
"windows-sys 0.52.0",
]
[[package]]
name = "flate2"
-version = "1.0.28"
+version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -762,9 +828,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
@@ -829,16 +895,16 @@ dependencies = [
[[package]]
name = "gix-actor"
-version = "0.31.1"
+version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c3a3bde455ad2ee8ba8a195745241ce0b770a8a26faae59fcf409d01b28c46"
+checksum = "d69c59d392c7e6c94385b6fd6089d6df0fe945f32b4357687989f3aee253cd7f"
dependencies = [
"bstr",
"gix-date",
"gix-utils",
"itoa",
"thiserror",
- "winnow 0.6.8",
+ "winnow 0.6.13",
]
[[package]]
@@ -861,9 +927,9 @@ dependencies = [
[[package]]
name = "gix-command"
-version = "0.3.6"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90009020dc4b3de47beed28e1334706e0a330ddd17f5cfeb097df3b15a54b77"
+checksum = "6c22e086314095c43ffe5cdc5c0922d5439da4fd726f3b0438c56147c34dc225"
dependencies = [
"bstr",
"gix-path",
@@ -879,7 +945,7 @@ checksum = "f7b102311085da4af18823413b5176d7c500fb2272eaf391cfa8635d8bcb12c4"
dependencies = [
"bstr",
"gix-chunk",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-hash 0.14.2",
"memmap2",
"thiserror",
@@ -921,10 +987,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c70146183bd3c7119329a3c7392d1aa0e0adbe48d727f4df31828fe6d8fdaa1"
dependencies = [
"bstr",
- "gix-command 0.3.6",
+ "gix-command 0.3.7",
"gix-config-value",
"gix-path",
- "gix-prompt 0.8.4",
+ "gix-prompt 0.8.5",
"gix-sec",
"gix-trace",
"gix-url 0.27.3",
@@ -933,9 +999,9 @@ dependencies = [
[[package]]
name = "gix-date"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180b130a4a41870edfbd36ce4169c7090bca70e195da783dea088dd973daa59c"
+checksum = "367ee9093b0c2b04fd04c5c7c8b6a1082713534eab537597ae343663a518fa99"
dependencies = [
"bstr",
"itoa",
@@ -969,9 +1035,9 @@ dependencies = [
[[package]]
name = "gix-features"
-version = "0.38.1"
+version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db4254037d20a247a0367aa79333750146a369719f0c6617fec4f5752cc62b37"
+checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69"
dependencies = [
"crc32fast",
"flate2",
@@ -991,7 +1057,7 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2184c40e7910529677831c8b481acf788ffd92427ed21fad65b6aa637e631b8"
dependencies = [
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-utils",
]
@@ -1028,21 +1094,21 @@ dependencies = [
[[package]]
name = "gix-object"
-version = "0.42.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d4f8efae72030df1c4a81d02dbe2348e748d9b9a11e108ed6efbd846326e051"
+checksum = "1fe2dc4a41191c680c942e6ebd630c8107005983c4679214fdb1007dcf5ae1df"
dependencies = [
"bstr",
"gix-actor",
"gix-date",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-hash 0.14.2",
"gix-utils",
"gix-validate",
"itoa",
"smallvec",
"thiserror",
- "winnow 0.6.8",
+ "winnow 0.6.13",
]
[[package]]
@@ -1053,7 +1119,7 @@ checksum = "e8bbb43d2fefdc4701ffdf9224844d05b136ae1b9a73c2f90710c8dd27a93503"
dependencies = [
"arc-swap",
"gix-date",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-fs",
"gix-hash 0.14.2",
"gix-object",
@@ -1073,7 +1139,7 @@ checksum = "b58bad27c7677fa6b587aab3a1aca0b6c97373bd371a0a4290677c838c9bcaf1"
dependencies = [
"gix-chunk",
"gix-diff",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-hash 0.14.2",
"gix-hashtable",
"gix-object",
@@ -1137,11 +1203,11 @@ dependencies = [
[[package]]
name = "gix-prompt"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5325eb17ce7b5e5d25dec5c2315d642a09d55b9888b3bf46b7d72e1621a55d8"
+checksum = "fddabbc7c51c241600ab3c4623b19fa53bde7c1a2f637f61043ed5fcadf000cc"
dependencies = [
- "gix-command 0.3.6",
+ "gix-command 0.3.7",
"gix-config-value",
"parking_lot",
"rustix",
@@ -1168,20 +1234,20 @@ dependencies = [
[[package]]
name = "gix-protocol"
-version = "0.45.0"
+version = "0.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aed3bb6179835a3250403baa9d7022579e559fc45f2efc416d9de1a14b5acf11"
+checksum = "3c140d4c6d209048826bad78f021a01b612830f89da356efeb31afe8957f8bee"
dependencies = [
"bstr",
"gix-credentials 0.24.2",
"gix-date",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-hash 0.14.2",
- "gix-transport 0.42.0",
+ "gix-transport 0.42.1",
"gix-utils",
"maybe-async",
"thiserror",
- "winnow 0.6.8",
+ "winnow 0.6.13",
]
[[package]]
@@ -1197,9 +1263,9 @@ dependencies = [
[[package]]
name = "gix-revwalk"
-version = "0.13.0"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7d393ae814eeaae41a333c0ff684b243121cc61ccdc5bbe9897094588047d"
+checksum = "4181db9cfcd6d1d0fd258e91569dbb61f94cb788b441b5294dd7f1167a3e788f"
dependencies = [
"gix-commitgraph",
"gix-date",
@@ -1259,13 +1325,13 @@ dependencies = [
[[package]]
name = "gix-transport"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d2f783b2fe86bf2a8cf1f3b8669d65b01ab4932f32cc0101d3893e1b16a3bd6"
+checksum = "eb0ffa5f869977f5b9566399154055902f05d7e85c787d5eacf551acdd0c4adf"
dependencies = [
"bstr",
- "gix-command 0.3.6",
- "gix-features 0.38.1",
+ "gix-command 0.3.7",
+ "gix-features 0.38.2",
"gix-packetline 0.17.5",
"gix-quote",
"gix-sec",
@@ -1275,9 +1341,9 @@ dependencies = [
[[package]]
name = "gix-traverse"
-version = "0.39.0"
+version = "0.39.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4029ec209b0cc480d209da3837a42c63801dd8548f09c1f4502c60accb62aeb"
+checksum = "f20cb69b63eb3e4827939f42c05b7756e3488ef49c25c412a876691d568ee2a0"
dependencies = [
"bitflags 2.5.0",
"gix-commitgraph",
@@ -1311,7 +1377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0db829ebdca6180fbe32be7aed393591df6db4a72dbbc0b8369162390954d1cf"
dependencies = [
"bstr",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-path",
"home",
"thiserror",
@@ -1330,9 +1396,9 @@ dependencies = [
[[package]]
name = "gix-validate"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e39fc6e06044985eac19dd34d474909e517307582e462b2eb4c8fa51b6241545"
+checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf"
dependencies = [
"bstr",
"thiserror",
@@ -1351,9 +1417,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.14.3"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hmac"
@@ -1396,14 +1462,134 @@ dependencies = [
"cc",
]
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
+
[[package]]
name = "idna"
-version = "0.5.0"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "icu_normalizer",
+ "icu_properties",
+ "smallvec",
+ "utf8_iter",
]
[[package]]
@@ -1455,6 +1641,12 @@ dependencies = [
"popol",
]
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
[[package]]
name = "itoa"
version = "1.0.11"
@@ -1535,14 +1727,14 @@ checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
"bitflags 2.5.0",
"libc",
- "redox_syscall",
+ "redox_syscall 0.4.1",
]
[[package]]
name = "libz-sys"
-version = "1.1.16"
+version = "1.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9"
+checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e"
dependencies = [
"cc",
"libc",
@@ -1552,9 +1744,15 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "litemap"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]]
name = "localtime"
@@ -1567,9 +1765,9 @@ dependencies = [
[[package]]
name = "lock_api"
-version = "0.4.11"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
@@ -1589,7 +1787,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.60",
+ "syn 2.0.66",
]
[[package]]
@@ -1609,9 +1807,9 @@ dependencies = [
[[package]]
name = "miniz_oxide"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
dependencies = [
"adler",
]
@@ -1716,9 +1914,9 @@ dependencies = [
[[package]]
name = "num-iter"
-version = "0.1.44"
+version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
+checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
@@ -1727,9 +1925,9 @@ dependencies = [
[[package]]
name = "num-traits"
-version = "0.2.18"
+version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
@@ -1802,9 +2000,9 @@ dependencies = [
[[package]]
name = "parking_lot"
-version = "0.12.1"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -1812,15 +2010,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.9"
+version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall",
+ "redox_syscall 0.5.1",
"smallvec",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.5",
]
[[package]]
@@ -1875,6 +2073,12 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+[[package]]
+name = "platforms"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
+
[[package]]
name = "poly1305"
version = "0.8.0"
@@ -1964,9 +2168,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.81"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
@@ -2036,7 +2240,6 @@ dependencies = [
"radicle-cob",
"radicle-crypto",
"radicle-git-ext",
- "radicle-ssh",
"serde",
"serde_json",
"siphasher 1.0.1",
@@ -2069,10 +2272,11 @@ dependencies = [
"serde",
"serde_json",
"shlex",
+ "ssh-agent-lib",
"tempfile",
"thiserror",
"timeago",
- "tree-sitter",
+ "tree-sitter 0.20.10",
"tree-sitter-bash",
"tree-sitter-c",
"tree-sitter-css",
@@ -2148,9 +2352,9 @@ dependencies = [
"qcheck",
"qcheck-macros",
"radicle-git-ext",
- "radicle-ssh",
"serde",
"sqlite",
+ "ssh-agent-lib",
"ssh-key",
"tempfile",
"thiserror",
@@ -2171,12 +2375,12 @@ dependencies = [
"bstr",
"either",
"gix-actor",
- "gix-features 0.38.1",
+ "gix-features 0.38.2",
"gix-hash 0.14.2",
"gix-odb",
"gix-pack",
- "gix-protocol 0.45.0",
- "gix-transport 0.42.0",
+ "gix-protocol 0.45.1",
+ "gix-transport 0.42.1",
"log",
"nonempty 0.9.0",
"radicle",
@@ -2257,16 +2461,6 @@ dependencies = [
"libc",
]
-[[package]]
-name = "radicle-ssh"
-version = "0.9.0"
-dependencies = [
- "byteorder",
- "log",
- "thiserror",
- "zeroize",
-]
-
[[package]]
name = "radicle-std-ext"
version = "0.1.0"
@@ -2355,6 +2549,15 @@ dependencies = [
"getrandom",
]
+[[package]]
+name = "raunch"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a67226789ccd419c55f5c826e04f7d58690b0593364f61bc8ed6e7dbbab49c5"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "redox_syscall"
version = "0.4.1"
@@ -2364,6 +2567,15 @@ dependencies = [
"bitflags 1.3.2",
]
+[[package]]
+name = "redox_syscall"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+dependencies = [
+ "bitflags 2.5.0",
+]
+
[[package]]
name = "redox_termios"
version = "0.1.3"
@@ -2372,9 +2584,9 @@ checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]]
name = "regex"
-version = "1.10.4"
+version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
@@ -2384,9 +2596,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
@@ -2395,9 +2607,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rfc6979"
@@ -2430,6 +2642,15 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
version = "0.38.34"
@@ -2445,9 +2666,9 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "salsa20"
@@ -2498,31 +2719,46 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "secrecy"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
+dependencies = [
+ "zeroize",
+]
+
+[[package]]
+name = "semver"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+
[[package]]
name = "serde"
-version = "1.0.198"
+version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
+checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.198"
+version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
+checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.60",
+ "syn 2.0.66",
]
[[package]]
name = "serde_json"
-version = "1.0.116"
+version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"indexmap",
"itoa",
@@ -2530,6 +2766,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "service-binding"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25663b9d8b83193ef83183edb3fd01e5447adb3e5baa35466ff9a6cd2408d6e8"
+dependencies = [
+ "raunch",
+]
+
[[package]]
name = "sha1_smol"
version = "1.0.0"
@@ -2624,9 +2869,9 @@ dependencies = [
[[package]]
name = "snapbox-macros"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1c4b838b05d15ab22754068cb73500b2f3b07bf09d310e15b27f88160f1de40"
+checksum = "b1f4c14672714436c09254801c934b203196a51182a5107fb76591c7cc56424d"
dependencies = [
"anstream",
]
@@ -2697,6 +2942,21 @@ dependencies = [
"sqlite3-src",
]
+[[package]]
+name = "ssh-agent-lib"
+version = "0.4.0"
+source = "git+https://github.com/wiktor-k/ssh-agent-lib?rev=refs/pull/81/head#d247e7edd91b80fa31feb19d18aa427d68c58b0c"
+dependencies = [
+ "byteorder",
+ "secrecy",
+ "service-binding",
+ "signature 2.2.0",
+ "ssh-encoding",
+ "ssh-key",
+ "subtle",
+ "thiserror",
+]
+
[[package]]
name = "ssh-cipher"
version = "0.2.0"
@@ -2732,6 +2992,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc"
dependencies = [
"bcrypt-pbkdf",
+ "ed25519-dalek",
+ "num-bigint-dig",
"p256",
"p384",
"p521",
@@ -2746,6 +3008,12 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
[[package]]
name = "subtle"
version = "2.5.0"
@@ -2765,20 +3033,31 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.60"
+version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
+[[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
+
[[package]]
name = "tar"
-version = "0.4.40"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
+checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909"
dependencies = [
"filetime",
"libc",
@@ -2823,22 +3102,22 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.60",
+ "syn 2.0.66",
]
[[package]]
@@ -2880,6 +3159,16 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1710e589de0a76aaf295cd47a6699f6405737dbfd3cf2b75c92d000b548d0e6"
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
[[package]]
name = "tinyvec"
version = "1.6.0"
@@ -2905,6 +3194,16 @@ dependencies = [
"regex",
]
+[[package]]
+name = "tree-sitter"
+version = "0.22.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df7cc499ceadd4dcdf7ec6d4cbc34ece92c3fa07821e287aedecd4416c516dca"
+dependencies = [
+ "cc",
+ "regex",
+]
+
[[package]]
name = "tree-sitter-bash"
version = "0.20.5"
@@ -2912,7 +3211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da2032c37eb2ce29fd18df7d3b94355fec8d6d854d8f80934955df542b5906"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2922,7 +3221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bbd5f3d8658c08581f8f2adac6c391c2e9fa00fe9246bf6c5f52213b9cc6b72"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2932,7 +3231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3306ddefa1d2681adda2613d11974ffabfbeb215e23235da6c862f3493a04fd"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2942,7 +3241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad6d11f19441b961af2fda7f12f5d0dac325f6d6de83836a1d3750018cc5114"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2953,17 +3252,17 @@ checksum = "042342584c5a7a0b833d9fc4e2bdab3f9868ddc6c4b339a1e01451c6720868bc"
dependencies = [
"regex",
"thiserror",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
name = "tree-sitter-html"
-version = "0.20.0"
+version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "017822b6bd42843c4bd67fabb834f61ce23254e866282dd93871350fd6b7fa1d"
+checksum = "95b3492b08a786bf5cc79feb0ef2ff3b115d5174364e0ddfd7860e0b9b088b53"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.22.6",
]
[[package]]
@@ -2973,7 +3272,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a9a38a9c679b55cc8d17350381ec08d69fa1a17a53fcf197f344516e485ed4d"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2983,7 +3282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c20d3ef8d202430b644a307e6299d84bf8ed87fa1b796e4638f8805a595060c"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -2993,7 +3292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c93b1b1fbd0d399db3445f51fd3058e43d0b4dcff62ddbdb46e66550978aa5"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -3003,7 +3302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d50ef383469df8485f024c5fb01faced8cb90368192a7ba02605b43b2427fe"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -3013,7 +3312,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0832309b0b2b6d33760ce5c0e818cb47e1d72b468516bfe4134408926fa7594"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -3023,7 +3322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca517f578a98b23d20780247cc2688407fa81effad5b627a5a364ec3339b53e8"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -3033,7 +3332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8bc1d2c24276a48ef097a71b56888ac9db63717e8f8d0b324668a27fd619670"
dependencies = [
"cc",
- "tree-sitter",
+ "tree-sitter 0.20.10",
]
[[package]]
@@ -3042,12 +3341,6 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
-[[package]]
-name = "unicode-bidi"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
-
[[package]]
name = "unicode-display-width"
version = "0.3.0"
@@ -3080,9 +3373,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unicode-width"
-version = "0.1.11"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "universal-hash"
@@ -3096,20 +3389,32 @@ dependencies = [
[[package]]
name = "url"
-version = "2.5.0"
+version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
[[package]]
name = "utf8parse"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "vcpkg"
@@ -3160,7 +3465,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.60",
+ "syn 2.0.66",
"wasm-bindgen-shared",
]
@@ -3182,7 +3487,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.60",
+ "syn 2.0.66",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -3195,9 +3500,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "winapi-util"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697"
+checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys 0.52.0",
]
@@ -3361,13 +3666,25 @@ dependencies = [
[[package]]
name = "winnow"
-version = "0.6.8"
+version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
+checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
dependencies = [
"memchr",
]
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
[[package]]
name = "xattr"
version = "1.3.1"
@@ -3385,8 +3702,75 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+[[package]]
+name = "yoke"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+ "synstructure",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+ "synstructure",
+]
+
[[package]]
name = "zeroize"
-version = "1.7.0"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
+checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.66",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 42cef9ba..25cf9dcd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,7 +11,6 @@ members = [
"radicle-fetch",
"radicle-node",
"radicle-remote-helper",
- "radicle-ssh",
"radicle-tools",
"radicle-signals",
]
@@ -22,7 +21,6 @@ default-members = [
"radicle-crdt",
"radicle-crypto",
"radicle-node",
- "radicle-ssh",
"radicle-remote-helper",
"radicle-term",
"radicle-signals",
diff --git a/radicle-cli/Cargo.toml b/radicle-cli/Cargo.toml
index 9de7d03d..e537b6b1 100644
--- a/radicle-cli/Cargo.toml
+++ b/radicle-cli/Cargo.toml
@@ -45,6 +45,7 @@ tree-sitter-bash = { version = "0.20" }
tree-sitter-go = { version = "0.20.0" }
tree-sitter-md = { version = "0.1.5" }
zeroize = { version = "1.1" }
+ssh-agent-lib = { version = "0.4.0", git = "https://github.com/wiktor-k/ssh-agent-lib", rev = "refs/pull/81/head", default-features = false }
[dependencies.radicle]
version = "0.11.0"
diff --git a/radicle-cli/src/commands/auth.rs b/radicle-cli/src/commands/auth.rs
index fe13ac88..b780e588 100644
--- a/radicle-cli/src/commands/auth.rs
+++ b/radicle-cli/src/commands/auth.rs
@@ -1,6 +1,6 @@
#![allow(clippy::or_fun_call)]
use std::ffi::OsString;
-use std::ops::Not as _;
+use std::ops::{Deref as _, Not as _};
use std::str::FromStr;
use anyhow::anyhow;
@@ -126,7 +126,7 @@ pub fn init(options: Options) -> anyhow::Result<()> {
spinner.warn();
}
}
- Err(e) if e.is_not_running() => {
+ Err(_) if ssh::agent::Agent::pid().is_none() => {
agent = false;
}
Err(e) => Err(e)?,
@@ -180,7 +180,16 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> {
// register it; only if it is running.
match ssh::agent::Agent::connect() {
Ok(mut agent) => {
- if agent.request_identities()?.contains(&profile.public_key) {
+ let ids = agent.request_identities().unwrap();
+ let has_pubkey = ids.iter().any(|id| {
+ if let ssh_agent_lib::ssh_key::public::KeyData::Ed25519(key) = id.pubkey {
+ *key.as_ref() == **profile.public_key.deref()
+ } else {
+ false
+ }
+ });
+
+ if has_pubkey {
term::success!("Radicle key already in ssh-agent");
return Ok(());
}
@@ -197,7 +206,7 @@ pub fn authenticate(options: Options, profile: &Profile) -> anyhow::Result<()> {
return Ok(());
}
- Err(e) if e.is_not_running() => {}
+ Err(_) if ssh::agent::Agent::pid().is_none() => {}
Err(e) => Err(e)?,
};
diff --git a/radicle-cli/src/commands/self.rs b/radicle-cli/src/commands/self.rs
index aad6768a..365f196f 100644
--- a/radicle-cli/src/commands/self.rs
+++ b/radicle-cli/src/commands/self.rs
@@ -144,11 +144,15 @@ fn all(profile: &Profile) -> anyhow::Result<()> {
]);
let ssh_agent = match ssh::agent::Agent::connect() {
- Ok(c) => term::format::positive(format!(
+ Ok(_) => term::format::positive(format!(
"running ({})",
- c.pid().map(|p| p.to_string()).unwrap_or(String::from("?"))
+ ssh::agent::Agent::pid()
+ .map(|p| p.to_string())
+ .unwrap_or(String::from("?"))
)),
- Err(e) if e.is_not_running() => term::format::yellow(String::from("not running")),
+ Err(_) if ssh::agent::Agent::pid().is_none() => {
+ term::format::yellow(String::from("not running"))
+ }
Err(e) => term::format::negative(format!("error: {e}")),
};
table.push([
diff --git a/radicle-crypto/Cargo.toml b/radicle-crypto/Cargo.toml
index d14900e4..d0b9bc9c 100644
--- a/radicle-crypto/Cargo.toml
+++ b/radicle-crypto/Cargo.toml
@@ -13,7 +13,7 @@ edition = "2021"
[features]
test = ["fastrand", "qcheck"]
-ssh = ["radicle-ssh", "ssh-key"]
+ssh = ["ssh-agent-lib", "ssh-key"]
[dependencies]
amplify = { version = "4.0.0" }
@@ -25,6 +25,7 @@ serde = { version = "1", features = ["derive"] }
sqlite = { version = "0.32.0", optional = true, features = ["bundled"] }
thiserror = { version = "1" }
zeroize = { version = "1.5.7" }
+ssh-agent-lib = { version = "0.4.0", git = "https://github.com/wiktor-k/ssh-agent-lib", rev = "refs/pull/81/head", default-features = false, optional = true }
[dependencies.radicle-git-ext]
version = "0.7.0"
@@ -42,12 +43,6 @@ version = "1"
default-features = false
optional = true
-[dependencies.radicle-ssh]
-path = "../radicle-ssh"
-version = "0"
-default-features = false
-optional = true
-
[dev-dependencies]
fastrand = { version = "2.0.0", default-features = false }
qcheck-macros = { version = "1", default-features = false }
diff --git a/radicle-crypto/src/ssh.rs b/radicle-crypto/src/ssh.rs
index 1f7e7e54..9f7c5683 100644
--- a/radicle-crypto/src/ssh.rs
+++ b/radicle-crypto/src/ssh.rs
@@ -5,13 +5,7 @@ use std::io;
use thiserror::Error;
-use radicle_ssh::encoding;
-use radicle_ssh::encoding::Encodable;
-use radicle_ssh::encoding::Encoding;
-use radicle_ssh::encoding::Reader;
-
use crate as crypto;
-use crate::PublicKey;
pub use keystore::{Keystore, Passphrase};
@@ -126,76 +120,25 @@ pub enum SignatureError {
#[error(transparent)]
Invalid(#[from] crypto::Error),
#[error(transparent)]
- Encoding(#[from] encoding::Error),
+ Encoding(#[from] ssh_agent_lib::proto::ProtoError),
#[error("unknown algorithm '{0}'")]
UnknownAlgorithm(String),
}
-impl Encodable for crypto::Signature {
- type Error = SignatureError;
-
- fn read(r: &mut encoding::Cursor) -> Result<Self, Self::Error> {
- let buf = r.read_string()?;
- let mut inner_strs = buf.reader(0);
-
- let sig_type = inner_strs.read_string()?;
- if sig_type != b"ssh-ed25519" {
- return Err(SignatureError::UnknownAlgorithm(
- String::from_utf8_lossy(sig_type).to_string(),
- ));
- }
- let sig = crypto::Signature::try_from(inner_strs.read_string()?)?;
-
- Ok(sig)
- }
-
- fn write<E: Encoding>(&self, buf: &mut E) {
- let mut inner_strs = Vec::new();
- inner_strs.extend_ssh_string(b"ssh-ed25519");
- inner_strs.extend_ssh_string(self.as_ref());
- buf.extend_ssh_string(&inner_strs);
- }
-}
-
#[derive(Debug, Error)]
pub enum PublicKeyError {
#[error(transparent)]
Invalid(#[from] crypto::Error),
#[error(transparent)]
- Encoding(#[from] encoding::Error),
+ Encoding(#[from] ssh_agent_lib::proto::ProtoError),
#[error("unknown algorithm '{0}'")]
UnknownAlgorithm(String),
}
-impl Encodable for PublicKey {
- type Error = PublicKeyError;
-
- fn read(r: &mut encoding::Cursor) -> Result<Self, Self::Error> {
- match r.read_string()? {
- b"ssh-ed25519" => {
- let s = r.read_string()?;
- let p = PublicKey::try_from(s)?;
-
- Ok(p)
- }
- v => Err(PublicKeyError::UnknownAlgorithm(
- String::from_utf8_lossy(v).to_string(),
- )),
- }
- }
-
- fn write<E: Encoding>(&self, w: &mut E) {
- let mut str_w: Vec<u8> = Vec::<u8>::new();
- str_w.extend_ssh_string(b"ssh-ed25519");
- str_w.extend_ssh_string(&self[..]);
- w.extend_ssh_string(&str_w)
- }
-}
-
#[derive(Debug, Error)]
pub enum SecretKeyError {
#[error(transparent)]
- Encoding(#[from] encoding::Error),
+ Encoding(#[from] ssh_agent_lib::proto::ProtoError),
#[error(transparent)]
Crypto(#[from] crypto::Error),
#[error(transparent)]
@@ -206,80 +149,13 @@ pub enum SecretKeyError {
Mismatch,
}
-impl Encodable for crypto::SecretKey {
- type Error = SecretKeyError;
-
- fn read(r: &mut encoding::Cursor) -> Result<Self, Self::Error> {
- match r.read_string()? {
- b"ssh-ed25519" => {
- let public = r.read_string()?;
- let pair = r.read_string()?;
- let _comment = r.read_string()?;
- let key = crypto::SecretKey::try_from(pair)?;
-
- if public != key.public_key().as_ref() {
- return Err(SecretKeyError::Mismatch);
- }
- Ok(key)
- }
- s => Err(SecretKeyError::UnknownAlgorithm(
- String::from_utf8_lossy(s).to_string(),
- )),
- }
- }
-
- fn write<E: Encoding>(&self, buf: &mut E) {
- let public = self.0.public_key();
-
- buf.extend_ssh_string(b"ssh-ed25519");
- buf.extend_ssh_string(public.as_ref());
- buf.extend_ssh_string(self.0.as_ref());
- buf.extend_ssh_string(b"radicle");
- }
-}
-
#[cfg(test)]
mod test {
- use std::sync::{Arc, Mutex};
-
- use qcheck_macros::quickcheck;
-
- use crate as crypto;
- use crate::{PublicKey, SecretKey};
- use radicle_ssh::agent::client::{AgentClient, ClientStream, Error};
- use radicle_ssh::encoding::*;
-
- #[derive(Clone, Default)]
- struct DummyStream {
- incoming: Arc<Mutex<Vec<u8>>>,
- }
-
- impl ClientStream for DummyStream {
- fn connect<P>(_path: P) -> Result<AgentClient<Self>, Error>
- where
- P: AsRef<std::path::Path> + Send,
- {
- panic!("This function should never be called!")
- }
-
- fn request(&mut self, buf: &[u8]) -> Result<Buffer, Error> {
- *self.incoming.lock().unwrap() = buf.to_vec();
-
- Ok(Buffer::default())
- }
- }
-
- #[quickcheck]
- fn prop_encode_decode_sk(input: [u8; 64]) {
- let mut buf = Buffer::default();
- let sk = crypto::SecretKey::from(input);
- sk.write(&mut buf);
-
- let mut cursor = buf.reader(0);
- let output = SecretKey::read(&mut cursor).unwrap();
-
- assert_eq!(sk, output);
- }
+ use crate::PublicKey;
+ use ssh_agent_lib::blocking::Client;
+ use ssh_agent_lib::proto::SignRequest;
+ use ssh_agent_lib::ssh_key::public::{Ed25519PublicKey, KeyData};
+ use std::ops::Deref;
#[test]
fn test_agent_encoding_remove() {
@@ -297,15 +173,15 @@ mod test {
37, 145, 51, 176, 174, 61, 136, 160, 107, 4, 95, 175, 144, // Key
];
- let stream = DummyStream::default();
- let mut agent = AgentClient::connect(stream.clone());
+ let mut client = Client::new(std::io::Cursor::new(vec![]));
- agent.remove_identity(&pk).unwrap();
+ client
+ .remove_identity(ssh_agent_lib::proto::RemoveIdentity {
+ pubkey: KeyData::Ed25519(Ed25519PublicKey(**pk.deref())),
+ })
+ .ok();
- assert_eq!(
- stream.incoming.lock().unwrap().as_slice(),
- expected.as_slice()
- );
+ assert_eq!(client.into_inner().into_inner(), expected.as_slice());
}
#[test]
@@ -327,15 +203,17 @@ mod test {
0, 0, 0, 0, // Signature flags
];
- let stream = DummyStream::default();
- let mut agent = AgentClient::connect(stream.clone());
+ let mut client = Client::new(std::io::Cursor::new(vec![]));
let data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
- agent.sign(&pk, &data).ok();
+ client
+ .sign(SignRequest {
+ pubkey: KeyData::Ed25519(Ed25519PublicKey(**pk.deref())),
+ data: data.clone(),
+ flags: 0,
+ })
+ .ok();
- assert_eq!(
- stream.incoming.lock().unwrap().as_slice(),
- expected.as_slice()
- );
+ assert_eq!(client.into_inner().into_inner(), expected);
}
}
diff --git a/radicle-crypto/src/ssh/agent.rs b/radicle-crypto/src/ssh/agent.rs
index 6f3d9854..b1877842 100644
--- a/radicle-crypto/src/ssh/agent.rs
+++ b/radicle-crypto/src/ssh/agent.rs
@@ -1,9 +1,9 @@
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;
-pub use radicle_ssh::agent::client::AgentClient;
-pub use radicle_ssh::agent::client::Error;
-pub use radicle_ssh::{self as ssh, agent::client::ClientStream};
+use ssh_agent_lib::proto::Credential;
+pub use ssh_agent_lib::proto::ProtoError as Error;
+use ssh_key::public::KeyData;
use crate::{PublicKey, SecretKey, Signature, Signer, SignerError};
@@ -13,28 +13,50 @@ pub use std::net::TcpStream as Stream;
pub use std::os::unix::net::UnixStream as Stream;
pub struct Agent {
- client: AgentClient<Stream>,
+ client: ssh_agent_lib::blocking::Client<Stream>,
}
impl Agent {
/// Connect to a running SSH agent.
- pub fn connect() -> Result<Self, ssh::agent::client::Error> {
- Stream::connect_env().map(|client| Self { client })
+ pub fn connect() -> Result<Self, Error> {
+ Ok(Agent {
+ client: ssh_agent_lib::blocking::Client::new(Stream::connect(
+ std::env::var("SSH_AUTH_SOCK").unwrap(),
+ )?),
+ })
}
/// Register a key with the agent.
- pub fn register(&mut self, key: &SecretKey) -> Result<(), ssh::Error> {
- self.client.add_identity(key, &[])
+ pub fn register(&mut self, key: &SecretKey) -> Result<(), Error> {
+ self.client
+ .add_identity(ssh_agent_lib::proto::AddIdentity {
+ credential: Credential::Key {
+ privkey: ssh_key::private::KeypairData::Ed25519(
+ ssh_key::private::Ed25519Keypair::from_bytes(&*key.deref()).unwrap(),
+ ),
+ comment: "".into(),
+ },
+ })
+ .unwrap();
+
+ Ok(())
}
/// Get a signer from this agent, given the public key.
pub fn signer(self, key: PublicKey) -> AgentSigner {
AgentSigner::new(self, key)
}
+
+ pub fn pid() -> Option<u32> {
+ use std::str::FromStr;
+ std::env::var("SSH_AGENT_PID")
+ .ok()
+ .and_then(|v| u32::from_str(&v).ok())
+ }
}
impl Deref for Agent {
- type Target = AgentClient<Stream>;
+ type Target = ssh_agent_lib::blocking::Client<Stream>;
fn deref(&self) -> &Self::Target {
&self.client
@@ -61,9 +83,14 @@ impl AgentSigner {
}
pub fn is_ready(&self) -> Result<bool, Error> {
- let ids = self.agent.lock().unwrap().request_identities()?;
-
- Ok(ids.contains(&self.public))
+ let ids = self.agent.lock().unwrap().request_identities().unwrap();
+ Ok(ids.iter().any(|id| {
+ if let KeyData::Ed25519(key) = id.pubkey {
+ *key.as_ref() == **self.public.deref()
+ } else {
+ false
+ }
+ }))
}
/// Box this signer into a [`Signer`].
@@ -85,11 +112,14 @@ impl Signer for AgentSigner {
let sig = self
.agent
.lock()
- // We'll take our chances here; the worse that can happen is the agent returns an error.
.unwrap_or_else(|e| e.into_inner())
- .sign(&self.public, msg)
+ .sign(ssh_agent_lib::proto::SignRequest {
+ pubkey: KeyData::Ed25519(ssh_key::public::Ed25519PublicKey(**self.public.deref())),
+ data: msg.into(),
+ flags: 0,
+ })
.map_err(SignerError::new)?;
-
- Ok(Signature::from(sig))
+ let bytes: [u8; 64] = sig.as_bytes().try_into().unwrap();
+ Ok(Signature::from(bytes))
}
}
diff --git a/radicle-ssh/Cargo.toml b/radicle-ssh/Cargo.toml
deleted file mode 100644
index 50add46b..00000000
--- a/radicle-ssh/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "radicle-ssh"
-description = "Radicle SSH library"
-homepage = "https://radicle.xyz"
-repository = "https://app.radicle.xyz/seeds/seed.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5"
-license = "Apache-2.0"
-version = "0.9.0"
-authors = [
- "Fintan Halpenny <fintan.halpenny@gmail.com>",
- "Pierre-Étienne Meunier <pe@pijul.org>",
- "cloudhead <cloudhead@radicle.xyz>"
-]
-edition = "2021"
-
-[dependencies]
-byteorder = "1.4"
-log = "0.4"
-thiserror = "1.0"
-zeroize = "1.5.7"
diff --git a/radicle-ssh/LICENSE b/radicle-ssh/LICENSE
deleted file mode 100644
index f433b1a5..00000000
--- a/radicle-ssh/LICENSE
+++ /dev/null
@@ -1,177 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
diff --git a/radicle-ssh/src/agent.rs b/radicle-ssh/src/agent.rs
deleted file mode 100644
index fd54bf85..00000000
--- a/radicle-ssh/src/agent.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-/// Write clients for SSH agents.
-pub mod client;
-
-mod msg;
-
-/// Constraints on how keys can be used.
-#[derive(Debug, PartialEq, Eq)]
-pub enum Constraint {
- /// The key shall disappear from the agent's memory after that many seconds.
- KeyLifetime { seconds: u32 },
- /// Signatures need to be confirmed by the agent (for instance using a dialog).
- Confirm,
- /// Custom constraints
- Extensions { name: Vec<u8>, details: Vec<u8> },
-}
diff --git a/radicle-ssh/src/agent/client.rs b/radicle-ssh/src/agent/client.rs
deleted file mode 100644
index 881c16fc..00000000
--- a/radicle-ssh/src/agent/client.rs
+++ /dev/null
@@ -1,423 +0,0 @@
-use std::fmt;
-use std::io::{Read, Write};
-use std::ops::DerefMut;
-use std::os::unix::net::UnixStream;
-use std::path::Path;
-use std::str::FromStr;
-
-use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
-use log::*;
-use thiserror::Error;
-use zeroize::Zeroize as _;
-
-use crate::agent::msg;
-use crate::agent::Constraint;
-use crate::encoding::{self, Encodable};
-use crate::encoding::{Buffer, Encoding, Reader};
-
-/// An ed25519 Signature.
-pub type Signature = [u8; 64];
-
-#[derive(Debug, Error)]
-pub enum Error {
- /// Agent protocol error.
- #[error("Agent protocol error")]
- AgentProtocolError,
- #[error("Agent failure")]
- AgentFailure,
- #[error("Unable to connect to ssh-agent. The environment variable `SSH_AUTH_SOCK` was set, but it points to a nonexistent file or directory.")]
- BadAuthSock,
- #[error(transparent)]
- Encoding(#[from] encoding::Error),
- #[error("Environment variable `{0}` not found")]
- EnvVar(&'static str),
- #[error(transparent)]
- Io(#[from] std::io::Error),
- #[error(transparent)]
- Private(Box<dyn std::error::Error + Send + Sync + 'static>),
- #[error(transparent)]
- Public(Box<dyn std::error::Error + Send + Sync + 'static>),
- #[error(transparent)]
- Signature(Box<dyn std::error::Error + Send + Sync + 'static>),
-}
-
-impl Error {
- pub fn is_not_running(&self) -> bool {
- matches!(self, Self::EnvVar("SSH_AUTH_SOCK"))
- }
-}
-
-/// SSH agent client.
-pub struct AgentClient<S> {
- stream: S,
-}
-
-impl<S> AgentClient<S> {
- /// Connect to an SSH agent via the provided stream (on Unix, usually a Unix-domain socket).
- pub fn connect(stream: S) -> Self {
- AgentClient { stream }
- }
-
- /// Get the agent PID.
- pub fn pid(&self) -> Option<u32> {
- std::env::var("SSH_AGENT_PID")
- .ok()
- .and_then(|v| u32::from_str(&v).ok())
- }
-}
-
-pub trait ClientStream: Sized + Send + Sync {
- /// Send an agent request through the stream and read the response.
- fn request(&mut self, req: &[u8]) -> Result<Buffer, Error>;
-
- /// How to connect the streaming socket
- fn connect<P>(path: P) -> Result<AgentClient<Self>, Error>
- where
- P: AsRef<Path> + Send;
-
- fn connect_env() -> Result<AgentClient<Self>, Error> {
- let Ok(var) = std::env::var("SSH_AUTH_SOCK") else {
- return Err(Error::EnvVar("SSH_AUTH_SOCK"));
- };
- match Self::connect(var) {
- Err(Error::Io(io_err)) if io_err.kind() == std::io::ErrorKind::NotFound => {
- Err(Error::BadAuthSock)
- }
- other => other,
- }
- }
-}
-
-impl<S: ClientStream> AgentClient<S> {
- /// Send a key to the agent, with a (possibly empty) slice of constraints
- /// to apply when using the key to sign.
- pub fn add_identity<K>(&mut self, key: &K, constraints: &[Constraint]) -> Result<(), Error>
- where
- K: Encodable,
- K::Error: std::error::Error + Send + Sync + 'static,
- {
- let mut buf = Buffer::default();
-
- buf.resize(4, 0);
-
- if constraints.is_empty() {
- buf.push(msg::ADD_IDENTITY)
- } else {
- buf.push(msg::ADD_ID_CONSTRAINED)
- }
- key.write(&mut buf);
-
- if !constraints.is_empty() {
- for cons in constraints {
- match *cons {
- Constraint::KeyLifetime { seconds } => {
- buf.push(msg::CONSTRAIN_LIFETIME);
- buf.deref_mut().write_u32::<BigEndian>(seconds)?
- }
- Constraint::Confirm => buf.push(msg::CONSTRAIN_CONFIRM),
- Constraint::Extensions {
- ref name,
- ref details,
- } => {
- buf.push(msg::CONSTRAIN_EXTENSION);
- buf.extend_ssh_string(name);
- buf.extend_ssh_string(details);
- }
- }
- }
- }
- buf.write_len();
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Add a smart card to the agent, with a (possibly empty) set of
- /// constraints to apply when signing.
- pub fn add_smartcard_key(
- &mut self,
- id: &str,
- pin: &[u8],
- constraints: &[Constraint],
- ) -> Result<(), Error> {
- let mut buf = Buffer::default();
-
- buf.resize(4, 0);
-
- if constraints.is_empty() {
- buf.push(msg::ADD_SMARTCARD_KEY)
- } else {
- buf.push(msg::ADD_SMARTCARD_KEY_CONSTRAINED)
- }
- buf.extend_ssh_string(id.as_bytes());
- buf.extend_ssh_string(pin);
-
- if !constraints.is_empty() {
- buf.deref_mut()
- .write_u32::<BigEndian>(constraints.len() as u32)?;
- for cons in constraints {
- match *cons {
- Constraint::KeyLifetime { seconds } => {
- buf.push(msg::CONSTRAIN_LIFETIME);
- buf.deref_mut().write_u32::<BigEndian>(seconds)?;
- }
- Constraint::Confirm => buf.push(msg::CONSTRAIN_CONFIRM),
- Constraint::Extensions {
- ref name,
- ref details,
- } => {
- buf.push(msg::CONSTRAIN_EXTENSION);
- buf.extend_ssh_string(name);
- buf.extend_ssh_string(details);
- }
- }
- }
- }
- buf.write_len();
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Lock the agent, making it refuse to sign until unlocked.
- pub fn lock(&mut self, passphrase: &[u8]) -> Result<(), Error> {
- let mut buf = Buffer::default();
-
- buf.resize(4, 0);
- buf.push(msg::LOCK);
- buf.extend_ssh_string(passphrase);
- buf.write_len();
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Unlock the agent, allowing it to sign again.
- pub fn unlock(&mut self, passphrase: &[u8]) -> Result<(), Error> {
- let mut buf = Buffer::default();
- buf.resize(4, 0);
- buf.push(msg::UNLOCK);
- buf.extend_ssh_string(passphrase);
- buf.write_len();
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Ask the agent for a list of the currently registered secret
- /// keys.
- pub fn request_identities<K>(&mut self) -> Result<Vec<K>, Error>
- where
- K: Encodable,
- K::Error: std::error::Error + Send + Sync + 'static,
- {
- let mut buf = Buffer::default();
- buf.resize(4, 0);
- buf.push(msg::REQUEST_IDENTITIES);
- buf.write_len();
-
- let mut keys = Vec::new();
- let resp = self.stream.request(&buf)?;
-
- if resp[0] == msg::IDENTITIES_ANSWER {
- let mut r = resp.reader(1);
- let n = r.read_u32()?;
-
- for _ in 0..n {
- let key = r.read_string()?;
- let _ = r.read_string()?;
- let mut r = key.reader(0);
-
- if let Ok(pk) = K::read(&mut r) {
- keys.push(pk);
- }
- }
- }
-
- Ok(keys)
- }
-
- /// Ask the agent to sign the supplied piece of data.
- pub fn sign<K>(&mut self, public: &K, data: &[u8]) -> Result<Signature, Error>
- where
- K: Encodable + fmt::Debug,
- {
- let req = self.prepare_sign_request(public, data);
- let resp = self.stream.request(&req)?;
-
- if !resp.is_empty() && resp[0] == msg::SIGN_RESPONSE {
- self.read_signature(&resp)
- } else if !resp.is_empty() && resp[0] == msg::FAILURE {
- Err(Error::AgentFailure)
- } else {
- Err(Error::AgentProtocolError)
- }
- }
-
- fn prepare_sign_request<K>(&self, public: &K, data: &[u8]) -> Buffer
- where
- K: Encodable + fmt::Debug,
- {
- // byte SSH_AGENTC_SIGN_REQUEST
- // string key blob
- // string data
- // uint32 flags
-
- let mut pk = Buffer::default();
- public.write(&mut pk);
-
- let total = 1 + pk.len() + 4 + data.len() + 4;
-
- let mut buf = Buffer::default();
- buf.write_u32::<BigEndian>(total as u32)
- .expect("Writing to a vector never fails");
- buf.push(msg::SIGN_REQUEST);
- buf.extend_from_slice(&pk);
- buf.extend_ssh_string(data);
-
- // Signature flags should be zero for ed25519.
- buf.write_u32::<BigEndian>(0).unwrap();
- buf
- }
-
- fn read_signature(&self, sig: &[u8]) -> Result<Signature, Error> {
- let mut r = sig.reader(1);
- let mut resp = r.read_string()?.reader(0);
- let _t = resp.read_string()?;
- let sig = resp.read_string()?;
-
- let mut out = [0; 64];
- out.copy_from_slice(sig);
-
- Ok(out)
- }
-
- /// Ask the agent to remove a key from its memory.
- pub fn remove_identity<K>(&mut self, public: &K) -> Result<(), Error>
- where
- K: Encodable,
- {
- let mut pk: Buffer = Vec::new().into();
- public.write(&mut pk);
-
- let total = 1 + pk.len();
-
- let mut buf = Buffer::default();
- buf.write_u32::<BigEndian>(total as u32)?;
- buf.push(msg::REMOVE_IDENTITY);
- buf.extend_from_slice(&pk);
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Ask the agent to remove a smartcard from its memory.
- pub fn remove_smartcard_key(&mut self, id: &str, pin: &[u8]) -> Result<(), Error> {
- let mut buf = Buffer::default();
- buf.resize(4, 0);
- buf.push(msg::REMOVE_SMARTCARD_KEY);
- buf.extend_ssh_string(id.as_bytes());
- buf.extend_ssh_string(pin);
- buf.write_len();
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Ask the agent to forget all known keys.
- pub fn remove_all_identities(&mut self) -> Result<(), Error> {
- let mut buf = Buffer::default();
- buf.resize(4, 0);
- buf.push(msg::REMOVE_ALL_IDENTITIES);
- buf.write_len();
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Send a custom message to the agent.
- pub fn extension(&mut self, typ: &[u8], ext: &[u8]) -> Result<(), Error> {
- let mut buf = Buffer::default();
-
- buf.resize(4, 0);
- buf.push(msg::EXTENSION);
- buf.extend_ssh_string(typ);
- buf.extend_ssh_string(ext);
- buf.write_len();
-
- self.stream.request(&buf)?;
-
- Ok(())
- }
-
- /// Ask the agent about supported extensions.
- pub fn query_extension(&mut self, typ: &[u8], mut ext: Buffer) -> Result<bool, Error> {
- let mut req = Buffer::default();
-
- req.resize(4, 0);
- req.push(msg::EXTENSION);
- req.extend_ssh_string(typ);
- req.write_len();
-
- let resp = self.stream.request(&req)?;
- let mut r = resp.reader(1);
- ext.extend(r.read_string()?);
-
- Ok(!resp.is_empty() && resp[0] == msg::SUCCESS)
- }
-}
-
-#[cfg(not(unix))]
-impl ClientStream for TcpStream {
- fn connect_uds<P>(_: P) -> Result<AgentClient<Self>, Error>
- where
- P: AsRef<Path> + Send,
- {
- Err(Error::AgentFailure)
- }
-
- fn read_response(&mut self, _: &mut Buffer) -> Result<(), Error> {
- Err(Error::AgentFailure)
- }
-
- fn connect_env() -> Result<AgentClient<Self>, Error> {
- Err(Error::AgentFailure)
- }
-}
-
-#[cfg(unix)]
-impl ClientStream for UnixStream {
- fn connect<P>(path: P) -> Result<AgentClient<Self>, Error>
- where
- P: AsRef<Path> + Send,
- {
- let stream = UnixStream::connect(path)?;
-
- Ok(AgentClient { stream })
- }
-
- fn request(&mut self, msg: &[u8]) -> Result<Buffer, Error> {
- let mut resp = Buffer::default();
-
- // Write the message
- self.write_all(msg)?;
- self.flush()?;
-
- // Read the length
- resp.resize(4, 0);
- self.read_exact(&mut resp)?;
-
- // Read the rest of the buffer
- let len = BigEndian::read_u32(&resp) as usize;
- resp.zeroize();
- resp.resize(len, 0);
- self.read_exact(&mut resp)?;
-
- Ok(resp)
- }
-}
diff --git a/radicle-ssh/src/agent/msg.rs b/radicle-ssh/src/agent/msg.rs
deleted file mode 100644
index d0786fd4..00000000
--- a/radicle-ssh/src/agent/msg.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-pub const FAILURE: u8 = 5;
-pub const SUCCESS: u8 = 6;
-pub const IDENTITIES_ANSWER: u8 = 12;
-pub const SIGN_RESPONSE: u8 = 14;
-#[allow(dead_code)]
-pub const EXTENSION_FAILURE: u8 = 28;
-
-pub const REQUEST_IDENTITIES: u8 = 11;
-pub const SIGN_REQUEST: u8 = 13;
-pub const ADD_IDENTITY: u8 = 17;
-pub const REMOVE_IDENTITY: u8 = 18;
-pub const REMOVE_ALL_IDENTITIES: u8 = 19;
-pub const ADD_ID_CONSTRAINED: u8 = 25;
-pub const ADD_SMARTCARD_KEY: u8 = 20;
-pub const REMOVE_SMARTCARD_KEY: u8 = 21;
-pub const LOCK: u8 = 22;
-pub const UNLOCK: u8 = 23;
-pub const ADD_SMARTCARD_KEY_CONSTRAINED: u8 = 26;
-pub const EXTENSION: u8 = 27;
-
-pub const CONSTRAIN_LIFETIME: u8 = 1;
-pub const CONSTRAIN_CONFIRM: u8 = 2;
-pub const CONSTRAIN_EXTENSION: u8 = 3;
diff --git a/radicle-ssh/src/encoding.rs b/radicle-ssh/src/encoding.rs
deleted file mode 100644
index 8342eefa..00000000
--- a/radicle-ssh/src/encoding.rs
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2016 Pierre-Étienne Meunier
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-use std::ops::DerefMut;
-
-use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
-use thiserror::Error;
-use zeroize::Zeroizing;
-
-/// General purpose writable byte buffer we use everywhere.
-pub type Buffer = Zeroizing<Vec<u8>>;
-
-#[derive(Debug, Error)]
-pub enum Error {
- /// Index out of bounds
- #[error("Index out of bounds")]
- IndexOutOfBounds,
-}
-
-pub trait Encodable: Sized {
- type Error: std::error::Error + Send + Sync + 'static;
-
- /// Read from the SSH format.
- fn read(reader: &mut Cursor) -> Result<Self, Self::Error>;
- /// Write to the SSH format.
- fn write<E: Encoding>(&self, buf: &mut E);
-}
-
-/// Encode in the SSH format.
-pub trait Encoding {
- /// Push an SSH-encoded string to `self`.
- fn extend_ssh_string(&mut self, s: &[u8]);
- /// Push an SSH-encoded blank string of length `s` to `self`.
- fn extend_ssh_string_blank(&mut self, s: usize) -> &mut [u8];
- /// Push an SSH-encoded multiple-precision integer.
- fn extend_ssh_mpint(&mut self, s: &[u8]);
- /// Push an SSH-encoded list.
- fn extend_list<'a, I: Iterator<Item = &'a [u8]>>(&mut self, list: I);
- /// Push an SSH-encoded unsigned 32-bit integer.
- fn extend_u32(&mut self, u: u32);
- /// Push an SSH-encoded empty list.
- fn write_empty_list(&mut self);
- /// Write the buffer length at the beginning of the buffer.
- fn write_len(&mut self);
-}
-
-/// Encoding length of the given mpint.
-pub fn mpint_len(s: &[u8]) -> usize {
- let mut i = 0;
- while i < s.len() && s[i] == 0 {
- i += 1
- }
- (if s[i] & 0x80 != 0 { 5 } else { 4 }) + s.len() - i
-}
-
-impl Encoding for Vec<u8> {
- fn extend_ssh_string(&mut self, s: &[u8]) {
- self.write_u32::<BigEndian>(s.len() as u32).unwrap();
- self.extend(s);
- }
-
- fn extend_ssh_string_blank(&mut self, len: usize) -> &mut [u8] {
- self.write_u32::<BigEndian>(len as u32).unwrap();
- let current = self.len();
- self.resize(current + len, 0u8);
-
- &mut self[current..]
- }
-
- fn extend_ssh_mpint(&mut self, s: &[u8]) {
- // Skip initial 0s.
- let mut i = 0;
- while i < s.len() && s[i] == 0 {
- i += 1
- }
- // If the first non-zero is >= 128, write its length (u32, BE), followed by 0.
- if s[i] & 0x80 != 0 {
- self.write_u32::<BigEndian>((s.len() - i + 1) as u32)
- .unwrap();
- self.push(0)
- } else {
- self.write_u32::<BigEndian>((s.len() - i) as u32).unwrap();
- }
- self.extend(&s[i..]);
- }
-
- fn extend_u32(&mut self, s: u32) {
- let mut buf = [0x0; 4];
- BigEndian::write_u32(&mut buf, s);
- self.extend(buf);
- }
-
- fn extend_list<'a, I: Iterator<Item = &'a [u8]>>(&mut self, list: I) {
- let len0 = self.len();
- self.extend([0, 0, 0, 0]);
-
- let mut first = true;
- for i in list {
- if !first {
- self.push(b',')
- } else {
- first = false;
- }
- self.extend(i)
- }
- let len = (self.len() - len0 - 4) as u32;
-
- BigEndian::write_u32(&mut self[len0..], len);
- }
-
- fn write_empty_list(&mut self) {
- self.extend([0, 0, 0, 0]);
- }
-
- fn write_len(&mut self) {
- let len = self.len() - 4;
- BigEndian::write_u32(&mut self[..], len as u32);
- }
-}
-
-impl Encoding for Buffer {
- fn extend_ssh_string(&mut self, s: &[u8]) {
- self.deref_mut().extend_ssh_string(s)
- }
-
- fn extend_ssh_string_blank(&mut self, len: usize) -> &mut [u8] {
- self.deref_mut().extend_ssh_string_blank(len)
- }
-
- fn extend_ssh_mpint(&mut self, s: &[u8]) {
- self.deref_mut().extend_ssh_mpint(s)
- }
-
- fn extend_list<'a, I: Iterator<Item = &'a [u8]>>(&mut self, list: I) {
- self.deref_mut().extend_list(list)
- }
-
- fn write_empty_list(&mut self) {
- self.deref_mut().write_empty_list()
- }
-
- fn extend_u32(&mut self, s: u32) {
- self.deref_mut().extend_u32(s);
- }
-
- fn write_len(&mut self) {
- self.deref_mut().write_len()
- }
-}
-
-/// A cursor-like trait to read SSH-encoded things.
-pub trait Reader {
- /// Create an SSH reader for `self`.
- fn reader(&self, starting_at: usize) -> Cursor;
-}
-
-impl Reader for Buffer {
- fn reader(&self, starting_at: usize) -> Cursor {
- Cursor {
- s: self,
- position: starting_at,
- }
- }
-}
-
-impl Reader for [u8] {
- fn reader(&self, starting_at: usize) -> Cursor {
- Cursor {
- s: self,
- position: starting_at,
- }
- }
-}
-
-/// A cursor-like type to read SSH-encoded values.
-#[derive(Debug)]
-pub struct Cursor<'a> {
- s: &'a [u8],
- #[doc(hidden)]
- pub position: usize,
-}
-
-impl<'a> Cursor<'a> {
- /// Read one string from this reader.
- pub fn read_string(&mut self) -> Result<&'a [u8], Error> {
- let len = self.read_u32()? as usize;
- if self.position + len <= self.s.len() {
- let result = &self.s[self.position..(self.position + len)];
- self.position += len;
- Ok(result)
- } else {
- Err(Error::IndexOutOfBounds)
- }
- }
-
- /// Read a `u32` from this reader.
- pub fn read_u32(&mut self) -> Result<u32, Error> {
- if self.position + 4 <= self.s.len() {
- let u = BigEndian::read_u32(&self.s[self.position..]);
- self.position += 4;
- Ok(u)
- } else {
- Err(Error::IndexOutOfBounds)
- }
- }
-
- /// Read one byte from this reader.
- pub fn read_byte(&mut self) -> Result<u8, Error> {
- if self.position < self.s.len() {
- let u = self.s[self.position];
- self.position += 1;
- Ok(u)
- } else {
- Err(Error::IndexOutOfBounds)
- }
- }
-
- pub fn read_bytes<const S: usize>(&mut self) -> Result<[u8; S], Error> {
- let mut buf = [0; S];
- for b in buf.iter_mut() {
- *b = self.read_byte()?;
- }
- Ok(buf)
- }
-
- /// Read one byte from this reader.
- pub fn read_mpint(&mut self) -> Result<&'a [u8], Error> {
- let len = self.read_u32()? as usize;
- if self.position + len <= self.s.len() {
- let result = &self.s[self.position..(self.position + len)];
- self.position += len;
- Ok(result)
- } else {
- Err(Error::IndexOutOfBounds)
- }
- }
-}
diff --git a/radicle-ssh/src/lib.rs b/radicle-ssh/src/lib.rs
deleted file mode 100644
index bd07d900..00000000
--- a/radicle-ssh/src/lib.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-pub mod agent;
-pub mod encoding;
-
-pub use agent::client::Error;
diff --git a/radicle/Cargo.toml b/radicle/Cargo.toml
index 946a0c13..15afad43 100644
--- a/radicle/Cargo.toml
+++ b/radicle/Cargo.toml
@@ -58,11 +58,6 @@ path = "../radicle-crypto"
version = "0"
features = ["radicle-git-ext", "ssh", "sqlite", "cyphernet"]
-[dependencies.radicle-ssh]
-path = "../radicle-ssh"
-version = "0"
-default-features = false
-
[dependencies.qcheck]
version = "1"
default-features = false
Exit code: 0
shell: 'cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny clippy::all cargo build --all-targets --workspace cargo doc --workspace cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name f4939526-fcc5-452f-9677-6e12e8d4e259 -v /opt/radcis/ci.rad.levitte.org/cci/state/f4939526-fcc5-452f-9677-6e12e8d4e259/s:/f4939526-fcc5-452f-9677-6e12e8d4e259/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/f4939526-fcc5-452f-9677-6e12e8d4e259/w:/f4939526-fcc5-452f-9677-6e12e8d4e259/w -w /f4939526-fcc5-452f-9677-6e12e8d4e259/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:bookworm bash /f4939526-fcc5-452f-9677-6e12e8d4e259/s/script.sh
+ cargo --version
info: syncing channel updates for '1.77-x86_64-unknown-linux-gnu'
info: latest update on 2024-04-09, rust version 1.77.2 (25ef9e3d8 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-std'
info: installing component 'rustc'
cargo 1.77.2 (e52e36006 2024-03-26)
+ rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09)
+ cargo fmt --check
error: 'cargo-fmt' is not installed for the toolchain '1.77-x86_64-unknown-linux-gnu'.
To install, run `rustup component add --toolchain 1.77-x86_64-unknown-linux-gnu rustfmt`
Exit code: 1
{
"response": "finished",
"result": "failure"
}