>From 07cef981edc26aa8010497d2690f0baa04ee161f Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 5 Aug 2014 13:52:48 +0200 Subject: [PATCH 1/7] SSSD: Load a user to run a service as from configuration Adds two new options, user and group that are specified in the [sssd] section. When these options are specified, SSSD will run as the user and group. When these are not specified, SSSD will run as the configure-time user and group. The group option only takes effect when user is also specified. Currently all services and providers are started as root. There is a temporary svc_supported_as_nonroot() function that returns true for a service if that service runs and was tested as nonroot and false otherwise. Currently this function always returns false, but will be amended in future patches. --- src/confdb/confdb.h | 2 + src/config/SSSDConfig/__init__.py.in | 2 + src/config/SSSDConfigTest.py | 2 + src/config/etc/sssd.api.conf | 2 + src/man/sssd.conf.5.xml | 26 ++++++++++++ src/monitor/monitor.c | 78 ++++++++++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 720b7dc1cc857d6aa34684c6fccd1c5fc5c33172..cb394a0a6b6119b297238fcc66c7a600d9ce6831 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -69,6 +69,8 @@ #define CONFDB_MONITOR_KRB5_RCACHEDIR "krb5_rcache_dir" #define CONFDB_MONITOR_DEFAULT_DOMAIN "default_domain_suffix" #define CONFDB_MONITOR_OVERRIDE_SPACE "override_space" +#define CONFDB_MONITOR_USER_RUNAS "user" +#define CONFDB_MONITOR_GROUP_RUNAS "group" /* Both monitor and domains */ #define CONFDB_NAME_REGEX "re_expression" diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index ee48094d0cd1c49d978c2c99213119028ab1acdf..89f51beaefa0de8f3c2223f2b825bb8589c9f02c 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -56,6 +56,8 @@ option_strings = { 'full_name_format' : _('Printf-compatible format for displaying fully-qualified names'), 'krb5_rcache_dir' : _('Directory on the filesystem where SSSD should store Kerberos replay cache files.'), 'default_domain_suffix' : _('Domain to add to names without a domain component.'), + 'user' : _('The user to drop privileges to'), + 'group' : _('The group to drop privileges to'), # [nss] 'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 2d12bc02af1768d22c8bfa9a21b1fc24bf199af4..4561e31d1105f79dcf93e083d92199a723e73382 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -280,6 +280,8 @@ class SSSDConfigTestSSSDService(unittest.TestCase): 're_expression', 'full_name_format', 'krb5_rcache_dir', + 'user', + 'group', 'default_domain_suffix', 'debug_level', 'debug_timestamps', diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index a20f5aa44dbadd24f644bffc9954df9e088979b9..41a3144e06297620739856c47a0f81c54554a320 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -23,6 +23,8 @@ sbus_timeout = int, None, false re_expression = str, None, false full_name_format = str, None, false krb5_rcache_dir = str, None, false +user = str, None, false +group = str, None, false default_domain_suffix = str, None, false [nss] diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index d5734166144a7c3ce7e62914558f8e69121bf774..19141d1044e99ea4aaf8d43cec872d5feec24cce 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -297,6 +297,32 @@ + user (string) + + + The user to drop the privileges to where + appropriate to avoid running as the + root user. + + + Default: not set, process will run as root + + + + + group (string) + + + The group to drop the privileges to where + appropriate to avoid running as the + root user. + + + Default: not set, process will run as root + + + + default_domain_suffix (string) diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index edd1c2dfc674d8a7ca9d069d6499c0dcc959f210..33f01f907120de52ea80c9666f590d003c6ff156 100644 --- a/src/monitor/monitor.c +++ b/src/monitor/monitor.c @@ -170,6 +170,10 @@ struct mt_ctx { struct sss_sigchild_ctx *sigchld_ctx; bool is_daemon; pid_t parent_pid; + + /* For running unprivileged services */ + uid_t uid; + gid_t gid; }; static int start_service(struct mt_svc *mt_svc); @@ -910,6 +914,51 @@ static char *check_services(char **services) return NULL; } +static int get_service_user(struct mt_ctx *ctx) +{ + errno_t ret; + char *user_str; + char *group_str; + + ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, + CONFDB_MONITOR_USER_RUNAS, + NULL, &user_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as"); + return ret; + } + + if (user_str != NULL) { + ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY, + CONFDB_MONITOR_GROUP_RUNAS, + user_str, &group_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the group to run as"); + return ret; + } + + } else { + user_str = SSSD_USER; + group_str = SSSD_GROUP; + } + + ret = sss_user_from_string(user_str, &ctx->uid); + talloc_free(user_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n"); + return ret; + } + + ret = sss_group_from_string(group_str, &ctx->gid); + talloc_free(group_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n"); + return ret; + } + + return EOK; +} + static int get_monitor_config(struct mt_ctx *ctx) { int ret; @@ -955,6 +1004,12 @@ static int get_monitor_config(struct mt_ctx *ctx) ctx->num_services++; } + ret = get_service_user(ctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get the unprivileged user\n"); + return ret; + } + ret = confdb_get_domains(ctx->cdb, &ctx->domains); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n"); @@ -1020,6 +1075,14 @@ static errno_t get_ping_config(struct mt_ctx *ctx, const char *path, return EOK; } +/* This is a temporary function that returns false if the service + * being started was only tested when running as root. + */ +static bool svc_supported_as_nonroot(const char *svc_name) +{ + return false; +} + static int get_service_config(struct mt_ctx *ctx, const char *name, struct mt_svc **svc_cfg) { @@ -1027,6 +1090,8 @@ static int get_service_config(struct mt_ctx *ctx, const char *name, char *path; struct mt_svc *svc; time_t now = time(NULL); + uid_t uid = 0; + gid_t gid = 0; *svc_cfg = NULL; @@ -1066,6 +1131,11 @@ static int get_service_config(struct mt_ctx *ctx, const char *name, return ret; } + if (svc_supported_as_nonroot(svc->name)) { + uid = ctx->uid; + gid = ctx->gid; + } + if (!svc->command) { svc->command = talloc_asprintf( svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name @@ -1075,6 +1145,14 @@ static int get_service_config(struct mt_ctx *ctx, const char *name, return ENOMEM; } + svc->command = talloc_asprintf_append(svc->command, + " --uid %"SPRIuid" --gid %"SPRIgid, + uid, gid); + if (!svc->command) { + talloc_free(svc); + return ENOMEM; + } + if (cmdline_debug_level != SSSDBG_UNRESOLVED) { svc->command = talloc_asprintf_append( svc->command, " -d %#.4x", cmdline_debug_level -- 1.9.3