From 3634423f3632b575a76bd5e711ecfb0f740d9452 Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Thu, 16 Jul 2009 22:15:26 -0700 Subject: [PATCH] Allow specifying runing user and chroot() enviroment Allow the admin to switch the user the kdc is running under and specify the chroot() directory to run in. Please note you need a very special setup to get this working. --- kdc/config.c | 10 ++++++++++ kdc/kdc_locl.h | 3 +++ kdc/main.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/kdc/config.c b/kdc/config.c index a7c7c80f4..c2c2a19e5 100644 --- a/kdc/config.c +++ b/kdc/config.c @@ -64,6 +64,10 @@ static struct getarg_strings addresses_str; /* addresses to listen on */ static char *v4_realm; +char *runas_string; +char *chroot_string; + + static struct getargs args[] = { { "config-file", 'c', arg_string, &config_file, @@ -118,6 +122,12 @@ static struct getargs args[] = { "disable DES" }, { "builtin-hdb", 0, arg_flag, &builtin_hdb_flag, "list builtin hdb backends"}, + { "runas-user", 0, arg_string, &runas_string, + "run as this user when connected to network" + }, + { "chroot", 0, arg_string, &chroot_string, + "chroot directory to run in" + }, { "help", 'h', arg_flag, &help_flag }, { "version", 'v', arg_flag, &version_flag } }; diff --git a/kdc/kdc_locl.h b/kdc/kdc_locl.h index daf155839..024937e76 100644 --- a/kdc/kdc_locl.h +++ b/kdc/kdc_locl.h @@ -67,6 +67,9 @@ extern const struct units _kdc_digestunits[]; extern struct timeval _kdc_now; #define kdc_time (_kdc_now.tv_sec) +extern char *runas_string; +extern char *chroot_string; + void loop(krb5_context context, krb5_kdc_configuration *config); diff --git a/kdc/main.c b/kdc/main.c index 062c1d8cd..e5dd4788d 100644 --- a/kdc/main.c +++ b/kdc/main.c @@ -48,6 +48,41 @@ sigterm(int sig) exit_flag = sig; } +/* + * Allow dropping root bit, since heimdal reopens the database all the + * time the database needs to be owned by the user you are switched + * too. A better solution is to split the kdc in to more processes and + * run the network facing part with very low privilege. + */ + +static void +switch_environment(void) +{ + if ((runas_string || chroot_string) && geteuid() != 0) + errx(1, "no running as root, can't switch user/chroot"); + + if (chroot_string && chroot(chroot_string) != 0) + errx(1, "chroot(%s)", "chroot_string failed"); + + if (runas_string) { + struct passwd *pw; + + pw = getpwnam(runas_string); + if (pw == NULL) + errx(1, "unknown user %s", runas_string); + + if (initgroups(pw->pw_name, pw->pw_gid) < 0) + err(1, "initgroups failed"); + + if (setgid(pw->pw_gid) < 0) + err(1, "setgid(%s) failed", runas_string); + + if (setuid(pw->pw_uid) < 0) + err(1, "setuid(%s)", runas_string); + } +} + + int main(int argc, char **argv) { @@ -95,6 +130,9 @@ main(int argc, char **argv) daemon(0, 0); #endif pidfile(NULL); + + switch_environment(); + loop(context, config); krb5_free_context(context); return 0;