Commit c3daccbb authored by Renato Figueiro Maia's avatar Renato Figueiro Maia
Browse files

[OPENBUS-2304] (Lua) Permitir fazer chamadas dentro de cadeias (join)...

[OPENBUS-2304] (Lua) Permitir fazer chamadas dentro de cadeias (join) recebidas com um login diferente, mas da mesma entidade
- Campo 'CallChain.target' passa a conter o 'EntityName' ao invés do 'LoginId'.
- A operação 'AccessControl:signChainFor(target)' passa a receber o 'EntityName'
  ao invés do 'LoginId', mas continua sem validar o valor do parâmetro 'target',
  simplesmente colocando o valor no campo 'CallChain.target' da cadeia gerada.
  Isso é necessário pra permitir assinar cadeias pra entidades deslogadas, que
  é importante pra permitir que um processo possa receber chamadas de entidades
  conhecidas (autenticadas previamente) mesmo sem ter acesso ao ACS. 
- Campo 'CredentialReset.login' passar a conter o 'EntityName' ao invés do
  'LoginId'. Esse campo também é renomeado pra 'CredentialReset.target' pra
  melhor clareza.
  - As sessões de saída não podem mais ter indexadas pelo 'LoginId' do destino
    (target), exatamente porque tal informação não vem mais no
    'CredentialReset'. Também não é razoável indexá-las pelo 'EntityName' pois
    potencialmente há multiplas instâncias da biblioteca de acesso (OpenBusLib)
    mantendo diferentes sessões com o mesmo 'EntityName' (assumiamos que o mesmo
    não acontecia com 'LoginId'), portanto quando uma instância da biblioteca
    conversasse com duas outras instâncias que usem o mesmo 'EntityName' a
    sessão de uma sobreporia a da outra concorrentemente degradando o desempenho
    podendo inclusive levar a uma situação de starvation em casos extremos.
    - A solução adotada foi indexar as sessões diretamente pelo
      'IOR.profile_data' do objeto sendo acessado. Antes fazíamos essa indexação
      de forma indireta através de dois mapas: um que mapeava 'IOR.profile_data'
      pra 'LoginId' e outro de 'LoginId' pra sessão. O intuito disso era
      diminuir o número de sessões a serem mantidas no cache.
- A forma de identificar se uma chamada está sendo feita a um objeto residente
  no núcleo do barramento (core) é feito comparando o 'CredentialReset.target'
  com o 'BusEntity' (nome da entidade que representa o núcleo do barramento).
	- Com isso, não é mais necessário padronizar o 'BusLogin' (login ID utilizado
		pelo núcleo do barramento). Inclusive o login ID utilizado pode ser o mesmo
    bus ID utilizado para diferenciar duas instâncias do barramento OpenBus.

git-svn-id: https://subversion.tecgraf.puc-rio.br/engdist/openbus/core/branches/02_00_00@142237 ae0415b3-e90b-0410-900d-d0be9363c56b
parent 1015e49d
......@@ -317,7 +317,7 @@ Os dados do \term{service context} consitem da seguinte estrutura deve codificad
// File: credential.idl
// Name: tecgraf::openbus::core::v2_0::credential::CredentialReset
struct CredentialReset {
Identifier login; // callee UUID
Identifier target; // callee entity
unsigned long session; // session ID
EncryptedBlock challenge; // encrypted 16-byte random value (the secret)
};
......@@ -376,15 +376,15 @@ struct SignedCallChain {
// File: access_control.idl
// Name: tecgraf::openbus::core::v2_0::services::access:control::CallChain
struct CallChain {
Identifier target; // Identificador do login a quem a cadeia se destina.
Identifier target; // Node da entidade a quem a cadeia se destina.
LoginInfoSeq originators; // Informações de login das entidades que realizaram as chamadas em cadeia que originam essa chamada.
LoginInfo caller; // Informações de login da entidades que efetivamente fez chamada atual (última da cadeia).
};
\end{samplecode}
\item[Campo \code{target}] contém o identificador do login a quem a cadeia está destinada.
Ou seja, esse campo contém o mesmo identificador fornecido pelo campo \code{login} da estrutura \code{CredentialReset} descrito na seção \ref{sub:validacao_da_personalidade} que informa o login do objeto ao qual a chamada se destina.
Esse campo \code{target} da cadeia garante que a cadeia só possa ser utilizada (fazer novas chamadas dentro daquela cadeia) por quem detiver o login ao qual ela foi enviada.
\item[Campo \code{target}] contém o nome da entidade a quem a cadeia está destinada.
Ou seja, esse campo contém o mesmo identificador fornecido pelo campo \code{target} da estrutura \code{CredentialReset} descrito na seção \ref{sub:validacao_da_personalidade} que informa o login do objeto ao qual a chamada se destina.
Esse campo \code{target} da cadeia garante que a cadeia só possa ser utilizada (fazer novas chamadas dentro daquela cadeia) por quem estiver logado como a mesma entidade ao quem ela foi enviada.
\item[Campo \code{originators}] contém uma sequência de informações sobre os vários logins que realizaram as chamadas em cadeia que originam essa chamada.
......@@ -399,7 +399,7 @@ Para que a cadeia de chamada seja v
\begin{itemize}
\item O campo \code{SignedCallChain::signature} deve conter uma assinatura válida do campo \code{SignedCallChain::encoded} a ser autenticada com a chave pública do barramento.
\item O campo \code{CallChain::target} deve ser o login de quem recebe a chamada.
\item O campo \code{CallChain::target} deve ser o nome da entidade de quem recebe a chamada.
\item O campo \code{CallChain::caller} deve indicar as informações do login de quem iniciou a chamada.
\end{itemize}
......@@ -419,7 +419,7 @@ const unsigned long InvalidChainCode;
Muitas chamadas para operações das facetas fornecidas pelo barramento são feitas usando credenciais de chamada como especificadas neste documento.
Contudo, as cadeias de chamada enviadas nas credenciais em chamadas ao barramento são diferente das cadeias enviadas em outras chamadas.
A identificação de que o objeto CORBA sendo chamado reside no barramento é feita comparando o campo \code{CredentialReset::login} com o identificador do barramento, que é obtido através do atributo \code{busid} da \term{Faceta de Controle de Acesso} do barramento.
A identificação de que o objeto CORBA sendo chamado reside no barramento é feita comparando o campo \code{CredentialReset::target} com o identificador do barramento, que é obtido através do atributo \code{busid} da \term{Faceta de Controle de Acesso} do barramento.
Nas chamadas para o barramento, que são feitas fora de qualquer cadeia de chamada obtida previamente pelo iniciador da chamada, a cadeia a ser enviada na credencial é uma cadeia nula, que consiste da estrutura \code{SignedCallChain} em que o campo \code{signed} é uma sequência de zeros e o campo \code{encoded} é uma sequência vazia.
......@@ -439,7 +439,7 @@ Ou seja,
Nesse sentido, para gerar uma cadeia nova que não seja uma extensão de outra cadeia previamente recebida, é necessário enviar uma cadeia nula na credencial da chamada de \code{signChainFor}, o que está em conformidade com a regra para geração de cadeias para o barramento, uma vez que a operação \code{signChainFor} é do barramento.
Como resultado da operação \code{signChainFor} é devolvida uma nova cadeia em que o campo \code{CallChain::caller} da cadeia original será adicionado à sequência do campo \code{CallChain::originators} e o campo \code{CallChain::caller} conterá informações do login de quem chamou a operação \code{signChainFor}.
Adicionalmente, o campo \code{CallChain::target} conterá o identificador de login fornecido pelo parâmetro \code{target} da chamada de \code{signChainFor}.
Adicionalmente, o campo \code{CallChain::target} conterá o nome da entidade fornecido pelo parâmetro \code{target} da chamada de \code{signChainFor}.
Note que dessa forma é possível se adicionar a cadeias recebidas (processo denominado \term{join}), assim como gerar tais cadeias para quaisquer destinos para o qual seja necessário enviar credenciais.
......
......@@ -48,7 +48,7 @@ local PredefinedUserSets = {
local function getLoginInfoFor(self, loginId)
return self.LoginRegistry:getLoginEntry(loginId)
or { id = loginId, entity = "<unknown>" }
or {id=loginId,entity="<unknown>"}
end
......@@ -58,12 +58,12 @@ local BusInterceptor = class({}, Context, Interceptor)
function BusInterceptor:__init()
self.context = self
self.signedChainOf = memoize(function(chain) -- [chain] = SignedChainCache
return LRUCache{ -- [remoteid] = signedChain
retrieve = function(remoteid)
return LRUCache{ -- [target] = signedChain
retrieve = function(target)
local originators = { unpack(chain.originators) }
originators[#originators+1] = chain.caller
return self.AccessControl:encodeChain{
target = remoteid,
target = target,
originators = originators,
caller = self.login,
}
......@@ -117,21 +117,26 @@ function BusInterceptor:unmarshalCredential(...)
signature = false,
originators = {},
caller = getLoginInfoFor(self, credential.login),
target = self.login.id,
target = self.login.entity,
}
credential.chain = chain
elseif chain.signature ~= nil then -- joined non-legacy call
local originators = chain.originators
originators[#originators+1] = chain.caller -- add last originator
chain.caller = getLoginInfoFor(self, chain.target)
chain.target = self.login.id
local caller = getLoginInfoFor(self, credential.login)
chain.caller = caller
local target = chain.target
if target ~= caller.entity then
chain.caller = {id="<unknown>",entity=target}
end
chain.target = self.login.entity
end
end
return credential
end
function BusInterceptor:signChainFor(remoteid, chain)
return self.signedChainOf[chain]:get(remoteid)
function BusInterceptor:signChainFor(target, chain)
return self.signedChainOf[chain]:get(target)
end
function BusInterceptor:receiverequest(request)
......
......@@ -172,7 +172,7 @@ end
local LoginRegistry -- forward declaration
local AccessControl = {
login = {id=idl.const.BusLogin, entity=idl.const.BusEntity},
login = {id=nil, entity=idl.const.BusEntity},
pendingChallenges = {}
}
......@@ -199,6 +199,7 @@ function AccessControl:__init(data)
-- initialize access
self.busid = busid
self.login.id = busid
local access = self.access
local encodedkey = assert(access.prvkey:encode("public"))
self.buskey = encodedkey
......
......@@ -15,7 +15,6 @@ local decodeprvkey = pubkey.decodeprivate
local idl = require "openbus.core.idl"
local loadIDL = idl.loadto
local BusLogin = idl.const.BusLogin
local EncryptedBlockSize = idl.const.EncryptedBlockSize
local CredentialContextId = idl.const.credential.CredentialContextId
local loginconst = idl.const.services.access_control
......@@ -209,18 +208,18 @@ end
-- chain signature -------------------------------------------------------------
do -- sign chain for an invalid login
do -- sign chain for an invalid entity
validlogin.busSession:newCred("signChainFor")
signed = ac:signChainFor(logoutid)
signed = ac:signChainFor("invalid")
local chain = decodeChain(bus.key, signed)
assert(chain.target == logoutid)
assert(chain.target == "invalid")
assert(chain.caller.id == validlogin.id)
assert(chain.caller.entity == user)
end
do -- join chain targeted for other login (an invalid one)
do -- join chain targeted for other entity (an invalid one)
validlogin.busSession:newCred("signChainFor", signed)
local ok, ex = pcall(ac.signChainFor, ac, logoutid)
local ok, ex = pcall(ac.signChainFor, ac, "invalid")
assert(ok == false)
assert(ex._repid == "IDL:omg.org/CORBA/NO_PERMISSION:1.0")
assert(ex.completed == "COMPLETED_NO")
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment