NFD: Named Data Networking Forwarding Daemon 24.07-28-gdcc0e6e0
Loading...
Searching...
No Matches
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-2024, 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
27#include "common/logger.hpp"
28
29#include <pwd.h>
30#include <grp.h>
31
32namespace nfd {
33
34NFD_LOG_INIT(PrivilegeHelper);
35
36#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
37uid_t PrivilegeHelper::s_normalUid = ::geteuid();
38gid_t PrivilegeHelper::s_normalGid = ::getegid();
39
40uid_t PrivilegeHelper::s_privilegedUid = ::geteuid();
41gid_t PrivilegeHelper::s_privilegedGid = ::getegid();
42#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
43
44void
45PrivilegeHelper::initialize(const std::string& userName, const std::string& groupName)
46{
47#ifdef NFD_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 group gr;
67 group* grResult = nullptr;
68
69 int errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
70
71 while (errorCode == ERANGE) {
72 if (groupBuffer.size() * 2 > MAX_GROUP_BUFFER_SIZE)
73 throw Error("Cannot allocate large enough buffer for struct group");
74
75 groupBuffer.resize(groupBuffer.size() * 2);
76 errorCode = getgrnam_r(groupName.data(), &gr, groupBuffer.data(), groupBuffer.size(), &grResult);
77 }
78
79 if (errorCode != 0 || !grResult)
80 throw Error("Failed to get gid for \"" + groupName + "\"");
81
82 s_normalGid = gr.gr_gid;
83 }
84
85 if (!userName.empty()) {
86 static long passwdSize = ::sysconf(_SC_GETPW_R_SIZE_MAX);
87
88 if (passwdSize == -1)
89 passwdSize = FALLBACK_PASSWD_BUFFER_SIZE;
90
91 std::vector<char> passwdBuffer(static_cast<size_t>(passwdSize));
92 passwd pw;
93 passwd* pwResult = nullptr;
94
95 int errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
96
97 while (errorCode == ERANGE) {
98 if (passwdBuffer.size() * 2 > MAX_PASSWD_BUFFER_SIZE)
99 throw Error("Cannot allocate large enough buffer for struct passwd");
100
101 passwdBuffer.resize(passwdBuffer.size() * 2);
102 errorCode = getpwnam_r(userName.data(), &pw, passwdBuffer.data(), passwdBuffer.size(), &pwResult);
103 }
104
105 if (errorCode != 0 || !pwResult)
106 throw Error("Failed to get uid for \"" + userName + "\"");
107
108 s_normalUid = pw.pw_uid;
109 }
110#else
111 if (!userName.empty() || !groupName.empty()) {
112 throw Error("Dropping and raising privileges is not supported on this platform");
113 }
114#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
115}
116
117void
119{
120#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
121 if (::geteuid() == s_normalUid && ::getegid() == s_normalGid)
122 return;
123
124 NFD_LOG_TRACE("dropping to effective gid=" << s_normalGid);
125 if (::setegid(s_normalGid) != 0)
126 throw Error("Failed to drop to effective gid=" + std::to_string(s_normalGid));
127
128 NFD_LOG_TRACE("dropping to effective uid=" << s_normalUid);
129 if (::seteuid(s_normalUid) != 0)
130 throw Error("Failed to drop to effective uid=" + std::to_string(s_normalUid));
131
132 NFD_LOG_INFO("dropped to effective uid=" << ::geteuid() << " gid=" << ::getegid());
133#else
134 NFD_LOG_WARN("Dropping privileges is not supported on this platform");
135#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
136}
137
138void
139PrivilegeHelper::raise()
140{
141#ifdef NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
142 if (::geteuid() == s_privilegedUid && ::getegid() == s_privilegedGid)
143 return;
144
145 NFD_LOG_TRACE("elevating to effective uid=" << s_privilegedUid);
146 if (::seteuid(s_privilegedUid) != 0)
147 throw Error("Failed to elevate to effective uid=" + std::to_string(s_privilegedUid));
148
149 NFD_LOG_TRACE("elevating to effective gid=" << s_privilegedGid);
150 if (::setegid(s_privilegedGid) != 0)
151 throw Error("Failed to elevate to effective gid=" + std::to_string(s_privilegedGid));
152
153 NFD_LOG_INFO("elevated to effective uid=" << ::geteuid() << " gid=" << ::getegid());
154#else
155 NFD_LOG_WARN("Elevating privileges is not supported on this platform");
156#endif // NFD_HAVE_PRIVILEGE_DROP_AND_ELEVATE
157}
158
159} // namespace nfd
Indicates a serious seteuid/setegid failure.
static void initialize(const std::string &userName, const std::string &groupName)
#define NFD_LOG_INFO
Definition logger.hpp:39
#define NFD_LOG_INIT(name)
Definition logger.hpp:31
#define NFD_LOG_WARN
Definition logger.hpp:40
#define NFD_LOG_TRACE
Definition logger.hpp:37
Definition common.hpp:71