Commit 64b6d5f0 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

merged trac268: -u for b10-auth


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@2675 e5f2f494-b856-4b98-b285-d166d9295462
parents 4e773581 365fe1d4
......@@ -47,6 +47,7 @@ libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS)
BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-auth
b10_auth_SOURCES = auth_srv.cc auth_srv.h
b10_auth_SOURCES += change_user.cc change_user.h
b10_auth_SOURCES += common.h
b10_auth_SOURCES += main.cc
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a
......
......@@ -48,6 +48,7 @@
<arg><option>-4</option></arg>
<arg><option>-6</option></arg>
<arg><option>-p <replaceable>number</replaceable></option></arg>
<arg><option>-u <replaceable>username</replaceable></option></arg>
<arg><option>-v</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -119,6 +120,20 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-u <replaceable>username</replaceable></option></term>
<listitem>
<para>
The user name of the <command>b10-auth</command> daemon.
If specified, the daemon changes the process owner to the
specified user.
The <replaceable>username</replaceable> must be either a
valid numeric user ID or a valid user name.
By default the daemon runs as the user who invokes it.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<listitem><para>
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <boost/lexical_cast.hpp>
#include <exceptions/exceptions.h>
#include <auth/common.h>
using namespace boost;
void
changeUser(const char* const username) {
const struct passwd *runas_pw = NULL;
runas_pw = getpwnam(username);
endpwent();
if (runas_pw == NULL) {
try {
runas_pw = getpwuid(lexical_cast<uid_t>(username));
endpwent();
} catch (const bad_lexical_cast&) {
; // fall through to isc_throw below.
}
}
if (runas_pw == NULL) {
isc_throw(FatalError, "Unknown user name or UID:" << username);
}
if (setgid(runas_pw->pw_gid) < 0) {
isc_throw(FatalError, "setgid() failed: " << strerror(errno));
}
if (setuid(runas_pw->pw_uid) < 0) {
isc_throw(FatalError, "setuid() failed: " << strerror(errno));
}
}
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#ifndef __CHANGE_USER_H
#define __CHANGE_USER_H 1
/// \brief Change the run time user.
///
/// This function changes the user and its group of the authoritative server
/// process.
///
/// On success the user ID of the process is changed to the specified user,
/// and the group is changed to that of the new user.
///
/// This is considered a short term workaround until we develop clearer
/// privilege separation, where the server won't even have to open privileged
/// ports and can be started by a non privileged user from the beginning.
/// This function therefore ignores some corner case problems (see below)
/// which we would address otherwise.
///
/// \c username can be either a textual user name or its numeric ID.
/// If the specified user name (or ID) doesn't specify a local user ID
/// or the user originally starting the process doesn't have a permission
/// of changing the user to \c username, this function throws an exception
/// of class \c FatalError.
///
/// This function internally uses system libraries that do not guarantee
/// reentrancy. In fact, it doesn't even expect to be called more than once.
/// The behavior is undefined if this function is called from multiple threads
/// simultaneously or more generally called multiple times.
///
/// This function only offers the basic exception guarantee, that is, if
/// an exception is thrown from this function, it's possible that an exception
/// is thrown after changing the group ID. This function doesn't recover
/// from that situation. In practice, the process is expected to consider
/// this event a fatal error and will immediately exit, and shouldn't cause
/// a real trouble.
///
/// \param username User name or ID of the new effective user.
void changeUser(const char* const username);
#endif // __CHANGE_USER_H
// Local Variables:
// mode: c++
// End:
......@@ -41,6 +41,7 @@
#include <auth/spec_config.h>
#include <auth/common.h>
#include <auth/change_user.h>
#include <auth/auth_srv.h>
#include <auth/asio_link.h>
......@@ -97,9 +98,10 @@ main(int argc, char* argv[]) {
int ch;
const char* port = DNSPORT;
const char* address = NULL;
const char* uid = NULL;
bool use_ipv4 = true, use_ipv6 = true, cache = true;
while ((ch = getopt(argc, argv, "46a:np:v")) != -1) {
while ((ch = getopt(argc, argv, "46a:np:u:v")) != -1) {
switch (ch) {
case '4':
// Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
......@@ -121,6 +123,9 @@ main(int argc, char* argv[]) {
case 'p':
port = optarg;
break;
case 'u':
uid = optarg;
break;
case 'v':
verbose_mode = true;
break;
......@@ -188,6 +193,10 @@ main(int argc, char* argv[]) {
my_command_handler);
cout << "[b10-auth] Configuration channel established." << endl;
if (uid != NULL) {
changeUser(uid);
}
xfrin_session = new Session(io_service->get_io_service());
cout << "[b10-auth] Xfrin session channel created." << endl;
xfrin_session->establish(NULL);
......
......@@ -13,7 +13,9 @@ TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
run_unittests_SOURCES += ../change_user.h ../change_user.cc
run_unittests_SOURCES += auth_srv_unittest.cc
run_unittests_SOURCES += change_user_unittest.cc
run_unittests_SOURCES += asio_link_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <stdlib.h>
#include <unistd.h> // for getuid
#include <string>
#include <gtest/gtest.h>
#include <auth/common.h>
#include <auth/change_user.h>
using namespace std;
namespace {
class ChangeUserTest : public ::testing::Test {
protected:
// normally the USER environment variable should be set to the name
// of the local user running this test. If we encounter a case where
// this doesn't hold, we'll need to add a prerequisite check in each
// test. For now we assume this is valid for simplicity.
ChangeUserTest() : my_username(getenv("USER")) {}
const string my_username;
};
TEST_F(ChangeUserTest, changeToTheSameUser) {
// changing to the run time user should succeed.
EXPECT_NO_THROW(changeUser(my_username.c_str()));
}
TEST_F(ChangeUserTest, badUID) {
// -1 should be an invalid numeric UID, and (hopefully) shouldn't be
// a valid textual username.
EXPECT_THROW(changeUser("-1"), FatalError);
}
TEST_F(ChangeUserTest, promotionAttempt) {
// change to root should fail unless the running user is a super user.
if (getuid() == 0) {
cerr << "Already a super user, skipping the test" << endl;
return;
}
EXPECT_THROW(changeUser("root"), FatalError);
}
}
......@@ -336,6 +336,8 @@ class BoB:
authargs += ['-a', str(self.address)]
if self.nocache:
authargs += ['-n']
if self.uid:
authargs += ['-u', str(self.uid)]
if self.verbose:
authargs += ['-v']
sys.stdout.write("Starting b10-auth using port %d" %
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment