jimklimov

Backport of https://github.com/maekitalo/tntnet/pull/52

Nov 11th, 2016
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.65 KB | None | 0 0
  1. tntnet-2.2.1-allUserGroups.patch : this is a backport of tntnet improvement "When doing setuid(), optionally also pick up supplementary groups of that user" posted by me in PR https://github.com/maekitalo/tntnet/pull/52 so this can be applied to the current release tarball.
  2. Copyright (C) Nov 2016 by Jim Klimov <EvgenyKlimov@eaton.com>
  3.  
  4. diff -Naur tntnet-2.2.1.orig/configure.in tntnet-2.2.1/configure.in
  5. --- tntnet-2.2.1.orig/configure.in  2014-01-17 20:07:21.000000000 +0100
  6. +++ tntnet-2.2.1/configure.in   2016-11-10 20:53:55.805453772 +0100
  7. @@ -41,6 +41,30 @@
  8.  AC_CHECK_FUNCS([fopen64], ,[AM_CFLAGS=-DUSE_FILE32API])
  9.  AC_SUBST(AM_CFLAGS)
  10.  
  11. +AC_MSG_CHECKING([if system provides getgrouplist() with semantics we expect])
  12. +AC_COMPILE_IFELSE(
  13. +    [AC_LANG_SOURCE([
  14. +#include <grp.h>
  15. +#include <pwd.h>
  16. +struct passwd pw;
  17. +gid_t groups;
  18. +int foundgroups = 1;
  19. +int gotgroups = getgrouplist("username", pw.pw_gid, &groups, &foundgroups);
  20. +])], AC_DEFINE(HAVE_GETGROUPLIST, [1], [Defined if system provides getgrouplist() with semantics we expect])
  21. +     AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]))
  22. +
  23. +AC_MSG_CHECKING([if system provides setgroups() with semantics we expect])
  24. +AC_COMPILE_IFELSE(
  25. +    [AC_LANG_SOURCE([
  26. +#include <sys/types.h>
  27. +#include <unistd.h>
  28. +#include <grp.h>
  29. +#include <pwd.h>
  30. +gid_t groups;
  31. +int errcode = setgroups(1, &groups);
  32. +])], AC_DEFINE(HAVE_SETGROUPS, [1], [Defined if system provides setgroups() with semantics we expect])
  33. +     AC_MSG_RESULT([yes]), AC_MSG_RESULT([no]))
  34. +
  35.  AC_ARG_WITH([epoll],
  36.    AS_HELP_STRING([--with-epoll=yes|no|probe], [use epoll]),
  37.    [epoll_option=$withval],
  38. diff -Naur tntnet-2.2.1.orig/doc/man/tntnet.xml.7 tntnet-2.2.1/doc/man/tntnet.xml.7
  39. --- tntnet-2.2.1.orig/doc/man/tntnet.xml.7  2014-01-17 20:07:21.000000000 +0100
  40. +++ tntnet-2.2.1/doc/man/tntnet.xml.7   2016-11-10 20:53:55.805453772 +0100
  41. @@ -32,4 +32,12 @@
  42.  .RE
  43.  .PP
  44. +\fB\fC<allUserGroups>\fR\fIyes|no\fP\fB\fC</allUserGroups>\fR
  45. +.IP
  46. +Specifies that if the \fI<user>\fP is changed for the server process, then the
  47. +groups (primary and secondary) which this account is a member of should
  48. +become the primary GID and supplementary GIDs of this process too.
  49. +.IP
  50. +The legacy default value is \fIno\fP - to avoid surprises during upgrades.
  51. +.PP
  52.  \fB\fC<bufferSize>\fR\fIbytes\fP\fB\fC</bufferSize>\fR
  53.  .IP
  54. diff -Naur tntnet-2.2.1.orig/framework/common/tnt/tntconfig.h tntnet-2.2.1/framework/common/tnt/tntconfig.h
  55. --- tntnet-2.2.1.orig/framework/common/tnt/tntconfig.h  2014-01-17 20:07:21.000000000 +0100
  56. +++ tntnet-2.2.1/framework/common/tnt/tntconfig.h   2016-11-10 20:53:55.806364580 +0100
  57. @@ -81,6 +81,7 @@
  58.      unsigned maxRequestSize;
  59.      unsigned maxRequestTime;
  60.      std::string user;
  61. +    bool allUserGroups;
  62.      std::string group;
  63.      std::string dir;
  64.      std::string chrootdir;
  65. diff -Naur tntnet-2.2.1.orig/framework/common/tntconfig.cpp tntnet-2.2.1/framework/common/tntconfig.cpp
  66. --- tntnet-2.2.1.orig/framework/common/tntconfig.cpp    2014-01-17 20:07:21.000000000 +0100
  67. +++ tntnet-2.2.1/framework/common/tntconfig.cpp 2016-11-10 20:53:55.806725535 +0100
  68. @@ -112,6 +112,7 @@
  69.      si.getMember("maxRequestSize", config.maxRequestSize);
  70.      si.getMember("maxRequestTime", config.maxRequestTime);
  71.      si.getMember("user", config.user);
  72. +    si.getMember("allUserGroups", config.allUserGroups);
  73.      si.getMember("group", config.group);
  74.      si.getMember("dir", config.dir);
  75.      si.getMember("chrootdir", config.chrootdir);
  76. @@ -217,6 +217,7 @@ namespace tnt
  77.    TntConfig::TntConfig()
  78.      : maxRequestSize(0),
  79.        maxRequestTime(600),
  80. +      allUserGroups(false),
  81.        daemon(false),
  82.        minThreads(5),
  83.        maxThreads(100),
  84. diff -Naur tntnet-2.2.1.orig/framework/runtime/process.cpp tntnet-2.2.1/framework/runtime/process.cpp
  85. --- tntnet-2.2.1.orig/framework/runtime/process.cpp 2013-12-26 19:11:56.000000000 +0100
  86. +++ tntnet-2.2.1/framework/runtime/process.cpp  2016-11-10 20:53:55.807163455 +0100
  87. @@ -27,6 +27,7 @@
  88.   */
  89.  
  90.  
  91. +#include "config.h"
  92.  #include "tnt/process.h"
  93.  #include "tnt/tntconfig.h"
  94.  #include <cxxtools/systemerror.h>
  95. @@ -72,12 +72,104 @@
  96.        throw cxxtools::SystemError("setgid");
  97.    }
  98.  
  99. +#if (HAVE_GETGROUPLIST != 1)
  100. +// Code below snatched from https://gist.github.com/bhaskarvk/6a15083ab9a7997df0a2
  101. +#include <string.h>
  102. +int
  103. +getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
  104. +{
  105. +    const struct group *grp;
  106. +    int i, maxgroups, ngroups, ret;
  107. +
  108. +    ret = 0;
  109. +    ngroups = 0;
  110. +    maxgroups = *grpcnt;
  111. +    /*
  112. +     * When installing primary group, duplicate it;
  113. +     * the first element of groups is the effective gid
  114. +     * and will be overwritten when a setgid file is executed.
  115. +     */
  116. +    groups ? groups[ngroups++] = agroup : ngroups++;
  117. +    if (maxgroups > 1)
  118. +        groups ? groups[ngroups++] = agroup : ngroups++;
  119. +    /*
  120. +     * Scan the group file to find additional groups.
  121. +     */
  122. +    setgrent();
  123. +    while ((grp = getgrent()) != NULL) {
  124. +        if (groups) {
  125. +            for (i = 0; i < ngroups; i++) {
  126. +                if (grp->gr_gid == groups[i])
  127. +                    goto skip;
  128. +            }
  129. +        }
  130. +        for (i = 0; grp->gr_mem[i]; i++) {
  131. +            if (!strcmp(grp->gr_mem[i], uname)) {
  132. +                if (ngroups >= maxgroups) {
  133. +                    ret = -1;
  134. +                    break;
  135. +                }
  136. +                groups ? groups[ngroups++] = grp->gr_gid : ngroups++;
  137. +                break;
  138. +            }
  139. +        }
  140. +skip:
  141. +        ;
  142. +    }
  143. +    endgrent();
  144. +    *grpcnt = ngroups;
  145. +    return (ret);
  146. +}
  147. +#define HAVE_GETGROUPLIST 1
  148. +#endif // no HAVE_GETGROUPLIST
  149. +
  150. -  void setUser(const std::string& user)
  151. +  void setUser(const std::string& user, bool allUserGroups)
  152.    {
  153.      struct passwd * pw = getpwnam(user.c_str());
  154.      if (pw == 0)
  155.        throw std::runtime_error("unknown user " + user);
  156.  
  157. +    if (allUserGroups)
  158. +    {
  159. +#if (HAVE_GETGROUPLIST == 1) && (HAVE_SETGROUPS == 1)
  160. +        std::stringstream message;
  161. +        int ngroups = 0;
  162. +        int foundgroups = 0;
  163. +        int foundgroups2 = 0;
  164. +        gid_t tmp_group;
  165. +        ngroups = getgrouplist(user.c_str(), pw->pw_gid, &tmp_group, &foundgroups);
  166. +        if (foundgroups > 0) {
  167. +            gid_t *groups = (gid_t *)malloc(foundgroups * sizeof(gid_t));
  168. +            if (groups != NULL) {
  169. +                foundgroups2 = foundgroups;
  170. +                ngroups = getgrouplist(user.c_str(), pw->pw_gid, groups, &foundgroups);
  171. +                if ( ngroups > 0 && ngroups == foundgroups && foundgroups2 == foundgroups ) {
  172. +                    log_debug("set " << ngroups << " supplementary groups of user " << user << '(' << pw->pw_uid << ')');
  173. +                    setgroups (ngroups, groups);
  174. +                } else {
  175. +                    message << "could not getgrouplist() second time: retrieved " << ngroups << ", found " << foundgroups << ", earlier found " << foundgroups2;
  176. +                    //throw std::runtime_error(message.str());
  177. +                    log_error(message.str());
  178. +                }
  179. +                free(groups);
  180. +            } else {
  181. +                message << "could not malloc for " << foundgroups << " supplementary groups";
  182. +                // throw std::runtime_error( message.str() );
  183. +                log_error(message.str());
  184. +            // throw std::runtime_error(message.str());
  185. +            log_error(message.str());
  186. +        }
  187. +#else
  188. +    // throw std::runtime_error("allUserGroups was requested, but support was not compiled in on this platform");
  189. +    log_error("allUserGroups was requested, but support was not compiled in on this platform");
  190. +#endif
  191. +    } else {
  192. +        log_debug("allUserGroups not requested, so not setting supplementary groups of user " << user << '(' << pw->pw_uid << ')');
  193. +    }
  194. +
  195.      log_debug("change user to " << user << '(' << pw->pw_uid << ')');
  196.  
  197.      int ret = ::setuid(pw->pw_uid);
  198. @@ -85,6 +100,15 @@
  199.        throw cxxtools::SystemError("getuid");
  200.    }
  201.  
  202. +#ifdef __GNUC__
  203. +    // Function with legacy signature is not directly used here now
  204. +    void setUser(const std::string& user)    __attribute__ ((unused)) ;
  205. +#endif
  206. +  void setUser(const std::string& user)
  207. +  {
  208. +    setUser(user, false);
  209. +  }
  210. +
  211.    void setDir(const std::string& dir)
  212.    {
  213.      log_debug("chdir(" << dir << ')');
  214. @@ -289,7 +308,7 @@
  215.      if (!tnt::TntConfig::it().user.empty())
  216.      {
  217.        log_debug("set user to \"" << tnt::TntConfig::it().user << '"');
  218. -      ::setUser(tnt::TntConfig::it().user);
  219. +      ::setUser(tnt::TntConfig::it().user, tnt::TntConfig::it().allUserGroups);
  220.      }
  221.  
  222.      if (!tnt::TntConfig::it().dir.empty())
  223. diff -Naur tntnet-2.2.1.orig/sdk/demos/controls/tntnet.xml tntnet-2.2.1/sdk/demos/controls/tntnet.xml
  224. --- tntnet-2.2.1.orig/sdk/demos/controls/tntnet.xml 2014-01-17 20:08:24.000000000 +0100
  225. +++ tntnet-2.2.1/sdk/demos/controls/tntnet.xml  2016-11-10 20:53:55.807455155 +0100
  226. @@ -57,6 +57,7 @@
  227.    <!-- <maxRequestSize>65536</maxRequestSize> -->
  228.    <!-- <maxRequestTime>600</maxRequestTime> -->
  229.    <!-- <user>tntnet</user> -->
  230. +  <!-- <allUserGroups>no</allUserGroups> -->
  231.    <!-- <group>tntnet</group> -->
  232.    <!-- <dir>/</dir> -->
  233.    <!-- <chrootdir>/var/safedir</chrootdir> -->
  234. diff -Naur tntnet-2.2.1.orig/tntnet-conf2xml.pl tntnet-2.2.1/tntnet-conf2xml.pl
  235. --- tntnet-2.2.1.orig/tntnet-conf2xml.pl    2013-12-26 15:08:34.000000000 +0100
  236. +++ tntnet-2.2.1/tntnet-conf2xml.pl 2016-11-10 20:53:55.807753679 +0100
  237. @@ -21,6 +21,7 @@
  238.      MaxRequestSize => 'maxRequestSize',
  239.      MaxRequestTime => 'maxRequestTime',
  240.      User => 'user',
  241. +    AllUserGroups => 'allUserGroups',
  242.      Group => 'group',
  243.      Dir => 'dir',
  244.      Chroot => 'chrootdir',
Add Comment
Please, Sign In to add comment