This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch nm-vpn-username-capture
in repository enlightenment.
View the commit online.
commit 02757b99e1ad1e832501a63326f6e098aa996af0
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 21 20:52:47 2026 -0600
networkmanager: add enm_vpn_username_needed predicate
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
---
.../networkmanager/e_networkmanager_vpn_username.c | 46 +++++++++++++++++++
.../networkmanager/e_networkmanager_vpn_username.h | 51 ++++++++++++++++++++++
src/modules/networkmanager/meson.build | 2 +
src/modules/networkmanager/test_vpn_username.c | 33 ++++++++++++++
4 files changed, 132 insertions(+)
diff --git a/src/modules/networkmanager/e_networkmanager_vpn_username.c b/src/modules/networkmanager/e_networkmanager_vpn_username.c
new file mode 100644
index 000000000..c9f8b9b47
--- /dev/null
+++ b/src/modules/networkmanager/e_networkmanager_vpn_username.c
@@ -0,0 +1,46 @@
+#ifdef ENM_VPN_USERNAME_TEST
+/* Standalone unit-test build: no EFL, no config.h. */
+typedef unsigned char Eina_Bool;
+# define EINA_TRUE 1
+# define EINA_FALSE 0
+# include <string.h>
+#else
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+# include <string.h>
+# include <stdlib.h>
+# include "e.h"
+# include "e_networkmanager.h"
+# include "e_networkmanager_import.h"
+# include "e_networkmanager_vpn_username.h"
+#endif
+
+Eina_Bool
+enm_vpn_username_needed(const char *svc_short, const char *conn_type,
+ const char *current_username)
+{
+ if (current_username && current_username[0]) return EINA_FALSE;
+ if (!svc_short) return EINA_FALSE;
+
+ if (!strcmp(svc_short, "openvpn"))
+ {
+ if (!conn_type) return EINA_FALSE;
+ return (!strcmp(conn_type, "password") ||
+ !strcmp(conn_type, "password-tls"))
+ ? EINA_TRUE : EINA_FALSE;
+ }
+
+ if (!strcmp(svc_short, "pptp") || !strcmp(svc_short, "l2tp") ||
+ !strcmp(svc_short, "fortisslvpn") || !strcmp(svc_short, "vpnc") ||
+ !strcmp(svc_short, "openswan") || !strcmp(svc_short, "libreswan") ||
+ !strcmp(svc_short, "strongswan"))
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+#ifndef ENM_VPN_USERNAME_TEST
+/* enm_vpn_username_set / enm_vpn_username_dialog / enm_vpn_username_maybe_prompt
+ * are added in Tasks 2 and 3. */
+#endif
diff --git a/src/modules/networkmanager/e_networkmanager_vpn_username.h b/src/modules/networkmanager/e_networkmanager_vpn_username.h
new file mode 100644
index 000000000..24b77b1e1
--- /dev/null
+++ b/src/modules/networkmanager/e_networkmanager_vpn_username.h
@@ -0,0 +1,51 @@
+#ifndef E_NETWORKMANAGER_VPN_USERNAME_H
+#define E_NETWORKMANAGER_VPN_USERNAME_H
+
+#include <Eina.h>
+
+/*
+ * VPN username capture.
+ *
+ * NetworkManager stores a VPN username as a connection *property*
+ * (vpn.data["username"]), not as a secret, and the SecretAgent D-Bus API
+ * (GetSecrets) only ever deals with secrets. NM therefore never prompts for
+ * a missing username: importing an .ovpn with a bare `auth-user-pass` yields a
+ * connection with password-flags set but no username, which is unusable.
+ *
+ * This long-standing NetworkManager behaviour is reported in:
+ * - https://bugzilla.redhat.com/show_bug.cgi?id=1535517
+ * - https://bugzilla.redhat.com/show_bug.cgi?id=1548873
+ * - https://bbs.archlinux.org/viewtopic.php?id=286378
+ * - https://bbs.archlinux.org/viewtopic.php?id=225395
+ * - https://github.com/pop-os/cosmic-settings/issues/1820
+ *
+ * All functions here are MAIN THREAD ONLY.
+ */
+
+/* True when the VPN type uses username auth and current_username is empty.
+ * svc_short is the short service name ("openvpn", "pptp", ...); conn_type is
+ * vpn.data["connection-type"] (may be NULL). */
+Eina_Bool enm_vpn_username_needed(const char *svc_short,
+ const char *conn_type,
+ const char *current_username);
+
+/* Called with the entered username (NULL on cancel). */
+typedef void (*Enm_Username_Entered_Cb)(void *data, const char *username);
+
+/* Called when the nmcli modify completes. */
+typedef void (*Enm_Username_Done_Cb)(void *data, Eina_Bool ok);
+
+/* Persist username to vpn.data["username"] via `nmcli connection modify`. */
+void enm_vpn_username_set(const char *conn_name, const char *username,
+ Enm_Username_Done_Cb cb, void *data);
+
+/* Single-field username dialog. Calls cb(username) on OK, cb(NULL) on cancel. */
+void enm_vpn_username_dialog(const char *conn_name, const char *type_label,
+ const char *initial,
+ Enm_Username_Entered_Cb cb, void *data);
+
+/* Post-import orchestrator: query the connection, and if it needs a username,
+ * prompt for one and persist it. Fire-and-forget. */
+void enm_vpn_username_maybe_prompt(const char *conn_name);
+
+#endif
diff --git a/src/modules/networkmanager/meson.build b/src/modules/networkmanager/meson.build
index b83a30442..6fb04a071 100644
--- a/src/modules/networkmanager/meson.build
+++ b/src/modules/networkmanager/meson.build
@@ -8,6 +8,8 @@ src = ""
'e_networkmanager_vpn.h',
'e_networkmanager_import.c',
'e_networkmanager_import.h',
+ 'e_networkmanager_vpn_username.c',
+ 'e_networkmanager_vpn_username.h',
'e_mod_main.h'
)
diff --git a/src/modules/networkmanager/test_vpn_username.c b/src/modules/networkmanager/test_vpn_username.c
new file mode 100644
index 000000000..740dd4377
--- /dev/null
+++ b/src/modules/networkmanager/test_vpn_username.c
@@ -0,0 +1,33 @@
+/* Standalone unit test for enm_vpn_username_needed.
+ * Build: gcc -DENM_VPN_USERNAME_TEST test_vpn_username.c -o /tmp/t && /tmp/t */
+#include <assert.h>
+#include <stdio.h>
+
+#define ENM_VPN_USERNAME_TEST 1
+#include "e_networkmanager_vpn_username.c"
+
+int main(void)
+{
+ /* openvpn: only password / password-tls need a username */
+ assert(enm_vpn_username_needed("openvpn", "password", NULL));
+ assert(enm_vpn_username_needed("openvpn", "password-tls", ""));
+ assert(!enm_vpn_username_needed("openvpn", "tls", NULL));
+ assert(!enm_vpn_username_needed("openvpn", NULL, NULL));
+
+ /* already has a username -> never needed */
+ assert(!enm_vpn_username_needed("openvpn", "password", "alice"));
+
+ /* xauth / password-based types always need it when empty */
+ assert(enm_vpn_username_needed("pptp", NULL, NULL));
+ assert(enm_vpn_username_needed("l2tp", NULL, ""));
+ assert(enm_vpn_username_needed("vpnc", NULL, NULL));
+ assert(enm_vpn_username_needed("libreswan", NULL, NULL));
+ assert(!enm_vpn_username_needed("libreswan", NULL, "bob"));
+
+ /* unknown / NULL type -> not needed */
+ assert(!enm_vpn_username_needed("wireguard", NULL, NULL));
+ assert(!enm_vpn_username_needed(NULL, NULL, NULL));
+
+ printf("all enm_vpn_username_needed assertions passed\n");
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.