diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9a9b5b2..ebfc124 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1 @@ -* @conradev @malted @JettChenT @jdogcoder -burrow/ @conradev @malted @JettChenT @jdogcoder @Muirrum -tun/ @conradev @malted @JettChenT @jdogcoder @Muirrum -burrow-gtk/ @conradev @malted @JettChenT @jdogcoder @davnotdev +* @conradev @ma1ted @Muirrum \ No newline at end of file diff --git a/.github/actions/build-for-testing/action.yml b/.github/actions/build-for-testing/action.yml index ce91b43..fb5dd8d 100644 --- a/.github/actions/build-for-testing/action.yml +++ b/.github/actions/build-for-testing/action.yml @@ -43,7 +43,6 @@ runs: -clonedSourcePackagesDirPath SourcePackages \ -packageCachePath $PWD/PackageCache \ -skipPackagePluginValidation \ - -skipMacroValidation \ -scheme '${{ inputs.scheme }}' \ -destination '${{ inputs.destination }}' \ -resultBundlePath BuildResults.xcresult diff --git a/.github/workflows/build-apple.yml b/.github/workflows/build-apple.yml index da0f56a..1aadcc2 100644 --- a/.github/workflows/build-apple.yml +++ b/.github/workflows/build-apple.yml @@ -6,13 +6,10 @@ on: pull_request: branches: - "*" -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true jobs: build: name: Build App (${{ matrix.platform }}) - runs-on: macos-13 + runs-on: macos-12 strategy: fail-fast: false matrix: @@ -24,7 +21,7 @@ jobs: rust-targets: - aarch64-apple-ios - scheme: App - destination: platform=iOS Simulator,OS=17.2,name=iPhone 15 Pro + destination: platform=iOS Simulator,OS=16.2,name=iPhone 14 Pro platform: iOS Simulator sdk-name: iphonesimulator rust-targets: @@ -38,7 +35,7 @@ jobs: - x86_64-apple-darwin - aarch64-apple-darwin env: - DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.github/workflows/build-flatpak.yml b/.github/workflows/build-flatpak.yml index e0e804e..8a70613 100644 --- a/.github/workflows/build-flatpak.yml +++ b/.github/workflows/build-flatpak.yml @@ -15,5 +15,5 @@ jobs: - uses: flatpak/flatpak-github-actions/flatpak-builder@v6 with: bundle: Burrow.flatpak - manifest-path: burrow-gtk/build-aux/com.hackclub.burrow.devel.json + manifest-path: burrow-gtk/com.hackclub.burrow.devel.json cache-key: flatpak-builder-${{ github.sha }} diff --git a/.github/workflows/build-rust.yml b/.github/workflows/build-rust.yml index 4c3782a..0993ec2 100644 --- a/.github/workflows/build-rust.yml +++ b/.github/workflows/build-rust.yml @@ -54,10 +54,6 @@ jobs: run: | sudo apt-get update sudo apt-get install -y ${{ join(matrix.packages, ' ') }} - - name: Install Windows Deps - if: matrix.os == 'windows-2022' - shell: bash - run: echo "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin" >> $GITHUB_PATH - name: Install Rust uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/release-apple.yml b/.github/workflows/release-apple.yml index 3ea185d..8b8a76c 100644 --- a/.github/workflows/release-apple.yml +++ b/.github/workflows/release-apple.yml @@ -6,7 +6,7 @@ on: jobs: build: name: Build ${{ matrix.configuration['platform'] }} Release - runs-on: macos-13 + runs-on: macos-12 strategy: fail-fast: false matrix: @@ -22,7 +22,7 @@ jobs: method: mac-application artifact-file: Burrow.app.txz env: - DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer + DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer steps: - name: Checkout uses: actions/checkout@v3 diff --git a/.rustfmt.toml b/.rustfmt.toml deleted file mode 100644 index 2a12e19..0000000 --- a/.rustfmt.toml +++ /dev/null @@ -1,12 +0,0 @@ -condense_wildcard_suffixes = true -format_macro_matchers = true -imports_layout = "HorizontalVertical" -imports_granularity = "Crate" -newline_style = "Unix" -overflow_delimited_expr = true -reorder_impl_items = true -group_imports = "StdExternalCrate" -trailing_semicolon = false -use_field_init_shorthand = true -use_try_shorthand = true -struct_lit_width = 30 diff --git a/.vscode/settings.json b/.vscode/settings.json index 5fbfc5c..4718093 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,9 +8,6 @@ "editor.acceptSuggestionOnEnter": "on", "rust-analyzer.restartServerOnConfigChange": true, "rust-analyzer.cargo.features": "all", - "rust-analyzer.rustfmt.extraArgs": [ - "+nightly" - ], "[rust]": { "editor.defaultFormatter": "rust-lang.rust-analyzer", } diff --git a/Apple/App/BurrowApp.swift b/Apple/App/BurrowApp.swift index e8aed86..6d798fb 100644 --- a/Apple/App/BurrowApp.swift +++ b/Apple/App/BurrowApp.swift @@ -15,7 +15,7 @@ struct BurrowApp: App { var body: some Scene { WindowGroup { - TunnelView(tunnel: Self.tunnel) + TunnelView() } } } diff --git a/Apple/App/Menu/MenuView.swift b/Apple/App/Menu/MenuView.swift index 56a7494..9d8fb31 100644 --- a/Apple/App/Menu/MenuView.swift +++ b/Apple/App/Menu/MenuView.swift @@ -8,7 +8,7 @@ import SwiftUI struct MenuItemToggleView: View { - var tunnel: Tunnel + @ObservedObject var tunnel: Tunnel var body: some View { HStack { @@ -23,6 +23,7 @@ struct MenuItemToggleView: View { .padding(.horizontal, 4) .padding(10) .frame(minWidth: 300, minHeight: 32, maxHeight: 32) + .task { await tunnel.update() } } } diff --git a/Apple/App/NetworkExtension+Async.swift b/Apple/App/NetworkExtension+Async.swift index 4833efb..ba478f3 100644 --- a/Apple/App/NetworkExtension+Async.swift +++ b/Apple/App/NetworkExtension+Async.swift @@ -2,13 +2,13 @@ import NetworkExtension extension NEVPNManager { func remove() async throws { - _ = try await withUnsafeThrowingContinuation { continuation in + let _: Void = try await withUnsafeThrowingContinuation { continuation in removeFromPreferences(completionHandler: completion(continuation)) } } func save() async throws { - _ = try await withUnsafeThrowingContinuation { continuation in + let _: Void = try await withUnsafeThrowingContinuation { continuation in saveToPreferences(completionHandler: completion(continuation)) } } @@ -18,7 +18,13 @@ extension NETunnelProviderManager { class var managers: [NETunnelProviderManager] { get async throws { try await withUnsafeThrowingContinuation { continuation in - loadAllFromPreferences(completionHandler: completion(continuation)) + loadAllFromPreferences { managers, error in + if let error = error { + continuation.resume(throwing: error) + } else { + continuation.resume(returning: managers ?? []) + } + } } } } @@ -26,20 +32,10 @@ extension NETunnelProviderManager { private func completion(_ continuation: UnsafeContinuation) -> (Error?) -> Void { return { error in - if let error { + if let error = error { continuation.resume(throwing: error) } else { continuation.resume(returning: ()) } } } - -private func completion(_ continuation: UnsafeContinuation) -> (T?, Error?) -> Void { - return { value, error in - if let error { - continuation.resume(throwing: error) - } else if let value { - continuation.resume(returning: value) - } - } -} diff --git a/Apple/App/Tunnel.swift b/Apple/App/Tunnel.swift index 0421a0c..e8bff22 100644 --- a/Apple/App/Tunnel.swift +++ b/Apple/App/Tunnel.swift @@ -2,16 +2,15 @@ import Combine import NetworkExtension import SwiftUI -@Observable class Tunnel { - private(set) var status: Status = .unknown - private var error: NEVPNError? +@MainActor +class Tunnel: ObservableObject { + @Published private(set) var status: Status = .unknown + @Published private var error: NEVPNError? private let bundleIdentifier: String private let configure: (NETunnelProviderManager, NETunnelProviderProtocol) -> Void private var tasks: [Task] = [] - // Each manager corresponds to one entry in the Settings app. - // Our goal is to maintain a single manager, so we create one if none exist and delete extra if there are any. private var managers: [NEVPNManager]? { didSet { status = currentStatus } } @@ -49,31 +48,24 @@ import SwiftUI self.bundleIdentifier = bundleIdentifier self.configure = configure - listenForUpdates() - Task { await update() } - } - - private func listenForUpdates() { - let center = NotificationCenter.default let statusTask = Task { - for try await _ in center.notifications(named: .NEVPNStatusDidChange).map({ _ in () }) { + for try await _ in NotificationCenter.default.notifications(named: .NEVPNStatusDidChange) { status = currentStatus } } let configurationTask = Task { - for try await _ in center.notifications(named: .NEVPNConfigurationChange).map({ _ in () }) { + for try await _ in NotificationCenter.default.notifications(named: .NEVPNConfigurationChange) { await update() } } tasks = [statusTask, configurationTask] } - private func update() async { + func update() async { do { - let updated = try await NETunnelProviderManager.managers - await MainActor.run { managers = updated } - } catch let vpnError as NEVPNError { - error = vpnError + managers = try await NETunnelProviderManager.managers + } catch let error as NEVPNError { + self.error = error } catch { print(error) } @@ -117,9 +109,7 @@ import SwiftUI } deinit { - for task in tasks { - task.cancel() - } + tasks.forEach { $0.cancel() } } } diff --git a/Apple/App/TunnelView.swift b/Apple/App/TunnelView.swift index dd91603..e3b9e28 100644 --- a/Apple/App/TunnelView.swift +++ b/Apple/App/TunnelView.swift @@ -1,34 +1,36 @@ import SwiftUI struct TunnelView: View { - var tunnel: Tunnel +// @ObservedObject var tunnel: Tunnel var body: some View { - VStack { - Text(verbatim: tunnel.status.description) - switch tunnel.status { - case .connected: - Button("Disconnect", action: stop) - case .permissionRequired: - Button("Allow", action: configure) - case .disconnected: - Button("Start", action: start) - default: - EmptyView() - } - } - .padding() + EmptyView() +// VStack { +// Text(verbatim: tunnel.status.description) +// switch tunnel.status { +// case .connected: +// Button("Disconnect", action: stop) +// case .permissionRequired: +// Button("Allow", action: configure) +// case .disconnected: +// Button("Start", action: start) +// default: +// EmptyView() +// } +// } +// .task { await tunnel.update() } +// .padding() } - private func start() { - try? tunnel.start() - } - - private func stop() { - tunnel.stop() - } - - private func configure() { - Task { try await tunnel.configure() } - } +// private func start() { +// try? tunnel.start() +// } +// +// private func stop() { +// tunnel.stop() +// } +// +// private func configure() { +// Task { try await tunnel.configure() } +// } } diff --git a/Apple/Burrow.xcodeproj/project.pbxproj b/Apple/Burrow.xcodeproj/project.pbxproj index c0e4f09..7548f3e 100644 --- a/Apple/Burrow.xcodeproj/project.pbxproj +++ b/Apple/Burrow.xcodeproj/project.pbxproj @@ -196,7 +196,7 @@ buildRules = ( ); dependencies = ( - D08252712B5C3E2E005DA378 /* PBXTargetDependency */, + D0BCC6122A0B328800AD070D /* PBXTargetDependency */, ); name = NetworkExtension; productName = BurrowNetworkExtension; @@ -215,7 +215,7 @@ buildRules = ( ); dependencies = ( - D08252732B5C3E33005DA378 /* PBXTargetDependency */, + D0BCC6142A0B329200AD070D /* PBXTargetDependency */, D020F65C29E4A697002790F6 /* PBXTargetDependency */, ); name = App; @@ -231,7 +231,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1430; - LastUpgradeCheck = 1510; + LastUpgradeCheck = 1430; TargetAttributes = { D020F65229E4A697002790F6 = { CreatedOnToolsVersion = 14.3; @@ -251,7 +251,7 @@ ); mainGroup = D05B9F6929E39EEC008CB1F9; packageReferences = ( - D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */, + D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */, ); productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */; projectDirPath = ""; @@ -338,13 +338,13 @@ target = D020F65229E4A697002790F6 /* NetworkExtension */; targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */; }; - D08252712B5C3E2E005DA378 /* PBXTargetDependency */ = { + D0BCC6122A0B328800AD070D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - productRef = D08252702B5C3E2E005DA378 /* SwiftLintPlugin */; + productRef = D0BCC6112A0B328800AD070D /* SwiftLintPlugin */; }; - D08252732B5C3E33005DA378 /* PBXTargetDependency */ = { + D0BCC6142A0B329200AD070D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - productRef = D08252722B5C3E33005DA378 /* SwiftLintPlugin */; + productRef = D0BCC6132A0B329200AD070D /* SwiftLintPlugin */; }; /* End PBXTargetDependency section */ @@ -424,25 +424,25 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */ = { + D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/realm/SwiftLint.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 0.54.0; + minimumVersion = 0.51.0; }; }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - D08252702B5C3E2E005DA378 /* SwiftLintPlugin */ = { + D0BCC6112A0B328800AD070D /* SwiftLintPlugin */ = { isa = XCSwiftPackageProductDependency; - package = D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */; + package = D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */; productName = "plugin:SwiftLintPlugin"; }; - D08252722B5C3E33005DA378 /* SwiftLintPlugin */ = { + D0BCC6132A0B329200AD070D /* SwiftLintPlugin */ = { isa = XCSwiftPackageProductDependency; - package = D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */; + package = D0BCC6102A0B327700AD070D /* XCRemoteSwiftPackageReference "SwiftLint" */; productName = "plugin:SwiftLintPlugin"; }; /* End XCSwiftPackageProductDependency section */ diff --git a/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7522840..233bbf9 100644 --- a/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Apple/Burrow.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -9,15 +9,6 @@ "version" : "0.2.0" } }, - { - "identity" : "cryptoswift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", - "state" : { - "revision" : "7892a123f7e8d0fe62f9f03728b17bbd4f94df5c", - "version" : "1.8.1" - } - }, { "identity" : "sourcekitten", "kind" : "remoteSourceControl", @@ -41,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", - "version" : "509.0.2" + "revision" : "013a48e2312e57b7b355db25bd3ea75282ebf274", + "version" : "0.50900.0-swift-DEVELOPMENT-SNAPSHOT-2023-02-06-a" } }, { @@ -50,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/realm/SwiftLint.git", "state" : { - "revision" : "f17a4f9dfb6a6afb0408426354e4180daaf49cee", - "version" : "0.54.0" + "revision" : "eb85125a5f293de3d3248af259980c98bc2b1faa", + "version" : "0.51.0" } }, { @@ -77,8 +68,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/jpsim/Yams.git", "state" : { - "revision" : "0d9ee7ea8c4ebd4a489ad7a73d5c6cad55d6fed3", - "version" : "5.0.6" + "revision" : "f47ba4838c30dbd59998a4e4c87ab620ff959e8a", + "version" : "5.0.5" } } ], diff --git a/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme index c63f8e6..7bb7808 100644 --- a/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/Apple/Burrow.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -1,6 +1,6 @@ (_ request: any Request, type: U.Type) async throws -> U { + func request(_ request: Request, type: U.Type) async throws -> U { do { var data: Data = try JSONEncoder().encode(request) data.append(contentsOf: [10]) diff --git a/Apple/NetworkExtension/DataTypes.swift b/Apple/NetworkExtension/DataTypes.swift index 5d73805..b228d77 100644 --- a/Apple/NetworkExtension/DataTypes.swift +++ b/Apple/NetworkExtension/DataTypes.swift @@ -1,6 +1,5 @@ import Foundation -// swiftlint:disable identifier_name enum BurrowError: Error { case addrDoesntExist case resultIsError @@ -8,48 +7,22 @@ enum BurrowError: Error { case resultIsNone } -protocol Request: Codable where CommandT: Codable { - associatedtype CommandT +protocol Request: Codable { var id: UInt { get set } - var command: CommandT { get set } + var command: String { get set } } -struct BurrowSingleCommand: Request { +struct BurrowRequest: Request { var id: UInt var command: String } -struct BurrowRequest: Request where T: Codable { - var id: UInt - var command: T -} - -struct BurrowStartRequest: Codable { - struct TunOptions: Codable { - let name: String? - let no_pi: Bool - let tun_excl: Bool - let tun_retrieve: Bool - let address: String? - } - struct StartOptions: Codable { - let tun: TunOptions - } - let Start: StartOptions -} - -func start_req_fd(id: UInt) -> BurrowRequest { - let command = BurrowStartRequest(Start: BurrowStartRequest.StartOptions( - tun: BurrowStartRequest.TunOptions(name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil) - )) - return BurrowRequest(id: id, command: command) -} - struct Response: Decodable where T: Decodable { var id: UInt var result: T } +// swiftlint:disable identifier_name struct BurrowResult: Codable where T: Codable { var Ok: T? var Err: String? diff --git a/Apple/NetworkExtension/NetworkExtension-macOS.entitlements b/Apple/NetworkExtension/NetworkExtension-macOS.entitlements index edb3f26..c3d6dc2 100644 --- a/Apple/NetworkExtension/NetworkExtension-macOS.entitlements +++ b/Apple/NetworkExtension/NetworkExtension-macOS.entitlements @@ -4,8 +4,6 @@ com.apple.security.network.client - com.apple.security.network.server - com.apple.developer.networking.networkextension packet-tunnel-provider diff --git a/Apple/NetworkExtension/PacketTunnelProvider.swift b/Apple/NetworkExtension/PacketTunnelProvider.swift index 19fa760..4b72115 100644 --- a/Apple/NetworkExtension/PacketTunnelProvider.swift +++ b/Apple/NetworkExtension/PacketTunnelProvider.swift @@ -6,7 +6,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { let logger = Logger(subsystem: "com.hackclub.burrow", category: "frontend") var client: BurrowIpc? var osInitialized = false - override func startTunnel(options: [String: NSObject]? = nil) async throws { + override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { logger.log("Starting tunnel") if !osInitialized { libburrow.initialize_oslog() @@ -15,35 +15,28 @@ class PacketTunnelProvider: NEPacketTunnelProvider { libburrow.start_srv() client = BurrowIpc(logger: logger) logger.info("Started server") - do { - let command = BurrowSingleCommand(id: 0, command: "ServerConfig") - guard let data = try await client?.request(command, type: Response>.self) - else { - throw BurrowError.cantParseResult + Task { + do { + let command = BurrowRequest(id: 0, command: "ServerConfig") + guard let data = try await client?.request(command, type: Response>.self) + else { + throw BurrowError.cantParseResult + } + let encoded = try JSONEncoder().encode(data.result) + self.logger.log("Received final data: \(String(decoding: encoded, as: UTF8.self))") + guard let serverconfig = data.result.Ok else { + throw BurrowError.resultIsError + } + guard let tunNs = self.generateTunSettings(from: serverconfig) else { + throw BurrowError.addrDoesntExist + } + try await self.setTunnelNetworkSettings(tunNs) + self.logger.info("Set remote tunnel address to \(tunNs.tunnelRemoteAddress)") + completionHandler(nil) + } catch { + self.logger.error("An error occurred: \(error)") + completionHandler(error) } - let encoded = try JSONEncoder().encode(data.result) - self.logger.log("Received final data: \(String(decoding: encoded, as: UTF8.self))") - guard let serverconfig = data.result.Ok else { - throw BurrowError.resultIsError - } - guard let tunNs = self.generateTunSettings(from: serverconfig) else { - throw BurrowError.addrDoesntExist - } - try await self.setTunnelNetworkSettings(tunNs) - self.logger.info("Set remote tunnel address to \(tunNs.tunnelRemoteAddress)") - - // let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int; - // self.logger.info("Found File Descriptor: \(tunFd)") - let startCommand = start_req_fd(id: 1) - guard let data = try await client?.request(startCommand, type: Response>.self) - else { - throw BurrowError.cantParseResult - } - let encodedStartRes = try JSONEncoder().encode(data.result) - self.logger.log("Received start server response: \(String(decoding: encodedStartRes, as: UTF8.self))") - } catch { - self.logger.error("An error occurred: \(error)") - throw error } } private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? { @@ -57,12 +50,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider { logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)") return nst } - override func stopTunnel(with reason: NEProviderStopReason) async { + override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + completionHandler() } - override func handleAppMessage(_ messageData: Data) async -> Data? { - messageData + override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { + if let handler = completionHandler { + handler(messageData) + } } - override func sleep() async { + override func sleep(completionHandler: @escaping () -> Void) { + completionHandler() } override func wake() { } diff --git a/Cargo.lock b/Cargo.lock index cc8d3b3..6716320 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,16 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" 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.8.3" @@ -49,16 +39,15 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -88,9 +77,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -102,23 +91,15 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - [[package]] name = "async-channel" -version = "2.1.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", - "event-listener-strategy", "futures-core", - "pin-project-lite", ] [[package]] @@ -144,9 +125,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.5" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" @@ -195,7 +176,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.39", + "syn 2.0.22", "which", ] @@ -211,15 +192,6 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -239,30 +211,15 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" name = "burrow" version = "0.1.0" dependencies = [ - "aead", "anyhow", "async-channel", - "base64", - "blake2", "caps", - "chacha20poly1305", "clap", "env_logger", - "etherparse", - "fehler", - "futures", - "hmac", "insta", - "ip_network", - "ip_network_table", - "ipnet", "libsystemd", "log", "nix", - "parking_lot", - "rand", - "rand_core", - "ring", "schemars", "serde", "serde_json", @@ -273,8 +230,6 @@ dependencies = [ "tracing-oslog", "tracing-subscriber", "tun", - "uuid", - "x25519-dalek", ] [[package]] @@ -322,12 +277,11 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", - "libc", ] [[package]] @@ -345,30 +299,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - [[package]] name = "cipher" version = "0.4.4" @@ -377,7 +307,6 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", - "zeroize", ] [[package]] @@ -393,20 +322,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.10" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" +checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.10" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" +checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" dependencies = [ "anstream", "anstyle", @@ -416,14 +344,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -440,9 +368,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" dependencies = [ "crossbeam-utils", ] @@ -515,37 +443,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core", "typenum", ] -[[package]] -name = "curve25519-dalek" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "platforms", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "digest" version = "0.10.7" @@ -559,9 +459,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" [[package]] name = "either" @@ -618,35 +518,11 @@ dependencies = [ "libc", ] -[[package]] -name = "etherparse" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcb08c4aab4e2985045305551e67126b43f1b6b136bc4e1cd87fb0327877a611" -dependencies = [ - "arrayvec", -] - [[package]] name = "event-listener" -version = "4.0.0" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener", - "pin-project-lite", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" @@ -677,12 +553,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "fiat-crypto" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a481586acf778f1b1455424c343f71124b048ffa5f4fc3f8f6ae9dc432dcb3c7" - [[package]] name = "flate2" version = "1.0.26" @@ -779,7 +649,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -822,17 +692,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "gimli" version = "0.27.3" @@ -1005,9 +864,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.34.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +checksum = "a3e02c584f4595792d09509a94cdb92a3cef7592b1eb2d9877ee6f527062d0ea" dependencies = [ "console", "lazy_static", @@ -1037,36 +896,11 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ip_network" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" - -[[package]] -name = "ip_network_table" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" -dependencies = [ - "ip_network", - "ip_network_table-deps-treebitmap", -] - -[[package]] -name = "ip_network_table-deps-treebitmap" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" - [[package]] name = "ipnet" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" -dependencies = [ - "serde", -] [[package]] name = "is-terminal" @@ -1117,9 +951,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -1227,7 +1061,7 @@ checksum = "4901771e1d44ddb37964565c654a3223ba41a594d02b8da471cc4464912b5cfa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -1339,12 +1173,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "openssl" version = "0.10.55" @@ -1368,7 +1196,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -1395,12 +1223,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1461,9 +1283,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1477,29 +1299,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "prettyplease" version = "0.2.9" @@ -1507,56 +1306,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] [[package]] name = "redox_syscall" @@ -1636,20 +1411,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.48.0", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1662,15 +1423,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "0.37.21" @@ -1766,12 +1518,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" - [[package]] name = "serde" version = "1.0.164" @@ -1789,7 +1535,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -1876,9 +1622,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "similar" -version = "2.3.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "slab" @@ -1905,12 +1651,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "ssri" version = "9.0.0" @@ -1958,9 +1698,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" dependencies = [ "proc-macro2", "quote", @@ -2007,7 +1747,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -2077,7 +1817,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -2130,7 +1870,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", ] [[package]] @@ -2264,22 +2004,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[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]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" version = "2.4.0" @@ -2299,11 +2023,10 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.6.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" dependencies = [ - "getrandom", "serde", ] @@ -2361,7 +2084,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", "wasm-bindgen-shared", ] @@ -2395,7 +2118,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.22", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2629,18 +2352,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "x25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", -] - [[package]] name = "xxhash-rust" version = "0.8.6" @@ -2656,26 +2367,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 44981a2..7a17276 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,3 @@ [workspace] members = ["burrow", "tun"] -resolver = "2" exclude = ["burrow-gtk"] diff --git a/Makefile b/Makefile deleted file mode 100644 index e8e5687..0000000 --- a/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -tun_num := $(shell ifconfig | awk -F 'utun|[: ]' '/utun[0-9]/ {print $$2}' | tail -n 1) - -check: - @cargo check - -build: - @cargo run build - -daemon: - @RUST_BACKTRACE=1 RUST_LOG=debug cargo run daemon - -start: - @RUST_BACKTRACE=1 RUST_LOG=debug cargo run start - -test-dns: - @sudo route delete 8.8.8.8 - @sudo route add 8.8.8.8 -interface utun$(tun_num) - @dig @8.8.8.8 hackclub.com - -test-https: - @sudo route delete 193.183.0.162 - @sudo route add 193.183.0.162 -interface utun$(tun_num) - @curl -vv https://search.marginalia.nu - -test-http: - @sudo route delete 146.190.62.39 - @sudo route add 146.190.62.39 -interface utun$(tun_num) - @curl -vv 146.190.62.39:80 diff --git a/burrow-gtk/Cargo.lock b/burrow-gtk/Cargo.lock index d0b7009..59c05cc 100644 --- a/burrow-gtk/Cargo.lock +++ b/burrow-gtk/Cargo.lock @@ -17,16 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" 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.8.3" @@ -49,9 +39,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -69,60 +59,58 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "async-channel" -version = "2.1.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", - "event-listener-strategy", "futures-core", - "pin-project-lite", ] [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -148,9 +136,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.7" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -199,7 +187,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.48", + "syn 2.0.39", "which", ] @@ -211,18 +199,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block" @@ -249,40 +228,24 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" name = "burrow" version = "0.1.0" dependencies = [ - "aead", "anyhow", "async-channel", - "base64", - "blake2", "caps", - "chacha20poly1305", "clap", "env_logger", - "fehler", - "futures", - "hmac", - "ip_network", - "ip_network_table", - "ipnet", "libsystemd", "log", "nix", - "parking_lot", - "rand", - "rand_core", - "ring", "schemars", "serde", "serde_json", "tokio", "tracing", "tracing-journald", - "tracing-log 0.1.4", + "tracing-log", "tracing-oslog", "tracing-subscriber", "tun", - "uuid", - "x25519-dalek", ] [[package]] @@ -332,11 +295,11 @@ dependencies = [ [[package]] name = "cairo-rs" -version = "0.18.5" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +checksum = "f33613627f0dea6a731b0605101fad59ba4f193a52c96c4687728d822605a8a1" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.1", "cairo-sys-rs", "glib", "libc", @@ -386,9 +349,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.6" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6100bc57b6209840798d95cb2775684849d332f7bd788db2a8c8caf7ef82a41a" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", "target-lexicon", @@ -400,30 +363,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - [[package]] name = "cipher" version = "0.4.4" @@ -432,25 +371,24 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", - "zeroize", ] [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", - "libloading 0.8.1", + "libloading", ] [[package]] name = "clap" -version = "4.4.18" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -458,9 +396,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -477,7 +415,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -494,9 +432,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -509,9 +447,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -519,15 +457,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -543,9 +481,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] [[package]] name = "crypto-common" @@ -554,42 +495,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core", "typenum", ] -[[package]] -name = "curve25519-dalek" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "platforms", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "deranged" -version = "0.3.11" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" dependencies = [ "powerfmt", ] @@ -628,9 +541,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.2" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -647,34 +560,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "event-listener" -version = "4.0.3" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener", - "pin-project-lite", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" @@ -702,12 +600,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "fiat-crypto" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" - [[package]] name = "field-offset" version = "0.3.6" @@ -763,9 +655,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -778,9 +670,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -793,9 +685,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -803,15 +695,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -820,38 +712,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -867,9 +759,9 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.18.5" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +checksum = "446f32b74d22c33b7b258d4af4ffde53c2bf96ca2e29abdf1a785fe59bd6c82c" dependencies = [ "gdk-pixbuf-sys", "gio", @@ -935,9 +827,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -968,9 +860,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "gio" @@ -1006,11 +898,11 @@ dependencies = [ [[package]] name = "glib" -version = "0.18.5" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +checksum = "951bbd7fdc5c044ede9f05170f05a3ae9479239c3afdfe2d22d537a3add15c4e" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.1", "futures-channel", "futures-core", "futures-executor", @@ -1035,16 +927,16 @@ checksum = "3431c56f463443cba9bc3600248bc6d680cb614c2ee1cdd39dab5415bd12ac5c" [[package]] name = "glib-macros" -version = "0.18.5" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5" dependencies = [ "heck", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -1184,9 +1076,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1194,7 +1086,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -1203,9 +1095,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -1215,9 +1113,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1236,18 +1134,18 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "http" -version = "0.2.11" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" dependencies = [ "bytes", "fnv", @@ -1256,9 +1154,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -1285,9 +1183,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -1300,7 +1198,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1322,14 +1220,24 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.1.0" @@ -1337,7 +1245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.2", ] [[package]] @@ -1349,53 +1257,28 @@ dependencies = [ "generic-array", ] -[[package]] -name = "ip_network" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" - -[[package]] -name = "ip_network_table" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" -dependencies = [ - "ip_network", - "ip_network_table-deps-treebitmap", -] - -[[package]] -name = "ip_network_table-deps-treebitmap" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" - [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -dependencies = [ - "serde", -] [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -1408,9 +1291,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -1461,9 +1344,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -1475,16 +1358,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "libsystemd" version = "0.6.0" @@ -1505,9 +1378,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "locale_config" @@ -1558,9 +1431,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -1600,7 +1473,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -1626,13 +1499,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1736,32 +1609,26 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.63" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -1778,7 +1645,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -1789,9 +1656,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.99" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -1830,12 +1697,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1856,7 +1717,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -1890,9 +1751,9 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" @@ -1908,26 +1769,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" - -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "powerfmt" @@ -1935,20 +1779,14 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "prettyplease" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -1963,12 +1801,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.20.7", ] [[package]] @@ -1997,51 +1834,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] [[package]] name = "redox_syscall" @@ -2054,13 +1867,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", + "regex-automata 0.4.3", "regex-syntax 0.8.2", ] @@ -2075,9 +1888,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -2099,7 +1912,7 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "relm4" version = "0.7.0-beta.2" -source = "git+https://github.com/Relm4/Relm4#e189eee06b887470e0fd65cbaf6d7c0161bed5ea" +source = "git+https://github.com/Relm4/Relm4#61990d5c2a59565c5d11bd26270a2bb133e62ab1" dependencies = [ "async-trait", "flume", @@ -2116,18 +1929,18 @@ dependencies = [ [[package]] name = "relm4-macros" version = "0.7.0-beta.2" -source = "git+https://github.com/Relm4/Relm4#e189eee06b887470e0fd65cbaf6d7c0161bed5ea" +source = "git+https://github.com/Relm4/Relm4#61990d5c2a59565c5d11bd26270a2bb133e62ab1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64", "bytes", @@ -2161,20 +1974,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.48.0", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2198,37 +1997,37 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "schemars" -version = "0.8.16" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" dependencies = [ "dyn-clone", "schemars_derive", @@ -2238,9 +2037,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.16" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" dependencies = [ "proc-macro2", "quote", @@ -2279,28 +2078,28 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -2316,9 +2115,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2327,9 +2126,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2390,9 +2189,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "slab" @@ -2405,9 +2204,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" @@ -2426,7 +2225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2479,9 +2278,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -2524,9 +2323,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.13" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "temp-dir" @@ -2536,44 +2335,44 @@ checksum = "dd16aa9ffe15fe021c6ee3766772132c6e98dfa395a167e16864f61a9cfb71d6" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "termcolor" -version = "1.4.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -2588,9 +2387,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "powerfmt", @@ -2621,9 +2420,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", @@ -2633,7 +2432,7 @@ dependencies = [ "pin-project-lite", "socket2 0.5.5", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2644,7 +2443,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -2673,21 +2472,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] @@ -2698,18 +2497,29 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.1.0", "toml_datetime", "winnow", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -2741,7 +2551,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", ] [[package]] @@ -2776,17 +2586,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-oslog" version = "0.1.2" @@ -2804,9 +2603,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -2817,14 +2616,14 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log 0.2.0", + "tracing-log", ] [[package]] name = "try-lock" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "tun" @@ -2837,7 +2636,7 @@ dependencies = [ "futures", "lazy_static", "libc", - "libloading 0.7.4", + "libloading", "log", "nix", "reqwest", @@ -2861,9 +2660,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" @@ -2886,27 +2685,11 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -[[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]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - [[package]] name = "url" -version = "2.5.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -2921,11 +2704,10 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ - "getrandom", "serde", ] @@ -2970,9 +2752,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2980,24 +2762,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -3007,9 +2789,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3017,28 +2799,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -3099,7 +2881,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -3108,16 +2890,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", + "windows-targets", ] [[package]] @@ -3126,28 +2899,13 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -3156,89 +2914,47 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -3250,46 +2966,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "x25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", + "windows-sys", ] [[package]] name = "xxhash-rust" -version = "0.8.8" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] +checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b" [[package]] name = "zip" diff --git a/burrow-gtk/Cargo.toml b/burrow-gtk/Cargo.toml index 244c161..613dce3 100644 --- a/burrow-gtk/Cargo.toml +++ b/burrow-gtk/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1.0" relm4 = { features = ["libadwaita", "gnome_45"], git = "https://github.com/Relm4/Relm4" } burrow = { version = "*", path = "../burrow/" } tokio = { version = "1.35.0", features = ["time", "sync"] } -gettext-rs = { version = "0.7.0", features = ["gettext-system"] } +gettext-rs = "0.7.0" [build-dependencies] anyhow = "1.0" diff --git a/burrow-gtk/build-aux/com.hackclub.burrow.devel.json b/burrow-gtk/build-aux/com.hackclub.burrow.devel.json index 4a2e5fc..31b05c7 100644 --- a/burrow-gtk/build-aux/com.hackclub.burrow.devel.json +++ b/burrow-gtk/build-aux/com.hackclub.burrow.devel.json @@ -24,24 +24,12 @@ "RUST_LOG" : "burrow-gtk=debug" } }, - "cleanup" : [ - "/include", - "/lib/pkgconfig", - "/man", - "/share/doc", - "/share/gtk-doc", - "/share/man", - "/share/pkgconfig", - "*.la", - "*.a" - ], "modules" : [ { "name" : "burrow-gtk", "builddir" : true, "subdir" : "burrow-gtk", "buildsystem" : "meson", - "config-opts": ["--buildtype=debug"], "sources" : [ { "type": "dir", diff --git a/burrow-gtk/build-aux/com.hackclub.burrow.json b/burrow-gtk/build-aux/com.hackclub.burrow.json index c8b68e5..dde4f9a 100644 --- a/burrow-gtk/build-aux/com.hackclub.burrow.json +++ b/burrow-gtk/build-aux/com.hackclub.burrow.json @@ -41,7 +41,6 @@ "builddir" : true, "subdir" : "burrow-gtk", "buildsystem" : "meson", - "config-opts": ["--buildtype=release"], "sources" : [ { "type": "dir", diff --git a/burrow-gtk/data/app.gschema.xml.in b/burrow-gtk/data/app.gschema.xml.in deleted file mode 100644 index 0541c6f..0000000 --- a/burrow-gtk/data/app.gschema.xml.in +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/burrow-gtk/data/app.metainfo.xml.in b/burrow-gtk/data/app.metainfo.xml.in deleted file mode 100644 index 8cc2e59..0000000 --- a/burrow-gtk/data/app.metainfo.xml.in +++ /dev/null @@ -1,16 +0,0 @@ - - - @APP_ID@ - CC0 - GPL-3.0-or-later - @APP_NAME_CAPITALIZED@ - @APP_ID@.desktop - - -

No description

-
- - -

No Summary

-
-
diff --git a/burrow-gtk/data/com.hackclub.burrow.appdata.xml.in b/burrow-gtk/data/com.hackclub.burrow.appdata.xml.in new file mode 100644 index 0000000..7f8e86b --- /dev/null +++ b/burrow-gtk/data/com.hackclub.burrow.appdata.xml.in @@ -0,0 +1,8 @@ + + + com.hackclub.burrow.desktop + GPL-3.0-or-later + +

No description

+
+
diff --git a/burrow-gtk/data/app.desktop.in.in b/burrow-gtk/data/com.hackclub.burrow.desktop.in similarity index 60% rename from burrow-gtk/data/app.desktop.in.in rename to burrow-gtk/data/com.hackclub.burrow.desktop.in index 33b9c5b..91c463d 100644 --- a/burrow-gtk/data/app.desktop.in.in +++ b/burrow-gtk/data/com.hackclub.burrow.desktop.in @@ -1,7 +1,7 @@ [Desktop Entry] -Name=@APP_NAME_CAPITALIZED@ -Exec=@APP_NAME@ -Icon=@APP_ID@ +Name=Burrow +Exec=burrow-gtk +Icon=com.hackclub.burrow Terminal=false Type=Application Categories=GTK;Network diff --git a/burrow-gtk/data/com.hackclub.burrow.gschema.xml b/burrow-gtk/data/com.hackclub.burrow.gschema.xml new file mode 100644 index 0000000..d1bceef --- /dev/null +++ b/burrow-gtk/data/com.hackclub.burrow.gschema.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/burrow-gtk/data/icons/hicolor/scalable/apps/burrow-gtk.svg b/burrow-gtk/data/icons/hicolor/scalable/apps/com.hackclub.burrow.svg similarity index 100% rename from burrow-gtk/data/icons/hicolor/scalable/apps/burrow-gtk.svg rename to burrow-gtk/data/icons/hicolor/scalable/apps/com.hackclub.burrow.svg diff --git a/burrow-gtk/data/icons/hicolor/symbolic/apps/burrow-gtk-symbolic.svg b/burrow-gtk/data/icons/hicolor/symbolic/apps/com.hackclub.burrow-symbolic.svg similarity index 97% rename from burrow-gtk/data/icons/hicolor/symbolic/apps/burrow-gtk-symbolic.svg rename to burrow-gtk/data/icons/hicolor/symbolic/apps/com.hackclub.burrow-symbolic.svg index 5352e0a..0444828 100644 --- a/burrow-gtk/data/icons/hicolor/symbolic/apps/burrow-gtk-symbolic.svg +++ b/burrow-gtk/data/icons/hicolor/symbolic/apps/com.hackclub.burrow-symbolic.svg @@ -1 +1 @@ - + \ No newline at end of file diff --git a/burrow-gtk/data/icons/meson.build b/burrow-gtk/data/icons/meson.build new file mode 100644 index 0000000..86f6480 --- /dev/null +++ b/burrow-gtk/data/icons/meson.build @@ -0,0 +1,13 @@ +application_id = 'com.hackclub.burrow' + +scalable_dir = join_paths('hicolor', 'scalable', 'apps') +install_data( + join_paths(scalable_dir, ('@0@.svg').format(application_id)), + install_dir: join_paths(get_option('datadir'), 'icons', scalable_dir) +) + +symbolic_dir = join_paths('hicolor', 'symbolic', 'apps') +install_data( + join_paths(symbolic_dir, ('@0@-symbolic.svg').format(application_id)), + install_dir: join_paths(get_option('datadir'), 'icons', symbolic_dir) +) diff --git a/burrow-gtk/data/meson.build b/burrow-gtk/data/meson.build index 2c3ffd8..fadf18f 100644 --- a/burrow-gtk/data/meson.build +++ b/burrow-gtk/data/meson.build @@ -1,90 +1,39 @@ -# app.desktop.in.in -desktop_conf = configuration_data() -desktop_conf.set('APP_ID', app_id) -desktop_conf.set('APP_NAME', app_name) -desktop_conf.set('APP_NAME_CAPITALIZED', app_name_capitalized) - -desktop_file_in = configure_file( - input: 'app.desktop.in.in', - output: '@BASENAME@', - configuration: desktop_conf, -) - desktop_file = i18n.merge_file( - input: desktop_file_in, - output: app_id + '.desktop', - type: 'desktop', - po_dir: '../po', - install: true, - install_dir: datadir / 'applications', + input: 'com.hackclub.burrow.desktop.in', + output: 'com.hackclub.burrow.desktop', + type: 'desktop', + po_dir: '../po', + install: true, + install_dir: join_paths(get_option('datadir'), 'applications') ) -if desktop_file_validate.found() - test( - 'validate-desktop', - desktop_file_validate, - args: [desktop_file], - ) +desktop_utils = find_program('desktop-file-validate', required: false) +if desktop_utils.found() + test('Validate desktop file', desktop_utils, args: [desktop_file]) endif -# app.gschema.xml.in -gschema_conf = configuration_data() -gschema_conf.set('APP_ID', app_id) -gschema_conf.set('APP_NAME', app_name) -gschema_conf.set('APP_IDPATH', app_idpath) -gschema_file = configure_file( - input: 'app.gschema.xml.in', - output: app_id + '.gschema.xml', - configuration: gschema_conf, - install: true, - install_dir: datadir / 'glib-2.0' / 'schemas', -) - -if glib_compile_schemas.found() - test( - 'validate-gschema', - glib_compile_schemas, - args: [ - '--dry-run', - datadir / 'glib-2.0' / 'schemas', - ], - ) -endif - -# app.metainfo.xml.in -appdata_conf = configuration_data() -appdata_conf.set('APP_ID', app_id) -appdata_conf.set('APP_NAME', app_name) -appdata_conf.set('APP_NAME_CAPITALIZED', app_name_capitalized) -appdata_file_in = configure_file( - input: 'app.metainfo.xml.in', - output: '@BASENAME@', - configuration: appdata_conf, -) -appdata_file = i18n.merge_file( - input: appdata_file_in, - output: app_id + '.metainfo.xml', - po_dir: '../po', - install: true, - install_dir: datadir / 'metainfo', +appstream_file = i18n.merge_file( + input: 'com.hackclub.burrow.appdata.xml.in', + output: 'com.hackclub.burrow.appdata.xml', + po_dir: '../po', + install: true, + install_dir: join_paths(get_option('datadir'), 'appdata') ) +appstream_util = find_program('appstream-util', required: false) if appstream_util.found() - test( - 'validate-appdata', - appstream_util, - args: ['validate', '--nonet', appdata_file], - ) + test('Validate appstream file', appstream_util, args: ['validate', appstream_file]) endif -install_data( - 'icons/hicolor/scalable/apps/' + app_name + '.svg', - install_dir: datadir / 'icons' / 'hicolor' / 'scalable' / 'apps', - rename: app_id + '.svg', +install_data('com.hackclub.burrow.gschema.xml', + install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas') ) -install_data( - 'icons/hicolor/symbolic/apps/' + app_name + '-symbolic.svg', - install_dir: datadir / 'icons' / 'hicolor' / 'symbolic' / 'apps', - rename: app_id + '-symbolic.svg', -) +compile_schemas = find_program('glib-compile-schemas', required: false) +if compile_schemas.found() + test('Validate schema file', + compile_schemas, + args: ['--strict', '--dry-run', meson.current_source_dir()]) +endif + +subdir('icons') diff --git a/burrow-gtk/data/resources.gresource.xml b/burrow-gtk/data/resources.gresource.xml index 969e77c..381e8ef 100644 --- a/burrow-gtk/data/resources.gresource.xml +++ b/burrow-gtk/data/resources.gresource.xml @@ -3,3 +3,4 @@ + diff --git a/burrow-gtk/meson.build b/burrow-gtk/meson.build index 70d8403..2df1486 100644 --- a/burrow-gtk/meson.build +++ b/burrow-gtk/meson.build @@ -1,56 +1,28 @@ -project( - 'burrow-gtk', - ['rust'], - version: '0.0.1', - meson_version: '>= 1.0', +project('burrow-gtk', 'rust', + version: '0.1.0', + meson_version: '>= 0.62.0', + default_options: [ 'warning_level=2', 'werror=false', ], ) -# Find Cargo -cargo_bin = find_program('cargo') -cargo_env = ['CARGO_HOME=' + meson.project_build_root()] -cargo_opt = ['--manifest-path', meson.project_source_root() / 'Cargo.toml'] -cargo_opt += ['--target-dir', meson.project_build_root() / 'target'] - -# Config -prefix = get_option('prefix') -datadir = prefix / get_option('datadir') -localedir = prefix / get_option('localedir') - -app_name = 'burrow-gtk' -app_name_capitalized = 'Burrow' -base_id = 'com.hackclub.burrow' -app_idpath = '/com/hackclub/' + app_name + '/' -if get_option('buildtype') == 'release' - cargo_opt += ['--release'] - rust_target = 'release' - app_id = base_id -else - rust_target = 'debug' - app_id = base_id + '-' + 'devel' -endif - -# Imports i18n = import('i18n') gnome = import('gnome') -# External Dependencies -dependency('gtk4', version: '>= 4.12') -dependency('libadwaita-1', version: '>= 1.4') - glib_compile_resources = find_program('glib-compile-resources', required: true) glib_compile_schemas = find_program('glib-compile-schemas', required: true) desktop_file_validate = find_program('desktop-file-validate', required: false) appstream_util = find_program('appstream-util', required: false) fc_cache = find_program('fc-cache', required: false) +update_mime_database = find_program('update-mime-database', required: false) + +dependency('gtk4', version: '>= 4.12') +dependency('libadwaita-1', version: '>= 1.4') -# Our Sources subdir('po') subdir('data') subdir('src') -# Gnome Post Install gnome.post_install( - glib_compile_schemas: true, - gtk_update_icon_cache: true, - update_desktop_database: true, + glib_compile_schemas: true, + gtk_update_icon_cache: true, + update_desktop_database: true, ) diff --git a/burrow-gtk/po/POTFILES b/burrow-gtk/po/POTFILES index 08b570f..775914f 100644 --- a/burrow-gtk/po/POTFILES +++ b/burrow-gtk/po/POTFILES @@ -1 +1,3 @@ -data/app.desktop.in.in +data/com.hackclub.Burrow.desktop.in +data/com.hackclub.Burrow.appdata.xml.in +data/com.hackclub.Burrow.gschema.xml diff --git a/burrow-gtk/po/meson.build b/burrow-gtk/po/meson.build index 597577b..4b239a8 100644 --- a/burrow-gtk/po/meson.build +++ b/burrow-gtk/po/meson.build @@ -1 +1 @@ -i18n.gettext(app_name, preset: 'glib') +i18n.gettext('burrow-gtk', preset: 'glib') diff --git a/burrow-gtk/src/components/app.rs b/burrow-gtk/src/components/app.rs index b42b718..cffe466 100644 --- a/burrow-gtk/src/components/app.rs +++ b/burrow-gtk/src/components/app.rs @@ -18,7 +18,7 @@ pub enum AppMsg { impl App { pub fn run() { - let app = RelmApp::new(config::ID); + let app = RelmApp::new("com.hackclub.burrow"); Self::setup_gresources().unwrap(); Self::setup_i18n().unwrap(); diff --git a/burrow-gtk/src/components/settings_screen.rs b/burrow-gtk/src/components/settings_screen.rs index 778eb84..0a29e43 100644 --- a/burrow-gtk/src/components/settings_screen.rs +++ b/burrow-gtk/src/components/settings_screen.rs @@ -21,7 +21,7 @@ impl SimpleComponent for SettingsScreen { fn init( init: Self::Init, - root: Self::Root, + root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { let diag_group = settings::DiagGroup::builder() diff --git a/burrow-gtk/src/config.rs.in b/burrow-gtk/src/config.rs.in index 7da2f3f..1a24858 100644 --- a/burrow-gtk/src/config.rs.in +++ b/burrow-gtk/src/config.rs.in @@ -1,8 +1,4 @@ -#[allow(unused)] -pub const ID: &str = @ID@; -#[allow(unused)] -pub const VERSION: &str = @VERSION@; -#[allow(unused)] -pub const LOCALEDIR: &str = @LOCALEDIR@; -#[allow(unused)] -pub const GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; +pub static VERSION: &str = @VERSION@; +pub static GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; +pub static LOCALEDIR: &str = @LOCALEDIR@; +pub static PKGDATADIR: &str = @PKGDATADIR@; diff --git a/burrow-gtk/src/meson.build b/burrow-gtk/src/meson.build index ed77771..1d7422a 100644 --- a/burrow-gtk/src/meson.build +++ b/burrow-gtk/src/meson.build @@ -1,34 +1,46 @@ -# config.rs.in +pkgdatadir = get_option('prefix') / get_option('datadir') / meson.project_name() + global_conf = configuration_data() -global_conf.set_quoted('ID', app_id) global_conf.set_quoted('VERSION', meson.project_version()) -global_conf.set_quoted('LOCALEDIR', localedir) -global_conf.set_quoted('GETTEXT_PACKAGE', app_name) +global_conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) +global_conf.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir')) +global_conf.set_quoted('PKGDATADIR', pkgdatadir) config = configure_file( - input: 'config.rs.in', - output: 'config.rs', - configuration: global_conf, + input: 'config.rs.in', + output: 'config.rs', + configuration: global_conf ) run_command( - 'cp', - meson.project_build_root() / 'src' / 'config.rs', - meson.project_source_root() / 'src', - check: true, + 'cp', + meson.project_build_root() / 'src' / 'config.rs', + meson.project_source_root() / 'src' / 'config.rs', + check: true ) -# Cargo Build +cargo_bin = find_program('cargo') +cargo_opt = [ '--manifest-path', meson.project_source_root() / 'Cargo.toml' ] +cargo_opt += [ '--target-dir', meson.project_build_root() / 'src' ] +cargo_env = [ 'CARGO_HOME=' + meson.project_build_root() / 'cargo-home' ] + +if get_option('buildtype') == 'release' + cargo_options += [ '--release' ] + rust_target = 'release' +else + rust_target = 'debug' +endif + cargo_build = custom_target( - 'cargo-build', - build_by_default: true, - build_always_stale: true, - output: meson.project_name(), - console: true, - install: true, - install_dir: get_option('bindir'), - command: [ - 'env', cargo_env, - cargo_bin, 'build', - cargo_opt, '&&', 'cp', 'target' / rust_target / meson.project_name(), '@OUTPUT@', - ] - ) + 'cargo-build', + build_by_default: true, + build_always_stale: true, + output: meson.project_name(), + console: true, + install: true, + install_dir: get_option('bindir'), + command: [ + 'env', cargo_env, + cargo_bin, 'build', + cargo_opt, '&&', 'cp', 'src' / rust_target / meson.project_name(), '@OUTPUT@', + ] +) diff --git a/burrow/Cargo.toml b/burrow/Cargo.toml index f263cc6..ab19e5c 100644 --- a/burrow/Cargo.toml +++ b/burrow/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["lib", "staticlib"] [dependencies] anyhow = "1.0" -tokio = { version = "1.21", features = ["rt", "macros", "sync", "io-util", "rt-multi-thread", "time"] } +tokio = { version = "1.21", features = ["rt", "macros", "sync", "io-util", "rt-multi-thread"] } tun = { version = "0.1", path = "../tun", features = ["serde", "tokio"] } clap = { version = "4.3.2", features = ["derive"] } tracing = "0.1" @@ -22,24 +22,8 @@ env_logger = "0.10" log = "0.4" serde = { version = "1", features = ["derive"] } serde_json = "1" -blake2 = "0.10.6" -chacha20poly1305 = "0.10.1" -rand = "0.8.5" -rand_core = "0.6.4" -aead = "0.5.2" -x25519-dalek = { version = "2.0.0", features = ["reusable_secrets", "static_secrets"] } -ring = "0.17.7" -parking_lot = "0.12.1" -hmac = "0.12" -ipnet = { version = "2.8.0", features = ["serde"] } -base64 = "0.21.4" -fehler = "1.0.0" -ip_network_table = "0.2.0" -ip_network = "0.4.0" -async-channel = "2.1.1" +async-channel = "1.9" schemars = "0.8" -futures = "0.3.28" -uuid = { version = "1.6.1", features = ["v4"] } [target.'cfg(target_os = "linux")'.dependencies] caps = "0.5.5" @@ -50,7 +34,6 @@ nix = { version = "0.26.2" } [dev-dependencies] insta = { version = "1.32.0", features = ["yaml"] } -etherparse = "0.12" [package.metadata.generate-rpm] assets = [ diff --git a/burrow/src/apple.rs b/burrow/src/apple.rs index 9fc0140..0a96877 100644 --- a/burrow/src/apple.rs +++ b/burrow/src/apple.rs @@ -1,13 +1,15 @@ -use tracing::debug; +use tracing::{debug, Subscriber}; +use tracing::instrument::WithSubscriber; use tracing_oslog::OsLogger; +use tracing_subscriber::FmtSubscriber; use tracing_subscriber::layer::SubscriberExt; pub use crate::daemon::start_srv; #[no_mangle] pub extern "C" fn initialize_oslog() { - let collector = - tracing_subscriber::registry().with(OsLogger::new("com.hackclub.burrow", "backend")); + let collector = tracing_subscriber::registry() + .with(OsLogger::new("com.hackclub.burrow", "backend")); tracing::subscriber::set_global_default(collector).unwrap(); debug!("Initialized oslog tracing in libburrow rust FFI"); } \ No newline at end of file diff --git a/burrow/src/daemon/command.rs b/burrow/src/daemon/command.rs index 53b4108..a5a1f30 100644 --- a/burrow/src/daemon/command.rs +++ b/burrow/src/daemon/command.rs @@ -12,22 +12,21 @@ pub enum DaemonCommand { #[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct DaemonStartOptions { - pub tun: TunOptions, + pub(super) tun: TunOptions, } #[test] fn test_daemoncommand_serialization() { - insta::assert_snapshot!(serde_json::to_string(&DaemonCommand::Start( - DaemonStartOptions::default() - )) - .unwrap()); insta::assert_snapshot!( - serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions { - tun: TunOptions { ..TunOptions::default() } - })) - .unwrap() + serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap() ); - insta::assert_snapshot!(serde_json::to_string(&DaemonCommand::ServerInfo).unwrap()); - insta::assert_snapshot!(serde_json::to_string(&DaemonCommand::Stop).unwrap()); - insta::assert_snapshot!(serde_json::to_string(&DaemonCommand::ServerConfig).unwrap()) -} + insta::assert_snapshot!( + serde_json::to_string(&DaemonCommand::ServerInfo).unwrap() + ); + insta::assert_snapshot!( + serde_json::to_string(&DaemonCommand::Stop).unwrap() + ); + insta::assert_snapshot!( + serde_json::to_string(&DaemonCommand::ServerConfig).unwrap() + ) +} \ No newline at end of file diff --git a/burrow/src/daemon/instance.rs b/burrow/src/daemon/instance.rs index 34e9878..db9e1ac 100644 --- a/burrow/src/daemon/instance.rs +++ b/burrow/src/daemon/instance.rs @@ -1,43 +1,20 @@ -use std::sync::Arc; - -use anyhow::Result; -use tokio::{sync::RwLock, task::JoinHandle}; use tracing::{debug, info, warn}; -use tun::tokio::TunInterface; - -use crate::{ - daemon::{ - command::DaemonCommand, - response::{DaemonResponse, DaemonResponseData, ServerConfig, ServerInfo}, - }, - wireguard::Interface, -}; - -enum RunState { - Running(JoinHandle>), - Idle, -} +use DaemonResponse; +use crate::daemon::response::{DaemonResponseData, ServerConfig, ServerInfo}; +use super::*; pub struct DaemonInstance { rx: async_channel::Receiver, sx: async_channel::Sender, - tun_interface: Option>>, - wg_interface: Arc>, - wg_state: RunState, + tun_interface: Option, } impl DaemonInstance { - pub fn new( - rx: async_channel::Receiver, - sx: async_channel::Sender, - wg_interface: Arc>, - ) -> Self { + pub fn new(rx: async_channel::Receiver, sx: async_channel::Sender) -> Self { Self { rx, sx, - wg_interface, tun_interface: None, - wg_state: RunState::Idle, } } @@ -45,52 +22,28 @@ impl DaemonInstance { info!("Daemon got command: {:?}", command); match command { DaemonCommand::Start(st) => { - match self.wg_state { - RunState::Running(_) => { - warn!("Got start, but tun interface already up."); - } - RunState::Idle => { - let tun_if = Arc::new(RwLock::new(st.tun.open()?)); - - debug!("Setting tun_interface"); - self.tun_interface = Some(tun_if.clone()); - debug!("tun_interface set: {:?}", self.tun_interface); - - debug!("Setting tun on wg_interface"); - self.wg_interface.write().await.set_tun(tun_if); - debug!("tun set on wg_interface"); - - debug!("Cloning wg_interface"); - let tmp_wg = self.wg_interface.clone(); - debug!("wg_interface cloned"); - - debug!("Spawning run task"); - let run_task = tokio::spawn(async move { - debug!("Running wg_interface"); - let twlock = tmp_wg.read().await; - debug!("wg_interface read lock acquired"); - twlock.run().await - }); - debug!("Run task spawned: {:?}", run_task); - - debug!("Setting wg_state to Running"); - self.wg_state = RunState::Running(run_task); - debug!("wg_state set to Running"); - - info!("Daemon started tun interface"); - } + if self.tun_interface.is_none() { + debug!("Daemon attempting start tun interface."); + self.tun_interface = Some(st.tun.open()?); + info!("Daemon started tun interface"); + } else { + warn!("Got start, but tun interface already up."); } Ok(DaemonResponseData::None) } - DaemonCommand::ServerInfo => match &self.tun_interface { - None => Ok(DaemonResponseData::None), - Some(ti) => { - info!("{:?}", ti); - Ok(DaemonResponseData::ServerInfo(ServerInfo::try_from( - ti.read().await.inner.get_ref(), - )?)) + DaemonCommand::ServerInfo => { + match &self.tun_interface { + None => {Ok(DaemonResponseData::None)} + Some(ti) => { + info!("{:?}", ti); + Ok( + DaemonResponseData::ServerInfo( + ServerInfo::try_from(ti)? + ) + ) + } } - }, + } DaemonCommand::Stop => { if self.tun_interface.is_some() { self.tun_interface = None; diff --git a/burrow/src/daemon/mod.rs b/burrow/src/daemon/mod.rs index 5a35b28..b59ad7f 100644 --- a/burrow/src/daemon/mod.rs +++ b/burrow/src/daemon/mod.rs @@ -1,51 +1,26 @@ -use std::sync::Arc; +use super::*; +use tokio::sync::mpsc; mod command; mod instance; mod net; mod response; -use anyhow::Result; -pub use command::{DaemonCommand, DaemonStartOptions}; use instance::DaemonInstance; +use net::listen; + +pub use command::{DaemonCommand, DaemonStartOptions}; +pub use net::DaemonClient; + #[cfg(target_vendor = "apple")] pub use net::start_srv; -pub use net::DaemonClient; -pub use response::{DaemonResponse, DaemonResponseData, ServerInfo}; -use tokio::sync::{Notify, RwLock}; -use crate::{ - daemon::net::listen, - wireguard::{Config, Interface}, -}; +pub use response::{DaemonResponseData, DaemonResponse, ServerInfo}; -pub async fn daemon_main(notify_ready: Option>) -> Result<()> { +pub async fn daemon_main() -> Result<()> { let (commands_tx, commands_rx) = async_channel::unbounded(); let (response_tx, response_rx) = async_channel::unbounded(); + let mut inst = DaemonInstance::new(commands_rx, response_tx); - let config = Config::default(); - let iface: Interface = config.try_into()?; - - let mut inst: DaemonInstance = - DaemonInstance::new(commands_rx, response_tx, Arc::new(RwLock::new(iface))); - - tracing::info!("Starting daemon jobs..."); - - let inst_job = tokio::spawn(async move { - let res = inst.run().await; - if let Err(e) = res { - tracing::error!("Error when running instance: {}", e); - } - }); - - let listen_job = tokio::spawn(async move { - let res = listen(commands_tx, response_rx, notify_ready).await; - if let Err(e) = res { - tracing::error!("Error when listening: {}", e); - } - }); - - tokio::try_join!(inst_job, listen_job) - .map(|_| ()) - .map_err(|e| e.into()) + tokio::try_join!(inst.run(), listen(commands_tx, response_rx)).map(|_| ()) } diff --git a/burrow/src/daemon/net/apple.rs b/burrow/src/daemon/net/apple.rs index 143e913..e53bdaa 100644 --- a/burrow/src/daemon/net/apple.rs +++ b/burrow/src/daemon/net/apple.rs @@ -1,32 +1,24 @@ -use std::sync::Arc; use std::thread; - use tokio::runtime::Runtime; -use tokio::sync::Notify; -use tracing::{error, info}; - +use tracing::error; use crate::daemon::{daemon_main, DaemonClient}; #[no_mangle] -pub extern "C" fn start_srv() { - info!("Starting server"); - let start_notify = Arc::new(Notify::new()); - let start_recv = start_notify.clone(); +pub extern "C" fn start_srv(){ let _handle = thread::spawn(move || { let rt = Runtime::new().unwrap(); rt.block_on(async { - if let Err(e) = daemon_main(Some(start_notify.clone())).await { + if let Err(e) = daemon_main().await { error!("Error when starting rpc server: {}", e); } }); - start_notify.notify_one(); }); let rt = Runtime::new().unwrap(); rt.block_on(async { - start_recv.notified().await; - match DaemonClient::new().await { - Ok(..) => info!("Server successfully started"), - Err(e) => error!("Could not connect to server: {}", e) + loop { + if let Ok(_) = DaemonClient::new().await{ + break + } } }); -} +} \ No newline at end of file diff --git a/burrow/src/daemon/net/mod.rs b/burrow/src/daemon/net/mod.rs index d369f40..b5e0736 100644 --- a/burrow/src/daemon/net/mod.rs +++ b/burrow/src/daemon/net/mod.rs @@ -1,7 +1,6 @@ +use super::*; use serde::{Deserialize, Serialize}; -use super::DaemonCommand; - #[cfg(target_family = "unix")] mod unix; #[cfg(all(target_family = "unix", not(target_os = "linux")))] @@ -29,3 +28,4 @@ pub struct DaemonRequest { pub id: u32, pub command: DaemonCommand, } + diff --git a/burrow/src/daemon/net/systemd.rs b/burrow/src/daemon/net/systemd.rs index 4534742..446c259 100644 --- a/burrow/src/daemon/net/systemd.rs +++ b/burrow/src/daemon/net/systemd.rs @@ -1,33 +1,16 @@ -use std::os::fd::IntoRawFd; -use std::sync::Arc; - -use anyhow::Result; -use tokio::sync::Notify; - use super::*; -use crate::daemon::DaemonResponse; +use std::os::fd::IntoRawFd; -pub async fn listen( - cmd_tx: async_channel::Sender, - rsp_rx: async_channel::Receiver, - notify: Option> -) -> Result<()> { - if !libsystemd::daemon::booted() - || listen_with_systemd(cmd_tx.clone(), rsp_rx.clone()) - .await - .is_err() - { - unix::listen(cmd_tx, rsp_rx, notify).await?; +pub async fn listen(cmd_tx: async_channel::Sender, rsp_rx: async_channel::Receiver) -> Result<()> { + if !libsystemd::daemon::booted() || listen_with_systemd(cmd_tx.clone(), rsp_rx.clone()).await.is_err() { + unix::listen(cmd_tx, rsp_rx).await?; } Ok(()) } -async fn listen_with_systemd( - cmd_tx: async_channel::Sender, - rsp_rx: async_channel::Receiver, -) -> Result<()> { +async fn listen_with_systemd(cmd_tx: async_channel::Sender, rsp_rx: async_channel::Receiver) -> Result<()> { let fds = libsystemd::activation::receive_descriptors(false)?; - super::unix::listen_with_optional_fd(cmd_tx, rsp_rx, Some(fds[0].clone().into_raw_fd()), None).await + super::unix::listen_with_optional_fd(cmd_tx, rsp_rx,Some(fds[0].clone().into_raw_fd())).await } pub type DaemonClient = unix::DaemonClient; diff --git a/burrow/src/daemon/net/unix.rs b/burrow/src/daemon/net/unix.rs index 948bdff..d152240 100644 --- a/burrow/src/daemon/net/unix.rs +++ b/burrow/src/daemon/net/unix.rs @@ -1,23 +1,20 @@ +use super::*; +use anyhow::anyhow; +use log::log; +use std::hash::Hash; +use std::path::PathBuf; use std::{ - io, - os::{ - fd::{FromRawFd, RawFd}, - unix::net::UnixListener as StdUnixListener, - }, - path::{Path, PathBuf}, + ascii, io, + os::fd::{FromRawFd, RawFd}, + os::unix::net::UnixListener as StdUnixListener, + path::Path, }; -use std::sync::Arc; - -use anyhow::{anyhow, Result}; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, net::{UnixListener, UnixStream}, }; -use tracing::{debug, info}; - -use tokio::sync::Notify; -use super::*; -use crate::daemon::{DaemonCommand, DaemonResponse, DaemonResponseData}; +use tracing::debug; +use tracing::info; #[cfg(not(target_vendor = "apple"))] const UNIX_SOCKET_PATH: &str = "/run/burrow.sock"; @@ -38,7 +35,7 @@ fn fetch_socket_path() -> Option { for path in tries { let path = PathBuf::from(path); if path.exists() { - return Some(path) + return Some(path); } } None @@ -52,16 +49,14 @@ fn fetch_socket_path() -> Option { pub async fn listen( cmd_tx: async_channel::Sender, rsp_rx: async_channel::Receiver, - notify: Option> ) -> Result<()> { - listen_with_optional_fd(cmd_tx, rsp_rx, None, notify).await + listen_with_optional_fd(cmd_tx, rsp_rx, None).await } pub(crate) async fn listen_with_optional_fd( cmd_tx: async_channel::Sender, rsp_rx: async_channel::Receiver, raw_fd: Option, - notify: Option> ) -> Result<()> { let path = Path::new(UNIX_SOCKET_PATH); @@ -86,16 +81,12 @@ pub(crate) async fn listen_with_optional_fd( info!("Relative path: {}", path.to_string_lossy()); UnixListener::bind(path)? }; - if let Some(notify) = notify { - notify.notify_one(); - } loop { let (stream, _) = listener.accept().await?; let cmd_tx = cmd_tx.clone(); // I'm pretty sure we won't need to manually join / shut this down, - // `lines` will return Err during dropping, and this task should exit - // gracefully. + // `lines` will return Err during dropping, and this task should exit gracefully. let rsp_rxc = rsp_rx.clone(); tokio::task::spawn(async move { let cmd_tx = cmd_tx; @@ -111,7 +102,6 @@ pub(crate) async fn listen_with_optional_fd( Ok(req) => Some(req), Err(e) => { res.result = Err(e.to_string()); - tracing::error!("Failed to parse request: {}", e); None } }; @@ -125,8 +115,6 @@ pub(crate) async fn listen_with_optional_fd( retres.push('\n'); info!("Sending response: {}", retres); write_stream.write_all(retres.as_bytes()).await.unwrap(); - } else { - write_stream.write_all(res.as_bytes()).await.unwrap(); } } }); diff --git a/burrow/src/daemon/net/windows.rs b/burrow/src/daemon/net/windows.rs index c4a1d71..3f9d513 100644 --- a/burrow/src/daemon/net/windows.rs +++ b/burrow/src/daemon/net/windows.rs @@ -1,12 +1,6 @@ -use anyhow::Result; - use super::*; -use crate::daemon::DaemonResponse; -pub async fn listen( - _cmd_tx: async_channel::Sender, - _rsp_rx: async_channel::Receiver, -) -> Result<()> { +pub async fn listen(_cmd_tx: async_channel::Sender, _rsp_rx: async_channel::Receiver) -> Result<()> { unimplemented!("This platform does not currently support daemon mode.") } diff --git a/burrow/src/daemon/response.rs b/burrow/src/daemon/response.rs index 386da46..da47150 100644 --- a/burrow/src/daemon/response.rs +++ b/burrow/src/daemon/response.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use tun::TunInterface; @@ -6,27 +7,30 @@ use tun::TunInterface; pub struct DaemonResponse { // Error types can't be serialized, so this is the second best option. pub result: Result, - pub id: u32, + pub id: u32 } -impl DaemonResponse { - pub fn new(result: Result) -> Self { - Self { +impl DaemonResponse{ + pub fn new(result: Result) -> Self{ + Self{ result: result.map_err(|e| e.to_string()), - id: 0, + id: 0 } } } -impl From for DaemonResponse { - fn from(val: DaemonResponseData) -> Self { - DaemonResponse::new(Ok::(val)) +impl Into for DaemonResponseData{ + fn into(self) -> DaemonResponse{ + DaemonResponse::new(Ok::(self)) } } -impl DaemonResponse { - pub fn with_id(self, id: u32) -> Self { - Self { id, ..self } +impl DaemonResponse{ + pub fn with_id(self, id: u32) -> Self{ + Self { + id, + ..self + } } } @@ -34,22 +38,24 @@ impl DaemonResponse { pub struct ServerInfo { pub name: Option, pub ip: Option, - pub mtu: Option, + pub mtu: Option } -impl TryFrom<&TunInterface> for ServerInfo { +impl TryFrom<&TunInterface> for ServerInfo{ type Error = anyhow::Error; - #[cfg(any(target_os = "linux", target_vendor = "apple"))] + #[cfg(any(target_os="linux",target_vendor="apple"))] fn try_from(server: &TunInterface) -> anyhow::Result { - Ok(ServerInfo { - name: server.name().ok(), - ip: server.ipv4_addr().ok().map(|ip| ip.to_string()), - mtu: server.mtu().ok(), - }) + Ok( + ServerInfo{ + name: server.name().ok(), + ip: server.ipv4_addr().ok().map(|ip| ip.to_string()), + mtu: server.mtu().ok() + } + ) } - #[cfg(not(any(target_os = "linux", target_vendor = "apple")))] + #[cfg(not(any(target_os="linux",target_vendor="apple")))] fn try_from(server: &TunInterface) -> anyhow::Result { Err(anyhow!("Not implemented in this platform")) } @@ -59,55 +65,45 @@ impl TryFrom<&TunInterface> for ServerInfo { pub struct ServerConfig { pub address: Option, pub name: Option, - pub mtu: Option, + pub mtu: Option } impl Default for ServerConfig { fn default() -> Self { - Self { - address: Some("10.13.13.2".to_string()), // Dummy remote address + Self{ + address: Some("10.0.0.1".to_string()), // Dummy remote address name: None, - mtu: None, + mtu: None } } } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] -pub enum DaemonResponseData { +pub enum DaemonResponseData{ ServerInfo(ServerInfo), ServerConfig(ServerConfig), - None, + None } #[test] -fn test_response_serialization() -> anyhow::Result<()> { - insta::assert_snapshot!(serde_json::to_string(&DaemonResponse::new(Ok::< - DaemonResponseData, - String, - >( - DaemonResponseData::None - )))?); - insta::assert_snapshot!(serde_json::to_string(&DaemonResponse::new(Ok::< - DaemonResponseData, - String, - >( - DaemonResponseData::ServerInfo(ServerInfo { +fn test_response_serialization() -> anyhow::Result<()>{ + insta::assert_snapshot!( + serde_json::to_string(&DaemonResponse::new(Ok::(DaemonResponseData::None)))? + ); + insta::assert_snapshot!( + serde_json::to_string(&DaemonResponse::new(Ok::(DaemonResponseData::ServerInfo(ServerInfo{ name: Some("burrow".to_string()), ip: None, mtu: Some(1500) - }) - )))?); - insta::assert_snapshot!(serde_json::to_string(&DaemonResponse::new(Err::< - DaemonResponseData, - String, - >( - "error".to_string() - )))?); - insta::assert_snapshot!(serde_json::to_string(&DaemonResponse::new(Ok::< - DaemonResponseData, - String, - >( - DaemonResponseData::ServerConfig(ServerConfig::default()) - )))?); + }))))? + ); + insta::assert_snapshot!( + serde_json::to_string(&DaemonResponse::new(Err::("error".to_string())))? + ); + insta::assert_snapshot!( + serde_json::to_string(&DaemonResponse::new(Ok::(DaemonResponseData::ServerConfig( + ServerConfig::default() + ))))? + ); Ok(()) -} +} \ No newline at end of file diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap index 0eb9096..80b9e24 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-2.snap @@ -1,5 +1,5 @@ --- source: burrow/src/daemon/command.rs -expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions {\n tun: TunOptions { ..TunOptions::default() },\n })).unwrap()" +expression: "serde_json::to_string(&DaemonCommand::ServerInfo).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} +"ServerInfo" diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-3.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-3.snap index 80b9e24..8dc1b8b 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-3.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-3.snap @@ -1,5 +1,5 @@ --- source: burrow/src/daemon/command.rs -expression: "serde_json::to_string(&DaemonCommand::ServerInfo).unwrap()" +expression: "serde_json::to_string(&DaemonCommand::Stop).unwrap()" --- -"ServerInfo" +"Stop" diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-4.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-4.snap index 8dc1b8b..9334ece 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-4.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-4.snap @@ -1,5 +1,5 @@ --- source: burrow/src/daemon/command.rs -expression: "serde_json::to_string(&DaemonCommand::Stop).unwrap()" +expression: "serde_json::to_string(&DaemonCommand::ServerConfig).unwrap()" --- -"Stop" +"ServerConfig" diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-5.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-5.snap deleted file mode 100644 index 9334ece..0000000 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization-5.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: burrow/src/daemon/command.rs -expression: "serde_json::to_string(&DaemonCommand::ServerConfig).unwrap()" ---- -"ServerConfig" diff --git a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap index bfd5117..2f8af66 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__command__daemoncommand_serialization.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/command.rs expression: "serde_json::to_string(&DaemonCommand::Start(DaemonStartOptions::default())).unwrap()" --- -{"Start":{"tun":{"name":null,"no_pi":false,"tun_excl":false,"tun_retrieve":false,"address":null}}} +{"Start":{"tun":{"name":null,"no_pi":null,"tun_excl":null}}} diff --git a/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap b/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap index 9752ebc..95f9e7b 100644 --- a/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap +++ b/burrow/src/daemon/snapshots/burrow__daemon__response__response_serialization-4.snap @@ -2,4 +2,4 @@ source: burrow/src/daemon/response.rs expression: "serde_json::to_string(&DaemonResponse::new(Ok::(DaemonResponseData::ServerConfig(ServerConfig::default()))))?" --- -{"result":{"Ok":{"ServerConfig":{"address":"10.13.13.2","name":null,"mtu":null}}},"id":0} +{"result":{"Ok":{"ServerConfig":{"address":"10.0.0.1","name":null,"mtu":null}}},"id":0} diff --git a/burrow/src/ensureroot.rs b/burrow/src/ensureroot.rs new file mode 100644 index 0000000..b7c0757 --- /dev/null +++ b/burrow/src/ensureroot.rs @@ -0,0 +1,40 @@ +use tracing::instrument; + +// Check capabilities on Linux +#[cfg(target_os = "linux")] +#[instrument] +pub fn ensure_root() { + use caps::{has_cap, CapSet, Capability}; + + let cap_net_admin = Capability::CAP_NET_ADMIN; + if let Ok(has_cap) = has_cap(None, CapSet::Effective, cap_net_admin) { + if !has_cap { + eprintln!( + "This action needs the CAP_NET_ADMIN permission. Did you mean to run it as root?" + ); + std::process::exit(77); + } + } else { + eprintln!("Failed to check capabilities. Please file a bug report!"); + std::process::exit(71); + } +} + +// Check for root user on macOS +#[cfg(target_vendor = "apple")] +#[instrument] +pub fn ensure_root() { + use nix::unistd::Uid; + + let current_uid = Uid::current(); + if !current_uid.is_root() { + eprintln!("This action must be run as root!"); + std::process::exit(77); + } +} + +#[cfg(target_family = "windows")] +#[instrument] +pub fn ensure_root() { + todo!() +} diff --git a/burrow/src/lib.rs b/burrow/src/lib.rs index 3dfc4ac..ce6d637 100644 --- a/burrow/src/lib.rs +++ b/burrow/src/lib.rs @@ -1,16 +1,21 @@ -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -pub mod wireguard; +#![deny(missing_debug_implementations)] +pub mod ensureroot; + +use anyhow::Result; #[cfg(any(target_os = "linux", target_vendor = "apple"))] +use std::{ + mem, + os::fd::{AsRawFd, FromRawFd}, +}; + +use tun::TunInterface; + +// TODO Separate start and retrieve functions + mod daemon; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] pub use daemon::{ - DaemonClient, - DaemonCommand, - DaemonResponse, - DaemonResponseData, - DaemonStartOptions, - ServerInfo, + DaemonClient, DaemonCommand, DaemonResponse, DaemonResponseData, DaemonStartOptions, ServerInfo, }; #[cfg(target_vendor = "apple")] @@ -18,3 +23,24 @@ mod apple; #[cfg(target_vendor = "apple")] pub use apple::*; + +#[cfg(any(target_os = "linux", target_vendor = "apple"))] +#[no_mangle] +pub extern "C" fn retrieve() -> i32 { + let iface2 = (1..100) + .filter_map(|i| { + let iface = unsafe { TunInterface::from_raw_fd(i) }; + match iface.name() { + Ok(_name) => Some(iface), + Err(_) => { + mem::forget(iface); + None + } + } + }) + .next(); + match iface2 { + Some(iface) => iface.as_raw_fd(), + None => -1, + } +} diff --git a/burrow/src/main.rs b/burrow/src/main.rs index 9a692d6..f89ee39 100644 --- a/burrow/src/main.rs +++ b/burrow/src/main.rs @@ -1,22 +1,22 @@ -use anyhow::{Context, Result}; +use anyhow::Context; +use std::mem; +#[cfg(any(target_os = "linux", target_vendor = "apple"))] +use std::os::fd::FromRawFd; + use clap::{Args, Parser, Subcommand}; -use tracing::instrument; +use tracing::{instrument, Level}; + use tracing_log::LogTracer; use tracing_oslog::OsLogger; -use tracing_subscriber::{prelude::*, EnvFilter, FmtSubscriber}; +use tracing_subscriber::{prelude::*, FmtSubscriber, EnvFilter}; +use anyhow::Result; #[cfg(any(target_os = "linux", target_vendor = "apple"))] +use burrow::retrieve; use tun::TunInterface; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] mod daemon; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -mod wireguard; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] use daemon::{DaemonClient, DaemonCommand, DaemonStartOptions}; -use tun::TunOptions; - -#[cfg(any(target_os = "linux", target_vendor = "apple"))] use crate::daemon::DaemonResponseData; #[derive(Parser)] @@ -64,32 +64,17 @@ struct DaemonArgs {} async fn try_start() -> Result<()> { let mut client = DaemonClient::new().await?; client - .send_command(DaemonCommand::Start(DaemonStartOptions { - tun: TunOptions::new().address("10.13.13.2"), - })) + .send_command(DaemonCommand::Start(DaemonStartOptions::default())) .await .map(|_| ()) } -#[cfg(target_vendor = "apple")] +#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[instrument] async fn try_retrieve() -> Result<()> { - LogTracer::init() - .context("Failed to initialize LogTracer") - .unwrap(); - - if cfg!(target_os = "linux") || cfg!(target_vendor = "apple") { - let maybe_layer = system_log().unwrap(); - if let Some(layer) = maybe_layer { - let logger = layer.with_subscriber(FmtSubscriber::new()); - tracing::subscriber::set_global_default(logger) - .context("Failed to set the global tracing subscriber") - .unwrap(); - } - } - - let iface2 = TunInterface::retrieve().ok_or(anyhow::anyhow!("No interface found"))?; - tracing::info!("{:?}", iface2); + burrow::ensureroot::ensure_root(); + let iface2 = retrieve(); + tracing::info!("{}", iface2); Ok(()) } @@ -104,10 +89,9 @@ async fn initialize_tracing() -> Result<()> { FmtSubscriber::builder() .with_line_number(true) .with_env_filter(EnvFilter::from_default_env()) - .finish(), + .finish() ); - tracing::subscriber::set_global_default(logger) - .context("Failed to set the global tracing subscriber")?; + tracing::subscriber::set_global_default(logger).context("Failed to set the global tracing subscriber")?; } } @@ -122,7 +106,7 @@ async fn try_stop() -> Result<()> { } #[cfg(any(target_os = "linux", target_vendor = "apple"))] -async fn try_serverinfo() -> Result<()> { +async fn try_serverinfo() -> Result<()>{ let mut client = DaemonClient::new().await?; let res = client.send_command(DaemonCommand::ServerInfo).await?; match res.result { @@ -132,9 +116,7 @@ async fn try_serverinfo() -> Result<()> { Ok(DaemonResponseData::None) => { println!("Server not started.") } - Ok(res) => { - println!("Unexpected Response: {:?}", res) - } + Ok(res) => {println!("Unexpected Response: {:?}", res)} Err(e) => { println!("Error when retrieving from server: {}", e) } @@ -143,7 +125,7 @@ async fn try_serverinfo() -> Result<()> { } #[cfg(any(target_os = "linux", target_vendor = "apple"))] -async fn try_serverconfig() -> Result<()> { +async fn try_serverconfig() -> Result<()>{ let mut client = DaemonClient::new().await?; let res = client.send_command(DaemonCommand::ServerConfig).await?; match res.result { @@ -153,9 +135,7 @@ async fn try_serverconfig() -> Result<()> { Ok(DaemonResponseData::None) => { println!("Server not started.") } - Ok(res) => { - println!("Unexpected Response: {:?}", res) - } + Ok(res) => {println!("Unexpected Response: {:?}", res)} Err(e) => { println!("Error when retrieving from server: {}", e) } @@ -168,7 +148,7 @@ async fn try_start() -> Result<()> { Ok(()) } -#[cfg(not(target_vendor = "apple"))] +#[cfg(not(any(target_os = "linux", target_vendor = "apple")))] async fn try_retrieve() -> Result<()> { Ok(()) } @@ -187,7 +167,6 @@ async fn try_serverinfo() -> Result<()> { async fn try_serverconfig() -> Result<()> { Ok(()) } -#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { initialize_tracing().await?; @@ -206,32 +185,31 @@ async fn main() -> Result<()> { Commands::Stop => { try_stop().await?; } - Commands::Daemon(_) => daemon::daemon_main(None).await?, - Commands::ServerInfo => try_serverinfo().await?, - Commands::ServerConfig => try_serverconfig().await?, + Commands::Daemon(_) => daemon::daemon_main().await?, + Commands::ServerInfo => { + try_serverinfo().await? + } + Commands::ServerConfig => { + try_serverconfig().await? + } } Ok(()) } #[cfg(target_os = "linux")] -fn system_log() -> Result> { +fn system_log() -> anyhow::Result> { let maybe_journald = tracing_journald::layer(); match maybe_journald { Err(e) if e.kind() == std::io::ErrorKind::NotFound => { tracing::trace!("journald not found"); Ok(None) - } - _ => Ok(Some(maybe_journald?)), + }, + _ => Ok(Some(maybe_journald?)) } } #[cfg(target_vendor = "apple")] -fn system_log() -> Result> { +fn system_log() -> anyhow::Result> { Ok(Some(OsLogger::new("com.hackclub.burrow", "burrow-cli"))) } - -#[cfg(not(any(target_os = "linux", target_vendor = "apple")))] -pub fn main() { - eprintln!("This platform is not supported currently.") -} diff --git a/burrow/src/wireguard/config.rs b/burrow/src/wireguard/config.rs deleted file mode 100644 index afe7499..0000000 --- a/burrow/src/wireguard/config.rs +++ /dev/null @@ -1,112 +0,0 @@ -use std::{net::ToSocketAddrs, str::FromStr}; - -use anyhow::{anyhow, Error, Result}; -use base64::{engine::general_purpose, Engine}; -use fehler::throws; -use ip_network::IpNetwork; -use x25519_dalek::{PublicKey, StaticSecret}; - -use crate::wireguard::{Interface as WgInterface, Peer as WgPeer}; - -#[throws] -fn parse_key(string: &str) -> [u8; 32] { - let value = general_purpose::STANDARD.decode(string)?; - let mut key = [0u8; 32]; - key.copy_from_slice(&value[..]); - key -} - -#[throws] -fn parse_secret_key(string: &str) -> StaticSecret { - let key = parse_key(string)?; - StaticSecret::from(key) -} - -#[throws] -fn parse_public_key(string: &str) -> PublicKey { - let key = parse_key(string)?; - PublicKey::from(key) -} - -/// A raw version of Peer Config that can be used later to reflect configuration files. -/// This should be later converted to a `WgPeer`. -/// Refers to https://github.com/pirate/wireguard-docs?tab=readme-ov-file#overview -pub struct Peer { - pub public_key: String, - pub preshared_key: Option, - pub allowed_ips: Vec, - pub endpoint: String, - pub persistent_keepalive: Option, - pub name: Option, -} - -pub struct Interface { - pub private_key: String, - pub address: String, - pub listen_port: u32, - pub dns: Vec, - pub mtu: Option, -} - -pub struct Config { - pub peers: Vec, - pub interface: Interface, // Support for multiple interfaces? -} - -impl TryFrom for WgInterface { - type Error = anyhow::Error; - - fn try_from(cfig: Config) -> Result { - let sk = parse_secret_key(&cfig.interface.private_key)?; - let wg_peers: Vec = cfig - .peers - .iter() - .map(|p| { - Ok(WgPeer { - private_key: sk.clone(), - public_key: parse_public_key(&p.public_key)?, - endpoint: p - .endpoint - .to_socket_addrs()? - .find(|sock| sock.is_ipv4()) - .ok_or(anyhow!("DNS Lookup Fails!"))?, - preshared_key: match &p.preshared_key { - None => Ok(None), - Some(k) => parse_key(k).map(Some), - }?, - allowed_ips: p - .allowed_ips - .iter() - .map(|ip_addr| { - IpNetwork::from_str(ip_addr) - .map_err(|e| anyhow!("Error parsing IP Network {}: {}", ip_addr, e)) - }) - .collect::>>()?, - }) - }) - .collect::>>()?; - WgInterface::new(wg_peers) - } -} - -impl Default for Config { - fn default() -> Self { - Self { - interface: Interface { - private_key: "GNqIAOCRxjl/cicZyvkvpTklgQuUmGUIEkH7IXF/sEE=".into(), - address: "10.13.13.2/24".into(), - listen_port: 51820, - dns: Default::default(), - mtu: Default::default(), - }, - peers: vec![Peer { - endpoint: "wg.burrow.rs:51820".into(), - allowed_ips: vec!["8.8.8.8/32".into(), "0.0.0.0/0".into()], - public_key: "uy75leriJay0+oHLhRMpV+A5xAQ0hCJ+q7Ww81AOvT4=".into(), - preshared_key: Some("s7lx/mg+reVEMnGnqeyYOQkzD86n2+gYnx1M9ygi08k=".into()), - persistent_keepalive: Default::default(), - name: Default::default(), - }], - } - } -} diff --git a/burrow/src/wireguard/iface.rs b/burrow/src/wireguard/iface.rs deleted file mode 100755 index ba175de..0000000 --- a/burrow/src/wireguard/iface.rs +++ /dev/null @@ -1,181 +0,0 @@ -use std::{net::IpAddr, sync::Arc}; - -use anyhow::Error; -use fehler::throws; -use futures::future::join_all; -use ip_network_table::IpNetworkTable; -use tokio::sync::RwLock; -use tracing::{debug, error}; -use tun::tokio::TunInterface; - -use super::{noise::Tunnel, Peer, PeerPcb}; - -struct IndexedPcbs { - pcbs: Vec>, - allowed_ips: IpNetworkTable, -} - -impl IndexedPcbs { - pub fn new() -> Self { - Self { - pcbs: vec![], - allowed_ips: IpNetworkTable::new(), - } - } - - pub fn insert(&mut self, pcb: PeerPcb) { - let idx: usize = self.pcbs.len(); - for allowed_ip in pcb.allowed_ips.iter() { - self.allowed_ips.insert(*allowed_ip, idx); - } - self.pcbs.insert(idx, Arc::new(pcb)); - } - - pub fn find(&self, addr: IpAddr) -> Option { - let (_, &idx) = self.allowed_ips.longest_match(addr)?; - Some(idx) - } -} - -impl FromIterator for IndexedPcbs { - fn from_iter>(iter: I) -> Self { - iter.into_iter().fold(Self::new(), |mut acc, pcb| { - acc.insert(pcb); - acc - }) - } -} - -pub struct Interface { - tun: Option>>, - pcbs: Arc, -} - -impl Interface { - #[throws] - pub fn new>(peers: I) -> Self { - let pcbs: IndexedPcbs = peers - .into_iter() - .map(PeerPcb::new) - .collect::>()?; - - let pcbs = Arc::new(pcbs); - Self { pcbs, tun: None } - } - - pub fn set_tun(&mut self, tun: Arc>) { - self.tun = Some(tun); - } - - pub async fn run(&self) -> anyhow::Result<()> { - let pcbs = self.pcbs.clone(); - let tun = self - .tun - .clone() - .ok_or(anyhow::anyhow!("tun interface does not exist"))?; - log::info!("Starting interface"); - - let outgoing = async move { - loop { - let mut buf = [0u8; 3000]; - - let src = { - let src = match tun.read().await.recv(&mut buf[..]).await { - Ok(len) => &buf[..len], - Err(e) => { - error!("Failed to read from interface: {}", e); - continue - } - }; - debug!("Read {} bytes from interface", src.len()); - src - }; - - let dst_addr = match Tunnel::dst_address(src) { - Some(addr) => addr, - None => { - debug!("No destination found"); - continue - } - }; - - debug!("Routing packet to {}", dst_addr); - - let Some(idx) = pcbs.find(dst_addr) else { - continue - }; - - debug!("Found peer:{}", idx); - - match pcbs.pcbs[idx].send(src).await { - Ok(..) => { - let addr = pcbs.pcbs[idx].endpoint; - debug!("Sent packet to peer {}", addr); - } - Err(e) => { - log::error!("Failed to send packet {}", e); - continue - } - }; - } - }; - - let mut tsks = vec![]; - let tun = self - .tun - .clone() - .ok_or(anyhow::anyhow!("tun interface does not exist"))?; - let outgoing = tokio::task::spawn(outgoing); - tsks.push(outgoing); - debug!("preparing to spawn read tasks"); - - { - let pcbs = &self.pcbs; - for i in 0..pcbs.pcbs.len() { - debug!("spawning read task for peer {}", i); - let pcb = pcbs.pcbs[i].clone(); - let tun = tun.clone(); - let main_tsk = async move { - if let Err(e) = pcb.open_if_closed().await { - log::error!("failed to open pcb: {}", e); - return - } - let r2 = pcb.run(tun).await; - if let Err(e) = r2 { - log::error!("failed to run pcb: {}", e); - } else { - debug!("pcb ran successfully"); - } - }; - - let pcb = pcbs.pcbs[i].clone(); - let update_timers_tsk = async move { - let mut buf = [0u8; 65535]; - loop { - tokio::time::sleep(tokio::time::Duration::from_millis(250)).await; - pcb.update_timers(&mut buf).await; - } - }; - - let pcb = pcbs.pcbs[i].clone(); - let reset_rate_limiter_tsk = async move { - loop { - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - pcb.reset_rate_limiter().await; - } - }; - tsks.extend(vec![ - tokio::spawn(main_tsk), - tokio::spawn(update_timers_tsk), - tokio::spawn(reset_rate_limiter_tsk) - ]); - debug!("task made.."); - } - debug!("spawned read tasks"); - } - debug!("preparing to join.."); - join_all(tsks).await; - debug!("joined!"); - Ok(()) - } -} diff --git a/burrow/src/wireguard/mod.rs b/burrow/src/wireguard/mod.rs deleted file mode 100755 index b2e7b54..0000000 --- a/burrow/src/wireguard/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod config; -mod iface; -mod noise; -mod pcb; -mod peer; - -pub use config::Config; -pub use iface::Interface; -pub use pcb::PeerPcb; -pub use peer::Peer; -pub use x25519_dalek::{PublicKey, StaticSecret}; diff --git a/burrow/src/wireguard/noise/errors.rs b/burrow/src/wireguard/noise/errors.rs deleted file mode 100755 index e196635..0000000 --- a/burrow/src/wireguard/noise/errors.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#[derive(Debug)] -pub enum WireGuardError { - DestinationBufferTooSmall, - UnexpectedPacket, - WrongIndex, - WrongKey, - InvalidTai64nTimestamp, - WrongTai64nTimestamp, - InvalidMac, - InvalidAeadTag, - InvalidCounter, - DuplicateCounter, - InvalidPacket, - NoCurrentSession, - ConnectionExpired, - UnderLoad, -} diff --git a/burrow/src/wireguard/noise/handshake.rs b/burrow/src/wireguard/noise/handshake.rs deleted file mode 100755 index 2ec0c6a..0000000 --- a/burrow/src/wireguard/noise/handshake.rs +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -use std::{ - convert::TryInto, - time::{Duration, Instant, SystemTime}, -}; - -use aead::{Aead, Payload}; -use blake2::{ - digest::{FixedOutput, KeyInit}, - Blake2s256, - Blake2sMac, - Digest, -}; -use chacha20poly1305::XChaCha20Poly1305; -use rand_core::OsRng; -use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; - -use super::{ - errors::WireGuardError, - session::Session, - x25519, - HandshakeInit, - HandshakeResponse, - PacketCookieReply, -}; - -pub(crate) const LABEL_MAC1: &[u8; 8] = b"mac1----"; -pub(crate) const LABEL_COOKIE: &[u8; 8] = b"cookie--"; -const KEY_LEN: usize = 32; -const TIMESTAMP_LEN: usize = 12; - -// initiator.chaining_key = HASH(CONSTRUCTION) -const INITIAL_CHAIN_KEY: [u8; KEY_LEN] = [ - 96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248, - 114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54, -]; - -// initiator.chaining_hash = HASH(initiator.chaining_key || IDENTIFIER) -const INITIAL_CHAIN_HASH: [u8; KEY_LEN] = [ - 34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34, - 147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243, -]; - -#[inline] -pub(crate) fn b2s_hash(data1: &[u8], data2: &[u8]) -> [u8; 32] { - let mut hash = Blake2s256::new(); - hash.update(data1); - hash.update(data2); - hash.finalize().into() -} - -#[inline] -/// RFC 2401 HMAC+Blake2s, not to be confused with *keyed* Blake2s -pub(crate) fn b2s_hmac(key: &[u8], data1: &[u8]) -> [u8; 32] { - use blake2::digest::Update; - type HmacBlake2s = hmac::SimpleHmac; - let mut hmac = HmacBlake2s::new_from_slice(key).unwrap(); - hmac.update(data1); - hmac.finalize_fixed().into() -} - -#[inline] -/// Like b2s_hmac, but chain data1 and data2 together -pub(crate) fn b2s_hmac2(key: &[u8], data1: &[u8], data2: &[u8]) -> [u8; 32] { - use blake2::digest::Update; - type HmacBlake2s = hmac::SimpleHmac; - let mut hmac = HmacBlake2s::new_from_slice(key).unwrap(); - hmac.update(data1); - hmac.update(data2); - hmac.finalize_fixed().into() -} - -#[inline] -pub(crate) fn b2s_keyed_mac_16(key: &[u8], data1: &[u8]) -> [u8; 16] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); - blake2::digest::Update::update(&mut hmac, data1); - hmac.finalize_fixed().into() -} - -#[inline] -pub(crate) fn b2s_keyed_mac_16_2(key: &[u8], data1: &[u8], data2: &[u8]) -> [u8; 16] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); - blake2::digest::Update::update(&mut hmac, data1); - blake2::digest::Update::update(&mut hmac, data2); - hmac.finalize_fixed().into() -} - -pub(crate) fn b2s_mac_24(key: &[u8], data1: &[u8]) -> [u8; 24] { - let mut hmac = Blake2sMac::new_from_slice(key).unwrap(); - blake2::digest::Update::update(&mut hmac, data1); - hmac.finalize_fixed().into() -} - -#[inline] -/// This wrapper involves an extra copy and MAY BE SLOWER -fn aead_chacha20_seal(ciphertext: &mut [u8], key: &[u8], counter: u64, data: &[u8], aad: &[u8]) { - let mut nonce: [u8; 12] = [0; 12]; - nonce[4..12].copy_from_slice(&counter.to_le_bytes()); - - aead_chacha20_seal_inner(ciphertext, key, nonce, data, aad) -} - -#[inline] -fn aead_chacha20_seal_inner( - ciphertext: &mut [u8], - key: &[u8], - nonce: [u8; 12], - data: &[u8], - aad: &[u8], -) { - let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, key).unwrap()); - - ciphertext[..data.len()].copy_from_slice(data); - - let tag = key - .seal_in_place_separate_tag( - Nonce::assume_unique_for_key(nonce), - Aad::from(aad), - &mut ciphertext[..data.len()], - ) - .unwrap(); - - ciphertext[data.len()..].copy_from_slice(tag.as_ref()); -} - -#[inline] -/// This wrapper involves an extra copy and MAY BE SLOWER -fn aead_chacha20_open( - buffer: &mut [u8], - key: &[u8], - counter: u64, - data: &[u8], - aad: &[u8], -) -> Result<(), WireGuardError> { - let mut nonce: [u8; 12] = [0; 12]; - nonce[4..].copy_from_slice(&counter.to_le_bytes()); - aead_chacha20_open_inner(buffer, key, nonce, data, aad) - .map_err(|_| WireGuardError::InvalidAeadTag)?; - Ok(()) -} - -#[inline] -fn aead_chacha20_open_inner( - buffer: &mut [u8], - key: &[u8], - nonce: [u8; 12], - data: &[u8], - aad: &[u8], -) -> Result<(), ring::error::Unspecified> { - let key = LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, key).unwrap()); - - let mut inner_buffer = data.to_owned(); - - let plaintext = key.open_in_place( - Nonce::assume_unique_for_key(nonce), - Aad::from(aad), - &mut inner_buffer, - )?; - - buffer.copy_from_slice(plaintext); - - Ok(()) -} - -#[derive(Debug)] -/// This struct represents a 12 byte [Tai64N](https://cr.yp.to/libtai/tai64.html) timestamp -struct Tai64N { - secs: u64, - nano: u32, -} - -#[derive(Debug)] -/// This struct computes a [Tai64N](https://cr.yp.to/libtai/tai64.html) timestamp from current system time -struct TimeStamper { - duration_at_start: Duration, - instant_at_start: Instant, -} - -impl TimeStamper { - /// Create a new TimeStamper - pub fn new() -> TimeStamper { - TimeStamper { - duration_at_start: SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH) - .unwrap(), - instant_at_start: Instant::now(), - } - } - - /// Take time reading and generate a 12 byte timestamp - pub fn stamp(&self) -> [u8; 12] { - const TAI64_BASE: u64 = (1u64 << 62) + 37; - let mut ext_stamp = [0u8; 12]; - let stamp = Instant::now().duration_since(self.instant_at_start) + self.duration_at_start; - ext_stamp[0..8].copy_from_slice(&(stamp.as_secs() + TAI64_BASE).to_be_bytes()); - ext_stamp[8..12].copy_from_slice(&stamp.subsec_nanos().to_be_bytes()); - ext_stamp - } -} - -impl Tai64N { - /// A zeroed out timestamp - fn zero() -> Tai64N { - Tai64N { secs: 0, nano: 0 } - } - - /// Parse a timestamp from a 12 byte u8 slice - fn parse(buf: &[u8; 12]) -> Result { - if buf.len() < 12 { - return Err(WireGuardError::InvalidTai64nTimestamp) - } - - let (sec_bytes, nano_bytes) = buf.split_at(std::mem::size_of::()); - let secs = u64::from_be_bytes(sec_bytes.try_into().unwrap()); - let nano = u32::from_be_bytes(nano_bytes.try_into().unwrap()); - - // WireGuard does not actually expect tai64n timestamp, just monotonically - // increasing one if secs < (1u64 << 62) || secs >= (1u64 << 63) { - // return Err(WireGuardError::InvalidTai64nTimestamp); - //}; - // if nano >= 1_000_000_000 { - // return Err(WireGuardError::InvalidTai64nTimestamp); - //} - - Ok(Tai64N { secs, nano }) - } - - /// Check if this timestamp represents a time that is chronologically after - /// the time represented by the other timestamp - pub fn after(&self, other: &Tai64N) -> bool { - (self.secs > other.secs) || ((self.secs == other.secs) && (self.nano > other.nano)) - } -} - -/// Parameters used by the noise protocol -struct NoiseParams { - /// Our static public key - static_public: x25519::PublicKey, - /// Our static private key - static_private: x25519::StaticSecret, - /// Static public key of the other party - peer_static_public: x25519::PublicKey, - /// A shared key = DH(static_private, peer_static_public) - static_shared: x25519::SharedSecret, - /// A pre-computation of HASH("mac1----", peer_static_public) for this peer - sending_mac1_key: [u8; KEY_LEN], - /// An optional preshared key - preshared_key: Option<[u8; KEY_LEN]>, -} - -impl std::fmt::Debug for NoiseParams { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("NoiseParams") - .field("static_public", &self.static_public) - .field("static_private", &"") - .field("peer_static_public", &self.peer_static_public) - .field("static_shared", &"") - .field("sending_mac1_key", &self.sending_mac1_key) - .field("preshared_key", &self.preshared_key) - .finish() - } -} - -struct HandshakeInitSentState { - local_index: u32, - hash: [u8; KEY_LEN], - chaining_key: [u8; KEY_LEN], - ephemeral_private: x25519::ReusableSecret, - time_sent: Instant, -} - -impl std::fmt::Debug for HandshakeInitSentState { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("HandshakeInitSentState") - .field("local_index", &self.local_index) - .field("hash", &self.hash) - .field("chaining_key", &self.chaining_key) - .field("ephemeral_private", &"") - .field("time_sent", &self.time_sent) - .finish() - } -} - -#[derive(Debug)] -enum HandshakeState { - /// No handshake in process - None, - /// We initiated the handshake - InitSent(HandshakeInitSentState), - /// Handshake initiated by peer - InitReceived { - hash: [u8; KEY_LEN], - chaining_key: [u8; KEY_LEN], - peer_ephemeral_public: x25519::PublicKey, - peer_index: u32, - }, - /// Handshake was established too long ago (implies no handshake is in - /// progress) - Expired, -} - -#[derive(Debug)] -pub struct Handshake { - params: NoiseParams, - /// Index of the next session - next_index: u32, - /// Allow to have two outgoing handshakes in flight, because sometimes we - /// may receive a delayed response to a handshake with bad networks - previous: HandshakeState, - /// Current handshake state - state: HandshakeState, - cookies: Cookies, - /// The timestamp of the last handshake we received - last_handshake_timestamp: Tai64N, - // TODO: make TimeStamper a singleton - stamper: TimeStamper, - pub(super) last_rtt: Option, -} - -#[derive(Default, Debug)] -struct Cookies { - last_mac1: Option<[u8; 16]>, - index: u32, - write_cookie: Option<[u8; 16]>, -} - -#[derive(Debug)] -pub struct HalfHandshake { - pub peer_index: u32, - pub peer_static_public: [u8; 32], -} - -pub fn parse_handshake_anon( - static_private: &x25519::StaticSecret, - static_public: &x25519::PublicKey, - packet: &HandshakeInit, -) -> Result { - let peer_index = packet.sender_idx; - // initiator.chaining_key = HASH(CONSTRUCTION) - let mut chaining_key = INITIAL_CHAIN_KEY; - // initiator.hash = HASH(HASH(initiator.chaining_key || IDENTIFIER) || - // responder.static_public) - let mut hash = INITIAL_CHAIN_HASH; - hash = b2s_hash(&hash, static_public.as_bytes()); - // msg.unencrypted_ephemeral = DH_PUBKEY(initiator.ephemeral_private) - let peer_ephemeral_public = x25519::PublicKey::from(*packet.unencrypted_ephemeral); - // initiator.hash = HASH(initiator.hash || msg.unencrypted_ephemeral) - hash = b2s_hash(&hash, peer_ephemeral_public.as_bytes()); - // temp = HMAC(initiator.chaining_key, msg.unencrypted_ephemeral) - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac( - &b2s_hmac(&chaining_key, peer_ephemeral_public.as_bytes()), - &[0x01], - ); - // temp = HMAC(initiator.chaining_key, DH(initiator.ephemeral_private, - // responder.static_public)) - let ephemeral_shared = static_private.diffie_hellman(&peer_ephemeral_public); - let temp = b2s_hmac(&chaining_key, &ephemeral_shared.to_bytes()); - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // key = HMAC(temp, initiator.chaining_key || 0x2) - let key = b2s_hmac2(&temp, &chaining_key, &[0x02]); - - let mut peer_static_public = [0u8; KEY_LEN]; - // msg.encrypted_static = AEAD(key, 0, initiator.static_public, initiator.hash) - aead_chacha20_open( - &mut peer_static_public, - &key, - 0, - packet.encrypted_static, - &hash, - )?; - - Ok(HalfHandshake { peer_index, peer_static_public }) -} - -impl NoiseParams { - /// New noise params struct from our secret key, peers public key, and - /// optional preshared key - fn new( - static_private: x25519::StaticSecret, - static_public: x25519::PublicKey, - peer_static_public: x25519::PublicKey, - preshared_key: Option<[u8; 32]>, - ) -> Result { - let static_shared = static_private.diffie_hellman(&peer_static_public); - - let initial_sending_mac_key = b2s_hash(LABEL_MAC1, peer_static_public.as_bytes()); - - Ok(NoiseParams { - static_public, - static_private, - peer_static_public, - static_shared, - sending_mac1_key: initial_sending_mac_key, - preshared_key, - }) - } - - /// Set a new private key - fn set_static_private( - &mut self, - static_private: x25519::StaticSecret, - static_public: x25519::PublicKey, - ) -> Result<(), WireGuardError> { - // Check that the public key indeed matches the private key - let check_key = x25519::PublicKey::from(&static_private); - assert_eq!(check_key.as_bytes(), static_public.as_bytes()); - - self.static_private = static_private; - self.static_public = static_public; - - self.static_shared = self.static_private.diffie_hellman(&self.peer_static_public); - Ok(()) - } -} - -impl Handshake { - pub(crate) fn new( - static_private: x25519::StaticSecret, - static_public: x25519::PublicKey, - peer_static_public: x25519::PublicKey, - global_idx: u32, - preshared_key: Option<[u8; 32]>, - ) -> Result { - let params = NoiseParams::new( - static_private, - static_public, - peer_static_public, - preshared_key, - )?; - - Ok(Handshake { - params, - next_index: global_idx, - previous: HandshakeState::None, - state: HandshakeState::None, - last_handshake_timestamp: Tai64N::zero(), - stamper: TimeStamper::new(), - cookies: Default::default(), - last_rtt: None, - }) - } - - pub(crate) fn is_in_progress(&self) -> bool { - !matches!(self.state, HandshakeState::None | HandshakeState::Expired) - } - - pub(crate) fn timer(&self) -> Option { - match self.state { - HandshakeState::InitSent(HandshakeInitSentState { time_sent, .. }) => Some(time_sent), - _ => None, - } - } - - pub(crate) fn set_expired(&mut self) { - self.previous = HandshakeState::Expired; - self.state = HandshakeState::Expired; - } - - pub(crate) fn is_expired(&self) -> bool { - matches!(self.state, HandshakeState::Expired) - } - - pub(crate) fn has_cookie(&self) -> bool { - self.cookies.write_cookie.is_some() - } - - pub(crate) fn clear_cookie(&mut self) { - self.cookies.write_cookie = None; - } - - // The index used is 24 bits for peer index, allowing for 16M active peers per - // server and 8 bits for cyclic session index - fn inc_index(&mut self) -> u32 { - let index = self.next_index; - let idx8 = index as u8; - self.next_index = (index & !0xff) | u32::from(idx8.wrapping_add(1)); - self.next_index - } - - pub(crate) fn set_static_private( - &mut self, - private_key: x25519::StaticSecret, - public_key: x25519::PublicKey, - ) -> Result<(), WireGuardError> { - self.params.set_static_private(private_key, public_key) - } - - pub(super) fn receive_handshake_initialization<'a>( - &mut self, - packet: HandshakeInit, - dst: &'a mut [u8], - ) -> Result<(&'a mut [u8], Session), WireGuardError> { - // initiator.chaining_key = HASH(CONSTRUCTION) - let mut chaining_key = INITIAL_CHAIN_KEY; - // initiator.hash = HASH(HASH(initiator.chaining_key || IDENTIFIER) || - // responder.static_public) - let mut hash = INITIAL_CHAIN_HASH; - hash = b2s_hash(&hash, self.params.static_public.as_bytes()); - // msg.sender_index = little_endian(initiator.sender_index) - let peer_index = packet.sender_idx; - // msg.unencrypted_ephemeral = DH_PUBKEY(initiator.ephemeral_private) - let peer_ephemeral_public = x25519::PublicKey::from(*packet.unencrypted_ephemeral); - // initiator.hash = HASH(initiator.hash || msg.unencrypted_ephemeral) - hash = b2s_hash(&hash, peer_ephemeral_public.as_bytes()); - // temp = HMAC(initiator.chaining_key, msg.unencrypted_ephemeral) - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac( - &b2s_hmac(&chaining_key, peer_ephemeral_public.as_bytes()), - &[0x01], - ); - // temp = HMAC(initiator.chaining_key, DH(initiator.ephemeral_private, - // responder.static_public)) - let ephemeral_shared = self - .params - .static_private - .diffie_hellman(&peer_ephemeral_public); - let temp = b2s_hmac(&chaining_key, &ephemeral_shared.to_bytes()); - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // key = HMAC(temp, initiator.chaining_key || 0x2) - let key = b2s_hmac2(&temp, &chaining_key, &[0x02]); - - let mut peer_static_public_decrypted = [0u8; KEY_LEN]; - // msg.encrypted_static = AEAD(key, 0, initiator.static_public, initiator.hash) - aead_chacha20_open( - &mut peer_static_public_decrypted, - &key, - 0, - packet.encrypted_static, - &hash, - )?; - - ring::constant_time::verify_slices_are_equal( - self.params.peer_static_public.as_bytes(), - &peer_static_public_decrypted, - ) - .map_err(|_| WireGuardError::WrongKey)?; - - // initiator.hash = HASH(initiator.hash || msg.encrypted_static) - hash = b2s_hash(&hash, packet.encrypted_static); - // temp = HMAC(initiator.chaining_key, DH(initiator.static_private, - // responder.static_public)) - let temp = b2s_hmac(&chaining_key, self.params.static_shared.as_bytes()); - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // key = HMAC(temp, initiator.chaining_key || 0x2) - let key = b2s_hmac2(&temp, &chaining_key, &[0x02]); - // msg.encrypted_timestamp = AEAD(key, 0, TAI64N(), initiator.hash) - let mut timestamp = [0u8; TIMESTAMP_LEN]; - aead_chacha20_open(&mut timestamp, &key, 0, packet.encrypted_timestamp, &hash)?; - - let timestamp = Tai64N::parse(×tamp)?; - if !timestamp.after(&self.last_handshake_timestamp) { - // Possibly a replay - return Err(WireGuardError::WrongTai64nTimestamp) - } - self.last_handshake_timestamp = timestamp; - - // initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp) - hash = b2s_hash(&hash, packet.encrypted_timestamp); - - self.previous = std::mem::replace(&mut self.state, HandshakeState::InitReceived { - chaining_key, - hash, - peer_ephemeral_public, - peer_index, - }); - - self.format_handshake_response(dst) - } - - pub(super) fn receive_handshake_response( - &mut self, - packet: HandshakeResponse, - ) -> Result { - // Check if there is a handshake awaiting a response and return the correct one - let (state, is_previous) = match (&self.state, &self.previous) { - (HandshakeState::InitSent(s), _) if s.local_index == packet.receiver_idx => (s, false), - (_, HandshakeState::InitSent(s)) if s.local_index == packet.receiver_idx => (s, true), - _ => return Err(WireGuardError::UnexpectedPacket), - }; - - let peer_index = packet.sender_idx; - let local_index = state.local_index; - - let unencrypted_ephemeral = x25519::PublicKey::from(*packet.unencrypted_ephemeral); - // msg.unencrypted_ephemeral = DH_PUBKEY(responder.ephemeral_private) - // responder.hash = HASH(responder.hash || msg.unencrypted_ephemeral) - let mut hash = b2s_hash(&state.hash, unencrypted_ephemeral.as_bytes()); - // temp = HMAC(responder.chaining_key, msg.unencrypted_ephemeral) - let temp = b2s_hmac(&state.chaining_key, unencrypted_ephemeral.as_bytes()); - // responder.chaining_key = HMAC(temp, 0x1) - let mut chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, DH(responder.ephemeral_private, - // initiator.ephemeral_public)) - let ephemeral_shared = state - .ephemeral_private - .diffie_hellman(&unencrypted_ephemeral); - let temp = b2s_hmac(&chaining_key, &ephemeral_shared.to_bytes()); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, DH(responder.ephemeral_private, - // initiator.static_public)) - let temp = b2s_hmac( - &chaining_key, - &self - .params - .static_private - .diffie_hellman(&unencrypted_ephemeral) - .to_bytes(), - ); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, preshared_key) - let temp = b2s_hmac( - &chaining_key, - &self.params.preshared_key.unwrap_or([0u8; 32])[..], - ); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp2 = HMAC(temp, responder.chaining_key || 0x2) - let temp2 = b2s_hmac2(&temp, &chaining_key, &[0x02]); - // key = HMAC(temp, temp2 || 0x3) - let key = b2s_hmac2(&temp, &temp2, &[0x03]); - // responder.hash = HASH(responder.hash || temp2) - hash = b2s_hash(&hash, &temp2); - // msg.encrypted_nothing = AEAD(key, 0, [empty], responder.hash) - aead_chacha20_open(&mut [], &key, 0, packet.encrypted_nothing, &hash)?; - - // responder.hash = HASH(responder.hash || msg.encrypted_nothing) - // hash = b2s_hash(hash, buf[ENC_NOTHING_OFF..ENC_NOTHING_OFF + - // ENC_NOTHING_SZ]); - - // Derive keys - // temp1 = HMAC(initiator.chaining_key, [empty]) - // temp2 = HMAC(temp1, 0x1) - // temp3 = HMAC(temp1, temp2 || 0x2) - // initiator.sending_key = temp2 - // initiator.receiving_key = temp3 - // initiator.sending_key_counter = 0 - // initiator.receiving_key_counter = 0 - let temp1 = b2s_hmac(&chaining_key, &[]); - let temp2 = b2s_hmac(&temp1, &[0x01]); - let temp3 = b2s_hmac2(&temp1, &temp2, &[0x02]); - - let rtt_time = Instant::now().duration_since(state.time_sent); - self.last_rtt = Some(rtt_time.as_millis() as u32); - - if is_previous { - self.previous = HandshakeState::None; - } else { - self.state = HandshakeState::None; - } - Ok(Session::new(local_index, peer_index, temp3, temp2)) - } - - pub(super) fn receive_cookie_reply( - &mut self, - packet: PacketCookieReply, - ) -> Result<(), WireGuardError> { - let mac1 = match self.cookies.last_mac1 { - Some(mac) => mac, - None => return Err(WireGuardError::UnexpectedPacket), - }; - - let local_index = self.cookies.index; - if packet.receiver_idx != local_index { - return Err(WireGuardError::WrongIndex) - } - // msg.encrypted_cookie = XAEAD(HASH(LABEL_COOKIE || responder.static_public), - // msg.nonce, cookie, last_received_msg.mac1) - let key = b2s_hash(LABEL_COOKIE, self.params.peer_static_public.as_bytes()); // TODO: pre-compute - - let payload = Payload { - aad: &mac1[0..16], - msg: packet.encrypted_cookie, - }; - let plaintext = XChaCha20Poly1305::new_from_slice(&key) - .unwrap() - .decrypt(packet.nonce.into(), payload) - .map_err(|_| WireGuardError::InvalidAeadTag)?; - - let cookie = plaintext - .try_into() - .map_err(|_| WireGuardError::InvalidPacket)?; - self.cookies.write_cookie = Some(cookie); - Ok(()) - } - - // Compute and append mac1 and mac2 to a handshake message - fn append_mac1_and_mac2<'a>( - &mut self, - local_index: u32, - dst: &'a mut [u8], - ) -> Result<&'a mut [u8], WireGuardError> { - let mac1_off = dst.len() - 32; - let mac2_off = dst.len() - 16; - - // msg.mac1 = MAC(HASH(LABEL_MAC1 || responder.static_public), - // msg[0:offsetof(msg.mac1)]) - let msg_mac1 = b2s_keyed_mac_16(&self.params.sending_mac1_key, &dst[..mac1_off]); - - dst[mac1_off..mac2_off].copy_from_slice(&msg_mac1[..]); - - // msg.mac2 = MAC(initiator.last_received_cookie, msg[0:offsetof(msg.mac2)]) - let msg_mac2: [u8; 16] = if let Some(cookie) = self.cookies.write_cookie { - b2s_keyed_mac_16(&cookie, &dst[..mac2_off]) - } else { - [0u8; 16] - }; - - dst[mac2_off..].copy_from_slice(&msg_mac2[..]); - - self.cookies.index = local_index; - self.cookies.last_mac1 = Some(msg_mac1); - Ok(dst) - } - - pub(super) fn format_handshake_initiation<'a>( - &mut self, - dst: &'a mut [u8], - ) -> Result<&'a mut [u8], WireGuardError> { - if dst.len() < super::HANDSHAKE_INIT_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) - } - - let (message_type, rest) = dst.split_at_mut(4); - let (sender_index, rest) = rest.split_at_mut(4); - let (unencrypted_ephemeral, rest) = rest.split_at_mut(32); - let (encrypted_static, rest) = rest.split_at_mut(32 + 16); - let (encrypted_timestamp, _) = rest.split_at_mut(12 + 16); - - let local_index = self.inc_index(); - - // initiator.chaining_key = HASH(CONSTRUCTION) - let mut chaining_key = INITIAL_CHAIN_KEY; - // initiator.hash = HASH(HASH(initiator.chaining_key || IDENTIFIER) || - // responder.static_public) - let mut hash = INITIAL_CHAIN_HASH; - hash = b2s_hash(&hash, self.params.peer_static_public.as_bytes()); - // initiator.ephemeral_private = DH_GENERATE() - let ephemeral_private = x25519::ReusableSecret::random_from_rng(OsRng); - // msg.message_type = 1 - // msg.reserved_zero = { 0, 0, 0 } - message_type.copy_from_slice(&super::HANDSHAKE_INIT.to_le_bytes()); - // msg.sender_index = little_endian(initiator.sender_index) - sender_index.copy_from_slice(&local_index.to_le_bytes()); - // msg.unencrypted_ephemeral = DH_PUBKEY(initiator.ephemeral_private) - unencrypted_ephemeral - .copy_from_slice(x25519::PublicKey::from(&ephemeral_private).as_bytes()); - // initiator.hash = HASH(initiator.hash || msg.unencrypted_ephemeral) - hash = b2s_hash(&hash, unencrypted_ephemeral); - // temp = HMAC(initiator.chaining_key, msg.unencrypted_ephemeral) - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&b2s_hmac(&chaining_key, unencrypted_ephemeral), &[0x01]); - // temp = HMAC(initiator.chaining_key, DH(initiator.ephemeral_private, - // responder.static_public)) - let ephemeral_shared = ephemeral_private.diffie_hellman(&self.params.peer_static_public); - let temp = b2s_hmac(&chaining_key, &ephemeral_shared.to_bytes()); - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // key = HMAC(temp, initiator.chaining_key || 0x2) - let key = b2s_hmac2(&temp, &chaining_key, &[0x02]); - // msg.encrypted_static = AEAD(key, 0, initiator.static_public, initiator.hash) - aead_chacha20_seal( - encrypted_static, - &key, - 0, - self.params.static_public.as_bytes(), - &hash, - ); - // initiator.hash = HASH(initiator.hash || msg.encrypted_static) - hash = b2s_hash(&hash, encrypted_static); - // temp = HMAC(initiator.chaining_key, DH(initiator.static_private, - // responder.static_public)) - let temp = b2s_hmac(&chaining_key, self.params.static_shared.as_bytes()); - // initiator.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // key = HMAC(temp, initiator.chaining_key || 0x2) - let key = b2s_hmac2(&temp, &chaining_key, &[0x02]); - // msg.encrypted_timestamp = AEAD(key, 0, TAI64N(), initiator.hash) - let timestamp = self.stamper.stamp(); - aead_chacha20_seal(encrypted_timestamp, &key, 0, ×tamp, &hash); - // initiator.hash = HASH(initiator.hash || msg.encrypted_timestamp) - hash = b2s_hash(&hash, encrypted_timestamp); - - let time_now = Instant::now(); - self.previous = std::mem::replace( - &mut self.state, - HandshakeState::InitSent(HandshakeInitSentState { - local_index, - chaining_key, - hash, - ephemeral_private, - time_sent: time_now, - }), - ); - - self.append_mac1_and_mac2(local_index, &mut dst[..super::HANDSHAKE_INIT_SZ]) - } - - fn format_handshake_response<'a>( - &mut self, - dst: &'a mut [u8], - ) -> Result<(&'a mut [u8], Session), WireGuardError> { - if dst.len() < super::HANDSHAKE_RESP_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) - } - - let state = std::mem::replace(&mut self.state, HandshakeState::None); - let (mut chaining_key, mut hash, peer_ephemeral_public, peer_index) = match state { - HandshakeState::InitReceived { - chaining_key, - hash, - peer_ephemeral_public, - peer_index, - } => (chaining_key, hash, peer_ephemeral_public, peer_index), - _ => { - panic!("Unexpected attempt to call send_handshake_response"); - } - }; - - let (message_type, rest) = dst.split_at_mut(4); - let (sender_index, rest) = rest.split_at_mut(4); - let (receiver_index, rest) = rest.split_at_mut(4); - let (unencrypted_ephemeral, rest) = rest.split_at_mut(32); - let (encrypted_nothing, _) = rest.split_at_mut(16); - - // responder.ephemeral_private = DH_GENERATE() - let ephemeral_private = x25519::ReusableSecret::random_from_rng(OsRng); - let local_index = self.inc_index(); - // msg.message_type = 2 - // msg.reserved_zero = { 0, 0, 0 } - message_type.copy_from_slice(&super::HANDSHAKE_RESP.to_le_bytes()); - // msg.sender_index = little_endian(responder.sender_index) - sender_index.copy_from_slice(&local_index.to_le_bytes()); - // msg.receiver_index = little_endian(initiator.sender_index) - receiver_index.copy_from_slice(&peer_index.to_le_bytes()); - // msg.unencrypted_ephemeral = DH_PUBKEY(initiator.ephemeral_private) - unencrypted_ephemeral - .copy_from_slice(x25519::PublicKey::from(&ephemeral_private).as_bytes()); - // responder.hash = HASH(responder.hash || msg.unencrypted_ephemeral) - hash = b2s_hash(&hash, unencrypted_ephemeral); - // temp = HMAC(responder.chaining_key, msg.unencrypted_ephemeral) - let temp = b2s_hmac(&chaining_key, unencrypted_ephemeral); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, DH(responder.ephemeral_private, - // initiator.ephemeral_public)) - let ephemeral_shared = ephemeral_private.diffie_hellman(&peer_ephemeral_public); - let temp = b2s_hmac(&chaining_key, &ephemeral_shared.to_bytes()); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, DH(responder.ephemeral_private, - // initiator.static_public)) - let temp = b2s_hmac( - &chaining_key, - &ephemeral_private - .diffie_hellman(&self.params.peer_static_public) - .to_bytes(), - ); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp = HMAC(responder.chaining_key, preshared_key) - let temp = b2s_hmac( - &chaining_key, - &self.params.preshared_key.unwrap_or([0u8; 32])[..], - ); - // responder.chaining_key = HMAC(temp, 0x1) - chaining_key = b2s_hmac(&temp, &[0x01]); - // temp2 = HMAC(temp, responder.chaining_key || 0x2) - let temp2 = b2s_hmac2(&temp, &chaining_key, &[0x02]); - // key = HMAC(temp, temp2 || 0x3) - let key = b2s_hmac2(&temp, &temp2, &[0x03]); - // responder.hash = HASH(responder.hash || temp2) - hash = b2s_hash(&hash, &temp2); - // msg.encrypted_nothing = AEAD(key, 0, [empty], responder.hash) - aead_chacha20_seal(encrypted_nothing, &key, 0, &[], &hash); - - // Derive keys - // temp1 = HMAC(initiator.chaining_key, [empty]) - // temp2 = HMAC(temp1, 0x1) - // temp3 = HMAC(temp1, temp2 || 0x2) - // initiator.sending_key = temp2 - // initiator.receiving_key = temp3 - // initiator.sending_key_counter = 0 - // initiator.receiving_key_counter = 0 - let temp1 = b2s_hmac(&chaining_key, &[]); - let temp2 = b2s_hmac(&temp1, &[0x01]); - let temp3 = b2s_hmac2(&temp1, &temp2, &[0x02]); - - let dst = self.append_mac1_and_mac2(local_index, &mut dst[..super::HANDSHAKE_RESP_SZ])?; - - Ok((dst, Session::new(local_index, peer_index, temp2, temp3))) - } -} diff --git a/burrow/src/wireguard/noise/mod.rs b/burrow/src/wireguard/noise/mod.rs deleted file mode 100755 index 24f4fbb..0000000 --- a/burrow/src/wireguard/noise/mod.rs +++ /dev/null @@ -1,638 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -pub mod errors; -pub mod handshake; -pub mod rate_limiter; - -mod session; -mod timers; - -use std::{ - collections::VecDeque, - convert::{TryFrom, TryInto}, - net::{IpAddr, Ipv4Addr, Ipv6Addr}, - sync::Arc, - time::Duration, -}; - -use errors::WireGuardError; -use handshake::Handshake; -use rate_limiter::RateLimiter; -use timers::{TimerName, Timers}; - -/// The default value to use for rate limiting, when no other rate limiter is -/// defined -const PEER_HANDSHAKE_RATE_LIMIT: u64 = 10; - -const IPV4_MIN_HEADER_SIZE: usize = 20; -const IPV4_LEN_OFF: usize = 2; -const IPV4_SRC_IP_OFF: usize = 12; -const IPV4_DST_IP_OFF: usize = 16; -const IPV4_IP_SZ: usize = 4; - -const IPV6_MIN_HEADER_SIZE: usize = 40; -const IPV6_LEN_OFF: usize = 4; -const IPV6_SRC_IP_OFF: usize = 8; -const IPV6_DST_IP_OFF: usize = 24; -const IPV6_IP_SZ: usize = 16; - -const IP_LEN_SZ: usize = 2; - -const MAX_QUEUE_DEPTH: usize = 256; -/// number of sessions in the ring, better keep a PoT -const N_SESSIONS: usize = 8; - -pub mod x25519 { - pub use x25519_dalek::{ - EphemeralSecret, - PublicKey, - ReusableSecret, - SharedSecret, - StaticSecret, - }; -} - -#[derive(Debug)] -pub enum TunnResult<'a> { - Done, - Err(WireGuardError), - WriteToNetwork(&'a mut [u8]), - WriteToTunnelV4(&'a mut [u8], Ipv4Addr), - WriteToTunnelV6(&'a mut [u8], Ipv6Addr), -} - -impl<'a> From for TunnResult<'a> { - fn from(err: WireGuardError) -> TunnResult<'a> { - TunnResult::Err(err) - } -} - -/// Tunnel represents a point-to-point WireGuard connection -#[derive(Debug)] -pub struct Tunnel { - /// The handshake currently in progress - handshake: handshake::Handshake, - /// The N_SESSIONS most recent sessions, index is session id modulo - /// N_SESSIONS - sessions: [Option; N_SESSIONS], - /// Index of most recently used session - current: usize, - /// Queue to store blocked packets - packet_queue: VecDeque>, - /// Keeps tabs on the expiring timers - timers: timers::Timers, - tx_bytes: usize, - rx_bytes: usize, - rate_limiter: Arc, -} - -type MessageType = u32; -const HANDSHAKE_INIT: MessageType = 1; -const HANDSHAKE_RESP: MessageType = 2; -const COOKIE_REPLY: MessageType = 3; -const DATA: MessageType = 4; - -const HANDSHAKE_INIT_SZ: usize = 148; -const HANDSHAKE_RESP_SZ: usize = 92; -const COOKIE_REPLY_SZ: usize = 64; -const DATA_OVERHEAD_SZ: usize = 32; - -#[derive(Debug)] -pub struct HandshakeInit<'a> { - sender_idx: u32, - unencrypted_ephemeral: &'a [u8; 32], - encrypted_static: &'a [u8], - encrypted_timestamp: &'a [u8], -} - -#[derive(Debug)] -pub struct HandshakeResponse<'a> { - sender_idx: u32, - pub receiver_idx: u32, - unencrypted_ephemeral: &'a [u8; 32], - encrypted_nothing: &'a [u8], -} - -#[derive(Debug)] -pub struct PacketCookieReply<'a> { - pub receiver_idx: u32, - nonce: &'a [u8], - encrypted_cookie: &'a [u8], -} - -#[derive(Debug)] -pub struct PacketData<'a> { - pub receiver_idx: u32, - counter: u64, - encrypted_encapsulated_packet: &'a [u8], -} - -/// Describes a packet from network -#[derive(Debug)] -pub enum Packet<'a> { - HandshakeInit(HandshakeInit<'a>), - HandshakeResponse(HandshakeResponse<'a>), - CookieReply(PacketCookieReply<'a>), - Data(PacketData<'a>), -} - -impl Tunnel { - #[inline(always)] - pub fn parse_incoming_packet(src: &[u8]) -> Result { - if src.len() < 4 { - return Err(WireGuardError::InvalidPacket) - } - - // Checks the type, as well as the reserved zero fields - let packet_type = u32::from_le_bytes(src[0..4].try_into().unwrap()); - tracing::debug!("packet_type: {}", packet_type); - - Ok(match (packet_type, src.len()) { - (HANDSHAKE_INIT, HANDSHAKE_INIT_SZ) => Packet::HandshakeInit(HandshakeInit { - sender_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), - unencrypted_ephemeral: <&[u8; 32] as TryFrom<&[u8]>>::try_from(&src[8..40]) - .expect("length already checked above"), - encrypted_static: &src[40..88], - encrypted_timestamp: &src[88..116], - }), - (HANDSHAKE_RESP, HANDSHAKE_RESP_SZ) => Packet::HandshakeResponse(HandshakeResponse { - sender_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), - receiver_idx: u32::from_le_bytes(src[8..12].try_into().unwrap()), - unencrypted_ephemeral: <&[u8; 32] as TryFrom<&[u8]>>::try_from(&src[12..44]) - .expect("length already checked above"), - encrypted_nothing: &src[44..60], - }), - (COOKIE_REPLY, COOKIE_REPLY_SZ) => Packet::CookieReply(PacketCookieReply { - receiver_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), - nonce: &src[8..32], - encrypted_cookie: &src[32..64], - }), - (DATA, DATA_OVERHEAD_SZ..=std::usize::MAX) => Packet::Data(PacketData { - receiver_idx: u32::from_le_bytes(src[4..8].try_into().unwrap()), - counter: u64::from_le_bytes(src[8..16].try_into().unwrap()), - encrypted_encapsulated_packet: &src[16..], - }), - _ => return Err(WireGuardError::InvalidPacket), - }) - } - - pub fn is_expired(&self) -> bool { - self.handshake.is_expired() - } - - pub fn dst_address(packet: &[u8]) -> Option { - if packet.is_empty() { - return None - } - - match packet[0] >> 4 { - 4 if packet.len() >= IPV4_MIN_HEADER_SIZE => { - let addr_bytes: [u8; IPV4_IP_SZ] = packet - [IPV4_DST_IP_OFF..IPV4_DST_IP_OFF + IPV4_IP_SZ] - .try_into() - .unwrap(); - Some(IpAddr::from(addr_bytes)) - } - 6 if packet.len() >= IPV6_MIN_HEADER_SIZE => { - let addr_bytes: [u8; IPV6_IP_SZ] = packet - [IPV6_DST_IP_OFF..IPV6_DST_IP_OFF + IPV6_IP_SZ] - .try_into() - .unwrap(); - Some(IpAddr::from(addr_bytes)) - } - _ => None, - } - } - - pub fn src_address(packet: &[u8]) -> Option { - if packet.is_empty() { - return None - } - - match packet[0] >> 4 { - 4 if packet.len() >= IPV4_MIN_HEADER_SIZE => { - let addr_bytes: [u8; IPV4_IP_SZ] = packet - [IPV4_SRC_IP_OFF..IPV4_SRC_IP_OFF + IPV4_IP_SZ] - .try_into() - .unwrap(); - Some(IpAddr::from(addr_bytes)) - } - 6 if packet.len() >= IPV6_MIN_HEADER_SIZE => { - let addr_bytes: [u8; IPV6_IP_SZ] = packet - [IPV6_SRC_IP_OFF..IPV6_SRC_IP_OFF + IPV6_IP_SZ] - .try_into() - .unwrap(); - Some(IpAddr::from(addr_bytes)) - } - _ => None, - } - } - - /// Create a new tunnel using own private key and the peer public key - pub fn new( - static_private: x25519::StaticSecret, - peer_static_public: x25519::PublicKey, - preshared_key: Option<[u8; 32]>, - persistent_keepalive: Option, - index: u32, - rate_limiter: Option>, - ) -> Result { - let static_public = x25519::PublicKey::from(&static_private); - - let tunn = Tunnel { - handshake: Handshake::new( - static_private, - static_public, - peer_static_public, - index << 8, - preshared_key, - ) - .map_err(|_| "Invalid parameters")?, - sessions: Default::default(), - current: Default::default(), - tx_bytes: Default::default(), - rx_bytes: Default::default(), - - packet_queue: VecDeque::new(), - timers: Timers::new(persistent_keepalive, rate_limiter.is_none()), - - rate_limiter: rate_limiter.unwrap_or_else(|| { - Arc::new(RateLimiter::new(&static_public, PEER_HANDSHAKE_RATE_LIMIT)) - }), - }; - - Ok(tunn) - } - - /// Update the private key and clear existing sessions - pub fn set_static_private( - &mut self, - static_private: x25519::StaticSecret, - static_public: x25519::PublicKey, - rate_limiter: Option>, - ) -> Result<(), WireGuardError> { - self.timers.should_reset_rr = rate_limiter.is_none(); - self.rate_limiter = rate_limiter.unwrap_or_else(|| { - Arc::new(RateLimiter::new(&static_public, PEER_HANDSHAKE_RATE_LIMIT)) - }); - self.handshake - .set_static_private(static_private, static_public)?; - for s in &mut self.sessions { - *s = None; - } - Ok(()) - } - - /// Encapsulate a single packet from the tunnel interface. - /// Returns TunnResult. - /// - /// # Panics - /// Panics if dst buffer is too small. - /// Size of dst should be at least src.len() + 32, and no less than 148 - /// bytes. - pub fn encapsulate<'a>(&mut self, src: &[u8], dst: &'a mut [u8]) -> TunnResult<'a> { - let current = self.current; - if let Some(ref session) = self.sessions[current % N_SESSIONS] { - // Send the packet using an established session - let packet = session.format_packet_data(src, dst); - self.timer_tick(TimerName::TimeLastPacketSent); - // Exclude Keepalive packets from timer update. - if !src.is_empty() { - self.timer_tick(TimerName::TimeLastDataPacketSent); - } - self.tx_bytes += src.len(); - return TunnResult::WriteToNetwork(packet) - } - - // If there is no session, queue the packet for future retry - self.queue_packet(src); - // Initiate a new handshake if none is in progress - self.format_handshake_initiation(dst, false) - } - - /// Receives a UDP datagram from the network and parses it. - /// Returns TunnResult. - /// - /// If the result is of type TunnResult::WriteToNetwork, should repeat the - /// call with empty datagram, until TunnResult::Done is returned. If - /// batch processing packets, it is OK to defer until last - /// packet is processed. - pub fn decapsulate<'a>( - &mut self, - src_addr: Option, - datagram: &[u8], - dst: &'a mut [u8], - ) -> TunnResult<'a> { - if datagram.is_empty() { - // Indicates a repeated call - return self.send_queued_packet(dst) - } - - let mut cookie = [0u8; COOKIE_REPLY_SZ]; - let packet = match self - .rate_limiter - .verify_packet(src_addr, datagram, &mut cookie) - { - Ok(packet) => packet, - Err(TunnResult::WriteToNetwork(cookie)) => { - dst[..cookie.len()].copy_from_slice(cookie); - return TunnResult::WriteToNetwork(&mut dst[..cookie.len()]) - } - Err(TunnResult::Err(e)) => return TunnResult::Err(e), - _ => unreachable!(), - }; - - self.handle_verified_packet(packet, dst) - } - - pub fn reset_rate_limiter(&self) { - self.rate_limiter.reset_count(); - } - - pub(crate) fn handle_verified_packet<'a>( - &mut self, - packet: Packet, - dst: &'a mut [u8], - ) -> TunnResult<'a> { - match packet { - Packet::HandshakeInit(p) => self.handle_handshake_init(p, dst), - Packet::HandshakeResponse(p) => self.handle_handshake_response(p, dst), - Packet::CookieReply(p) => self.handle_cookie_reply(p), - Packet::Data(p) => self.handle_data(p, dst), - } - .unwrap_or_else(TunnResult::from) - } - - fn handle_handshake_init<'a>( - &mut self, - p: HandshakeInit, - dst: &'a mut [u8], - ) -> Result, WireGuardError> { - tracing::debug!( - message = "Received handshake_initiation", - remote_idx = p.sender_idx - ); - - let (packet, session) = self.handshake.receive_handshake_initialization(p, dst)?; - - // Store new session in ring buffer - let index = session.local_index(); - self.sessions[index % N_SESSIONS] = Some(session); - - self.timer_tick(TimerName::TimeLastPacketReceived); - self.timer_tick(TimerName::TimeLastPacketSent); - self.timer_tick_session_established(false, index); // New session established, we are not the initiator - - tracing::debug!(message = "Sending handshake_response", local_idx = index); - - Ok(TunnResult::WriteToNetwork(packet)) - } - - fn handle_handshake_response<'a>( - &mut self, - p: HandshakeResponse, - dst: &'a mut [u8], - ) -> Result, WireGuardError> { - tracing::debug!( - message = "Received handshake_response", - local_idx = p.receiver_idx, - remote_idx = p.sender_idx - ); - - let session = self.handshake.receive_handshake_response(p)?; - - let keepalive_packet = session.format_packet_data(&[], dst); - // Store new session in ring buffer - let l_idx = session.local_index(); - let index = l_idx % N_SESSIONS; - self.sessions[index] = Some(session); - - self.timer_tick(TimerName::TimeLastPacketReceived); - self.timer_tick_session_established(true, index); // New session established, we are the initiator - self.set_current_session(l_idx); - - tracing::debug!("Sending keepalive"); - - Ok(TunnResult::WriteToNetwork(keepalive_packet)) // Send a keepalive as - // a response - } - - fn handle_cookie_reply<'a>( - &mut self, - p: PacketCookieReply, - ) -> Result, WireGuardError> { - tracing::debug!( - message = "Received cookie_reply", - local_idx = p.receiver_idx - ); - - self.handshake.receive_cookie_reply(p)?; - self.timer_tick(TimerName::TimeLastPacketReceived); - self.timer_tick(TimerName::TimeCookieReceived); - - tracing::debug!("Did set cookie"); - - Ok(TunnResult::Done) - } - - /// Update the index of the currently used session, if needed - fn set_current_session(&mut self, new_idx: usize) { - let cur_idx = self.current; - if cur_idx == new_idx { - // There is nothing to do, already using this session, this is the common case - return - } - if self.sessions[cur_idx % N_SESSIONS].is_none() - || self.timers.session_timers[new_idx % N_SESSIONS] - >= self.timers.session_timers[cur_idx % N_SESSIONS] - { - self.current = new_idx; - tracing::debug!(message = "New session", session = new_idx); - } - } - - /// Decrypts a data packet, and stores the decapsulated packet in dst. - fn handle_data<'a>( - &mut self, - packet: PacketData, - dst: &'a mut [u8], - ) -> Result, WireGuardError> { - let r_idx = packet.receiver_idx as usize; - let idx = r_idx % N_SESSIONS; - - // Get the (probably) right session - let decapsulated_packet = { - let session = self.sessions[idx].as_ref(); - let session = session.ok_or_else(|| { - tracing::trace!(message = "No current session available", remote_idx = r_idx); - WireGuardError::NoCurrentSession - })?; - session.receive_packet_data(packet, dst)? - }; - - self.set_current_session(r_idx); - - self.timer_tick(TimerName::TimeLastPacketReceived); - - Ok(self.validate_decapsulated_packet(decapsulated_packet)) - } - - /// Formats a new handshake initiation message and store it in dst. If - /// force_resend is true will send a new handshake, even if a handshake - /// is already in progress (for example when a handshake times out) - pub fn format_handshake_initiation<'a>( - &mut self, - dst: &'a mut [u8], - force_resend: bool, - ) -> TunnResult<'a> { - if self.handshake.is_in_progress() && !force_resend { - return TunnResult::Done - } - - if self.handshake.is_expired() { - self.timers.clear(); - } - - let starting_new_handshake = !self.handshake.is_in_progress(); - - match self.handshake.format_handshake_initiation(dst) { - Ok(packet) => { - tracing::debug!("Sending handshake_initiation"); - - if starting_new_handshake { - self.timer_tick(TimerName::TimeLastHandshakeStarted); - } - self.timer_tick(TimerName::TimeLastPacketSent); - TunnResult::WriteToNetwork(packet) - } - Err(e) => TunnResult::Err(e), - } - } - - /// Check if an IP packet is v4 or v6, truncate to the length indicated by - /// the length field Returns the truncated packet and the source IP as - /// TunnResult - fn validate_decapsulated_packet<'a>(&mut self, packet: &'a mut [u8]) -> TunnResult<'a> { - let (computed_len, src_ip_address) = match packet.len() { - 0 => return TunnResult::Done, // This is keepalive, and not an error - _ if packet[0] >> 4 == 4 && packet.len() >= IPV4_MIN_HEADER_SIZE => { - let len_bytes: [u8; IP_LEN_SZ] = packet[IPV4_LEN_OFF..IPV4_LEN_OFF + IP_LEN_SZ] - .try_into() - .unwrap(); - let addr_bytes: [u8; IPV4_IP_SZ] = packet - [IPV4_SRC_IP_OFF..IPV4_SRC_IP_OFF + IPV4_IP_SZ] - .try_into() - .unwrap(); - ( - u16::from_be_bytes(len_bytes) as usize, - IpAddr::from(addr_bytes), - ) - } - _ if packet[0] >> 4 == 6 && packet.len() >= IPV6_MIN_HEADER_SIZE => { - let len_bytes: [u8; IP_LEN_SZ] = packet[IPV6_LEN_OFF..IPV6_LEN_OFF + IP_LEN_SZ] - .try_into() - .unwrap(); - let addr_bytes: [u8; IPV6_IP_SZ] = packet - [IPV6_SRC_IP_OFF..IPV6_SRC_IP_OFF + IPV6_IP_SZ] - .try_into() - .unwrap(); - ( - u16::from_be_bytes(len_bytes) as usize + IPV6_MIN_HEADER_SIZE, - IpAddr::from(addr_bytes), - ) - } - _ => return TunnResult::Err(WireGuardError::InvalidPacket), - }; - - if computed_len > packet.len() { - return TunnResult::Err(WireGuardError::InvalidPacket) - } - - self.timer_tick(TimerName::TimeLastDataPacketReceived); - self.rx_bytes += computed_len; - - match src_ip_address { - IpAddr::V4(addr) => TunnResult::WriteToTunnelV4(&mut packet[..computed_len], addr), - IpAddr::V6(addr) => TunnResult::WriteToTunnelV6(&mut packet[..computed_len], addr), - } - } - - /// Get a packet from the queue, and try to encapsulate it - fn send_queued_packet<'a>(&mut self, dst: &'a mut [u8]) -> TunnResult<'a> { - if let Some(packet) = self.dequeue_packet() { - match self.encapsulate(&packet, dst) { - TunnResult::Err(_) => { - // On error, return packet to the queue - self.requeue_packet(packet); - } - r => return r, - } - } - TunnResult::Done - } - - /// Push packet to the back of the queue - fn queue_packet(&mut self, packet: &[u8]) { - if self.packet_queue.len() < MAX_QUEUE_DEPTH { - // Drop if too many are already in queue - self.packet_queue.push_back(packet.to_vec()); - } - } - - /// Push packet to the front of the queue - fn requeue_packet(&mut self, packet: Vec) { - if self.packet_queue.len() < MAX_QUEUE_DEPTH { - // Drop if too many are already in queue - self.packet_queue.push_front(packet); - } - } - - fn dequeue_packet(&mut self) -> Option> { - self.packet_queue.pop_front() - } - - fn estimate_loss(&self) -> f32 { - let session_idx = self.current; - - let mut weight = 9.0; - let mut cur_avg = 0.0; - let mut total_weight = 0.0; - - for i in 0..N_SESSIONS { - if let Some(ref session) = self.sessions[(session_idx.wrapping_sub(i)) % N_SESSIONS] { - let (expected, received) = session.current_packet_cnt(); - - let loss = if expected == 0 { - 0.0 - } else { - 1.0 - received as f32 / expected as f32 - }; - - cur_avg += loss * weight; - total_weight += weight; - weight /= 3.0; - } - } - - if total_weight == 0.0 { - 0.0 - } else { - cur_avg / total_weight - } - } - - /// Return stats from the tunnel: - /// * Time since last handshake in seconds - /// * Data bytes sent - /// * Data bytes received - pub fn stats(&self) -> (Option, usize, usize, f32, Option) { - let time = self.time_since_last_handshake(); - let tx_bytes = self.tx_bytes; - let rx_bytes = self.rx_bytes; - let loss = self.estimate_loss(); - let rtt = self.handshake.last_rtt; - - (time, tx_bytes, rx_bytes, loss, rtt) - } -} diff --git a/burrow/src/wireguard/noise/rate_limiter.rs b/burrow/src/wireguard/noise/rate_limiter.rs deleted file mode 100755 index ff19efd..0000000 --- a/burrow/src/wireguard/noise/rate_limiter.rs +++ /dev/null @@ -1,212 +0,0 @@ -use std::{ - net::IpAddr, - sync::atomic::{AtomicU64, Ordering}, - time::Instant, -}; - -use aead::{generic_array::GenericArray, AeadInPlace, KeyInit}; -use chacha20poly1305::{Key, XChaCha20Poly1305}; -use parking_lot::Mutex; -use rand_core::{OsRng, RngCore}; -use ring::constant_time::verify_slices_are_equal; - -use super::{ - handshake::{ - b2s_hash, - b2s_keyed_mac_16, - b2s_keyed_mac_16_2, - b2s_mac_24, - LABEL_COOKIE, - LABEL_MAC1, - }, - HandshakeInit, - HandshakeResponse, - Packet, - TunnResult, - Tunnel, - WireGuardError, -}; - -const COOKIE_REFRESH: u64 = 128; // Use 128 and not 120 so the compiler can optimize out the division -const COOKIE_SIZE: usize = 16; -const COOKIE_NONCE_SIZE: usize = 24; - -/// How often should reset count in seconds -const RESET_PERIOD: u64 = 1; - -type Cookie = [u8; COOKIE_SIZE]; - -/// There are two places where WireGuard requires "randomness" for cookies -/// * The 24 byte nonce in the cookie massage - here the only goal is to avoid -/// nonce reuse -/// * A secret value that changes every two minutes -/// Because the main goal of the cookie is simply for a party to prove ownership -/// of an IP address we can relax the randomness definition a bit, in order to -/// avoid locking, because using less resources is the main goal of any DoS -/// prevention mechanism. In order to avoid locking and calls to rand we derive -/// pseudo random values using the AEAD and some counters. -#[derive(Debug)] -pub struct RateLimiter { - /// The key we use to derive the nonce - nonce_key: [u8; 32], - /// The key we use to derive the cookie - secret_key: [u8; 16], - start_time: Instant, - /// A single 64 bit counter (should suffice for many years) - nonce_ctr: AtomicU64, - mac1_key: [u8; 32], - cookie_key: Key, - limit: u64, - /// The counter since last reset - count: AtomicU64, - /// The time last reset was performed on this rate limiter - last_reset: Mutex, -} - -impl RateLimiter { - pub fn new(public_key: &super::x25519::PublicKey, limit: u64) -> Self { - let mut secret_key = [0u8; 16]; - OsRng.fill_bytes(&mut secret_key); - RateLimiter { - nonce_key: Self::rand_bytes(), - secret_key, - start_time: Instant::now(), - nonce_ctr: AtomicU64::new(0), - mac1_key: b2s_hash(LABEL_MAC1, public_key.as_bytes()), - cookie_key: b2s_hash(LABEL_COOKIE, public_key.as_bytes()).into(), - limit, - count: AtomicU64::new(0), - last_reset: Mutex::new(Instant::now()), - } - } - - fn rand_bytes() -> [u8; 32] { - let mut key = [0u8; 32]; - OsRng.fill_bytes(&mut key); - key - } - - /// Reset packet count (ideally should be called with a period of 1 second) - pub fn reset_count(&self) { - // The rate limiter is not very accurate, but at the scale we care about it - // doesn't matter much - let current_time = Instant::now(); - let mut last_reset_time = self.last_reset.lock(); - if current_time.duration_since(*last_reset_time).as_secs() >= RESET_PERIOD { - self.count.store(0, Ordering::SeqCst); - *last_reset_time = current_time; - } - } - - /// Compute the correct cookie value based on the current secret value and - /// the source IP - fn current_cookie(&self, addr: IpAddr) -> Cookie { - let mut addr_bytes = [0u8; 16]; - - match addr { - IpAddr::V4(a) => addr_bytes[..4].copy_from_slice(&a.octets()[..]), - IpAddr::V6(a) => addr_bytes[..].copy_from_slice(&a.octets()[..]), - } - - // The current cookie for a given IP is the - // MAC(responder.changing_secret_every_two_minutes, initiator.ip_address) - // First we derive the secret from the current time, the value of cur_counter - // would change with time. - let cur_counter = Instant::now().duration_since(self.start_time).as_secs() / COOKIE_REFRESH; - - // Next we derive the cookie - b2s_keyed_mac_16_2(&self.secret_key, &cur_counter.to_le_bytes(), &addr_bytes) - } - - fn nonce(&self) -> [u8; COOKIE_NONCE_SIZE] { - let ctr = self.nonce_ctr.fetch_add(1, Ordering::Relaxed); - - b2s_mac_24(&self.nonce_key, &ctr.to_le_bytes()) - } - - fn is_under_load(&self) -> bool { - self.count.fetch_add(1, Ordering::SeqCst) >= self.limit - } - - pub(crate) fn format_cookie_reply<'a>( - &self, - idx: u32, - cookie: Cookie, - mac1: &[u8], - dst: &'a mut [u8], - ) -> Result<&'a mut [u8], WireGuardError> { - if dst.len() < super::COOKIE_REPLY_SZ { - return Err(WireGuardError::DestinationBufferTooSmall) - } - - let (message_type, rest) = dst.split_at_mut(4); - let (receiver_index, rest) = rest.split_at_mut(4); - let (nonce, rest) = rest.split_at_mut(24); - let (encrypted_cookie, _) = rest.split_at_mut(16 + 16); - - // msg.message_type = 3 - // msg.reserved_zero = { 0, 0, 0 } - message_type.copy_from_slice(&super::COOKIE_REPLY.to_le_bytes()); - // msg.receiver_index = little_endian(initiator.sender_index) - receiver_index.copy_from_slice(&idx.to_le_bytes()); - nonce.copy_from_slice(&self.nonce()[..]); - - let cipher = XChaCha20Poly1305::new(&self.cookie_key); - - let iv = GenericArray::from_slice(nonce); - - encrypted_cookie[..16].copy_from_slice(&cookie); - let tag = cipher - .encrypt_in_place_detached(iv, mac1, &mut encrypted_cookie[..16]) - .map_err(|_| WireGuardError::DestinationBufferTooSmall)?; - - encrypted_cookie[16..].copy_from_slice(&tag); - - Ok(&mut dst[..super::COOKIE_REPLY_SZ]) - } - - /// Verify the MAC fields on the datagram, and apply rate limiting if needed - pub fn verify_packet<'a, 'b>( - &self, - src_addr: Option, - src: &'a [u8], - dst: &'b mut [u8], - ) -> Result, TunnResult<'b>> { - let packet = Tunnel::parse_incoming_packet(src)?; - tracing::debug!("packet: {:?}", packet); - - // Verify and rate limit handshake messages only - if let Packet::HandshakeInit(HandshakeInit { sender_idx, .. }) - | Packet::HandshakeResponse(HandshakeResponse { sender_idx, .. }) = packet - { - tracing::debug!("sender_idx: {}", sender_idx); - tracing::debug!("response: {:?}", packet); - let (msg, macs) = src.split_at(src.len() - 32); - let (mac1, mac2) = macs.split_at(16); - - let computed_mac1 = b2s_keyed_mac_16(&self.mac1_key, msg); - verify_slices_are_equal(&computed_mac1[..16], mac1) - .map_err(|_| TunnResult::Err(WireGuardError::InvalidMac))?; - - if self.is_under_load() { - let addr = match src_addr { - None => return Err(TunnResult::Err(WireGuardError::UnderLoad)), - Some(addr) => addr, - }; - - // Only given an address can we validate mac2 - let cookie = self.current_cookie(addr); - let computed_mac2 = b2s_keyed_mac_16_2(&cookie, msg, mac1); - - if verify_slices_are_equal(&computed_mac2[..16], mac2).is_err() { - let cookie_packet = self - .format_cookie_reply(sender_idx, cookie, mac1, dst) - .map_err(TunnResult::Err)?; - return Err(TunnResult::WriteToNetwork(cookie_packet)) - } - } - } - - Ok(packet) - } -} diff --git a/burrow/src/wireguard/noise/session.rs b/burrow/src/wireguard/noise/session.rs deleted file mode 100755 index 8988728..0000000 --- a/burrow/src/wireguard/noise/session.rs +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -use std::sync::atomic::{AtomicUsize, Ordering}; - -use parking_lot::Mutex; -use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305}; - -use super::{errors::WireGuardError, PacketData}; - -pub struct Session { - pub(crate) receiving_index: u32, - sending_index: u32, - receiver: LessSafeKey, - sender: LessSafeKey, - sending_key_counter: AtomicUsize, - receiving_key_counter: Mutex, -} - -impl std::fmt::Debug for Session { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "Session: {}<- ->{}", - self.receiving_index, self.sending_index - ) - } -} - -/// Where encrypted data resides in a data packet -const DATA_OFFSET: usize = 16; -/// The overhead of the AEAD -const AEAD_SIZE: usize = 16; - -// Receiving buffer constants -const WORD_SIZE: u64 = 64; -const N_WORDS: u64 = 16; // Suffice to reorder 64*16 = 1024 packets; can be increased at will -const N_BITS: u64 = WORD_SIZE * N_WORDS; - -#[derive(Debug, Clone, Default)] -struct ReceivingKeyCounterValidator { - /// In order to avoid replays while allowing for some reordering of the - /// packets, we keep a bitmap of received packets, and the value of the - /// highest counter - next: u64, - /// Used to estimate packet loss - receive_cnt: u64, - bitmap: [u64; N_WORDS as usize], -} - -impl ReceivingKeyCounterValidator { - #[inline(always)] - fn set_bit(&mut self, idx: u64) { - let bit_idx = idx % N_BITS; - let word = (bit_idx / WORD_SIZE) as usize; - let bit = (bit_idx % WORD_SIZE) as usize; - self.bitmap[word] |= 1 << bit; - } - - #[inline(always)] - fn clear_bit(&mut self, idx: u64) { - let bit_idx = idx % N_BITS; - let word = (bit_idx / WORD_SIZE) as usize; - let bit = (bit_idx % WORD_SIZE) as usize; - self.bitmap[word] &= !(1u64 << bit); - } - - /// Clear the word that contains idx - #[inline(always)] - fn clear_word(&mut self, idx: u64) { - let bit_idx = idx % N_BITS; - let word = (bit_idx / WORD_SIZE) as usize; - self.bitmap[word] = 0; - } - - /// Returns true if bit is set, false otherwise - #[inline(always)] - fn check_bit(&self, idx: u64) -> bool { - let bit_idx = idx % N_BITS; - let word = (bit_idx / WORD_SIZE) as usize; - let bit = (bit_idx % WORD_SIZE) as usize; - ((self.bitmap[word] >> bit) & 1) == 1 - } - - /// Returns true if the counter was not yet received, and is not too far - /// back - #[inline(always)] - fn will_accept(&self, counter: u64) -> Result<(), WireGuardError> { - if counter >= self.next { - // As long as the counter is growing no replay took place for sure - return Ok(()) - } - if counter + N_BITS < self.next { - // Drop if too far back - return Err(WireGuardError::InvalidCounter) - } - if !self.check_bit(counter) { - Ok(()) - } else { - Err(WireGuardError::DuplicateCounter) - } - } - - /// Marks the counter as received, and returns true if it is still good (in - /// case during decryption something changed) - #[inline(always)] - fn mark_did_receive(&mut self, counter: u64) -> Result<(), WireGuardError> { - if counter + N_BITS < self.next { - // Drop if too far back - return Err(WireGuardError::InvalidCounter) - } - if counter == self.next { - // Usually the packets arrive in order, in that case we simply mark the bit and - // increment the counter - self.set_bit(counter); - self.next += 1; - return Ok(()) - } - if counter < self.next { - // A packet arrived out of order, check if it is valid, and mark - if self.check_bit(counter) { - return Err(WireGuardError::InvalidCounter) - } - self.set_bit(counter); - return Ok(()) - } - // Packets where dropped, or maybe reordered, skip them and mark unused - if counter - self.next >= N_BITS { - // Too far ahead, clear all the bits - for c in self.bitmap.iter_mut() { - *c = 0; - } - } else { - let mut i = self.next; - while i % WORD_SIZE != 0 && i < counter { - // Clear until i aligned to word size - self.clear_bit(i); - i += 1; - } - while i + WORD_SIZE < counter { - // Clear whole word at a time - self.clear_word(i); - i = (i + WORD_SIZE) & 0u64.wrapping_sub(WORD_SIZE); - } - while i < counter { - // Clear any remaining bits - self.clear_bit(i); - i += 1; - } - } - self.set_bit(counter); - self.next = counter + 1; - Ok(()) - } -} - -impl Session { - pub(super) fn new( - local_index: u32, - peer_index: u32, - receiving_key: [u8; 32], - sending_key: [u8; 32], - ) -> Session { - Session { - receiving_index: local_index, - sending_index: peer_index, - receiver: LessSafeKey::new( - UnboundKey::new(&CHACHA20_POLY1305, &receiving_key).unwrap(), - ), - sender: LessSafeKey::new(UnboundKey::new(&CHACHA20_POLY1305, &sending_key).unwrap()), - sending_key_counter: AtomicUsize::new(0), - receiving_key_counter: Mutex::new(Default::default()), - } - } - - pub(super) fn local_index(&self) -> usize { - self.receiving_index as usize - } - - /// Returns true if receiving counter is good to use - fn receiving_counter_quick_check(&self, counter: u64) -> Result<(), WireGuardError> { - let counter_validator = self.receiving_key_counter.lock(); - counter_validator.will_accept(counter) - } - - /// Returns true if receiving counter is good to use, and marks it as used { - fn receiving_counter_mark(&self, counter: u64) -> Result<(), WireGuardError> { - let mut counter_validator = self.receiving_key_counter.lock(); - let ret = counter_validator.mark_did_receive(counter); - if ret.is_ok() { - counter_validator.receive_cnt += 1; - } - ret - } - - /// src - an IP packet from the interface - /// dst - pre-allocated space to hold the encapsulating UDP packet to send - /// over the network returns the size of the formatted packet - pub(super) fn format_packet_data<'a>(&self, src: &[u8], dst: &'a mut [u8]) -> &'a mut [u8] { - if dst.len() < src.len() + super::DATA_OVERHEAD_SZ { - panic!("The destination buffer is too small"); - } - - let sending_key_counter = self.sending_key_counter.fetch_add(1, Ordering::Relaxed) as u64; - - let (message_type, rest) = dst.split_at_mut(4); - let (receiver_index, rest) = rest.split_at_mut(4); - let (counter, data) = rest.split_at_mut(8); - - message_type.copy_from_slice(&super::DATA.to_le_bytes()); - receiver_index.copy_from_slice(&self.sending_index.to_le_bytes()); - counter.copy_from_slice(&sending_key_counter.to_le_bytes()); - - // TODO: spec requires padding to 16 bytes, but actually works fine without it - let n = { - let mut nonce = [0u8; 12]; - nonce[4..12].copy_from_slice(&sending_key_counter.to_le_bytes()); - data[..src.len()].copy_from_slice(src); - self.sender - .seal_in_place_separate_tag( - Nonce::assume_unique_for_key(nonce), - Aad::from(&[]), - &mut data[..src.len()], - ) - .map(|tag| { - data[src.len()..src.len() + AEAD_SIZE].copy_from_slice(tag.as_ref()); - src.len() + AEAD_SIZE - }) - .unwrap() - }; - - &mut dst[..DATA_OFFSET + n] - } - - /// packet - a data packet we received from the network - /// dst - pre-allocated space to hold the encapsulated IP packet, to send to - /// the interface dst will always take less space than src - /// return the size of the encapsulated packet on success - pub(super) fn receive_packet_data<'a>( - &self, - packet: PacketData, - dst: &'a mut [u8], - ) -> Result<&'a mut [u8], WireGuardError> { - let ct_len = packet.encrypted_encapsulated_packet.len(); - if dst.len() < ct_len { - // This is a very incorrect use of the library, therefore panic and not error - panic!("The destination buffer is too small"); - } - if packet.receiver_idx != self.receiving_index { - return Err(WireGuardError::WrongIndex) - } - // Don't reuse counters, in case this is a replay attack we want to quickly - // check the counter without running expensive decryption - self.receiving_counter_quick_check(packet.counter)?; - - tracing::debug!("TAG C"); - let ret = { - let mut nonce = [0u8; 12]; - nonce[4..12].copy_from_slice(&packet.counter.to_le_bytes()); - dst[..ct_len].copy_from_slice(packet.encrypted_encapsulated_packet); - self.receiver - .open_in_place( - Nonce::assume_unique_for_key(nonce), - Aad::from(&[]), - &mut dst[..ct_len], - ) - .map_err(|_| WireGuardError::InvalidAeadTag)? - }; - - // After decryption is done, check counter again, and mark as received - self.receiving_counter_mark(packet.counter)?; - Ok(ret) - } - - /// Returns the estimated downstream packet loss for this session - pub(super) fn current_packet_cnt(&self) -> (u64, u64) { - let counter_validator = self.receiving_key_counter.lock(); - (counter_validator.next, counter_validator.receive_cnt) - } -} diff --git a/burrow/src/wireguard/noise/timers.rs b/burrow/src/wireguard/noise/timers.rs deleted file mode 100755 index 1d0cf1f..0000000 --- a/burrow/src/wireguard/noise/timers.rs +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2019 Cloudflare, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -use std::{ - mem, - ops::{Index, IndexMut}, - time::{Duration, Instant}, -}; - -use super::{errors::WireGuardError, TunnResult, Tunnel}; - -// Some constants, represent time in seconds -// https://www.wireguard.com/papers/wireguard.pdf#page=14 -pub(crate) const REKEY_AFTER_TIME: Duration = Duration::from_secs(120); -const REJECT_AFTER_TIME: Duration = Duration::from_secs(180); -const REKEY_ATTEMPT_TIME: Duration = Duration::from_secs(90); -pub(crate) const REKEY_TIMEOUT: Duration = Duration::from_secs(5); -const KEEPALIVE_TIMEOUT: Duration = Duration::from_secs(10); -const COOKIE_EXPIRATION_TIME: Duration = Duration::from_secs(120); - -#[derive(Debug)] -pub enum TimerName { - /// Current time, updated each call to `update_timers` - TimeCurrent, - /// Time when last handshake was completed - TimeSessionEstablished, - /// Time the last attempt for a new handshake began - TimeLastHandshakeStarted, - /// Time we last received and authenticated a packet - TimeLastPacketReceived, - /// Time we last send a packet - TimeLastPacketSent, - /// Time we last received and authenticated a DATA packet - TimeLastDataPacketReceived, - /// Time we last send a DATA packet - TimeLastDataPacketSent, - /// Time we last received a cookie - TimeCookieReceived, - /// Time we last sent persistent keepalive - TimePersistentKeepalive, - Top, -} - -use self::TimerName::*; - -#[derive(Debug)] -pub struct Timers { - /// Is the owner of the timer the initiator or the responder for the last - /// handshake? - is_initiator: bool, - /// Start time of the tunnel - time_started: Instant, - timers: [Duration; TimerName::Top as usize], - pub(super) session_timers: [Duration; super::N_SESSIONS], - /// Did we receive data without sending anything back? - want_keepalive: bool, - /// Did we send data without hearing back? - want_handshake: bool, - persistent_keepalive: usize, - /// Should this timer call reset rr function (if not a shared rr instance) - pub(super) should_reset_rr: bool, -} - -impl Timers { - pub(super) fn new(persistent_keepalive: Option, reset_rr: bool) -> Timers { - Timers { - is_initiator: false, - time_started: Instant::now(), - timers: Default::default(), - session_timers: Default::default(), - want_keepalive: Default::default(), - want_handshake: Default::default(), - persistent_keepalive: usize::from(persistent_keepalive.unwrap_or(0)), - should_reset_rr: reset_rr, - } - } - - fn is_initiator(&self) -> bool { - self.is_initiator - } - - // We don't really clear the timers, but we set them to the current time to - // so the reference time frame is the same - pub(super) fn clear(&mut self) { - let now = Instant::now().duration_since(self.time_started); - for t in &mut self.timers[..] { - *t = now; - } - self.want_handshake = false; - self.want_keepalive = false; - } -} - -impl Index for Timers { - type Output = Duration; - - fn index(&self, index: TimerName) -> &Duration { - &self.timers[index as usize] - } -} - -impl IndexMut for Timers { - fn index_mut(&mut self, index: TimerName) -> &mut Duration { - &mut self.timers[index as usize] - } -} - -impl Tunnel { - pub(super) fn timer_tick(&mut self, timer_name: TimerName) { - match timer_name { - TimeLastPacketReceived => { - self.timers.want_keepalive = true; - self.timers.want_handshake = false; - } - TimeLastPacketSent => { - self.timers.want_handshake = true; - self.timers.want_keepalive = false; - } - _ => {} - } - - let time = self.timers[TimeCurrent]; - self.timers[timer_name] = time; - } - - pub(super) fn timer_tick_session_established( - &mut self, - is_initiator: bool, - session_idx: usize, - ) { - self.timer_tick(TimeSessionEstablished); - self.timers.session_timers[session_idx % super::N_SESSIONS] = self.timers[TimeCurrent]; - self.timers.is_initiator = is_initiator; - } - - // We don't really clear the timers, but we set them to the current time to - // so the reference time frame is the same - fn clear_all(&mut self) { - for session in &mut self.sessions { - *session = None; - } - - self.packet_queue.clear(); - - self.timers.clear(); - } - - fn update_session_timers(&mut self, time_now: Duration) { - let timers = &mut self.timers; - - for (i, t) in timers.session_timers.iter_mut().enumerate() { - if time_now - *t > REJECT_AFTER_TIME { - if let Some(session) = self.sessions[i].take() { - tracing::debug!( - message = "SESSION_EXPIRED(REJECT_AFTER_TIME)", - session = session.receiving_index - ); - } - *t = time_now; - } - } - } - - pub fn update_timers<'a>(&mut self, dst: &'a mut [u8]) -> TunnResult<'a> { - let mut handshake_initiation_required = false; - let mut keepalive_required = false; - - let time = Instant::now(); - - if self.timers.should_reset_rr { - self.rate_limiter.reset_count(); - } - - // All the times are counted from tunnel initiation, for efficiency our timers - // are rounded to a second, as there is no real benefit to having highly - // accurate timers. - let now = time.duration_since(self.timers.time_started); - self.timers[TimeCurrent] = now; - - self.update_session_timers(now); - - // Load timers only once: - let session_established = self.timers[TimeSessionEstablished]; - let handshake_started = self.timers[TimeLastHandshakeStarted]; - let aut_packet_received = self.timers[TimeLastPacketReceived]; - let aut_packet_sent = self.timers[TimeLastPacketSent]; - let data_packet_received = self.timers[TimeLastDataPacketReceived]; - let data_packet_sent = self.timers[TimeLastDataPacketSent]; - let persistent_keepalive = self.timers.persistent_keepalive; - - { - if self.handshake.is_expired() { - return TunnResult::Err(WireGuardError::ConnectionExpired) - } - - // Clear cookie after COOKIE_EXPIRATION_TIME - if self.handshake.has_cookie() - && now - self.timers[TimeCookieReceived] >= COOKIE_EXPIRATION_TIME - { - self.handshake.clear_cookie(); - } - - // All ephemeral private keys and symmetric session keys are zeroed out after - // (REJECT_AFTER_TIME * 3) ms if no new keys have been exchanged. - if now - session_established >= REJECT_AFTER_TIME * 3 { - tracing::error!("CONNECTION_EXPIRED(REJECT_AFTER_TIME * 3)"); - self.handshake.set_expired(); - self.clear_all(); - return TunnResult::Err(WireGuardError::ConnectionExpired) - } - - if let Some(time_init_sent) = self.handshake.timer() { - // Handshake Initiation Retransmission - if now - handshake_started >= REKEY_ATTEMPT_TIME { - // After REKEY_ATTEMPT_TIME ms of trying to initiate a new handshake, - // the retries give up and cease, and clear all existing packets queued - // up to be sent. If a packet is explicitly queued up to be sent, then - // this timer is reset. - tracing::error!("CONNECTION_EXPIRED(REKEY_ATTEMPT_TIME)"); - self.handshake.set_expired(); - self.clear_all(); - return TunnResult::Err(WireGuardError::ConnectionExpired) - } - - if time_init_sent.elapsed() >= REKEY_TIMEOUT { - // We avoid using `time` here, because it can be earlier than `time_init_sent`. - // Once `checked_duration_since` is stable we can use that. - // A handshake initiation is retried after REKEY_TIMEOUT + jitter ms, - // if a response has not been received, where jitter is some random - // value between 0 and 333 ms. - tracing::warn!("HANDSHAKE(REKEY_TIMEOUT)"); - handshake_initiation_required = true; - } - } else { - if self.timers.is_initiator() { - // After sending a packet, if the sender was the original initiator - // of the handshake and if the current session key is REKEY_AFTER_TIME - // ms old, we initiate a new handshake. If the sender was the original - // responder of the handshake, it does not re-initiate a new handshake - // after REKEY_AFTER_TIME ms like the original initiator does. - if session_established < data_packet_sent - && now - session_established >= REKEY_AFTER_TIME - { - tracing::debug!("HANDSHAKE(REKEY_AFTER_TIME (on send))"); - handshake_initiation_required = true; - } - - // After receiving a packet, if the receiver was the original initiator - // of the handshake and if the current session key is REJECT_AFTER_TIME - // - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT ms old, we initiate a new - // handshake. - if session_established < data_packet_received - && now - session_established - >= REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT - { - tracing::warn!( - "HANDSHAKE(REJECT_AFTER_TIME - KEEPALIVE_TIMEOUT - \ - REKEY_TIMEOUT \ - (on receive))" - ); - handshake_initiation_required = true; - } - } - - // If we have sent a packet to a given peer but have not received a - // packet after from that peer for (KEEPALIVE + REKEY_TIMEOUT) ms, - // we initiate a new handshake. - if data_packet_sent > aut_packet_received - && now - aut_packet_received >= KEEPALIVE_TIMEOUT + REKEY_TIMEOUT - && mem::replace(&mut self.timers.want_handshake, false) - { - tracing::warn!("HANDSHAKE(KEEPALIVE + REKEY_TIMEOUT)"); - handshake_initiation_required = true; - } - - if !handshake_initiation_required { - // If a packet has been received from a given peer, but we have not sent one - // back to the given peer in KEEPALIVE ms, we send an empty - // packet. - if data_packet_received > aut_packet_sent - && now - aut_packet_sent >= KEEPALIVE_TIMEOUT - && mem::replace(&mut self.timers.want_keepalive, false) - { - tracing::debug!("KEEPALIVE(KEEPALIVE_TIMEOUT)"); - keepalive_required = true; - } - - // Persistent KEEPALIVE - if persistent_keepalive > 0 - && (now - self.timers[TimePersistentKeepalive] - >= Duration::from_secs(persistent_keepalive as _)) - { - tracing::debug!("KEEPALIVE(PERSISTENT_KEEPALIVE)"); - self.timer_tick(TimePersistentKeepalive); - keepalive_required = true; - } - } - } - } - - if handshake_initiation_required { - return self.format_handshake_initiation(dst, true) - } - - if keepalive_required { - return self.encapsulate(&[], dst) - } - - TunnResult::Done - } - - pub fn time_since_last_handshake(&self) -> Option { - let current_session = self.current; - if self.sessions[current_session % super::N_SESSIONS].is_some() { - let duration_since_tun_start = Instant::now().duration_since(self.timers.time_started); - let duration_since_session_established = self.timers[TimeSessionEstablished]; - - Some(duration_since_tun_start - duration_since_session_established) - } else { - None - } - } - - pub fn persistent_keepalive(&self) -> Option { - let keepalive = self.timers.persistent_keepalive; - - if keepalive > 0 { - Some(keepalive as u16) - } else { - None - } - } -} diff --git a/burrow/src/wireguard/pcb.rs b/burrow/src/wireguard/pcb.rs deleted file mode 100755 index c6ebaa6..0000000 --- a/burrow/src/wireguard/pcb.rs +++ /dev/null @@ -1,159 +0,0 @@ -use std::{net::SocketAddr, sync::Arc}; - -use anyhow::{Error, Result}; -use fehler::throws; -use ip_network::IpNetwork; -use rand::random; -use tokio::{net::UdpSocket, sync::RwLock, task::JoinHandle}; -use tun::tokio::TunInterface; - -use super::{ - noise::{TunnResult, Tunnel}, - Peer, -}; - -#[derive(Debug)] -pub struct PeerPcb { - pub endpoint: SocketAddr, - pub allowed_ips: Vec, - pub handle: RwLock>>, - socket: RwLock>, - tunnel: RwLock, -} - -impl PeerPcb { - #[throws] - pub fn new(peer: Peer) -> Self { - let tunnel = RwLock::new( - Tunnel::new( - peer.private_key, - peer.public_key, - peer.preshared_key, - None, - 1, - None, - ) - .map_err(|s| anyhow::anyhow!("{}", s))?, - ); - Self { - endpoint: peer.endpoint, - allowed_ips: peer.allowed_ips, - handle: RwLock::new(None), - socket: RwLock::new(None), - tunnel, - } - } - - pub async fn open_if_closed(&self) -> Result<(), Error> { - if self.socket.read().await.is_none() { - let socket = UdpSocket::bind("0.0.0.0:0").await?; - socket.connect(self.endpoint).await?; - self.socket.write().await.replace(socket); - } - Ok(()) - } - - pub async fn run(&self, tun_interface: Arc>) -> Result<(), Error> { - tracing::debug!("starting read loop for pcb... for {:?}", &self); - let rid: i32 = random(); - let mut buf: [u8; 3000] = [0u8; 3000]; - tracing::debug!("start read loop {}", rid); - loop { - tracing::debug!("{}: waiting for packet", rid); - let guard = self.socket.read().await; - let Some(socket) = guard.as_ref() else { - continue - }; - let mut res_buf = [0; 1500]; - // tracing::debug!("{} : waiting for readability on {:?}", rid, socket); - let len = match socket.recv(&mut res_buf).await { - Ok(l) => l, - Err(e) => { - log::error!("{}: error reading from socket: {:?}", rid, e); - continue - } - }; - let mut res_dat = &res_buf[..len]; - tracing::debug!("{}: Decapsulating {} bytes", rid, len); - tracing::debug!("{:?}", &res_dat); - loop { - match self - .tunnel - .write() - .await - .decapsulate(None, res_dat, &mut buf[..]) - { - TunnResult::Done => break, - TunnResult::Err(e) => { - tracing::error!(message = "Decapsulate error", error = ?e); - break - } - TunnResult::WriteToNetwork(packet) => { - tracing::debug!("WriteToNetwork: {:?}", packet); - self.open_if_closed().await?; - socket.send(packet).await?; - tracing::debug!("WriteToNetwork done"); - res_dat = &[]; - continue - } - TunnResult::WriteToTunnelV4(packet, addr) => { - tracing::debug!("WriteToTunnelV4: {:?}, {:?}", packet, addr); - tun_interface.read().await.send(packet).await?; - break - } - TunnResult::WriteToTunnelV6(packet, addr) => { - tracing::debug!("WriteToTunnelV6: {:?}, {:?}", packet, addr); - tun_interface.read().await.send(packet).await?; - break - } - } - } - } - } - - pub async fn send(&self, src: &[u8]) -> Result<(), Error> { - let mut dst_buf = [0u8; 3000]; - match self.tunnel.write().await.encapsulate(src, &mut dst_buf[..]) { - TunnResult::Done => {} - TunnResult::Err(e) => { - tracing::error!(message = "Encapsulate error", error = ?e) - } - TunnResult::WriteToNetwork(packet) => { - self.open_if_closed().await?; - let handle = self.socket.read().await; - let Some(socket) = handle.as_ref() else { - tracing::error!("No socket for peer"); - return Ok(()) - }; - tracing::debug!("Our Encapsulated packet: {:?}", packet); - socket.send(packet).await?; - } - _ => panic!("Unexpected result from encapsulate"), - }; - Ok(()) - } - - pub async fn update_timers(&self, dst: &mut [u8]) -> Result<(), Error> { - match self.tunnel.write().await.update_timers(dst) { - TunnResult::Done => {} - TunnResult::Err(e) => { - tracing::error!(message = "Update timers error", error = ?e) - } - TunnResult::WriteToNetwork(packet) => { - self.open_if_closed().await?; - let handle = self.socket.read().await; - let Some(socket) = handle.as_ref() else { - tracing::error!("No socket for peer"); - return Ok(()) - }; - socket.send(packet).await?; - } - _ => panic!("Unexpected result from update_timers"), - }; - Ok(()) - } - - pub async fn reset_rate_limiter(&self) { - self.tunnel.read().await.reset_rate_limiter(); - } -} diff --git a/burrow/src/wireguard/peer.rs b/burrow/src/wireguard/peer.rs deleted file mode 100755 index 131b0d4..0000000 --- a/burrow/src/wireguard/peer.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::{fmt, net::SocketAddr}; - -use ip_network::IpNetwork; -use x25519_dalek::{PublicKey, StaticSecret}; - -pub struct Peer { - pub endpoint: SocketAddr, - pub private_key: StaticSecret, - pub public_key: PublicKey, - pub allowed_ips: Vec, - pub preshared_key: Option<[u8; 32]>, -} - -impl fmt::Debug for Peer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Peer") - .field("endpoint", &self.endpoint) - .field("public_key", &self.public_key) - .field("allowed_ips", &self.allowed_ips) - .finish() - } -} diff --git a/tun/Cargo.toml b/tun/Cargo.toml index e67e45f..b95c1bf 100644 --- a/tun/Cargo.toml +++ b/tun/Cargo.toml @@ -39,5 +39,5 @@ anyhow = "1.0" bindgen = "0.65" reqwest = { version = "0.11", features = ["native-tls"] } ssri = { version = "9.0", default-features = false } -tokio = { version = "1.28", features = ["rt", "macros"] } +tokio = { version = "1.28", features = ["rt"] } zip = { version = "0.6", features = ["deflate"] } diff --git a/tun/build.rs b/tun/build.rs index 8da8a40..5569cc4 100644 --- a/tun/build.rs +++ b/tun/build.rs @@ -26,7 +26,7 @@ async fn generate(out_dir: &std::path::Path) -> anyhow::Result<()> { println!("cargo:rerun-if-changed={}", binary_path.to_str().unwrap()); if let (Ok(..), Ok(..)) = (File::open(&bindings_path), File::open(&binary_path)) { - return Ok(()) + return Ok(()); }; let archive = download(out_dir) @@ -80,9 +80,8 @@ async fn download(directory: &std::path::Path) -> anyhow::Result #[cfg(windows)] fn parse(file: std::fs::File) -> anyhow::Result<(bindgen::Bindings, Vec)> { - use std::io::Read; - use anyhow::Context; + use std::io::Read; let reader = std::io::BufReader::new(file); let mut archive = zip::ZipArchive::new(reader)?; diff --git a/tun/src/lib.rs b/tun/src/lib.rs index a1ca636..151c10d 100644 --- a/tun/src/lib.rs +++ b/tun/src/lib.rs @@ -2,11 +2,11 @@ #[cfg(target_os = "windows")] #[path = "windows/mod.rs"] -mod os_imp; +mod imp; #[cfg(any(target_os = "linux", target_vendor = "apple"))] #[path = "unix/mod.rs"] -pub(crate) mod os_imp; +pub(crate) mod imp; mod options; @@ -14,5 +14,5 @@ mod options; #[cfg(feature = "tokio")] pub mod tokio; +pub use imp::{TunInterface, TunQueue}; pub use options::TunOptions; -pub use os_imp::{TunInterface, TunQueue}; diff --git a/tun/src/options.rs b/tun/src/options.rs index 339f71a..e74afe3 100644 --- a/tun/src/options.rs +++ b/tun/src/options.rs @@ -1,27 +1,17 @@ +use fehler::throws; use std::io::Error; -use fehler::throws; - -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -#[cfg(feature = "tokio")] -use super::tokio::TunInterface; +use super::TunInterface; #[derive(Debug, Clone, Default)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema) -)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema))] pub struct TunOptions { /// (Windows + Linux) Name the tun interface. - pub name: Option, + pub(crate) name: Option, /// (Linux) Don't include packet information. - pub no_pi: bool, + pub(crate) no_pi: Option<()>, /// (Linux) Avoid opening an existing persistant device. - pub tun_excl: bool, - /// (Apple) Retrieve the tun interface - pub tun_retrieve: bool, - /// (Linux) The IP address of the tun interface. - pub address: Option, + pub(crate) tun_excl: Option<()>, } impl TunOptions { @@ -34,26 +24,16 @@ impl TunOptions { self } - pub fn no_pi(mut self, enable: bool) -> Self { - self.no_pi = enable; - self + pub fn no_pi(mut self, enable: bool) { + self.no_pi = enable.then_some(()); } - pub fn tun_excl(mut self, enable: bool) -> Self { - self.tun_excl = enable; - self + pub fn tun_excl(mut self, enable: bool) { + self.tun_excl = enable.then_some(()); } - pub fn address(mut self, address: impl ToString) -> Self { - self.address = Some(address.to_string()); - self - } - - #[cfg(any(target_os = "linux", target_vendor = "apple"))] - #[cfg(feature = "tokio")] #[throws] pub fn open(self) -> TunInterface { - let ti = super::TunInterface::new_with_options(self)?; - TunInterface::new(ti)? + TunInterface::new_with_options(self)? } } diff --git a/tun/src/tokio/mod.rs b/tun/src/tokio/mod.rs index bd27109..7828279 100644 --- a/tun/src/tokio/mod.rs +++ b/tun/src/tokio/mod.rs @@ -1,22 +1,22 @@ use std::io; - use tokio::io::unix::AsyncFd; use tracing::instrument; #[derive(Debug)] pub struct TunInterface { - pub inner: AsyncFd, + inner: AsyncFd, } impl TunInterface { #[instrument] - pub fn new(mut tun: crate::TunInterface) -> io::Result { - tun.set_nonblocking(true)?; - Ok(Self { inner: AsyncFd::new(tun)? }) + pub fn new(tun: crate::TunInterface) -> io::Result { + Ok(Self { + inner: AsyncFd::new(tun)?, + }) } #[instrument] - pub async fn send(&self, buf: &[u8]) -> io::Result { + pub async fn write(&self, buf: &[u8]) -> io::Result { loop { let mut guard = self.inner.writable().await?; match guard.try_io(|inner| inner.get_ref().send(buf)) { @@ -26,15 +26,13 @@ impl TunInterface { } } - pub async fn recv(&self, buf: &mut [u8]) -> io::Result { + #[instrument] + pub async fn read(&mut self, buf: &mut [u8]) -> io::Result { loop { - let mut guard = self.inner.readable().await?; - match guard.try_io(|inner| inner.get_ref().recv(buf)) { + let mut guard = self.inner.readable_mut().await?; + match guard.try_io(|inner| (*inner).get_mut().recv(buf)) { Ok(result) => return result, - Err(_would_block) => { - tracing::debug!("WouldBlock"); - continue - } + Err(_would_block) => continue, } } } diff --git a/tun/src/unix/apple/kern_control.rs b/tun/src/unix/apple/kern_control.rs index 76e576f..abc1e04 100644 --- a/tun/src/unix/apple/kern_control.rs +++ b/tun/src/unix/apple/kern_control.rs @@ -1,6 +1,7 @@ -use std::{io::Error, mem::size_of, os::unix::io::AsRawFd}; - use fehler::throws; +use std::io::Error; +use std::mem::size_of; +use std::os::unix::io::AsRawFd; use super::sys; @@ -15,7 +16,10 @@ pub trait SysControlSocket { impl SysControlSocket for socket2::Socket { #[throws] fn resolve(&self, name: &str, index: u32) -> socket2::SockAddr { - let mut info = sys::ctl_info { ctl_id: 0, ctl_name: [0; 96] }; + let mut info = sys::ctl_info { + ctl_id: 0, + ctl_name: [0; 96], + }; info.ctl_name[..name.len()].copy_from_slice(name.as_bytes()); unsafe { sys::resolve_ctl_info(self.as_raw_fd(), &mut info as *mut sys::ctl_info)? }; @@ -24,7 +28,7 @@ impl SysControlSocket for socket2::Socket { socket2::SockAddr::init(|addr_storage, len| { *len = size_of::() as u32; - let addr: &mut sys::sockaddr_ctl = &mut *addr_storage.cast(); + let mut addr: &mut sys::sockaddr_ctl = &mut *addr_storage.cast(); addr.sc_len = *len as u8; addr.sc_family = sys::AF_SYSTEM as u8; addr.ss_sysaddr = sys::AF_SYS_CONTROL as u16; diff --git a/tun/src/unix/apple/mod.rs b/tun/src/unix/apple/mod.rs index e72fb06..f4fd1e2 100644 --- a/tun/src/unix/apple/mod.rs +++ b/tun/src/unix/apple/mod.rs @@ -1,24 +1,21 @@ -use std::{ - io::{Error, IoSlice}, - mem, - net::{Ipv4Addr, SocketAddrV4}, - os::fd::{AsRawFd, FromRawFd, RawFd}, -}; - use byteorder::{ByteOrder, NetworkEndian}; use fehler::throws; use libc::{c_char, iovec, writev, AF_INET, AF_INET6}; +use tracing::info; use socket2::{Domain, SockAddr, Socket, Type}; -use tracing::{self, instrument}; +use std::io::IoSlice; +use std::net::{Ipv4Addr, SocketAddrV4}; +use std::os::fd::{AsRawFd, RawFd}; +use std::{io::Error, mem}; +use tracing::instrument; -pub mod kern_control; -pub mod sys; - -use kern_control::SysControlSocket; +mod kern_control; +mod sys; pub use super::queue::TunQueue; -use super::{ifname_to_string, string_to_ifname}; -use crate::TunOptions; + +use super::{ifname_to_string, string_to_ifname, TunOptions}; +use kern_control::SysControlSocket; #[derive(Debug)] pub struct TunInterface { @@ -34,49 +31,8 @@ impl TunInterface { #[throws] #[instrument] - pub fn new_with_options(options: TunOptions) -> TunInterface { - let ti = if options.tun_retrieve { - TunInterface::retrieve().ok_or(Error::new( - std::io::ErrorKind::NotFound, - "No tun interface found", - ))? - } else { - TunInterface::connect(0)? - }; - ti.configure(options)?; - ti - } - - pub fn retrieve() -> Option { - (3..100) - .filter_map(|fd| unsafe { - let peer_addr = socket2::SockAddr::init(|storage, len| { - *len = mem::size_of::() as u32; - libc::getpeername(fd, storage as *mut _, len); - Ok(()) - }) - .map(|(_, addr)| (fd, addr)); - peer_addr.ok() - }) - .filter(|(_fd, addr)| { - let ctl_addr = unsafe { &*(addr.as_ptr() as *const libc::sockaddr_ctl) }; - addr.family() == libc::AF_SYSTEM as u8 - && ctl_addr.ss_sysaddr == libc::AF_SYS_CONTROL as u16 - }) - .map(|(fd, _)| { - let socket = unsafe { socket2::Socket::from_raw_fd(fd) }; - TunInterface { socket } - }) - .next() - } - - #[throws] - fn configure(&self, options: TunOptions) { - if let Some(addr) = options.address { - if let Ok(addr) = addr.parse() { - self.set_ipv4_addr(addr)?; - } - } + pub fn new_with_options(_: TunOptions) -> TunInterface { + TunInterface::connect(0)? } #[throws] @@ -125,7 +81,7 @@ impl TunInterface { let mut iff = self.ifreq()?; iff.ifr_ifru.ifru_addr = unsafe { *addr.as_ptr() }; self.perform(|fd| unsafe { sys::if_set_addr(fd, &iff) })?; - tracing::info!("ipv4_addr_set: {:?} (fd: {:?})", addr, self.as_raw_fd()) + info!("ipv4_addr_set: {:?} (fd: {:?})", addr, self.as_raw_fd()) } #[throws] @@ -162,7 +118,7 @@ impl TunInterface { let mut iff = self.ifreq()?; iff.ifr_ifru.ifru_mtu = mtu; self.perform(|fd| unsafe { sys::if_set_mtu(fd, &iff) })?; - tracing::info!("mtu_set: {:?} (fd: {:?})", mtu, self.as_raw_fd()) + info!("mtu_set: {:?} (fd: {:?})", mtu, self.as_raw_fd()) } #[throws] @@ -184,7 +140,7 @@ impl TunInterface { let mut iff = self.ifreq()?; iff.ifr_ifru.ifru_netmask = unsafe { *addr.as_ptr() }; self.perform(|fd| unsafe { sys::if_set_netmask(fd, &iff) })?; - tracing::info!( + info!( "netmask_set: {:?} (fd: {:?})", unsafe { iff.ifr_ifru.ifru_netmask }, self.as_raw_fd() diff --git a/tun/src/unix/apple/sys.rs b/tun/src/unix/apple/sys.rs index b4d4a6a..c0ea613 100644 --- a/tun/src/unix/apple/sys.rs +++ b/tun/src/unix/apple/sys.rs @@ -2,20 +2,11 @@ use std::mem; use libc::{c_char, c_int, c_short, c_uint, c_ulong, sockaddr}; pub use libc::{ - c_void, - sockaddr_ctl, - sockaddr_in, - socklen_t, - AF_SYSTEM, - AF_SYS_CONTROL, - IFNAMSIZ, + c_void, sockaddr_ctl, sockaddr_in, socklen_t, AF_SYSTEM, AF_SYS_CONTROL, IFNAMSIZ, SYSPROTO_CONTROL, }; use nix::{ - ioctl_read_bad, - ioctl_readwrite, - ioctl_write_ptr_bad, - request_code_readwrite, + ioctl_read_bad, ioctl_readwrite, ioctl_write_ptr_bad, request_code_readwrite, request_code_write, }; diff --git a/tun/src/unix/linux/mod.rs b/tun/src/unix/linux/mod.rs index 60d6341..75bb9d2 100644 --- a/tun/src/unix/linux/mod.rs +++ b/tun/src/unix/linux/mod.rs @@ -1,21 +1,18 @@ -use std::{ - fs::OpenOptions, - io::{Error, Write}, - mem, - net::{Ipv4Addr, Ipv6Addr, SocketAddrV4}, - os::{ - fd::RawFd, - unix::io::{AsRawFd, FromRawFd, IntoRawFd}, - }, -}; - use fehler::throws; -use libc::in6_ifreq; + use socket2::{Domain, SockAddr, Socket, Type}; +use std::fs::OpenOptions; +use std::io::{Error, Write}; +use std::mem; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4}; +use std::os::fd::RawFd; +use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; + use tracing::{info, instrument}; -use super::{ifname_to_string, string_to_ifname}; -use crate::TunOptions; +use libc::in6_ifreq; + +use super::{ifname_to_string, string_to_ifname, TunOptions}; mod sys; @@ -41,10 +38,10 @@ impl TunInterface { let mut flags = libc::IFF_TUN as i16; - if options.no_pi { + if options.no_pi.is_some() { flags |= libc::IFF_NO_PI as i16; } - if options.tun_excl { + if options.tun_excl.is_some() { flags |= libc::IFF_TUN_EXCL as i16; } diff --git a/tun/src/unix/linux/sys.rs b/tun/src/unix/linux/sys.rs index e12c8ec..8d8725b 100644 --- a/tun/src/unix/linux/sys.rs +++ b/tun/src/unix/linux/sys.rs @@ -1,7 +1,10 @@ +use nix::{ioctl_read_bad, ioctl_write_ptr_bad, request_code_read, request_code_write}; use std::mem::size_of; -pub use libc::{ifreq, sockaddr, sockaddr_in, sockaddr_in6}; -use nix::{ioctl_read_bad, ioctl_write_ptr_bad, request_code_read, request_code_write}; +pub use libc::ifreq; +pub use libc::sockaddr; +pub use libc::sockaddr_in; +pub use libc::sockaddr_in6; ioctl_write_ptr_bad!( tun_set_iff, diff --git a/tun/src/unix/mod.rs b/tun/src/unix/mod.rs index ae0b77a..9da4204 100644 --- a/tun/src/unix/mod.rs +++ b/tun/src/unix/mod.rs @@ -1,11 +1,11 @@ use std::{ - io::Error, - mem::MaybeUninit, + io::{Error, Read}, os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, }; - use tracing::instrument; +use super::TunOptions; + mod queue; #[cfg(target_vendor = "apple")] @@ -28,8 +28,9 @@ impl AsRawFd for TunInterface { impl FromRawFd for TunInterface { unsafe fn from_raw_fd(fd: RawFd) -> TunInterface { - let socket = socket2::Socket::from_raw_fd(fd); - TunInterface { socket } + TunInterface { + socket: socket2::Socket::from_raw_fd(fd), + } } } @@ -39,26 +40,11 @@ impl IntoRawFd for TunInterface { } } -unsafe fn assume_init(buf: &[MaybeUninit]) -> &[u8] { - &*(buf as *const [MaybeUninit] as *const [u8]) -} - impl TunInterface { #[throws] #[instrument] - pub fn recv(&self, buf: &mut [u8]) -> usize { - // Use IoVec to read directly into target buffer - let mut tmp_buf = [MaybeUninit::uninit(); 1500]; - let len = self.socket.recv(&mut tmp_buf)?; - let result_buf = unsafe { assume_init(&tmp_buf[4..len]) }; - buf[..len - 4].copy_from_slice(result_buf); - len - 4 - } - - #[throws] - #[instrument] - pub fn set_nonblocking(&mut self, nb: bool) { - self.socket.set_nonblocking(nb)?; + pub fn recv(&mut self, buf: &mut [u8]) -> usize { + self.socket.read(buf)? } } @@ -79,4 +65,4 @@ pub fn string_to_ifname(name: &str) -> [libc::c_char; libc::IFNAMSIZ] { let len = name.len().min(buf.len()); buf[..len].copy_from_slice(unsafe { &*(name.as_bytes() as *const _ as *const [libc::c_char]) }); buf -} +} \ No newline at end of file diff --git a/tun/src/unix/queue.rs b/tun/src/unix/queue.rs index 879dcd5..923f926 100644 --- a/tun/src/unix/queue.rs +++ b/tun/src/unix/queue.rs @@ -1,10 +1,10 @@ +use fehler::throws; + use std::{ io::{Error, Read, Write}, mem::MaybeUninit, os::unix::io::{AsRawFd, IntoRawFd, RawFd}, }; - -use fehler::throws; use tracing::instrument; use crate::TunInterface; @@ -15,9 +15,10 @@ pub struct TunQueue { } impl TunQueue { + #[throws] #[instrument] - pub fn recv(&self, buf: &mut [MaybeUninit]) -> Result { - self.socket.recv(buf) + pub fn recv(&self, buf: &mut [MaybeUninit]) -> usize { + self.socket.recv(buf)? } } @@ -42,7 +43,9 @@ impl Write for TunQueue { impl From for TunQueue { fn from(interface: TunInterface) -> TunQueue { - TunQueue { socket: interface.socket } + TunQueue { + socket: interface.socket, + } } } diff --git a/tun/src/windows/mod.rs b/tun/src/windows/mod.rs index dadd53f..bae75c0 100644 --- a/tun/src/windows/mod.rs +++ b/tun/src/windows/mod.rs @@ -1,14 +1,15 @@ -use std::{fmt::Debug, io::Error, ptr}; - +use std::fmt::Debug; use fehler::throws; +use std::io::Error; +use std::ptr; use widestring::U16CString; use windows::Win32::Foundation::GetLastError; mod queue; -pub use queue::TunQueue; - use super::TunOptions; +pub use queue::TunQueue; + pub struct TunInterface { handle: sys::WINTUN_ADAPTER_HANDLE, name: String, @@ -39,7 +40,10 @@ impl TunInterface { if handle.is_null() { unsafe { GetLastError() }.ok()? } - TunInterface { handle, name: name_owned } + TunInterface { + handle, + name: name_owned, + } } pub fn name(&self) -> String { diff --git a/tun/tests/configure.rs b/tun/tests/configure.rs index e7e2c6d..0f1199d 100644 --- a/tun/tests/configure.rs +++ b/tun/tests/configure.rs @@ -1,6 +1,6 @@ -use std::{io::Error, net::Ipv4Addr}; - use fehler::throws; +use std::io::Error; +use std::net::Ipv4Addr; use tun::TunInterface; #[test] diff --git a/tun/tests/packets.rs b/tun/tests/packets.rs index 28090a2..b160893 100644 --- a/tun/tests/packets.rs +++ b/tun/tests/packets.rs @@ -1,6 +1,7 @@ -use std::{io::Error, net::Ipv4Addr}; - use fehler::throws; +use std::io::Error; + +use std::net::Ipv4Addr; use tun::TunInterface; #[throws] @@ -8,10 +9,10 @@ use tun::TunInterface; #[ignore = "requires interactivity"] #[cfg(not(target_os = "windows"))] fn tst_read() { - // This test is interactive, you need to send a packet to any server through - // 192.168.1.10 EG. `sudo route add 8.8.8.8 192.168.1.10`, + // This test is interactive, you need to send a packet to any server through 192.168.1.10 + // EG. `sudo route add 8.8.8.8 192.168.1.10`, //`dig @8.8.8.8 hackclub.com` - let tun = TunInterface::new()?; + let mut tun = TunInterface::new()?; println!("tun name: {:?}", tun.name()?); tun.set_ipv4_addr(Ipv4Addr::from([192, 168, 1, 10]))?; println!("tun ip: {:?}", tun.ipv4_addr()?); diff --git a/tun/tests/tokio.rs b/tun/tests/tokio.rs index f7cb273..e745c27 100644 --- a/tun/tests/tokio.rs +++ b/tun/tests/tokio.rs @@ -4,7 +4,7 @@ use std::net::Ipv4Addr; #[cfg(all(feature = "tokio", not(target_os = "windows")))] async fn test_create() { let tun = tun::TunInterface::new().unwrap(); - let _ = tun::tokio::TunInterface::new(tun).unwrap(); + let async_tun = tun::tokio::TunInterface::new(tun).unwrap(); } #[tokio::test] @@ -17,6 +17,6 @@ async fn test_write() { let async_tun = tun::tokio::TunInterface::new(tun).unwrap(); let mut buf = [0u8; 1500]; buf[0] = 6 << 4; - let bytes_written = async_tun.send(&buf).await.unwrap(); + let bytes_written = async_tun.write(&buf).await.unwrap(); assert!(bytes_written > 0); }