amagovpt / autenticacao.gov

Middleware Oficial de Identificação Eletrónica em Portugal - Cartão de Cidadão, da Chave Móvel Digital e Sistema de Certificação de atributos profissionais
https://www.autenticacao.gov.pt
European Union Public License 1.2
168 stars 33 forks source link

Problema de concorrência na leitura entre aplicações (pt.portugal.eid) - C# #173

Open jcprata opened 1 month ago

jcprata commented 1 month ago

Num cenário com 2 aplicações (C#) que estão ao mesmo tempo à espera da leitura de dados do mesmo Cartão do Cidadão no mesmo leitor, a primeira aplicação a fazer a leitura funciona bem, mas a segunda retorna um erro. Quando usado a implementação através do namespace eidpt funciona bem, mas com o pt.portugal.eid já não. Já implementei uma abordagem com Begin e End Transaction, mas o problema continua.

O que recomendam para ultrapassar esta concorrência?

Capturar

agrr commented 1 month ago

Boa tarde,

os acessos concorrentes ao mesmo cartão podem gerar erros de facto. O ideal seria tentar evitar os acessos concorrentes coordenando as duas aplicações, se possível.

Internamente no middleware tentamos que os acessos concorrentes não quebrem as operações de assinatura usando as funções SCardBeginTransaction e SCardEndTransaction.

Se conseguir partilhar os logs gerados nas aplicações podemos investigar melhor o issue. Deve ativar o modo de diagnóstico através da página de configurações da aplicação: https://amagovpt.github.io/docs.autenticacao.gov/user_manual.html#configura%C3%A7%C3%B5es

Os ficheiros de log são gerados em C:\Program Files\Portugal Identity Card\log

Sobre a componente/DLL eidpt sabemos que é um projeto não-oficial e que está abandonado desde há bastante tempo, por isso não recomendamos o seu uso.

jcprata commented 1 month ago

Bom dia,

Obrigado pela resposta.

Criei o seguinte cenário de teste que retornou um erro:

1- Abri as duas aplicações (A e B) 2- Inseri o Cartão do Cidadão no leitor 3- As duas aplicações, leram corretamente: 3.1- A aplicação "A" leu corretamente o bloco .getID() e depois o .getAddr() - por esta ordem 3.2- A aplicação "B" leu corretamente o bloco .getID() 4- Removi o Cartão Cidadão do leitor e voltei a colocar de seguida 5- A aplicação "B" leu corretamente o bloco .getID() 6- A aplicação "A" leu corretamenteo o bloco .getID(), mas não leu corretamente o bloco .getAddr(), mais concretamente no método .getPinByPinRef(PTEID_Pin.ADDR_PIN), quando é pedido na dialog o PIN da morada, tendo gerado no log o seguinte:

C:\_Dev\AplicaçãoA.Shell.exe - 2024-07-26 10:06:09 - 20220|13392 - dialog - DEBUG: --> DlgAskPin() returns DLG_OK C:\_Dev\AplicaçãoA.Shell.exe - 2024-07-26 10:06:09 - 20220|13392 - cardlayer - DEBUG: SCardTransmit(00 20 00 83 08) C:\_Dev\AplicaçãoA.Shell.exe - 2024-07-26 10:06:09 - 20220|13392 - cardlayer - DEBUG: SCardTransmit(): 0x80100068 C:\_Dev\AplicaçãoA.Shell.exe - 2024-07-26 10:06:09 - 20220|13392 - eidlib - DEBUG: PTEID_Exception generated from pcsc.cpp:366 error code: e1d0020e C:\_Dev\AplicaçãoA.Shell.exe - 2024-07-26 10:06:09 - 20220|13392- cardlayer - DEBUG: SCardEndTransaction(0x0): 0x80100068

Em ambas as aplicações estou a invocar o BeginTransaction antes da leitura do PTEID_ReaderContext.getEIDCard(), e no finally no scope (try) da leitura dos dados invoco o EndTransaction.

EDIT:

Pelo que consegui apurar nos logs, o erro está a ser gerado na invocação deste método: PCSC.cpp LONG lRet = SCardTransmit(hCard, pioSendPci, oCmdAPDU.GetBytes(), (DWORD) oCmdAPDU.Size(), NULL, tucRecv, &dwRecvLen);

Sendo que é retornado o valor 0x80100068 e a documentação da Microsoft refere o seguinte:

https://learn.microsoft.com/en-us/windows/win32/api/winscard/nf-winscard-scardtransmit https://learn.microsoft.com/en-us/windows/win32/secauthn/authentication-return-values

image