Add DBUS communication in dbus.py, update README and add changes to sources
parent
d606210675
commit
fb4cfa2413
18
README.md
18
README.md
|
@ -14,4 +14,20 @@
|
|||
The following section briefly describes how to start the stuff for testing purposes
|
||||
|
||||
* `./src/nm-openvpn-service --bus-name org.freedesktop.NetworkManager.wireguard` to start the plugin
|
||||
* `examples/dbus/dbus.py` to send Disconnect() to the plugin
|
||||
* `examples/dbus/dbus.py` to send Disconnect() to the plugin
|
||||
|
||||
## Files
|
||||
The following is a list of files that I created over the course of the project and is mainly for myself to keep track of them.
|
||||
|
||||
* `nm-wireguard-service.conf`
|
||||
* `includes2strings.py`
|
||||
|
||||
## Knowledge
|
||||
* The wireguard plugin basically handles incoming DBUS requests for the *NM VPN Plugin Interface* (can be looked at via `examples/dbus/dbus.py`)
|
||||
* `auth-dialog/nm-openvpn-auth-dialog` reads the secrets from STDIN until the string "DONE" occurs and then proceeds to handle them
|
||||
|
||||
NM VPN Plugin:
|
||||
https://developer.gnome.org/libnm-glib/stable/libnm-glib-NMVPNPlugin.html
|
||||
|
||||
Settings VPN (sent via DBus on Connect(a{sa{sv}}) method):
|
||||
https://developer.gnome.org/libnm/stable/NMSettingVpn.html#nm-setting-vpn-get-data-item
|
|
@ -457,6 +457,8 @@ main (int argc, char *argv[])
|
|||
AskUserFunc ask_user_func = NULL;
|
||||
FinishFunc finish_func = NULL;
|
||||
|
||||
// this describes how the arguments are supposed to be parsed
|
||||
// e.g. "-u UUID"
|
||||
GOptionContext *context;
|
||||
GOptionEntry entries[] = {
|
||||
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
|
||||
|
@ -485,16 +487,22 @@ main (int argc, char *argv[])
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// the parameters are supplied via arguments
|
||||
printf("UUID: %s, Name: %s, Service: %s\n", vpn_uuid, vpn_name, vpn_service);
|
||||
|
||||
if (strcmp (vpn_service, NM_VPN_SERVICE_TYPE_OPENVPN) != 0) {
|
||||
fprintf (stderr, "This dialog only works with the '%s' service\n", NM_VPN_SERVICE_TYPE_OPENVPN);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Reading stdin details\n");
|
||||
// reads secrets/data from STDIN until "DONE" is read
|
||||
if (!nm_vpn_service_plugin_read_vpn_details (0, &data, &secrets)) {
|
||||
fprintf (stderr, "Failed to read '%s' (%s) data and secrets from stdin.\n",
|
||||
vpn_name, vpn_uuid);
|
||||
return 1;
|
||||
//return 1; // TODO re-add
|
||||
}
|
||||
printf("Done reading\n");
|
||||
|
||||
if (external_ui_mode) {
|
||||
no_secrets_required_func = eui_no_secrets_required;
|
||||
|
|
|
@ -24,12 +24,14 @@ show_introspect = True
|
|||
|
||||
def send_desktop_notification(title="Hello World", msg="pydbus works!"):
|
||||
"""Send a notification to the desktop environment to display"""
|
||||
|
||||
bus = SessionBus()
|
||||
notifications = bus.get('.Notifications')
|
||||
notifications.Notify('test', 0, 'dialog-information', title, msg, [], {}, 5000)
|
||||
|
||||
def list_systemd_units():
|
||||
"""Fetch all systemd units and print them"""
|
||||
|
||||
bus = SystemBus()
|
||||
|
||||
# systemd is now a proxy for the .systemd1 remote object
|
||||
|
@ -42,6 +44,7 @@ def list_systemd_units():
|
|||
|
||||
def stop_start_systemd_unit(name="ssh.service"):
|
||||
"""Stop and restart a systemd unit"""
|
||||
|
||||
bus = SystemBus()
|
||||
|
||||
# systemd is now a proxy for the .systemd1 remote object
|
||||
|
@ -51,6 +54,7 @@ def stop_start_systemd_unit(name="ssh.service"):
|
|||
|
||||
def watch_for_new_systemd_jobs():
|
||||
"""Wait for new systemd units and when they are created, print them out"""
|
||||
|
||||
bus = SystemBus()
|
||||
|
||||
# systemd is now a proxy for the .systemd1 remote object
|
||||
|
@ -76,8 +80,9 @@ def hibernate():
|
|||
else:
|
||||
print("Cannot hibernate")
|
||||
|
||||
except GLib.Error as e:
|
||||
except Exception as ex:
|
||||
print("Could not get PowerManager from DBUS")
|
||||
print(str(ex))
|
||||
|
||||
|
||||
def get_wg_plugin(bus_name="org.freedesktop.NetworkManager.wireguard",
|
||||
|
@ -98,15 +103,39 @@ def get_wg_plugin(bus_name="org.freedesktop.NetworkManager.wireguard",
|
|||
|
||||
def wg_disconnect(wg_plugin):
|
||||
"""Disconnect the WG VPN plugin"""
|
||||
|
||||
wg_plugin.Disconnect()
|
||||
|
||||
def wg_connect(wg_plugin):
|
||||
"""Send the Connect Command to the Wireguard Plugin"""
|
||||
|
||||
# these are the settings that are expected by Connect(a{sa{sv}}) for a VPN plugin
|
||||
service_type = GLib.Variant("s", "service")
|
||||
user_name = GLib.Variant("s", "wireguard")
|
||||
persistent = GLib.Variant("b", False)
|
||||
data = GLib.Variant("a{ss}", {"maxi": "cool"})
|
||||
secrets = GLib.Variant("a{ss}", {"name": "maxi moser"})
|
||||
timeout = GLib.Variant("u", 1337)
|
||||
|
||||
# The DBus type: a{sa{sv}}
|
||||
# is a Dictionary with...
|
||||
# Key: Type ("wireless", "wired", "vpn", ...) -- we want VPN
|
||||
# Value: Dictionary with Key: Setting Name, Value: Setting Value
|
||||
settings = {"vpn":
|
||||
{"service-type": service_type,
|
||||
"user-name": user_name,
|
||||
"persistent": persistent,
|
||||
"data": data,
|
||||
"secrets": secrets,
|
||||
"timeout": timeout}
|
||||
}
|
||||
wg_plugin.Connect(settings)
|
||||
|
||||
|
||||
show_introspect = False
|
||||
|
||||
if __name__ == "__main__":
|
||||
# send_desktop_notification("Guten Tag", "pydbus funktioniert, mein Herr!")
|
||||
# list_systemd_units()
|
||||
# hibernate()
|
||||
try:
|
||||
wg = get_wg_plugin()
|
||||
|
||||
|
@ -114,7 +143,7 @@ if __name__ == "__main__":
|
|||
print(wg.Introspect())
|
||||
help(wg)
|
||||
|
||||
wg_disconnect(wg)
|
||||
wg_connect(wg)
|
||||
|
||||
except Exception as ex:
|
||||
print(str(ex))
|
||||
print(str(ex))
|
||||
|
|
|
@ -236,6 +236,28 @@ _LOGD_enabled (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
wg_quick_find_exepath (void)
|
||||
{
|
||||
static const char *paths[] = {
|
||||
"/usr/sbin/wg-quick",
|
||||
"/usr/bin/wg-quick",
|
||||
"/sbin/wg-quick",
|
||||
"/bin/wg-quick",
|
||||
"/usr/local/sbin/wg-quick",
|
||||
"/usr/local/bin/wg-quick",
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(paths); i++) {
|
||||
if (g_file_test (paths[i], G_FILE_TEST_EXISTS)) {
|
||||
return paths[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
openvpn_binary_find_exepath (void)
|
||||
{
|
||||
|
@ -393,6 +415,59 @@ pids_pending_add (GPid pid, NMWireguardPlugin *plugin)
|
|||
gl.pids_pending_list = g_slist_prepend (gl.pids_pending_list, pid_data);
|
||||
}
|
||||
|
||||
// TODO implement me right
|
||||
wg_quick_closed(GPid pid, gint status, gpointer user_data){
|
||||
PidsPendingData *pid_data = user_data;
|
||||
NMWireguardPlugin *plugin;
|
||||
|
||||
if (WIFEXITED (status)) {
|
||||
int exit_status;
|
||||
|
||||
exit_status = WEXITSTATUS (status);
|
||||
if (exit_status != 0)
|
||||
_LOGW ("wg-quick[%ld] exited with error code %d", (long) pid, exit_status);
|
||||
else
|
||||
_LOGI ("wg-quick[%ld] exited with success", (long) pid);
|
||||
}
|
||||
else if (WIFSTOPPED (status))
|
||||
_LOGW ("wg-quick[%ld] stopped unexpectedly with signal %d", (long) pid, WSTOPSIG (status));
|
||||
else if (WIFSIGNALED (status))
|
||||
_LOGW ("wg-quick[%ld] died with signal %d", (long) pid, WTERMSIG (status));
|
||||
else
|
||||
_LOGW ("wg-quick[%ld] died from an unnatural cause", (long) pid);
|
||||
|
||||
g_return_if_fail (pid_data);
|
||||
g_return_if_fail (pid_data->pid == pid);
|
||||
g_return_if_fail (g_slist_find (gl.pids_pending_list, pid_data));
|
||||
|
||||
plugin = pid_data->plugin;
|
||||
|
||||
pid_data->watch_id = 0;
|
||||
gl.pids_pending_list = g_slist_remove (gl.pids_pending_list , pid_data);
|
||||
pids_pending_data_free (pid_data);
|
||||
}
|
||||
|
||||
// TODO implement me right
|
||||
static void
|
||||
pids_pending_add_wg (GPid pid, NMWireguardPlugin *plugin)
|
||||
{
|
||||
PidsPendingData *pid_data;
|
||||
|
||||
g_return_if_fail (NM_IS_WIREGUARD_PLUGIN (plugin));
|
||||
g_return_if_fail (pid > 0);
|
||||
|
||||
_LOGI ("wg-quick[%ld] started", (long) pid);
|
||||
|
||||
pid_data = g_slice_new (PidsPendingData);
|
||||
pid_data->pid = pid;
|
||||
pid_data->kill_id = 0;
|
||||
pid_data->watch_id = g_child_watch_add (pid, wg_quick_closed, pid_data);
|
||||
pid_data->plugin = plugin;
|
||||
g_object_add_weak_pointer ((GObject *) plugin, (gpointer *) &pid_data->plugin);
|
||||
|
||||
gl.pids_pending_list = g_slist_prepend (gl.pids_pending_list, pid_data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pids_pending_ensure_killed (gpointer user_data)
|
||||
{
|
||||
|
@ -2038,23 +2113,47 @@ real_disconnect (NMVpnServicePlugin *plugin,
|
|||
static gboolean
|
||||
test_connect (NMVpnServicePlugin *plugin,
|
||||
NMConnection *connection,
|
||||
GError **error)
|
||||
GError **err)
|
||||
{
|
||||
_LOGI("Did a dummy connect");
|
||||
|
||||
/*
|
||||
printf("I Know It!\n");
|
||||
// FIXME find something useful
|
||||
char **cmd = {"touch", "/home/maxmanski/iknowhwatyoudidlastsummer", NULL};
|
||||
GPid pid = 0;
|
||||
GSpawnFlags spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD;
|
||||
spawn_flags = G_SPAWN_DEFAULT;
|
||||
NMSettingVpn *setting = nm_connection_get_setting_vpn(connection);
|
||||
char *secret = nm_setting_vpn_get_secret(setting, "name");
|
||||
char *str_setting = nm_setting_to_string(setting);
|
||||
char *wg_quick_path = wg_quick_find_exepath();
|
||||
//char *
|
||||
|
||||
if (!g_spawn_async (NULL, cmd, NULL, spawn_flags, NULL, NULL, &pid, error)){
|
||||
if(wg_quick_path == NULL){
|
||||
_LOGW("Error: Could not find wg-quick!");
|
||||
return FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
printf("Setting to String: %s\n", str_setting);
|
||||
printf("Secret: %s\n", secret);
|
||||
|
||||
//char **cmd = {wg_quick_path, "up", "mullvad", NULL};
|
||||
char **cmd = {"/usr/bin/touch", "/home/maxmanski/uwotm8", NULL};
|
||||
GPid pid = 0;
|
||||
GSpawnFlags spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD;
|
||||
spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL;
|
||||
spawn_flags = G_SPAWN_DEFAULT | G_SPAWN_DO_NOT_REAP_CHILD;
|
||||
|
||||
// if (!g_spawn_async (NULL, cmd, NULL, spawn_flags, NULL, NULL, &pid, err)){
|
||||
int exit_code = 0;
|
||||
*err = NULL; // TODO remove?
|
||||
|
||||
if (!g_spawn_async(NULL, cmd, NULL, spawn_flags, NULL, NULL, &pid, err)){
|
||||
_LOGW("An error occured while spawning wg-quick! (Error: %s)", (*err)->message);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pids_pending_add_wg(pid, plugin);
|
||||
printf("PID of spawned command: %d\n", pid);
|
||||
// note: exit code 139 means SIGSEV (program died because of segfault or so)
|
||||
{
|
||||
printf("WG set up and ready to go!\n");
|
||||
}
|
||||
|
||||
_LOGI("Did a dummy connect");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue