11#include "wvdbusserver.h"
12#include "wvdbusconn.h"
15#include "wvtcplistener.h"
16#include "wvdelayedcallback.h"
24 enum State { NullWait, AuthWait, BeginWait };
31 virtual wvuid_t get_uid() {
return client_uid; }
35WvDBusServerAuth::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);
111WvDBusServer::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);
425void WvDBusServer::conn_closed(
WvStream &s)
433void 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");
virtual unsigned int addRef()=0
Indicate you are using this object.
virtual unsigned int release()=0
Indicate that you are finished using this object.
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.
uint32_t send(WvDBusMsg msg)
Send a message on the bus, not expecting any reply.
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...
WvString uniquename() const
Return this connection's unique name on the bus, assigned by the server at connect time.
WvDBusMsg reply()
Generate a message that will be a reply to this one.
void send(WvDBusConn &conn)
A shortcut for sending this message on the given connection.
WvDBusMsg & append(const char *s)
The following methods are designed to allow appending various arguments to the message.
virtual bool authorize(WvDBusConn &c)
Main action callback.
void listen(WvStringParm moniker)
Listen using a given WvListener moniker.
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
void unregister_name(WvStringParm name, WvDBusConn *conn)
Undo a register_name().
void unregister_conn(WvDBusConn *conn)
Forget all name registrations for a particular connection.
WvString get_addr()
get the full, final address (identification guid and all) of the server if there's more than one list...
virtual ~WvDBusServer()
Shut down this server.
void register_name(WvStringParm name, WvDBusConn *conn)
Register a given dbus service name as belonging to a particular connection.
virtual bool isok() const
return true if the stream is actually usable right now
WvString strflushstr(WvStringParm instr, bool finish=false)
Flushes data through the encoder from a string to a string.
virtual int geterr() const
If isok() is false, return the system error number corresponding to the error, -1 for a special error...
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
int num() const
Return a stdc++ string with the contents of this string.
bool isnull() const
returns true if this string is null
const char * cstr() const
return a (const char *) for this string.
virtual bool isok() const
return true if the stream is actually usable right now
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Unified support for streams, that is, sequences of bytes that may or may not be ready for read/write ...
IWvStreamCallback setclosecallback(IWvStreamCallback _callback)
Sets a callback to be invoked on close().
virtual size_t read(void *buf, size_t count)
read a data block on the stream.
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.
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.
WvString popstr()
get the first string in the list, or an empty string if the list is empty.
WvString is an implementation of a simple and efficient printable-string class.
X509 Class to handle certificates and their related functions.
WvString get_fingerprint(const FprintMode mode=FingerSHA1) const
Get the certHash (fingerprint) of the certificate.
virtual void decode(const DumpMode mode, WvStringParm str)
Load the information from the format requested by mode into the class - this overwrites the certifica...
Various little string functions.