Commit 47263bda authored by Renato Figueiro Maia's avatar Renato Figueiro Maia

[OPENBUS-2638] [Lua] Inclusão de suporte a serialização de dados para...

[OPENBUS-2638] [Lua] Inclusão de suporte a serialização de dados para autenticação compartilhada em formato interoperável.

git-svn-id: https://subversion.tecgraf.puc-rio.br/engdist/openbus/sdk/lua/branches/02_00_01@158082 ae0415b3-e90b-0410-900d-d0be9363c56b
parent 3ebdb6a5
local except = require "openbus.util.except"
local log = require "openbus.util.logger"
local openbus = require "openbus"
......@@ -20,17 +21,12 @@ local OpenBusContext = orb.OpenBusContext
local conn = OpenBusContext:createConnection(bushost, busport)
OpenBusContext:setDefaultConnection(conn)
-- load interface definition
orb:loadidlfile("idl/sharedauth/encoding.idl")
local idltype = orb.types:lookup("tecgraf::openbus::interop::sharedauth::EncodedSharedAuth")
-- read shared authentication data
log:TEST("retrieve shared authentication data")
local sharedauth = orb:newdecoder(waitfile("sharedauth.dat")):get(idltype)
attempt, secret = orb:narrow(sharedauth.attempt), sharedauth.secret
local secret = OpenBusContext:decodeSharedAuth(waitfile("sharedauth.dat"))
-- login to the bus
conn:loginBySharedAuth(attempt, secret)
conn:loginBySharedAuth(secret)
-- define service properties
local props = {{name="openbus.component.interface",value=iface.repID}}
......
......@@ -49,16 +49,9 @@ OfferRegistry:registerService(component.IComponent, properties)
log:TEST("hello service ready!")
-- generate shared authentication data
local attempt, secret = conn:startSharedAuth()
-- load interface definition
orb:loadidlfile("idl/sharedauth/encoding.idl")
local idltype = orb.types:lookup("tecgraf::openbus::interop::sharedauth::EncodedSharedAuth")
-- serialize shared authentication data
local encoder = orb:newencoder()
encoder:put({attempt=attempt,secret=secret}, idltype)
assert(oil.writeto("sharedauth.dat", encoder:getdata(), "wb"))
local secret = conn:startSharedAuth()
local encoded = OpenBusContext:encodeSharedAuth(secret)
assert(oil.writeto("sharedauth.dat", encoded, "wb"))
log:TEST("shared authentication data written to file!")
......@@ -17,9 +17,9 @@ local running = coroutine.running
local newthread = coroutine.create
local string = require "string"
local findstr = string.find
local findstring = string.find
local repeatstr = string.rep
local substr = string.sub
local substring = string.sub
local math = require "math"
local inf = math.huge
......@@ -64,7 +64,8 @@ local AlreadyLoggedIn = libthrow.AlreadyLoggedIn
local InvalidBusAddress = libthrow.InvalidBusAddress
local InvalidLoginProcess = libthrow.InvalidLoginProcess
local InvalidPropertyValue = libthrow.InvalidPropertyValue
local InvalidChainStream = throw.InvalidChainStream
local InvalidEncodedStream = libthrow.InvalidEncodedStream
local WrongBus = libthrow.WrongBus
local coreidl = require "openbus.core.idl"
local coreconst = coreidl.const
local BusLogin = coreconst.BusLogin
......@@ -94,8 +95,6 @@ local InvalidLogins = loginthrow.InvalidLogins
local ServiceFailure = coresrvthrow.ServiceFailure
local exportconst = coreidl.const.data_export
local ExportVersion = exportconst.CurrentVersion
local MagicTag_CallChain = exportconst.MagicTag_CallChain
local MagicTag_SharedAuth = exportconst.MagicTag_SharedAuth
local exporttypes = coreidl.types.data_export
local ExportedVersionSeqRepId = exporttypes.ExportedVersionSeq
local ExportedCallChainRepId = exporttypes.ExportedCallChain
......@@ -279,8 +278,7 @@ local function encryptLogin(self, buskey, pubkey, data)
return buskey:encrypt(encoder:getdata())
end
local function localLogin(self, AccessControl, buskey, login, lease)
local busid = AccessControl:_get_busid()
local function localLogin(self, AccessControl, busid, buskey, login, lease)
local LoginRegistry = getCoreFacet(self, "LoginRegistry", LoginRegistryRepId)
if self.login ~= nil then AlreadyLoggedIn() end
self.invalidLogin = nil
......@@ -369,6 +367,19 @@ end
local SharedAuthSecret = class()
function SharedAuthSecret:__init()
self.busid = self.bus
end
function SharedAuthSecret:cancel()
local attempt = self.attempt
return pcall(attempt.cancel, attempt)
end
local Connection = class({}, BaseInterceptor)
function Connection:__init()
......@@ -510,7 +521,8 @@ function Connection:loginByPassword(entity, password)
AccessDenied{message=msg.UnableToEncryptPassword:tag{message=errmsg}}
end
local login, lease = AccessControl:loginByPassword(entity, pubkey, encrypted)
localLogin(self, AccessControl, buskey, login, lease)
local busid = AccessControl:_get_busid()
localLogin(self, AccessControl, busid, buskey, login, lease)
log:request(msg.LoginByPassword:tag{
login = login.id,
entity = login.entity,
......@@ -539,7 +551,8 @@ function Connection:loginByCertificate(entity, privatekey)
end
error(login)
end
localLogin(self, AccessControl, buskey, login, lease)
local busid = AccessControl:_get_busid()
localLogin(self, AccessControl, busid, buskey, login, lease)
log:request(msg.LoginByCertificate:tag{
login = login.id,
entity = login.entity,
......@@ -561,16 +574,20 @@ function Connection:startSharedAuth()
pcall(attempt.cancel, attempt)
ServiceFailure{message=msg.UnableToDecryptChallenge:tag{message=errmsg}}
end
return attempt, secret
end
function Connection:cancelSharedAuth(attempt)
return pcall(attempt.cancel, attempt)
return SharedAuthSecret{
bus = self.busid,
attempt = attempt,
secret = secret,
}
end
function Connection:loginBySharedAuth(attempt, secret)
function Connection:loginBySharedAuth(sharedauth)
if self.login ~= nil then AlreadyLoggedIn() end
local AccessControl, buskey = intiateLogin(self)
local busid = AccessControl:_get_busid()
if busid ~= sharedauth.bus then WrongBus() end
local attempt = sharedauth.attempt
local secret = sharedauth.secret
local pubkey = self.prvkey:encode("public")
local encrypted, errmsg = encryptLogin(self, buskey, pubkey, secret)
if encrypted == nil then
......@@ -584,7 +601,7 @@ function Connection:loginBySharedAuth(attempt, secret)
end
error(login)
end
localLogin(self, AccessControl, buskey, login, lease)
localLogin(self, AccessControl, busid, buskey, login, lease)
log:request(msg.LoginBySharedAuth:tag{
login = login.id,
entity = login.entity,
......@@ -789,7 +806,7 @@ end
function Context:makeChainFor(loginId)
local conn = self:getCurrentConnection()
if conn == nil or conn.login == nil then
sysexthrow.NO_PERMISSION{
NO_PERMISSION{
completed = "COMPLETED_NO",
minor = NoLoginCode,
}
......@@ -798,63 +815,95 @@ function Context:makeChainFor(loginId)
return unmarshalSignedChain(self, signed, conn.busid)
end
function Context:encodeChain(chain)
local types = self.types
local orb = self.orb
local encoder = orb:newencoder()
local result, errmsg = pcall(encoder.put, encoder, {
bus = chain.busid,
signedChain = chain,
}, types.ExportedCallChain)
if result then
local encoded = encoder:getdata()
encoder = orb:newencoder()
result, errmsg = pcall(encoder.put, encoder, {{
version = ExportVersion,
encoded = encoded,
}}, types.ExportedVersionSeq)
local EncodingValues = {
Chain = {
magictag = exportconst.MagicTag_CallChain,
typename = "ExportedCallChain",
pack = function (self, chain)
return {
bus = chain.busid,
signedChain = chain,
}
end,
unpack = function (self, decoded)
return unmarshalSignedChain(self, decoded.signedChain, decoded.bus)
end,
},
SharedAuth = {
magictag = exportconst.MagicTag_SharedAuth,
typename = "ExportedSharedAuth",
unpack = function (self, decoded)
return SharedAuthSecret(decoded)
end,
},
}
for name, info in pairs(EncodingValues) do
Context["encode"..name] = function (self, value)
local types = self.types
local orb = self.orb
local encoder = orb:newencoder()
local packvalue = info.pack
if packvalue ~= nil then
value = packvalue(self, value)
end
local result, errmsg = pcall(encoder.put, encoder, value, types[info.typename])
if result then
return MagicTag_CallChain..encoder:getdata()
local encoded = encoder:getdata()
encoder = orb:newencoder()
result, errmsg = pcall(encoder.put, encoder, {{
version = ExportVersion,
encoded = encoded,
}}, types.ExportedVersionSeq)
if result then
return info.magictag..encoder:getdata()
end
end
error(msg.UnableToEncodeChain:tag{ errmsg = errmsg })
end
error(msg.UnableToEncodeChain:tag{ errmsg = errmsg })
end
function Context:decodeChain(stream)
if findstr(stream, MagicTag_CallChain, 1, "no regex") then
local types = self.types
local orb = self.orb
local decoder = orb:newdecoder(substr(stream, 1+#MagicTag_CallChain))
local ok, result = pcall(decoder.get, decoder, types.ExportedVersionSeq)
if ok then
local exports = result
result = msg.NoSupportedVersionFound
for _, exported in ipairs(exports) do
if exported.version == ExportVersion then
decoder = orb:newdecoder(exported.encoded)
ok, result = pcall(decoder.get, decoder, types.ExportedCallChain)
if ok then
return unmarshalSignedChain(self, result.signedChain, result.bus)
Context["decode"..name] = function (self, stream)
local magictag = info.magictag
if findstring(stream, magictag, 1, "no regex") == 1 then
local types = self.types
local orb = self.orb
local decoder = orb:newdecoder(substring(stream, 1+#magictag))
local ok, result = pcall(decoder.get, decoder, types.ExportedVersionSeq)
if ok then
local exports = result
result = msg.NoSupportedVersionFound
for _, exported in ipairs(exports) do
if exported.version == ExportVersion then
decoder = orb:newdecoder(exported.encoded)
ok, result = pcall(decoder.get, decoder, types[info.typename])
if ok then
local unpackvalue = info.unpack
if unpackvalue ~= nil then
result = unpackvalue(self, result)
end
return result
end
break
end
break
end
end
InvalidEncodedStream{ message = result }
end
InvalidChainStream{ message = result }
InvalidEncodedStream{ message = msg.MagicTagNotFound }
end
InvalidChainStream{ message = msg.MagicTagNotFound }
end
-- allow login operations to be performed without credentials
do
local IgnoredMethods = {
[SharedAuthSecret] = {
"cancel",
},
[Connection] = {
"loginByPassword",
"loginByCertificate",
"loginBySharedAuth",
"cancelSharedAuth",
},
[Context] = {
"createConnection",
......@@ -921,12 +970,14 @@ end
-- insert function argument typing
local argcheck = require "openbus.util.argcheck"
argcheck.convertclass(SharedAuthSecret, {
cancel = {},
})
argcheck.convertclass(Connection, {
loginByPassword = { "string", "string" },
loginByCertificate = { "string", "userdata" },
startSharedAuth = {},
cancelSharedAuth = { "table" },
loginBySharedAuth = { "table", "string" },
loginBySharedAuth = { "table" },
logout = {},
})
local ContextOperations = {
......@@ -944,6 +995,8 @@ local ContextOperations = {
makeChainFor = { "string" },
encodeChain = { "table" },
decodeChain = { "string" },
encodeSharedAuth = { "table" },
decodeSharedAuth = { "string" },
}
argcheck.convertclass(Context, ContextOperations)
argcheck.convertmodule(openbus, {
......
......@@ -363,12 +363,9 @@ do
self.loginargs = callback
localLogin(self)
end
end
for _, name in ipairs{"startSharedAuth", "cancelSharedAuth"} do
Assistant[name] = function (self, ...)
local conn = self.connection
return conn[name](conn, ...)
function Assistant:startSharedAuth(...)
return self.connection:startSharedAuth(...)
end
end
......@@ -497,7 +494,6 @@ argcheck.convertclass(Assistant, {
loginByCertificate = { "string", "userdata" },
loginByCallback = { "function" },
startSharedAuth = {},
cancelSharedAuth = { "table" },
logout = {},
getAllServices = {},
findServices = { "table" },
......
......@@ -95,7 +95,7 @@ do log:TEST("Decode malformed chain")
for _, malformed in ipairs(malformedstreams) do
local ok, ex = pcall(OpenBusContext.decodeChain, OpenBusContext, malformed)
assert(not ok)
assert(ex._repid == libidl.types.InvalidChainStream)
assert(ex._repid == libidl.types.InvalidEncodedStream)
assert(ex.message ~= nil)
end
end
......
......@@ -32,6 +32,8 @@ local orb = openbus.initORB()
local OpenBusContext = orb.OpenBusContext
assert(OpenBusContext.orb == orb)
local conns = {}
local busid
local otherBusConn
local function catcherr(...)
local ok, err = pcall(...)
......@@ -54,16 +56,20 @@ local loginways = {
loginByPassword = function() return user, password end,
loginByCertificate = function() return system, syskey end,
loginBySharedAuth = function()
return { -- dummy login process object
login = function()
return {
id = "60D57646-33A4-4108-88DD-AE9B7A9E3C7A",
entity = system,
}, 1
end,
return {
busid = busid,
attempt = { -- dummy login process object
login = function()
return {
id = "60D57646-33A4-4108-88DD-AE9B7A9E3C7A",
entity = system,
}, 1
end,
cancel = function () end,
},
secret = "fake secret",
cancel = function () end,
},
"fake secret"
}
end,
}
local function assertlogged(conn)
......@@ -85,7 +91,7 @@ local function assertlogged(conn)
assert(conn.busid == busid)
end
-- check the failure of 'startSharedAuth'
conn:cancelSharedAuth(conn:startSharedAuth())
assert(conn:startSharedAuth():cancel() == true)
-- check the login is valid to perform calls
local OfferRegistry = callwithin(conn, OpenBusContext.getOfferRegistry, OpenBusContext)
assert(OfferRegistry ~= nil)
......@@ -164,6 +170,7 @@ do log:TEST "connect to bus"
for i = 1, 2 do
conns[i] = assertlogoff(OpenBusContext:createConnection(bushost, busport))
end
otherBusConn = OpenBusContext:createConnection(bus2host, bus2port)
end
-- create a valid key to be used as a wrong key in the tests below.
......@@ -177,6 +184,7 @@ local invalidate, shutdown, leasetime do
local conn = OpenBusContext:createConnection(bushost, busport)
conn:loginByPassword(admin, admpsw)
OpenBusContext:setDefaultConnection(conn)
busid = conn.busid
leasetime = conn.AccessControl:renew()
function invalidate(loginId)
OpenBusContext:getLoginRegistry():invalidateLogin(loginId)
......@@ -282,27 +290,37 @@ for _, connOp in ipairs({"DefaultConnection", "CurrentConnection"}) do
do log:TEST "login with wrong secret"
local attempt = conn:startSharedAuth()
local ex = catcherr(other.loginBySharedAuth, other, attempt, "WrongSecret")
attempt.secret = "WrongSecret" -- this is not allowed by the API
local ex = catcherr(other.loginBySharedAuth, other, attempt)
assert(ex._repid == idl.types.services.access_control.AccessDenied)
assertlogoff(other)
assertlogged(conn)
end
do log:TEST "login with canceled attempt"
local attempt, secret = conn:startSharedAuth()
conn:cancelSharedAuth(attempt)
local ex = catcherr(other.loginBySharedAuth, other, attempt, secret)
local attempt = conn:startSharedAuth()
attempt:cancel()
local ex = catcherr(other.loginBySharedAuth, other, attempt)
assert(ex._repid == libidl.types.InvalidLoginProcess)
assertlogoff(other)
assertlogged(conn)
end
do log:TEST "login with expired attempt"
local attempt, secret = conn:startSharedAuth()
local attempt = conn:startSharedAuth()
sleep(2*leasetime)
local ex = catcherr(other.loginBySharedAuth, other, attempt, secret)
local ex = catcherr(other.loginBySharedAuth, other, attempt)
assert(ex._repid == libidl.types.InvalidLoginProcess)
assertlogoff(other)
assertlogged(conn)
end
do log:TEST "login with wrong bus"
otherBusConn:loginByPassword(user, password)
local attempt = otherBusConn:startSharedAuth()
assert(otherBusConn:logout() == true)
local ex = catcherr(other.loginBySharedAuth, other, attempt)
assert(ex._repid == libidl.types.WrongBus)
assertlogoff(other)
assertlogged(conn)
end
do
testlogin(other, "loginBySharedAuth", function()
return conn:startSharedAuth()
......
......@@ -46,16 +46,20 @@ local loginways = {
loginByCertificate = function() return system, syskey end,
loginByCallback = function()
return function ()
return "SharedAuth", { -- dummy login process object
login = function()
return {
id = "60D57646-33A4-4108-88DD-AE9B7A9E3C7A",
entity = system,
}, 1
end,
return "SharedAuth", {
busid = busid,
attempt = { -- dummy login process object
login = function()
return {
id = "60D57646-33A4-4108-88DD-AE9B7A9E3C7A",
entity = system,
}, 1
end,
cancel = function () end,
},
secret = "fake secret",
cancel = function () end,
},
"fake secret"
}
end
end,
}
......@@ -78,7 +82,7 @@ local function assertlogged(conn)
assert(conn.busid == busid)
end
-- check the success of 'startSharedAuth'
conn:cancelSharedAuth(conn:startSharedAuth())
conn:startSharedAuth():cancel()
-- check the login is valid to perform calls
assert(type(conn:getAllServices()) == "table")
return conn
......@@ -264,28 +268,29 @@ for _, connOp in ipairs({"DefaultConnection", "CurrentConnection"}) do
do log:TEST "login with wrong secret"
local attempt = conn:startSharedAuth()
attempt.secret = "WrongSecret" -- this is not allowed by the API
local ex = catcherr(other.loginByCallback, other, function ()
return "SharedAuth", attempt, "WrongSecret"
return "SharedAuth", attempt
end)
assert(ex._repid == idl.types.services.access_control.AccessDenied)
assertlogoff(other)
assertlogged(conn)
end
do log:TEST "login with canceled attempt"
local attempt, secret = conn:startSharedAuth()
conn:cancelSharedAuth(attempt)
local attempt = conn:startSharedAuth()
attempt:cancel()
local ex = catcherr(other.loginByCallback, other, function ()
return "SharedAuth", attempt, secret
return "SharedAuth", attempt
end)
assert(ex._repid == libidl.types.InvalidLoginProcess)
assertlogoff(other)
assertlogged(conn)
end
do log:TEST "login with expired attempt"
local attempt, secret = conn:startSharedAuth()
local attempt = conn:startSharedAuth()
sleep(2*leasetime)
local ex = catcherr(other.loginByCallback, other, function ()
return "SharedAuth", attempt, secret
return "SharedAuth", attempt
end)
assert(ex._repid == libidl.types.InvalidLoginProcess)
assertlogoff(other)
......
......@@ -28,7 +28,7 @@ setuplog(log, get("openbus.log.level" , 0),
get("openbus.log.file" , ""))
log:flag("TEST", get("openbus.test.verbose", "no"):lower() == "yes")
leasetime = get("login.lease.time" , 1)
expirationgap = get("login.expiration.gap", leasetime/2)
expirationgap = get("login.expiration.gap", 2)
bushost = get("bus.host.name" , "localhost")
busport = get("bus.host.port" , 2089)
bus2host = get("bus2.host.name" , bushost)
......
Markdown is supported
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