unix-caps.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2018 Andy Green <[email protected]>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #define _GNU_SOURCE
  22. #include "core/private.h"
  23. #include <pwd.h>
  24. #include <grp.h>
  25. #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
  26. static void
  27. _lws_plat_apply_caps(int mode, const cap_value_t *cv, int count)
  28. {
  29. cap_t caps;
  30. if (!count)
  31. return;
  32. caps = cap_get_proc();
  33. cap_set_flag(caps, mode, count, cv, CAP_SET);
  34. cap_set_proc(caps);
  35. prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
  36. cap_free(caps);
  37. }
  38. #endif
  39. void
  40. lws_plat_drop_app_privileges(const struct lws_context_creation_info *info)
  41. {
  42. if (info->gid && info->gid != -1)
  43. if (setgid(info->gid))
  44. lwsl_warn("setgid: %s\n", strerror(LWS_ERRNO));
  45. if (info->uid && info->uid != -1) {
  46. struct passwd *p = getpwuid(info->uid);
  47. if (p) {
  48. #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
  49. _lws_plat_apply_caps(CAP_PERMITTED, info->caps,
  50. info->count_caps);
  51. #endif
  52. initgroups(p->pw_name, info->gid);
  53. if (setuid(info->uid))
  54. lwsl_warn("setuid: %s\n", strerror(LWS_ERRNO));
  55. else
  56. lwsl_notice("Set privs to user '%s'\n",
  57. p->pw_name);
  58. #if defined(LWS_HAVE_SYS_CAPABILITY_H) && defined(LWS_HAVE_LIBCAP)
  59. _lws_plat_apply_caps(CAP_EFFECTIVE, info->caps,
  60. info->count_caps);
  61. if (info->count_caps) {
  62. int n;
  63. for (n = 0; n < info->count_caps; n++)
  64. lwsl_notice(" RETAINING CAP %d\n",
  65. (int)info->caps[n]);
  66. }
  67. #endif
  68. } else
  69. lwsl_warn("getpwuid: unable to find uid %d", info->uid);
  70. }
  71. }