diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 4fd1cc975..110e3758b 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -25,7 +25,7 @@ jobs: - target: i686-linux-android steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -33,7 +33,7 @@ jobs: toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo @@ -57,14 +57,14 @@ jobs: needs: build steps: - name: Checkout repo (PR) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'pull_request' with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.ref }} - name: Checkout repo (Push) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'push' with: fetch-depth: 0 @@ -75,7 +75,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-combine-cache diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 624a69c4f..9aa39ab51 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -22,7 +22,7 @@ jobs: package_version: ${{ steps.retrieve-version.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get Package Version id: retrieve-version @@ -60,7 +60,7 @@ jobs: target: aarch64-unknown-linux-gnu steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -69,7 +69,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} @@ -115,7 +115,7 @@ jobs: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -155,7 +155,7 @@ jobs: - setup steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -163,7 +163,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-cli-about diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 608e8c47d..272fec363 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index b55ef939f..16f87a177 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -51,10 +51,10 @@ jobs: strip *.node steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" @@ -67,7 +67,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 0b868367d..203276556 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -43,7 +43,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Build run: cargo build -p ${{ matrix.package }} --release @@ -64,7 +64,7 @@ jobs: - build steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -73,7 +73,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 007cf5d17..7cfa9b078 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -30,7 +30,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Add build architecture run: rustup target add ${{ matrix.settings.target }} diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index 48f72ff65..a3afad257 100644 --- a/.github/workflows/cloc.yml +++ b/.github/workflows/cloc.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up cloc run: | diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index 517560ede..323a9a0a2 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -22,4 +22,4 @@ jobs: min-versions-to-keep: 25 # Ignore versions only containing version numbers - ignore-versions: '^\\d*\\.\\d*\\.\\d*$' + ignore-versions: '^\\d*\\.\\d*\\.\\d*(-SNAPSHOT)?$' diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 579817c49..b2085892a 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -45,7 +45,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: dmv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 9b2ac57c3..5f5742da0 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -21,7 +21,7 @@ jobs: toolchain: stable - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" @@ -31,7 +31,7 @@ jobs: run: npm ci - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: NPM Schemas run: npm run schemas diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 425f4e83a..cb1fb2b67 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -25,13 +25,13 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Cargo fmt run: cargo fmt --check - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 7c819986e..c86b90dd1 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 4cef3fe63..468570cd8 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -43,7 +43,7 @@ jobs: packages_command: ${{ steps.packages-list.outputs.packages_command }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -100,7 +100,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" @@ -120,7 +120,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 5d4d3c3e7..4c52529e8 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -27,7 +27,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-checksum@main with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -125,7 +125,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" @@ -145,7 +145,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 5c4992fc5..daa450c0b 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -33,7 +33,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/release-version-check@main with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -90,10 +90,10 @@ jobs: _PKG_VERSION: ${{ needs.setup.outputs.release-version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index f77cb29f6..d4177bea1 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -44,7 +44,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Test run: cargo test --all-features @@ -56,7 +56,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -65,7 +65,7 @@ jobs: targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Check run: cargo check -p bitwarden-wasm --target wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index c672edb61..d902c5700 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Branch - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -37,7 +37,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-edit @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" diff --git a/.vscode/settings.json b/.vscode/settings.json index e75498e9c..d49fe884f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "Pbkdf", "PKCS8", "repr", + "reqwest", "schemars", "uniffi", "wordlist" diff --git a/Cargo.lock b/Cargo.lock index 362288421..184066772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -197,24 +197,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-lock" -version = "2.8.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener", + "event-listener 3.0.1", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -250,9 +252,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -262,18 +264,18 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" dependencies = [ "serde", ] [[package]] name = "bat" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4b13b0233143ae151a66e0135d715b65f631d1028c40502cc88182bcb9f4fa" +checksum = "9dcc9e5637c2330d8eb7b920f2aa5d9e184446c258466f825ea1412c7614cc86" dependencies = [ "ansi_colours", "bincode", @@ -281,17 +283,17 @@ dependencies = [ "clircle", "console", "content_inspector", - "dirs", - "encoding", + "encoding_rs", "flate2", "globset", - "nu-ansi-term", + "home", + "nu-ansi-term 0.49.0", "once_cell", "path_abs", "plist", "semver", "serde", - "serde_yaml 0.8.26", + "serde_yaml", "syntect", "thiserror", "unicode-width", @@ -314,18 +316,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitwarden" -version = "0.3.0" +version = "0.3.1" dependencies = [ "aes", "argon2", "assert_matches", - "base64 0.21.4", + "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", "cbc", @@ -358,7 +360,7 @@ dependencies = [ [[package]] name = "bitwarden-api-api" -version = "0.2.1" +version = "0.2.2" dependencies = [ "reqwest", "serde", @@ -371,7 +373,7 @@ dependencies = [ [[package]] name = "bitwarden-api-identity" -version = "0.2.1" +version = "0.2.2" dependencies = [ "reqwest", "serde", @@ -414,7 +416,7 @@ dependencies = [ [[package]] name = "bitwarden-napi" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bitwarden-json", "env_logger", @@ -442,6 +444,7 @@ version = "0.1.0" dependencies = [ "async-lock", "bitwarden", + "chrono", "env_logger", "openssl", "schemars", @@ -492,9 +495,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "serde", @@ -523,7 +526,7 @@ dependencies = [ [[package]] name = "bws" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bat", "bitwarden", @@ -538,12 +541,12 @@ dependencies = [ "openssl", "serde", "serde_json", - "serde_yaml 0.9.25", + "serde_yaml", "supports-color", "tempfile", "thiserror", "tokio", - "toml 0.8.2", + "toml 0.8.6", "uuid", ] @@ -582,9 +585,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" dependencies = [ "serde", ] @@ -652,9 +655,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -662,9 +665,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -674,18 +677,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -695,15 +698,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clircle" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68bbd985a63de680ab4d1ad77b6306611a8f961b282c8b5ab513e6de934e396" +checksum = "c8e87cbed5354f17bd8ca8821a097fb62599787fe8f611743fad7ee156a0a600" dependencies = [ "cfg-if", "libc", @@ -746,11 +749,11 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.0.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ - "crossterm 0.26.1", + "crossterm 0.27.0", "strum", "strum_macros", "unicode-width", @@ -841,9 +844,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -884,17 +887,14 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.26.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "crossterm_winapi", "libc", - "mio", "parking_lot", - "signal-hook", - "signal-hook-mio", "winapi", ] @@ -959,9 +959,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -984,15 +987,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -1023,70 +1017,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -1117,30 +1047,40 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" dependencies = [ - "cc", - "libc", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "event-listener-strategy" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.0.1", + "pin-project-lite", +] [[package]] name = "eyre" @@ -1169,9 +1109,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -1215,9 +1155,9 @@ checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1230,9 +1170,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1240,15 +1180,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1257,9 +1197,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1278,9 +1218,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -1289,15 +1229,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -1307,9 +1247,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1323,6 +1263,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1420,9 +1373,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -1454,6 +1407,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "http" version = "0.2.9" @@ -1532,7 +1494,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1554,16 +1516,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1609,7 +1571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.2", ] [[package]] @@ -1661,9 +1623,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -1717,9 +1679,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -1746,23 +1708,17 @@ dependencies = [ "safemem", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1774,6 +1730,29 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "pin-utils", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.6.4" @@ -1822,9 +1801,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -1838,7 +1817,7 @@ version = "2.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd063c93b900149304e3ba96ce5bf210cd4f81ef5eb80ded0d100df3e85a3ac0" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "ctor", "napi-derive", "napi-sys", @@ -1929,11 +1908,21 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.47.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df031e117bca634c262e9bd3173776844b6c17a90b3741c9163663b4385af76" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "windows-sys 0.45.0", + "overload", + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" +dependencies = [ + "windows-sys 0.48.0", ] [[package]] @@ -1987,9 +1976,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -2020,6 +2009,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "oneshot" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" +dependencies = [ + "loom", +] + [[package]] name = "onig" version = "6.4.0" @@ -2048,7 +2046,7 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -2076,9 +2074,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.5+3.1.3" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] @@ -2102,6 +2100,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -2110,9 +2114,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2126,13 +2130,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -2234,11 +2238,11 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" +checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "indexmap 1.9.3", "line-wrap", "quick-xml", @@ -2246,6 +2250,12 @@ dependencies = [ "time", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2254,9 +2264,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -2325,9 +2335,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47b0777feb17f61eea78667d61103758b243a871edc09a7786500a50467b605" +checksum = "c09c2b349b6538d8a73d436ca606dab6ce0aaab4dad9e6b7bdd57a4f556c3bc3" dependencies = [ "arc-swap", "log", @@ -2359,9 +2369,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", ] @@ -2457,9 +2467,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] @@ -2477,40 +2487,61 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.2", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "reqwest" version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2551,25 +2582,23 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" dependencies = [ - "byteorder", "const-oid", "digest", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -2588,11 +2617,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.17" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -2732,27 +2761,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -2772,9 +2801,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2805,9 +2834,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", @@ -2816,9 +2845,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2837,21 +2866,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.26" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - -[[package]] -name = "serde_yaml" -version = "0.9.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap 2.0.2", "itoa", @@ -2954,9 +2971,9 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2964,9 +2981,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -3008,21 +3025,21 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -3075,7 +3092,7 @@ dependencies = [ "fnv", "once_cell", "onig", - "regex-syntax", + "regex-syntax 0.7.5", "serde", "serde_json", "thiserror", @@ -3105,19 +3122,19 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "windows-sys 0.48.0", ] @@ -3133,18 +3150,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -3163,12 +3180,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -3206,9 +3224,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", @@ -3216,7 +3234,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -3244,9 +3262,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -3267,9 +3285,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" dependencies = [ "serde", "serde_spanned", @@ -3279,18 +3297,18 @@ dependencies = [ [[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", ] [[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 2.0.2", "serde", @@ -3307,20 +3325,31 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3336,15 +3365,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ + "matchers", + "nu-ansi-term 0.46.0", + "once_cell", + "regex", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -3403,8 +3450,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3424,8 +3471,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "askama", @@ -3439,7 +3486,6 @@ dependencies = [ "once_cell", "paste", "serde", - "serde_json", "toml 0.5.11", "uniffi_meta", "uniffi_testing", @@ -3448,8 +3494,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3458,8 +3504,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "quote", "syn 2.0.38", @@ -3467,23 +3513,23 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", "camino", - "cargo_metadata", "log", "once_cell", + "oneshot", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "bincode", "camino", @@ -3500,34 +3546,31 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", - "serde", "siphasher", "uniffi_checksum_derive", ] [[package]] name = "uniffi_testing" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", "cargo_metadata", "fs-err", "once_cell", - "serde", - "serde_json", ] [[package]] name = "uniffi_udl" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "uniffi_meta", @@ -3567,9 +3610,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "serde", ] @@ -3734,7 +3777,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "nom", ] @@ -3779,6 +3822,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -3913,9 +3965,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] @@ -3938,7 +3990,7 @@ checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "deadpool", "futures", "futures-timer", @@ -3952,15 +4004,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zeroize" version = "1.6.0" diff --git a/Cargo.toml b/Cargo.toml index dbd4ed30f..da8805342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ codegen-units = 1 # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true -# Uniffi proc-macro support is still not part of a release, so we need to use the git version for now +# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index fd5780dad..518cc33ed 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-api" -version = "0.2.1" +version = "0.2.2" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index a74a43961..70be0560b 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-identity" -version = "0.2.1" +version = "0.2.2" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index f771a5ce4..416067b66 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -46,13 +46,15 @@ impl Client { match cmd { #[cfg(feature = "internal")] - Command::PasswordLogin(req) => self.0.password_login(&req).await.into_string(), + Command::PasswordLogin(req) => self.0.auth().login_password(&req).await.into_string(), #[cfg(feature = "secrets")] - Command::AccessTokenLogin(req) => self.0.access_token_login(&req).await.into_string(), + Command::AccessTokenLogin(req) => { + self.0.auth().login_access_token(&req).await.into_string() + } #[cfg(feature = "internal")] Command::GetUserApiKey(req) => self.0.get_user_api_key(&req).await.into_string(), #[cfg(feature = "internal")] - Command::ApiKeyLogin(req) => self.0.api_key_login(&req).await.into_string(), + Command::ApiKeyLogin(req) => self.0.auth().login_api_key(&req).await.into_string(), #[cfg(feature = "internal")] Command::Sync(req) => self.0.sync(&req).await.into_string(), #[cfg(feature = "internal")] diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index bc170631d..505b68e57 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-napi" -version = "0.3.0" +version = "0.3.1" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden-napi/npm/darwin-arm64/package.json b/crates/bitwarden-napi/npm/darwin-arm64/package.json index b9c1c95b7..52d785d87 100644 --- a/crates/bitwarden-napi/npm/darwin-arm64/package.json +++ b/crates/bitwarden-napi/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-darwin-arm64", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/darwin-x64/package.json b/crates/bitwarden-napi/npm/darwin-x64/package.json index 66f352df4..0a1b06423 100644 --- a/crates/bitwarden-napi/npm/darwin-x64/package.json +++ b/crates/bitwarden-napi/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-darwin-x64", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/linux-x64-gnu/package.json b/crates/bitwarden-napi/npm/linux-x64-gnu/package.json index 7f91c241c..2284d8415 100644 --- a/crates/bitwarden-napi/npm/linux-x64-gnu/package.json +++ b/crates/bitwarden-napi/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-linux-x64-gnu", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/win32-x64-msvc/package.json b/crates/bitwarden-napi/npm/win32-x64-msvc/package.json index e4cfa367c..261554e93 100644 --- a/crates/bitwarden-napi/npm/win32-x64-msvc/package.json +++ b/crates/bitwarden-napi/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-win32-x64-msvc", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 02ea37bec..65266d1e4 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "license": "SEE LICENSE IN LICENSE", "devDependencies": { "@napi-rs/cli": "^2.13.2", @@ -55,9 +55,9 @@ } }, "node_modules/@napi-rs/cli": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.3.tgz", - "integrity": "sha512-3mLNPlbbOhpbIUKicLrJtIearlHXUuXL3UeueYyRRplpVMNkdn8xCyzY6PcYZi3JXR8bmCOiWgkVmLnrSL7DKw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-mFEzwrg4IOLngGd2/P6yeqIWgwQNn59Z08n1rndu6kLDq1gg954NH9cM1O9Da0RJuybt46p43lqgSsnAY2mxqA==", "dev": true, "bin": { "napi": "scripts/index.js" @@ -95,16 +95,19 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -114,9 +117,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -205,6 +208,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/crates/bitwarden-napi/package.json b/crates/bitwarden-napi/package.json index 50bebb58b..a0dbcee3b 100644 --- a/crates/bitwarden-napi/package.json +++ b/crates/bitwarden-napi/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 4c1ce2101..a7b774c3c 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,15 +12,19 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "2.7.0" +async-lock = "3.0.0" +chrono = { version = ">=0.4.26, <0.5", features = [ + "serde", + "std", +], default-features = false } env_logger = "0.10.0" -uniffi = "=0.24.1" +uniffi = "=0.25.0" schemars = { version = ">=0.8, <0.9", optional = true } bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.24.1", features = ["build"] } +uniffi = { version = "=0.25.0", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index bd30e974e..bc47a19c3 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -3,7 +3,10 @@ use bitwarden::{ client::kdf::Kdf, mobile::crypto::InitCryptoRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, - vault::{Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView}, + vault::{ + Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, + TotpResponse, + }, }; use schemars::JsonSchema; @@ -35,4 +38,7 @@ pub enum DocRef { // Kdf Kdf(Kdf), + + /// TOTP + TotpResponse(TotpResponse), } diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index 1a1e9d29a..b6175eb3b 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -1,7 +1,7 @@ use std::fmt::{Display, Formatter}; // Name is converted from *Error to *Exception, so we can't just name the enum Error because Exception already exists -#[derive(uniffi::Error)] +#[derive(uniffi::Error, Debug)] #[uniffi(flat_error)] pub enum BitwardenError { E(bitwarden::error::Error), @@ -21,4 +21,12 @@ impl Display for BitwardenError { } } +impl std::error::Error for BitwardenError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + BitwardenError::E(e) => Some(e), + } + } +} + pub type Result = std::result::Result; diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 2e2543ab3..6e5415d38 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -9,6 +9,7 @@ use bitwarden::{client::client_settings::ClientSettings, mobile::crypto::InitCry pub mod auth; mod error; pub mod tool; +mod uniffi_support; pub mod vault; #[cfg(feature = "docs")] diff --git a/crates/bitwarden-uniffi/src/sdk.udl b/crates/bitwarden-uniffi/src/sdk.udl deleted file mode 100644 index 96cfb31c0..000000000 --- a/crates/bitwarden-uniffi/src/sdk.udl +++ /dev/null @@ -1,8 +0,0 @@ -interface Client { - constructor(optional string settings = ""); - string run_command(string command); -}; - -namespace bitwarden { - -}; diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs new file mode 100644 index 000000000..82cd343a7 --- /dev/null +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -0,0 +1,3 @@ +// Forward the type definitions to the main bitwarden crate +type DateTime = chrono::DateTime; +uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index 2692632ab..79b3e5835 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -1,5 +1,8 @@ use std::sync::Arc; +use bitwarden::vault::TotpResponse; +use chrono::{DateTime, Utc}; + use crate::Client; pub mod ciphers; @@ -37,4 +40,20 @@ impl ClientVault { pub fn sends(self: Arc) -> Arc { Arc::new(sends::ClientSends(self.0.clone())) } + + /// Generate a TOTP code from a provided key. + /// + /// The key can be either: + /// - A base32 encoded string + /// - OTP Auth URI + /// - Steam URI + pub async fn generate_totp(&self, key: String, time: Option>) -> TotpResponse { + self.0 + .0 + .read() + .await + .vault() + .generate_totp(key, time) + .await + } } diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index d61af5206..8bb18ff72 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,10 +7,16 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Deprecated + +- `client.access_token_login()` is now deprecated and will be removed in a future release. Please + use `client.auth().login_access_token()` instead. (#319) + +## [0.3.1] - 2023-10-13 + ### Changed - `auth::request::AccessTokenLoginRequest` moved to `auth::login::AccessTokenLoginRequest` (#178) - - Support for fetching multiple secrets by ids (#150) ## [0.3.0] - 2023-07-26 diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 1f89c7aae..65db9db7d 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden" -version = "0.3.0" +version = "0.3.1" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" @@ -50,13 +50,13 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -uniffi = { version = "=0.24.1", optional = true } +uniffi = { version = "=0.25.0", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } -bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.1" } -bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.1" } +bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } +bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } [dev-dependencies] rand_chacha = "0.3.1" diff --git a/crates/bitwarden/README.md b/crates/bitwarden/README.md index a0708b7e6..67c347583 100644 --- a/crates/bitwarden/README.md +++ b/crates/bitwarden/README.md @@ -42,7 +42,7 @@ async fn test() -> Result<()> { // Before we operate, we need to authenticate with a token let token = AccessTokenLoginRequest { access_token: String::from("") }; - client.access_token_login(&token).await.unwrap(); + client.auth().login_access_token(&token).await.unwrap(); let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 8ffca0a44..aa1615c3b 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,14 +1,40 @@ -use super::{ - password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, - register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, +#[cfg(feature = "secrets")] +use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::{auth::renew::renew_token, error::Result, Client}; +#[cfg(feature = "internal")] +use crate::{ + auth::{ + login::{ + login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, + ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, + TwoFactorEmailRequest, + }, + password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, + register::{make_register_keys, register}, + RegisterKeyResponse, RegisterRequest, + }, + client::kdf::Kdf, }; -use crate::{client::kdf::Kdf, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, } +impl<'a> ClientAuth<'a> { + pub async fn renew_token(&mut self) -> Result<()> { + renew_token(self.client).await + } + + #[cfg(feature = "secrets")] + pub async fn login_access_token( + &mut self, + input: &AccessTokenLoginRequest, + ) -> Result { + login_access_token(self.client, input).await + } +} + +#[cfg(feature = "internal")] impl<'a> ClientAuth<'a> { pub async fn password_strength( &self, @@ -37,10 +63,33 @@ impl<'a> ClientAuth<'a> { make_register_keys(email, password, kdf) } - #[cfg(feature = "internal")] pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } + + pub async fn prelogin(&mut self, email: String) -> Result { + use crate::auth::login::request_prelogin; + + request_prelogin(self.client, email).await?.try_into() + } + + pub async fn login_password( + &mut self, + input: &PasswordLoginRequest, + ) -> Result { + login_password(self.client, input).await + } + + pub async fn login_api_key( + &mut self, + input: &ApiKeyLoginRequest, + ) -> Result { + login_api_key(self.client, input).await + } + + pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { + send_two_factor_email(self.client, tf).await + } } impl<'a> Client { @@ -48,3 +97,101 @@ impl<'a> Client { ClientAuth { client: self } } } + +#[cfg(test)] +mod tests { + + #[cfg(feature = "secrets")] + #[tokio::test] + async fn test_access_token_login() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; + + // Create the mock server with the necessary routes for this test + let (_server, mut client) = crate::util::start_mock(vec![ + Mock::given(matchers::path("/identity/connect/token")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ + ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ + iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ + mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ + 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ + ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ + 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ + SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ + Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ + He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ + TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", + "expires_in":3600, + "token_type":"Bearer", + "scope":"api.secrets", + "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ + Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) + )), + Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "secrets":[{ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z" + }], + "projects":[], + "object":"SecretsWithProjectsList" + }) + )), + Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", + "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z", + "object":"secret" + }) + )) + ]).await; + + // Test the login is correct and we store the returned organization ID correctly + let res = client + .auth() + .login_access_token(&AccessTokenLoginRequest { + access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), + }) + .await + .unwrap(); + assert!(res.authenticated); + let organization_id = client.get_access_token_organization().unwrap(); + assert_eq!( + organization_id.to_string(), + "f4e44a7f-1190-432a-9d4a-af96013127cb" + ); + + // Test that we can retrieve the list of secrets correctly + let mut res = client + .secrets() + .list(&SecretIdentifiersRequest { organization_id }) + .await + .unwrap(); + assert_eq!(res.data.len(), 1); + + // Test that given a secret ID we can get it's data + let res = client + .secrets() + .get(&SecretGetRequest { + id: res.data.remove(0).id, + }) + .await + .unwrap(); + assert_eq!(res.key, "TEST"); + assert_eq!(res.note, "TEST"); + assert_eq!(res.value, "TEST"); + } +} diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs new file mode 100644 index 000000000..14cbaf84f --- /dev/null +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -0,0 +1,71 @@ +use std::str::FromStr; + +use base64::Engine; + +use crate::{error::Result, util::BASE64_ENGINE}; + +/// A Bitwarden secrets manager JWT Token. +/// +/// References: +/// - +/// - +/// +/// TODO: We need to expand this to support user based JWT tokens. +#[derive(serde::Deserialize)] +pub struct JWTToken { + pub sub: String, + pub email: Option, + pub organization: Option, + pub scope: Vec, +} + +impl FromStr for JWTToken { + type Err = crate::error::Error; + + /// Parses a JWT token from a string. + /// + /// **Note:** This function does not validate the token signature. + fn from_str(s: &str) -> Result { + let split = s.split('.').collect::>(); + if split.len() != 3 { + return Err(crate::error::Error::Internal( + "JWT token has an invalid number of parts", + )); + } + let decoded = BASE64_ENGINE.decode(split[1])?; + Ok(serde_json::from_slice(&decoded)?) + } +} + +#[cfg(test)] +mod tests { + use crate::auth::jwt_token::JWTToken; + + #[test] + fn can_decode_jwt() { + let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ + g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ + YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ + 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ + EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ + iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ + bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ + jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ + IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ + XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ + wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ + a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ + ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ + qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ + wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ + U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ + f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; + + let token: JWTToken = jwt.parse().unwrap(); + assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); + assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); + assert_eq!(token.organization.as_deref(), None); + assert_eq!(token.scope[0], "api"); + assert_eq!(token.scope[1], "offline_access"); + } +} diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 46fa35779..1ec8c8b34 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use base64::Engine; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,30 +6,31 @@ use crate::{ auth::{ api::{request::AccessTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, - util::{decode_token, BASE64_ENGINE}, + util::BASE64_ENGINE, Client, }; -pub(crate) async fn access_token_login( +pub(crate) async fn login_access_token( client: &mut Client, input: &AccessTokenLoginRequest, ) -> Result { //info!("api key logging in"); //debug!("{:#?}, {:#?}", client, input); - let access_token = AccessToken::from_str(&input.access_token)?; + let access_token: AccessToken = input.access_token.parse()?; let response = request_access_token(client, &access_token).await?; if let IdentityTokenResponse::Payload(r) = &response { // Extract the encrypted payload and use the access token encryption key to decrypt it - let payload = EncString::from_str(&r.encrypted_payload)?; + let payload: EncString = r.encrypted_payload.parse()?; - let decrypted_payload = payload.decrypt_with_key(&access_token.encryption_key)?; + let decrypted_payload: Vec = payload.decrypt_with_key(&access_token.encryption_key)?; // Once decrypted, we have to JSON decode to extract the organization encryption key #[derive(serde::Deserialize)] @@ -46,7 +45,7 @@ pub(crate) async fn access_token_login( let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an access token let organization_id = access_token_obj diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index a9fa954d7..db5cbe01d 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -7,15 +5,15 @@ use crate::{ auth::{ api::{request::ApiTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{LoginMethod, UserLoginMethod}, crypto::EncString, error::{Error, Result}, - util::decode_token, Client, }; -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( client: &mut Client, input: &ApiKeyLoginRequest, ) -> Result { @@ -25,14 +23,14 @@ pub(crate) async fn api_key_login( let response = request_api_identity_tokens(client, input).await?; if let IdentityTokenResponse::Authenticated(r) = &response { - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an api key let email = access_token_obj .email .ok_or(Error::Internal("Access token doesn't contain email"))?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; client.set_tokens( r.access_token.clone(), @@ -46,8 +44,8 @@ pub(crate) async fn api_key_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 9e1dbb818..4ec9d1b49 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -14,7 +14,7 @@ pub mod response; mod password; #[cfg(feature = "internal")] -pub(crate) use password::password_login; +pub(crate) use password::login_password; #[cfg(feature = "internal")] pub use password::PasswordLoginRequest; pub use password::PasswordLoginResponse; @@ -28,14 +28,14 @@ pub use two_factor::{TwoFactorEmailRequest, TwoFactorProvider, TwoFactorRequest} #[cfg(feature = "internal")] mod api_key; #[cfg(feature = "internal")] -pub(crate) use api_key::api_key_login; +pub(crate) use api_key::login_api_key; #[cfg(feature = "internal")] pub use api_key::{ApiKeyLoginRequest, ApiKeyLoginResponse}; #[cfg(feature = "secrets")] mod access_token; #[cfg(feature = "secrets")] -pub(crate) use access_token::access_token_login; +pub(super) use access_token::login_access_token; #[cfg(feature = "secrets")] pub use access_token::{AccessTokenLoginRequest, AccessTokenLoginResponse}; diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 33f7ea338..a320131ea 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "internal")] -use std::str::FromStr; - #[cfg(feature = "internal")] use log::{debug, info}; use schemars::JsonSchema; @@ -25,7 +22,7 @@ use crate::{ }; #[cfg(feature = "internal")] -pub(crate) async fn password_login( +pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { @@ -49,8 +46,8 @@ pub(crate) async fn password_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index 04c411349..d8ede2473 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -20,7 +20,7 @@ pub(crate) async fn send_two_factor_email( input: &TwoFactorEmailRequest, ) -> Result<()> { // TODO: This should be resolved from the client - let kdf = client.prelogin(input.email.clone()).await?; + let kdf = client.auth().prelogin(input.email.clone()).await?; let password_hash = determine_password_hash(&input.email, &kdf, &input.password).await?; diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index f2f6a3144..023f3270b 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,10 +1,11 @@ pub(super) mod api; -#[cfg(feature = "internal")] pub mod client_auth; +mod jwt_token; pub mod login; #[cfg(feature = "internal")] pub mod password; pub mod renew; +pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 8336ec9c9..206c1905b 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -79,7 +79,7 @@ pub(super) fn make_register_keys( #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct RegisterKeyResponse { - master_password_hash: String, - encrypted_user_key: String, - keys: RsaKeyPair, + pub master_password_hash: String, + pub encrypted_user_key: String, + pub keys: RsaKeyPair, } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index f6eb0c954..213a12fb2 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,11 +1,12 @@ use std::time::{Duration, Instant}; +use reqwest::header::{self}; +use uuid::Uuid; + +#[cfg(feature = "secrets")] +use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ - auth::login::{ - api_key_login, password_login, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, - }, client::kdf::Kdf, crypto::EncString, platform::{ @@ -13,13 +14,7 @@ use crate::{ SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, }, }; -use reqwest::header::{self}; -use uuid::Uuid; - -#[cfg(feature = "secrets")] -use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; use crate::{ - auth::renew::renew_token, client::{ client_settings::{ClientSettings, DeviceType}, encryption_settings::EncryptionSettings, @@ -133,39 +128,17 @@ impl Client { pub(crate) async fn get_api_configurations(&mut self) -> &ApiConfigurations { // At the moment we ignore the error result from the token renewal, if it fails, // the token will end up expiring and the next operation is going to fail anyway. - self.renew_token().await.ok(); + self.auth().renew_token().await.ok(); &self.__api_configurations } - #[cfg(feature = "internal")] - pub async fn prelogin(&mut self, email: String) -> Result { - use crate::auth::login::request_prelogin; - - request_prelogin(self, email).await?.try_into() - } - - #[cfg(feature = "internal")] - pub async fn password_login( - &mut self, - input: &PasswordLoginRequest, - ) -> Result { - password_login(self, input).await - } - - #[cfg(feature = "internal")] - pub async fn api_key_login( - &mut self, - input: &ApiKeyLoginRequest, - ) -> Result { - api_key_login(self, input).await - } - #[cfg(feature = "secrets")] + #[deprecated(note = "Use auth().login_access_token() instead")] pub async fn access_token_login( &mut self, input: &AccessTokenLoginRequest, ) -> Result { - access_token_login(self, input).await + self.auth().login_access_token(input).await } #[cfg(feature = "internal")] @@ -223,10 +196,6 @@ impl Client { self.__api_configurations.api.oauth_access_token = Some(token); } - pub async fn renew_token(&mut self) -> Result<()> { - renew_token(self).await - } - #[cfg(feature = "internal")] pub fn is_authed(&self) -> bool { self.token.is_some() || self.login_method.is_some() @@ -279,104 +248,4 @@ impl Client { pub fn fingerprint(&mut self, input: &FingerprintRequest) -> Result { generate_fingerprint(input) } - - #[cfg(feature = "internal")] - pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { - send_two_factor_email(self, tf).await - } -} - -#[cfg(test)] -mod tests { - use wiremock::{matchers, Mock, ResponseTemplate}; - - use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; - - #[tokio::test] - async fn test_access_token_login() { - // Create the mock server with the necessary routes for this test - let (_server, mut client) = crate::util::start_mock(vec![ - Mock::given(matchers::path("/identity/connect/token")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ - ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ - iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ - mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ - 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ - ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ - 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ - SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ - Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ - He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ - TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", - "expires_in":3600, - "token_type":"Bearer", - "scope":"api.secrets", - "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ - Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) - )), - Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "secrets":[{ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z" - }], - "projects":[], - "object":"SecretsWithProjectsList" - }) - )), - Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", - "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z", - "object":"secret" - }) - )) - ]).await; - - // Test the login is correct and we store the returned organization ID correctly - let res = client - .access_token_login(&AccessTokenLoginRequest { - access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), - }) - .await - .unwrap(); - assert!(res.authenticated); - let organization_id = client.get_access_token_organization().unwrap(); - assert_eq!( - organization_id.to_string(), - "f4e44a7f-1190-432a-9d4a-af96013127cb" - ); - - // Test that we can retrieve the list of secrets correctly - let mut res = client - .secrets() - .list(&SecretIdentifiersRequest { organization_id }) - .await - .unwrap(); - assert_eq!(res.data.len(), 1); - - // Test that given a secret ID we can get it's data - let res = client - .secrets() - .get(&SecretGetRequest { - id: res.data.remove(0).id, - }) - .await - .unwrap(); - assert_eq!(res.key, "TEST"); - assert_eq!(res.note, "TEST"); - assert_eq!(res.value, "TEST"); - } } diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 9c79a1781..da5398a12 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -4,14 +4,15 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::client::UserLoginMethod, + crate::{ + client::UserLoginMethod, + crypto::{EncString, KeyDecryptable}, + error::{CryptoError, Result}, + }, rsa::{pkcs8::DecodePrivateKey, Oaep}, }; -use crate::{ - crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey}, - error::{CryptoError, Result}, -}; +use crate::crypto::SymmetricCryptoKey; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, @@ -46,7 +47,7 @@ impl EncryptionSettings { // Decrypt the private key with the user key let private_key = { - let dec = private_key.decrypt_with_key(&user_key)?; + let dec: Vec = private_key.decrypt_with_key(&user_key)?; Some( rsa::RsaPrivateKey::from_pkcs8_der(&dec) .map_err(|_| CryptoError::InvalidKey)?, @@ -98,7 +99,7 @@ impl EncryptionSettings { Ok(self) } - fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { + pub(crate) fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { // If we don't have a private key set (to decode multiple org keys), we just use the main user key if self.private_key.is_none() { return Some(&self.user_key); @@ -109,43 +110,4 @@ impl EncryptionSettings { None => Some(&self.user_key), } } - - pub(crate) fn decrypt_bytes( - &self, - cipher: &EncString, - org_id: &Option, - ) -> Result> { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - cipher.decrypt_with_key(key) - } - - pub(crate) fn decrypt(&self, cipher: &EncString, org_id: &Option) -> Result { - let dec = self.decrypt_bytes(cipher, org_id)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) - } - - pub(crate) fn encrypt(&self, data: &[u8], org_id: &Option) -> Result { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - - let dec = encrypt_aes256_hmac(data, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key)?; - Ok(dec) - } -} - -#[cfg(test)] -mod tests { - use super::{EncryptionSettings, SymmetricCryptoKey}; - use crate::crypto::{Decryptable, Encryptable}; - - #[test] - fn test_encryption_settings() { - let key = SymmetricCryptoKey::generate("test"); - let settings = EncryptionSettings::new_single_key(key); - - let test_string = "encrypted_test_string".to_string(); - let cipher = test_string.clone().encrypt(&settings, &None).unwrap(); - - let decrypted_str = cipher.decrypt(&settings, &None).unwrap(); - assert_eq!(decrypted_str, test_string); - } } diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 34d4021e8..132718349 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -1,3 +1,13 @@ +//! # AES operations +//! +//! Contains low level AES operations used by the rest of the library. +//! +//! **Warning**: Consider carefully if you have to use these functions directly, as generally we +//! expose higher level functions that are easier to use and more secure. +//! +//! In most cases you should use the [EncString] with [KeyEncryptable][super::KeyEncryptable] & +//! [KeyDecryptable][super::KeyDecryptable] instead. + use aes::cipher::{ block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, BlockEncryptMut, KeyIvInit, @@ -10,6 +20,9 @@ use crate::{ error::{CryptoError, Result}, }; +/// Decrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [decrypt_aes256_hmac], but does not validate the MAC. pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) -> Result> { // Decrypt data let iv = GenericArray::from_slice(iv); @@ -18,13 +31,16 @@ pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; - //Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length let decrypted_len = decrypted_key_slice.len(); data.truncate(decrypted_len); Ok(data) } +/// Decrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [decrypt_aes256], but also validates the MAC. pub fn decrypt_aes256_hmac( iv: &[u8; 16], mac: &[u8; 32], @@ -39,12 +55,27 @@ pub fn decrypt_aes256_hmac( decrypt_aes256(iv, data, key) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [encrypt_aes256_hmac], but does't generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_B64 EncString +#[allow(unused)] pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { let (iv, data) = encrypt_aes256_internal(data_dec, key); Ok(EncString::AesCbc256_B64 { iv, data }) } +/// Encrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [encrypt_aes256], but also generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_HmacSha256_B64 EncString pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, @@ -56,6 +87,11 @@ pub fn encrypt_aes256_hmac( Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Used internally by: +/// - [encrypt_aes256] +/// - [encrypt_aes256_hmac] fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; rand::thread_rng().fill_bytes(&mut iv); @@ -65,6 +101,7 @@ fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; (iv, data) } +/// Validate a MAC using HMAC-SHA256. fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); hmac.update(iv); diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index b701aaf8f..ac7f3fc6b 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -2,15 +2,54 @@ use std::{fmt::Display, str::FromStr}; use base64::Engine; use serde::{de::Visitor, Deserialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{decrypt_aes256_hmac, Decryptable, Encryptable, SymmetricCryptoKey}, + crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; +use super::{KeyDecryptable, KeyEncryptable, LocateKey}; + +/// # Encrypted string primitive +/// +/// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are +/// are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and decrypt +/// data using [SymmetricCryptoKey]s. +/// +/// The flexibility of the [EncString] type allows for different encryption algorithms to be used +/// which is represented by the different variants of the enum. +/// +/// ## Note +/// +/// We are currently in the progress of splitting the [EncString] into distinct AES and RSA +/// variants. To provide better control of which encryption algorithm is expected. +/// +/// For backwards compatibility we will rarely if ever be able to remove support for decrypting old +/// variants, but we should be opinionated in which variants are used for encrypting. +/// +/// ## Variants +/// - [AesCbc256_B64](EncString::AesCbc256_B64) +/// - [AesCbc128_HmacSha256_B64](EncString::AesCbc128_HmacSha256_B64) +/// - [AesCbc256_HmacSha256_B64](EncString::AesCbc256_HmacSha256_B64) +/// - [Rsa2048_OaepSha256_B64](EncString::Rsa2048_OaepSha256_B64) +/// - [Rsa2048_OaepSha1_B64](EncString::Rsa2048_OaepSha1_B64) +/// +/// ## Serialization +/// +/// [EncString] implements [Display] and [FromStr] to allow for easy serialization and uses a +/// custom scheme to represent the different variants. +/// +/// The scheme is one of the following schemes: +/// - `[type].[iv]|[data]` +/// - `[type].[iv]|[data]|[mac]` +/// - `[type].[data]` +/// +/// Where: +/// - `[type]`: is a digit number representing the variant. +/// - `[iv]`: (optional) is the initialization vector used for encryption. +/// - `[data]`: is the encrypted data. +/// - `[mac]`: (optional) is the MAC used to validate the integrity of the data. #[derive(Clone)] #[allow(unused, non_camel_case_types)] pub enum EncString { @@ -40,13 +79,14 @@ pub enum EncString { Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec }, } -// We manually implement these to make sure we don't print any sensitive data +/// To avoid printing sensitive information, [EncString] debug prints to `EncString`. impl std::fmt::Debug for EncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EncString").finish() } } +/// Deserializes an [EncString] from a string. impl FromStr for EncString { type Err = Error; @@ -291,6 +331,7 @@ impl serde::Serialize for EncString { } impl EncString { + /// The numerical representation of the encryption type of the [EncString]. const fn enc_type(&self) -> u8 { match self { EncString::AesCbc256_B64 { .. } => 0, @@ -304,8 +345,24 @@ impl EncString { EncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, } } +} + +fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { + move |e: Vec<_>| EncStringParseError::InvalidLength { + expected, + got: e.len(), + } +} + +impl LocateKey for EncString {} +impl KeyEncryptable for &[u8] { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + super::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + } +} - pub fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { +impl KeyDecryptable> for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; @@ -317,29 +374,36 @@ impl EncString { } } -fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { - move |e: Vec<_>| EncStringParseError::InvalidLength { - expected, - got: e.len(), - } -} - -impl Encryptable for String { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.encrypt(self.as_bytes(), org_id) +impl KeyEncryptable for String { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + self.as_bytes().encrypt_with_key(key) } } -impl Decryptable for EncString { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.decrypt(self, org_id) +impl KeyDecryptable for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let dec: Vec = self.decrypt_with_key(key)?; + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) } } #[cfg(test)] mod tests { + use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use super::EncString; + #[test] + fn test_enc_string_roundtrip() { + let key = SymmetricCryptoKey::generate("test"); + + let test_string = "encrypted_test_string".to_string(); + let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); + + let decrypted_str: String = cipher.decrypt_with_key(&key).unwrap(); + assert_eq!(decrypted_str, test_string); + } + #[test] fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index bd987060f..f1bc78f15 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -2,25 +2,44 @@ use std::{collections::HashMap, hash::Hash}; use uuid::Uuid; -use crate::{client::encryption_settings::EncryptionSettings, error::Result}; +use crate::{ + client::encryption_settings::EncryptionSettings, + error::{Error, Result}, +}; +use super::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + +pub trait LocateKey { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + org_id: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(org_id) + } +} + +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Encryptable { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; } +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } -impl, Output> Encryptable> for Option { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.map(|e| e.encrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Encryptable for T { + fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.encrypt_with_key(key) } } -impl, Output> Decryptable> for Option { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.as_ref().map(|e| e.decrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Decryptable for T { + fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.decrypt_with_key(key) } } @@ -46,7 +65,7 @@ impl, Output, Id: Hash + Eq> Encryptable Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) - .collect::>>() + .collect() } } @@ -60,18 +79,6 @@ impl, Output, Id: Hash + Eq + Copy> Decryptable Result> { self.iter() .map(|(id, e)| Ok((*id, e.decrypt(enc, org_id)?))) - .collect::>>() - } -} - -impl, Output> Encryptable for Box { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (*self).encrypt(enc, org_id) - } -} - -impl, Output> Decryptable for Box { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (**self).decrypt(enc, org_id) + .collect() } } diff --git a/crates/bitwarden/src/crypto/fingerprint.rs b/crates/bitwarden/src/crypto/fingerprint.rs index 9473a2cda..ddcf89d40 100644 --- a/crates/bitwarden/src/crypto/fingerprint.rs +++ b/crates/bitwarden/src/crypto/fingerprint.rs @@ -7,6 +7,11 @@ use crate::{ wordlist::EFF_LONG_WORD_LIST, }; +/// Computes a fingerprint of the given `fingerprint_material` using the given `public_key`. +/// +/// This is commonly used for account fingerprints. With the following arguments: +/// - `fingerprint_material`: user's id. +/// - `public_key`: user's public key. pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result { let mut h = sha2::Sha256::new(); h.update(public_key); @@ -22,6 +27,7 @@ pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Resu Ok(hash_word(user_fingerprint).unwrap()) } +/// Derive a 5 word phrase from a 32 byte hash. fn hash_word(hash: [u8; 32]) -> Result { let minimum_entropy = 64; diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden/src/crypto/key_encryptable.rs new file mode 100644 index 000000000..99c610bb2 --- /dev/null +++ b/crates/bitwarden/src/crypto/key_encryptable.rs @@ -0,0 +1,69 @@ +use std::{collections::HashMap, hash::Hash}; + +use crate::error::Result; + +use super::SymmetricCryptoKey; + +pub trait KeyEncryptable { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; +} + +pub trait KeyDecryptable { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result; +} + +impl, Output> KeyEncryptable> for Option { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.map(|e| e.encrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyDecryptable> for Option { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.as_ref().map(|e| e.decrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyEncryptable for Box { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + (*self).encrypt_with_key(key) + } +} + +impl, Output> KeyDecryptable for Box { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + (**self).decrypt_with_key(key) + } +} + +impl, Output> KeyEncryptable> for Vec { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter().map(|e| e.encrypt_with_key(key)).collect() + } +} + +impl, Output> KeyDecryptable> for Vec { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter().map(|e| e.decrypt_with_key(key)).collect() + } +} + +impl, Output, Id: Hash + Eq> KeyEncryptable> + for HashMap +{ + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter() + .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?))) + .collect() + } +} + +impl, Output, Id: Hash + Eq + Copy> KeyDecryptable> + for HashMap +{ + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter() + .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?))) + .collect() + } +} diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index f908d5299..b2c8e6e5f 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256, hkdf_expand, EncString, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, - PBKDF_SHA256_HMAC_OUT_SIZE, + encrypt_aes256_hmac, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, + SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -41,23 +41,33 @@ impl MasterKey { } pub(crate) fn make_user_key(&self) -> Result<(UserKey, EncString)> { - let mut user_key = [0u8; 64]; - rand::thread_rng().fill(&mut user_key); - - let protected = encrypt_aes256(&user_key, self.0.key)?; - - let u: &[u8] = &user_key; - Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) + make_user_key(rand::thread_rng(), self) } pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; - let dec = user_key.decrypt_with_key(&stretched_key)?; + let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_slice()) } } +/// Generate a new random user key and encrypt it with the master key. +fn make_user_key( + mut rng: impl rand::RngCore, + master_key: &MasterKey, +) -> Result<(UserKey, EncString)> { + let mut user_key = [0u8; 64]; + rng.fill(&mut user_key); + + let stretched_key = stretch_master_key(master_key)?; + let protected = + encrypt_aes256_hmac(&user_key, stretched_key.mac_key.unwrap(), stretched_key.key)?; + + let u: &[u8] = &user_key; + Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) +} + /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { let hash = match kdf { @@ -112,7 +122,9 @@ fn stretch_master_key(master_key: &MasterKey) -> Result { mod tests { use std::num::NonZeroU32; - use super::{stretch_master_key, HashPurpose, MasterKey}; + use rand::SeedableRng; + + use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; use crate::{client::kdf::Kdf, crypto::SymmetricCryptoKey}; #[test] @@ -225,4 +237,47 @@ mod tests { .unwrap(), ); } + + #[test] + fn test_make_user_key() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let master_key = MasterKey(SymmetricCryptoKey { + key: [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, 167, + 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + mac_key: None, + }); + + let (user_key, protected) = make_user_key(&mut rng, &master_key).unwrap(); + + assert_eq!( + user_key.0.key.as_slice(), + [ + 62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161, 44, 132, 14, + 195, 206, 154, 127, 59, 24, 27, 225, 136, 239, 113, 26, 30 + ] + ); + assert_eq!( + user_key.0.mac_key.unwrap().as_slice(), + [ + 152, 76, 225, 114, 185, 33, 111, 65, 159, 68, 83, 103, 69, 109, 86, 25, 49, 74, 66, + 163, 218, 134, 176, 1, 56, 123, 253, 184, 14, 12, 254, 66 + ] + ); + + // Ensure we can decrypt the key and get back the same key + let decrypted = master_key.decrypt_user_key(protected).unwrap(); + + assert_eq!( + decrypted.key, user_key.0.key, + "Decrypted key doesn't match user key" + ); + assert_eq!( + decrypted.mac_key, user_key.0.mac_key, + "Decrypted key doesn't match user key" + ); + } } diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index b35157981..b030a5107 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -29,9 +29,11 @@ use crate::error::{Error, Result}; mod enc_string; pub use enc_string::EncString; mod encryptable; -pub use encryptable::{Decryptable, Encryptable}; +pub use encryptable::{Decryptable, Encryptable, LocateKey}; +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; mod aes_ops; -pub use aes_ops::{decrypt_aes256, decrypt_aes256_hmac, encrypt_aes256, encrypt_aes256_hmac}; +use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; mod symmetric_crypto_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod shareable_key; diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs index 0fe560665..7f5bae413 100644 --- a/crates/bitwarden/src/crypto/user_key.rs +++ b/crates/bitwarden/src/crypto/user_key.rs @@ -6,7 +6,7 @@ use crate::{ error::Result, }; -pub(crate) struct UserKey(SymmetricCryptoKey); +pub(crate) struct UserKey(pub(super) SymmetricCryptoKey); impl UserKey { pub(crate) fn new(key: SymmetricCryptoKey) -> Self { diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index a61857992..20e36d237 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -39,7 +39,7 @@ //! //! // Before we operate, we need to authenticate with a token //! let token = AccessTokenLoginRequest { access_token: String::from("") }; -//! client.access_token_login(&token).await.unwrap(); +//! client.auth().login_access_token(&token).await.unwrap(); //! //! let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; //! println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bitwarden/src/mobile/mod.rs b/crates/bitwarden/src/mobile/mod.rs index ad2d794af..fe3083aa8 100644 --- a/crates/bitwarden/src/mobile/mod.rs +++ b/crates/bitwarden/src/mobile/mod.rs @@ -3,8 +3,11 @@ pub mod crypto; pub mod kdf; pub mod vault; -pub(crate) mod client_crypto; -pub(crate) mod client_kdf; +mod client_crypto; +mod client_kdf; + +pub use client_crypto::ClientCrypto; +pub use client_kdf::ClientKdf; // Usually we wouldn't want to expose EncStrings in the API or the schemas, // but we need them in the mobile API, so define it here to limit the scope diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index 0adef3410..b1de05f44 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -2,8 +2,8 @@ use std::path::Path; use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, EncString, Encryptable}, - error::Result, + crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}, + error::{Error, Result}, vault::{Send, SendListView, SendView}, Client, }; @@ -43,11 +43,11 @@ impl<'a> ClientSends<'a> { pub async fn decrypt_buffer(&self, send: Send, encrypted_buffer: &[u8]) -> Result> { let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; + let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; let buf = EncString::from_buffer(encrypted_buffer)?; - - enc.decrypt_bytes(&buf, &None) + buf.decrypt_with_key(&key) } pub async fn encrypt(&self, send_view: SendView) -> Result { @@ -71,10 +71,14 @@ impl<'a> ClientSends<'a> { } pub async fn encrypt_buffer(&self, send: Send, buffer: &[u8]) -> Result> { - let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; - - let enc = enc.encrypt(buffer, &None)?; + let key = self + .client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; + + let enc = buffer.encrypt_with_key(&key)?; enc.to_buffer() } } diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs new file mode 100644 index 000000000..97eb243af --- /dev/null +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -0,0 +1,18 @@ +use chrono::{DateTime, Utc}; + +use crate::vault::{generate_totp, TotpResponse}; + +use super::client_vault::ClientVault; + +impl<'a> ClientVault<'a> { + /// Generate a TOTP code from a provided key. + /// + /// Key can be either: + /// - A base32 encoded string + /// - OTP Auth URI + /// - Steam URI + /// + pub async fn generate_totp(&'a self, key: String, time: Option>) -> TotpResponse { + generate_totp(key, time).await + } +} diff --git a/crates/bitwarden/src/mobile/vault/mod.rs b/crates/bitwarden/src/mobile/vault/mod.rs index f0fe4ca76..97f9556af 100644 --- a/crates/bitwarden/src/mobile/vault/mod.rs +++ b/crates/bitwarden/src/mobile/vault/mod.rs @@ -3,4 +3,12 @@ mod client_collection; mod client_folders; mod client_password_history; mod client_sends; +mod client_totp; mod client_vault; + +pub use client_ciphers::ClientCiphers; +pub use client_collection::ClientCollections; +pub use client_folders::ClientFolders; +pub use client_password_history::ClientPasswordHistory; +pub use client_sends::ClientSends; +pub use client_vault::ClientVault; diff --git a/crates/bitwarden/src/secrets_manager/mod.rs b/crates/bitwarden/src/secrets_manager/mod.rs index 0afbfe38c..27b84121e 100644 --- a/crates/bitwarden/src/secrets_manager/mod.rs +++ b/crates/bitwarden/src/secrets_manager/mod.rs @@ -3,3 +3,6 @@ pub mod secrets; mod client_projects; mod client_secrets; + +pub use client_projects::ClientProjects; +pub use client_secrets::ClientSecrets; diff --git a/crates/bitwarden/src/secrets_manager/projects/create.rs b/crates/bitwarden/src/secrets_manager/projects/create.rs index 3ba6ecd36..996a3463e 100644 --- a/crates/bitwarden/src/secrets_manager/projects/create.rs +++ b/crates/bitwarden/src/secrets_manager/projects/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -19,12 +23,13 @@ pub(crate) async fn create_project( client: &mut Client, input: &ProjectCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectCreateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/projects/update.rs b/crates/bitwarden/src/secrets_manager/projects/update.rs index b0a040c96..6a0479d88 100644 --- a/crates/bitwarden/src/secrets_manager/projects/update.rs +++ b/crates/bitwarden/src/secrets_manager/projects/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -21,12 +25,13 @@ pub(crate) async fn update_project( client: &mut Client, input: &ProjectPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectUpdateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/secrets/create.rs b/crates/bitwarden/src/secrets_manager/secrets/create.rs index ddec3abd4..a1bb81799 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/create.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{error::Result, Client}; +use crate::{ + crypto::KeyEncryptable, + error::{Error, Result}, + Client, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn create_secret( client: &mut Client, input: &SecretCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretCreateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); diff --git a/crates/bitwarden/src/secrets_manager/secrets/update.rs b/crates/bitwarden/src/secrets_manager/secrets/update.rs index b1a82bad8..970812c5a 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/update.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn update_secret( client: &mut Client, input: &SecretPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretUpdateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 508aae8fb..1170dbd38 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -6,6 +6,7 @@ use crate::{ }; mod client_exporter; +pub use client_exporter::ClientExporters; #[derive(JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs index 31c7c3e47..12c526930 100644 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ b/crates/bitwarden/src/tool/generators/mod.rs @@ -2,5 +2,6 @@ mod client_generator; mod passphrase; mod password; +pub use client_generator::ClientGenerator; pub use passphrase::PassphraseGeneratorRequest; pub use password::PasswordGeneratorRequest; diff --git a/crates/bitwarden/src/tool/mod.rs b/crates/bitwarden/src/tool/mod.rs index 2130a6b0c..212ce4bf7 100644 --- a/crates/bitwarden/src/tool/mod.rs +++ b/crates/bitwarden/src/tool/mod.rs @@ -1,5 +1,5 @@ mod exporters; mod generators; -pub use exporters::ExportFormat; -pub use generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; +pub use exporters::{ClientExporters, ExportFormat}; +pub use generators::{ClientGenerator, PassphraseGeneratorRequest, PasswordGeneratorRequest}; diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index fc9f30447..b6c8465ec 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -3,11 +3,8 @@ use std::num::NonZeroU32; use base64::{ alphabet, engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, - Engine, }; -use crate::error::Result; - pub fn default_pbkdf2_iterations() -> NonZeroU32 { NonZeroU32::new(600_000).unwrap() } @@ -24,14 +21,6 @@ pub fn default_argon2_parallelism() -> NonZeroU32 { NonZeroU32::new(4).unwrap() } -#[derive(serde::Deserialize)] -pub struct JWTToken { - pub sub: String, - pub email: Option, - pub organization: Option, - pub scope: Vec, -} - const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(DecodePaddingMode::Indifferent); @@ -39,48 +28,6 @@ const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() pub const BASE64_ENGINE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); -pub fn decode_token(token: &str) -> Result { - let split = token.split('.').collect::>(); - if split.len() != 3 { - return Err(crate::error::Error::Internal( - "JWT token has an invalid number of parts", - )); - } - let decoded = BASE64_ENGINE.decode(split[1])?; - Ok(serde_json::from_slice(&decoded)?) -} - -#[cfg(test)] -mod tests { - #[test] - fn can_decode_jwt() { - let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ - g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ - YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ - 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ - EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ - iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ - bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ - jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ - IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ - XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ - wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ - a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ - ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ - qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ - wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ - U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ - f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; - - let token = super::decode_token(jwt).unwrap(); - assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); - assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); - assert_eq!(token.organization.as_deref(), None); - assert_eq!(token.scope[0], "api"); - assert_eq!(token.scope[1], "offline_access"); - } -} - #[cfg(test)] pub async fn start_mock(mocks: Vec) -> (wiremock::MockServer, crate::Client) { let server = wiremock::MockServer::start().await; diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 143e2a4f9..101c8f4bc 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -33,28 +31,28 @@ pub struct AttachmentView { pub key: Option, } -impl Encryptable for AttachmentView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for AttachmentView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, url: self.url, size: self.size, size_name: self.size_name, - file_name: self.file_name.encrypt(enc, org_id)?, - key: self.key.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, + key: self.key.encrypt_with_key(key)?, }) } } -impl Decryptable for Attachment { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Attachment { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), size: self.size.clone(), size_name: self.size_name.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, - key: self.key.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, + key: self.key.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 9636ba83f..1545ad171 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -32,28 +30,28 @@ pub struct CardView { pub number: Option, } -impl Encryptable for CardView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for CardView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { - cardholder_name: self.cardholder_name.encrypt(enc, org_id)?, - exp_month: self.exp_month.encrypt(enc, org_id)?, - exp_year: self.exp_year.encrypt(enc, org_id)?, - code: self.code.encrypt(enc, org_id)?, - brand: self.brand.encrypt(enc, org_id)?, - number: self.number.encrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.encrypt_with_key(key)?, + exp_month: self.exp_month.encrypt_with_key(key)?, + exp_year: self.exp_year.encrypt_with_key(key)?, + code: self.code.encrypt_with_key(key)?, + brand: self.brand.encrypt_with_key(key)?, + number: self.number.encrypt_with_key(key)?, }) } } -impl Decryptable for Card { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Card { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { - cardholder_name: self.cardholder_name.decrypt(enc, org_id)?, - exp_month: self.exp_month.decrypt(enc, org_id)?, - exp_year: self.exp_year.decrypt(enc, org_id)?, - code: self.code.decrypt(enc, org_id)?, - brand: self.brand.decrypt(enc, org_id)?, - number: self.number.decrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.decrypt_with_key(key)?, + exp_month: self.exp_month.decrypt_with_key(key)?, + exp_year: self.exp_year.decrypt_with_key(key)?, + code: self.code.decrypt_with_key(key)?, + brand: self.brand.decrypt_with_key(key)?, + number: self.number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 9bf4bbd25..b95a2f090 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -11,7 +11,7 @@ use super::{ }; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, vault::password_history, }; @@ -43,6 +43,9 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, + /// More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + pub key: Option, + pub name: EncString, pub notes: Option, @@ -77,6 +80,8 @@ pub struct CipherView { pub folder_id: Option, pub collection_ids: Vec, + pub key: Option, + pub name: String, pub notes: Option, @@ -129,30 +134,33 @@ pub struct CipherListView { pub revision_date: DateTime, } -impl Encryptable for CipherView { - fn encrypt(self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyEncryptable for CipherView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + key: self.key, + name: self.name.encrypt_with_key(key)?, + notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, - login: self.login.encrypt(enc, org_id)?, - identity: self.identity.encrypt(enc, org_id)?, - card: self.card.encrypt(enc, org_id)?, - secure_note: self.secure_note.encrypt(enc, org_id)?, + login: self.login.encrypt_with_key(key)?, + identity: self.identity.encrypt_with_key(key)?, + card: self.card.encrypt_with_key(key)?, + secure_note: self.secure_note.encrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.encrypt(enc, org_id)?, - attachments: self.attachments.encrypt(enc, org_id)?, - fields: self.fields.encrypt(enc, org_id)?, - password_history: self.password_history.encrypt(enc, org_id)?, + local_data: self.local_data.encrypt_with_key(key)?, + attachments: self.attachments.encrypt_with_key(key)?, + fields: self.fields.encrypt_with_key(key)?, + password_history: self.password_history.encrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -160,30 +168,33 @@ impl Encryptable for CipherView { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + key: self.key.clone(), + name: self.name.decrypt_with_key(key)?, + notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, - login: self.login.decrypt(enc, org_id)?, - identity: self.identity.decrypt(enc, org_id)?, - card: self.card.decrypt(enc, org_id)?, - secure_note: self.secure_note.decrypt(enc, org_id)?, + login: self.login.decrypt_with_key(key)?, + identity: self.identity.decrypt_with_key(key)?, + card: self.card.decrypt_with_key(key)?, + secure_note: self.secure_note.decrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.decrypt(enc, org_id)?, - attachments: self.attachments.decrypt(enc, org_id)?, - fields: self.fields.decrypt(enc, org_id)?, - password_history: self.password_history.decrypt(enc, org_id)?, + local_data: self.local_data.decrypt_with_key(key)?, + attachments: self.attachments.decrypt_with_key(key)?, + fields: self.fields.decrypt_with_key(key)?, + password_history: self.password_history.decrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -192,17 +203,30 @@ impl Decryptable for Cipher { } impl Cipher { - fn get_decrypted_subtitle( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { + /// Get the decrypted individual encryption key for this cipher. + /// Note that some ciphers do not have individual encryption keys, + /// in which case this will return Ok(None) and the key associated + /// with this cipher's user or organization must be used instead + fn get_cipher_key( + key: &SymmetricCryptoKey, + ciphers_key: &Option, + ) -> Result> { + ciphers_key + .as_ref() + .map(|k| { + let key: Vec = k.decrypt_with_key(key)?; + SymmetricCryptoKey::try_from(key.as_slice()) + }) + .transpose() + } + + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { return Ok(String::new()); }; - login.username.decrypt(enc, org_id)?.unwrap_or_default() + login.username.decrypt_with_key(key)?.unwrap_or_default() } CipherType::SecureNote => String::new(), CipherType::Card => { @@ -212,11 +236,12 @@ impl Cipher { let mut sub_title = String::new(); if let Some(brand) = &card.brand { - sub_title.push_str(&brand.decrypt(enc, org_id)?); + let brand: String = brand.decrypt_with_key(key)?; + sub_title.push_str(&brand); } if let Some(number) = &card.number { - let number = number.decrypt(enc, org_id)?; + let number: String = number.decrypt_with_key(key)?; let number_len = number.len(); if number_len > 4 { if !sub_title.is_empty() { @@ -242,14 +267,16 @@ impl Cipher { let mut sub_title = String::new(); if let Some(first_name) = &identity.first_name { - sub_title.push_str(&first_name.decrypt(enc, org_id)?); + let first_name: String = first_name.decrypt_with_key(key)?; + sub_title.push_str(&first_name); } if let Some(last_name) = &identity.last_name { if !sub_title.is_empty() { sub_title.push(' '); } - sub_title.push_str(&last_name.decrypt(enc, org_id)?); + let last_name: String = last_name.decrypt_with_key(key)?; + sub_title.push_str(&last_name); } sub_title @@ -258,16 +285,18 @@ impl Cipher { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherListView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - sub_title: self.get_decrypted_subtitle(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + sub_title: self.get_decrypted_subtitle(key)?, r#type: self.r#type, favorite: self.favorite, reprompt: self.reprompt, @@ -284,3 +313,22 @@ impl Decryptable for Cipher { }) } } + +impl LocateKey for Cipher { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} +impl LocateKey for CipherView { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 9fa05257a..13f7dc9bb 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,12 +1,10 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use super::linked_id::LinkedIdType; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -42,22 +40,22 @@ pub struct FieldView { linked_id: Option, } -impl Encryptable for FieldView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for FieldView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { - name: self.name.encrypt(enc, org_id)?, - value: self.value.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(key)?, + value: self.value.encrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) } } -impl Decryptable for Field { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Field { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { - name: self.name.decrypt(enc, org_id)?, - value: self.value.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + value: self.value.decrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index aace84152..d40991866 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -56,52 +54,52 @@ pub struct IdentityView { pub license_number: Option, } -impl Encryptable for IdentityView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for IdentityView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { - title: self.title.encrypt(enc, org_id)?, - first_name: self.first_name.encrypt(enc, org_id)?, - middle_name: self.middle_name.encrypt(enc, org_id)?, - last_name: self.last_name.encrypt(enc, org_id)?, - address1: self.address1.encrypt(enc, org_id)?, - address2: self.address2.encrypt(enc, org_id)?, - address3: self.address3.encrypt(enc, org_id)?, - city: self.city.encrypt(enc, org_id)?, - state: self.state.encrypt(enc, org_id)?, - postal_code: self.postal_code.encrypt(enc, org_id)?, - country: self.country.encrypt(enc, org_id)?, - company: self.company.encrypt(enc, org_id)?, - email: self.email.encrypt(enc, org_id)?, - phone: self.phone.encrypt(enc, org_id)?, - ssn: self.ssn.encrypt(enc, org_id)?, - username: self.username.encrypt(enc, org_id)?, - passport_number: self.passport_number.encrypt(enc, org_id)?, - license_number: self.license_number.encrypt(enc, org_id)?, + title: self.title.encrypt_with_key(key)?, + first_name: self.first_name.encrypt_with_key(key)?, + middle_name: self.middle_name.encrypt_with_key(key)?, + last_name: self.last_name.encrypt_with_key(key)?, + address1: self.address1.encrypt_with_key(key)?, + address2: self.address2.encrypt_with_key(key)?, + address3: self.address3.encrypt_with_key(key)?, + city: self.city.encrypt_with_key(key)?, + state: self.state.encrypt_with_key(key)?, + postal_code: self.postal_code.encrypt_with_key(key)?, + country: self.country.encrypt_with_key(key)?, + company: self.company.encrypt_with_key(key)?, + email: self.email.encrypt_with_key(key)?, + phone: self.phone.encrypt_with_key(key)?, + ssn: self.ssn.encrypt_with_key(key)?, + username: self.username.encrypt_with_key(key)?, + passport_number: self.passport_number.encrypt_with_key(key)?, + license_number: self.license_number.encrypt_with_key(key)?, }) } } -impl Decryptable for Identity { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Identity { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { - title: self.title.decrypt(enc, org_id)?, - first_name: self.first_name.decrypt(enc, org_id)?, - middle_name: self.middle_name.decrypt(enc, org_id)?, - last_name: self.last_name.decrypt(enc, org_id)?, - address1: self.address1.decrypt(enc, org_id)?, - address2: self.address2.decrypt(enc, org_id)?, - address3: self.address3.decrypt(enc, org_id)?, - city: self.city.decrypt(enc, org_id)?, - state: self.state.decrypt(enc, org_id)?, - postal_code: self.postal_code.decrypt(enc, org_id)?, - country: self.country.decrypt(enc, org_id)?, - company: self.company.decrypt(enc, org_id)?, - email: self.email.decrypt(enc, org_id)?, - phone: self.phone.decrypt(enc, org_id)?, - ssn: self.ssn.decrypt(enc, org_id)?, - username: self.username.decrypt(enc, org_id)?, - passport_number: self.passport_number.decrypt(enc, org_id)?, - license_number: self.license_number.decrypt(enc, org_id)?, + title: self.title.decrypt_with_key(key)?, + first_name: self.first_name.decrypt_with_key(key)?, + middle_name: self.middle_name.decrypt_with_key(key)?, + last_name: self.last_name.decrypt_with_key(key)?, + address1: self.address1.decrypt_with_key(key)?, + address2: self.address2.decrypt_with_key(key)?, + address3: self.address3.decrypt_with_key(key)?, + city: self.city.decrypt_with_key(key)?, + state: self.state.decrypt_with_key(key)?, + postal_code: self.postal_code.decrypt_with_key(key)?, + country: self.country.decrypt_with_key(key)?, + company: self.company.decrypt_with_key(key)?, + email: self.email.decrypt_with_key(key)?, + phone: self.phone.decrypt_with_key(key)?, + ssn: self.ssn.decrypt_with_key(key)?, + username: self.username.decrypt_with_key(key)?, + passport_number: self.passport_number.decrypt_with_key(key)?, + license_number: self.license_number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index 1811ffa8b..8d5fe8694 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -24,8 +22,8 @@ pub struct LocalDataView { last_launched: Option, } -impl Encryptable for LocalDataView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for LocalDataView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -33,8 +31,8 @@ impl Encryptable for LocalDataView { } } -impl Decryptable for LocalData { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for LocalData { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 941aed221..7a8e18411 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -2,11 +2,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -65,45 +63,45 @@ pub struct LoginView { pub autofill_on_page_load: Option, } -impl Encryptable for LoginUriView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginUriView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { - uri: self.uri.encrypt(enc, org_id)?, + uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Encryptable for LoginView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { - username: self.username.encrypt(enc, org_id)?, - password: self.password.encrypt(enc, org_id)?, + username: self.username.encrypt_with_key(key)?, + password: self.password.encrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.encrypt(enc, org_id)?, - totp: self.totp.encrypt(enc, org_id)?, + uris: self.uris.encrypt_with_key(key)?, + totp: self.totp.encrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } } -impl Decryptable for LoginUri { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for LoginUri { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { - uri: self.uri.decrypt(enc, org_id)?, + uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Decryptable for Login { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Login { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { - username: self.username.decrypt(enc, org_id)?, - password: self.password.decrypt(enc, org_id)?, + username: self.username.decrypt_with_key(key)?, + password: self.password.decrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.decrypt(enc, org_id)?, - totp: self.totp.decrypt(enc, org_id)?, + uris: self.uris.decrypt_with_key(key)?, + totp: self.totp.decrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 422a55da1..0c7b4c799 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,11 +1,9 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -30,16 +28,16 @@ pub struct SecureNoteView { r#type: SecureNoteType, } -impl Encryptable for SecureNoteView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for SecureNoteView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, }) } } -impl Decryptable for SecureNote { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for SecureNote { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 38863a946..58492ef17 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -4,7 +4,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, + crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -36,15 +36,22 @@ pub struct CollectionView { read_only: bool, } -impl Decryptable for Collection { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = Some(self.organization_id); - +impl LocateKey for Collection { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&Some(self.organization_id)) + } +} +impl KeyDecryptable for Collection { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, - name: self.name.decrypt(enc, &org_id)?, + name: self.name.decrypt_with_key(key)?, external_id: self.external_id.clone(), hide_passwords: self.hide_passwords, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 97d861310..f9ae06055 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -4,8 +4,7 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -27,21 +26,23 @@ pub struct FolderView { revision_date: DateTime, } -impl Encryptable for FolderView { - fn encrypt(self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for FolderView {} +impl KeyEncryptable for FolderView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, - name: self.name.encrypt(enc, &None)?, + name: self.name.encrypt_with_key(key)?, revision_date: self.revision_date, }) } } -impl Decryptable for Folder { - fn decrypt(&self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for Folder {} +impl KeyDecryptable for Folder { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, - name: self.name.decrypt(enc, &None)?, + name: self.name.decrypt_with_key(key)?, revision_date: self.revision_date, }) } diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index 9eecd6620..12910283c 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -3,9 +3,11 @@ mod collection; mod folder; mod password_history; mod send; +mod totp; pub use cipher::{Cipher, CipherListView, CipherView}; pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; pub use send::{Send, SendListView, SendView}; +pub use totp::{generate_totp, TotpResponse}; diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 8566c9870..da6a4b19e 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,11 +1,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -25,23 +23,21 @@ pub struct PasswordHistoryView { last_used_date: DateTime, } -impl Encryptable for PasswordHistoryView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for PasswordHistoryView {} +impl KeyEncryptable for PasswordHistoryView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { - password: self.password.encrypt(enc, org_id)?, + password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, }) } } -impl Decryptable for PasswordHistory { - fn decrypt( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { +impl LocateKey for PasswordHistory {} +impl KeyDecryptable for PasswordHistory { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistoryView { - password: self.password.decrypt(enc, org_id)?, + password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, }) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 124b9dc2f..5c463a0cf 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -5,8 +5,10 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{derive_shareable_key, Decryptable, EncString, Encryptable, SymmetricCryptoKey}, + crypto::{ + derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, + }, error::Result, }; @@ -126,86 +128,75 @@ pub struct SendListView { } impl Send { - fn get_key( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, + pub(crate) fn get_key( + send_key: &EncString, + enc_key: &SymmetricCryptoKey, ) -> Result { - let key: Vec = enc.decrypt_bytes(key, org_id)?; + let key: Vec = send_key.decrypt_with_key(enc_key)?; let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); Ok(key) } - - pub(crate) fn get_encryption( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { - let key = Send::get_key(key, enc, org_id)?; - Ok(EncryptionSettings::new_single_key(key)) - } } -impl Decryptable for SendText { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendText { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { - text: self.text.decrypt(enc, org_id)?, + text: self.text.decrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Encryptable for SendTextView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendTextView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { - text: self.text.encrypt(enc, org_id)?, + text: self.text.encrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Decryptable for SendFile { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendFile { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Encryptable for SendFileView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendFileView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), - file_name: self.file_name.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for Send {} +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, + notes: self.notes.decrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.decrypt(enc, org_id)?, - text: self.text.decrypt(enc, org_id)?, + file: self.file.decrypt_with_key(&key)?, + text: self.text.decrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -219,19 +210,17 @@ impl Decryptable for Send { } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendListView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, r#type: self.r#type, disabled: self.disabled, @@ -243,27 +232,25 @@ impl Decryptable for Send { } } -impl Encryptable for SendView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for SendView {} +impl KeyEncryptable for SendView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let key = Send::get_key(&self.key, enc, org_id)?; - let enc_owned = EncryptionSettings::new_single_key(key); - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(Send { id: self.id, access_id: self.access_id, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(&key)?, + notes: self.notes.encrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.encrypt(enc, org_id)?, - text: self.text.encrypt(enc, org_id)?, + file: self.file.encrypt_with_key(&key)?, + text: self.text.encrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -298,6 +285,8 @@ mod tests { "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw=".parse().unwrap(), ).unwrap(); + let k = enc.get_key(&None).unwrap(); + // Create a send object, the only value we really care about here is the key let send = Send { id: "d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap(), @@ -330,7 +319,7 @@ mod tests { }; // Get the send key - let send_key = Send::get_key(&send.key, &enc, &None).unwrap(); + let send_key = Send::get_key(&send.key, k).unwrap(); let send_key_b64 = send_key.to_base64(); assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs new file mode 100644 index 000000000..7e701f92e --- /dev/null +++ b/crates/bitwarden/src/vault/totp.rs @@ -0,0 +1,30 @@ +use chrono::{DateTime, Utc}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct TotpResponse { + /// Generated TOTP code + pub code: String, + /// Time period + pub period: u32, +} + +/// Generate a OATH or RFC 6238 TOTP code from a provided key. +/// +/// +/// +/// Key can be either: +/// - A base32 encoded string +/// - OTP Auth URI +/// - Steam URI +/// +/// Supports providing an optional time, and defaults to current system time if none is provided. +pub async fn generate_totp(_key: String, _time: Option>) -> TotpResponse { + TotpResponse { + code: "000 000".to_string(), + period: 30, + } +} diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs new file mode 100644 index 000000000..d4e632e55 --- /dev/null +++ b/crates/bitwarden/tests/register.rs @@ -0,0 +1,35 @@ +/// Integration test for registering a new user and unlocking the vault +#[cfg(feature = "mobile")] +#[tokio::test] +async fn test_register_initialize_crypto() { + use std::num::NonZeroU32; + + use bitwarden::{client::kdf::Kdf, mobile::crypto::InitCryptoRequest, Client}; + + let mut client = Client::new(None); + + let email = "test@bitwarden.com"; + let password = "test123"; + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }; + + let register_response = client + .auth() + .make_register_keys(email.to_owned(), password.to_owned(), kdf.clone()) + .unwrap(); + + // Ensure we can initialize the crypto with the new keys + client + .crypto() + .initialize_crypto(InitCryptoRequest { + kdf_params: kdf, + email: email.to_owned(), + password: password.to_owned(), + user_key: register_response.encrypted_user_key, + private_key: register_response.keys.private.to_string(), + organization_keys: Default::default(), + }) + .await + .unwrap(); +} diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 29252d133..0793470b3 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -22,7 +22,7 @@ env_logger = "0.10.0" color-eyre = "0.6" inquire = "0.6.2" -bitwarden = { path = "../bitwarden", version = "0.3.0", features = [ +bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ "internal", "mobile", ] } diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index 1c169817f..1fcd15414 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -10,15 +10,16 @@ use color_eyre::eyre::{bail, Result}; use inquire::{Password, Text}; use log::{debug, error, info}; -pub(crate) async fn password_login(mut client: Client, email: Option) -> Result<()> { +pub(crate) async fn login_password(mut client: Client, email: Option) -> Result<()> { let email = text_prompt_when_none("Email", email)?; let password = Password::new("Password").without_confirmation().prompt()?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email: email.clone(), password: password.clone(), two_factor: None, @@ -45,6 +46,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> } else if let Some(tf) = two_factor.email { // Send token client + .auth() .send_two_factor_email(&TwoFactorEmailRequest { email: email.clone(), password: password.clone(), @@ -64,7 +66,8 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> }; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email, password, two_factor, @@ -80,7 +83,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> Ok(()) } -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( mut client: Client, client_id: Option, client_secret: Option, @@ -91,7 +94,8 @@ pub(crate) async fn api_key_login( let password = Password::new("Password").without_confirmation().prompt()?; let result = client - .api_key_login(&ApiKeyLoginRequest { + .auth() + .login_api_key(&ApiKeyLoginRequest { client_id, client_secret, password, diff --git a/crates/bw/src/auth/mod.rs b/crates/bw/src/auth/mod.rs index a745a70f0..a4c7e2ed5 100644 --- a/crates/bw/src/auth/mod.rs +++ b/crates/bw/src/auth/mod.rs @@ -1,2 +1,2 @@ mod login; -pub(crate) use login::{api_key_login, password_login}; +pub(crate) use login::{login_api_key, login_password}; diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index daeec9d9a..c4664c7f4 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -157,12 +157,12 @@ async fn process_commands() -> Result<()> { match args.command { // FIXME: Rust CLI will not support password login! LoginCommands::Password { email } => { - auth::password_login(client, email).await?; + auth::login_password(client, email).await?; } LoginCommands::ApiKey { client_id, client_secret, - } => auth::api_key_login(client, client_id, client_secret).await?, + } => auth::login_api_key(client, client_id, client_secret).await?, } return Ok(()); } diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 15fcfdf3b..2dc71f152 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,6 +7,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.3.1] - 2023-10-13 + ### Added - Support for shell autocompletion with the `bws completions` command (#103) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index ed4dc3b91..00ec40da7 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bws" -version = "0.3.0" +version = "0.3.1" edition = "2021" rust-version = "1.60" authors = ["Bitwarden Inc"] @@ -15,7 +15,7 @@ keywords = ["bitwarden", "secrets-manager", "cli"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bat = { version = "0.23.0", features = [ +bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } chrono = { version = "0.4.26", features = [ @@ -38,7 +38,7 @@ tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } -bitwarden = { path = "../bitwarden", version = "0.3.0", features = ["secrets"] } +bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } [dev-dependencies] tempfile = "3.5.0" diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 5e6da19d8..6f27a0e4d 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -247,7 +247,7 @@ async fn process_commands() -> Result<()> { let Some(command) = cli.command else { let mut cmd = Cli::command(); eprintln!("{}", cmd.render_help().ansi()); - return Ok(()); + std::process::exit(1); }; // These commands don't require authentication, so we process them first @@ -324,7 +324,8 @@ async fn process_commands() -> Result<()> { // Load session or return if no session exists let _ = client - .access_token_login(&AccessTokenLoginRequest { access_token }) + .auth() + .login_access_token(&AccessTokenLoginRequest { access_token }) .await?; let organization_id = match client.get_access_token_organization() { diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index c9c177c84..980434e89 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.24.1", features = ["cli"] } +uniffi = { version = "=0.25.0", features = ["cli"] } diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index da527fe32..066f862be 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -9,7 +9,7 @@ "text-encoding": "0.7.0", "ts-loader": "9.5.0", "wasm-pack": "0.12.1", - "webpack": "5.88.2", + "webpack": "5.89.0", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" } @@ -72,9 +72,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -88,9 +88,9 @@ "dev": true }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", "dev": true, "dependencies": { "@types/connect": "*", @@ -98,27 +98,27 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", + "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", + "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -136,9 +136,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", - "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -146,15 +146,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", "dev": true }, "node_modules/@types/express": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", - "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -164,9 +164,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -182,48 +182,60 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", + "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", - "dev": true + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", + "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", "dev": true }, "node_modules/@types/retry": { @@ -233,9 +245,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -243,18 +255,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", + "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -263,18 +275,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "version": "0.3.35", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", + "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", + "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", "dev": true, "dependencies": { "@types/node": "*" @@ -496,9 +508,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -753,9 +765,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.11", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.11.tgz", - "integrity": "sha512-xn1UXOKUz7DjdGlg9RrUr0GGiWzI97UQJnugHtH0OLDfJB7jMgoIkYvRIEO1l9EeEERVqeqLYOcFBW9ldjypbQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, "funding": [ { @@ -772,8 +784,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001538", - "electron-to-chromium": "^1.4.526", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.13" }, @@ -800,13 +812,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -823,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001538", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", - "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "version": "1.0.30001558", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", + "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", "dev": true, "funding": [ { @@ -1118,6 +1131,20 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1251,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.528", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.528.tgz", - "integrity": "sha512-UdREXMXzLkREF4jA8t89FQjA8WHI6ssP38PMY4/4KhXFQbtImnghh4GkCgrtiZwLKUKVD2iTVXvDVQjfomEQuA==", + "version": "1.4.569", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", + "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", "dev": true }, "node_modules/encodeurl": { @@ -1534,6 +1561,15 @@ "node": ">=8" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/follow-redirects": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", @@ -1597,9 +1633,9 @@ } }, "node_modules/fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", "dev": true }, "node_modules/fs.realpath": { @@ -1623,21 +1659,24 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1693,6 +1732,18 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1705,18 +1756,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1726,6 +1765,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -1750,6 +1801,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2033,12 +2096,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2209,13 +2272,13 @@ } }, "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", "dev": true, "dependencies": { "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" + "shell-quote": "^1.8.1" } }, "node_modules/loader-runner": { @@ -2520,9 +2583,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2923,9 +2986,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -3035,11 +3098,12 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -3178,6 +3242,21 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3442,9 +3521,9 @@ } }, "node_modules/terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.23.0.tgz", + "integrity": "sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3595,6 +3674,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -3718,9 +3803,9 @@ } }, "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -4007,12 +4092,13 @@ } }, "node_modules/webpack-merge": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", - "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { diff --git a/languages/js_webassembly/package.json b/languages/js_webassembly/package.json index df67eb9b7..95d7002a5 100644 --- a/languages/js_webassembly/package.json +++ b/languages/js_webassembly/package.json @@ -8,7 +8,7 @@ "text-encoding": "0.7.0", "ts-loader": "9.5.0", "wasm-pack": "0.12.1", - "webpack": "5.88.2", + "webpack": "5.89.0", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index b083fa123..8b7957ed7 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -441,6 +441,24 @@ Sends operations **Output**: Arc +### `generate_totp` + +Generate a TOTP code from a provided key. + +The key can be either: + +- A base32 encoded string +- OTP Auth URI +- Steam URI + +**Arguments**: + +- self: +- key: String +- time: Option + +**Output**: [TotpResponse](#totpresponse) + # References References are generated from the JSON schemas and should mostly match the kotlin and swift @@ -541,17 +559,17 @@ implementations. attachments - array + array,null fields - array + array,null passwordHistory - array + array,null @@ -606,7 +624,7 @@ implementations. notes - string + string,null @@ -666,17 +684,17 @@ implementations. attachments - array + array,null fields - array + array,null passwordHistory - array + array,null @@ -1253,3 +1271,23 @@ implementations. + +## `TotpResponse` + + + + + + + + + + + + + + + + + +
KeyTypeDescription
codestringGenerated TOTP code
periodintegerTime period
diff --git a/package-lock.json b/package-lock.json index 22f0e6282..7791b3b69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,17 +11,17 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" } }, "node_modules/@babel/runtime": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", - "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -363,16 +363,19 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/urijs": { - "version": "1.19.20", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.20.tgz", - "integrity": "sha512-77Mq/2BeHU894J364dUv9tSwxxyCLtcX228Pc8TwZpP5bvOoMns+gZoftp3LYl3FBH8vChpWbuagKGiMki2c1A==", + "version": "1.19.22", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.22.tgz", + "integrity": "sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==", "dev": true }, "node_modules/abort-controller": { @@ -388,9 +391,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -400,9 +403,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1315,9 +1318,9 @@ } }, "node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -1467,9 +1470,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -1491,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.76", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.76.tgz", - "integrity": "sha512-QinZRNovSTQcFuhRKxeHb22eFmyucbG96EPaQDSbz9qvIPxUhs1BZviNc8HAkHWYFqTSET/xZcEoHpm1DeDbRg==", + "version": "23.0.77", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.77.tgz", + "integrity": "sha512-QABFgMHVsyW7CAcLGWvIQXgjZ7ehPnebfV/3x9c5HtuJVXgYLrEG/+zyQd1O+OPWpQrhbwU97doJTZRw+acA6A==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", @@ -1970,6 +1973,13 @@ "node": ">=8" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "peer": true + }, "node_modules/unicode-properties": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", @@ -2120,9 +2130,9 @@ } }, "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "dev": true, "engines": { "node": ">= 14" diff --git a/package.json b/package.json index fdeb8fe58..ad38f3a10 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2"