| /* |
| * libwebsockets - small server side websockets and web server implementation |
| * |
| * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com> |
| * |
| * 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 <pwd.h> |
| #include <grp.h> |
| |
| #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 CAPABILITY %d\n", |
| (int)info->caps[n]); |
| } |
| #endif |
| |
| } else |
| lwsl_warn("getpwuid: unable to find uid %d", info->uid); |
| } |
| } |