[network-manager-openvpn/jk/openvpn-unprivilege-user] service: allow running openvpn as an unprivilege user (bgo #555518)
- From: Jiří Klimeš <jklimes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openvpn/jk/openvpn-unprivilege-user] service: allow running openvpn as an unprivilege user (bgo #555518)
- Date: Mon, 23 Mar 2015 14:58:43 +0000 (UTC)
commit bb8c1787d96d9a27f92e80009a3f7e9f5f282cc0
Author: Jiří Klimeš <jklimes redhat com>
Date: Wed Feb 25 14:02:40 2015 +0100
service: allow running openvpn as an unprivilege user (bgo #555518)
The patch uses --user, --group and --chroot command line parameteres
to do that.
spec change for RPM:
(http://fedoraproject.org/wiki/Packaging:UsersAndGroups)
Requires(pre): shadow-utils
[...]
%pre
getent group nm-openvpn >/dev/null || groupadd -r nm-openvpn
getent passwd nm-openvpn >/dev/null || \
useradd -r -g nm-openvpn -d / -s /sbin/nologin \
-c "Default user for running openvpn spawned by NetworkManager" nm-openvpn
exit 0
https://bugzilla.gnome.org/show_bug.cgi?id=555518
https://bugzilla.redhat.com/show_bug.cgi?id=1195057
src/nm-openvpn-service.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++
src/nm-openvpn-service.h | 5 +++
2 files changed, 96 insertions(+), 0 deletions(-)
---
diff --git a/src/nm-openvpn-service.c b/src/nm-openvpn-service.c
index 4912082..b36c8eb 100644
--- a/src/nm-openvpn-service.c
+++ b/src/nm-openvpn-service.c
@@ -47,6 +47,8 @@
#include <ctype.h>
#include <errno.h>
#include <locale.h>
+#include <pwd.h>
+#include <grp.h>
#include <NetworkManager.h>
#include <NetworkManagerVPN.h>
@@ -867,6 +869,62 @@ update_io_data_from_vpn_setting (NMOpenvpnPluginIOData *io_data,
}
static gboolean
+is_dir_writable (const char *dir, const char *user)
+{
+ struct stat sb;
+ struct passwd *pw;
+
+ if (stat (dir, &sb) == -1)
+ return FALSE;
+ pw = getpwnam (user);
+ if (!pw)
+ return FALSE;
+
+ if (pw->pw_uid == 0)
+ return TRUE;
+
+ if (sb.st_mode & 0002)
+ return TRUE;
+ else if (sb.st_mode & 0020) {
+ /* Group has write access. Is user in that group? */
+ int i, ngroups;
+ gid_t groups[64];
+
+ getgrouplist(user, pw->pw_gid, groups, &ngroups);
+ for (i = 0; i < ngroups; i++) {
+ if (groups[i] == sb.st_gid)
+ return TRUE;
+ }
+ } else if (sb.st_mode & 0200) {
+ /* The owner has write access. Does the user own the file? */
+ if (pw->pw_uid == sb.st_uid)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* Check existence of 'tmp' directory inside @chdir
+ * and write access in @chdir and @chdir/tmp for @user.
+ */
+static gboolean
+check_chroot_dir_usability (const char *chdir, const char *user)
+{
+ char *tmp_dir;
+ gboolean b1, b2;
+
+ tmp_dir = g_strdup_printf ("%s/tmp", chdir);
+ if (!g_file_test (tmp_dir, G_FILE_TEST_IS_DIR)) {
+ g_free (tmp_dir);
+ return FALSE;
+ }
+
+ b1 = is_dir_writable (chdir, user);
+ b2 = is_dir_writable (tmp_dir, user);
+ g_free (tmp_dir);
+ return b1 && b2;
+}
+
+static gboolean
nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
NMSettingVPN *s_vpn,
const char *default_username,
@@ -881,6 +939,7 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
gboolean dev_type_is_tap;
char *stmp;
const char *defport, *proto_tcp;
+ const char *nm_openvpn_user, *nm_openvpn_group, *nm_openvpn_chroot;
/* Find openvpn */
openvpn_binary = nm_find_openvpn ();
@@ -1268,6 +1327,38 @@ nm_openvpn_start_openvpn_binary (NMOpenvpnPlugin *plugin,
return FALSE;
}
+ /* Allow openvpn to be run as a specified user:group and drop privileges. */
+ nm_openvpn_user = getenv ("NM_OPENVPN_USER");
+ nm_openvpn_group = getenv ("NM_OPENVPN_GROUP");
+ nm_openvpn_chroot = getenv ("NM_OPENVPN_CHROOT");
+ if (!nm_openvpn_user)
+ nm_openvpn_user = NM_OPENVPN_USER;
+ if (!nm_openvpn_group)
+ nm_openvpn_group = NM_OPENVPN_GROUP;
+ if (!nm_openvpn_chroot)
+ nm_openvpn_chroot = NM_OPENVPN_CHROOT;
+
+ if (getpwnam (nm_openvpn_user)) {
+ add_openvpn_arg (args, "--user");
+ add_openvpn_arg (args, nm_openvpn_user);
+ } else {
+ g_warning ("User '%s' not found, openvpn will use 'root'.",
+ nm_openvpn_user);
+ nm_openvpn_user = "root";
+ }
+ if (getgrnam (nm_openvpn_group)) {
+ add_openvpn_arg (args, "--group");
+ add_openvpn_arg (args, nm_openvpn_group);
+ } else
+ g_warning ("Group '%s' not found, openvpn will use 'root'.",
+ nm_openvpn_group);
+ if (check_chroot_dir_usability (nm_openvpn_chroot, nm_openvpn_user)) {
+ add_openvpn_arg (args, "--chroot");
+ add_openvpn_arg (args, nm_openvpn_chroot);
+ } else
+ g_warning ("Directory '%s' not usable for chroot by '%s', openvpn will not be chrooted.",
+ nm_openvpn_chroot, nm_openvpn_user);
+
g_ptr_array_add (args, NULL);
if (debug) {
diff --git a/src/nm-openvpn-service.h b/src/nm-openvpn-service.h
index 5493cf5..51e00a7 100644
--- a/src/nm-openvpn-service.h
+++ b/src/nm-openvpn-service.h
@@ -100,6 +100,11 @@
#define NM_OPENVPN_REM_CERT_TLS_CLIENT "client"
#define NM_OPENVPN_REM_CERT_TLS_SERVER "server"
+/* User name and group to run nm-openvpn-service under */
+#define NM_OPENVPN_USER "nm-openvpn"
+#define NM_OPENVPN_GROUP "nm-openvpn"
+#define NM_OPENVPN_CHROOT "/var/lib/openvpn/chroot";
+
typedef struct {
NMVPNPlugin parent;
} NMOpenvpnPlugin;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]