/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010-2018 Andy Green * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #define _GNU_SOURCE #include "core/private.h" #include #include #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP) static void _lws_plat_apply_caps(int mode, const cap_value_t *cv, int count) { cap_t caps; if (!count) return; caps = cap_get_proc(); 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 void lws_plat_drop_app_privileges(const struct lws_context_creation_info *info) { if (info->gid && info->gid != -1) if (setgid(info->gid)) lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO)); if (info->uid && info->uid != -1) { 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) { int n; for (n = 0; n < info->count_caps; n++) lwsl_notice(" RETAINING CAP %d\n", (int)info->caps[n]); } #endif } else lwsl_warn("getpwuid: unable to find uid %d", info->uid); } }