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");
void send(WvDBusConn &conn)
A shortcut for sending this message on the given connection.
WvString get_fingerprint(const FprintMode mode=FingerSHA1) const
Get the certHash (fingerprint) of the certificate.
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
virtual bool isok() const
return true if the stream is actually usable right now
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
void add_callback(CallbackPri pri, WvDBusCallback cb, void *cookie=NULL)
Adds a callback to the connection: all received messages will be sent to all callbacks to look at and...
void unregister_conn(WvDBusConn *conn)
Forget all name registrations for a particular connection.
void register_name(WvStringParm name, WvDBusConn *conn)
Register a given dbus service name as belonging to a particular connection.
X509 Class to handle certificates and their related functions.
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
uint32_t send(WvDBusMsg msg)
Send a message on the bus, not expecting any reply.
WvDBusMsg & append(const char *s)
The following methods are designed to allow appending various arguments to the message.
WvDBusMsg reply()
Generate a message that will be a reply to this one.
WvString strflushstr(WvStringParm instr, bool finish=false)
Flushes data through the encoder from a string to a string.
void unregister_name(WvStringParm name, WvDBusConn *conn)
Undo a register_name().
void listen(WvStringParm moniker)
Listen using a given WvListener moniker.
WvString uniquename() const
Return this connection's unique name on the bus, assigned by the server at connect time.
virtual void close()
Close the stream if it is open; isok() becomes false from now on.
virtual void seterr(int _errnum)
Override seterr() from WvError so that it auto-closes the stream.
virtual ~WvDBusServer()
Shut down this server.
WvString is an implementation of a simple and efficient printable-string class.
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
bool isnull() const
returns true if this string is null
const char * cstr() const
return a (const char *) for this string.
virtual unsigned int release()=0
Indicate that you are finished using this object.
virtual size_t read(void *buf, size_t count)
read a data block on the stream.
virtual IWvListenerCallback onaccept(IWvListenerCallback _cb)=0
Set a user-defined function to be called when a new connection is available.
virtual bool isok() const =0
By default, returns true if geterr() == 0.
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
WvString get_addr()
get the full, final address (identification guid and all) of the server if there's more than one list...
virtual bool isok() const
return true if the stream is actually usable right now
IWvStreamCallback setclosecallback(IWvStreamCallback _callback)
Sets a callback to be invoked on close().
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
This is a WvList of WvStrings, and is a really handy way to parse strings.
void split(WvStringParm s, const char *splitchars=" \t\r\n", int limit=0)
split s and form a list ignoring splitchars (except at beginning and end) ie.
virtual unsigned int addRef()=0
Indicate you are using this object.
int num() const
Return a stdc++ string with the contents of this string.
virtual bool authorize(WvDBusConn &c)
Main action callback.