Proposal for a new VPN DBUS interface


I'd like to share some thoughts about an improved DBUS-API between
NetworkManager and a VPN service. I think we need some changes here to
support multiple active connections per service, and to allow multiple
services to have active connections at the same time.

We have to consider that we are targeting different kinds of services.
Some launch a separate process for each tunnel, others use a long
running daemon and handle multiple tunnels.

VPN service:
I think we should define a generic DBUS interface for VPN services.
Currently, all services are implementing their own interface. This
doesn't make sense to me.
A VPN service should handle multiple connections. In the
process-per-tunnel case, a helper (the vpn.service interface
implementer) could launch multiple processes and manage them. In the
case of a multiple-tunnel-daemon, the daemon could implement the DBUS
API on it's own (or using a helper).
A generic VPN service could look like this:

   startConnection(in str name, in array(struct{str key, str value}));
   stopConnection(in str name);
   getConnections(out array(struct{str name, int state));

startConnections() has a list of implementation specific options (from
the configuration dialog). The name uniquely defines the connections
name. The getConnections() call lists all connections with its current

To notify NetworkManager (and others) about the connections state, a
service sends signals (as it currently does):

   stateChange(str name, int state);
   connectionEstablished(str name, str banner,
                         array(struct{str key, str value}));
   connectionFailed(str name, str reason);

If an asynchronous call to startConnection() is successful,
connectionEstablished() is signaled. It contains a list of configuration
options (currently IP4Config). It may contain options for IPv4 and IPv6,
as a tunnel may establish mixed routes.
If connection setup fails, a single signal seems sufficient to me. The
reason gives the user information about what has failed. We may consider
to include a numeric failure code to handle them more generic.

Authentication service:
The current authentication mechanism seems to be too limited to me. The
daemon should be able to request authentication data actively. This is
needed to:
- Do proper re-authentication
- The VPN gateway may decide how to authenticate (e.g. EAP in IKEv2).
  We can't authenticate in previous, as we don't know which
  authentication method will be used.

The nm-applet could provide a "authentication facility", which allows a
VPN service to request authentication. This would allow us to reuse
authentication dialogs and integrate them using shared libs.

This authentication service could listen to signals emitted by the

   authRequest(str name, str type, bool prompt, 
               array(struct{str key, str value}));

If the authentication facility receives such a signal, it pops up the
dialog using the key/value strings (containing challenges, ...), or, if
prompt is not set, fetches them from the keyring. The type says which
authentication dialog should be used. Then it calls the vpn.service's
authData method.

   authData(in str name, in array(struct{str key, str value}));


The complete VPN service would look like this:


   /* start a connection called "name", using options in array */
   startConnection(in str name, in array(struct{str key, str value}));
   /* stop a previously started connection called "name" */
   stopConnection(in str name);
   /* get a list of active connections, and its state */
   getConnections(out array(struct{str name, int state));
   /* pass authentication data for connection "name" to the service */
   authData(in str name, in array(struct{str key, str value}));


   /* the state of the connection "name" has changed to "state" */
   stateChange(str name, int state);
   /* the connection "name" has been established, options in array */
   connectionEstablished(str name, str banner,
                         array(struct{str key, str value}));
   /* the connection "name" failed to establish, because of "reason" */
   connectionFailed(str name, str reason);
   /* the daemon needs authentication data for "name" of "type" */
   authRequest(str name, str type, array(struct{str key, str value}));

We could use "dicts" for the key/value arrays, but it seems a bit
overkill. Every VPN service would need the somewhat complicated "dict"
routines, so I would prefer simple array of strings. Or are/will be
these dicts parts of DBUS?

I'd like to hear what you think about a new DBUS interface. I'm
currently implementing a NM interface into strongSwan (an IPsec
solution). But the current interface limits its functionality, so I
think we need a more powerful API.

Awaiting your comments...


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]