Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

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
indent20px

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
collapsefalse
<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

...

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
languagecpp
themeEclipse
linenumberstrue
collapsefalse
#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
languagecpp
themeEclipse
linenumberstrue
collapsefalse
#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.