Compare commits

..
Author SHA1 Message Date
Max Goedjen da56dd6434 WIP 2026-09-06 18:08:16 -07:00
Max Goedjen 00804587de Adding host reader xpc service and connection info 2026-08-19 10:41:50 +02:00
Max Goedjen b71cbf8529 Merge 2026-08-15 19:15:03 +02:00
Max Goedjen f527e136e3 WIP 2026-03-28 13:22:27 -07:00
Max Goedjen ece3865d9a Merge branch 'main' into sshextensions 2026-03-25 15:07:22 -07:00
Max Goedjen 6b1f5bbb7c WIP 2026-03-12 12:46:45 -07:00
Max Goedjen f848eb659e Messy WIP for agent extensions 2026-03-11 14:57:38 -07:00
20 changed files with 211 additions and 265 deletions
+7 -2
View File
@@ -11,7 +11,7 @@ on:
jobs: jobs:
analyze: analyze:
name: Analyze (${{ matrix.language }}) name: Analyze (${{ matrix.language }})
runs-on: ${{ (matrix.language == 'swift' && 'xcode-27') || 'ubuntu-latest' }} runs-on: ${{ (matrix.language == 'swift' && 'macos-26') || 'ubuntu-latest' }}
permissions: permissions:
security-events: write security-events: write
packages: read packages: read
@@ -24,15 +24,20 @@ jobs:
include: include:
- language: actions - language: actions
build-mode: none build-mode: none
# Disable this until CodeQL supports Xcode 26 builds.
# - language: swift
# build-mode: manual
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v5 uses: actions/checkout@v4
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }} build-mode: ${{ matrix.build-mode }}
- if: matrix.build-mode == 'manual' - if: matrix.build-mode == 'manual'
name: "Select Xcode"
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- if: matrix.build-mode == 'manual' - if: matrix.build-mode == 'manual'
name: "Build" name: "Build"
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme Secretive CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme Secretive CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
+3 -1
View File
@@ -6,7 +6,7 @@ on:
jobs: jobs:
build: build:
runs-on: xcode-27 runs-on: macos-26
permissions: permissions:
id-token: write id-token: write
contents: write contents: write
@@ -25,6 +25,8 @@ jobs:
APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }} APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- name: Update Build Number - name: Update Build Number
env: env:
RUN_ID: ${{ github.run_id }} RUN_ID: ${{ github.run_id }}
+3 -1
View File
@@ -5,7 +5,7 @@ on:
jobs: jobs:
build: build:
runs-on: xcode-27 runs-on: macos-26
permissions: permissions:
id-token: write id-token: write
contents: write contents: write
@@ -24,6 +24,8 @@ jobs:
APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }} APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- name: Update Build Number - name: Update Build Number
env: env:
RUN_ID: ${{ github.run_id }} RUN_ID: ${{ github.run_id }}
+6 -2
View File
@@ -8,7 +8,7 @@ jobs:
test: test:
permissions: permissions:
contents: read contents: read
runs-on: xcode-27 runs-on: macos-26
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
@@ -21,6 +21,8 @@ jobs:
APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }} APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- name: Test - name: Test
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test
# SPM doesn't seem to pick up on the tests currently? # SPM doesn't seem to pick up on the tests currently?
@@ -32,7 +34,7 @@ jobs:
attestations: write attestations: write
artifact-metadata: write artifact-metadata: write
actions: read actions: read
runs-on: xcode-27 runs-on: macos-26
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
@@ -45,6 +47,8 @@ jobs:
APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }} APPLE_API_KEY_DATA: ${{ secrets.APPLE_API_KEY_DATA }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
run: ./.github/scripts/signing.sh run: ./.github/scripts/signing.sh
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- name: Update Build Number - name: Update Build Number
env: env:
TAG_NAME: ${{ github.ref }} TAG_NAME: ${{ github.ref }}
+3 -1
View File
@@ -5,10 +5,12 @@ jobs:
test: test:
permissions: permissions:
contents: read contents: read
runs-on: xcode-27 runs-on: macos-26
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Set Environment
run: sudo xcrun xcode-select -s /Applications/Xcode_26.4.app
- name: Test Main Packages - name: Test Main Packages
run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test run: xcrun xcodebuild -project Sources/Secretive.xcodeproj -scheme PackageTests test
# SPM doesn't seem to pick up on the tests currently? # SPM doesn't seem to pick up on the tests currently?
+1 -1
View File
@@ -139,7 +139,7 @@ var localization: Resource {
var swiftSettings: [PackageDescription.SwiftSetting] { var swiftSettings: [PackageDescription.SwiftSetting] {
[ [
.swiftLanguageMode(.v6), .swiftLanguageMode(.v6),
.treatAllWarnings(as: .error), // .treatAllWarnings(as: .error),
.strictMemorySafety() .strictMemorySafety()
] ]
} }
+110 -185
View File
@@ -490,8 +490,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Log de Build" "value" : "Build Log"
} }
}, },
"ro" : { "ro" : {
@@ -675,8 +675,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Sobre o Secretive" "value" : "About Secretive"
} }
}, },
"ro" : { "ro" : {
@@ -860,8 +860,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "O Secretive é Open Source e distribuído sob a licença MIT" "value" : "Secretive is Open Source and MIT Licensed"
} }
}, },
"ro" : { "ro" : {
@@ -1045,8 +1045,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Agradecimentos especiais aos nossos [Contribuidores](%1$(contributorsLink)@) e [Patrocinadores](%2$(sponsorsLink)@)" "value" : "Special thanks our [Contributors](%1$(contributorsLink)@) and [Sponsors](%2$(sponsorsLink)@)"
} }
}, },
"ro" : { "ro" : {
@@ -1230,8 +1230,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Ver no GitHub" "value" : "View on GitHub"
} }
}, },
"ro" : { "ro" : {
@@ -1416,7 +1416,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive não foi capaz de iniciar o SecretAgent. Por favor, tente reiniciar seu Mac e, se isso não resolver, registre uma issue no GitHub." "value" : "Secretive não foi capaz de obter o SecretAgent para iniciar. Por favor tente reiniciar seu Mac e se isso não resolver, registre um problema em nosso GitHub."
} }
}, },
"ro" : { "ro" : {
@@ -1601,7 +1601,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Desativar o Agente" "value" : "Desabilitar o Agente"
} }
}, },
"ro" : { "ro" : {
@@ -2156,7 +2156,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Caminho do socket" "value" : "Caminho do Socket"
} }
}, },
"ro" : { "ro" : {
@@ -2526,7 +2526,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Iniciando Agente" "value" : "Agente iniciando"
} }
}, },
"ro" : { "ro" : {
@@ -2896,7 +2896,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O SecretAgent é um processo que roda em segundo plano para assinar pedidos, sem precisar manter o Secretive aberto o tempo todo.\n\n**O Secretive não funcionará corretamente a menos que o agente esteja instalado e rodando.**" "value" : "SecretAgent é um processo que é executado em segundo plano para assinar pedidos, então não há necessidade de manter Secretive aberto o tempo todo.\n\n**Secretive não funcionará corretamente a menos que o agente esteja instalado e executando.**"
} }
}, },
"ro" : { "ro" : {
@@ -3081,7 +3081,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Agente não está rodando" "value" : "Agent não está rodando"
} }
}, },
"ro" : { "ro" : {
@@ -3266,7 +3266,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O SecretAgent é um processo que roda em segundo plano para assinar pedidos, sem precisar manter o Secretive aberto o tempo todo.\n\n**Você pode fechar o Secretive e tudo continuará funcionando.**" "value" : "SecretAgent é um processo que roda em background para assinar requisições para que você não precise manter o Secretive aberto a todo momento.\n\n**Você pode fechar o Secretive e tudo continuará funcionando.**"
} }
}, },
"ro" : { "ro" : {
@@ -3451,7 +3451,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O SecretAgent está rodando" "value" : "Secret Agent está rodando"
} }
}, },
"ro" : { "ro" : {
@@ -3636,7 +3636,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Agente está rodando" "value" : "Agent está rodando"
} }
}, },
"ro" : { "ro" : {
@@ -3879,6 +3879,21 @@
} }
} }
} }
},
"All" : {
},
"Allow Connection Operations" : {
},
"Allow Forwarding" : {
},
"Allow Signing Operations" : {
},
"Allowed Domains" : {
}, },
"app_menu_help_button" : { "app_menu_help_button" : {
"extractionState" : "manual", "extractionState" : "manual",
@@ -4375,8 +4390,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Depois" "value" : "Later"
} }
}, },
"ro" : { "ro" : {
@@ -4561,7 +4576,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive precisa estar no seu diretório de Aplicativos para funcionar corretamente. Por favor, mova-o e abra novamente." "value" : "Secretive necessita estar no seu diretório de Aplicações para funcionar corretamente. Por favor mova-o e abra novamente."
} }
}, },
"ro" : { "ro" : {
@@ -4745,8 +4760,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Encerrar" "value" : "Quit"
} }
}, },
"ro" : { "ro" : {
@@ -4931,7 +4946,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive não está no diretório de Aplicativos" "value" : "Secretive não está no diretório de Aplicações"
} }
}, },
"ro" : { "ro" : {
@@ -5117,7 +5132,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "destrancar o segredo “%1$(secretName)@” por %2$(duration)@" "value" : "destravar segredo “%1$(secretName)@” for %2$(duration)@"
} }
}, },
"ro" : { "ro" : {
@@ -5489,7 +5504,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "assinar um pedido de “%1$(appName)@” usando o segredo “%2$(secretName)@”" "value" : "assinar requisição a partir do “%1$(appName)@” utilizando o segredo “%2$(secretName)@”"
} }
}, },
"ro" : { "ro" : {
@@ -5928,12 +5943,6 @@
"state" : "translated", "state" : "translated",
"value" : "Critical Options" "value" : "Critical Options"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Opções críticas"
}
} }
} }
}, },
@@ -5945,12 +5954,6 @@
"state" : "translated", "state" : "translated",
"value" : "Extensions" "value" : "Extensions"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Extensões"
}
} }
} }
}, },
@@ -5962,12 +5965,6 @@
"state" : "translated", "state" : "translated",
"value" : "Key ID" "value" : "Key ID"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "ID da Chave"
}
} }
} }
}, },
@@ -5979,12 +5976,6 @@
"state" : "translated", "state" : "translated",
"value" : "Certificate Path" "value" : "Certificate Path"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Caminho do Certificado"
}
} }
} }
}, },
@@ -5996,12 +5987,6 @@
"state" : "translated", "state" : "translated",
"value" : "Principals" "value" : "Principals"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Entidades Principais"
}
} }
} }
}, },
@@ -6013,12 +5998,6 @@
"state" : "translated", "state" : "translated",
"value" : "Serial Number" "value" : "Serial Number"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Número de Série"
}
} }
} }
}, },
@@ -6030,12 +6009,6 @@
"state" : "translated", "state" : "translated",
"value" : "Public Key Fingerprint" "value" : "Public Key Fingerprint"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Impressão Digital da Chave Pública"
}
} }
} }
}, },
@@ -6047,12 +6020,6 @@
"state" : "translated", "state" : "translated",
"value" : "Signing CA Fingerprint" "value" : "Signing CA Fingerprint"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Impressão Digital da AC de Assinatura"
}
} }
} }
}, },
@@ -6064,12 +6031,6 @@
"state" : "translated", "state" : "translated",
"value" : "Valid After" "value" : "Valid After"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Válido após"
}
} }
} }
}, },
@@ -6081,12 +6042,6 @@
"state" : "translated", "state" : "translated",
"value" : "Valid Until" "value" : "Valid Until"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Válido até"
}
} }
} }
}, },
@@ -6098,12 +6053,6 @@
"state" : "translated", "state" : "translated",
"value" : "Validity Range" "value" : "Validity Range"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Intervalo de validade"
}
} }
} }
}, },
@@ -6236,7 +6185,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Clique para copiar" "value" : "Clique para Copiar"
} }
}, },
"ro" : { "ro" : {
@@ -6791,7 +6740,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você mudar suas configurações de biometria de _qualquer forma_, incluindo adicionar uma nova impressão digital, esta chave não será mais acessível." "value" : "Se você mudar suas configurações de biometria de _qualquer forma_, incluindo adicionar uma nova impressão digital, esta chave não estará mais acessível."
} }
}, },
"ro" : { "ro" : {
@@ -7346,7 +7295,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Isso é exibido ao final da sua chave pública. É geralmente um endereço de email." "value" : "Isto é exibido ao final da sua chave pública. É geralmente um endereço de email."
} }
}, },
"ro" : { "ro" : {
@@ -7900,8 +7849,8 @@
}, },
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "new",
"value" : "Indisponível nessa versão do macOS" "value" : "Unavailable on this version of macOS"
} }
}, },
"ro" : { "ro" : {
@@ -8086,7 +8035,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Aviso: Chaves ML-DSA são muito novas e ainda não suportadas por vários servidores. Por favor, verifique se o servidor em que você usará essa chave aceita chaves ML-DSA." "value" : "Aviso: Chaves ML-DSA são muito novas e não são suportadas por muitos servidores ainda. Por favor, verifique se o servidor que você estará utilizando esta chave aceita chaves ML-DSA."
} }
}, },
"ro" : { "ro" : {
@@ -8641,7 +8590,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Nenhuma autenticação é solicitada enquanto seu Mac estiver desbloqueado, mas você será notificado quando um segredo for usado." "value" : "Autenticação não é requerida enquanto seu Mac estiver destravado, mas você será notificado quando um segredo for utilizado."
} }
}, },
"ro" : { "ro" : {
@@ -9566,7 +9515,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Você será solicitado a autenticar usando Touch ID, Apple Watch ou senha a cada uso." "value" : "Você será requerido a autenticar utilizando Touch ID, Apple Watch ou senha antes de cada uso."
} }
}, },
"ro" : { "ro" : {
@@ -9751,7 +9700,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Requer autenticação" "value" : "Requer Autenticação"
} }
}, },
"ro" : { "ro" : {
@@ -9936,7 +9885,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Criar um novo Segredo" "value" : "Criar um Novo Segredo"
} }
}, },
"ro" : { "ro" : {
@@ -10121,7 +10070,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Não apagar" "value" : "Não Apagar"
} }
}, },
"ro" : { "ro" : {
@@ -10491,7 +10440,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você apagar %1$(secretName)@, não poderá recuperá-lo. Digite “%2$(confirmSecretName)@” para confirmar." "value" : "Se você deletar %1$(secretName)@, você não será permitido recuperá-lo. Digite “%2$(confirmSecretName)@” para confirmar."
} }
}, },
"ro" : { "ro" : {
@@ -10676,7 +10625,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Apagar %1$(name)@?" "value" : "Deletar %1$(name)@?"
} }
}, },
"ro" : { "ro" : {
@@ -11046,7 +10995,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Salvar" "value" : "Renomear"
} }
}, },
"ro" : { "ro" : {
@@ -11231,7 +11180,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Crie um novo clicando aqui." "value" : "Criar um novo clicando aqui."
} }
}, },
"ro" : { "ro" : {
@@ -11601,7 +11550,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Parece que você pode ter atualizado o macOS recentemente. Às vezes, isso coloca o Secure Enclave em um estado estranho, e talvez você precise reiniciar seu Mac antes que as coisas comecem a funcionar novamente." "value" : "Parece que você pode ter atualizado recentemente o macOS. Às vezes, isto coloca o Secure Enclave em um estado estranho, e talvez você precise reiniciar seu Mac antes que as coisas comecem a funcionar novamente."
} }
}, },
"ro" : { "ro" : {
@@ -11786,7 +11735,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Segredos faltando?" "value" : "Credenciais faltando?"
} }
}, },
"ro" : { "ro" : {
@@ -11971,7 +11920,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Use a ferramenta de gestão do seu Smart Card para criar um segredo." "value" : "Utilize sua ferramenta de gestão de Smart Card para criar um segredo."
} }
}, },
"ro" : { "ro" : {
@@ -12156,7 +12105,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive suporta chaves EC256, EC384 e RSA2048." "value" : "Secretive suporta chaves EC256, EC384, RSA1024 e RSA2048."
} }
}, },
"ro" : { "ro" : {
@@ -12399,6 +12348,9 @@
} }
} }
} }
},
"example.com" : {
}, },
"export SSH_AUTH_SOCK=%@" : { "export SSH_AUTH_SOCK=%@" : {
"localizations" : { "localizations" : {
@@ -13254,7 +13206,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Há uma lista de instruções para aplicativos no GitHub, mantida pela comunidade. Se o aplicativo que você está procurando não é suportado, registre uma issue e a comunidade deve conseguir ajudar." "value" : "Há uma lista de instruções para aplicativos no GitHub, mantida pela comunidade. Se o aplicativo que você está procurando não é suportado, registre um ticket para que a comunidade possa ajudar."
} }
}, },
"ro" : { "ro" : {
@@ -13439,7 +13391,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Há uma lista de instruções para shells no GitHub, mantida pela comunidade. Se o shell que você está procurando não é suportado, registre uma issue e a comunidade deve conseguir ajudar." "value" : "Há uma lista de instruções para aplicativos no GitHub, mantida pela comunidade. Se o aplicativo que você está procurando não é suportado, registre um ticket para que a comunidade possa ajudar."
} }
}, },
"ro" : { "ro" : {
@@ -13507,12 +13459,6 @@
"state" : "translated", "state" : "translated",
"value" : "your_email@example.com" "value" : "your_email@example.com"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "seu_email@exemplo.com.br"
}
} }
} }
}, },
@@ -13524,12 +13470,6 @@
"state" : "translated", "state" : "translated",
"value" : "The email address you set when you configured git (visible in gitconfig)." "value" : "The email address you set when you configured git (visible in gitconfig)."
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "O endereço de email que você definiu quando configurou o git (visível no gitconfig)."
}
} }
} }
}, },
@@ -13541,12 +13481,6 @@
"state" : "translated", "state" : "translated",
"value" : "Email Address" "value" : "Email Address"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Endereço de email"
}
} }
} }
}, },
@@ -13676,7 +13610,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Você precisará criar um Segredo antes de configurar essa ação." "value" : "Você precisará criar uma Credencial antes de configurar esta ação."
} }
}, },
"ro" : { "ro" : {
@@ -13861,7 +13795,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Configurar usando Segredo" "value" : "Configurar Usando Credencial"
} }
}, },
"ro" : { "ro" : {
@@ -14046,7 +13980,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Sem Segredo" "value" : "Sem Credenciais"
} }
}, },
"ro" : { "ro" : {
@@ -14231,7 +14165,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Segredo" "value" : "Credencial"
} }
}, },
"ro" : { "ro" : {
@@ -14416,7 +14350,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Você pode configurar mais de uma ferramenta, elas geralmente não interferem umas com as outras." "value" : "Você pode configurar mais de uma ferramenta, eles geralmente não interferem uns com os outros."
} }
}, },
"ro" : { "ro" : {
@@ -14971,7 +14905,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você estiver tentando assinar seus commits no git, configure Assinatura no Git." "value" : "Se você estiver tentando registrar seus commits no git, configure o Git Signing."
} }
}, },
"ro" : { "ro" : {
@@ -15156,7 +15090,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você está tentando configurar qualquer coisa em sua linha de comando para usar o Secretive, configure seu shell." "value" : "Se você está tentando configurar qualquer coisa em sua linha de comando para usar com Secretive, configure seu shell."
} }
}, },
"ro" : { "ro" : {
@@ -15341,7 +15275,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você não sabe qual shell usa e não o alterou, você provavelmente está usando `%(shellName)@`." "value" : "Se você não sabia qual shell você usa e não alterou, você provavelmente está usando `%(shellName)@`."
} }
}, },
"ro" : { "ro" : {
@@ -15711,7 +15645,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Configurando ferramentas para o Secretive" "value" : "Configurando Ferramentas para Secretive"
} }
}, },
"ro" : { "ro" : {
@@ -15896,7 +15830,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "A maioria das ferramentas tentará procurar chaves SSH no disco em `~/.ssh`. Para usar o Secretive, precisamos configurar essas ferramentas para falarem com o Secretive ao invés disso." "value" : "A maioria das ferramentas tentará procurar chaves SSH no disco em `~/.ssh`. Para usar o Secretive, precisamos configurar essas ferramentas para comunicar com o Secretive."
} }
}, },
"ro" : { "ro" : {
@@ -16081,7 +16015,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O que devo configurar?" "value" : "O que devo Configurar?"
} }
}, },
"ro" : { "ro" : {
@@ -17192,7 +17126,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Arquivo de configuração" "value" : "Arquivo de Configuração"
} }
}, },
"ro" : { "ro" : {
@@ -17562,7 +17496,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Você pode dizer ao SSH para usar uma chave específica com determinado host. Consulte a documentação na web para mais detalhes." "value" : "Você pode pedir ao SSH para usar uma chave específica para um determinado host. Consulte a documentação na web para mais detalhes."
} }
}, },
"ro" : { "ro" : {
@@ -18304,7 +18238,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Assinatura no Git" "value" : "Assinatura Git"
} }
}, },
"ro" : { "ro" : {
@@ -18861,7 +18795,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Ver no GitHub" "value" : "Visualizar no GitHub"
} }
}, },
"ro" : { "ro" : {
@@ -19046,7 +18980,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Ver documentação na web" "value" : "Ver Documentação na Web"
} }
}, },
"ro" : { "ro" : {
@@ -19289,6 +19223,9 @@
} }
} }
} }
},
"Key Properties" : {
}, },
"no_secure_storage_description" : { "no_secure_storage_description" : {
"extractionState" : "manual", "extractionState" : "manual",
@@ -19601,7 +19538,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Sem Armazenamento Seguro disponível" "value" : "Sem Armazenamento Seguro Disponível"
} }
}, },
"ro" : { "ro" : {
@@ -19786,7 +19723,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Se você procura adicionar um para seu Mac, o YubiKey 5 Series é muito bom." "value" : "Se você está buscando adicionar um para seu Mac, o YubiKey 5 Series é muito bom."
} }
}, },
"ro" : { "ro" : {
@@ -19972,7 +19909,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Manter destrancado" "value" : "Deixar Destrancado"
} }
}, },
"ro" : { "ro" : {
@@ -20158,7 +20095,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Não destrancar" "value" : "Não Destravar"
} }
}, },
"ro" : { "ro" : {
@@ -20225,12 +20162,6 @@
"state" : "translated", "state" : "translated",
"value" : "Name" "value" : "Name"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nome"
}
} }
} }
}, },
@@ -20242,14 +20173,11 @@
"state" : "translated", "state" : "translated",
"value" : "Certificate Name" "value" : "Certificate Name"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Nome do Certificado"
}
} }
} }
},
"Restrictions" : {
}, },
"reveal_in_finder_button" : { "reveal_in_finder_button" : {
"extractionState" : "manual", "extractionState" : "manual",
@@ -20444,12 +20372,6 @@
"state" : "translated", "state" : "translated",
"value" : "Matching Certificates" "value" : "Matching Certificates"
} }
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "Certificados correspondentes"
}
} }
} }
}, },
@@ -21504,7 +21426,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Editar" "value" : "Renomear"
} }
}, },
"ro" : { "ro" : {
@@ -22053,7 +21975,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Esse aplicativo auxiliar se chama **Secret Agent** e você pode vê-lo no Monitor de Atividades de tempos em tempos." "value" : "Este aplicativo de ajuda é chamado **Secret Agent** e você pode vê-lo no Monitor de Atividades de tempo em tempo."
} }
}, },
"ro" : { "ro" : {
@@ -22238,7 +22160,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive precisa configurar um aplicativo auxiliar para funcionar corretamente. Ele irá assinar pedidos de clientes SSH em segundo plano, para que você não precise manter o aplicativo principal do Secretive aberto." "value" : "Secretive precisa configurar um aplicativo de ajuda para funcionar corretamente. Isso irá assinar requisições de clientes SSH no plano de fundo para que você não precise manter o aplicativo Secretive aberto."
} }
}, },
"ro" : { "ro" : {
@@ -22608,7 +22530,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Configurar Agente" "value" : "Configurar Agent"
} }
}, },
"ro" : { "ro" : {
@@ -23533,7 +23455,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "O Secretive vai verificar o GitHub periodicamente para saber se há uma nova versão. Se notar requisições de rede para o GitHub, esse é o motivo." "value" : "Secretive irá periodicamente verificar com o GitHub para verificar se existe uma nova versão. Se você ver alguma requisição de rede para o GitHub, este é o porque."
} }
}, },
"ro" : { "ro" : {
@@ -24460,7 +24382,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Usando o segredo %1$(secretName)@" "value" : "Utilizando o segredo %1$(secretName)@"
} }
}, },
"ro" : { "ro" : {
@@ -24646,7 +24568,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Assinado pedido de %1$(appName)@" "value" : "Requisição Assinada fr %1$(appName)@"
} }
}, },
"ro" : { "ro" : {
@@ -25017,7 +24939,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Smart Card" "value" : "Cartões com chip"
} }
}, },
"ro" : { "ro" : {
@@ -25075,6 +24997,9 @@
} }
} }
} }
},
"Specific" : {
}, },
"unnamed_secret" : { "unnamed_secret" : {
"extractionState" : "manual", "extractionState" : "manual",
@@ -25202,7 +25127,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Sem nome" "value" : "Sem Nome"
} }
}, },
"ro" : { "ro" : {
@@ -25387,7 +25312,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Atualização Crítica de Segurança necessária" "value" : "Atualização Crítica de Segurança Requerida"
} }
}, },
"ro" : { "ro" : {
@@ -25757,7 +25682,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Atualização disponível" "value" : "Atualização Disponível"
} }
}, },
"ro" : { "ro" : {
@@ -26501,7 +26426,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Clique para atualizar" "value" : "Clique para Atualizar"
} }
}, },
"ro" : { "ro" : {
@@ -26872,7 +26797,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Notas de Lançamento" "value" : "Notas de Mudanças"
} }
}, },
"ro" : { "ro" : {
@@ -27057,7 +26982,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Build de Teste" "value" : "Versão de Teste"
} }
}, },
"ro" : { "ro" : {
@@ -27612,7 +27537,7 @@
"pt-BR" : { "pt-BR" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Baixar a Nightly Build mais recente" "value" : "Baixar a última Nightly Build"
} }
}, },
"ro" : { "ro" : {
+3 -3
View File
@@ -36,10 +36,10 @@ import XPCWrappers
self.currentVersion = currentVersion self.currentVersion = currentVersion
_ = Task { _ = Task {
if checkOnLaunch { if checkOnLaunch {
try await checkForUpdates() try? await checkForUpdates()
} }
while true { while !Task.isCancelled {
try await Task.sleep(for: .seconds(Int(checkFrequency))) try? await Task.sleep(for: .seconds(Int(checkFrequency)))
try await checkForUpdates() try await checkForUpdates()
} }
} }
@@ -151,6 +151,7 @@ extension SSHAgentInputParser {
let signature = try signatureBlob.readNextChunk() let signature = try signatureBlob.readNextChunk()
let forwarding = try reader.readNextByteAsBool() let forwarding = try reader.readNextByteAsBool()
switch hostKeyType { switch hostKeyType {
// FIXME: FACTOR OUT?
case "ssh-ed25519": case "ssh-ed25519":
let hostKey = try CryptoKit.Curve25519.Signing.PublicKey(rawRepresentation: hostKeyData) let hostKey = try CryptoKit.Curve25519.Signing.PublicKey(rawRepresentation: hostKeyData)
guard hostKey.isValidSignature(signature, for: sessionID) else { guard hostKey.isValidSignature(signature, for: sessionID) else {
@@ -185,6 +186,7 @@ extension SSHAgentInputParser {
throw AgentParsingError.unhandledRequest throw AgentParsingError.unhandledRequest
} }
case "ssh-rsa": case "ssh-rsa":
// FIXME: HANDLE
throw AgentParsingError.unhandledRequest throw AgentParsingError.unhandledRequest
default: default:
throw AgentParsingError.unhandledRequest throw AgentParsingError.unhandledRequest
@@ -79,23 +79,19 @@ extension Agent {
default: default:
target = nil target = nil
} }
_ = target
response.append(SSHAgent.Response.agentSignResponse.data) response.append(SSHAgent.Response.agentSignResponse.data)
response.append(try await sign(data: context.dataToSign.raw, keyBlob: context.keyBlob, provenance: provenance, target: target)) response.append(try await sign(data: context.dataToSign.raw, keyBlob: context.keyBlob, provenance: provenance, target: target))
logger.debug("Agent returned \(SSHAgent.Response.agentSignResponse.debugDescription)") logger.debug("Agent returned \(SSHAgent.Response.agentSignResponse.debugDescription)")
case .protocolExtension(.openSSH(.sessionBind(let bind))): case .protocolExtension(.openSSH(.sessionBind(let bind))):
// This is disabled until forward enforcement is handled.
_ = bind
response = try await MainActor.run { response = try await MainActor.run {
logger.debug("Agent received bind request but not currently supported.") guard sessionID == nil else {
throw UnhandledRequestError() logger.error("Agent received bind request, but already bound.")
// guard sessionID == nil else { // FIXME: This will break forwarding for now.
// logger.error("Agent received bind request, but already bound.") throw BindingFailure()
// throw BindingFailure() }
// } logger.debug("Agent bound")
// logger.debug("Agent bound") sessionID = bind
// sessionID = bind return SSHAgent.Response.agentSuccess.data
// return SSHAgent.Response.agentSuccess.data
} }
logger.debug("Agent returned \(SSHAgent.Response.agentSuccess.debugDescription)") logger.debug("Agent returned \(SSHAgent.Response.agentSuccess.debugDescription)")
case .unknown(let value): case .unknown(let value):
@@ -0,0 +1,26 @@
import Foundation
extension ProcessInfo {
private static let fallbackTeamID = "Z72PRUAWF6"
private static let teamID: String = {
#if DEBUG
guard let task = SecTaskCreateFromSelf(nil) else {
assertionFailure("SecTaskCreateFromSelf failed")
return fallbackTeamID
}
guard let value = SecTaskCopyValueForEntitlement(task, "com.apple.developer.team-identifier" as CFString, nil) as? String else {
// assertionFailure("SecTaskCopyValueForEntitlement(com.apple.developer.team-identifier) failed")
return fallbackTeamID
}
return value
#else
/// Always use hardcoded team ID for release builds, just in case.
return fallbackTeamID
#endif
}()
public var teamID: String { Self.teamID }
}
@@ -12,9 +12,7 @@ public final class XPCServiceDelegate: NSObject, NSXPCListenerDelegate {
newConnection.exportedInterface = NSXPCInterface(with: (any _XPCProtocol).self) newConnection.exportedInterface = NSXPCInterface(with: (any _XPCProtocol).self)
let exportedObject = exportedObject let exportedObject = exportedObject
newConnection.exportedObject = exportedObject newConnection.exportedObject = exportedObject
#if !DEBUG newConnection.setCodeSigningRequirement("anchor apple generic and certificate leaf[subject.OU] = \"\(ProcessInfo.processInfo.teamID)\"")
newConnection.setCodeSigningRequirement("anchor apple generic and certificate leaf[subject.OU] = \"Z72PRUAWF6\"")
#endif
newConnection.resume() newConnection.resume()
return true return true
} }
@@ -8,9 +8,7 @@ public struct XPCTypedSession<ResponseType: Codable & Sendable, ErrorType: Error
public init(serviceName: String, warmup: Bool = false) async throws { public init(serviceName: String, warmup: Bool = false) async throws {
let connection = NSXPCConnection(serviceName: serviceName) let connection = NSXPCConnection(serviceName: serviceName)
connection.remoteObjectInterface = NSXPCInterface(with: (any _XPCProtocol).self) connection.remoteObjectInterface = NSXPCInterface(with: (any _XPCProtocol).self)
#if !DEBUG connection.setCodeSigningRequirement("anchor apple generic and certificate leaf[subject.OU] = \"\(ProcessInfo.processInfo.teamID)\"")
connection.setCodeSigningRequirement("anchor apple generic and certificate leaf[subject.OU] = \"Z72PRUAWF6\"")
#endif
connection.resume() connection.resume()
guard let proxy = connection.remoteObjectProxy as? _XPCProtocol else { fatalError() } guard let proxy = connection.remoteObjectProxy as? _XPCProtocol else { fatalError() }
self.connection = connection self.connection = connection
@@ -13,7 +13,7 @@ import CertificateKit
@Test func emptyStores() async throws { @Test func emptyStores() async throws {
let agent = Agent(storeList: SecretStoreList(), certificateStore: CertificateStore()) let agent = Agent(storeList: SecretStoreList(), certificateStore: CertificateStore())
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities)
let response = await agent.handle(request: request, provenance: .test, hosts: nil) let response = await agent.handle(request: request, provenance: .test)
#expect(response == Constants.Responses.requestIdentitiesEmpty) #expect(response == Constants.Responses.requestIdentitiesEmpty)
} }
@@ -21,7 +21,7 @@ import CertificateKit
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret]) let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
let agent = Agent(storeList: list, certificateStore: CertificateStore()) let agent = Agent(storeList: list, certificateStore: CertificateStore())
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestIdentities)
let response = await agent.handle(request: request, provenance: .test, hosts: nil) let response = await agent.handle(request: request, provenance: .test)
let actual = OpenSSHReader(data: response) let actual = OpenSSHReader(data: response)
let expected = OpenSSHReader(data: Constants.Responses.requestIdentitiesMultiple) let expected = OpenSSHReader(data: Constants.Responses.requestIdentitiesMultiple)
@@ -35,7 +35,7 @@ import CertificateKit
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret]) let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
let agent = Agent(storeList: list, certificateStore: CertificateStore()) let agent = Agent(storeList: list, certificateStore: CertificateStore())
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignatureWithNoneMatching) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignatureWithNoneMatching)
let response = await agent.handle(request: request, provenance: .test, hosts: nil) let response = await agent.handle(request: request, provenance: .test)
#expect(response == Constants.Responses.requestFailure) #expect(response == Constants.Responses.requestFailure)
} }
@@ -44,7 +44,7 @@ import CertificateKit
guard case SSHAgent.Request.signRequest(let context) = request else { return } guard case SSHAgent.Request.signRequest(let context) = request else { return }
let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret]) let list = await storeList(with: [Constants.Secrets.ecdsa256Secret, Constants.Secrets.ecdsa384Secret])
let agent = Agent(storeList: list, certificateStore: CertificateStore()) let agent = Agent(storeList: list, certificateStore: CertificateStore())
let response = await agent.handle(request: request, provenance: .test, hosts: nil) let response = await agent.handle(request: request, provenance: .test)
let responseReader = OpenSSHReader(data: response) let responseReader = OpenSSHReader(data: response)
let length = try responseReader.readNextBytes(as: UInt32.self) let length = try responseReader.readNextBytes(as: UInt32.self)
let type = try responseReader.readNextBytes(as: UInt8.self) let type = try responseReader.readNextBytes(as: UInt8.self)
@@ -68,7 +68,7 @@ import CertificateKit
let signature = try P256.Signing.ECDSASignature(rawRepresentation: rs) let signature = try P256.Signing.ECDSASignature(rawRepresentation: rs)
// Correct signature // Correct signature
#expect(try P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey) #expect(try P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey)
.isValidSignature(signature, for: context.dataToSign.raw)) .isValidSignature(signature, for: context.dataToSign))
} }
// MARK: Witness protocol // MARK: Witness protocol
@@ -79,7 +79,7 @@ import CertificateKit
return true return true
}, witness: { _, _ in }) }, witness: { _, _ in })
let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness) let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness)
let response = await agent.handle(request: .signRequest(.empty), provenance: .test, hosts: nil) let response = await agent.handle(request: .signRequest(.empty), provenance: .test)
#expect(response == Constants.Responses.requestFailure) #expect(response == Constants.Responses.requestFailure)
} }
@@ -93,7 +93,7 @@ import CertificateKit
}) })
let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness) let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness)
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
_ = await agent.handle(request: request, provenance: .test, hosts: nil) _ = await agent.handle(request: request, provenance: .test)
#expect(witnessed) #expect(witnessed)
} }
@@ -109,7 +109,7 @@ import CertificateKit
}) })
let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness) let agent = Agent(storeList: list, certificateStore: CertificateStore(), witness: witness)
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
_ = await agent.handle(request: request, provenance: .test, hosts: nil) _ = await agent.handle(request: request, provenance: .test)
#expect(witnessTrace == speakNowTrace) #expect(witnessTrace == speakNowTrace)
#expect(witnessTrace == .test) #expect(witnessTrace == .test)
} }
@@ -122,7 +122,7 @@ import CertificateKit
store.shouldThrow = true store.shouldThrow = true
let agent = Agent(storeList: list, certificateStore: CertificateStore()) let agent = Agent(storeList: list, certificateStore: CertificateStore())
let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature) let request = try SSHAgentInputParser().parse(data: Constants.Requests.requestSignature)
let response = await agent.handle(request: request, provenance: .test, hosts: nil) let response = await agent.handle(request: request, provenance: .test)
#expect(response == Constants.Responses.requestFailure) #expect(response == Constants.Responses.requestFailure)
} }
@@ -130,7 +130,7 @@ import CertificateKit
@Test func unhandledAdd() async throws { @Test func unhandledAdd() async throws {
let agent = Agent(storeList: SecretStoreList(), certificateStore: CertificateStore()) let agent = Agent(storeList: SecretStoreList(), certificateStore: CertificateStore())
let response = await agent.handle(request: .addIdentity, provenance: .test, hosts: nil) let response = await agent.handle(request: .addIdentity, provenance: .test)
#expect(response == Constants.Responses.requestFailure) #expect(response == Constants.Responses.requestFailure)
} }
@@ -10,14 +10,14 @@ struct StubWitness {
extension StubWitness: SigningWitness { extension StubWitness: SigningWitness {
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, target: SigningRequestTarget?) throws { func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
let objection = speakNow(secret, provenance) let objection = speakNow(secret, provenance)
if objection { if objection {
throw TheresMyChance() throw TheresMyChance()
} }
} }
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, target: SigningRequestTarget?) throws { func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
witness(secret, provenance) witness(secret, provenance)
} }
+7 -7
View File
@@ -13,7 +13,7 @@ import SwiftUI
extension EnvironmentValues { extension EnvironmentValues {
@MainActor fileprivate static let _certificateStore: CertificateStore = CertificateStore() @MainActor fileprivate static let _certificateStore = CertificateStore()
@MainActor var certificateStore: CertificateStore { @MainActor var certificateStore: CertificateStore {
EnvironmentValues._certificateStore EnvironmentValues._certificateStore
@@ -49,20 +49,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) { func applicationDidFinishLaunching(_ aNotification: Notification) {
logger.debug("SecretAgent finished launching") logger.debug("SecretAgent finished launching")
Task { _ = Task {
for await session in socketController.sessions { for await session in socketController.sessions {
Task { _ = Task {
let inputParser = try await XPCAgentInputParser()
let hostsReader = try await XPCHostsfileReader()
let hosts = try? await hostsReader.read()
do { do {
let inputParser = try await XPCAgentInputParser()
let hostsReader = try? await XPCHostsfileReader()
let hosts = try? await hostsReader?.read()
for await message in session.messages { for await message in session.messages {
let request = try await inputParser.parse(data: message) let request = try await inputParser.parse(data: message)
let agentResponse = await agent.handle(request: request, provenance: session.provenance, hosts: hosts) let agentResponse = await agent.handle(request: request, provenance: session.provenance, hosts: hosts)
try session.write(agentResponse) try session.write(agentResponse)
} }
} catch { } catch {
try? session.close() try session.close()
} }
} }
} }
+2 -2
View File
@@ -16,10 +16,10 @@
<string>1</string> <string>1</string>
<key>com.apple.security.hardened-process.hardened-heap</key> <key>com.apple.security.hardened-process.hardened-heap</key>
<true/> <true/>
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
<string>2</string>
<key>com.apple.security.smartcard</key> <key>com.apple.security.smartcard</key>
<true/> <true/>
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
<string>2</string>
<key>keychain-access-groups</key> <key>keychain-access-groups</key>
<array> <array>
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string> <string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
@@ -8,9 +8,10 @@ final class SecretAgentHostsfileReader: NSObject, XPCProtocol {
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.SecretAgentHostsfileReader", category: "SecretAgentHostsfileReader") private let logger = Logger(subsystem: "com.maxgoedjen.secretive.SecretAgentHostsfileReader", category: "SecretAgentHostsfileReader")
func process(_ data: Data) async throws -> [Data: String] { func process(_ data: Data) async throws -> [Data: String] {
logger.log("Parsing hostsfile") logger.log("Parser parsed certificate")
var result: [Data: String] = [:] var result: [Data: String] = [:]
for try await line in URL(filePath: NSHomeDirectory().appending("/.ssh/known_hosts")).lines { // FIXME: THIS
for try await line in URL(filePath: "/Users/max/.ssh/known_hosts").lines {
let split = line.split(separator: " ").map(String.init) let split = line.split(separator: " ").map(String.init)
guard split.count == 3 else { continue } guard split.count == 3 else { continue }
guard let decoded = Data(base64Encoded: split[2]) else { continue } guard let decoded = Data(base64Encoded: split[2]) else { continue }
+9 -24
View File
@@ -1710,22 +1710,17 @@
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = NO;
ENABLE_ENHANCED_SECURITY = YES; ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES; ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
ENABLE_RESOURCE_ACCESS_CALENDARS = NO; ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
ENABLE_RESOURCE_ACCESS_CAMERA = NO; ENABLE_RESOURCE_ACCESS_CAMERA = NO;
ENABLE_RESOURCE_ACCESS_CONTACTS = NO; ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
ENABLE_RESOURCE_ACCESS_LOCATION = NO; ENABLE_RESOURCE_ACCESS_LOCATION = NO;
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
ENABLE_RESOURCE_ACCESS_USB = NO;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -1741,6 +1736,7 @@
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO; RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;
}; };
name = Test; name = Test;
}; };
@@ -1755,22 +1751,17 @@
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)"; DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = NO;
ENABLE_ENHANCED_SECURITY = YES; ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES; ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
ENABLE_RESOURCE_ACCESS_CALENDARS = NO; ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
ENABLE_RESOURCE_ACCESS_CAMERA = NO; ENABLE_RESOURCE_ACCESS_CAMERA = NO;
ENABLE_RESOURCE_ACCESS_CONTACTS = NO; ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
ENABLE_RESOURCE_ACCESS_LOCATION = NO; ENABLE_RESOURCE_ACCESS_LOCATION = NO;
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
ENABLE_RESOURCE_ACCESS_USB = NO;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -1786,6 +1777,7 @@
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO; RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;
}; };
name = Debug; name = Debug;
}; };
@@ -1801,22 +1793,17 @@
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"SecretAgent/Preview Content\"";
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)"; DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = NO;
ENABLE_ENHANCED_SECURITY = YES; ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
ENABLE_POINTER_AUTHENTICATION = YES; ENABLE_POINTER_AUTHENTICATION = YES;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO; ENABLE_RESOURCE_ACCESS_AUDIO_INPUT = NO;
ENABLE_RESOURCE_ACCESS_BLUETOOTH = NO;
ENABLE_RESOURCE_ACCESS_CALENDARS = NO; ENABLE_RESOURCE_ACCESS_CALENDARS = NO;
ENABLE_RESOURCE_ACCESS_CAMERA = NO; ENABLE_RESOURCE_ACCESS_CAMERA = NO;
ENABLE_RESOURCE_ACCESS_CONTACTS = NO; ENABLE_RESOURCE_ACCESS_CONTACTS = NO;
ENABLE_RESOURCE_ACCESS_LOCATION = NO; ENABLE_RESOURCE_ACCESS_LOCATION = NO;
ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO; ENABLE_RESOURCE_ACCESS_PHOTO_LIBRARY = NO;
ENABLE_RESOURCE_ACCESS_PRINTING = NO;
ENABLE_RESOURCE_ACCESS_USB = NO;
INFOPLIST_FILE = SecretAgent/Info.plist; INFOPLIST_FILE = SecretAgent/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -1833,6 +1820,7 @@
RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO; RUNTIME_EXCEPTION_DEBUGGING_TOOL = NO;
RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO; RUNTIME_EXCEPTION_DISABLE_EXECUTABLE_PAGE_PROTECTION = NO;
RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO; RUNTIME_EXCEPTION_DISABLE_LIBRARY_VALIDATION = NO;
SWIFT_TREAT_WARNINGS_AS_ERRORS = NO;
}; };
name = Release; name = Release;
}; };
@@ -1847,7 +1835,6 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)"; DEVELOPMENT_TEAM = "$(SECRETIVE_DEVELOPMENT_TEAM)";
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -1879,7 +1866,6 @@
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -1913,7 +1899,6 @@
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=macosx*]" = Z72PRUAWF6; "DEVELOPMENT_TEAM[sdk=macosx*]" = Z72PRUAWF6;
ENABLE_APP_SANDBOX = YES; ENABLE_APP_SANDBOX = YES;
ENABLE_ENHANCED_SECURITY = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu17; GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@@ -12,11 +12,11 @@
<true/> <true/>
<key>com.apple.security.hardened-process.dyld-ro</key> <key>com.apple.security.hardened-process.dyld-ro</key>
<true/> <true/>
<key>com.apple.security.hardened-process.enhanced-security-version-string</key> <key>com.apple.security.hardened-process.enhanced-security-version</key>
<string>2</string> <integer>1</integer>
<key>com.apple.security.hardened-process.hardened-heap</key> <key>com.apple.security.hardened-process.hardened-heap</key>
<true/> <true/>
<key>com.apple.security.hardened-process.platform-restrictions-string</key> <key>com.apple.security.hardened-process.platform-restrictions</key>
<string>2</string> <integer>2</integer>
</dict> </dict>
</plist> </plist>