replaced --with-gid/uid by --with-group/user

using named users, groups
fixed capability dropping in pluto
This commit is contained in:
Martin Willi
2008-05-08 10:58:04 +00:00
parent 97e820f5fd
commit 25b12c696b
12 changed files with 190 additions and 97 deletions
+16 -8
View File
@@ -118,17 +118,25 @@ AC_ARG_WITH(
) )
AC_ARG_WITH( AC_ARG_WITH(
[uid], [uid],,[AC_MSG_ERROR([--with-uid is gone, use --with-user instead!])]
AS_HELP_STRING([--with-uid=uid],[change user of the daemons to UID after startup (default is 0).]),
[AC_DEFINE_UNQUOTED(IPSEC_UID, $withval) AC_SUBST(ipsecuid, "$withval")],
[AC_DEFINE_UNQUOTED(IPSEC_UID, 0) AC_SUBST(ipsecuid, "0")]
) )
AC_ARG_WITH( AC_ARG_WITH(
[gid], [gid],,[AC_MSG_ERROR([--with-gid is gone, use --with-group instead!])]
AS_HELP_STRING([--with-gid=gid],[change group of the daemons to GID after startup (default is 0).]), )
[AC_DEFINE_UNQUOTED(IPSEC_GID, $withval) AC_SUBST(ipsecgid, "$withval")],
[AC_DEFINE_UNQUOTED(IPSEC_GID, 0) AC_SUBST(ipsecgid, "0")] AC_ARG_WITH(
[user],
AS_HELP_STRING([--with-user=user],[change user of the daemons to "user" after startup (default is 0).]),
[AC_DEFINE_UNQUOTED(IPSEC_USER, "$withval") AC_SUBST(ipsecuser, "$withval")],
[AC_SUBST(ipsecuser, "root")]
)
AC_ARG_WITH(
[group],
AS_HELP_STRING([--with-group=group],[change group of the daemons to "group" after startup (default is 0).]),
[AC_DEFINE_UNQUOTED(IPSEC_GROUP, "$withval") AC_SUBST(ipsecgroup, "$withval")],
[AC_SUBST(ipsecgroup, "root")]
) )
AC_ARG_ENABLE( AC_ARG_ENABLE(
+2 -2
View File
@@ -42,5 +42,5 @@ endif
EXTRA_DIST = strongswan.conf EXTRA_DIST = strongswan.conf
install-exec-local : install-exec-local :
test -e "$(DESTDIR)${sysconfdir}" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" test -e "$(DESTDIR)${sysconfdir}" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)"
test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -m 600 strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -m 640 strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf
+52 -11
View File
@@ -28,6 +28,8 @@
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include <errno.h> #include <errno.h>
#include <pwd.h>
#include <grp.h>
#ifdef HAVE_BACKTRACE #ifdef HAVE_BACKTRACE
# include <execinfo.h> # include <execinfo.h>
#endif /* HAVE_BACKTRACE */ #endif /* HAVE_BACKTRACE */
@@ -207,11 +209,17 @@ static void destroy(private_daemon_t *this)
static void kill_daemon(private_daemon_t *this, char *reason) static void kill_daemon(private_daemon_t *this, char *reason)
{ {
/* we send SIGTERM, so the daemon can cleanly shut down */ /* we send SIGTERM, so the daemon can cleanly shut down */
DBG1(DBG_DMN, "killing daemon: %s", reason); if (this->public.bus)
{
DBG1(DBG_DMN, "killing daemon: %s", reason);
}
else
{
fprintf(stderr, "killing daemon: %s\n", reason);
}
if (this->main_thread_id == pthread_self()) if (this->main_thread_id == pthread_self())
{ {
/* initialization failed, terminate daemon */ /* initialization failed, terminate daemon */
destroy(this);
unlink(PID_FILE); unlink(PID_FILE);
exit(-1); exit(-1);
} }
@@ -237,18 +245,14 @@ static void drop_capabilities(private_daemon_t *this, bool full)
if (full) if (full)
{ {
# if IPSEC_GID if (setgid(charon->gid) != 0)
if (setgid(IPSEC_GID) != 0)
{ {
kill_daemon(this, "changing GID to unprivileged group failed"); kill_daemon(this, "change to unprivileged group failed");
} }
# endif if (setuid(charon->uid) != 0)
# if IPSEC_UID
if (setuid(IPSEC_UID) != 0)
{ {
kill_daemon(this, "changing UID to unprivileged user failed"); kill_daemon(this, "change to unprivileged user failed");
} }
# endif
} }
else else
{ {
@@ -282,6 +286,39 @@ static void drop_capabilities(private_daemon_t *this, bool full)
} }
} }
/**
* lookup UID and GID
*/
static void lookup_uid_gid(private_daemon_t *this)
{
#ifdef IPSEC_USER
{
char buf[1024];
struct passwd passwd, *pwp;
if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
pwp == NULL)
{
kill_daemon(this, "resolving user '"IPSEC_USER"' failed");
}
charon->uid = pwp->pw_uid;
}
#endif
#ifdef IPSEC_GROUP
{
char buf[1024];
struct group group, *grp;
if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
grp == NULL)
{
kill_daemon(this, "reslvoing group '"IPSEC_GROUP"' failed");
}
charon->gid = grp->gr_gid;
}
#endif
}
/** /**
* Initialize the daemon * Initialize the daemon
*/ */
@@ -428,6 +465,8 @@ private_daemon_t *daemon_create(void)
this->public.outlog = NULL; this->public.outlog = NULL;
this->public.syslog = NULL; this->public.syslog = NULL;
this->public.authlog = NULL; this->public.authlog = NULL;
this->public.uid = 0;
this->public.gid = 0;
this->main_thread_id = pthread_self(); this->main_thread_id = pthread_self();
@@ -496,6 +535,8 @@ int main(int argc, char *argv[])
private_charon = daemon_create(); private_charon = daemon_create();
charon = (daemon_t*)private_charon; charon = (daemon_t*)private_charon;
lookup_uid_gid(private_charon);
/* drop the capabilities we won't need for initialization */ /* drop the capabilities we won't need for initialization */
prctl(PR_SET_KEEPCAPS, 1); prctl(PR_SET_KEEPCAPS, 1);
drop_capabilities(private_charon, FALSE); drop_capabilities(private_charon, FALSE);
@@ -571,7 +612,7 @@ int main(int argc, char *argv[])
if (pid_file) if (pid_file)
{ {
fprintf(pid_file, "%d\n", getpid()); fprintf(pid_file, "%d\n", getpid());
fchown(fileno(pid_file), IPSEC_UID, IPSEC_GID); fchown(fileno(pid_file), charon->uid, charon->gid);
fclose(pid_file); fclose(pid_file);
} }
+10
View File
@@ -298,6 +298,16 @@ struct daemon_t {
mediation_manager_t *mediation_manager; mediation_manager_t *mediation_manager;
#endif /* ME */ #endif /* ME */
/**
* User ID the daemon will user after initialization
*/
uid_t uid;
/**
* Group ID the daemon will use after initialization
*/
gid_t gid;
/** /**
* Shut down the daemon. * Shut down the daemon.
* *
+1 -1
View File
@@ -728,7 +728,7 @@ plugin_t *plugin_create()
return NULL; return NULL;
} }
umask(old); umask(old);
if (chown(unix_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0) if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0)
{ {
DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno)); DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
} }
+1 -1
View File
@@ -537,7 +537,7 @@ static bool open_socket(private_stroke_socket_t *this)
return FALSE; return FALSE;
} }
umask(old); umask(old);
if (chown(socket_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0) if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
{ {
DBG1(DBG_CFG, "changing stroke socket permissions failed: %s", DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
strerror(errno)); strerror(errno));
+2
View File
@@ -249,6 +249,8 @@ char *whitelist[] = {
"getprotobynumber", "getprotobynumber",
"getservbyport", "getservbyport",
"getservbyname", "getservbyname",
"getpwnam_r",
"getgrnam_r",
"register_printf_function", "register_printf_function",
"syslog", "syslog",
"vsyslog", "vsyslog",
+32 -6
View File
@@ -31,6 +31,8 @@
#include <sys/queue.h> #include <sys/queue.h>
#include <linux/capability.h> #include <linux/capability.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <pwd.h>
#include <grp.h>
#include <freeswan.h> #include <freeswan.h>
@@ -617,19 +619,43 @@ main(int argc, char **argv)
init_fetch(); init_fetch();
/* drop unneeded capabilities and change UID/GID */ /* drop unneeded capabilities and change UID/GID */
#ifdef _LINUX_CAPABILITY_VERSION_1
hdr.version = _LINUX_CAPABILITY_VERSION_1;
#else
hdr.version = _LINUX_CAPABILITY_VERSION; hdr.version = _LINUX_CAPABILITY_VERSION;
#endif
hdr.pid = 0; hdr.pid = 0;
data.inheritable = data.effective = data.permitted = data.inheritable = data.effective = data.permitted =
1<<CAP_NET_ADMIN | 1<<CAP_NET_BIND_SERVICE; 1<<CAP_NET_ADMIN | 1<<CAP_NET_BIND_SERVICE;
prctl(PR_SET_KEEPCAPS, 1); prctl(PR_SET_KEEPCAPS, 1);
# if IPSEC_GID #ifdef IPSEC_GROUP
setgid(IPSEC_GID); {
# endif struct group group, *grp;
# if IPSEC_UID char buf[1024];
setuid(IPSEC_UID);
# endif if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
grp == NULL || setgid(grp->gr_gid) != 0)
{
plog("unable to change daemon group");
abort();
}
}
#endif
#ifdef IPSEC_USER
{
struct passwd passwd, *pwp;
char buf[1024];
if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
pwp == NULL || setuid(pwp->pw_uid) != 0)
{
plog("unable to change daemon user");
abort();
}
}
#endif
if (capset(&hdr, &data)) if (capset(&hdr, &data))
{ {
plog("unable to drop root privileges"); plog("unable to drop root privileges");
+10 -10
View File
@@ -31,14 +31,14 @@ defs.o: $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
$(COMPILE) -c -o $@ $< $(COMPILE) -c -o $@ $<
install-exec-local : install-exec-local :
test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d" test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/certs" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/crls" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs"
test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(MKDIR_P) -m 700 "$(DESTDIR)$(sysconfdir)/ipsec.d/private" test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private"
test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -m 644 ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -m 644 ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf
+1 -29
View File
@@ -103,8 +103,8 @@ starter_stop_charon (void)
int int
starter_start_charon (starter_config_t *cfg, bool debug) starter_start_charon (starter_config_t *cfg, bool debug)
{ {
int pid, i;
struct stat stb; struct stat stb;
int pid, i;
char buffer[BUF_LEN]; char buffer[BUF_LEN];
int argc = 1; int argc = 1;
char *arg[] = { char *arg[] = {
@@ -159,34 +159,6 @@ starter_start_charon (starter_config_t *cfg, bool debug)
unlink(CHARON_CTL_FILE); unlink(CHARON_CTL_FILE);
_stop_requested = 0; _stop_requested = 0;
/* if ipsec.secrets file is missing then generate RSA default key pair */
if (stat(SECRETS_FILE, &stb) != 0)
{
mode_t oldmask;
FILE *f;
plog("no %s file, generating RSA key", SECRETS_FILE);
seteuid(IPSEC_UID);
setegid(IPSEC_GID);
system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
seteuid(0);
setegid(0);
/* ipsec.secrets is root readable only */
oldmask = umask(0066);
f = fopen(SECRETS_FILE, "w");
if (f)
{
fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
fprintf(f, "\n");
fprintf(f, ": RSA myKey.der\n");
fclose(f);
}
chown(SECRETS_FILE, IPSEC_UID, IPSEC_GID);
umask(oldmask);
}
pid = fork(); pid = fork();
switch (pid) switch (pid)
{ {
+1 -29
View File
@@ -106,8 +106,8 @@ starter_stop_pluto (void)
int int
starter_start_pluto (starter_config_t *cfg, bool debug) starter_start_pluto (starter_config_t *cfg, bool debug)
{ {
int i;
struct stat stb; struct stat stb;
int i;
pid_t pid; pid_t pid;
char **l; char **l;
int argc = 2; int argc = 2;
@@ -218,34 +218,6 @@ starter_start_pluto (starter_config_t *cfg, bool debug)
if (cfg->setup.prepluto) if (cfg->setup.prepluto)
system(cfg->setup.prepluto); system(cfg->setup.prepluto);
/* if ipsec.secrets file is missing then generate RSA default key pair */
if (stat(SECRETS_FILE, &stb) != 0)
{
mode_t oldmask;
FILE *f;
plog("no %s file, generating RSA key", SECRETS_FILE);
seteuid(IPSEC_UID);
setegid(IPSEC_GID);
system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
seteuid(0);
setegid(0);
/* ipsec.secrets is root readable only */
oldmask = umask(0066);
f = fopen(SECRETS_FILE, "w");
if (f)
{
fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
fprintf(f, "\n");
fprintf(f, ": RSA myKey.der\n");
fclose(f);
}
chown(SECRETS_FILE, IPSEC_UID, IPSEC_GID);
umask(oldmask);
}
pid = fork(); pid = fork();
switch (pid) switch (pid)
{ {
+62
View File
@@ -26,6 +26,8 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <freeswan.h> #include <freeswan.h>
@@ -139,6 +141,64 @@ fsig(int signal)
} }
} }
static void generate_selfcert()
{
struct stat stb;
/* if ipsec.secrets file is missing then generate RSA default key pair */
if (stat(SECRETS_FILE, &stb) != 0)
{
mode_t oldmask;
FILE *f;
uid_t uid = 0;
gid_t gid = 0;
#ifdef IPSEC_GROUP
{
char buf[1024];
struct group group, *grp;
if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) == 0 &&
grp)
{
gid = grp->gr_gid;
}
}
#endif
#ifdef IPSEC_USER
{
char buf[1024];
struct passwd passwd, *pwp;
if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) == 0 &&
pwp)
{
uid = pwp->pw_uid;
}
}
#endif
setegid(gid);
seteuid(uid);
system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
seteuid(0);
setegid(0);
/* ipsec.secrets is root readable only */
oldmask = umask(0066);
f = fopen(SECRETS_FILE, "w");
if (f)
{
fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
fprintf(f, "\n");
fprintf(f, ": RSA myKey.der\n");
fclose(f);
}
chown(SECRETS_FILE, uid, gid);
umask(oldmask);
}
}
static void static void
usage(char *name) usage(char *name)
{ {
@@ -275,6 +335,8 @@ int main (int argc, char **argv)
exit(LSB_RC_SUCCESS); exit(LSB_RC_SUCCESS);
} }
generate_selfcert();
/* fork if we're not debugging stuff */ /* fork if we're not debugging stuff */
if (!no_fork) if (!no_fork)
{ {