Skip to content

Commit dfa287d

Browse files
committed
password store / dbus: put dbus stuff in separate file
1 parent a9962e2 commit dfa287d

File tree

2 files changed

+294
-267
lines changed

2 files changed

+294
-267
lines changed

ext/lib/dbus.js

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
/* Copyright Torbjorn Tyridal 2015
2+
3+
This file is part of Masterpassword for Firefox (herby known as "the software").
4+
5+
The software is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
The software is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with the software. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
/*
20+
*
21+
* Minimal dbus api for accessing Secret Services API (gnome keyring / ksecretservice)
22+
* and Kwallet.
23+
*
24+
**/
25+
26+
var {Cu} = require('chrome');
27+
Cu.import("resource://gre/modules/ctypes.jsm");
28+
29+
30+
function dbus() {
31+
var lib
32+
try { lib = ctypes.open("libdbus-1.so.3"); }
33+
catch(e) { return null; }
34+
35+
const DBusError = ctypes.StructType('DBusError', [
36+
{'name': ctypes.char.ptr},
37+
{'message': ctypes.char.ptr},
38+
{'dummy1': ctypes.int},
39+
{'dummy2': ctypes.int},
40+
{'dummy3': ctypes.int},
41+
{'dummy4': ctypes.int},
42+
{'dummy5': ctypes.int},
43+
{'padding': ctypes.voidptr_t},
44+
]),
45+
DBusConnection = ctypes.StructType('DBusConnection'),
46+
DBusMessage = ctypes.StructType('DBusMessage'),
47+
DBusMessageIter = ctypes.StructType('DBusMessageIter', [
48+
{'dummy1': ctypes.voidptr_t},
49+
{'dummy2': ctypes.voidptr_t},
50+
{'dummy3': ctypes.uint32_t},
51+
{'dummy4': ctypes.int},
52+
{'dummy5': ctypes.int},
53+
{'dummy6': ctypes.int},
54+
{'dummy7': ctypes.int},
55+
{'dummy8': ctypes.int},
56+
{'dummy9': ctypes.int},
57+
{'dummy10': ctypes.int},
58+
{'dummy11': ctypes.int},
59+
{'pad1': ctypes.int},
60+
{'pad2': ctypes.int},
61+
{'pad3': ctypes.voidptr_t}
62+
63+
]);
64+
65+
66+
const bus_get = lib.declare('dbus_bus_get', ctypes.default_abi, DBusConnection.ptr,
67+
ctypes.int, DBusError.ptr),
68+
message_iter_init = lib.declare('dbus_message_iter_init', ctypes.default_abi, ctypes.bool,
69+
DBusMessage.ptr, DBusMessageIter.ptr),
70+
message_iter_get_arg_type = lib.declare('dbus_message_iter_get_arg_type', ctypes.default_abi, ctypes.int,
71+
DBusMessageIter.ptr),
72+
message_iter_get_basic = lib.declare('dbus_message_iter_get_basic', ctypes.default_abi, ctypes.void_t,
73+
DBusMessageIter.ptr, ctypes.voidptr_t),
74+
message_iter_recurse = lib.declare('dbus_message_iter_recurse', ctypes.default_abi, ctypes.void_t,
75+
DBusMessageIter.ptr, DBusMessageIter.ptr),
76+
message_iter_init_append = lib.declare('dbus_message_iter_init_append', ctypes.default_abi, ctypes.void_t,
77+
DBusMessage.ptr, DBusMessageIter.ptr),
78+
message_iter_append_basic = lib.declare('dbus_message_iter_append_basic', ctypes.default_abi, ctypes.bool,
79+
DBusMessageIter.ptr, ctypes.int, ctypes.voidptr_t),
80+
message_iter_next = lib.declare('dbus_message_iter_next', ctypes.default_abi, ctypes.bool,
81+
DBusMessageIter.ptr),
82+
message_iter_open_container = lib.declare('dbus_message_iter_open_container', ctypes.default_abi, ctypes.bool,
83+
DBusMessageIter.ptr, ctypes.int, ctypes.char.ptr, DBusMessageIter.ptr),
84+
message_iter_close_container = lib.declare('dbus_message_iter_close_container', ctypes.default_abi, ctypes.bool,
85+
DBusMessageIter.ptr, DBusMessageIter.ptr),
86+
message_new_method_call = lib.declare('dbus_message_new_method_call', ctypes.default_abi, DBusMessage.ptr,
87+
ctypes.char.ptr, ctypes.char.ptr, ctypes.char.ptr, ctypes.char.ptr ),
88+
connection_send_with_reply_and_block = lib.declare('dbus_connection_send_with_reply_and_block', ctypes.default_abi, DBusMessage.ptr,
89+
DBusConnection.ptr, DBusMessage.ptr, ctypes.int, DBusError.ptr);
90+
91+
const dbus_type = {'string': 's'.charCodeAt(0),
92+
'objectpath': 'o'.charCodeAt(0),
93+
'integer': 'i'.charCodeAt(0),
94+
'bool': 'b'.charCodeAt(0),
95+
'int64': 'x'.charCodeAt(0),
96+
'variant': 'v'.charCodeAt(0),
97+
'array': 'a'.charCodeAt(0),
98+
'byte': 'y'.charCodeAt(0),
99+
'struct': 'r'.charCodeAt(0),
100+
'dict_entry': 'e'.charCodeAt(0),
101+
}
102+
103+
function iter_result(it) {
104+
var typ, data, ret = [];
105+
for (typ = message_iter_get_arg_type(it); typ != 0; message_iter_next(it), typ = message_iter_get_arg_type(it)) {
106+
switch(typ) {
107+
case dbus_type.objectpath:
108+
case dbus_type.string:
109+
data = ctypes.char.ptr();
110+
message_iter_get_basic(it, data.address());
111+
ret.push(data.readString());
112+
break;
113+
case dbus_type.integer:
114+
data = ctypes.int();
115+
message_iter_get_basic(it, data.address());
116+
ret.push(data.value);
117+
break;
118+
case dbus_type.int64:
119+
data = ctypes.int64_t();
120+
message_iter_get_basic(it, data.address());
121+
ret.push(data.value);
122+
break;
123+
case dbus_type.byte:
124+
data = ctypes.uint8_t();
125+
message_iter_get_basic(it, data.address());
126+
ret.push(data.value);
127+
break;
128+
case dbus_type.struct:
129+
case dbus_type.variant:
130+
case dbus_type.array:
131+
data = new DBusMessageIter();
132+
message_iter_recurse(it, data.address());
133+
if (typ==dbus_type.variant)
134+
ret.push( iter_result(data.address())[0] );
135+
else
136+
ret.push( iter_result(data.address()) );
137+
break;
138+
default:
139+
console.warn("iter_result, Unknown data type",typ);
140+
}
141+
}
142+
return ret;
143+
}
144+
145+
var err = new DBusError();
146+
var dbus_con = bus_get(0, err.address());
147+
if (dbus_con.isNull()) {
148+
console.error('Failed to get bus', err.name, err.message);
149+
return null;
150+
}
151+
152+
/// helpers ///
153+
function iter_each(ar, cb) {
154+
for (var key in ar)
155+
if (ar.hasOwnProperty(key))
156+
cb(key, ar[key]);
157+
}
158+
function msg_arg_str(it, s) {
159+
var ss = ctypes.char.array()(s);
160+
var x = ctypes.cast(ss.address(), ctypes.char.ptr);
161+
message_iter_append_basic(it, dbus_type.string, x.address());
162+
}
163+
function msg_arg_objectpath(it, s) {
164+
var ss = ctypes.char.array()(s);
165+
var x = ctypes.cast(ss.address(), ctypes.char.ptr);
166+
message_iter_append_basic(it, dbus_type.objectpath, x.address());
167+
}
168+
function msg_arg_dict(it, typ, then) {
169+
var dic = new DBusMessageIter();
170+
message_iter_open_container(it, dbus_type.array, typ, dic.address());
171+
then(dic.address());
172+
message_iter_close_container(it, dic.address());
173+
}
174+
function msg_arg_dict_entry(dic, key, then) {
175+
var entry = new DBusMessageIter();
176+
message_iter_open_container(dic, dbus_type.dict_entry, null, entry.address());
177+
msg_arg_str(entry.address(), key);
178+
then(entry.address());
179+
message_iter_close_container(dic, entry.address());
180+
}
181+
function msg_arg_variant(it, typ, then) {
182+
var va = new DBusMessageIter();
183+
message_iter_open_container(it, dbus_type.variant, typ, va.address());
184+
then(va.address());
185+
message_iter_close_container(it, va.address());
186+
}
187+
function msg_arg_struct(it, then) {
188+
var va = new DBusMessageIter();
189+
message_iter_open_container(it, dbus_type.struct, null, va.address());
190+
then(va.address());
191+
message_iter_close_container(it, va.address());
192+
}
193+
function msg_arg_bytearray(it, ar) {
194+
var va = new DBusMessageIter();
195+
message_iter_open_container(it, dbus_type.array, 'y', va.address());
196+
for (var x of ar) {
197+
if (x.charCodeAt(0) > 255) throw "Illegal byte array thing.. did you forget to convert to utf-8?";
198+
var x = ctypes.uint8_t(x.charCodeAt(0));
199+
message_iter_append_basic(va.address(), dbus_type.byte, x.address());
200+
}
201+
message_iter_close_container(it, va.address());
202+
}
203+
//compounds
204+
function msg_arg_var_str(it, s) {
205+
msg_arg_variant(it, 's', function(v){ msg_arg_str(v, s);});
206+
}
207+
function msg_arg_dict_strs(it, d) {
208+
msg_arg_dict(it, '{ss}', function(dic) {
209+
iter_each(d, function(key, val) {
210+
msg_arg_dict_entry(dic, key, function(c){ msg_arg_str(c, d[key]); });
211+
});
212+
});
213+
}
214+
215+
const new_method_call = function(dest, path, iface, method) {
216+
var m = message_new_method_call(dest, path, iface, method);
217+
var it = new DBusMessageIter();
218+
message_iter_init_append(m, it.address());
219+
return {
220+
'secret_services_attributes_arg': function(label, attrs) {
221+
msg_arg_dict(it.address(), '{sv}', function(dic) {
222+
msg_arg_dict_entry(dic, 'org.freedesktop.Secret.Item.Label', function(e){ msg_arg_var_str(e, label); });
223+
msg_arg_dict_entry(dic, 'org.freedesktop.Secret.Item.Attributes', function(e) {
224+
msg_arg_variant(e, 'a{ss}', function(v) {
225+
msg_arg_dict_strs(v, attrs);
226+
});
227+
});
228+
});
229+
},
230+
'secret_services_passwd_arg': function(session, session_key, pass, pass_fmt) {
231+
msg_arg_struct(it.address(), function(s) {
232+
msg_arg_objectpath(s, session);
233+
msg_arg_bytearray(s, session_key);
234+
msg_arg_bytearray(s, pass);
235+
msg_arg_str(s, pass_fmt);
236+
});
237+
},
238+
'dict_str_arg': function(s) { msg_arg_dict_strs(it.address(), s); },
239+
'var_string_arg': function(s) { msg_arg_var_str(it.address(), s); },
240+
'string_arg': function(s) { msg_arg_str(it.address(), s); },
241+
'objpath_arg': function(s) { msg_arg_objectpath(it.address(), s); },
242+
'int_arg': function(s) {
243+
var x = ctypes.int(s);
244+
message_iter_append_basic(it.address(), dbus_type.integer, x.address());
245+
},
246+
'int64_arg': function(s) {
247+
var x = ctypes.int64_t(s);
248+
message_iter_append_basic(it.address(), dbus_type.int64, x.address());
249+
},
250+
'bool_arg': function(s) {
251+
var x = ctypes.int({true:1, false:0}[s]);
252+
message_iter_append_basic(it.address(), dbus_type.bool, x.address());
253+
},
254+
'execute': function(timeout) {
255+
if (timeout === undefined) timeout = 1000;
256+
console.log('execute',method,'timeout:',timeout);
257+
var err = new DBusError();
258+
var rep = connection_send_with_reply_and_block(dbus_con, m, timeout, err.address());
259+
if (rep.isNull()) {
260+
throw "method execute, Failed to send message:"+err.name.readString()+"\n"+err.message.readString();
261+
}
262+
it = new DBusMessageIter();
263+
if (message_iter_init(rep, it.address())) {
264+
return iter_result(it.address());
265+
} else
266+
{
267+
return [];
268+
}
269+
}
270+
};
271+
}
272+
273+
const get_property = function(dest, path, iface, prop) {
274+
var m = new_method_call(dest, path, 'org.freedesktop.DBus.Properties', 'Get');
275+
m.string_arg(iface);
276+
m.string_arg(prop);
277+
return m.execute()[0];
278+
}
279+
280+
return {
281+
'get': function (dest) { return {
282+
'load': function(path) { return {
283+
'bind': function(iface) { return {
284+
'method_call': function(m) { return new_method_call(dest, path, iface, m); },
285+
'get_property': function(p) { return get_property(dest, path, iface, p); }
286+
};}
287+
};}
288+
};}
289+
};
290+
}
291+
292+
exports.dbus = dbus;

0 commit comments

Comments
 (0)