11 #include "wvdbusserver.h"
12 #include "wvdbusconn.h"
15 #include "wvtcplistener.h"
16 #include "wvdelayedcallback.h"
17 #undef interface // windows
18 #include <dbus/dbus.h>
24 enum State { NullWait, AuthWait, BeginWait };
31 virtual wvuid_t get_uid() {
return client_uid; }
35 WvDBusServerAuth::WvDBusServerAuth()
38 client_uid = WVUID_INVALID;
44 c.log(
"State=%s\n", state);
45 if (state == NullWait)
48 size_t len = c.
read(buf, 1);
49 if (len == 1 && buf[0] ==
'\0')
55 c.
seterr(
"Client didn't start with NUL byte");
60 const char *line = c.in();
68 if (state == AuthWait)
70 if (!strcasecmp(cmd,
"AUTH"))
74 if (!strcasecmp(typ,
"EXTERNAL"))
81 client_uid = uid.
num();
92 c.out(
"REJECTED EXTERNAL\r\n");
97 c.
seterr(
"AUTH command expected: '%s'", line);
99 else if (state == BeginWait)
101 if (!strcasecmp(cmd,
"BEGIN"))
104 c.
seterr(
"BEGIN command expected: '%s'", line);
111 WvDBusServer::WvDBusServer()
112 : log(
"DBus Server",
WvLog::Debug)
115 add(&listeners,
false,
"listeners");
128 IWvListener *listener = IWvListener::create(moniker);
129 log(WvLog::Info,
"Listening on '%s'\n", *listener->src());
130 if (!listener->
isok())
131 log(WvLog::Info,
"Can't listen: %s\n",
133 listener->
onaccept(wv::bind(&WvDBusServer::new_connection_cb,
135 listeners.add(listener,
true,
"listener");
144 WvIStreamList::Iter i(listeners);
145 for (i.rewind(); i.next(); )
161 WvIStreamList::Iter i(listeners);
162 for (i.rewind(); i.next(); )
164 return WvString(
"tcp:%s", *i->src());
171 name_to_conn[name] = conn;
177 assert(name_to_conn[name] == conn);
178 name_to_conn.erase(name);
185 std::map<WvString,WvDBusConn*>::iterator i;
186 for (i = name_to_conn.begin(); i != name_to_conn.end(); )
188 if (i->second == conn)
190 name_to_conn.erase(i->first);
191 i = name_to_conn.begin();
198 all_conns.unlink(conn);
206 if (msg.get_path() ==
"/org/freedesktop/DBus/Local")
208 if (method ==
"Disconnected")
212 if (msg.get_dest() !=
"org.freedesktop.DBus")
return false;
219 if (method ==
"Hello")
225 else if (method ==
"RequestName")
231 log(
"request_name_cb(%s)\n", _name);
234 msg.
reply().
append((uint32_t)DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
238 else if (method ==
"ReleaseName")
243 log(
"release_name_cb(%s)\n", _name);
246 msg.
reply().
append((uint32_t)DBUS_RELEASE_NAME_REPLY_RELEASED)
250 else if (method ==
"NameHasOwner")
253 WvString known_name = args.getnext();
258 else if (method ==
"GetNameOwner")
261 WvString known_name = args.getnext();
266 WvDBusError(msg,
"org.freedesktop.DBus.Error.NameHasNoOwner",
267 "No match for name '%s'", known_name).
send(conn);
270 else if (method ==
"AddMatch")
276 else if (method ==
"StartServiceByName")
283 else if (method ==
"GetConnectionUnixUser" ||
284 method ==
"GetConnectionUnixUserName")
292 WvDBusError(msg,
"org.freedesktop.DBus.Error.Failed",
293 "No connection found for name '%s'.", _name).
send(conn);
297 wvuid_t client_uid = target->get_uid();
299 if (client_uid == WVUID_INVALID)
301 WvDBusError(msg,
"org.freedesktop.DBus.Error.Failed",
302 "No user associated with connection '%s'.",
307 log(
"Found unix user for '%s', uid is %s.\n", _name, client_uid);
309 if (method ==
"GetConnectionUnixUser")
315 else if (method ==
"GetConnectionUnixUserName")
317 WvString username = wv_username_from_uid(client_uid);
320 WvDBusError(msg,
"org.freedesktop.DBus.Error.Failed",
321 "No username for uid='%s'", client_uid)
334 else if (method ==
"GetConnectionCert" ||
335 method ==
"GetConnectionCertFingerprint")
342 WvString ret = c ? c->getattr(
"peercert") : WvString::null;
344 WvDBusError(msg,
"org.freedesktop.DBus.Error.Failed",
345 "Connection %s did not present a certificate",
349 if (method ==
"GetConnectionCertFingerprint")
353 tempcert.
decode(WvX509::CertPEM, ret);
363 WvDBusError(msg,
"org.freedesktop.DBus.Error.UnknownMethod",
364 "Unknown dbus method '%s'", method).
send(conn);
374 if (!!msg.get_dest())
376 std::map<WvString,WvDBusConn*>::iterator i
377 = name_to_conn.find(msg.get_dest());
378 WvDBusConn *dconn = (i == name_to_conn.end()) ? NULL : i->second;
379 log(
"Proxying #%s -> %s\n",
388 "Proxy: no connection for '%s'\n", msg.get_dest());
402 log(
"Broadcasting #%s\n", msg.get_serial());
408 WvDBusConnList::Iter i(all_conns);
409 for (i.rewind(); i.next(); )
419 WvDBusError(msg,
"org.freedesktop.DBus.Error.NameHasNoOwner",
420 "No running service named '%s'", msg.get_dest()).send(conn);
425 void WvDBusServer::conn_closed(
WvStream &s)
433 void WvDBusServer::new_connection_cb(
IWvStream *s)
438 all_conns.append(c,
true);
449 IWvStreamCallback mycb = wv::bind(&WvDBusServer::conn_closed,
this,
454 wv::bind(&WvDBusServer::do_server_msg,
this,
457 wv::bind(&WvDBusServer::do_bridge_msg,
this,
460 wv::bind(&WvDBusServer::do_broadcast_msg,
this,
463 wv::bind(&WvDBusServer::do_gaveup_msg,
this,
466 append(c,
true,
"wvdbus servconn");