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
|
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
|
* `./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;
|
AskUserFunc ask_user_func = NULL;
|
||||||
FinishFunc finish_func = NULL;
|
FinishFunc finish_func = NULL;
|
||||||
|
|
||||||
|
// this describes how the arguments are supposed to be parsed
|
||||||
|
// e.g. "-u UUID"
|
||||||
GOptionContext *context;
|
GOptionContext *context;
|
||||||
GOptionEntry entries[] = {
|
GOptionEntry entries[] = {
|
||||||
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
|
{ "reprompt", 'r', 0, G_OPTION_ARG_NONE, &retry, "Reprompt for passwords", NULL},
|
||||||
|
@ -485,16 +487,22 @@ main (int argc, char *argv[])
|
||||||
return EXIT_FAILURE;
|
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) {
|
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);
|
fprintf (stderr, "This dialog only works with the '%s' service\n", NM_VPN_SERVICE_TYPE_OPENVPN);
|
||||||
return EXIT_FAILURE;
|
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)) {
|
if (!nm_vpn_service_plugin_read_vpn_details (0, &data, &secrets)) {
|
||||||
fprintf (stderr, "Failed to read '%s' (%s) data and secrets from stdin.\n",
|
fprintf (stderr, "Failed to read '%s' (%s) data and secrets from stdin.\n",
|
||||||
vpn_name, vpn_uuid);
|
vpn_name, vpn_uuid);
|
||||||
return 1;
|
//return 1; // TODO re-add
|
||||||
}
|
}
|
||||||
|
printf("Done reading\n");
|
||||||
|
|
||||||
if (external_ui_mode) {
|
if (external_ui_mode) {
|
||||||
no_secrets_required_func = eui_no_secrets_required;
|
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!"):
|
def send_desktop_notification(title="Hello World", msg="pydbus works!"):
|
||||||
"""Send a notification to the desktop environment to display"""
|
"""Send a notification to the desktop environment to display"""
|
||||||
|
|
||||||
bus = SessionBus()
|
bus = SessionBus()
|
||||||
notifications = bus.get('.Notifications')
|
notifications = bus.get('.Notifications')
|
||||||
notifications.Notify('test', 0, 'dialog-information', title, msg, [], {}, 5000)
|
notifications.Notify('test', 0, 'dialog-information', title, msg, [], {}, 5000)
|
||||||
|
|
||||||
def list_systemd_units():
|
def list_systemd_units():
|
||||||
"""Fetch all systemd units and print them"""
|
"""Fetch all systemd units and print them"""
|
||||||
|
|
||||||
bus = SystemBus()
|
bus = SystemBus()
|
||||||
|
|
||||||
# systemd is now a proxy for the .systemd1 remote object
|
# 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"):
|
def stop_start_systemd_unit(name="ssh.service"):
|
||||||
"""Stop and restart a systemd unit"""
|
"""Stop and restart a systemd unit"""
|
||||||
|
|
||||||
bus = SystemBus()
|
bus = SystemBus()
|
||||||
|
|
||||||
# systemd is now a proxy for the .systemd1 remote object
|
# 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():
|
def watch_for_new_systemd_jobs():
|
||||||
"""Wait for new systemd units and when they are created, print them out"""
|
"""Wait for new systemd units and when they are created, print them out"""
|
||||||
|
|
||||||
bus = SystemBus()
|
bus = SystemBus()
|
||||||
|
|
||||||
# systemd is now a proxy for the .systemd1 remote object
|
# systemd is now a proxy for the .systemd1 remote object
|
||||||
|
@ -76,8 +80,9 @@ def hibernate():
|
||||||
else:
|
else:
|
||||||
print("Cannot hibernate")
|
print("Cannot hibernate")
|
||||||
|
|
||||||
except GLib.Error as e:
|
except Exception as ex:
|
||||||
print("Could not get PowerManager from DBUS")
|
print("Could not get PowerManager from DBUS")
|
||||||
|
print(str(ex))
|
||||||
|
|
||||||
|
|
||||||
def get_wg_plugin(bus_name="org.freedesktop.NetworkManager.wireguard",
|
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):
|
def wg_disconnect(wg_plugin):
|
||||||
"""Disconnect the WG VPN plugin"""
|
"""Disconnect the WG VPN plugin"""
|
||||||
|
|
||||||
wg_plugin.Disconnect()
|
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
|
show_introspect = False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# send_desktop_notification("Guten Tag", "pydbus funktioniert, mein Herr!")
|
# send_desktop_notification("Guten Tag", "pydbus funktioniert, mein Herr!")
|
||||||
# list_systemd_units()
|
|
||||||
# hibernate()
|
|
||||||
try:
|
try:
|
||||||
wg = get_wg_plugin()
|
wg = get_wg_plugin()
|
||||||
|
|
||||||
|
@ -114,7 +143,7 @@ if __name__ == "__main__":
|
||||||
print(wg.Introspect())
|
print(wg.Introspect())
|
||||||
help(wg)
|
help(wg)
|
||||||
|
|
||||||
wg_disconnect(wg)
|
wg_connect(wg)
|
||||||
|
|
||||||
except Exception as ex:
|
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 *
|
static const char *
|
||||||
openvpn_binary_find_exepath (void)
|
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);
|
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
|
static gboolean
|
||||||
pids_pending_ensure_killed (gpointer user_data)
|
pids_pending_ensure_killed (gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -2038,23 +2113,47 @@ real_disconnect (NMVpnServicePlugin *plugin,
|
||||||
static gboolean
|
static gboolean
|
||||||
test_connect (NMVpnServicePlugin *plugin,
|
test_connect (NMVpnServicePlugin *plugin,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
GError **error)
|
GError **err)
|
||||||
{
|
{
|
||||||
_LOGI("Did a dummy connect");
|
|
||||||
|
|
||||||
/*
|
NMSettingVpn *setting = nm_connection_get_setting_vpn(connection);
|
||||||
printf("I Know It!\n");
|
char *secret = nm_setting_vpn_get_secret(setting, "name");
|
||||||
// FIXME find something useful
|
char *str_setting = nm_setting_to_string(setting);
|
||||||
char **cmd = {"touch", "/home/maxmanski/iknowhwatyoudidlastsummer", NULL};
|
char *wg_quick_path = wg_quick_find_exepath();
|
||||||
GPid pid = 0;
|
//char *
|
||||||
GSpawnFlags spawn_flags = G_SPAWN_DO_NOT_REAP_CHILD;
|
|
||||||
spawn_flags = G_SPAWN_DEFAULT;
|
|
||||||
|
|
||||||
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;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue