我正在尝试从awesome-wm会话的密钥环获取密码(通过lgi库使用DBus)。
我能够找到钥匙圈输入路径,打开通信会话并解锁输入。
然后,我调用GetSecrets
方法并将结果存储到secret
变量中。
根据文档,它应该是struct Secret。似乎lgi
无法处理此类型,而将其作为userdata
类型传递(至少我无法使它能够访问结构字段)。是否有一种无需编写自定义C处理程序即可获取struct Secret
value
字段内容的方法?
代码如下:
local bus = Gio.bus_get_sync(Gio.BusType.SESSION, nil)
local attr = {}
attr[1] = {attribute = "value"} -- attribute-value pair to search for
-- search for secret path
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "SearchItems"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(a{ss})", attr))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local location
for _, l in result:get_body():pairs() do
if #l > 0 then location = l[1] end
end
print(location) -- returns "/org/freedesktop/secrets/collection/Default/1"
-- open session
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "OpenSession"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(sv)", {"plain", GLib.Variant("s", "")}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local session = result:get_body()[2]
print(session) -- returns "/org/freedesktop/secrets/session/s4"
-- unlock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Unlock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- at this point key property "Locked" if false. tested using d-feet
-- get secret
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "GetSecrets"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(aoo)", {{location},session}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
local secret = result:get_body()
print(#secret) -- returns "1"
print(secret) -- returns table address
print(type(secret)) -- returns "userdata"
-- lock key
local name = "org.freedesktop.secrets"
local object = "/org/freedesktop/secrets"
local interface = "org.freedesktop.Secret.Service"
local method = "Lock"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
message:set_body(GLib.Variant("(ao)", {{location}}))
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
-- close session
local name = "org.freedesktop.secrets"
local object = location
local interface = "org.freedesktop.Secret.Session"
local method = "Close"
local message = Gio.DBusMessage.new_method_call(name, object, interface, method)
local result, err = bus:send_message_with_reply_sync(message, Gio.DBusSendMessageFlags.NONE,
-1, nil)
当我执行print(secret)
时,将返回lgi.rec 0x7f57d0014960:GLib.Variant
。
因此,secret
是一个对象。如何从value
对象中检索GLib.Variant
字段?
secret:get_data_as_bytes():get_data()
以字节数组形式转储结构; secret:print()
返回格式化的struct字符串。我想知道是否有更好的方法。
secret
变量的类型是(a{o(oayays)})
重新创建该类型对象的代码:
local lgi = require 'lgi'
local Gio = lgi.require 'Gio'
local GLib = lgi.require 'GLib'
local var = GLib.Variant("(a{o(oayays)})", {{["/path/to/object"]={"/path/to/session","parameters","value","content_type"}}})
答案 0 :(得分:1)
(请注意,我没有安装此密码管理器,也没有尝试使用任何密码管理器)
上次我问LGI的作者有关此类问题的答案是:
我已提交对Variant的修复,该修复可以恢复此功能。所以 一个使用示例是:
称为_from_C(userdata)的本地函数
本地变体= GLib.Variant(userdata)
打印(变体)
结束
如果您必须支持较旧的(以及已发布的:)lgi版本,则可以 使用未公开的方式:
本地核心=要求'lgi.core'
名为_from_C(userdata)的局部函数
本地变体= core.record.new(GLib.Variant,userdata)
打印(变体)
结束
请注意,还有其他方法。为了解决另一个此类错误,我还创建了一个C Lua插件,并用C编写了该代码。对于Lua [2]而言,这实际上是微不足道的。
如果使用LuaJIT,另一种方法是使用内置的FFI即时将结构定义编译为Lua对象[1]。
最后,如果问题更多地在于LGI正确使用GVariant值后如何解压缩它们,请在此处https://github.com/Elv13/wirefu/blob/master/proxy.lua
查看我的代码[1] http://luajit.org/ext_ffi_api.html
[2] https://github.com/Elv13/lua_async_binding/blob/master/src/luabridge.c#L407
答案 1 :(得分:0)
最后我找到了解决方案。要解压复杂类型的值(例如(a{o(oayays)})
),应使用get_child_value
函数。
secret:get_child_value(0):get_child_value(0):get_child_value(1):get_child_value(2).value
说明:索引元组;索引数组索引字典索引元组