diff options
author | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2009-09-04 23:50:35 +0000 |
---|---|---|
committer | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2009-09-04 23:50:35 +0000 |
commit | 9938544706154aa7849596f68204d152aa564154 (patch) | |
tree | e50f3c9935ee51654eac8b565111f9eff008e1e8 | |
parent | Added new ./configure flags: (diff) | |
download | openvpn-9938544706154aa7849596f68204d152aa564154.tar.xz |
Added "setcon" directive for interoperability with SELinux
(Sebastien Raveau).
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4932 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r-- | configure.ac | 23 | ||||
-rw-r--r-- | init.c | 32 | ||||
-rw-r--r-- | openvpn.8 | 33 | ||||
-rw-r--r-- | options.c | 13 | ||||
-rw-r--r-- | options.h | 3 | ||||
-rw-r--r-- | syshead.h | 4 |
6 files changed, 104 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac index ae40458..116ff7c 100644 --- a/configure.ac +++ b/configure.ac @@ -206,6 +206,12 @@ AC_ARG_ENABLE(strict-options, [STRICT_OPTIONS="no"] ) +AC_ARG_ENABLE(selinux, + [ --disable-selinux Disable SELinux support], + [SELINUX="$enableval"], + [SELINUX="yes"] +) + AC_ARG_WITH(ssl-headers, [ --with-ssl-headers=DIR Crypto/SSL Include files location], [CS_HDR_DIR="$withval"] @@ -863,6 +869,23 @@ if test "$PASSWORD_SAVE" = "yes"; then AC_DEFINE(ENABLE_PASSWORD_SAVE, 1, [Allow --askpass and --auth-user-pass passwords to be read from a file]) 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 + TAP_ID="PRODUCT_TAP_ID" TAP_WIN32_MIN_MAJOR="PRODUCT_TAP_WIN32_MIN_MAJOR" TAP_WIN32_MIN_MINOR="PRODUCT_TAP_WIN32_MIN_MINOR" @@ -667,7 +667,7 @@ possibly_become_daemon (const struct options *options, const bool first_time) } /* - * Actually do UID/GID downgrade, and chroot, if requested. + * Actually do UID/GID downgrade, chroot and SELinux context switching, if requested. */ static void do_uid_gid_chroot (struct context *c, bool no_delay) @@ -697,6 +697,26 @@ do_uid_gid_chroot (struct context *c, bool no_delay) { msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not); } + +#ifdef HAVE_SETCON + /* Apply a SELinux context in order to restrict what OpenVPN can do + * to _only_ what it is supposed to do after initialization is complete + * (basically just network I/O operations). 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) { + if (-1 == setcon (c->options.selinux_context)) + msg (M_ERR, "setcon to '%s' failed; is /proc accessible?", c->options.selinux_context); + else + msg (M_INFO, "setcon to '%s' succeeded", c->options.selinux_context); + } + else + msg (M_INFO, "NOTE: setcon %s", why_not); + } +#endif } } @@ -1964,16 +1984,20 @@ do_option_warnings (struct context *c) 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) + if (o->username || o->groupname || o->chroot_dir +#ifdef HAVE_SETCON + || o->selinux_context +#endif + ) { if (!o->persist_tun) - msg (M_WARN, "WARNING: you are using user/group/chroot without persist-tun -- this may cause restarts to fail"); + msg (M_WARN, "WARNING: you are using user/group/chroot/setcon without persist-tun -- this may cause restarts to fail"); if (!o->persist_key #ifdef ENABLE_PKCS11 && !o->pkcs11_id #endif ) - msg (M_WARN, "WARNING: you are using user/group/chroot without persist-key -- this may cause restarts to fail"); + msg (M_WARN, "WARNING: you are using user/group/chroot/setcon without persist-key -- this may cause restarts to fail"); } if (o->chroot_dir && !(o->username && o->groupname)) @@ -1889,6 +1889,39 @@ complications can result when scripts or restarts are executed after the chroot operation. .\"********************************************************* .TP +.B --setcon context +Apply SELinux +.B context +after initialization. This +essentially provides the ability to restrict OpenVPN's +rights to only network I/O operations, thanks to +SELinux. This goes further than +.B --user +and +.B --chroot +in that those two, while being great security features, +unfortunately do not protect against privilege escalation +by exploitation of a vulnerable system call. You can of +course combine all three, but please note that since +setcon requires access to /proc you will have to provide +it inside the chroot directory (e.g. with mount --bind). + +Since the setcon operation is delayed until after +initialization, OpenVPN can be restricted to just +network-related system calls, whereas by applying the +context before startup (such as the OpenVPN one provided +in the SELinux Reference Policies) you will have to +allow many things required only during initialization. + +Like with chroot, complications can result when scripts +or restarts are executed after the setcon operation, +which is why you should really consider using the +.B --persist-key +and +.B --persist-tun +options. +.\"********************************************************* +.TP .B --daemon [progname] Become a daemon after all initialization functions are completed. This option will cause all message and error output to @@ -265,6 +265,9 @@ static const char usage_message[] = "--user user : Set UID to user after initialization.\n" "--group group : Set GID to group after initialization.\n" "--chroot dir : Chroot to this directory after initialization.\n" +#ifdef HAVE_SETCON + "--setcon context: Apply this SELinux context after initialization.\n" +#endif "--cd dir : Change to this directory before initialization.\n" "--daemon [name] : Become a daemon after initialization.\n" " The optional 'name' parameter will be passed\n" @@ -1216,6 +1219,9 @@ show_settings (const struct options *o) SHOW_STR (groupname); SHOW_STR (chroot_dir); SHOW_STR (cd_dir); +#ifdef HAVE_SETCON + SHOW_STR (selinux_context); +#endif SHOW_STR (writepid); SHOW_STR (up_script); SHOW_STR (down_script); @@ -3710,6 +3716,13 @@ add_option (struct options *options, } options->cd_dir = p[1]; } +#ifdef HAVE_SETCON + else if (streq (p[0], "setcon") && p[1]) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->selinux_context = p[1]; + } +#endif else if (streq (p[0], "writepid") && p[1]) { VERIFY_PERMISSION (OPT_P_GENERAL); @@ -253,6 +253,9 @@ struct options const char *groupname; const char *chroot_dir; const char *cd_dir; +#ifdef HAVE_SETCON + char *selinux_context; +#endif const char *writepid; const char *up_script; const char *down_script; @@ -180,6 +180,10 @@ #include <sys/epoll.h> #endif +#ifdef HAVE_SETCON +#include <selinux/selinux.h> +#endif + #ifdef TARGET_SOLARIS #ifdef HAVE_STRINGS_H #include <strings.h> |