Restrição do TLS com APN Privada

O uso do TLS implica a configuração de um hostname, em vez de um IP, no parâmetro de endereço do servidor SiTef. Para que o componente de TLS possa atestar a autenticidade do servidor, esse hostname deve ser obrigatoriamente igual ao nome que consta no certificado TLS.

Devido a essa restrição, a comunicação TLS não pode ser utilizada no cenário GPRS com APN Privada. Isso porque, em geral, não há resolução de hostname nesse cenário — normalmente usa-se somente os IPs da VPN — o que resulta em falha na verificação de autenticidade do certificado TLS do servidor. Portanto, se o terminal utilizar um chip GPRS com APN Privada, a aplicação não poderá utilizar a configuração TLS.

Caso a aplicação realize a alternância de diferentes formas de comunicação que incluam tanto a Internet pública — onde o uso de TLS é obrigatório por norma — como APN Privada — onde é preciso que exista uma VPN segura —, a aplicação precisará desenvolver um mecanismo de chaveamento da configuração para ligar e desligar a configuração TLS de acordo com o canal de comunicação.

Em outras palavras, se o terminal estiver utilizando a comunicação via Internet pública (WiFi, Ethernet, APN Pública), a aplicação deve ativar a configuração TLS e definir o endereço do Sitef de acordo (i.e. usar o hostname em vez de IP). E se o terminal estiver utilizando a comunicação com APN Privada com VPN, a aplicação deve desativar a configuração TLS e definir o endereço do SiTef de acordo (i.e. usar o IP da VPN). Neste caso, é importante certificar-se de que as regras de segurança aplicadas ao ambiente da aplicação permitem que o TLS seja desligado.

A aplicação pode implementar esse comportamento da maneira mais adequada a estrutura do seu código-fonte. Mas, em linhas gerais, o procedimento para obter esse comportamento deve seguir a seguinte lógica básica:

  1. Antes do início de cada transação, verificar qual meio de comunicação está ativo no momento.
    1. Se a comunicação exigir TLS (se for WiFi, Ethernet ou Celular com APN Pública), habilitar TLS e definir o endereço do SiTef como o hostname do SiTef.
    2. Se a comunicação não suportar TLS (Celular com APN Privada), desabilitar TLS e definir endereço do SiTef como o IP do SiTef na VPN.
  2. Inicia a transação.

A seguir, ilustramos essa lógica em trechos de código considerando os cenários de integração com CliSiTef e com m-SiTef.

Detecção da Comunicação#

public static boolean comunicacaoPermiteTls(Context context) {
boolean result = true;
// Aqui estamos assumindo que a comunicação por Celular sempre usa uma
// APN Privada. Se isso não for verdade, a aplicação deverá implementar um
// mecanismo adicional para determinal se APN é privada ou não.
// Essa verificação provavelmente dependerá do modelo do Android.
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (cm != null) {
NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
result = true;
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
result = false;
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
result = true;
}
}
}
} else {
if (cm != null) {
NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
result = true;
} else if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
result = false;
} else if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
result = true;
}
}
}
}
return result;
}

Cenário CliSiTef#

// O fluxo de instanciação e chamada à CliSiTef foi simplificado
// para ilustrar o mecanismo de chaveamento de conexão.
CliSiTef clisitef = new CliSiTef(this.getApplicationContext());
//...
String sitefAddr;
String storeId = "00000000";
String terminalId = "TERM0000";
String comParams;
// Antes do início de cada transação, verificar qual meio de comunicação está ativo
// no momento.
if (comunicacaoPermiteTls(getApplicationContext())) {
// Se a comunicação exigir TLS (se for WiFi, Ethernet ou Celular com APN Pública),
// habilitar TLS e definir o endereço do SiTef como o hostname do SiTef.
comParams = "[TipoComunicacaoExterna=SSL;CaminhoCertificadoCA=ca_cert.pem]";
sitefAddr = "sitef.exemplotls.com.br:20000";
} else {
// Se a comunicação não suportar TLS (Celular com APN Privada), desabilitar TLS e
// definir endereço do SiTef como o IP do SiTef na VPN.
// (Verificar se as regras de segurança permitem desligar o TLS no seu ambiente!)
comParams = "";
sitefAddr = "192.168.0.2:10000";
}
int res = clisitef.configure(sitefAddr, storeId, terminalId, comParams);
if (res != 0) {
// trata erro
}
//...
int modalidade = 0;
String valor = "1000";
String docFiscal = "123456";
String dataFiscal = "20230518";
String horaFiscal = "160000";
String operador = "OPERADOR";
String restricoes = "";
clisitef.startTransaction (this, modalidade, valor, docFiscal, dataFiscal, horaFiscal, operador, restricoes);
//...

Cenário m-SiTef#

Intent i = new Intent("br.com.softwareexpress.sitef.msitef.ACTIVITY_CLISITEF");
i.putExtra("empresaSitef", "00000000");
i.putExtra("operador", "OPERADOR");
i.putExtra("data", "20230519");
i.putExtra("hora", "150000");
i.putExtra("numeroCupom", "123456");
i.putExtra("numParcelas", "3");
i.putExtra("modalidade", "0");
i.putExtra("valor", "9000");
i.putExtra("CNPJ_CPF", "12345678909");
i.putExtra("timeoutColeta", "30");
i.putExtra("acessibilidadeVisual", "0");
// Antes do início de cada transação, verificar qual meio de comunicação está ativo
// no momento.
if (comunicacaoPermiteTls(getApplicationContext())) {
// Se a comunicação exigir TLS (se for WiFi, Ethernet ou Celular com APN Pública),
// habilitar TLS e definir o endereço do SiTef como o hostname do SiTef.
i.putExtra("comExterna", "1");
i.putExtra("enderecoSitef", "sitef.exemplotls.com.br:20000");
} else {
// Se a comunicação não suportar TLS (Celular com APN Privada), desabilitar TLS e
// definir endereço do SiTef como o IP do SiTef na VPN.
// (Verificar se as regras de segurança permitem desligar o TLS no seu ambiente!)
i.putExtra("comExterna", "0");
i.putExtra("enderecoSitef", "192.168.0.2:10000");
}
// Inicia a transação via m-SiTef.
startActivityForResult(i,1234);