1
/* Copyright © 2005-2011 Roger Leigh <rleigh@debian.org>
3
* sbuild is free software: you can redistribute it and/or modify it
4
* under the terms of the GNU General Public License as published by
5
* the Free Software Foundation, either version 2 of the License, or
6
* (at your option) any later version.
8
* sbuild is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see
15
* <http://www.gnu.org/licenses/>.
17
*********************************************************************/
27
using namespace sbuild;
29
* Check group membership.
31
* @param group the group to check for.
32
* @returns true if the user is a member of group, otherwise false.
35
is_group_member (sbuild::group const& group)
39
bool group_member = false;
40
if (group.gr_gid == getgid())
46
int supp_group_count = getgroups(0, 0);
47
if (supp_group_count < 0)
49
std::cerr << "Failed to get supplementary group count" << std::endl;
52
if (supp_group_count > 0)
54
gid_t *supp_groups = new gid_t[supp_group_count];
56
if (getgroups(supp_group_count, supp_groups) < 1)
58
// Free supp_groups before throwing to avoid leak.
60
std::cerr << "Failed to get supplementary groups: "
61
<< strerror(errno) << std::endl;
65
for (int i = 0; i < supp_group_count; ++i)
67
if (group.gr_gid == supp_groups[i])
77
const char *sbuild_user = "sbuild";
78
const char *sbuild_group = "sbuild";
81
main (int argc, char *argv[])
83
bool in_group = false;
85
sbuild::group grp(sbuild_group);
90
std::cerr << "Group '" << sbuild_group << "' not found" << std::endl;
94
std::cerr << "Group '" << sbuild_group << "' not found: "
95
<< strerror(errno) << std::endl;
100
sbuild::passwd current_user(getuid());
105
std::cerr << "User '" << getuid() << "' not found" << std::endl;
109
std::cerr << "User '" << getuid() << "' not found: "
110
<< strerror(errno) << std::endl;
115
sbuild::passwd new_user(sbuild_user);
120
std::cerr << "User '" << sbuild_user << "' not found" << std::endl;
124
std::cerr << "User '" << sbuild_user << "' not found: "
125
<< strerror(errno) << std::endl;
130
sbuild::group new_group(new_user.pw_gid);
135
std::cerr << "Group '" << new_user.pw_gid << "' not found" << std::endl;
139
std::cerr << "Group '" << new_user.pw_gid << "' not found: "
140
<< strerror(errno) << std::endl;
145
// Check primary group
146
if (current_user.pw_gid == grp.gr_gid)
149
// Check supplementary groups
150
if (is_group_member(grp))
153
// Root is allowed to skip the permissions checks, i.e. not be
154
// required to be in the sbuild group.
155
if (current_user.pw_uid != 0 && !in_group) {
156
std::cerr << "Permission denied: not a member of group sbuild" << std::endl;
161
if (setgid (new_user.pw_gid))
163
std::cerr << "Failed to set group '" << new_group.gr_name << "': "
164
<< strerror(errno) << std::endl;
168
// Set supplementary groups
169
if (initgroups (new_user.pw_name, new_user.pw_gid))
171
std::cerr << "Failed to set supplementary groups: "
172
<< strerror(errno) << std::endl;
177
if (setuid (new_user.pw_uid))
179
std::cerr << "Failed to set user '" << new_user.pw_name << "': "
180
<< strerror(errno) << std::endl;
184
// Check we're not still root
187
std::cerr << "Failed to drop root permissions" << std::endl;
191
// exec schroot under new identity
192
execvp("schroot", argv);
193
std::cerr << "Failed to exec 'schroot'" << std::endl;