capabilities support
This commit is contained in:
parent
af7f943e05
commit
156363f3de
8 changed files with 91 additions and 0 deletions
|
@ -495,6 +495,9 @@ CHECK_INCLUDE_FILE(sys/stat.h LWS_HAVE_SYS_STAT_H)
|
|||
CHECK_INCLUDE_FILE(sys/types.h LWS_HAVE_SYS_TYPES_H)
|
||||
CHECK_INCLUDE_FILE(unistd.h LWS_HAVE_UNISTD_H)
|
||||
CHECK_INCLUDE_FILE(vfork.h LWS_HAVE_VFORK_H)
|
||||
CHECK_INCLUDE_FILE(sys/capability.h LWS_HAVE_SYS_CAPABILITY_H)
|
||||
|
||||
CHECK_LIBRARY_EXISTS(cap cap_set_flag "" LWS_HAVE_LIBCAP)
|
||||
|
||||
if (LWS_WITH_LIBUV)
|
||||
CHECK_INCLUDE_FILE(uv-version.h LWS_HAVE_UV_VERSION_H)
|
||||
|
@ -1016,6 +1019,12 @@ if (UNIX)
|
|||
list(APPEND LIB_LIST m)
|
||||
endif()
|
||||
|
||||
if (LWS_HAVE_LIBCAP)
|
||||
list(APPEND LIB_LIST cap )
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# Setup the linking for all libs.
|
||||
foreach (lib ${LWS_LIBRARIES})
|
||||
target_link_libraries(${lib} ${LIB_LIST})
|
||||
|
@ -1767,6 +1776,8 @@ message(" LWS_WITH_ZIP_FOPS = ${LWS_WITH_ZIP_FOPS}")
|
|||
message(" LWS_AVOID_SIGPIPE_IGN = ${LWS_AVOID_SIGPIPE_IGN}")
|
||||
message(" LWS_WITH_STATS = ${LWS_WITH_STATS}")
|
||||
message(" LWS_WITH_SOCKS5 = ${LWS_WITH_SOCKS5}")
|
||||
message(" LWS_HAVE_SYS_CAPABILITY_H = ${LWS_HAVE_SYS_CAPABILITY_H}")
|
||||
message(" LWS_HAVE_LIBCAP = ${LWS_HAVE_LIBCAP}")
|
||||
|
||||
message("---------------------------------------------------------------------")
|
||||
|
||||
|
|
|
@ -122,12 +122,25 @@ and libnsl, and only builds in 64bit mode.
|
|||
$ make
|
||||
```
|
||||
|
||||
@section lcap Linux Capabilities
|
||||
|
||||
On Linux, lws now lets you retain selected root capabilities when dropping
|
||||
privileges. If libcap-dev or similar package is installed providing
|
||||
sys/capabilities.h, and libcap or similar package is installed providing
|
||||
libcap.so, CMake will enable the capability features.
|
||||
|
||||
The context creation info struct .caps[] and .count_caps members can then
|
||||
be set by user code to enable selected root capabilities to survive the
|
||||
transition to running under an unprivileged user.
|
||||
|
||||
@section cmq Quirk of cmake
|
||||
|
||||
When changing cmake options, for some reason the only way to get it to see the
|
||||
changes sometimes is delete the contents of your build directory and do the
|
||||
cmake from scratch.
|
||||
|
||||
deleting build/CMakeCache.txt may be enough.
|
||||
|
||||
|
||||
@section cmw Building on Windows (Visual Studio)
|
||||
|
||||
|
|
|
@ -892,6 +892,11 @@ lws_create_context(struct lws_context_creation_info *info)
|
|||
context->uid = info->uid;
|
||||
context->gid = info->gid;
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
memcpy(context->caps, info->caps, sizeof(context->caps));
|
||||
context->count_caps = info->count_caps;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* drop any root privs for this process
|
||||
* to listen on port < 1023 we would have needed root, but now we are
|
||||
|
|
|
@ -2220,6 +2220,11 @@ lws_finalize_startup(struct lws_context *context)
|
|||
info.uid = context->uid;
|
||||
info.gid = context->gid;
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
memcpy(info.caps, context->caps, sizeof(info.caps));
|
||||
info.count_caps = context->count_caps;
|
||||
#endif
|
||||
|
||||
if (lws_check_opt(context->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
|
||||
lws_plat_drop_app_privileges(&info);
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ struct sockaddr_in;
|
|||
|
||||
#else /* NOT WIN32 */
|
||||
#include <unistd.h>
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
#include <sys/capability.h>
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#include <netinet/in.h>
|
||||
|
@ -1976,6 +1979,18 @@ struct lws_context_creation_info {
|
|||
* If proxy auth is required, use format "username:password\@server:port" */
|
||||
unsigned int socks_proxy_port;
|
||||
/**< VHOST: If socks_proxy_address was non-NULL, uses this port */
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
cap_value_t caps[4];
|
||||
/**< CONTEXT: array holding Linux capabilities you want to
|
||||
* continue to be available to the server after it transitions
|
||||
* to a noprivileged user. Usually none are needed but for, eg,
|
||||
* .bind_iface, CAP_NET_RAW is required. This gives you a way
|
||||
* to still have the capability but drop root.
|
||||
*/
|
||||
char count_caps;
|
||||
/**< CONTEXT: count of Linux capabilities in .caps[]. 0 means
|
||||
* no capabilities will be inherited from root (the default) */
|
||||
#endif
|
||||
|
||||
/* Add new things just above here ---^
|
||||
* This is part of the ABI, don't needlessly break compatibility
|
||||
|
|
|
@ -279,9 +279,29 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
static void
|
||||
_lws_plat_apply_caps(int mode, cap_value_t *cv, int count)
|
||||
{
|
||||
cap_t caps = cap_get_proc();
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
cap_set_flag(caps, mode, count, cv, CAP_SET);
|
||||
cap_set_proc(caps);
|
||||
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
|
||||
cap_free(caps);
|
||||
}
|
||||
#endif
|
||||
|
||||
LWS_VISIBLE void
|
||||
lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
||||
{
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
int n;
|
||||
#endif
|
||||
|
||||
if (info->gid != -1)
|
||||
if (setgid(info->gid))
|
||||
lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
|
||||
|
@ -290,11 +310,25 @@ lws_plat_drop_app_privileges(struct lws_context_creation_info *info)
|
|||
struct passwd *p = getpwuid(info->uid);
|
||||
|
||||
if (p) {
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
_lws_plat_apply_caps(CAP_PERMITTED, info->caps, info->count_caps);
|
||||
#endif
|
||||
|
||||
initgroups(p->pw_name, info->gid);
|
||||
if (setuid(info->uid))
|
||||
lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
|
||||
else
|
||||
lwsl_notice("Set privs to user '%s'\n", p->pw_name);
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
_lws_plat_apply_caps(CAP_EFFECTIVE, info->caps, info->count_caps);
|
||||
|
||||
if (info->count_caps)
|
||||
for (n = 0; n < info->count_caps; n++)
|
||||
lwsl_notice(" RETAINING CAPABILITY %d\n", (int)info->caps[n]);
|
||||
#endif
|
||||
|
||||
} else
|
||||
lwsl_warn("getpwuid: unable to find uid %d", info->uid);
|
||||
}
|
||||
|
|
|
@ -935,6 +935,11 @@ struct lws_context {
|
|||
const struct lws_protocol_vhost_options *reject_service_keywords;
|
||||
lws_reload_func deprecation_cb;
|
||||
|
||||
#if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
|
||||
cap_value_t caps[4];
|
||||
char count_caps;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_USE_LIBEV)
|
||||
lws_ev_signal_cb_t * lws_ev_sigint_cb;
|
||||
#endif
|
||||
|
|
|
@ -136,6 +136,9 @@
|
|||
#cmakedefine LWS_WITH_STATS
|
||||
#cmakedefine LWS_WITH_SOCKS5
|
||||
|
||||
#cmakedefine LWS_HAVE_SYS_CAPABILITY_H
|
||||
#cmakedefine LWS_HAVE_LIBCAP
|
||||
|
||||
/* OpenSSL various APIs */
|
||||
|
||||
#cmakedefine LWS_HAVE_TLS_CLIENT_METHOD
|
||||
|
|
Loading…
Add table
Reference in a new issue