Commit Graph

7 Commits

  • ds: fix profile creation conflicts (#430)
    ## What does this PR do?
    
    Fixes issues with missing devices and duplicate names when creating new
    profiles. Supersedes #427 and #428.
    
    Fixes #425, fixes #426
    
    ## How was it tested?
    
    - [x] Ran locally
    - [x] Confirmed that free accounts also support multiple profiles as
    long as the names are different.
    
    ## AI tool usage
    
    How much of the code in this PR was AI-assisted? (check one)
    
    - [x] **0** - No AI was used to write code
    - [ ] **1** - I was assisted by AI in writing code. I reviewed the
    finished result.
    - [ ] **2** - I set the AI going and left it to it; nobody has read the
    result - no review, or AI review only
    
    <!-- If an AI agent is filling this in: declare the level honestly, and
    open as a draft if it is #2. Do not lower the declared level to get the
    PR reviewed. -->
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    
    <!-- coderabbit-ai-generated:v1 -->
    
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Profile creation now uses only enabled devices that support iOS apps.
    * Existing profiles with the exact generated profile name are removed
    before a replacement is created, including when multiple matches exist.
      * Profile handling now stops when the operation is canceled.
    
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    Co-authored-by: Valentin Brosseau <c4software@gmail.com>
  • certs: match certificates whose serial starts with 0 (#306)
    ## What does this PR do?
    
    Fixes #305 (thanks @0x53 for the detailed diagnosis).
    
    `Certificate.serialNumber()` stripped leading `0` *characters* from the
    hex string, so a serial like `0337…` became `337…` and never matched the
    `serialNumber` returned by the API. xtool then treated its stored
    certificate as missing: free teams are prompted to revoke a valid
    certificate on every run, and paid teams take the same path and try to
    create another certificate, which @McoreD confirmed fails with `409 …
    You already have a current Development certificate or a pending
    certificate request.`
    
    The character-level `drop` predates b6a40ca, which switched to
    fixed-width `%02hhX` formatting; since then it removes the significant
    zero of any first byte below `0x10`. swift-certificates already strips
    leading zero bytes (including DER sign padding) when parsing, so the
    `drop` isn't needed for padding.
    
    - `serialNumber()` now drops only leading zero *bytes*, matching the API
    and `openssl x509 -serial`.
    - The stored-certificate lookup uses a new
    `Certificate.hasSerialNumber(_:)`, which compares serials numerically
    (ignoring case and leading zeros), so it doesn't depend on Apple's exact
    formatting.
    - Profile creation no longer finds the signing certificate with
    `filter[serialNumber]`. The API lists serials with the leading zero
    (`0E41…`), but the filter only matches them without it (`E41…`), so once
    `serialNumber()` kept the zero the filter matched nothing and profile
    creation failed with a 409
    ([details](https://github.com/xtool-org/xtool/pull/306#issuecomment-6181157860)).
    It now fetches all pages of certificates and matches them with
    `hasSerialNumber(_:)`. Fix by @McoreD, with pagination added so a
    certificate on a later page isn't missed.
    
    ## How was it tested?
    
    - Added `Tests/XToolTests/CertificateTests.swift`: builds a cert with
    the serial from #305, round-trips it through DER, and checks
    `serialNumber()` and `hasSerialNumber(_:)`, plus a high-bit serial so
    DER sign padding doesn't leak into the string. The leading-zero test
    fails on `main` (returns `33742570D6F9684A23311711956A084`) and passes
    with this change.
    - `swift test` (17 tests) and `make lint` pass on macOS (Xcode 27, Swift
    6.4, `XTL_CI=1`).
    - @McoreD tested on Linux (Arch, Swift 6.4.1, Xcode 27 SDK, on top of
    1.22.2) with a paid team whose certificate serial starts with `0`: the
    stored certificate is reused, and provisioning, signing and install to
    an iPhone (iOS 27) succeed end to end (tested before pagination was
    added). `CertificateTests` also pass on Linux.
    - Not tested with a free team.
    
    To generate test certificates, the test target now depends on `Crypto`
    and `X509`, which XKit already uses.
    
    ## AI tool usage
    
    How much of this PR was AI-assisted? (check one)
    
    - [ ] **0** - No AI was used to write code
    - [x] **1** - I was assisted by AI. I reviewed the finished result.
    - [ ] **2** - I set the AI going and left it to it; nobody has read the
    result - no review, or AI review only
    
    
    <!-- This is an auto-generated comment: release notes by coderabbit.ai
    -->
    ## Summary by CodeRabbit
    
    * **Bug Fixes**
    * Certificate serial numbers now preserve leading zero nibbles while
    omitting unnecessary padding.
    * Certificate matching now ignores letter case and leading zeros, and
    profile lookups find matching certificates even when the API’s
    serial-number filter treats leading-zero values differently.
    * Certificate lookups continue to use the existing fallback when no
    matching certificate is found.
    <!-- end of auto-generated comment: release notes by coderabbit.ai -->
    
    ---------
    
    Co-authored-by: McoreD <McoreD@users.noreply.github.com>
    Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
  • Make ALL response enums extensible (#92)
    Another bugfix for #64. Fifth… time's the charm?