mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-04-02 18:31:50 -04:00
refactor: encrypt the sensitive data
This commit is contained in:
parent
bf96a88e21
commit
601f422863
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -5,11 +5,13 @@
|
|||||||
"clickaway",
|
"clickaway",
|
||||||
"clientgpversion",
|
"clientgpversion",
|
||||||
"clientos",
|
"clientos",
|
||||||
|
"consts",
|
||||||
"devicename",
|
"devicename",
|
||||||
"distro",
|
"distro",
|
||||||
"gpcommon",
|
"gpcommon",
|
||||||
"gpgui",
|
"gpgui",
|
||||||
"gpservice",
|
"gpservice",
|
||||||
|
"humantime",
|
||||||
"Immer",
|
"Immer",
|
||||||
"jnlp",
|
"jnlp",
|
||||||
"oneshot",
|
"oneshot",
|
||||||
@ -17,7 +19,10 @@
|
|||||||
"prelogin",
|
"prelogin",
|
||||||
"prelogon",
|
"prelogon",
|
||||||
"prelogonuserauthcookie",
|
"prelogonuserauthcookie",
|
||||||
|
"repr",
|
||||||
|
"rustc",
|
||||||
"tauri",
|
"tauri",
|
||||||
|
"thiserror",
|
||||||
"unlisten",
|
"unlisten",
|
||||||
"userauthcookie",
|
"userauthcookie",
|
||||||
"vpnc",
|
"vpnc",
|
||||||
|
695
Cargo.lock
generated
695
Cargo.lock
generated
@ -8,6 +8,53 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher 0.3.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher 0.4.4",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-gcm"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"aes 0.8.3",
|
||||||
|
"cipher 0.4.4",
|
||||||
|
"ctr",
|
||||||
|
"ghash",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.20"
|
version = "0.7.20"
|
||||||
@ -51,8 +98,11 @@ checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
|||||||
name = "app"
|
name = "app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"aes-gcm",
|
||||||
|
"anyhow",
|
||||||
"gpcommon",
|
"gpcommon",
|
||||||
|
"hex",
|
||||||
|
"keyring",
|
||||||
"log",
|
"log",
|
||||||
"openssl",
|
"openssl",
|
||||||
"regex",
|
"regex",
|
||||||
@ -69,6 +119,117 @@ dependencies = [
|
|||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-broadcast"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
|
||||||
|
dependencies = [
|
||||||
|
"event-listener",
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-channel"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
|
||||||
|
dependencies = [
|
||||||
|
"concurrent-queue",
|
||||||
|
"event-listener",
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-executor"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb"
|
||||||
|
dependencies = [
|
||||||
|
"async-lock",
|
||||||
|
"async-task",
|
||||||
|
"concurrent-queue",
|
||||||
|
"fastrand",
|
||||||
|
"futures-lite",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-fs"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
|
||||||
|
dependencies = [
|
||||||
|
"async-lock",
|
||||||
|
"autocfg",
|
||||||
|
"blocking",
|
||||||
|
"futures-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-io"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
|
||||||
|
dependencies = [
|
||||||
|
"async-lock",
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"concurrent-queue",
|
||||||
|
"futures-lite",
|
||||||
|
"log",
|
||||||
|
"parking",
|
||||||
|
"polling",
|
||||||
|
"rustix",
|
||||||
|
"slab",
|
||||||
|
"socket2",
|
||||||
|
"waker-fn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-lock"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7"
|
||||||
|
dependencies = [
|
||||||
|
"event-listener",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-process"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
|
||||||
|
dependencies = [
|
||||||
|
"async-io",
|
||||||
|
"async-lock",
|
||||||
|
"autocfg",
|
||||||
|
"blocking",
|
||||||
|
"cfg-if",
|
||||||
|
"event-listener",
|
||||||
|
"futures-lite",
|
||||||
|
"rustix",
|
||||||
|
"signal-hook",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-recursion"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.16",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-task"
|
||||||
|
version = "4.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.66"
|
version = "0.1.66"
|
||||||
@ -104,6 +265,12 @@ dependencies = [
|
|||||||
"system-deps 6.0.3",
|
"system-deps 6.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-waker"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "attohttpc"
|
name = "attohttpc"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
@ -170,6 +337,37 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-modes"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
|
||||||
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
|
"cipher 0.3.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blocking"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
|
||||||
|
dependencies = [
|
||||||
|
"async-channel",
|
||||||
|
"async-lock",
|
||||||
|
"async-task",
|
||||||
|
"atomic-waker",
|
||||||
|
"fastrand",
|
||||||
|
"futures-lite",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "3.3.4"
|
version = "3.3.4"
|
||||||
@ -329,6 +527,25 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "cocoa"
|
name = "cocoa"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
@ -387,6 +604,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "concurrent-queue"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "convert_case"
|
name = "convert_case"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -478,6 +704,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
|
"rand_core 0.6.4",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -518,6 +745,15 @@ dependencies = [
|
|||||||
"syn 1.0.107",
|
"syn 1.0.107",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctr"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||||
|
dependencies = [
|
||||||
|
"cipher 0.4.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cty"
|
name = "cty"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -571,6 +807,17 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5"
|
checksum = "8d7439c3735f405729d52c3fbbe4de140eaf938a1fe47d227c27f8254d4302a5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derivative"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.107",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.17"
|
version = "0.99.17"
|
||||||
@ -592,6 +839,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -671,16 +919,24 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_logger"
|
name = "enumflags2"
|
||||||
version = "0.10.0"
|
version = "0.7.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
|
checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"humantime",
|
"enumflags2_derive",
|
||||||
"is-terminal",
|
"serde",
|
||||||
"log",
|
]
|
||||||
"regex",
|
|
||||||
"termcolor",
|
[[package]]
|
||||||
|
name = "enumflags2_derive"
|
||||||
|
version = "0.7.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.16",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -704,6 +960,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "event-listener"
|
||||||
|
version = "2.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
@ -729,7 +991,7 @@ version = "0.3.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
|
checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset 0.6.5",
|
||||||
"rustc_version 0.3.3",
|
"rustc_version 0.3.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -827,6 +1089,21 @@ version = "0.3.26"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
|
checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-lite"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"memchr",
|
||||||
|
"parking",
|
||||||
|
"pin-project-lite",
|
||||||
|
"waker-fn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.26"
|
version = "0.3.26"
|
||||||
@ -857,8 +1134,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
"futures-macro",
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"slab",
|
"slab",
|
||||||
@ -1004,6 +1284,16 @@ dependencies = [
|
|||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ghash"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
|
||||||
|
dependencies = [
|
||||||
|
"opaque-debug",
|
||||||
|
"polyval",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio"
|
name = "gio"
|
||||||
version = "0.15.12"
|
version = "0.15.12"
|
||||||
@ -1139,8 +1429,9 @@ dependencies = [
|
|||||||
name = "gpservice"
|
name = "gpservice"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"fern",
|
||||||
"gpcommon",
|
"gpcommon",
|
||||||
|
"humantime",
|
||||||
"log",
|
"log",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
@ -1251,6 +1542,24 @@ version = "0.4.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hkdf"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
||||||
|
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 = "html5ever"
|
name = "html5ever"
|
||||||
version = "0.25.2"
|
version = "0.25.2"
|
||||||
@ -1388,6 +1697,15 @@ dependencies = [
|
|||||||
"cfb",
|
"cfb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instant"
|
name = "instant"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
@ -1408,18 +1726,6 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "is-terminal"
|
|
||||||
version = "0.4.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi 0.3.1",
|
|
||||||
"io-lifetimes",
|
|
||||||
"rustix",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_executable"
|
name = "is_executable"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -1505,6 +1811,20 @@ dependencies = [
|
|||||||
"treediff",
|
"treediff",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "keyring"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04ac4b8b0884cdf23c4619d139acf43839eac4f0739b92980c2a6d460d9c84f5"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"lazy_static",
|
||||||
|
"linux-keyutils",
|
||||||
|
"secret-service",
|
||||||
|
"security-framework",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kuchiki"
|
name = "kuchiki"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@ -1538,6 +1858,16 @@ dependencies = [
|
|||||||
"safemem",
|
"safemem",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-keyutils"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f27bb67f6dd1d0bb5ab582868e4f65052e58da6401188a08f0da09cf512b84b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@ -1638,6 +1968,15 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
@ -1711,6 +2050,19 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.26.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"memoffset 0.7.1",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodrop"
|
name = "nodrop"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
@ -1727,6 +2079,40 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -1737,6 +2123,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-rational"
|
name = "num-rational"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -1744,6 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
|
"num-bigint",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@ -1831,6 +2229,12 @@ version = "1.17.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "open"
|
name = "open"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@ -1886,6 +2290,16 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-stream"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1917,6 +2331,12 @@ dependencies = [
|
|||||||
"system-deps 6.0.3",
|
"system-deps 6.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -2104,6 +2524,34 @@ dependencies = [
|
|||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polling"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"concurrent-queue",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"pin-project-lite",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyval"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -2423,6 +2871,25 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "secret-service"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95"
|
||||||
|
dependencies = [
|
||||||
|
"aes 0.7.5",
|
||||||
|
"block-modes",
|
||||||
|
"futures-util",
|
||||||
|
"generic-array",
|
||||||
|
"hkdf",
|
||||||
|
"num",
|
||||||
|
"once_cell",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
|
"zbus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "security-framework"
|
name = "security-framework"
|
||||||
version = "2.8.2"
|
version = "2.8.2"
|
||||||
@ -2616,6 +3083,17 @@ dependencies = [
|
|||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
@ -2636,6 +3114,16 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b824b6e687aff278cdbf3b36f07aa52d4bd4099699324d5da86a2ebce3aa00b3"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -2725,6 +3213,12 @@ dependencies = [
|
|||||||
"loom",
|
"loom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "string_cache"
|
name = "string_cache"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@ -2757,6 +3251,12 @@ version = "0.10.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "subtle"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.107"
|
version = "1.0.107"
|
||||||
@ -3112,15 +3612,6 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "termcolor"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thin-slice"
|
name = "thin-slice"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -3354,6 +3845,16 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
|
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uds_windows"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d"
|
||||||
|
dependencies = [
|
||||||
|
"tempfile",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.10"
|
version = "0.3.10"
|
||||||
@ -3381,6 +3882,16 @@ version = "1.10.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "universal-hash"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -3501,6 +4012,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "waker-fn"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
@ -4041,3 +4558,117 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xdg-home"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
|
||||||
|
dependencies = [
|
||||||
|
"nix",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus"
|
||||||
|
version = "3.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948"
|
||||||
|
dependencies = [
|
||||||
|
"async-broadcast",
|
||||||
|
"async-executor",
|
||||||
|
"async-fs",
|
||||||
|
"async-io",
|
||||||
|
"async-lock",
|
||||||
|
"async-process",
|
||||||
|
"async-recursion",
|
||||||
|
"async-task",
|
||||||
|
"async-trait",
|
||||||
|
"blocking",
|
||||||
|
"byteorder",
|
||||||
|
"derivative",
|
||||||
|
"enumflags2",
|
||||||
|
"event-listener",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"hex",
|
||||||
|
"nix",
|
||||||
|
"once_cell",
|
||||||
|
"ordered-stream",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"serde",
|
||||||
|
"serde_repr",
|
||||||
|
"sha1",
|
||||||
|
"static_assertions",
|
||||||
|
"tracing",
|
||||||
|
"uds_windows",
|
||||||
|
"winapi",
|
||||||
|
"xdg-home",
|
||||||
|
"zbus_macros",
|
||||||
|
"zbus_names",
|
||||||
|
"zvariant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_macros"
|
||||||
|
version = "3.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn 1.0.107",
|
||||||
|
"zvariant_utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zbus_names"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"static_assertions",
|
||||||
|
"zvariant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant"
|
||||||
|
version = "3.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"enumflags2",
|
||||||
|
"libc",
|
||||||
|
"serde",
|
||||||
|
"static_assertions",
|
||||||
|
"zvariant_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant_derive"
|
||||||
|
version = "3.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.107",
|
||||||
|
"zvariant_utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zvariant_utils"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.107",
|
||||||
|
]
|
||||||
|
@ -201,8 +201,14 @@ impl Client {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn connect(&self, server: String, cookie: String) -> Result<(), ServerApiError> {
|
pub async fn connect(
|
||||||
self.send_command(Connect::new(server, cookie).into()).await
|
&self,
|
||||||
|
server: String,
|
||||||
|
cookie: String,
|
||||||
|
user_agent: String,
|
||||||
|
) -> Result<(), ServerApiError> {
|
||||||
|
self.send_command(Connect::new(server, cookie, user_agent).into())
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn disconnect(&self) -> Result<(), ServerApiError> {
|
pub async fn disconnect(&self) -> Result<(), ServerApiError> {
|
||||||
|
@ -7,11 +7,16 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub struct Connect {
|
pub struct Connect {
|
||||||
server: String,
|
server: String,
|
||||||
cookie: String,
|
cookie: String,
|
||||||
|
user_agent: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connect {
|
impl Connect {
|
||||||
pub fn new(server: String, cookie: String) -> Self {
|
pub fn new(server: String, cookie: String, user_agent: String) -> Self {
|
||||||
Self { server, cookie }
|
Self {
|
||||||
|
server,
|
||||||
|
cookie,
|
||||||
|
user_agent,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +30,7 @@ impl Command for Connect {
|
|||||||
return Err(format!("VPN is already in state: {:?}", status).into());
|
return Err(format!("VPN is already in state: {:?}", status).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = vpn.connect(&self.server, &self.cookie).await {
|
if let Err(err) = vpn.connect(&self.server, &self.cookie, &self.user_agent).await {
|
||||||
return Err(err.to_string().into());
|
return Err(err.to_string().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,16 +5,17 @@ use tokio::sync::mpsc;
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub(crate) struct Options {
|
pub(crate) struct Options {
|
||||||
pub server: *const ::std::os::raw::c_char,
|
pub server: *const std::os::raw::c_char,
|
||||||
pub cookie: *const ::std::os::raw::c_char,
|
pub cookie: *const std::os::raw::c_char,
|
||||||
pub script: *const ::std::os::raw::c_char,
|
pub script: *const std::os::raw::c_char,
|
||||||
|
pub user_agent: *const std::os::raw::c_char,
|
||||||
pub user_data: *mut c_void,
|
pub user_data: *mut c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[link(name = "vpn")]
|
#[link(name = "vpn")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = "vpn_connect"]
|
#[link_name = "vpn_connect"]
|
||||||
pub(crate) fn connect(options: *const Options) -> ::std::os::raw::c_int;
|
pub(crate) fn connect(options: *const Options) -> std::os::raw::c_int;
|
||||||
|
|
||||||
#[link_name = "vpn_disconnect"]
|
#[link_name = "vpn_disconnect"]
|
||||||
pub(crate) fn disconnect();
|
pub(crate) fn disconnect();
|
||||||
@ -32,7 +33,7 @@ extern "C" fn on_vpn_connected(value: i32, sender: *mut c_void) {
|
|||||||
// level: 0 = error, 1 = info, 2 = debug, 3 = trace
|
// level: 0 = error, 1 = info, 2 = debug, 3 = trace
|
||||||
// map the error level log in openconnect to the warning level
|
// map the error level log in openconnect to the warning level
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn vpn_log(level: i32, message: *const ::std::os::raw::c_char) {
|
extern "C" fn vpn_log(level: i32, message: *const std::os::raw::c_char) {
|
||||||
let message = unsafe { std::ffi::CStr::from_ptr(message) };
|
let message = unsafe { std::ffi::CStr::from_ptr(message) };
|
||||||
let message = message.to_str().unwrap_or("Invalid log message");
|
let message = message.to_str().unwrap_or("Invalid log message");
|
||||||
// Strip the trailing newline
|
// Strip the trailing newline
|
||||||
|
@ -56,6 +56,7 @@ pub(crate) struct VpnOptions {
|
|||||||
server: CString,
|
server: CString,
|
||||||
cookie: CString,
|
cookie: CString,
|
||||||
script: CString,
|
script: CString,
|
||||||
|
user_agent: CString,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VpnOptions {
|
impl VpnOptions {
|
||||||
@ -64,6 +65,7 @@ impl VpnOptions {
|
|||||||
server: self.server.as_ptr(),
|
server: self.server.as_ptr(),
|
||||||
cookie: self.cookie.as_ptr(),
|
cookie: self.cookie.as_ptr(),
|
||||||
script: self.script.as_ptr(),
|
script: self.script.as_ptr(),
|
||||||
|
user_agent: self.user_agent.as_ptr(),
|
||||||
user_data,
|
user_data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,6 +90,7 @@ impl Vpn {
|
|||||||
&self,
|
&self,
|
||||||
server: &str,
|
server: &str,
|
||||||
cookie: &str,
|
cookie: &str,
|
||||||
|
user_agent: &str,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let script = match find_default_vpnc_script() {
|
let script = match find_default_vpnc_script() {
|
||||||
Some(script) => {
|
Some(script) => {
|
||||||
@ -104,6 +107,7 @@ impl Vpn {
|
|||||||
server: VpnOptions::to_cstr(server),
|
server: VpnOptions::to_cstr(server),
|
||||||
cookie: VpnOptions::to_cstr(cookie),
|
cookie: VpnOptions::to_cstr(cookie),
|
||||||
script: VpnOptions::to_cstr(script),
|
script: VpnOptions::to_cstr(script),
|
||||||
|
user_agent: VpnOptions::to_cstr(user_agent),
|
||||||
});
|
});
|
||||||
|
|
||||||
let vpn_options = self.vpn_options.clone();
|
let vpn_options = self.vpn_options.clone();
|
||||||
|
@ -53,7 +53,7 @@ int vpn_connect(const vpn_options *options)
|
|||||||
g_user_data = options->user_data;
|
g_user_data = options->user_data;
|
||||||
g_vpnc_script = options->script;
|
g_vpnc_script = options->script;
|
||||||
|
|
||||||
vpninfo = openconnect_vpninfo_new("PAN GlobalProtect", validate_peer_cert, NULL, NULL, print_progress, NULL);
|
vpninfo = openconnect_vpninfo_new(options->user_agent, validate_peer_cert, NULL, NULL, print_progress, NULL);
|
||||||
|
|
||||||
if (!vpninfo)
|
if (!vpninfo)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ typedef struct vpn_options
|
|||||||
const char *server;
|
const char *server;
|
||||||
const char *cookie;
|
const char *cookie;
|
||||||
const char *script;
|
const char *script;
|
||||||
|
const char *user_agent;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
} vpn_options;
|
} vpn_options;
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-spinners": "^0.13.8",
|
"react-spinners": "^0.13.8",
|
||||||
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log",
|
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1"
|
||||||
"tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#v1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^1.3.1",
|
"@tauri-apps/cli": "^1.3.1",
|
||||||
|
28
gpgui/pnpm-lock.yaml
generated
28
gpgui/pnpm-lock.yaml
generated
@ -1,4 +1,4 @@
|
|||||||
lockfileVersion: '6.1'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
@ -48,11 +48,8 @@ dependencies:
|
|||||||
specifier: ^0.13.8
|
specifier: ^0.13.8
|
||||||
version: 0.13.8(react-dom@18.2.0)(react@18.2.0)
|
version: 0.13.8(react-dom@18.2.0)(react@18.2.0)
|
||||||
tauri-plugin-log-api:
|
tauri-plugin-log-api:
|
||||||
specifier: github:tauri-apps/tauri-plugin-log
|
specifier: github:tauri-apps/tauri-plugin-log#v1
|
||||||
version: github.com/tauri-apps/tauri-plugin-log/21921031d74f871180381317a338559f588ad8e9
|
version: github.com/tauri-apps/tauri-plugin-log/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6
|
||||||
tauri-plugin-store-api:
|
|
||||||
specifier: github:tauri-apps/tauri-plugin-store#v1
|
|
||||||
version: github.com/tauri-apps/tauri-plugin-store/1467ba770623ab1d41d825841c3d9435d9eaa0f1
|
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
@ -878,6 +875,11 @@ packages:
|
|||||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@tauri-apps/api@1.4.0:
|
||||||
|
resolution: {integrity: sha512-Jd6HPoTM1PZSFIzq7FB8VmMu3qSSyo/3lSwLpoapW+lQ41CL5Dow2KryLg+gyazA/58DRWI9vu/XpEeHK4uMdw==}
|
||||||
|
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@tauri-apps/cli-darwin-arm64@1.3.1:
|
/@tauri-apps/cli-darwin-arm64@1.3.1:
|
||||||
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
|
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
@ -1465,18 +1467,10 @@ packages:
|
|||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
github.com/tauri-apps/tauri-plugin-log/21921031d74f871180381317a338559f588ad8e9:
|
github.com/tauri-apps/tauri-plugin-log/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6:
|
||||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-log/tar.gz/21921031d74f871180381317a338559f588ad8e9}
|
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-log/tar.gz/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6}
|
||||||
name: tauri-plugin-log-api
|
name: tauri-plugin-log-api
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tauri-apps/api': 1.3.0
|
'@tauri-apps/api': 1.4.0
|
||||||
dev: false
|
|
||||||
|
|
||||||
github.com/tauri-apps/tauri-plugin-store/1467ba770623ab1d41d825841c3d9435d9eaa0f1:
|
|
||||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-store/tar.gz/1467ba770623ab1d41d825841c3d9435d9eaa0f1}
|
|
||||||
name: tauri-plugin-store-api
|
|
||||||
version: 0.0.0
|
|
||||||
dependencies:
|
|
||||||
'@tauri-apps/api': 1.3.0
|
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -23,7 +23,6 @@ tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", br
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.10"
|
|
||||||
webkit2gtk = "0.18.2"
|
webkit2gtk = "0.18.2"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
url = "2.3"
|
url = "2.3"
|
||||||
@ -32,6 +31,10 @@ veil = "0.1.6"
|
|||||||
whoami = "1.4.1"
|
whoami = "1.4.1"
|
||||||
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||||
openssl = "0.10"
|
openssl = "0.10"
|
||||||
|
keyring = "2"
|
||||||
|
aes-gcm = { version = "0.10", features = ["std"] }
|
||||||
|
hex = "0.4"
|
||||||
|
anyhow = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# by default Tauri runs in production mode
|
# by default Tauri runs in production mode
|
||||||
|
@ -133,7 +133,7 @@ fn build_window(app_handle: &AppHandle, ua: &str) -> tauri::Result<Window> {
|
|||||||
Window::builder(app_handle, AUTH_WINDOW_LABEL, url)
|
Window::builder(app_handle, AUTH_WINDOW_LABEL, url)
|
||||||
.visible(false)
|
.visible(false)
|
||||||
.title("GlobalProtect Login")
|
.title("GlobalProtect Login")
|
||||||
.inner_size(400.0, 647.0)
|
.inner_size(600.0, 500.0)
|
||||||
.min_inner_size(370.0, 600.0)
|
.min_inner_size(370.0, 600.0)
|
||||||
.user_agent(ua)
|
.user_agent(ua)
|
||||||
.always_on_top(true)
|
.always_on_top(true)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
auth::{self, AuthData, AuthRequest, SamlBinding, SamlLoginParams},
|
auth::{self, AuthData, AuthRequest, SamlBinding, SamlLoginParams},
|
||||||
|
storage::{AppStorage, KeyHint},
|
||||||
utils::get_openssl_conf,
|
utils::get_openssl_conf,
|
||||||
utils::get_openssl_conf_path,
|
utils::get_openssl_conf_path,
|
||||||
};
|
};
|
||||||
use gpcommon::{Client, ServerApiError, VpnStatus};
|
use gpcommon::{Client, ServerApiError, VpnStatus};
|
||||||
|
use serde_json::Value;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tauri::{AppHandle, State};
|
use tauri::{AppHandle, State};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
@ -24,9 +26,10 @@ pub(crate) async fn vpn_status<'a>(
|
|||||||
pub(crate) async fn vpn_connect<'a>(
|
pub(crate) async fn vpn_connect<'a>(
|
||||||
server: String,
|
server: String,
|
||||||
cookie: String,
|
cookie: String,
|
||||||
|
user_agent: String,
|
||||||
client: State<'a, Arc<Client>>,
|
client: State<'a, Arc<Client>>,
|
||||||
) -> Result<(), ServerApiError> {
|
) -> Result<(), ServerApiError> {
|
||||||
client.connect(server, cookie).await
|
client.connect(server, cookie, user_agent).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@ -40,10 +43,10 @@ pub(crate) async fn vpn_disconnect<'a>(
|
|||||||
pub(crate) async fn saml_login(
|
pub(crate) async fn saml_login(
|
||||||
binding: SamlBinding,
|
binding: SamlBinding,
|
||||||
request: String,
|
request: String,
|
||||||
|
user_agent: String,
|
||||||
clear_cookies: bool,
|
clear_cookies: bool,
|
||||||
app_handle: AppHandle,
|
app_handle: AppHandle,
|
||||||
) -> tauri::Result<Option<AuthData>> {
|
) -> tauri::Result<Option<AuthData>> {
|
||||||
let user_agent = String::from("PAN GlobalProtect");
|
|
||||||
let params = SamlLoginParams {
|
let params = SamlLoginParams {
|
||||||
auth_request: AuthRequest::new(binding, request),
|
auth_request: AuthRequest::new(binding, request),
|
||||||
user_agent,
|
user_agent,
|
||||||
@ -71,3 +74,29 @@ pub(crate) async fn update_openssl_config(app_handle: AppHandle) -> tauri::Resul
|
|||||||
fs::write(openssl_conf_path, openssl_conf).await?;
|
fs::write(openssl_conf_path, openssl_conf).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub(crate) async fn store_get<'a>(
|
||||||
|
hint: KeyHint<'_>,
|
||||||
|
app_storage: State<'_, AppStorage<'_>>,
|
||||||
|
) -> Result<Option<Value>, ()> {
|
||||||
|
Ok(app_storage.get(hint))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub(crate) fn store_set(
|
||||||
|
hint: KeyHint,
|
||||||
|
value: Value,
|
||||||
|
app_storage: State<'_, AppStorage>,
|
||||||
|
) -> Result<(), tauri_plugin_store::Error> {
|
||||||
|
app_storage.set(hint, &value)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub(crate) fn store_save(
|
||||||
|
app_storage: State<'_, AppStorage>,
|
||||||
|
) -> Result<(), tauri_plugin_store::Error> {
|
||||||
|
app_storage.save()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
46
gpgui/src-tauri/src/crypto.rs
Normal file
46
gpgui/src-tauri/src/crypto.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use aes_gcm::{
|
||||||
|
aead::{consts::U12, Aead, OsRng},
|
||||||
|
AeadCore, Aes256Gcm, Key, KeyInit, Nonce,
|
||||||
|
};
|
||||||
|
use keyring::Entry;
|
||||||
|
|
||||||
|
const SERVICE_NAME: &str = "GlobalProtect-openconnect";
|
||||||
|
const ENTRY_KEY: &str = "master-key";
|
||||||
|
|
||||||
|
fn get_master_key() -> Result<Key<Aes256Gcm>, anyhow::Error> {
|
||||||
|
let key_entry = Entry::new(SERVICE_NAME, ENTRY_KEY)?;
|
||||||
|
|
||||||
|
if let Ok(key) = key_entry.get_password() {
|
||||||
|
let key = hex::decode(key)?;
|
||||||
|
return Ok(Key::<Aes256Gcm>::clone_from_slice(&key));
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = Aes256Gcm::generate_key(OsRng);
|
||||||
|
let encoded_key = hex::encode(key);
|
||||||
|
|
||||||
|
key_entry.set_password(&encoded_key)?;
|
||||||
|
|
||||||
|
Ok(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn encrypt(data: &str) -> Result<String, anyhow::Error> {
|
||||||
|
let master_key = get_master_key()?;
|
||||||
|
let cipher = Aes256Gcm::new(&master_key);
|
||||||
|
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
|
||||||
|
let cipher_text = cipher.encrypt(&nonce, data.as_bytes())?;
|
||||||
|
|
||||||
|
let mut encrypted = nonce.to_vec();
|
||||||
|
encrypted.extend_from_slice(&cipher_text);
|
||||||
|
Ok(hex::encode(encrypted))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn decrypt(encrypted: &str) -> Result<String, anyhow::Error> {
|
||||||
|
let master_key = get_master_key()?;
|
||||||
|
let encrypted = hex::decode(encrypted)?;
|
||||||
|
let nonce = Nonce::<U12>::from_slice(&encrypted[..12]);
|
||||||
|
let cipher_text = &encrypted[12..];
|
||||||
|
let cipher = Aes256Gcm::new(&master_key);
|
||||||
|
let plain_text = cipher.decrypt(nonce, cipher_text)?;
|
||||||
|
|
||||||
|
String::from_utf8(plain_text).map_err(|err| err.into())
|
||||||
|
}
|
@ -2,93 +2,26 @@
|
|||||||
all(not(debug_assertions), target_os = "windows"),
|
all(not(debug_assertions), target_os = "windows"),
|
||||||
windows_subsystem = "windows"
|
windows_subsystem = "windows"
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use crate::utils::get_openssl_conf_path;
|
|
||||||
use env_logger::Env;
|
|
||||||
use gpcommon::{Client, ClientStatus, VpnStatus};
|
|
||||||
use log::{info, warn};
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::{path::PathBuf, sync::Arc};
|
|
||||||
use tauri::{Manager, Wry};
|
|
||||||
use tauri_plugin_log::LogTarget;
|
use tauri_plugin_log::LogTarget;
|
||||||
use tauri_plugin_store::{with_store, StoreCollection};
|
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
mod commands;
|
mod commands;
|
||||||
|
mod crypto;
|
||||||
|
mod settings;
|
||||||
|
mod setup;
|
||||||
|
mod storage;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
struct VpnStatusPayload {
|
|
||||||
status: VpnStatus,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let client = Arc::new(Client::default());
|
|
||||||
let client_clone = client.clone();
|
|
||||||
let app_handle = app.handle();
|
|
||||||
|
|
||||||
let stores = app.state::<StoreCollection<Wry>>();
|
|
||||||
let path = PathBuf::from(".settings.dat");
|
|
||||||
let _ = with_store(app_handle.clone(), stores, path, |store| {
|
|
||||||
let settings_data = store.get("SETTINGS_DATA");
|
|
||||||
let custom_openssl = settings_data.map_or(false, |data| {
|
|
||||||
data["customOpenSSL"].as_bool().unwrap_or(false)
|
|
||||||
});
|
|
||||||
|
|
||||||
if custom_openssl {
|
|
||||||
info!("Using custom OpenSSL config");
|
|
||||||
let openssl_conf = get_openssl_conf_path(&app_handle).into_os_string();
|
|
||||||
std::env::set_var("OPENSSL_CONF", openssl_conf);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move {
|
|
||||||
client_clone.subscribe_status(move |client_status| match client_status {
|
|
||||||
ClientStatus::Vpn(vpn_status) => {
|
|
||||||
let payload = VpnStatusPayload { status: vpn_status };
|
|
||||||
if let Err(err) = app_handle.emit_all("vpn-status-received", payload) {
|
|
||||||
warn!("Error emitting event: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClientStatus::Service(is_online) => {
|
|
||||||
if let Err(err) = app_handle.emit_all("service-status-changed", is_online) {
|
|
||||||
warn!("Error emitting event: {}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let _ = client_clone.run().await;
|
|
||||||
});
|
|
||||||
|
|
||||||
app.manage(client);
|
|
||||||
|
|
||||||
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
|
|
||||||
if desktop == "KDE" {
|
|
||||||
if let Some(main_window) = app.get_window("main") {
|
|
||||||
let _ = main_window.set_decorations(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(
|
.plugin(
|
||||||
tauri_plugin_log::Builder::default()
|
tauri_plugin_log::Builder::default()
|
||||||
.targets([
|
.targets([LogTarget::LogDir, LogTarget::Stdout])
|
||||||
LogTarget::LogDir,
|
|
||||||
LogTarget::Stdout, /*LogTarget::Webview*/
|
|
||||||
])
|
|
||||||
.level(log::LevelFilter::Info)
|
.level(log::LevelFilter::Info)
|
||||||
.with_colors(Default::default())
|
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.plugin(tauri_plugin_store::Builder::default().build())
|
.plugin(tauri_plugin_store::Builder::default().build())
|
||||||
.setup(setup)
|
.setup(setup::setup)
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
commands::service_online,
|
commands::service_online,
|
||||||
commands::vpn_status,
|
commands::vpn_status,
|
||||||
@ -98,6 +31,9 @@ fn main() {
|
|||||||
commands::os_version,
|
commands::os_version,
|
||||||
commands::openssl_config,
|
commands::openssl_config,
|
||||||
commands::update_openssl_config,
|
commands::update_openssl_config,
|
||||||
|
commands::store_get,
|
||||||
|
commands::store_set,
|
||||||
|
commands::store_save,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
19
gpgui/src-tauri/src/settings.rs
Normal file
19
gpgui/src-tauri/src/settings.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use crate::storage::{AppStorage, KeyHint};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tauri::{AppHandle, Manager};
|
||||||
|
|
||||||
|
const STORAGE_KEY: &str = "SETTINGS_DATA";
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct Settings {
|
||||||
|
#[serde(rename = "customOpenSSL")]
|
||||||
|
custom_openssl: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn is_custom_openssl_enabled(app_handle: &AppHandle) -> bool {
|
||||||
|
let app_storage = app_handle.state::<AppStorage>();
|
||||||
|
let hint = KeyHint::new(STORAGE_KEY, false);
|
||||||
|
let settings = app_storage.get::<Settings>(hint);
|
||||||
|
|
||||||
|
settings.map_or(false, |settings| settings.custom_openssl)
|
||||||
|
}
|
81
gpgui/src-tauri/src/setup.rs
Normal file
81
gpgui/src-tauri/src/setup.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use crate::{settings, storage::AppStorage, utils::get_openssl_conf_path};
|
||||||
|
use gpcommon::{Client, ClientStatus, VpnStatus};
|
||||||
|
use log::{info, warn};
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tauri::Manager;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
struct VpnStatusPayload {
|
||||||
|
status: VpnStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_window(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let desktop = std::env::var("XDG_CURRENT_DESKTOP")?;
|
||||||
|
if desktop == "KDE" {
|
||||||
|
if let Some(main_window) = app.get_window("main") {
|
||||||
|
let _ = main_window.set_decorations(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_app_storage(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let app_handle = app.app_handle();
|
||||||
|
let app_storage = AppStorage::new(app_handle);
|
||||||
|
|
||||||
|
app.manage(app_storage);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_app_env(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let app_handle = app.app_handle();
|
||||||
|
let use_custom_openssl = settings::is_custom_openssl_enabled(&app_handle);
|
||||||
|
|
||||||
|
if use_custom_openssl {
|
||||||
|
info!("Using custom OpenSSL config");
|
||||||
|
|
||||||
|
let openssl_conf = get_openssl_conf_path(&app_handle).into_os_string();
|
||||||
|
std::env::set_var("OPENSSL_CONF", openssl_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_vpn_client(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let app_handle = app.handle();
|
||||||
|
let client = Arc::new(Client::default());
|
||||||
|
let client_clone = client.clone();
|
||||||
|
|
||||||
|
app.manage(client_clone);
|
||||||
|
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
client.subscribe_status(move |client_status| match client_status {
|
||||||
|
ClientStatus::Vpn(vpn_status) => {
|
||||||
|
let payload = VpnStatusPayload { status: vpn_status };
|
||||||
|
if let Err(err) = app_handle.emit_all("vpn-status-received", payload) {
|
||||||
|
warn!("Error emitting event: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClientStatus::Service(is_online) => {
|
||||||
|
if let Err(err) = app_handle.emit_all("service-status-changed", is_online) {
|
||||||
|
warn!("Error emitting event: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let _ = client.run().await;
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
setup_window(app)?;
|
||||||
|
setup_app_storage(app)?;
|
||||||
|
setup_app_env(app)?;
|
||||||
|
setup_vpn_client(app)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
87
gpgui/src-tauri/src/storage.rs
Normal file
87
gpgui/src-tauri/src/storage.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
use crate::crypto::{decrypt, encrypt};
|
||||||
|
use log::warn;
|
||||||
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use tauri::{AppHandle, Manager, Wry};
|
||||||
|
use tauri_plugin_store::{with_store, Error, StoreCollection};
|
||||||
|
|
||||||
|
const STORE_PATH: &str = ".data.json";
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub(crate) struct KeyHint<'a> {
|
||||||
|
key: &'a str,
|
||||||
|
encrypted: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> KeyHint<'a> {
|
||||||
|
pub(crate) fn new(key: &'a str, encrypted: bool) -> Self {
|
||||||
|
Self { key, encrypted }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AppStorage<'a> {
|
||||||
|
path: &'a str,
|
||||||
|
app_handle: AppHandle<Wry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppStorage<'_> {
|
||||||
|
pub(crate) fn new(app_handle: AppHandle<Wry>) -> Self {
|
||||||
|
Self {
|
||||||
|
path: STORE_PATH,
|
||||||
|
app_handle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<T: DeserializeOwned + Debug>(&self, hint: KeyHint) -> Option<T> {
|
||||||
|
let stores = self.app_handle.state::<StoreCollection<Wry>>();
|
||||||
|
with_store(self.app_handle.clone(), stores, self.path, |store| {
|
||||||
|
store
|
||||||
|
.get(hint.key)
|
||||||
|
.ok_or_else(|| Error::Deserialize("Value not found".into()))
|
||||||
|
.and_then(|value| {
|
||||||
|
if !hint.encrypted {
|
||||||
|
return Ok(serde_json::from_value::<T>(value.clone())?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = value
|
||||||
|
.as_str()
|
||||||
|
.ok_or_else(|| Error::Deserialize("Value is not a string".into()))?;
|
||||||
|
let value = decrypt(value).map_err(|err| {
|
||||||
|
Error::Deserialize(format!("Failed to decrypt value: {}", err).into())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(serde_json::from_str::<T>(&value)?)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map_err(|err| warn!("Error getting value: {:?}", err))
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set<T: serde::Serialize>(&self, hint: KeyHint, value: &T) -> Result<(), Error> {
|
||||||
|
let stores = self.app_handle.state::<StoreCollection<Wry>>();
|
||||||
|
|
||||||
|
with_store(self.app_handle.clone(), stores, self.path, |store| {
|
||||||
|
let value = if hint.encrypted {
|
||||||
|
let json_str = serde_json::to_string(value)?;
|
||||||
|
let encrypted = encrypt(&json_str).map_err(|err| {
|
||||||
|
Error::Serialize(format!("Failed to encrypt value: {}", err).into())
|
||||||
|
})?;
|
||||||
|
serde_json::to_value(encrypted)?
|
||||||
|
} else {
|
||||||
|
serde_json::to_value(value)?
|
||||||
|
};
|
||||||
|
|
||||||
|
store.insert(hint.key.to_string(), value)?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> Result<(), Error> {
|
||||||
|
let stores = self.app_handle.state::<StoreCollection<Wry>>();
|
||||||
|
|
||||||
|
with_store(self.app_handle.clone(), stores, self.path, |store| {
|
||||||
|
store.save()?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,11 @@ export const portalGatewaysAtom = atom<GatewayData[]>((get) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const selectedGatewayAtom = atom(
|
export const selectedGatewayAtom = atom(
|
||||||
(get) => get(currentPortalDataAtom).selectedGateway,
|
(get) => {
|
||||||
|
const { selectedGateway } = get(currentPortalDataAtom);
|
||||||
|
const gateways = get(portalGatewaysAtom);
|
||||||
|
return gateways.find(({ name }) => name === selectedGateway);
|
||||||
|
},
|
||||||
async (get, set, update: string) => {
|
async (get, set, update: string) => {
|
||||||
const portalData = get(currentPortalDataAtom);
|
const portalData = get(currentPortalDataAtom);
|
||||||
await set(updatePortalDataAtom, { ...portalData, selectedGateway: update });
|
await set(updatePortalDataAtom, { ...portalData, selectedGateway: update });
|
||||||
|
@ -62,7 +62,7 @@ export const loginPortalAtom = atom(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Here, we have got the portal config successfully, refresh the cached portal data
|
// Here, we have got the portal config successfully, refresh the cached portal data
|
||||||
const previousSelectedGateway = get(selectedGatewayAtom);
|
const previousSelectedGateway = get(selectedGatewayAtom)?.name;
|
||||||
const selectedGateway = gateways.find(
|
const selectedGateway = gateways.find(
|
||||||
({ name }) => name === previousSelectedGateway
|
({ name }) => name === previousSelectedGateway
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { atom } from "jotai";
|
import { atom } from "jotai";
|
||||||
import { atomWithDefault } from "jotai/utils";
|
import { atomWithDefault } from "jotai/utils";
|
||||||
import { PortalCredential } from "../services/portalService";
|
import { PortalCredential } from "../services/portalService";
|
||||||
import { atomWithTauriStorage } from "../services/storeService";
|
import { atomWithTauriStorage } from "../services/storageService";
|
||||||
import { unwrap } from "./unwrap";
|
import { unwrap } from "./unwrap";
|
||||||
|
|
||||||
export type GatewayData = {
|
export type GatewayData = {
|
||||||
@ -31,7 +31,11 @@ const DEFAULT_APP_DATA: AppData = {
|
|||||||
clearCookies: true,
|
clearCookies: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const appDataAtom = atomWithTauriStorage("APP_DATA", DEFAULT_APP_DATA);
|
const keyHint = {
|
||||||
|
key: "APP_DATA",
|
||||||
|
encrypted: true,
|
||||||
|
};
|
||||||
|
export const appDataAtom = atomWithTauriStorage(keyHint, DEFAULT_APP_DATA);
|
||||||
const unwrappedAppDataAtom = atom(
|
const unwrappedAppDataAtom = atom(
|
||||||
(get) => get(unwrap(appDataAtom)) || DEFAULT_APP_DATA
|
(get) => get(unwrap(appDataAtom)) || DEFAULT_APP_DATA
|
||||||
);
|
);
|
||||||
@ -51,6 +55,11 @@ export const currentPortalDataAtom = atom<PortalData>((get) => {
|
|||||||
return portalData || { address: portalAddress, gateways: [] };
|
return portalData || { address: portalAddress, gateways: [] };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const allPortalsAtom = atom((get) => {
|
||||||
|
const { portals } = get(unwrappedAppDataAtom);
|
||||||
|
return portals.map(({ address }) => address);
|
||||||
|
});
|
||||||
|
|
||||||
export const updatePortalDataAtom = atom(
|
export const updatePortalDataAtom = atom(
|
||||||
null,
|
null,
|
||||||
async (get, set, update: PortalData) => {
|
async (get, set, update: PortalData) => {
|
||||||
|
@ -5,7 +5,7 @@ import settingsService, {
|
|||||||
DEFAULT_SETTINGS_DATA,
|
DEFAULT_SETTINGS_DATA,
|
||||||
SETTINGS_DATA,
|
SETTINGS_DATA,
|
||||||
} from "../services/settingsService";
|
} from "../services/settingsService";
|
||||||
import { atomWithTauriStorage } from "../services/storeService";
|
import { atomWithTauriStorage } from "../services/storageService";
|
||||||
import { unwrap } from "./unwrap";
|
import { unwrap } from "./unwrap";
|
||||||
|
|
||||||
const settingsDataAtom = atomWithTauriStorage(
|
const settingsDataAtom = atomWithTauriStorage(
|
||||||
|
@ -4,6 +4,7 @@ import vpnService from "../services/vpnService";
|
|||||||
import { selectedGatewayAtom, switchGatewayAtom } from "./gateway";
|
import { selectedGatewayAtom, switchGatewayAtom } from "./gateway";
|
||||||
import { notifyErrorAtom, notifySuccessAtom } from "./notification";
|
import { notifyErrorAtom, notifySuccessAtom } from "./notification";
|
||||||
import { unwrap } from "./unwrap";
|
import { unwrap } from "./unwrap";
|
||||||
|
import { portalAddressAtom } from "./portal";
|
||||||
|
|
||||||
export type Status =
|
export type Status =
|
||||||
| "disconnected"
|
| "disconnected"
|
||||||
@ -75,14 +76,16 @@ export const statusTextAtom = atom<string>((get) => {
|
|||||||
|
|
||||||
if (status === "connected") {
|
if (status === "connected") {
|
||||||
const selectedGateway = get(selectedGatewayAtom);
|
const selectedGateway = get(selectedGatewayAtom);
|
||||||
return selectedGateway
|
const portalAddress = get(portalAddressAtom);
|
||||||
? `Gateway: ${selectedGateway}`
|
|
||||||
: statusTextMap[status];
|
return selectedGateway?.address === portalAddress
|
||||||
|
? statusTextMap[status]
|
||||||
|
: selectedGateway?.address!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchingGateway) {
|
if (switchingGateway) {
|
||||||
const selectedGateway = get(selectedGatewayAtom);
|
const selectedGateway = get(selectedGatewayAtom);
|
||||||
return `Switching to ${selectedGateway}`;
|
return `Switching to ${selectedGateway?.name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return statusTextMap[status];
|
return statusTextMap[status];
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import {
|
import { Box, CssBaseline, ThemeProvider } from "@mui/material";
|
||||||
Box,
|
import React, { Suspense } from "react";
|
||||||
CssBaseline,
|
|
||||||
ThemeProvider,
|
|
||||||
createTheme,
|
|
||||||
useMediaQuery,
|
|
||||||
} from "@mui/material";
|
|
||||||
import React, { Suspense, useMemo } from "react";
|
|
||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import "./styles.css";
|
import "./styles.css";
|
||||||
|
import useGlobalTheme from "./useGlobalTheme";
|
||||||
|
|
||||||
function Loading() {
|
function Loading() {
|
||||||
console.warn("Loading rendered");
|
console.warn("Loading rendered");
|
||||||
@ -27,16 +22,7 @@ function Loading() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AppShell({ children }: { children: React.ReactNode }) {
|
function AppShell({ children }: { children: React.ReactNode }) {
|
||||||
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
|
const theme = useGlobalTheme();
|
||||||
const theme = useMemo(
|
|
||||||
() =>
|
|
||||||
createTheme({
|
|
||||||
palette: {
|
|
||||||
mode: prefersDarkMode ? "dark" : "light",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
[prefersDarkMode]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
31
gpgui/src/components/AppShell/useGlobalTheme.ts
Normal file
31
gpgui/src/components/AppShell/useGlobalTheme.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { createTheme, useMediaQuery } from "@mui/material";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
export default function useGlobalTheme() {
|
||||||
|
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
|
||||||
|
return useMemo(
|
||||||
|
() =>
|
||||||
|
createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: prefersDarkMode ? "dark" : "light",
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
textTransform: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiTab: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
textTransform: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[prefersDarkMode]
|
||||||
|
);
|
||||||
|
}
|
@ -57,7 +57,7 @@ export default function PasswordAuth() {
|
|||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={cancelPasswordAuth}
|
onClick={cancelPasswordAuth}
|
||||||
sx={{ flex: 1, textTransform: "none" }}
|
sx={{ flex: 1 }}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
@ -66,7 +66,6 @@ export default function PasswordAuth() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
sx={{ flex: 1, textTransform: "none" }}
|
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Button, TextField } from "@mui/material";
|
import { Autocomplete, Button, TextField } from "@mui/material";
|
||||||
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||||
import { ChangeEvent } from "react";
|
import { ChangeEvent, useState } from "react";
|
||||||
import {
|
import {
|
||||||
cancelConnectPortalAtom,
|
cancelConnectPortalAtom,
|
||||||
connectPortalAtom,
|
connectPortalAtom,
|
||||||
} from "../../atoms/connectPortal";
|
} from "../../atoms/connectPortal";
|
||||||
import { switchGatewayAtom } from "../../atoms/gateway";
|
import { switchGatewayAtom } from "../../atoms/gateway";
|
||||||
import { portalAddressAtom } from "../../atoms/portal";
|
import { allPortalsAtom, portalAddressAtom } from "../../atoms/portal";
|
||||||
import {
|
import {
|
||||||
backgroundServiceStartedAtom,
|
backgroundServiceStartedAtom,
|
||||||
isProcessingAtom,
|
isProcessingAtom,
|
||||||
@ -26,6 +26,7 @@ function normalizePortalAddress(input: string) {
|
|||||||
|
|
||||||
export default function PortalForm() {
|
export default function PortalForm() {
|
||||||
const backgroundServiceStarted = useAtomValue(backgroundServiceStartedAtom);
|
const backgroundServiceStarted = useAtomValue(backgroundServiceStartedAtom);
|
||||||
|
const allPortals = useAtomValue(allPortalsAtom);
|
||||||
const [portalAddress, setPortalAddress] = useAtom(portalAddressAtom);
|
const [portalAddress, setPortalAddress] = useAtom(portalAddressAtom);
|
||||||
// Use useAtom instead of useSetAtom, otherwise the onMount of the atom is not triggered
|
// Use useAtom instead of useSetAtom, otherwise the onMount of the atom is not triggered
|
||||||
const [, connectPortal] = useAtom(connectPortalAtom);
|
const [, connectPortal] = useAtom(connectPortalAtom);
|
||||||
@ -35,8 +36,10 @@ export default function PortalForm() {
|
|||||||
const disconnectVpn = useSetAtom(disconnectVpnAtom);
|
const disconnectVpn = useSetAtom(disconnectVpnAtom);
|
||||||
const switchingGateway = useAtomValue(switchGatewayAtom);
|
const switchingGateway = useAtomValue(switchGatewayAtom);
|
||||||
|
|
||||||
function handlePortalAddressChange(e: ChangeEvent<HTMLInputElement>) {
|
const readOnly = status !== "disconnected" || switchingGateway;
|
||||||
setPortalAddress(normalizePortalAddress(e.target.value));
|
|
||||||
|
function handlePortalAddressChange(e: unknown, value: string) {
|
||||||
|
setPortalAddress(normalizePortalAddress(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSubmit(e: ChangeEvent<HTMLFormElement>) {
|
function handleSubmit(e: ChangeEvent<HTMLFormElement>) {
|
||||||
@ -46,16 +49,35 @@ export default function PortalForm() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} data-tauri-drag-region>
|
<form onSubmit={handleSubmit} data-tauri-drag-region>
|
||||||
<TextField
|
<Autocomplete
|
||||||
autoFocus
|
freeSolo
|
||||||
label="Portal address"
|
options={allPortals}
|
||||||
placeholder="Hostname or IP address"
|
inputValue={portalAddress}
|
||||||
fullWidth
|
onInputChange={handlePortalAddressChange}
|
||||||
|
readOnly={readOnly}
|
||||||
|
forcePopupIcon={!readOnly}
|
||||||
|
disableClearable
|
||||||
size="small"
|
size="small"
|
||||||
value={portalAddress}
|
sx={{
|
||||||
onChange={handlePortalAddressChange}
|
mb: 1,
|
||||||
InputProps={{ readOnly: status !== "disconnected" || switchingGateway }}
|
}}
|
||||||
sx={{ mb: 1 }}
|
componentsProps={{
|
||||||
|
paper: {
|
||||||
|
sx: {
|
||||||
|
"& .MuiAutocomplete-listbox .MuiAutocomplete-option": {
|
||||||
|
minHeight: "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
autoFocus
|
||||||
|
label="Portal address"
|
||||||
|
placeholder="Hostname or IP address"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{status === "disconnected" && !switchingGateway && (
|
{status === "disconnected" && !switchingGateway && (
|
||||||
@ -64,7 +86,6 @@ export default function PortalForm() {
|
|||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
disabled={!backgroundServiceStarted}
|
disabled={!backgroundServiceStarted}
|
||||||
sx={{ textTransform: "none" }}
|
|
||||||
>
|
>
|
||||||
Connect
|
Connect
|
||||||
</Button>
|
</Button>
|
||||||
@ -81,19 +102,13 @@ export default function PortalForm() {
|
|||||||
switchingGateway
|
switchingGateway
|
||||||
}
|
}
|
||||||
onClick={cancelConnectPortal}
|
onClick={cancelConnectPortal}
|
||||||
sx={{ textTransform: "none" }}
|
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{status === "connected" && (
|
{status === "connected" && (
|
||||||
<Button
|
<Button fullWidth variant="contained" onClick={disconnectVpn}>
|
||||||
fullWidth
|
|
||||||
variant="contained"
|
|
||||||
onClick={disconnectVpn}
|
|
||||||
sx={{ textTransform: "none" }}
|
|
||||||
>
|
|
||||||
Disconnect
|
Disconnect
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
@ -1,7 +1,18 @@
|
|||||||
import { GppBad, VerifiedUser as VerifiedIcon } from "@mui/icons-material";
|
import { GppBad, VerifiedUser as VerifiedIcon } from "@mui/icons-material";
|
||||||
import { Box, CircularProgress, styled, useTheme } from "@mui/material";
|
import {
|
||||||
import { useAtomValue } from "jotai";
|
Box,
|
||||||
|
Button,
|
||||||
|
CircularProgress,
|
||||||
|
Tooltip,
|
||||||
|
styled,
|
||||||
|
useTheme,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useAtomValue, useSetAtom } from "jotai";
|
||||||
import { BeatLoader } from "react-spinners";
|
import { BeatLoader } from "react-spinners";
|
||||||
|
import {
|
||||||
|
openGatewaySwitcherAtom,
|
||||||
|
selectedGatewayAtom,
|
||||||
|
} from "../../atoms/gateway";
|
||||||
import { isProcessingAtom, statusAtom } from "../../atoms/status";
|
import { isProcessingAtom, statusAtom } from "../../atoms/status";
|
||||||
|
|
||||||
function useStatusColor() {
|
function useStatusColor() {
|
||||||
@ -59,11 +70,48 @@ function ProcessingIcon() {
|
|||||||
return <BeatLoader color={theme.palette.info.main} />;
|
return <BeatLoader color={theme.palette.info.main} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConnectedIcon = styled(VerifiedIcon)(({ theme }) => ({
|
const ConnectedIcon = () => {
|
||||||
position: "relative",
|
const selectedGateway = useAtomValue(selectedGatewayAtom);
|
||||||
fontSize: 80,
|
const openGatewaySwitcher = useSetAtom(openGatewaySwitcherAtom);
|
||||||
color: theme.palette.success.main,
|
|
||||||
}));
|
return (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<VerifiedIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: 70,
|
||||||
|
color: (theme) => theme.palette.success.main,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tooltip title={`Connected to ${selectedGateway?.name}`}>
|
||||||
|
<Button
|
||||||
|
sx={{
|
||||||
|
position: "relative",
|
||||||
|
zIndex: 1,
|
||||||
|
fontSize: "0.75rem",
|
||||||
|
fontWeight: "bold",
|
||||||
|
display: "block",
|
||||||
|
width: 100,
|
||||||
|
mt: 0.2,
|
||||||
|
padding: 0.2,
|
||||||
|
overflow: "hidden",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
color="success"
|
||||||
|
onClick={openGatewaySwitcher}
|
||||||
|
>
|
||||||
|
{selectedGateway?.name}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const IconContainer = styled(Box)(({ theme }) =>
|
const IconContainer = styled(Box)(({ theme }) =>
|
||||||
theme.unstable_sx({
|
theme.unstable_sx({
|
||||||
|
@ -20,7 +20,7 @@ export default function GatewaySwitcher() {
|
|||||||
gatewaySwitcherVisibleAtom
|
gatewaySwitcherVisibleAtom
|
||||||
);
|
);
|
||||||
const gateways = useAtomValue(portalGatewaysAtom);
|
const gateways = useAtomValue(portalGatewaysAtom);
|
||||||
const selectedGateway = useAtomValue(selectedGatewayAtom);
|
const selectedGateway = useAtomValue(selectedGatewayAtom)?.name;
|
||||||
const switchGateway = useSetAtom(switchGatewayAtom);
|
const switchGateway = useSetAtom(switchGatewayAtom);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
@ -43,14 +43,12 @@ export default function SettingsPanel() {
|
|||||||
value="simulation"
|
value="simulation"
|
||||||
icon={<Devices />}
|
icon={<Devices />}
|
||||||
iconPosition="start"
|
iconPosition="start"
|
||||||
sx={{ textTransform: "none" }}
|
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="OpenSSL"
|
label="OpenSSL"
|
||||||
value="openssl"
|
value="openssl"
|
||||||
icon={<Https />}
|
icon={<Https />}
|
||||||
iconPosition="start"
|
iconPosition="start"
|
||||||
sx={{ textTransform: "none" }}
|
|
||||||
/>
|
/>
|
||||||
</TabList>
|
</TabList>
|
||||||
<Box sx={{ flex: 1 }}>
|
<Box sx={{ flex: 1 }}>
|
||||||
@ -61,12 +59,8 @@ export default function SettingsPanel() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ flexShrink: 0, borderTop: 1, borderColor: "divider" }}>
|
<Box sx={{ flexShrink: 0, borderTop: 1, borderColor: "divider" }}>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button sx={{ textTransform: "none" }} onClick={closeWindow}>
|
<Button onClick={closeWindow}>Cancel</Button>
|
||||||
Cancel
|
<Button onClick={save}>Save</Button>
|
||||||
</Button>
|
|
||||||
<Button sx={{ textTransform: "none" }} onClick={save}>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
|
import { useAtomValue } from "jotai";
|
||||||
|
import { appDataAtom } from "../atoms/portal";
|
||||||
import { renderToRoot } from "../components/AppShell";
|
import { renderToRoot } from "../components/AppShell";
|
||||||
import ConnectForm from "../components/ConnectForm";
|
import ConnectForm from "../components/ConnectForm";
|
||||||
import ConnectionStatus from "../components/ConnectionStatus";
|
import ConnectionStatus from "../components/ConnectionStatus";
|
||||||
@ -8,6 +10,10 @@ import MainMenu from "../components/MainMenu";
|
|||||||
import Notification from "../components/Notification";
|
import Notification from "../components/Notification";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
// Use the this atom to trigger loading data from the storage
|
||||||
|
// And render the loading indicator
|
||||||
|
useAtomValue(appDataAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box data-tauri-drag-region padding={2} paddingBottom={0}>
|
<Box data-tauri-drag-region padding={2} paddingBottom={0}>
|
||||||
<MainMenu />
|
<MainMenu />
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { emit, listen } from "@tauri-apps/api/event";
|
import { emit, listen } from "@tauri-apps/api/event";
|
||||||
import invokeCommand from "../utils/invokeCommand";
|
import invokeCommand from "../utils/invokeCommand";
|
||||||
|
import settingsService from "./settingsService";
|
||||||
|
|
||||||
export type AuthData = {
|
export type AuthData = {
|
||||||
username: string;
|
username: string;
|
||||||
@ -30,9 +31,12 @@ class AuthService {
|
|||||||
|
|
||||||
// binding: "POST" | "REDIRECT"
|
// binding: "POST" | "REDIRECT"
|
||||||
async samlLogin(binding: string, request: string, clearCookies: boolean) {
|
async samlLogin(binding: string, request: string, clearCookies: boolean) {
|
||||||
|
const { userAgent } = await settingsService.getSimulation();
|
||||||
|
|
||||||
return invokeCommand<AuthData>("saml_login", {
|
return invokeCommand<AuthData>("saml_login", {
|
||||||
binding,
|
binding,
|
||||||
request,
|
request,
|
||||||
|
userAgent: `${userAgent} ${navigator.userAgent}`,
|
||||||
clearCookies,
|
clearCookies,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Body, ResponseType, fetch } from "@tauri-apps/api/http";
|
import { Body, ResponseType, fetch } from "@tauri-apps/api/http";
|
||||||
import { parseXml } from "../utils/parseXml";
|
import { parseXml } from "../utils/parseXml";
|
||||||
|
import settingsService from "./settingsService";
|
||||||
|
|
||||||
type LoginParams = {
|
type LoginParams = {
|
||||||
user: string;
|
user: string;
|
||||||
@ -15,6 +16,9 @@ class GatewayService {
|
|||||||
throw new Error("Gateway address is required");
|
throw new Error("Gateway address is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { userAgent, clientOS, osVersion } =
|
||||||
|
await settingsService.getSimulation();
|
||||||
|
|
||||||
const loginUrl = `https://${gateway}/ssl-vpn/login.esp`;
|
const loginUrl = `https://${gateway}/ssl-vpn/login.esp`;
|
||||||
const body = Body.form({
|
const body = Body.form({
|
||||||
prot: "https:",
|
prot: "https:",
|
||||||
@ -25,8 +29,8 @@ class GatewayService {
|
|||||||
direct: "yes",
|
direct: "yes",
|
||||||
"ipv6-support": "yes",
|
"ipv6-support": "yes",
|
||||||
clientVer: "4100",
|
clientVer: "4100",
|
||||||
clientos: "Linux",
|
clientos: clientOS,
|
||||||
"os-version": "Linux",
|
"os-version": osVersion,
|
||||||
server: gateway,
|
server: gateway,
|
||||||
user,
|
user,
|
||||||
passwd: passwd || "",
|
passwd: passwd || "",
|
||||||
@ -38,7 +42,7 @@ class GatewayService {
|
|||||||
const response = await fetch<string>(loginUrl, {
|
const response = await fetch<string>(loginUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "PAN GlobalProtect",
|
"User-Agent": userAgent,
|
||||||
},
|
},
|
||||||
responseType: ResponseType.Text,
|
responseType: ResponseType.Text,
|
||||||
body,
|
body,
|
||||||
|
@ -2,6 +2,7 @@ import { Body, ResponseType, fetch } from "@tauri-apps/api/http";
|
|||||||
import ErrorWithTitle from "../utils/ErrorWithTitle";
|
import ErrorWithTitle from "../utils/ErrorWithTitle";
|
||||||
import { parseXml } from "../utils/parseXml";
|
import { parseXml } from "../utils/parseXml";
|
||||||
import { Gateway } from "./types";
|
import { Gateway } from "./types";
|
||||||
|
import settingsService from "./settingsService";
|
||||||
|
|
||||||
export type SamlPrelogin = {
|
export type SamlPrelogin = {
|
||||||
isSamlAuth: true;
|
isSamlAuth: true;
|
||||||
@ -37,12 +38,15 @@ export type PortalCredential = {
|
|||||||
class PortalService {
|
class PortalService {
|
||||||
async prelogin(portal: string): Promise<Prelogin> {
|
async prelogin(portal: string): Promise<Prelogin> {
|
||||||
const preloginUrl = `https://${portal}/global-protect/prelogin.esp`;
|
const preloginUrl = `https://${portal}/global-protect/prelogin.esp`;
|
||||||
|
const { userAgent, clientOS, osVersion } =
|
||||||
|
await settingsService.getSimulation();
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
try {
|
try {
|
||||||
response = await fetch<string>(preloginUrl, {
|
response = await fetch<string>(preloginUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "PAN GlobalProtect",
|
"User-Agent": userAgent,
|
||||||
},
|
},
|
||||||
responseType: ResponseType.Text,
|
responseType: ResponseType.Text,
|
||||||
query: {
|
query: {
|
||||||
@ -51,8 +55,8 @@ class PortalService {
|
|||||||
body: Body.form({
|
body: Body.form({
|
||||||
tmp: "tmp",
|
tmp: "tmp",
|
||||||
clientVer: "4100",
|
clientVer: "4100",
|
||||||
clientos: "Linux",
|
clientos: clientOS,
|
||||||
"os-version": "Linux",
|
"os-version": osVersion,
|
||||||
"ipv6-support": "yes",
|
"ipv6-support": "yes",
|
||||||
"default-browser": "0",
|
"default-browser": "0",
|
||||||
"cas-support": "yes",
|
"cas-support": "yes",
|
||||||
@ -118,6 +122,9 @@ class PortalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetchConfig(portal: string, params: PortalCredential) {
|
async fetchConfig(portal: string, params: PortalCredential) {
|
||||||
|
const { userAgent, clientOS, osVersion, clientVersion } =
|
||||||
|
await settingsService.getSimulation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
passwd,
|
passwd,
|
||||||
@ -132,12 +139,12 @@ class PortalService {
|
|||||||
inputStr: "",
|
inputStr: "",
|
||||||
jnlpReady: "jnlpReady",
|
jnlpReady: "jnlpReady",
|
||||||
computer: "Linux", // TODO
|
computer: "Linux", // TODO
|
||||||
clientos: "Linux",
|
clientos: clientOS,
|
||||||
ok: "Login",
|
ok: "Login",
|
||||||
direct: "yes",
|
direct: "yes",
|
||||||
clientVer: "4100",
|
clientVer: "4100",
|
||||||
"os-version": "Linux",
|
"os-version": osVersion,
|
||||||
clientgpversion: "6.0.1-19",
|
clientgpversion: clientVersion,
|
||||||
"ipv6-support": "yes",
|
"ipv6-support": "yes",
|
||||||
server: portal,
|
server: portal,
|
||||||
host: portal,
|
host: portal,
|
||||||
@ -151,7 +158,7 @@ class PortalService {
|
|||||||
const response = await fetch<string>(configUrl, {
|
const response = await fetch<string>(configUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "PAN GlobalProtect",
|
"User-Agent": userAgent,
|
||||||
},
|
},
|
||||||
responseType: ResponseType.Text,
|
responseType: ResponseType.Text,
|
||||||
body,
|
body,
|
||||||
@ -166,8 +173,6 @@ class PortalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private parsePortalConfigResponse(response: string): PortalConfig {
|
private parsePortalConfigResponse(response: string): PortalConfig {
|
||||||
// console.log(response);
|
|
||||||
|
|
||||||
const result = parseXml(response);
|
const result = parseXml(response);
|
||||||
const gateways = result.all("gateways list > entry").map((entry) => {
|
const gateways = result.all("gateways list > entry").map((entry) => {
|
||||||
const address = entry.attr("name");
|
const address = entry.attr("name");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { UserAttentionType, WebviewWindow } from "@tauri-apps/api/window";
|
import { UserAttentionType, WebviewWindow } from "@tauri-apps/api/window";
|
||||||
import invokeCommand from "../utils/invokeCommand";
|
import invokeCommand from "../utils/invokeCommand";
|
||||||
import { appStore } from "./storeService";
|
import { appStorage } from "./storageService";
|
||||||
|
|
||||||
export type TabValue = "simulation" | "openssl";
|
export type TabValue = "simulation" | "openssl";
|
||||||
const SETTINGS_WINDOW_LABEL = "settings";
|
const SETTINGS_WINDOW_LABEL = "settings";
|
||||||
@ -68,9 +68,10 @@ export const DEFAULT_SETTINGS_DATA: SettingsData = {
|
|||||||
customOpenSSL: false,
|
customOpenSSL: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getSimulationSettings(): Promise<SimulationSettings> {
|
async function getSimulation(): Promise<SimulationSettings> {
|
||||||
const { clientOS, osVersion, clientVersion } =
|
const { clientOS, osVersion, clientVersion } =
|
||||||
(await appStore.get<SettingsData>(SETTINGS_DATA)) || DEFAULT_SETTINGS_DATA;
|
(await appStorage.get<SettingsData>(SETTINGS_DATA)) ||
|
||||||
|
DEFAULT_SETTINGS_DATA;
|
||||||
const currentOsVersion = await getCurrentOsVersion();
|
const currentOsVersion = await getCurrentOsVersion();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -81,8 +82,8 @@ async function getSimulationSettings(): Promise<SimulationSettings> {
|
|||||||
clientVersion
|
clientVersion
|
||||||
),
|
),
|
||||||
clientOS,
|
clientOS,
|
||||||
osVersion,
|
osVersion: determineOsVersion(clientOS, osVersion, currentOsVersion),
|
||||||
clientVersion,
|
clientVersion: clientVersion || DEFAULT_CLIENT_VERSION,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ export default {
|
|||||||
openSettings,
|
openSettings,
|
||||||
closeSettings,
|
closeSettings,
|
||||||
getCurrentOsVersion,
|
getCurrentOsVersion,
|
||||||
getSimulationSettings,
|
getSimulation,
|
||||||
buildUserAgent,
|
buildUserAgent,
|
||||||
determineOsVersion,
|
determineOsVersion,
|
||||||
getOpenSSLConfig,
|
getOpenSSLConfig,
|
||||||
|
70
gpgui/src/services/storageService.ts
Normal file
70
gpgui/src/services/storageService.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { atom } from "jotai";
|
||||||
|
import { RESET, atomWithDefault } from "jotai/utils";
|
||||||
|
import invokeCommand from "../utils/invokeCommand";
|
||||||
|
|
||||||
|
type SetStateActionWithReset<T> =
|
||||||
|
| T
|
||||||
|
| typeof RESET
|
||||||
|
| ((prev: T) => T | typeof RESET);
|
||||||
|
|
||||||
|
type KeyHint =
|
||||||
|
| {
|
||||||
|
key: string;
|
||||||
|
encrypted: boolean;
|
||||||
|
}
|
||||||
|
| string;
|
||||||
|
|
||||||
|
type AppStorage = {
|
||||||
|
get: <T>(key: KeyHint) => Promise<T | undefined>;
|
||||||
|
set: <T>(key: KeyHint, value: T) => Promise<void>;
|
||||||
|
save: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const appStorage: AppStorage = {
|
||||||
|
get: async (key) => {
|
||||||
|
const hint = typeof key === "string" ? { key, encrypted: false } : key;
|
||||||
|
return invokeCommand("store_get", { hint });
|
||||||
|
},
|
||||||
|
set: async (key, value) => {
|
||||||
|
const hint = typeof key === "string" ? { key, encrypted: false } : key;
|
||||||
|
return invokeCommand("store_set", { hint, value });
|
||||||
|
},
|
||||||
|
save: async () => {
|
||||||
|
return invokeCommand("store_save");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export function atomWithTauriStorage<T>(key: KeyHint, initialValue: T) {
|
||||||
|
const baseAtom = atomWithDefault<T | Promise<T>>(async () => {
|
||||||
|
const storedValue = await appStorage.get<T>(key);
|
||||||
|
if (!storedValue) {
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
return storedValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
const anAtom = atom(
|
||||||
|
(get) => get(baseAtom),
|
||||||
|
async (get, set, update: SetStateActionWithReset<T>) => {
|
||||||
|
const value = await get(baseAtom);
|
||||||
|
let newValue: T | typeof RESET;
|
||||||
|
if (typeof update === "function") {
|
||||||
|
newValue = (update as (prev: T) => T | typeof RESET)(value);
|
||||||
|
} else {
|
||||||
|
newValue = update as T | typeof RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue === RESET) {
|
||||||
|
set(baseAtom, initialValue);
|
||||||
|
await appStorage.set(key, initialValue);
|
||||||
|
} else {
|
||||||
|
set(baseAtom, newValue);
|
||||||
|
await appStorage.set(key, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
await appStorage.save();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return anAtom;
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
import { atom } from "jotai";
|
|
||||||
import { RESET, atomWithDefault } from "jotai/utils";
|
|
||||||
import { Store } from "tauri-plugin-store-api";
|
|
||||||
|
|
||||||
type SetStateActionWithReset<T> =
|
|
||||||
| T
|
|
||||||
| typeof RESET
|
|
||||||
| ((prev: T) => T | typeof RESET);
|
|
||||||
|
|
||||||
export const appStore = new Store(".settings.dat");
|
|
||||||
|
|
||||||
export function atomWithTauriStorage<T>(key: string, initialValue: T) {
|
|
||||||
const baseAtom = atomWithDefault<T | Promise<T>>(async () => {
|
|
||||||
const storedValue = await appStore.get<T>(key);
|
|
||||||
if (!storedValue) {
|
|
||||||
return initialValue;
|
|
||||||
}
|
|
||||||
return storedValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
const anAtom = atom(
|
|
||||||
(get) => get(baseAtom),
|
|
||||||
async (get, set, update: SetStateActionWithReset<T>) => {
|
|
||||||
const value = await get(baseAtom);
|
|
||||||
let newValue: T | typeof RESET;
|
|
||||||
if (typeof update === "function") {
|
|
||||||
newValue = (update as (prev: T) => T | typeof RESET)(value);
|
|
||||||
} else {
|
|
||||||
newValue = update as T | typeof RESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newValue === RESET) {
|
|
||||||
set(baseAtom, initialValue);
|
|
||||||
await appStore.set(key, initialValue);
|
|
||||||
} else {
|
|
||||||
set(baseAtom, newValue);
|
|
||||||
await appStore.set(key, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
await appStore.save();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return anAtom;
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
import { Event, listen } from "@tauri-apps/api/event";
|
import { Event, listen } from "@tauri-apps/api/event";
|
||||||
import invokeCommand from "../utils/invokeCommand";
|
import invokeCommand from "../utils/invokeCommand";
|
||||||
|
import settingsService from "./settingsService";
|
||||||
|
|
||||||
type VpnStatus = "disconnected" | "connecting" | "connected" | "disconnecting";
|
type VpnStatus = "disconnected" | "connecting" | "connected" | "disconnecting";
|
||||||
type VpnStatusCallback = (status: VpnStatus) => void;
|
type VpnStatusCallback = (status: VpnStatus) => void;
|
||||||
@ -64,7 +65,8 @@ class VpnService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async connect(server: string, cookie: string) {
|
async connect(server: string, cookie: string) {
|
||||||
return invokeCommand("vpn_connect", { server, cookie });
|
const { userAgent } = await settingsService.getSimulation();
|
||||||
|
return invokeCommand("vpn_connect", { server, cookie, userAgent });
|
||||||
}
|
}
|
||||||
|
|
||||||
async disconnect() {
|
async disconnect() {
|
||||||
|
@ -8,8 +8,9 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
gpcommon = { path = "../gpcommon" }
|
gpcommon = { path = "../gpcommon" }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
env_logger = "0.10"
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
fern = "0.6"
|
||||||
|
humantime = "2.1"
|
||||||
# warp = "0.3"
|
# warp = "0.3"
|
||||||
# aes-gcm = "0.10"
|
# aes-gcm = "0.10"
|
||||||
# procfs = "0.15"
|
# procfs = "0.15"
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
include!(concat!(env!("OUT_DIR"), "/client_hash.rs"));
|
include!(concat!(env!("OUT_DIR"), "/client_hash.rs"));
|
||||||
|
|
||||||
// use aes_gcm::{aead::OsRng, Aes256Gcm, KeyInit};
|
|
||||||
use gpcommon::{server, SOCKET_PATH};
|
use gpcommon::{server, SOCKET_PATH};
|
||||||
use env_logger::Env;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use std::fs::File;
|
||||||
use tokio::signal;
|
use tokio::signal;
|
||||||
|
|
||||||
// static mut HTTP_PORT: u16 = 0;
|
// static mut HTTP_PORT: u16 = 0;
|
||||||
@ -96,10 +95,10 @@ use tokio::signal;
|
|||||||
// println!("Shutting down http server");
|
// println!("Shutting down http server");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
const LOG_FILE: &str = "/var/log/gpservice.log";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
|
||||||
|
|
||||||
// println!("{GPCLIENT_HASH}");
|
// println!("{GPCLIENT_HASH}");
|
||||||
|
|
||||||
// unsafe {
|
// unsafe {
|
||||||
@ -110,6 +109,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
// start_http_server().await;
|
// start_http_server().await;
|
||||||
// server::start().await
|
// server::start().await
|
||||||
|
|
||||||
|
let log_file = File::create(LOG_FILE)?;
|
||||||
|
fern::Dispatch::new()
|
||||||
|
.format(|out, message, record| {
|
||||||
|
out.finish(format_args!(
|
||||||
|
"[{} {} {}] {}",
|
||||||
|
humantime::format_rfc3339_millis(std::time::SystemTime::now()),
|
||||||
|
record.level(),
|
||||||
|
record.target(),
|
||||||
|
message
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.level(log::LevelFilter::Info)
|
||||||
|
.chain(std::io::stdout())
|
||||||
|
.chain(log_file)
|
||||||
|
.apply()?;
|
||||||
|
|
||||||
if let Err(err) = server::run(SOCKET_PATH, signal::ctrl_c()).await {
|
if let Err(err) = server::run(SOCKET_PATH, signal::ctrl_c()).await {
|
||||||
error!("Error running server: {}", err);
|
error!("Error running server: {}", err);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user