NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
privilege-helper.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2019, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "privilege-helper.hpp"
27 #include "core/logger.hpp"
28 
29 #include <pwd.h>
30 #include <grp.h>
31 
32 namespace nfd {
33 
35 
36 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
37 uid_t PrivilegeHelper::s_normalUid = ::geteuid();
38 gid_t PrivilegeHelper::s_normalGid = ::getegid();
39 
40 uid_t PrivilegeHelper::s_privilegedUid = ::geteuid();
41 gid_t PrivilegeHelper::s_privilegedGid = ::getegid();
42 #endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
43 
44 void
45 PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
46 {
47 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
48  static const size_t MAX_GROUP_BUFFER_SIZE = 16384; // 16 KiB
49  static const size_t MAX_PASSWD_BUFFER_SIZE = 16384;
50 
51  static const size_t FALLBACK_GROUP_BUFFER_SIZE = 1024;
52  static const size_t FALLBACK_PASSWD_BUFFER_SIZE = 1024;
53 
54  NFD_LOG_TRACE("initializing with user \"" << userName << "\""
55  << " group \"" << groupName << "\"");
56 
57  // workflow from man getpwnam_r
58 
59  if (!groupName.empty()) {
60  static long groupSize = ::sysconf(_SC_GETGR_R_SIZE_MAX);
61 
62  if (groupSize == -1)
63  groupSize = FALLBACK_GROUP_BUFFER_SIZE;
64 
65  std::vector<char> groupBuffer(static_cast<size_t>(groupSize));
66  struct group group;
67  struct group* groupResult = nullptr;
68 
69  int errorCode = getgrnam_r(groupName.data(), &group,
70  groupBuffer.data(), groupBuffer.size(), &groupResult);
71 
72  while (errorCode == ERANGE) {
73  if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
74  throw Error("Cannot allocate large enough buffer for struct group");
75 
76  groupBuffer.resize(groupBuffer.size() * 2);
77  errorCode = getgrnam_r(groupName.data(), &group,
78  groupBuffer.data(), groupBuffer.size(), &groupResult);
79  }
80 
81  if (errorCode != 0 || !groupResult)
82  throw Error("Failed to get gid for \"" + groupName + "\"");
83 
84  s_normalGid = group.gr_gid;
85  }
86 
87  if (!userName.empty()) {
88  static long passwdSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
89 
90  if (passwdSize == -1)
91  passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
92 
93  std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
94  struct passwd passwd;
95  struct passwd* passwdResult = nullptr;
96 
97  int errorCode = getpwnam_r(userName.data(), &passwd,
98  passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
99 
100  while (errorCode == ERANGE) {
101  if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
102  throw Error("Cannot allocate large enough buffer for struct passwd");
103 
104  passwdBuffer.resize(passwdBuffer.size() * 2);
105  errorCode = getpwnam_r(userName.data(), &passwd,
106  passwdBuffer.data(), passwdBuffer.size(), &passwdResult);
107  }
108 
109  if (errorCode != 0 || !passwdResult)
110  throw Error("Failed to get uid for \"" + userName + "\"");
111 
112  s_normalUid = passwd.pw_uid;
113  }
114 #else
115  if (!userName.empty() || !groupName.empty()) {
116  throw Error("Dropping and raising privileges is not supported on this platform");
117  }
118 #endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
119 }
120 
121 void
123 {
124 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
125  if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
126  return;
127 
128  NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
129  if (::setegid(s_normalGid) != 0)
130  throw Error("Failed to drop to effective gid=" + to_string(s_normalGid));
131 
132  NFD_LOG_TRACE("dropping to effective uid=" << s_normalUid);
133  if (::seteuid(s_normalUid) != 0)
134  throw Error("Failed to drop to effective uid=" + to_string(s_normalUid));
135 
136  NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
137 #else
138  NFD_LOG_WARN("Dropping privileges is not supported on this platform");
139 #endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
140 }
141 
142 void
143 PrivilegeHelper::raise()
144 {
145 #ifdef HAVE_PRIVILEGE_DROP_AND_ELEVATE
146  if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
147  return;
148 
149  NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
150  if (::seteuid(s_privilegedUid) != 0)
151  throw Error("Failed to elevate to effective uid=" + to_string(s_privilegedUid));
152 
153  NFD_LOG_TRACE("elevating to effective gid=" << s_privilegedGid);
154  if (::setegid(s_privilegedGid) != 0)
155  throw Error("Failed to elevate to effective gid=" + to_string(s_privilegedGid));
156 
157  NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
158 #else
159  NFD_LOG_WARN("Elevating privileges is not supported on this platform");
160 #endif // HAVE_PRIVILEGE_DROP_AND_ELEVATE
161 }
162 
163 } // namespace nfd
#define NFD_LOG_WARN
Definition: logger.hpp:40
represents a serious seteuid/gid failure
#define NFD_LOG_INFO
Definition: logger.hpp:39
static void initialize(const std::string &userName, const std::string &groupName)
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
#define NFD_LOG_TRACE
Definition: logger.hpp:37
std::string to_string(const V &v)
Definition: backports.hpp:67
#define NFD_LOG_INIT(name)
Definition: logger.hpp:31