Histórico da Página
Resumo
Este how to Este 'How To' tem como objetivo apresentar e explicar a validação de clientes RPC como ferramenta para reforçar a segurança na execução de chamadas via RPC.
Sumário
Índice | ||
---|---|---|
|
Validação de Clientes RPC
...
Através da execução de uma função AdvPL, definida pelo usuário e indicada no arquivo de configurações do servidor RPC, é possível criar uma política flexível de permissões de execução de funções via RPC de maneira flexível.
A medida de segurança é opcional pois depende da configuração ou não da função de validação. No entanto, uma vez configurada, a validação será executada de maneira obrigatória e a cada chamada de método RPC por parte do cliente, até que o servidor seja reiniciado com validação desabilitada.
...
A função de validação de clientes RPC é indicada no arquivo de configuração do servidor RPC na seção 'RPC', chave 'OnCall'.
Caso configurada, habilita a validação de clientes RPC; caso não configurada, o cliente RPC é considerado válido por padrão.
Localização da Função de Validação
A função definida pelo usuário deverá estar no mesmo ambiente (environment) a ser utilizado para execução das tarefas (funções) RPC no servidor, conforme instância da classe 'TRpc' em uso.
Assinatura da Função de Validação
A função de validação de clientes RPC deverá receber ter 3 (três) strings de caracteres como argumentos, definindo o IP do cliente RPC, o nome da máquina do cliente RPC e o ambiente (environment) no servidor RPC onde a função está localizada.
User Function SomeFunc( _cClientIP, _cClientHostName, _cServerEnv )
Local lResult := .F.
Return lResult
, e deverá retornar um lógico, indicando o resultado da validação conforme definido no corpo da função.
Sintaxe
Bloco de código | ||
---|---|---|
| ||
<SomeFunc>User Function < SomeFunc >( < _cClientIP >, < _cClientHostName >, < _cServerEnv > ) |
Parâmetros
Nome | Tipo | Descrição | Obrigatório | Referência |
---|---|---|---|---|
_cClientIP | caractere | IP do cliente RPC. | X |
|
_cClientHostName | caractere | Nome da máquina (host name) do cliente RPC. | X |
|
_cServerEnv | caractere | Ambiente (environment) no servidor RPC onde a função está localizada. | X |
|
Retorno
Nome | Tipo | Descrição |
---|---|---|
cRetlResult | caractere | Retorna uma cadeia de caracteres criptografada. |
Observações
- Página com a tabela ASCII: http://www.ascii-code.com/
- Página online para criptografar RC4: http://www.fyneworks.com/encryption/rc4-encryption/
...
lógico | Retorna o resultado da validação do cliente RPC, conforme definido no corpo da função criada. Caso o retorno seja .T., indica que o cliente está habilitado a executar funções via RPC; caso o retorno seja .F., indica que o cliente não está habilitado a executar funções via RPC. |
Observações
Nos exemplos de função de validação e seus testes, é assumido que:
- existe no servidor um ambiente propriamente configurado com nome 'EnvTopPorSQL';
- não existe no servidor um ambiente propriamente configurado com nome 'OutroEnv';
- a função de validação foi compilada no ambiente 'EnvTopPorSQL' do servidor;
- a função de validação foi configurada no servidor, seção 'RPC', chave 'OnCall'.
Exemplo da Função de Validação (Lado do Servidor)
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
#include "TOTVS.CH" // --------------------------------------------------------------------------- // // LADO DO SERVIDOR // // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Função para verificar se o cliente pode executar funções via RPC no // servidor. // --------------------------------------------------------------------------- User Function rc4crypt_exemplo() local cRet local cOriginal // resultado ASCII em hex: "55AB394524" cRet = rc4crypt( "abcde" ,"123456789", .T.) conout("Criptografado em ascii = " + cRet) cRet = rc4crypt( "abcde" ,"123456789", .F.) conout("Criptografado em string = " + cRet) // processo inverso cOriginal = rc4crypt(cRet, "123456789", .F.) conout("String original = " + cOriginal) // converte de ASCII em hex para string cRet = chr(CTON('55', 16)) cRet += chr(CTON('AB', 16)) cRet += chr(CTON('39', 16)) cRet += chr(CTON('45', 16)) cRet += chr(CTON('24', 16)) conout ("resultado em hex convertido = " +cRet) cOriginal = SomeFunc( _cClientIP, _cClientHostName, _cServerEnv ) Local cStatus := "NOT VALID" Local lResult := .F. Local cValidIP := "<client_ip>" Local cValidHostName := "<client_host_name>" Local cValidServerEnv := "<server_environment>" If _cClientIP == cValidIP ; .And. _cClientHostName == cValidHostName ; .And. _cServerEnv == cValidServerEnv // cliente pode executar tarefas via RPC neste servidor cStatus := "VALID" lResult := .T. Else // cliente não pode executar tarefas via RPC neste servidor cStatus := "NOT VALID" lResult := .F. Endif ConOut( "[INFO] Client is [" + cStatus ; + "] for RPC tasks - client IP [" + _cClientIP ; + "] - client host name [" + _cClientHostName ; + "] - server env [" + _cServerEnv ; + "]." ) Return lResult |
Exemplo de Testes da Função de Validação (Lado do Cliente)
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
#include "TOTVS.CH" // --------------------------------------------------------------------------- // // LADO DO CLIENTE // // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Teste da função de validação em um ambiente no qual não foi compilada // --------------------------------------------------------------------------- User Function RpcConn2() Return U_RpcConn( "OutroEnv" ) // --------------------------------------------------------------------------- // Teste da função de validação de múltiplas chamadas na mesma conexão // --------------------------------------------------------------------------- User Function RpcConn3() Return U_RpcConn( "EnvTopPorSQL", 3 ) // --------------------------------------------------------------------------- // Teste da função de validação // --------------------------------------------------------------------------- User Function RpcConn( cEnv, nNumExc ) Local nCount Default cEnv := "EnvTopPorSQL" // ambiente padrão Default nNumExc := 1 // apenas uma chamada por conexão cServer := "<ip_servidor>" // servidor RPC cPort := <porta_servidor> oRpcSrv := TRpc():New( cEnv ) If ( oRpcSrv:Connect( cServer, cPort ) ) ConOut( 'BEGIN...' ) For nCount := 1 To nNumExc If nCount > 0 Sleep( 1000 ) Endif cTime := oRpcSrv:CallProc('Time') cResult := Str( nCount ) + " - Time(): [" + cTime + "]" ConOut( cResult ) Next ConOut( 'END.' ) oRpcSrv:Disconnect() Else UserException('RPC connection attempt failed...') Endif rc4crypt(cRet, "123456789", .F.) conout("String original = " + cOriginal) Return User Function input_ascii_test() local cRet local cOriginal // resultado ASCII em hex: "55AB394524" cRet = rc4crypt( "abcde" ,"123456789", .T.) conout("Criptografado em ascii = " + cRet) cOriginal = rc4crypt(cRet, "123456789", .F., .T.) conout("String original = " + cOriginal) Return |
Resultado da Função de Validação
...
Caso mal sucedida, a função de validação retorna falso (.F.), o cliente RPC é considerado como não-válido e a mensagem de erro "Invalid RPC Client..." é retornada ao cliente e logada.
...
Caso bem sucedida, a função de validação somente será executada novamente após o período de 300 segundos (5 minutos), independente do resultado da validação do cliente RPC.
...
Caso não-valido, o cliente RPC não estará habilitado a executar chamadas RPC e a função de validação RPC será executada novamente na próxima requisição RPC do cliente após o período de latência.