Re: [Openvpn-devel] [PATCH] Post-initialization SELinux support for OpenVPN

2009-08-19 Thread James Yonan

Sebastien Raveau wrote:

Hi everybody!


OpenVPN already has support for dropping privileges and confining
itself to a directory *after* startup (thanks to calls like setgid,
setuid and chroot) which makes for much better management than if you
had to respectively start OpenVPN unprivileged and add the privileges
it (only) needs during startup, or if you chroot'ed OpenVPN before
startup and had to copy the necessary files in the confinement
directory.

The very same problem occurs with SELinux policy enforcement: one can
apply a policy before startup (such as the ready-to-use one provided
by 
http://oss.tresys.com/projects/refpolicy/browser/trunk/policy/modules/services/openvpn.te)
but it is wy too complicated, just because many rights have to be
granted to OpenVPN during its initialization... or one can apply a
very simple SELinux policy to OpenVPN when the only need left is
basically network I/O operations.

The only downside to this is that, just like with setuid() and
chroot(), OpenVPN has to call setcon() itself, which is why I am
submitting this patch :-)

Please note that, while this patch does indeed bring a new dependency
to libselinux in OpenVPN on Linux:
* the feature will of course only be added if detected by ./configure
* libselinux is so common now that even /bin/ls is linked against it
on most Linux systems
so OpenVPN should get SELinux support quite transparently ;-)


Sebastien,

This looks good...  Thanks for putting it together!

A couple things:

Can you adapt the patch to the OpenVPN 2.1 branch?

Can you modify the patch slightly so that no code is added unless #ifdef 
HAVE_SETCON is true?


Thanks,
James



[Openvpn-devel] [PATCH] Post-initialization SELinux support for OpenVPN

2009-06-28 Thread Sebastien Raveau
Hi everybody!


OpenVPN already has support for dropping privileges and confining
itself to a directory *after* startup (thanks to calls like setgid,
setuid and chroot) which makes for much better management than if you
had to respectively start OpenVPN unprivileged and add the privileges
it (only) needs during startup, or if you chroot'ed OpenVPN before
startup and had to copy the necessary files in the confinement
directory.

The very same problem occurs with SELinux policy enforcement: one can
apply a policy before startup (such as the ready-to-use one provided
by 
http://oss.tresys.com/projects/refpolicy/browser/trunk/policy/modules/services/openvpn.te)
but it is wy too complicated, just because many rights have to be
granted to OpenVPN during its initialization... or one can apply a
very simple SELinux policy to OpenVPN when the only need left is
basically network I/O operations.

The only downside to this is that, just like with setuid() and
chroot(), OpenVPN has to call setcon() itself, which is why I am
submitting this patch :-)

Please note that, while this patch does indeed bring a new dependency
to libselinux in OpenVPN on Linux:
* the feature will of course only be added if detected by ./configure
* libselinux is so common now that even /bin/ls is linked against it
on most Linux systems
so OpenVPN should get SELinux support quite transparently ;-)


Best regards,

-- 
Sebastien Raveau
Information Warfare Consultant
http://blog.sebastien.raveau.name/
diff -urN -X generated openvpn-2.0.9.orig/configure.ac openvpn-2.0.9/configure.ac
--- openvpn-2.0.9.orig/configure.ac	2006-10-01 14:18:15.0 +0200
+++ openvpn-2.0.9/configure.ac	2009-06-22 22:42:30.0 +0200
@@ -95,6 +95,12 @@
[DEBUG="yes"]
 )
 
+AC_ARG_ENABLE(selinux,
+   [  --disable-selinux   Disable SELinux support],
+   [SELINUX="$enableval"],
+   [SELINUX="yes"]
+)
+
 AC_ARG_ENABLE(small,
[  --enable-small  Enable smaller executable size (disable OCC, usage message, and verb 4 parm list)],
[SMALL="$enableval"],
@@ -568,6 +574,23 @@
fi
 fi
 
+dnl
+dnl check for SELinux library and headers
+dnl
+if test "$SELINUX" = "yes"; then
+   AC_CHECKING([for libselinux Library and Header files])
+   AC_CHECK_HEADER(selinux/selinux.h,
+  [AC_CHECK_LIB(selinux, setcon,
+ [
+OPENVPN_ADD_LIBS(-lselinux)
+AC_DEFINE(HAVE_SETCON, 1, [SELinux support])
+ ],
+[AC_MSG_RESULT([SELinux library not found.])]
+ )],
+  [AC_MSG_RESULT([SELinux headers not found.])]
+   )
+fi
+
 dnl enable multi-client mode
 if test "$MULTI" = "yes"; then
AC_DEFINE(ENABLE_CLIENT_SERVER, 1, [Enable client/server capability])
diff -urN -X generated openvpn-2.0.9.orig/init.c openvpn-2.0.9/init.c
--- openvpn-2.0.9.orig/init.c	2006-04-05 08:42:32.0 +0200
+++ openvpn-2.0.9/init.c	2009-06-22 22:42:30.0 +0200
@@ -405,6 +405,17 @@
 	{
 	  msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not);
 	}
+
+  /* set SELinux context; doing it after chroot requires /proc
+ to be mounted in the chroot (which is annoying indeed but
+ doing it before requires more complex SELinux policies */
+  if (c->options.selinux_context)
+{
+  if (no_delay)
+do_setcon(c->options.selinux_context);
+  else
+msg (M_INFO, "NOTE: setcon %s", why_not);
+}
 }
 }
 
@@ -1563,8 +1574,8 @@
   if (o->ping_send_timeout && !o->ping_rec_timeout)
 msg (M_WARN, "WARNING: --ping should normally be used with --ping-restart or --ping-exit");
 
-  if ((o->username || o->groupname || o->chroot_dir) && (!o->persist_tun || !o->persist_key))
-msg (M_WARN, "WARNING: you are using user/group/chroot without persist-key/persist-tun -- this may cause restarts to fail");
+  if ((o->username || o->groupname || o->chroot_dir || o->selinux_context) && (!o->persist_tun || !o->persist_key))
+msg (M_WARN, "WARNING: you are using user/group/chroot/setcon without persist-key/persist-tun -- this may cause restarts to fail");
 
 #if P2MP
   if (o->pull && o->ifconfig_local && c->first_time)
diff -urN -X generated openvpn-2.0.9.orig/misc.c openvpn-2.0.9/misc.c
--- openvpn-2.0.9.orig/misc.c	2005-11-05 08:04:22.0 +0100
+++ openvpn-2.0.9/misc.c	2009-06-22 23:00:36.0 +0200
@@ -62,6 +62,25 @@
 }
 }
 
+/* Apply SELinux context in order to restrict what
+   OpenVPN can do to _only_ what it is supposed to
+   do after initialization is complete (basically
+   network I/O operations) */
+void
+do_setcon (const char *context)
+{
+  if (context)
+{
+#ifdef HAVE_SETCON
+  if (-1 == setcon (context))
+msg (M_ERR, "setcon to '%s' failed; is /proc accessible?", context);
+  msg (M_INFO, "setcon to '%s' succeeded", context);
+#else
+  msg (M_FATAL, "Sorry but I can't set SELinux context to '%s' because this operating system doesn't appear to support the setcon() system call", context);
+#endif
+}
+}
+
 /*