difftreelog
feat initial work on russh+remowt prototype
in: trunk
30 files changed
.rustfmt.tomldiffbeforeafterboth--- /dev/null
+++ b/.rustfmt.toml
@@ -0,0 +1 @@
+hard_tabs = true
Cargo.lockdiffbeforeafterboth306 packageslockfile v3
Might be heavy and slow!
addr2line
0.22.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678depends onused byadler
1.0.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35feused byadler2
2.0.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627used byaead
0.5.2crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0depends onused byaes
0.8.4crates.io↘ 3↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0depends onaes-gcm
0.10.3crates.io↘ 6↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1aho-corasick
1.1.3crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916depends onanstream
0.6.15crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526depends onused byanstyle
1.0.8crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1anstyle-parse
0.2.5crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cbdepends onused byanstyle-query
1.1.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422adepends onused byanstyle-wincon
3.0.4crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8depends onused byanyhow
1.0.86crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063daasync-broadcast
0.7.1crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7eused byasync-channel
2.3.1crates.io↘ 4↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6aasync-executor
1.13.0crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7used byasync-fs
2.1.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04aused byasync-io
2.3.3crates.io↘ 11↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964depends onasync-lock
3.4.0crates.io↘ 3↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18async-process
2.2.3crates.io↘ 12↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2adepends onused byasync-recursion
1.1.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11depends onused byasync-signal
0.2.9crates.io↘ 10↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdfb3634b73397aa844481f814fad23bbf07fdb0eabec10f2eb95e58944b1ec32depends onused byasync-task
4.7.1crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3deasync-trait
0.1.81crates.io↘ 3↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107depends onatomic-waker
1.1.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0used byautocfg
1.3.0crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0backtrace
0.3.73crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0adepends onused bybase16ct
0.2.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cfbase64ct
1.6.0crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5bbcrypt-pbkdf
0.10.0crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2depends onbifrostlink-ports
0.1.0workspace↘ 4↖ 2bindgen
0.69.4crates.io↘ 12↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0depends onused bybitflags
1.3.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718abitflags
2.6.0crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71deblock-buffer
0.10.4crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71depends onused byblock-padding
0.3.3crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93depends onblocking
1.6.1crates.io↘ 5↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29eablowfish
0.9.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7depends onused bybstr
1.10.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0cdepends onused bybumpalo
3.16.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012cused bybyteorder
1.5.0crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64bbytes
1.7.1crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50cbc
0.1.2crates.io↘ 1↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6depends oncc
1.1.7crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbcused bycexpr
0.6.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766depends onused bycfg_aliases
0.2.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724used bycfg-if
1.0.0crates.io↘ 0↖ 18sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbaf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fdchacha20
0.9.1crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818depends oncipher
0.4.4crates.io↘ 2↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3daddepends onclang-sys
1.8.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4depends onused byclap
4.5.16crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019depends onclap_builder
4.5.15crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6used byclap_derive
4.5.13crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0used byclap_lex
0.7.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97used bycolorchoice
1.0.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0used byconcurrent-queue
2.5.0crates.io↘ 1↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973depends onconst-oid
0.9.6crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8used bycpufeatures
0.2.12crates.io↘ 1↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504depends oncrc32fast
1.4.2crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3depends onused bycrossbeam-utils
0.8.20crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80used bycrypto-bigint
0.5.5crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76used bycrypto-common
0.1.6crates.io↘ 3↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3ctr
0.9.2crates.io↘ 1↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835depends oncurve25519-dalek
4.1.3crates.io↘ 8↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2bedepends oncurve25519-dalek-derive
0.1.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3depends onused bydata-encoding
2.6.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2used bydelegate
0.12.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79bdepends onused byder
0.7.9crates.io↘ 3↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0derivative
2.2.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumfcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770bdepends onused bydes
0.8.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1edepends onused bydigest
0.10.7crates.io↘ 4↖ 12sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292ecdsa
0.16.9crates.io↘ 6↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bcaed25519
2.2.3crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53depends onused byed25519-dalek
2.1.1crates.io↘ 7↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871depends oneither
1.13.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0used byelliptic-curve
0.13.8crates.io↘ 13↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47depends onendi
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bfused byenum-repr
0.2.6crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18depends onused byenumflags2
0.7.10crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133ddepends onenumflags2_derive
0.7.10crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumde0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8depends onused byequivalent
1.0.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5used byerrno
0.3.9crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820badepends onused byevent-listener
5.3.1crates.io↘ 3↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675baevent-listener-strategy
0.5.2crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1fastrand
2.1.0crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51aff
0.13.0crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449depends onfiat-crypto
0.2.9crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811dused byflate2
1.0.32crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666depends onused byfuchsia-cprng
0.1.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3baused byfutures
0.3.30crates.io↘ 7↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0depends onfutures-channel
0.3.30crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78depends onfutures-core
0.3.30crates.io↘ 0↖ 12sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1dfutures-executor
0.3.30crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01dused byfutures-io
0.3.30crates.io↘ 0↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1futures-lite
2.3.0crates.io↘ 5↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5futures-macro
0.3.30crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489acdepends onused byfutures-sink
0.3.30crates.io↘ 0↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5futures-task
0.3.30crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004futures-util
0.3.30crates.io↘ 10↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48depends ongeneric-array
0.14.7crates.io↘ 3↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9agetrandom
0.2.15crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7used byghash
0.5.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1depends onused bygimli
0.29.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffdused byglob
0.3.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9bused byglobset
0.4.14crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1used bygroup
0.13.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63depends onused byhashbrown
0.14.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1used byheck
0.5.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55eaused byhermit-abi
0.3.9crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024used byhermit-abi
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumfbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fccused byhex-literal
0.4.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46used byhkdf
0.12.4crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7depends onused byhmac
0.12.1crates.io↘ 1↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5edepends onhome
0.5.9crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5depends onindexmap
2.3.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumde3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0depends onused byinout
0.1.3crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5depends onis_terminal_polyfill
1.70.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecfused byitertools
0.12.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569depends onused byitoa
1.0.11crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695bused byjs-sys
0.3.70crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37adepends onused bylazy_static
1.5.0crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fedepends onlazycell
1.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55used bylibc
0.2.155crates.io↘ 0↖ 20sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847clibm
0.2.8crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058linux-raw-sys
0.4.14crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89used bylog
0.4.22crates.io↘ 0↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24md5
0.7.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771used bymemchr
2.7.4crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3memoffset
0.9.1crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218adepends onused byminimal-lexical
0.2.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79aused byminiz_oxide
0.7.4crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08depends onused byminiz_oxide
0.8.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1depends onused bymio
1.0.1crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4used bynix
0.29.0crates.io↘ 5↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46nom
7.1.3crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4adepends onused bynon-zero-byte-slice
0.1.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum89daa1daa11c9df05d1181bcd0936d8066f8543144d77b09808eb78d65e38024depends onused bynu-ansi-term
0.46.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84depends onused bynum-bigint
0.4.6crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9used bynum-bigint-dig
0.8.4crates.io↘ 9↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151depends onused bynum-integer
0.1.46crates.io↘ 1↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858fdepends onnum-iter
0.1.45crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bfused bynum-traits
0.2.19crates.io↘ 2↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841depends onobject
0.36.2crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170edepends onused byonce_cell
1.19.0crates.io↘ 0↖ 9sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92opaque-debug
0.3.1crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381openssh
0.11.0crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0f27389e5da64700a3efb7f925e442f824f6e3d4b1c27f75e115a92ad3aecbb1depends onused byopenssh-mux-client
0.17.5crates.io↘ 10↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb87a1b6780afc5f9f38f81f7928c91c3c24532c48914477ab6caf2ba076ae866depends onused byopenssh-mux-client-error
0.1.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum015d49e592f4d2a456033e6ec48036588e8e58c8908424b1bc40994de58ae648depends onused byordered-stream
0.2.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50depends onused byoverload
0.1.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39used byp256
0.13.2crates.io↘ 4↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4bp384
0.13.0crates.io↘ 4↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209p521
0.13.3crates.io↘ 6↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2pageant
0.0.1-beta.3github.com/Eugeny/russh/↘ 7↖ 1sourcegit+https://github.com/Eugeny/russh/#4115b8fd3a94c17c0178761ea769a40ca410903dused bypam-client
0.5.0crates.io↘ 6↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum51bd776116a7ada5ebbe31f54cdc5b1030ed7265686cf7c8a21c057a2f8dab9aused bypam-sys
1.0.0-alpha5crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumce9484729b3e52c0bacdc5191cb6a6a5f31ef4c09c5e4ab1209d3340ad9e997bdepends onused byparking
2.2.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9caepassword-hash
0.4.2crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700depends onused bypbkdf2
0.11.0crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917used bypbkdf2
0.12.2crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2depends onpem-rfc7468
0.7.0crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412depends onpin-project-lite
0.2.14crates.io↘ 0↖ 13sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02pin-utils
0.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184used bypiper
0.2.3crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391used bypkcs1
0.7.5crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47fdepends onpkcs5
0.7.1crates.io↘ 7↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6pkcs8
0.10.2crates.io↘ 4↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7polkit-backend
0.1.0workspace↘ 11↖ 0polling
3.7.2crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985bdepends onused bypoly1305
0.8.0crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abfpolyval
0.6.2crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25used byppv-lite86
0.2.20crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04depends onused byprimeorder
0.13.6crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6depends onproc-macro-crate
3.1.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284depends onproc-macro2
1.0.86crates.io↘ 1↖ 27sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77depends onused by- async-recursion
1.1.1 - async-trait
0.1.81 - bindgen
0.69.4 - clap_derive
4.5.13 - curve25519-dalek-derive
0.1.1 - delegate
0.12.0 - derivative
2.2.0 - enum-repr
0.2.6 - enumflags2_derive
0.7.10 - futures-macro
0.3.30 - quote
1.0.36 - serde_derive
1.0.208 - serde_repr
0.1.19 - syn
1.0.109 - syn
2.0.72 - thiserror-impl
1.0.63 - tokio-macros
2.4.0 - tracing-attributes
0.1.27 - typed-builder-macro
0.20.0 - wasm-bindgen-backend
0.2.93 - wasm-bindgen-macro-support
0.2.93 - windows-implement
0.58.0 - windows-interface
0.58.0 - zbus_macros
4.4.0 - zerocopy-derive
0.7.35 - zvariant_derive
4.2.0 - zvariant_utils
2.1.0
- async-recursion
quote
1.0.36crates.io↘ 1↖ 27sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7depends onused by- async-recursion
1.1.1 - async-trait
0.1.81 - bindgen
0.69.4 - clap_derive
4.5.13 - curve25519-dalek-derive
0.1.1 - delegate
0.12.0 - derivative
2.2.0 - enum-repr
0.2.6 - enumflags2_derive
0.7.10 - futures-macro
0.3.30 - serde_derive
1.0.208 - serde_repr
0.1.19 - syn
1.0.109 - syn
2.0.72 - thiserror-impl
1.0.63 - tokio-macros
2.4.0 - tracing-attributes
0.1.27 - typed-builder-macro
0.20.0 - wasm-bindgen-backend
0.2.93 - wasm-bindgen-macro
0.2.93 - wasm-bindgen-macro-support
0.2.93 - windows-implement
0.58.0 - windows-interface
0.58.0 - zbus_macros
4.4.0 - zerocopy-derive
0.7.35 - zvariant_derive
4.2.0 - zvariant_utils
2.1.0
- async-recursion
rand
0.4.6crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293used byrand
0.8.5crates.io↘ 3↖ 7sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404rand_chacha
0.3.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88depends onused byrand_core
0.3.1crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4bdepends onused byrand_core
0.4.2crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dcused byrand_core
0.6.4crates.io↘ 1↖ 16sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922cdepends onrdrand
0.4.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2depends onused byredox_syscall
0.4.1crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aadepends onused byregex
1.10.6crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619used byregex-automata
0.4.7crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92dfused byregex-syntax
0.8.4crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209bremove_dir_all
0.5.3crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7depends onused byremowt-agent
0.1.0workspace↘ 19↖ 0rfc6979
0.4.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2depends onused byrpassword
6.0.1crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956used byrsa
0.9.6crates.io↘ 13↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfcdepends onrussh
0.46.0-beta.4github.com/Eugeny/russh/↘ 35↖ 1sourcegit+https://github.com/Eugeny/russh/#4115b8fd3a94c17c0178761ea769a40ca410903ddepends on- aes
0.8.4 - aes-gcm
0.10.3 - async-trait
0.1.81 - bitflags
2.6.0 - byteorder
1.5.0 - cbc
0.1.2 - chacha20
0.9.1 - ctr
0.9.2 - curve25519-dalek
4.1.3 - des
0.8.1 - digest
0.10.7 - elliptic-curve
0.13.8 - flate2
1.0.32 - futures
0.3.30 - generic-array
0.14.7 - hex-literal
0.4.1 - hmac
0.12.1 - log
0.4.22 - num-bigint
0.4.6 - once_cell
1.19.0 - p256
0.13.2 - p384
0.13.0 - p521
0.13.3 - poly1305
0.8.0 - rand
0.8.5 - rand_core
0.6.4 - russh-cryptovec
0.7.3 - russh-keys
0.46.0-beta.3 - sha1
0.10.6 - sha2
0.10.8 - ssh-encoding
0.2.0 - ssh-key
0.6.6 - subtle
2.6.1 - thiserror
1.0.63 - tokio
1.39.3
used by- aes
russh-config
0.7.1github.com/Eugeny/russh/↘ 7↖ 1sourcegit+https://github.com/Eugeny/russh/#4115b8fd3a94c17c0178761ea769a40ca410903dused byrussh-cryptovec
0.7.3github.com/Eugeny/russh/↘ 2↖ 2sourcegit+https://github.com/Eugeny/russh/#4115b8fd3a94c17c0178761ea769a40ca410903ddepends onrussh-keys
0.46.0-beta.3github.com/Eugeny/russh/↘ 44↖ 2sourcegit+https://github.com/Eugeny/russh/#4115b8fd3a94c17c0178761ea769a40ca410903ddepends on- aes
0.8.4 - async-trait
0.1.81 - bcrypt-pbkdf
0.10.0 - block-padding
0.3.3 - byteorder
1.5.0 - cbc
0.1.2 - ctr
0.9.2 - data-encoding
2.6.0 - der
0.7.9 - digest
0.10.7 - ecdsa
0.16.9 - ed25519-dalek
2.1.1 - elliptic-curve
0.13.8 - futures
0.3.30 - hmac
0.12.1 - home
0.5.9 - inout
0.1.3 - log
0.4.22 - md5
0.7.0 - num-integer
0.1.46 - p256
0.13.2 - p384
0.13.0 - p521
0.13.3 - pageant
0.0.1-beta.3 - pbkdf2
0.11.0 - pkcs1
0.7.5 - pkcs5
0.7.1 - pkcs8
0.10.2 - rand
0.8.5 - rand_core
0.6.4 - rsa
0.9.6 - russh-cryptovec
0.7.3 - sec1
0.7.3 - serde
1.0.208 - sha1
0.10.6 - sha2
0.10.8 - spki
0.7.3 - ssh-encoding
0.2.0 - ssh-key
0.6.6 - thiserror
1.0.63 - tokio
1.39.3 - tokio-stream
0.1.15 - typenum
1.17.0 - zeroize
1.8.1
- aes
rustc_version
0.4.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366depends onused byrustc-demangle
0.1.24crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1fused byrustc-hash
1.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2used byrustix
0.38.34crates.io↘ 5↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730frustversion
1.0.17crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6used byryu
1.0.18crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9fused bysalsa20
0.10.2crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213depends onused byscrypt
0.11.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1fdepends onused bysec1
0.7.3crates.io↘ 6↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dcsemver
1.0.23crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988bused bysendfd
0.4.3crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum604b71b8fc267e13bb3023a2c901126c8f349393666a6d98ac1ae5729b701798depends onused byserde
1.0.208crates.io↘ 1↖ 19sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2depends onused by- bifrostlink
0.1.0 - bstr
1.10.0 - ed25519-dalek
2.1.1 - enumflags2
0.7.10 - non-zero-byte-slice
0.1.0 - openssh-mux-client
0.17.5 - polkit-shared
0.1.0 - remowt-agent
0.1.0 - remowt-link-shared
0.1.0 - rpassword
6.0.1 - russh-keys
0.46.0-beta.3 - serde_json
1.0.125 - ssh_format
0.14.1 - ssh_format_error
0.1.0 - ui-prompt
0.1.0 - zbus
4.4.0 - zbus_names
3.0.0 - zbus_polkit
4.0.0 - zvariant
4.2.0
- bifrostlink
serde_derive
1.0.208crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcfdepends onused byserde_json
1.0.125crates.io↘ 4↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31edserde_repr
0.1.19crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9depends onused bysha1
0.10.6crates.io↘ 3↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksume3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6badepends onsha2
0.10.8crates.io↘ 3↖ 13sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8depends onsharded-slab
0.1.7crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6depends onused byshell-escape
0.1.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184fused byshlex
1.3.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64used bysignal-hook-registry
1.4.2crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1depends onused bysignature
2.2.0crates.io↘ 2↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329dedepends onslab
0.4.9crates.io↘ 1↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67depends onsmallvec
1.13.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67socket2
0.5.7crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191cdepends onused byspin
0.9.8crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67used byspki
0.7.3crates.io↘ 2↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumd91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29ddepends onssh_format
0.14.1crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum24ab31081d1c9097c327ec23550858cb5ffb4af6b866c1ef4d728455f01f3304depends onused byssh_format_error
0.1.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbe3c6519de7ca611f71ef7e8a56eb57aa1c818fecb5242d0a0f39c83776c210cdepends onssh-cipher
0.2.0crates.io↘ 9↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumcaac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784fdepends onused byssh-encoding
0.2.0crates.io↘ 3↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumeb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15depends onssh-key
0.6.6crates.io↘ 15↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafcdepends onstatic_assertions
1.1.0crates.io↘ 0↖ 4sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543fstrsim
0.11.1crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4fused bysubtle
2.6.1crates.io↘ 0↖ 16sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292syn
1.0.109crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237syn
2.0.72crates.io↘ 3↖ 22sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8afused by- async-recursion
1.1.1 - async-trait
0.1.81 - bindgen
0.69.4 - clap_derive
4.5.13 - curve25519-dalek-derive
0.1.1 - delegate
0.12.0 - enumflags2_derive
0.7.10 - futures-macro
0.3.30 - serde_derive
1.0.208 - serde_repr
0.1.19 - thiserror-impl
1.0.63 - tokio-macros
2.4.0 - tracing-attributes
0.1.27 - typed-builder-macro
0.20.0 - wasm-bindgen-backend
0.2.93 - wasm-bindgen-macro-support
0.2.93 - windows-implement
0.58.0 - windows-interface
0.58.0 - zbus_macros
4.4.0 - zerocopy-derive
0.7.35 - zvariant_derive
4.2.0 - zvariant_utils
2.1.0
- async-recursion
tempdir
0.3.7crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8depends onused bytempfile
3.11.0crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53thiserror
1.0.63crates.io↘ 1↖ 8sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724depends onthiserror-impl
1.0.63crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261depends onused bythread_local
1.1.8crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719cdepends onused bytokio
1.39.3crates.io↘ 10↖ 18sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5depends onused by- bifrostlink
0.1.0 - bifrostlink-ports
0.1.0 - openssh
0.11.0 - openssh-mux-client
0.17.5 - pageant
0.0.1-beta.3 - polkit-backend
0.1.0 - remowt-agent
0.1.0 - remowt-link-shared
0.1.0 - remowt-ssh
0.1.0 - russh
0.46.0-beta.4 - russh-config
0.7.1 - russh-keys
0.46.0-beta.3 - sendfd
0.4.3 - tokio-io-utility
0.7.6 - tokio-stream
0.1.15 - tokio-util
0.7.11 - ui-prompt
0.1.0 - zbus
4.4.0
- bifrostlink
tokio-io-utility
0.7.6crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8d672654d175710e52c7c41f6aec77c62b3c0954e2a7ebce9049d1e94ed7c263depends onused bytokio-macros
2.4.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752depends onused bytokio-stream
0.1.15crates.io↘ 4↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37afused bytokio-util
0.7.11crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1toml_datetime
0.6.8crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41used bytoml_edit
0.21.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1used bytracing
0.1.40crates.io↘ 3↖ 10sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364eftracing-attributes
0.1.27crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7depends onused bytracing-core
0.1.32crates.io↘ 2↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54depends ontracing-log
0.2.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3used bytracing-subscriber
0.3.18crates.io↘ 6↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8bdepends ontyped-builder
0.20.0crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum7e14ed59dc8b7b26cacb2a92bad2e8b1f098806063898ab42a3bd121d7d45e75depends onused bytyped-builder-macro
0.20.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum560b82d656506509d43abe30e0ba64c56b1953ab3d4fe7ba5902747a7a3cedd5depends onused bytypenum
1.17.0crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825uds_windows
1.1.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9depends onused byui-prompt
0.1.0workspace↘ 6↖ 2unicode-ident
1.0.12crates.io↘ 0↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4buniversal-hash
0.5.1crates.io↘ 2↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumfc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07eadepends onused byutf8parse
0.2.2crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821uuid
1.10.0crates.io↘ 1↖ 3sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314depends onvaluable
0.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6dused byversion_check
0.9.5crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105aused bywasi
0.11.0+wasi-snapshot-preview1crates.io↘ 0↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423used bywasite
0.1.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumb8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855bused bywasm-bindgen
0.2.93crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5used bywasm-bindgen-backend
0.2.93crates.io↘ 7↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77bdepends onwasm-bindgen-macro
0.2.93crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccfused bywasm-bindgen-macro-support
0.2.93crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumafc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836used byweb-sys
0.3.70crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0depends onused bywhoami
1.5.1crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksuma44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9used bywinapi
0.3.9crates.io↘ 2↖ 6sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419winapi-i686-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6used bywinapi-x86_64-pc-windows-gnu
0.4.0crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183fused bywindows
0.58.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumdd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6depends onused bywindows_aarch64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3used bywindows_aarch64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469used bywindows_i686_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0bused bywindows_i686_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66used bywindows_i686_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66used bywindows_x86_64_gnu
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78used bywindows_x86_64_gnullvm
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0dused bywindows_x86_64_msvc
0.52.6crates.io↘ 0↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ecused bywindows-core
0.58.0crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99depends onused bywindows-implement
0.58.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579bdepends onused bywindows-interface
0.58.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515depends onused bywindows-result
0.2.0crates.io↘ 1↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0edepends onwindows-strings
0.1.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10depends onused bywindows-sys
0.52.0crates.io↘ 1↖ 15sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33ddepends onwindows-targets
0.52.6crates.io↘ 8↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973depends onwinnow
0.5.40crates.io↘ 1↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumf593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876depends onused byxdg-home
1.2.0crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8depends onused byzbus
4.4.0crates.io↘ 31↖ 5sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumbb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725depends on- async-broadcast
0.7.1 - async-executor
1.13.0 - async-fs
2.1.2 - async-io
2.3.3 - async-lock
3.4.0 - async-process
2.2.3 - async-recursion
1.1.1 - async-task
4.7.1 - async-trait
0.1.81 - blocking
1.6.1 - enumflags2
0.7.10 - event-listener
5.3.1 - futures-core
0.3.30 - futures-sink
0.3.30 - futures-util
0.3.30 - hex
0.4.3 - nix
0.29.0 - ordered-stream
0.2.0 - rand
0.8.5 - serde
1.0.208 - serde_repr
0.1.19 - sha1
0.10.6 - static_assertions
1.1.0 - tokio
1.39.3 - tracing
0.1.40 - uds_windows
1.1.0 - windows-sys
0.52.0 - xdg-home
1.2.0 - zbus_macros
4.4.0 - zbus_names
3.0.0 - zvariant
4.2.0
- async-broadcast
zbus_macros
4.4.0crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983eused byzbus_names
3.0.0crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6cused byzbus_polkit
4.0.0crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum00a29bfa927b29f91b7feb4e1990f2dd1b4604072f493dc2f074cf59e4e0ba90zerocopy
0.7.35crates.io↘ 2↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0depends onused byzerocopy-derive
0.7.35crates.io↘ 3↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumfa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3edepends onused byzeroize
1.8.1crates.io↘ 0↖ 11sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4ddezvariant
4.2.0crates.io↘ 5↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81feused byzvariant_derive
4.2.0crates.io↘ 5↖ 1sourceregistry+https://github.com/rust-lang/crates.io-indexchecksum73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449used byzvariant_utils
2.1.0crates.io↘ 3↖ 2sourceregistry+https://github.com/rust-lang/crates.io-indexchecksumc51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340depends on
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,6 +2,6 @@
members = ["cmds/*", "crates/*"]
resolver = "2"
-[workspace.packages]
+[workspace.dependencies]
bifrostlink = { path = "../bifrostlink/crates/bifrostlink" }
bifrostlink-ports = { path = "../bifrostlink/crates/bifrostlink-ports" }
Justfilediffbeforeafterboth--- /dev/null
+++ b/Justfile
@@ -0,0 +1,12 @@
+dev: dev-build dev-install
+
+dev-install:
+ mkdir -p ./target/libexec
+ ln -sf ./target/x86_64-unknown-linux-musl/release/remowt-agent ./target/libexec/remowt-x86_64-linux
+
+dev-build:
+ cargo build --release --target=x86_64-unknown-linux-musl -p remowt-agent
+
+dev-deploy: dev-build dev-install
+ ssh edgeworth2 mkdir -p /home/lach/.remowt
+ rsync -arv ./target/x86_64-unknown-linux-musl/release/remowt-agent edgeworth2:/home/lach/.remowt/remowt-agent
cmds/polkit-backend/Cargo.tomldiffbeforeafterboth--- a/cmds/polkit-backend/Cargo.toml
+++ /dev/null
@@ -1,17 +0,0 @@
-[package]
-name = "polkit-backend"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-anyhow = "1.0.86"
-clap = { version = "4.5.11", features = ["derive"] }
-nix = "0.29.0"
-pam-client = "0.5.0"
-polkit-shared = { version = "0.1.0", path = "../../crates/polkit-shared" }
-tokio = { version = "1.39.2", features = ["macros", "rt", "rt-multi-thread"] }
-tracing = "0.1.40"
-tracing-subscriber = "0.3.18"
-ui-prompt = { version = "0.1.0", path = "../../crates/ui-prompt" }
-zbus = { version = "4.4.0", features = ["tokio"] }
-zbus_polkit = { version = "4.0.0", features = ["tokio"] }
cmds/polkit-backend/etc/systemd/system/remowt-polkit-helper.servicediffbeforeafterboth--- a/cmds/polkit-backend/etc/systemd/system/remowt-polkit-helper.service
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=Remowt polkit helper service
-
-[Service]
-Type=dbus
-BusName=lach.polkit.helper1
-ExecStart=@libexecdir@/polkit-backend
-# TODO: Hardening
-
-[Install]
-WantedBy=multi-user.target
-Alias=dbus-lach.polkit.helper1.service
cmds/polkit-backend/share/dbus-1/system-services/lach.polkit.helper1.confdiffbeforeafterboth--- a/cmds/polkit-backend/share/dbus-1/system-services/lach.polkit.helper1.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-[D-BUS Service]
-Name=lach.polkit.helper1
-Exec=/bin/false
-User=root
-SystemdService=dbus-lach.polkit.helper1.service
cmds/polkit-backend/share/dbus-1/system.d/lach.polkit.helper1.confdiffbeforeafterboth--- a/cmds/polkit-backend/share/dbus-1/system.d/lach.polkit.helper1.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "https://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
- <policy user="root">
- <allow own = "lach.polkit.helper1"/>
- <allow send_interface="lach.PolkitInputHandler"/>
- </policy>
- <policy context="default">
- <allow send_destination="lach.polkit.helper1"/>
- <deny send_interface="lach.PolkitInputHandler"/>
- </policy>
-</busconfig>
cmds/polkit-backend/src/main.rsdiffbeforeafterboth--- a/cmds/polkit-backend/src/main.rs
+++ /dev/null
@@ -1,238 +0,0 @@
-use std::collections::{HashMap, HashSet};
-use std::ffi::{CStr, CString};
-use std::future::pending;
-use std::sync::LazyLock;
-
-use anyhow::Context as _;
-use clap::Parser;
-use nix::unistd::{setuid, Uid, User};
-use pam_client::{Context, ConversationHandler, ErrorCode, Flag};
-use polkit_shared::BackendRequest;
-use tokio::runtime::Handle;
-use tokio::task::{block_in_place, spawn_blocking};
-use tracing::trace;
-use ui_prompt::dbus::DbusPrompterProxyBlocking;
-use ui_prompt::{BlockingPrompter, Prompter};
-use zbus::fdo;
-use zbus::message::Header;
-use zbus::zvariant::OwnedValue;
-use zbus::{blocking, interface, proxy, Connection};
-
-struct Helper {
- connection: Connection,
- blocking_connection: blocking::Connection,
-}
-
-static ALLOWED_ENVIRONMENT: LazyLock<HashSet<&str>> = LazyLock::new(|| {
- [
- // pam ssh agent auth
- "SSH_AUTH_SOCK",
- // ssh itself provides this when running PAM
- "SSH_AUTH_INFO_0",
- // contains user which ran sudo
- "SUDO_USER",
- ]
- .into_iter()
- .collect()
-});
-
-struct Conversation<P>(P);
-impl<P: BlockingPrompter> Conversation<P> {
- fn prompt_inner(&self, echo: bool, prompt: &CStr) -> Result<CString, ErrorCode> {
- trace!("do prompt");
- let out = self
- .0
- .prompt_text(
- echo,
- &prompt.to_string_lossy(),
- "PAM prompt request",
- &[],
- )
- .map_err(|e| {
- trace!("prompt error: {e}");
- ErrorCode::CONV_ERR
- })?;
- CString::new(out).map_err(|_| ErrorCode::CONV_AGAIN)
- }
- fn text_inner(&self, error: bool, msg: &CStr) {
- trace!("do text");
- let msg = msg.to_string_lossy();
- let _ = self.0.display_text(error, &msg, &[]);
- }
-}
-impl<P: BlockingPrompter> ConversationHandler for Conversation<P> {
- fn prompt_echo_on(&mut self, prompt: &CStr) -> Result<CString, ErrorCode> {
- self.prompt_inner(true, prompt)
- }
-
- fn prompt_echo_off(&mut self, prompt: &CStr) -> Result<CString, ErrorCode> {
- self.prompt_inner(false, prompt)
- }
-
- fn text_info(&mut self, msg: &CStr) {
- self.text_inner(false, msg)
- }
-
- fn error_msg(&mut self, msg: &CStr) {
- self.text_inner(true, msg)
- }
-
- fn radio_prompt(&mut self, prompt: &CStr) -> Result<bool, ErrorCode> {
- let prompt = prompt.to_string_lossy();
- let result = self
- .0
- .prompt_radio(&prompt, "PAM prompt request", &[])
- .map_err(|_| ErrorCode::CONV_ERR)?;
- Ok(result)
- }
-}
-
-#[proxy(
- default_service = "org.freedesktop.DBus",
- default_path = "/org/freedesktop/DBus"
-)]
-trait DBus {
- fn get_connection_credentials(&self, body: &str) -> zbus::Result<HashMap<String, OwnedValue>>;
-}
-
-#[interface(name = "lach.PolkitHelper")]
-impl Helper {
- async fn init_conversation(
- &self,
- request: BackendRequest,
- #[zbus(header)] hdr: Header<'_>,
- ) -> fdo::Result<()> {
- let Some(sender) = hdr.sender().map(|v| v.to_owned()) else {
- trace!("missing sender");
- return Err(fdo::Error::AuthFailed("missing sender".to_owned()));
- };
-
- let dbus = DBusProxy::new(&self.connection).await?;
-
- // TOCTOU: sender might be already disconnected, and there might be another
- // user with different user id here, but does it matters?
- let reply = dbus.get_connection_credentials(&sender).await?;
- let uid: u32 = (&reply["UnixUserID"]).try_into().unwrap();
-
- let blocking_connection = self.blocking_connection.clone();
- let thread_result: fdo::Result<()> = block_in_place(move || {
- trace!("find user");
- let user = User::from_uid(Uid::from_raw(uid))
- .map_err(|_| fdo::Error::AuthFailed("error querying user".to_owned()))?
- .ok_or_else(|| fdo::Error::AuthFailed("uid not found".to_owned()))?;
-
- let responder = DbusPrompterProxyBlocking::new(
- &blocking_connection,
- sender,
- request.prompter_path,
- )?;
- let conversation = Conversation(responder);
- trace!("run context for {}", &user.name);
- let mut ctx = Context::new(
- // TODO: Should another scope be used?
- "login",
- Some(&user.name),
- conversation,
- )
- .map_err(|_| fdo::Error::Failed("pam context init failed".to_owned()))?;
-
- trace!("fill env");
- for (k, v) in request.environment {
- if k.contains('=') || !ALLOWED_ENVIRONMENT.contains(k.as_str()) {
- continue;
- }
- let _ = ctx.putenv(format!("{k}={v}"));
- }
-
- trace!("authenticate");
- ctx.authenticate(Flag::NONE)
- .map_err(|_| fdo::Error::AuthFailed("pam authentication failed".to_owned()))?;
-
- trace!("acct mgmt");
- ctx.acct_mgmt(Flag::NONE)
- .map_err(|_| fdo::Error::AuthFailed("pam acct mgmt failed".to_owned()))?;
-
- Ok(())
- });
-
- thread_result?;
-
- trace!("respond");
- let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&self.connection).await?;
-
- let identity_details = request
- .identity
- .details
- .iter()
- .map(|(k, v)| (k.as_str(), (**v).try_clone().expect("success")))
- .collect::<HashMap<_, _>>();
- proxy
- .authentication_agent_response2(
- uid,
- &request.cookie,
- &zbus_polkit::policykit1::Identity {
- identity_kind: &request.identity.kind,
- identity_details: &identity_details,
- },
- )
- .await?;
- Ok(())
- }
-}
-
-const OBJ_PATH: &str = "/lach/PolkitHelper";
-
-#[derive(Parser)]
-struct Opts {
- /// Not recommended: start as a session connection, then use escalation
- /// to respond to polkit requests.
- #[arg(long)]
- session: bool,
-}
-
-#[tokio::main]
-async fn main() -> anyhow::Result<()> {
- tracing_subscriber::fmt::init();
- let opts = Opts::parse();
- let connection = if opts.session {
- Connection::session().await
- } else {
- Connection::system().await
- }
- .context("failed to open connection")?;
-
- let session = opts.session;
- let blocking_connection: anyhow::Result<blocking::Connection> = spawn_blocking(move || {
- Ok(if session {
- blocking::Connection::session()?
- } else {
- blocking::Connection::system()?
- })
- })
- .await?;
- let blocking_connection = blocking_connection.context("failed to open blocking connection")?;
-
- if opts.session {
- setuid(Uid::from_raw(0))
- .context("polkit-backend needs to be suid if run in session mode")?;
- }
-
- connection
- .object_server()
- .at(
- OBJ_PATH,
- Helper {
- connection: connection.clone(),
- blocking_connection,
- },
- )
- .await
- .context("failed listen path")?;
-
- connection
- .request_name("lach.polkit.helper1")
- .await
- .context("failed to request name")?;
-
- pending().await
-}
cmds/polkit-dbus-helper/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "polkit-backend"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.86"
+clap = { version = "4.5.11", features = ["derive"] }
+nix = "0.29.0"
+pam-client = "0.5.0"
+polkit-shared = { version = "0.1.0", path = "../../crates/polkit-shared" }
+tokio = { version = "1.39.2", features = ["macros", "rt", "rt-multi-thread"] }
+tracing = "0.1.40"
+tracing-subscriber = "0.3.18"
+ui-prompt = { version = "0.1.0", path = "../../crates/ui-prompt" }
+zbus = { version = "4.4.0", features = ["tokio"] }
+zbus_polkit = { version = "4.0.0", features = ["tokio"] }
cmds/polkit-dbus-helper/README.adocdiffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/README.adoc
@@ -0,0 +1,8 @@
+== What is it?
+
+Usually, there is a `polkit-agent-helper-1` suid binary installed on the system with polkit package.
+
+This, however, an alternative to that approach, a system daemon listening for dbus requests, which works
+without using suid binaries.
+
+In future it will provide some additional features.
cmds/polkit-dbus-helper/etc/systemd/system/remowt-polkit-helper.servicediffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/etc/systemd/system/remowt-polkit-helper.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Remowt polkit helper service
+
+[Service]
+Type=dbus
+BusName=lach.polkit.helper1
+ExecStart=@libexecdir@/polkit-backend
+# TODO: Hardening
+
+[Install]
+WantedBy=multi-user.target
+Alias=dbus-lach.polkit.helper1.service
cmds/polkit-dbus-helper/share/dbus-1/system-services/lach.polkit.helper1.confdiffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/share/dbus-1/system-services/lach.polkit.helper1.conf
@@ -0,0 +1,5 @@
+[D-BUS Service]
+Name=lach.polkit.helper1
+Exec=/bin/false
+User=root
+SystemdService=dbus-lach.polkit.helper1.service
cmds/polkit-dbus-helper/share/dbus-1/system.d/lach.polkit.helper1.confdiffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/share/dbus-1/system.d/lach.polkit.helper1.conf
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" "https://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="root">
+ <allow own = "lach.polkit.helper1"/>
+ <allow send_interface="lach.PolkitInputHandler"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="lach.polkit.helper1"/>
+ <deny send_interface="lach.PolkitInputHandler"/>
+ </policy>
+</busconfig>
cmds/polkit-dbus-helper/src/main.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/polkit-dbus-helper/src/main.rs
@@ -0,0 +1,236 @@
+use std::collections::{HashMap, HashSet};
+use std::ffi::{CStr, CString};
+use std::future::pending;
+use std::sync::LazyLock;
+
+use anyhow::Context as _;
+use clap::Parser;
+use nix::unistd::{setuid, Uid, User};
+use pam_client::{Context, ConversationHandler, ErrorCode, Flag};
+use polkit_shared::BackendRequest;
+use tokio::task::{block_in_place, spawn_blocking};
+use tracing::trace;
+use ui_prompt::dbus::DbusPrompterProxyBlocking;
+use ui_prompt::BlockingPrompter;
+use zbus::fdo;
+use zbus::message::Header;
+use zbus::zvariant::OwnedValue;
+use zbus::{blocking, interface, proxy, Connection};
+
+struct Helper {
+ connection: Connection,
+ blocking_connection: blocking::Connection,
+}
+
+static ALLOWED_ENVIRONMENT: LazyLock<HashSet<&str>> = LazyLock::new(|| {
+ [
+ // pam ssh agent auth
+ "SSH_AUTH_SOCK",
+ // ssh itself provides this when running PAM
+ "SSH_AUTH_INFO_0",
+ // contains user which ran sudo
+ "SUDO_USER",
+ ]
+ .into_iter()
+ .collect()
+});
+
+struct Conversation<P>(P);
+impl<P: BlockingPrompter> Conversation<P> {
+ fn prompt_inner(&self, echo: bool, prompt: &CStr) -> Result<CString, ErrorCode> {
+ trace!("do prompt");
+ let out = self
+ .0
+ .prompt_text(echo, &prompt.to_string_lossy(), "PAM prompt request", &[])
+ .map_err(|e| {
+ trace!("prompt error: {e}");
+ ErrorCode::CONV_ERR
+ })?;
+ CString::new(out).map_err(|_| ErrorCode::CONV_AGAIN)
+ }
+ fn text_inner(&self, error: bool, msg: &CStr) {
+ trace!("do text");
+ let msg = msg.to_string_lossy();
+ let _ = self.0.display_text(error, &msg, &[]);
+ }
+}
+impl<P: BlockingPrompter> ConversationHandler for Conversation<P> {
+ fn prompt_echo_on(&mut self, prompt: &CStr) -> Result<CString, ErrorCode> {
+ self.prompt_inner(true, prompt)
+ }
+
+ fn prompt_echo_off(&mut self, prompt: &CStr) -> Result<CString, ErrorCode> {
+ self.prompt_inner(false, prompt)
+ }
+
+ fn text_info(&mut self, msg: &CStr) {
+ self.text_inner(false, msg)
+ }
+
+ fn error_msg(&mut self, msg: &CStr) {
+ self.text_inner(true, msg)
+ }
+
+ fn radio_prompt(&mut self, prompt: &CStr) -> Result<bool, ErrorCode> {
+ let prompt = prompt.to_string_lossy();
+ let result = self
+ .0
+ .prompt_radio(&prompt, "PAM prompt request", &[])
+ .map_err(|_| ErrorCode::CONV_ERR)?;
+ Ok(result)
+ }
+}
+
+#[proxy(
+ default_service = "org.freedesktop.DBus",
+ default_path = "/org/freedesktop/DBus"
+)]
+trait DBus {
+ fn get_connection_credentials(&self, body: &str) -> zbus::Result<HashMap<String, OwnedValue>>;
+}
+
+#[interface(name = "lach.PolkitHelper")]
+impl Helper {
+ async fn init_conversation(
+ &self,
+ request: BackendRequest,
+ #[zbus(header)] hdr: Header<'_>,
+ ) -> fdo::Result<()> {
+ let Some(sender) = hdr.sender().map(|v| v.to_owned()) else {
+ trace!("missing sender");
+ return Err(fdo::Error::AuthFailed("missing sender".to_owned()));
+ };
+
+ let dbus = DBusProxy::new(&self.connection).await?;
+
+ // TOCTOU: sender might be already disconnected, and there might be another
+ // user with different user id here, but does it matters?
+ let reply = dbus.get_connection_credentials(&sender).await?;
+ let connection_uid: u32 = (&reply["UnixUserID"]).try_into().unwrap();
+
+ let identity = request.identity.clone();
+ let blocking_connection = self.blocking_connection.clone();
+ let thread_result: fdo::Result<()> = block_in_place(move || {
+ trace!("find user");
+ let Some(identity_uid) = identity.uid() else {
+ return Err(fdo::Error::AuthFailed("can't process identity".to_owned()));
+ };
+ let user = User::from_uid(identity_uid)
+ .map_err(|_| fdo::Error::AuthFailed("error querying user".to_owned()))?
+ .ok_or_else(|| fdo::Error::AuthFailed("uid not found".to_owned()))?;
+
+ let responder = DbusPrompterProxyBlocking::new(
+ &blocking_connection,
+ sender,
+ request.prompter_path,
+ )?;
+ let conversation = Conversation(responder);
+ trace!("run context for {}", &user.name);
+ let mut ctx = Context::new(
+ // TODO: Should another scope be used?
+ "login",
+ Some(&user.name),
+ conversation,
+ )
+ .map_err(|_| fdo::Error::Failed("pam context init failed".to_owned()))?;
+
+ trace!("fill env");
+ for (k, v) in request.environment {
+ if k.contains('=') || !ALLOWED_ENVIRONMENT.contains(k.as_str()) {
+ continue;
+ }
+ let _ = ctx.putenv(format!("{k}={v}"));
+ }
+
+ trace!("authenticate");
+ ctx.authenticate(Flag::NONE)
+ .map_err(|_| fdo::Error::AuthFailed("pam authentication failed".to_owned()))?;
+
+ trace!("acct mgmt");
+ ctx.acct_mgmt(Flag::NONE)
+ .map_err(|_| fdo::Error::AuthFailed("pam acct mgmt failed".to_owned()))?;
+
+ Ok(())
+ });
+
+ thread_result?;
+
+ trace!("respond");
+ let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&self.connection).await?;
+
+ let identity_details = request
+ .identity
+ .details
+ .iter()
+ .map(|(k, v)| (k.as_str(), (**v).try_clone().expect("success")))
+ .collect::<HashMap<_, _>>();
+ proxy
+ .authentication_agent_response2(
+ connection_uid,
+ &request.cookie,
+ &zbus_polkit::policykit1::Identity {
+ identity_kind: &request.identity.kind,
+ identity_details: &identity_details,
+ },
+ )
+ .await?;
+ Ok(())
+ }
+}
+
+const OBJ_PATH: &str = "/lach/PolkitHelper";
+
+#[derive(Parser)]
+struct Opts {
+ /// Not recommended: start as a session connection, then use escalation
+ /// to respond to polkit requests.
+ #[arg(long)]
+ session: bool,
+}
+
+#[tokio::main]
+async fn main() -> anyhow::Result<()> {
+ tracing_subscriber::fmt::init();
+ let opts = Opts::parse();
+ let connection = if opts.session {
+ Connection::session().await
+ } else {
+ Connection::system().await
+ }
+ .context("failed to open connection")?;
+
+ let session = opts.session;
+ let blocking_connection: anyhow::Result<blocking::Connection> = spawn_blocking(move || {
+ Ok(if session {
+ blocking::Connection::session()?
+ } else {
+ blocking::Connection::system()?
+ })
+ })
+ .await?;
+ let blocking_connection = blocking_connection.context("failed to open blocking connection")?;
+
+ if opts.session {
+ setuid(Uid::from_raw(0))
+ .context("polkit-backend needs to be suid if run in session mode")?;
+ }
+
+ connection
+ .object_server()
+ .at(
+ OBJ_PATH,
+ Helper {
+ connection: connection.clone(),
+ blocking_connection,
+ },
+ )
+ .await
+ .context("failed listen path")?;
+
+ connection
+ .request_name("lach.polkit.helper1")
+ .await
+ .context("failed to request name")?;
+
+ pending().await
+}
cmds/remowt-agent/Cargo.tomldiffbeforeafterboth--- a/cmds/remowt-agent/Cargo.toml
+++ b/cmds/remowt-agent/Cargo.toml
@@ -5,12 +5,18 @@
[dependencies]
anyhow = "1.0.86"
+bifrostlink.workspace = true
+bifrostlink-ports.workspace = true
clap = { version = "4.5.13", features = ["derive"] }
-pam-client = "0.5.0"
+futures = "0.3.30"
+futures-util = "0.3.30"
+nix = "0.29.0"
polkit-shared = { version = "0.1.0", path = "../../crates/polkit-shared" }
rand = "0.8.5"
+remowt-link-shared = { version = "0.1.0", path = "../../crates/remowt-link-shared" }
serde = { version = "1.0.204", features = ["derive"] }
tokio = { version = "1.39.2", features = ["rt-multi-thread", "fs", "macros"] }
+tokio-util = { version = "0.7.11", features = ["codec"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
ui-prompt = { version = "0.1.0", path = "../../crates/ui-prompt" }
cmds/remowt-agent/src/helper/dbus.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/remowt-agent/src/helper/dbus.rs
@@ -0,0 +1,79 @@
+use std::collections::HashMap;
+use std::marker::PhantomData;
+
+use polkit_shared::{BackendRequest, Identity};
+use tokio::runtime::Handle;
+use ui_prompt::dbus::DbusPrompterInterface;
+use ui_prompt::Prompter;
+use zbus::Connection;
+
+use crate::PolkitHelperProxy;
+
+use super::Helper;
+
+
+struct TemporaryPrompterInterface<P: Prompter + 'static> {
+ connection: Connection,
+ path: String,
+ _marker: PhantomData<P>,
+}
+impl<P: Prompter + 'static> TemporaryPrompterInterface<P> {
+ async fn new(connection: Connection, prompter: P) -> Self {
+ let path = format!(
+ "/remowt/prompters/{}",
+ uuid::Uuid::new_v4().to_string().replace("-", "_")
+ );
+ let _ = connection
+ .object_server()
+ .at(path.clone(), DbusPrompterInterface(prompter))
+ .await;
+ Self {
+ connection,
+ path,
+ _marker: PhantomData,
+ }
+ }
+}
+impl<P: Prompter + Send + Sync + 'static> Drop for TemporaryPrompterInterface<P> {
+ fn drop(&mut self) {
+ // FIXME: block_in_place prevents to moving to current_thread runtime
+ // There should be a blocking way to remove ObjectServer listener.
+ // As far as I can see, it is only async because of async RwLock, shouldn't it be
+ // just a sync lock?
+ tokio::task::block_in_place(move || {
+ Handle::current().block_on(async {
+ let _ = self
+ .connection
+ .object_server()
+ .remove::<DbusPrompterInterface<P>, String>(self.path.clone())
+ .await;
+ });
+ });
+ }
+}
+
+pub struct DbusHelper {
+ connection: Connection,
+ helper: PolkitHelperProxy<'static>,
+}
+impl Helper for DbusHelper {
+ async fn help_me<P: Prompter + Send + Sync + 'static>(
+ &self,
+ cookie: &str,
+ prompter: P,
+ identity: Identity,
+ ) -> anyhow::Result<()> {
+ let prompter = TemporaryPrompterInterface::new(self.connection.clone(), prompter).await;
+ self.helper
+ .init_conversation(
+ BackendRequest {
+ cookie: cookie.to_owned(),
+ environment: HashMap::new(),
+ prompter_path: prompter.path.clone(),
+ identity,
+ }, // cookie.to_owned(), HashMap::new(), prompter.path.clone()
+ )
+ .await?;
+ Ok(())
+ }
+}
cmds/remowt-agent/src/helper/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/remowt-agent/src/helper/mod.rs
@@ -0,0 +1,18 @@
+use futures::Future;
+use polkit_shared::Identity;
+use ui_prompt::Prompter;
+
+mod suid;
+mod dbus;
+
+pub use suid::SuidHelper;
+pub use dbus::DbusHelper;
+
+pub trait Helper {
+ fn help_me<P: Prompter + Send + Sync + 'static>(
+ &self,
+ cookie: &str,
+ prompt: P,
+ identity: Identity,
+ ) -> impl Future<Output = anyhow::Result<()>> + Send;
+}
cmds/remowt-agent/src/helper/suid.rsdiffbeforeafterboth--- /dev/null
+++ b/cmds/remowt-agent/src/helper/suid.rs
@@ -0,0 +1,83 @@
+use std::pin::pin;
+use std::process::Stdio;
+
+use anyhow::{bail, anyhow};
+use futures::stream::Peekable;
+use futures::StreamExt as _;
+use nix::unistd::User;
+use polkit_shared::Identity;
+use tokio::io::AsyncWriteExt as _;
+use tokio::process::Command;
+use tokio::select;
+use tokio_util::codec::{FramedRead, LinesCodec};
+use ui_prompt::Prompter;
+
+use super::Helper;
+
+#[derive(Clone)]
+pub struct SuidHelper;
+impl Helper for SuidHelper {
+ async fn help_me<P: Prompter + 'static>(
+ &self,
+ cookie: &str,
+ prompt: P,
+ identity: Identity,
+ ) -> anyhow::Result<()> {
+ let Some(uid) = dbg!(identity.uid()) else {
+ bail!("can't process identity");
+ };
+ let user = User::from_uid(dbg!(uid))
+ .map_err(|e| anyhow!("error querying user: {e}"))?
+ .ok_or_else(|| anyhow!("user not found"))?;
+
+ let mut cmd = Command::new("polkit-agent-helper-1");
+ cmd.arg(user.name);
+ cmd.stdin(Stdio::piped());
+ cmd.stdout(Stdio::piped());
+ cmd.kill_on_drop(true);
+ let mut child = cmd.spawn()?;
+ let mut stdin = child.stdin.take().expect("piped");
+ let mut stdout =
+ pin!(
+ FramedRead::new(child.stdout.take().expect("piped"), LinesCodec::new()).peekable()
+ );
+
+ assert!(!cookie.contains("\n"));
+ stdin.write_all(cookie.as_bytes()).await?;
+ stdin.write_all(b"\n").await?;
+
+ while let Some(line) = stdout.next().await {
+ let line = dbg!(line?);
+ // TODO: Dedicated codec?
+ let res = if let Some(prompt_text) = line.strip_prefix("PAM_PROMPT_ECHO_OFF ") {
+ prompt.prompt_text(false, prompt_text, "", &[]).await?
+ } else if let Some(prompt_text) = line.strip_prefix("PAM_PROMPT_ECHO_ON ") {
+ prompt.prompt_text(true, prompt_text, "", &[]).await?
+ } else if let Some(msg_text) = line.strip_prefix("PAM_ERROR_MSG ") {
+ prompt.display_text(true, msg_text, &[]).await?;
+ String::new()
+ } else if let Some(msg_text) = line.strip_prefix("PAM_TEXT_INFO ") {
+ select! {
+ _ = Peekable::peek(stdout.as_mut()) => {},
+ r = prompt.display_text(false, msg_text, &[]) => {r?}
+ }
+ String::new()
+ } else if line == "SUCCESS" {
+ return Ok(());
+ } else if line == "FAILURE" {
+ bail!("helper binary reported failure")
+ } else {
+ // TODO: Success/failure handling
+ bail!("unknown agent request");
+ };
+
+ if res.contains("\n") {
+ bail!("response should not include newline")
+ }
+
+ stdin.write_all(res.as_bytes()).await?;
+ stdin.write_all(b"\n").await?;
+ }
+ bail!("agent finished unexpectedly")
+ }
+}
cmds/remowt-agent/src/main.rsdiffbeforeafterboth--- a/cmds/remowt-agent/src/main.rs
+++ b/cmds/remowt-agent/src/main.rs
@@ -1,281 +1,269 @@
use std::borrow::Cow;
use std::collections::{BTreeMap, HashMap};
+use std::future;
use std::io::{stdout, Write};
-use std::marker::PhantomData;
+use std::path::PathBuf;
use std::sync::{Arc, Mutex, OnceLock};
-use std::{future, process};
+use bifrostlink::{AddressT, Rpc};
+use bifrostlink_ports::unix_socket::from_socket;
use clap::Parser;
use polkit_shared::{emphasize, BackendRequest, Identity, PidDisplay};
-use tokio::runtime::Handle;
-use tokio::task::{AbortHandle, JoinHandle, LocalSet};
+use remowt_link_shared::Address;
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
+use tokio::net::UnixStream;
+use tokio::runtime::Runtime;
+use tokio::task::AbortHandle;
use tracing::{info, trace};
-use ui_prompt::dbus::DbusPrompterInterface;
use ui_prompt::rofi::RofiPrompter;
use ui_prompt::{PrependSourcePrompter, Prompter, Source};
+use zbus::fdo;
use zbus::zvariant::{OwnedValue, Str};
-use zbus::{fdo, ObjectServer};
use zbus::{interface, proxy, Connection};
use zbus_polkit::policykit1::Subject;
-struct TemporaryPrompterInterface<P: Prompter + Send + Sync + 'static> {
- connection: Connection,
- path: String,
- _marker: PhantomData<P>,
-}
-impl<P: Prompter + Send + Sync + 'static> TemporaryPrompterInterface<P> {
- async fn new(connection: Connection, prompter: P) -> Self {
- let path = format!(
- "/remowt/prompters/{}",
- uuid::Uuid::new_v4().to_string().replace("-", "_")
- );
- let _ = connection
- .object_server()
- .at(path.clone(), DbusPrompterInterface(prompter))
- .await;
- Self {
- connection,
- path,
- _marker: PhantomData,
- }
- }
-}
-impl<P: Prompter + Send + Sync + 'static> Drop for TemporaryPrompterInterface<P> {
- fn drop(&mut self) {
- // FIXME: block_in_place prevents to moving to current_thread runtime
- // There should be a blocking way to remove ObjectServer listener.
- // As far as I can see, it is only async because of async RwLock, shouldn't it be
- // just a sync lock?
- tokio::task::block_in_place(move || {
- Handle::current().block_on(async {
- let _ = self
- .connection
- .object_server()
- .remove::<DbusPrompterInterface<P>, String>(self.path.clone())
- .await;
- });
- });
- }
-}
+use self::helper::{Helper, SuidHelper};
+pub mod helper;
+
struct CancelTaskOnDrop {
- tasks: Arc<Mutex<HashMap<String, AbortHandle>>>,
- handle: String,
+ tasks: Arc<Mutex<HashMap<String, AbortHandle>>>,
+ handle: String,
}
impl Drop for CancelTaskOnDrop {
- fn drop(&mut self) {
- info!("cancel on drop");
- if let Some(task) = self
- .tasks
- .lock()
- .expect("not poisoned")
- .remove(&self.handle)
- {
- task.abort();
- }
- }
+ fn drop(&mut self) {
+ info!("cancel on drop");
+ if let Some(task) = self
+ .tasks
+ .lock()
+ .expect("not poisoned")
+ .remove(&self.handle)
+ {
+ task.abort();
+ }
+ }
}
-struct Agent {
- helper: PolkitHelperProxy<'static>,
- tasks: Arc<Mutex<HashMap<String, AbortHandle>>>,
- connection: Connection,
+struct Agent<H> {
+ tasks: Arc<Mutex<HashMap<String, AbortHandle>>>,
+ helper: H,
}
-impl Agent {
- async fn new(connection: Connection) -> anyhow::Result<Self> {
- Ok(Self {
- helper: PolkitHelperProxy::new(&connection).await?,
- tasks: Arc::new(Mutex::new(HashMap::new())),
- connection,
- })
- }
+impl<H> Agent<H> {
+ fn new(helper: H) -> Self {
+ Agent {
+ tasks: Arc::new(Mutex::new(HashMap::new())),
+ helper,
+ }
+ }
}
#[interface(name = "org.freedesktop.PolicyKit1.AuthenticationAgent")]
-impl Agent {
- /// BeginAuthentication method
- #[allow(clippy::too_many_arguments)]
- async fn begin_authentication(
- &self,
- action_id: String,
- message: String,
- icon_name: String,
- mut details: BTreeMap<String, String>,
- cookie: String,
- identities: Vec<Identity>,
- ) -> zbus::fdo::Result<()> {
- use std::fmt::Write;
- info!("begin auth");
- let _cancel_guard = Arc::new(OnceLock::new());
- let task = {
- let connection = self.connection.clone();
- let helper = self.helper.clone();
- let cookie = cookie.clone();
- let _cancel_guard = _cancel_guard.clone();
- tokio::task::spawn(async move {
- let _cancel_guard = _cancel_guard.clone();
- trace!("conversation task");
- let mut description = format!("{message}\n\n<b>Action id:</b> {action_id}",);
- if let Some(subject) = details.remove("polkit.caller-pid") {
- let _ = write!(description, "\n<b>Caller:</b> ");
- if let Ok(pid) = subject.parse::<u32>() {
- let _ = write!(description, "{}", PidDisplay(pid));
- } else {
- let _ = write!(description, "{}", emphasize("invalid pid"));
- }
- }
- if let Some(subject) = details.remove("polkit.subject-pid") {
- let _ = write!(description, "\n<b>Subject:</b> ");
- if let Ok(pid) = subject.parse::<u32>() {
- let _ = write!(description, "{}", PidDisplay(pid));
- } else {
- let _ = write!(description, "{}", emphasize("invalid pid"));
- }
- }
- let mut prompter = PrependSourcePrompter {
- source: vec![Source(Cow::Borrowed("polkit agent"))],
- description: description.clone(),
- prompter: RofiPrompter,
- };
+impl<H> Agent<H>
+where
+ H: Helper + Clone + Send + Sync + 'static,
+{
+ /// BeginAuthentication method
+ #[allow(clippy::too_many_arguments)]
+ async fn begin_authentication(
+ &self,
+ action_id: String,
+ message: String,
+ icon_name: String,
+ mut details: BTreeMap<String, String>,
+ cookie: String,
+ identities: Vec<Identity>,
+ ) -> zbus::fdo::Result<()> {
+ use std::fmt::Write;
+ info!("begin auth");
+ let _cancel_guard = Arc::new(OnceLock::new());
+ let task = {
+ let helper = self.helper.clone();
+ let cookie = cookie.clone();
+ let _cancel_guard = _cancel_guard.clone();
+ tokio::task::spawn(async move {
+ let _cancel_guard = _cancel_guard.clone();
+ trace!("conversation task");
+ let mut description = format!("{message}\n\n<b>Action id:</b> {action_id}",);
+ if let Some(subject) = details.remove("polkit.caller-pid") {
+ let _ = write!(description, "\n<b>Caller:</b> ");
+ if let Ok(pid) = subject.parse::<u32>() {
+ let _ = write!(description, "{}", PidDisplay(pid));
+ } else {
+ let _ = write!(description, "{}", emphasize("invalid pid"));
+ }
+ }
+ if let Some(subject) = details.remove("polkit.subject-pid") {
+ let _ = write!(description, "\n<b>Subject:</b> ");
+ if let Ok(pid) = subject.parse::<u32>() {
+ let _ = write!(description, "{}", PidDisplay(pid));
+ } else {
+ let _ = write!(description, "{}", emphasize("invalid pid"));
+ }
+ }
+ let mut prompter = PrependSourcePrompter {
+ source: vec![Source(Cow::Borrowed("polkit agent"))],
+ description: description.clone(),
+ prompter: RofiPrompter,
+ };
- let identity_displays: Vec<String> =
- identities.iter().map(|v| v.to_string()).collect();
- let identity_displays: Vec<&str> =
- identity_displays.iter().map(|v| v.as_str()).collect();
- info!("choose identity");
- let choosen_identity = match identity_displays.len() {
- 0 => {
- return Err(fdo::Error::AuthFailed(
- "no identity to authenticate as".to_owned(),
- ))
- }
- 1 => 0,
- _ => {
- prompter
- .prompt_enum(
- "Identity",
- "Select identity to use for polkit authorization",
- &identity_displays,
- &[],
- )
- .await?
- }
- };
- info!("identity chosen");
+ let identity_displays: Vec<String> =
+ identities.iter().map(|v| v.to_string()).collect();
+ let identity_displays: Vec<&str> =
+ identity_displays.iter().map(|v| v.as_str()).collect();
+ info!("choose identity");
+ let choosen_identity = match identity_displays.len() {
+ 0 => {
+ return Err(fdo::Error::AuthFailed(
+ "no identity to authenticate as".to_owned(),
+ ))
+ }
+ 1 => 0,
+ _ => {
+ prompter
+ .prompt_enum(
+ "Identity",
+ "Select identity to use for polkit authorization",
+ &identity_displays,
+ &[],
+ )
+ .await?
+ }
+ };
+ info!("identity chosen");
+
+ let _ = write!(
+ description,
+ "\n<b>Identity:</b> {}",
+ identities[choosen_identity as usize]
+ );
+ prompter.description = description;
- let _ = write!(
- description,
- "\n<b>Identity:</b> {}",
- identities[choosen_identity as usize]
- );
- prompter.description = description;
+ prompter.source.push(Source(Cow::Borrowed("polkit daemon")));
- prompter.source.push(Source(Cow::Borrowed("polkit daemon")));
- // let connection = Connection::system().await?;
- // let helper = PolkitHelperProxy::new(&connection).await?;
- let prompter = TemporaryPrompterInterface::new(connection, prompter).await;
- info!("init conv");
- helper
- .init_conversation(
- BackendRequest {
- cookie: cookie.to_owned(),
- environment: HashMap::new(),
- prompter_path: prompter.path.clone(),
- // TODO: Let user choose
- identity: identities[choosen_identity as usize].clone(),
- }, // cookie.to_owned(), HashMap::new(), prompter.path.clone()
- )
- .await?;
- println!("ASKED");
- dbg!(action_id, message, icon_name, details, cookie, identities);
+ helper
+ .help_me(
+ &cookie,
+ prompter,
+ identities[choosen_identity as usize].clone(),
+ )
+ .await
+ .map_err(|e| fdo::Error::Failed(e.to_string()))?;
+ // let connection = Connection::system().await?;
+ // let helper = PolkitHelperProxy::new(&connection).await?;
- Ok(())
- })
- };
- self.tasks
- .lock()
- .unwrap()
- .insert(cookie.clone(), task.abort_handle());
- info!("abort handle stored");
- let _ = _cancel_guard.set(CancelTaskOnDrop {
- tasks: self.tasks.clone(),
- handle: cookie.clone(),
- });
+ Ok(())
+ })
+ };
+ self.tasks
+ .lock()
+ .unwrap()
+ .insert(cookie.clone(), task.abort_handle());
+ info!("abort handle stored");
+ let _ = _cancel_guard.set(CancelTaskOnDrop {
+ tasks: self.tasks.clone(),
+ handle: cookie.clone(),
+ });
- let _ = task.await;
+ let _ = task.await;
- Ok(())
- }
+ Ok(())
+ }
- /// CancelAuthentication method
- async fn cancel_authentication(&self, cookie: &str) -> zbus::fdo::Result<()> {
- info!("auth cancelled");
- if let Some(abort) = self.tasks.lock().unwrap().remove(cookie) {
- info!("abort handle found");
- abort.abort();
- }
- // debug!("Authentication cancled ! {cookie}");
- Ok(())
- }
+ /// CancelAuthentication method
+ async fn cancel_authentication(&self, cookie: &str) -> zbus::fdo::Result<()> {
+ info!("auth cancelled");
+ if let Some(abort) = self.tasks.lock().unwrap().remove(cookie) {
+ info!("abort handle found");
+ abort.abort();
+ }
+ // debug!("Authentication cancled ! {cookie}");
+ Ok(())
+ }
}
const OBJ_PATH: &str = "/org/freedesktop/PolicyKit1/AuthenticationAgent";
#[proxy(
- interface = "lach.PolkitHelper",
- default_service = "lach.polkit.helper1",
- default_path = "/lach/PolkitHelper"
+ interface = "lach.PolkitHelper",
+ default_service = "lach.polkit.helper1",
+ default_path = "/lach/PolkitHelper"
)]
trait PolkitHelper {
- fn init_conversation(&self, request: BackendRequest) -> zbus::Result<()>;
+ fn init_conversation(&self, request: BackendRequest) -> zbus::Result<()>;
}
#[derive(Parser)]
enum Opts {
- Agent,
- AskPass { description: String },
+ Agent,
+ AskPass {
+ description: String,
+ },
+ RealAgent {
+ #[arg(long)]
+ path: PathBuf,
+ },
}
-#[tokio::main]
-async fn main() -> anyhow::Result<()> {
- tracing_subscriber::fmt::init();
- let opts = Opts::parse();
+fn main() -> anyhow::Result<()> {
+ tracing_subscriber::fmt::init();
+ let opts = Opts::parse();
- match opts {
- Opts::Agent => {
- trace!("started");
- let conn = Connection::system().await?;
+ let runtime = Runtime::new()?;
- let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&conn).await?;
- conn.object_server()
- .at(OBJ_PATH, Agent::new(conn.clone()).await?)
- .await?;
+ match opts {
+ Opts::Agent => {
+ // TODO: Setup env, directories with various things...
+ runtime.block_on(main_agent())
+ }
+ Opts::AskPass { description } => runtime.block_on(main_askpass(description)),
+ Opts::RealAgent { path } => runtime.block_on(main_real_agent(path)),
+ }
+}
+async fn main_real_agent(path: PathBuf) -> anyhow::Result<()> {
+ let mut stream = UnixStream::connect(path).await?;
+ stream.write_all(b"REMOWT_HELLO\0").await?;
+ let mut buf = [0u8; 12];
+ stream.read_exact(&mut buf).await?;
+ assert_eq!(&buf, b"REMOWT_EHLO\0");
+ let port = from_socket(stream);
+ let rpc = Rpc::<Address, remowt_link_shared::Error>::new(Address::Agent);
+ rpc.add_direct(Address::User, port, bifrostlink::Rtt(0));
+ Ok(())
+}
- let session_id = std::env::var("XDG_SESSION_ID")?;
- let mut details = HashMap::new();
- let val: OwnedValue = {
- let wrapped: Str<'_> = session_id.into();
- wrapped.into()
- };
- details.insert("session-id".to_string(), val);
- proxy
- .register_authentication_agent(
- &Subject {
- subject_kind: "unix-session".to_string(),
- subject_details: details,
- },
- "C",
- OBJ_PATH,
- )
- .await?;
- }
- Opts::AskPass { description } => {
- let password = RofiPrompter
- .prompt_text(false, &description, "SSH password request", &[])
- .await?;
- stdout().lock().write_all(password.as_bytes())?;
- }
- }
+async fn main_agent() -> anyhow::Result<()> {
+ trace!("started");
+ let conn = Connection::system().await?;
+
+ let proxy = zbus_polkit::policykit1::AuthorityProxy::new(&conn).await?;
+ conn.object_server()
+ .at(OBJ_PATH, Agent::new(SuidHelper))
+ .await?;
+
+ let session_id = std::env::var("XDG_SESSION_ID")?;
+ let mut details = HashMap::new();
+ let val: OwnedValue = {
+ let wrapped: Str<'_> = session_id.into();
+ wrapped.into()
+ };
+ details.insert("session-id".to_string(), val);
+ proxy
+ .register_authentication_agent(
+ &Subject {
+ subject_kind: "unix-session".to_string(),
+ subject_details: details,
+ },
+ "C",
+ OBJ_PATH,
+ )
+ .await?;
+ future::pending().await
+}
- future::pending().await
+async fn main_askpass(description: String) -> anyhow::Result<()> {
+ let password = RofiPrompter
+ .prompt_text(false, &description, "SSH password request", &[])
+ .await?;
+ stdout().lock().write_all(password.as_bytes())?;
+ future::pending().await
}
cmds/remowt-ssh/Cargo.tomldiffbeforeafterboth--- a/cmds/remowt-ssh/Cargo.toml
+++ b/cmds/remowt-ssh/Cargo.toml
@@ -4,3 +4,17 @@
edition = "2021"
[dependencies]
+clap = { version = "4.5.16", features = ["derive"] }
+openssh = { version = "0.11.0", features = ["native-mux"] }
+tracing-subscriber = "0.3.18"
+bifrostlink.workspace = true
+remowt-link-shared = { version = "0.1.0", path = "../../crates/remowt-link-shared" }
+tokio = { version = "1.39.3", features = ["macros"] }
+anyhow = "1.0.86"
+bifrostlink-ports.workspace = true
+uuid = { version = "1.10.0", features = ["v4"] }
+tempdir = "0.3.7"
+russh = { git = "https://github.com/Eugeny/russh/" }
+russh-config = { git = "https://github.com/Eugeny/russh/" }
+russh-keys = { git = "https://github.com/Eugeny/russh/" }
+async-trait = "0.1.81"
cmds/remowt-ssh/src/main.rsdiffbeforeafterboth--- a/cmds/remowt-ssh/src/main.rs
+++ b/cmds/remowt-ssh/src/main.rs
@@ -1,3 +1,140 @@
-fn main() {
- println!("Hello, world!");
+use std::borrow::Cow;
+use std::ffi::OsString;
+use std::os::unix::ffi::OsStringExt;
+use std::path::PathBuf;
+use std::sync::Arc;
+
+use anyhow::{bail, ensure};
+use async_trait::async_trait;
+use bifrostlink::Rpc;
+use clap::Parser;
+use remowt_link_shared::Address;
+use russh::client::{connect, Config, Handler, Session};
+use tempdir::TempDir;
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
+use tokio::net::UnixSocket;
+
+#[derive(Parser)]
+struct Opts {
+ host: String,
+}
+
+struct MyHandler {
+ host: String,
+ port: u16,
+}
+#[async_trait]
+impl Handler for MyHandler {
+ type Error = russh::Error;
+ async fn check_server_key(
+ &mut self,
+ server_public_key: &russh_keys::key::PublicKey,
+ ) -> Result<bool, Self::Error> {
+ Ok(russh_keys::check_known_hosts(
+ &self.host,
+ self.port,
+ &server_public_key,
+ )?)
+ }
+}
+
+#[tokio::main(flavor = "current_thread")]
+async fn main() -> anyhow::Result<()> {
+ let rpc = Rpc::<Address, remowt_link_shared::Error>::new(Address::User);
+ tracing_subscriber::fmt::init();
+ let opts = Opts::parse();
+
+ let conf = dbg!(russh_config::parse_home(&opts.host)?);
+ println!("connect");
+ let mut sess = connect(
+ Arc::new(Config {
+ ..Default::default()
+ }),
+ dbg!((conf.host_name.clone(), conf.port)),
+ MyHandler {
+ host: conf.host_name,
+ port: conf.port,
+ },
+ )
+ .await?;
+ println!("agent");
+ let mut agent = russh_keys::agent::client::AgentClient::connect_env().await?;
+ for ele in agent.request_identities().await? {
+ let (_agent, res) = sess.authenticate_future(conf.user.clone(), ele, agent).await;
+ agent = _agent;
+ if res? {
+ break;
+ }
+ }
+ // let sess = Session::connect(opts.host, openssh::KnownHosts::Strict).await?;
+
+ let socket = UnixSocket::new_stream()?;
+
+ println!("mktemp");
+ let mut cmd_chan = sess.channel_open_session().await?;
+ cmd_chan
+ .exec(true, "mktemp -d remowt.XXXXXXXXXXXX --tmpdir")
+ .await?;
+ let mut stdout = vec![];
+ loop {
+ let Some(msg) = cmd_chan.wait().await else {
+ bail!("unexpected channel end");
+ };
+ match msg {
+ russh::ChannelMsg::Data { data } => stdout.extend(data.as_ref()),
+ russh::ChannelMsg::ExitStatus { exit_status } => {
+ if exit_status != 0 {
+ bail!("mktemp failed");
+ }
+ break;
+ }
+ _ => {}
+ }
+ }
+
+ ensure!(stdout.ends_with(b"\n"));
+ stdout.pop();
+
+ // Remote host is not neccessary linux, openssh crate makes incorrect assumptions here.
+ // TODO: Remove on local close.
+ let remote_dir = PathBuf::from(OsString::from_vec(stdout));
+ let remote_socket = remote_dir.join("primary.sock");
+
+ let local_dir = TempDir::new("remowt")?;
+ let local_socket = local_dir.path().join("primary.sock");
+
+ println!("listen");
+ socket.bind(&local_socket)?;
+ let listener = socket.listen(1)?;
+
+ eprintln!("forward socket");
+
+ let mut sock = sess
+ .channel_open_direct_streamlocal(dbg!(remote_socket.to_str().expect("path is utf-8")))
+ .await?;
+
+ eprintln!("wait");
+ while let Some(v) = sock.wait().await {
+ dbg!(v);
+ }
+
+ eprintln!("spawn agent");
+
+ // let _agent = sess
+ // .command("/home/lach/.remowt/remowt-agent")
+ // .arg("agent-real")
+ // .arg("--path")
+ // .arg(remote_socket.to_str().expect("path is utf-8"))
+ // .spawn()
+ // .await?;
+ //
+ // let (mut conn, _) = listener.accept().await?;
+ // let mut buf = [0u8; 13];
+ // conn.read_exact(&mut buf).await?;
+ // assert_eq!(&buf, b"REMOWT_HELLO\0");
+ // conn.write_all(b"REMOWT_EHLO\0").await?;
+ //
+ // println!("handshake complete!");
+
+ Ok(())
}
crates/polkit-shared/src/lib.rsdiffbeforeafterboth--- a/crates/polkit-shared/src/lib.rs
+++ b/crates/polkit-shared/src/lib.rs
@@ -47,6 +47,19 @@
pub details: HashMap<String, OwnedValue>,
}
+impl Identity {
+ pub fn uid(&self) -> Option<Uid> {
+ if self.kind != "unix-user" {
+ return None;
+ }
+ let uid = self.details.get("uid")?;
+ let Value::U32(uid) = &**uid else {
+ return None;
+ };
+ Some(Uid::from_raw(*uid))
+ }
+}
+
impl fmt::Display for Identity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind.as_str() {
crates/remowt-link-shared/Cargo.tomldiffbeforeafterboth--- /dev/null
+++ b/crates/remowt-link-shared/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "remowt-link-shared"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+bifrostlink.workspace = true
+serde = { version = "1.0.208", features = ["derive"] }
+serde_json = "1.0.125"
+thiserror = "1.0.63"
+tokio = "1.39.3"
crates/remowt-link-shared/src/lib.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/remowt-link-shared/src/lib.rs
@@ -0,0 +1,39 @@
+use bifrostlink::error::{ErrorT, ListenerForYourRequestHasBeenDeadError, ResponseError};
+use bifrostlink::AddressT;
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Serialize, Hash, Eq, Debug, PartialEq, Deserialize)]
+pub enum Address {
+ User,
+ Agent,
+}
+impl AddressT for Address {}
+
+#[derive(thiserror::Error, Debug)]
+pub enum Error {
+ #[error("listener is dead")]
+ ListenerDead,
+ #[error("response: {0}")]
+ Response(String),
+}
+impl From<ListenerForYourRequestHasBeenDeadError> for Error {
+ fn from(_value: ListenerForYourRequestHasBeenDeadError) -> Self {
+ Self::ListenerDead
+ }
+}
+impl From<serde_json::Error> for Error {
+ fn from(_value: serde_json::Error) -> Self {
+ Self::ListenerDead
+ }
+}
+impl From<Error> for ResponseError {
+ fn from(val: Error) -> Self {
+ ResponseError(val.to_string())
+ }
+}
+impl From<ResponseError> for Error {
+ fn from(value: ResponseError) -> Self {
+ Self::Response(value.0)
+ }
+}
+impl ErrorT for Error {}
crates/ui-prompt/Cargo.tomldiffbeforeafterboth--- a/crates/ui-prompt/Cargo.toml
+++ b/crates/ui-prompt/Cargo.toml
@@ -4,6 +4,7 @@
edition = "2021"
[dependencies]
+bifrostlink.workspace = true
serde = "1.0.204"
thiserror = "1.0.63"
tokio = { version = "1.39.2", features = ["io-util", "macros", "process", "rt"] }
crates/ui-prompt/src/bifrost.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/ui-prompt/src/bifrost.rs
@@ -0,0 +1,166 @@
+use bifrostlink::error::ErrorT;
+use bifrostlink::{request, AddressT, Rpc};
+use serde::{Deserialize, Serialize};
+
+use crate::{Error, Prompter, Source};
+
+pub struct BifrostPrompter<A: AddressT, E: ErrorT> {
+ pub address: A,
+ pub rpc: Rpc<A, E>,
+}
+
+#[derive(Serialize, Deserialize)]
+struct EnumRequest {
+ prompt: String,
+ description: String,
+ variants: Vec<String>,
+ source: Vec<Source>,
+}
+#[derive(Serialize, Deserialize)]
+struct EnumResponse {
+ value: u32,
+}
+request!(EnumRequest => EnumResponse);
+
+#[derive(Serialize, Deserialize)]
+struct TextRequest {
+ echo: bool,
+ prompt: String,
+ description: String,
+ source: Vec<Source>,
+}
+#[derive(Serialize, Deserialize)]
+struct TextResponse {
+ value: String,
+}
+request!(TextRequest => TextResponse);
+
+#[derive(Serialize, Deserialize)]
+struct DisplayRequest {
+ error: bool,
+ description: String,
+ source: Vec<Source>,
+}
+request!(DisplayRequest => ());
+
+impl<A: AddressT, E: ErrorT> Prompter for BifrostPrompter<A, E>
+where
+ crate::Error: From<E>,
+{
+ async fn prompt_enum(
+ &self,
+ prompt: &str,
+ description: &str,
+ variants: &[&str],
+ source: &[crate::Source],
+ ) -> crate::Result<u32> {
+ let res = self
+ .rpc
+ .request(
+ self.address.clone(),
+ &EnumRequest {
+ prompt: prompt.to_owned(),
+ description: description.to_owned(),
+ variants: variants.into_iter().map(|v| (*v).to_owned()).collect(),
+ source: source.to_vec(),
+ },
+ )
+ .await?;
+ Ok(res.value)
+ }
+
+ async fn prompt_text(
+ &self,
+ echo: bool,
+ prompt: &str,
+ description: &str,
+ source: &[crate::Source],
+ ) -> crate::Result<String> {
+ let res = self
+ .rpc
+ .request(
+ self.address.clone(),
+ &TextRequest {
+ echo,
+ prompt: prompt.to_owned(),
+ description: description.to_owned(),
+ source: source.to_vec(),
+ },
+ )
+ .await?;
+ Ok(res.value)
+ }
+
+ async fn display_text(
+ &self,
+ error: bool,
+ description: &str,
+ source: &[crate::Source],
+ ) -> crate::Result<()> {
+ self.rpc
+ .request(
+ self.address.clone(),
+ &DisplayRequest {
+ error,
+ description: description.to_owned(),
+ source: source.to_vec(),
+ },
+ )
+ .await?;
+ Ok(())
+ }
+}
+
+pub fn handle_bifrost_prompts<
+ P: Prompter + Clone + 'static,
+ A: AddressT,
+ E: ErrorT + From<Error>,
+>(
+ rpc: &Rpc<A, E>,
+ prompt: P,
+) {
+ rpc.register_request_handler(true, {
+ let prompt = prompt.clone();
+ move |_addr, req: EnumRequest| {
+ let prompt = prompt.clone();
+ async move {
+ let i = prompt
+ .prompt_enum(
+ &req.prompt,
+ &req.description,
+ &req.variants.iter().map(|v| v.as_str()).collect::<Vec<_>>(),
+ &req.source,
+ )
+ .await?;
+
+ Ok(EnumResponse { value: i })
+ }
+ }
+ });
+ rpc.register_request_handler(true, {
+ let prompt = prompt.clone();
+ move |_addr, req: TextRequest| {
+ let prompt = prompt.clone();
+ async move {
+ let i = prompt
+ .prompt_text(req.echo, &req.prompt, &req.description, &req.source)
+ .await?;
+
+ Ok(TextResponse { value: i })
+ }
+ }
+ });
+ rpc.register_request_handler(true, {
+ let prompt = prompt.clone();
+ move |_addr, req: DisplayRequest| {
+ let prompt = prompt.clone();
+ async move {
+ prompt
+ .display_text(req.error, &req.description, &req.source)
+ .await?;
+
+ Ok(())
+ }
+ }
+ });
+}
crates/ui-prompt/src/lib.rsdiffbeforeafterboth--- a/crates/ui-prompt/src/lib.rs
+++ b/crates/ui-prompt/src/lib.rs
@@ -5,6 +5,7 @@
pub mod dbus;
pub mod rofi;
+pub mod bifrost;
#[derive(thiserror::Error, Debug)]
pub enum Error {
@@ -25,7 +26,7 @@
}
}
-pub trait Prompter {
+pub trait Prompter: Send + Sync {
fn prompt_radio(
&self,
prompt: &str,
@@ -77,6 +78,48 @@
) -> Result<String>;
fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()>;
}
+impl<P> Prompter for &P
+where
+ P: Prompter,
+{
+ fn prompt_radio(
+ &self,
+ prompt: &str,
+ description: &str,
+ source: &[Source],
+ ) -> impl Future<Output = Result<bool>> + Send {
+ (*self).prompt_radio(prompt, description, source)
+ }
+
+ fn prompt_enum(
+ &self,
+ prompt: &str,
+ description: &str,
+ variants: &[&str],
+ source: &[Source],
+ ) -> impl Future<Output = Result<u32>> + Send {
+ (*self).prompt_enum(prompt, description, variants, source)
+ }
+
+ fn prompt_text(
+ &self,
+ echo: bool,
+ prompt: &str,
+ description: &str,
+ source: &[Source],
+ ) -> impl Future<Output = Result<String>> + Send {
+ (*self).prompt_text(echo, prompt, description, source)
+ }
+
+ fn display_text(
+ &self,
+ error: bool,
+ description: &str,
+ source: &[Source],
+ ) -> impl Future<Output = Result<()>> + Send {
+ (*self).display_text(error, description, source)
+ }
+}
pub struct PrependSourcePrompter<P> {
pub prompter: P,
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -62,6 +62,7 @@
cargo-release
rustPlatform.bindgenHook
pam
+ just
];
};
formatter = pkgs.alejandra;
rust-toolchain.tomldiffbeforeafterboth--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,3 +1,4 @@
[toolchain]
channel = "nightly-2024-07-20"
components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]
+targets = ["x86_64-unknown-linux-musl"]