Instalas un perfil, o túnel érguense e todo parece rematado. Despois o teléfono reiníciase, on-demand esperta a conexión sen ningunha app en primeiro plano e o túnel négase a arrincar. O perfil segue aí e o contrasinal segue sendo correcto, e por iso este fallo manda á xente buscar no lugar equivocado. Unha Network Extension non pode ler o teu segredo do perfil: necesita unha referencia do chaveiro que poida resolver por si mesma.

O percorrido de abaixo segue un só intento de conexión por esa entrega, desde a consulta que constrúe a referencia ata o reinicio que a pon a proba.

O perfil garda unha asa, non o segredo

NEVPNProtocol expón passwordReference e sharedSecretReference por un motivo. Cando o demonio inicia un túnel pode que non se execute dentro do teu proceso, así que non pode chamar o teu código e pedir un contrasinal. Le unha referencia persistente do chaveiro, resólvea no seu propio contexto e obtén o elemento el mesmo.

Constrúes esa referencia pedíndolla ao chaveiro, que é unha petición distinta de pedir os datos:

let query: [String: Any] = [
  kSecClass as String: kSecClassGenericPassword,
  kSecAttrService as String: "vpn-credentials",
  kSecAttrAccount as String: "user",
  kSecReturnPersistentRef as String: true,
  kSecMatchLimit as String: kSecMatchLimitOne
]

Entrega o obxecto devolto ao protocolo, non os datos do elemento. Na práctica o perfil rexistra onde vive o segredo, e por iso unha copia de seguridade da configuración non duplica o contrasinal en silencio dentro dun plist.

Por que a API responde -50

errSecParam significa que a petición ou o valor estaban mal formados para a operación, e é o erro que máis se ve cando se mesturan as peticións de referencia e de datos. Pedir datos mentres o código receptor agarda unha referencia, asignar bytes en bruto a passwordReference ou consultar cun grupo de acceso que a app non pode usar, todos o producen.

As bibliotecas envoltorio invitan a isto. Un axudante que devolve bytes non é intercambiable cun que devolve unha referencia, así que a reparación adoita ser outra consulta e non outro contrasinal.

A mesma desavinza explica un perfil que se garda sen queixa e despois non conecta: o que se gardou é un blob, non unha asa, e o demonio non ten nada que resolver.

Garda ben, falla ao conectar

Gardar exercita o contexto da túa app. Conectar exercita o do demonio, e os dous non teñen o mesmo acceso. Por iso un perfil pode pasar todas as probas do simulador e fallar no primeiro arrinque on-demand.

Esa é tamén a forma do síntoma do reinicio: funciona mentres a app está aberta e morre cando o sistema inicia o túnel pola súa conta.

Proba o camiño en segundo plano a propósito antes de publicar. Dispara unha conexión on-demand coa app pechada e despois le a consola do dispositivo en lugar do log da app, porque o fallo rexístrao o proceso que intentou resolver a referencia. Se a consola mostra que o demonio rexeita o elemento, a referencia está ben e o problema é a accesibilidade do elemento.

A accesibilidade decide se un reinicio funciona

O elemento ten que ser lexible polo proceso do sistema que arrinque o túnel, e iso é un público máis amplo que a túa app mentres está en primeiro plano. Esa restrición escolle o atributo de accesibilidade por ti. Un elemento protexido ata o primeiro desbloqueo está dispoñible para un arrinque en segundo plano despois de que o dispositivo se desbloquease unha vez; un elemento que esixe que o dispositivo estea desbloqueado agora mesmo non o está.

Escoller a clase máis estrita é tentador e é exactamente o que rompe un perfil on-demand nun teléfono bloqueado.

Despois de cambiar a clase, recrea o elemento en lugar de editar atributos no existente, e volve gardar o protocolo cunha referencia nova. Os cambios de atributos nun elemento existente non sempre producen o comportamento que implica a documentación, e un elemento reconstruído elimina a dúbida.

A rotación é onde se podrecen os perfís gardados

Cambiar o contrasinal no chaveiro non cambia automaticamente aquilo a que apunta o perfil gardado. Borrar o elemento é peor: o perfil conserva unha referencia a algo que xa non existe, e o fallo parece un rexeitamento de autenticación.

Rota nunha soa orde. Actualiza o elemento, consulta unha referencia persistente nova, volve gardar o protocolo e despois conecta coa app pechada para demostrar que o demonio aínda pode resolvela. Mantén o contrasinal do usuario e o segredo compartido en elementos separados para que cada un rote segundo o seu propio calendario, e non rexistres nunca o dicionario da consulta nin a referencia mesma. A asa non é un segredo, pero é un mapa cara a un.

Artigos relacionados