diff options
Diffstat (limited to 'src/responder')
-rw-r--r-- | src/responder/common/responder.h | 10 | ||||
-rw-r--r-- | src/responder/common/responder_common.c | 136 | ||||
-rw-r--r-- | src/responder/pac/pacsrv.c | 19 |
3 files changed, 161 insertions, 4 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 43a4fa02..c09262d1 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -98,6 +98,9 @@ struct resp_ctx { struct timeval get_domains_last_call; + size_t allowed_uids_count; + uid_t *allowed_uids; + void *pvt_ctx; }; @@ -289,4 +292,11 @@ struct tevent_req *sss_dp_get_domains_send(TALLOC_CTX *mem_ctx, const char *hint); errno_t sss_dp_get_domains_recv(struct tevent_req *req); + +errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string, + bool allow_sss_loop, + size_t *_uid_count, uid_t **_uids); + +errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count, + uid_t *allowed_uids); #endif /* __SSS_RESPONDER_H__ */ diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index e5577403..e44c351a 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -33,6 +33,7 @@ #include <errno.h> #include <popt.h> #include "util/util.h" +#include "util/strtonum.h" #include "db/sysdb.h" #include "confdb/confdb.h" #include "dbus/dbus.h" @@ -104,15 +105,15 @@ static int client_destructor(struct cli_ctx *ctx) static errno_t get_client_cred(struct cli_ctx *cctx) { + cctx->client_euid = -1; + cctx->client_egid = -1; + cctx->client_pid = -1; + #ifdef HAVE_UCRED int ret; struct ucred client_cred; socklen_t client_cred_len = sizeof(client_cred); - cctx->client_euid = -1; - cctx->client_egid = -1; - cctx->client_pid = -1; - ret = getsockopt(cctx->cfd, SOL_SOCKET, SO_PEERCRED, &client_cred, &client_cred_len); if (ret != EOK) { @@ -136,6 +137,107 @@ static errno_t get_client_cred(struct cli_ctx *cctx) return EOK; } +errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count, + uid_t *allowed_uids) +{ + size_t c; + + if (allowed_uids == NULL) { + return EINVAL; + } + + for (c = 0; c < allowed_uids_count; c++) { + if (uid == allowed_uids[c]) { + return EOK; + } + } + + return EACCES; +} + +errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *cvs_string, + bool allow_sss_loop, + size_t *_uid_count, uid_t **_uids) +{ + int ret; + size_t c; + char **list = NULL; + int list_size; + uid_t *uids = NULL; + char *endptr; + struct passwd *pwd; + + ret = split_on_separator(mem_ctx, cvs_string, ',', true, &list, &list_size); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("split_on_separator failed [%d][%s].\n", + ret, strerror(ret))); + goto done; + } + + uids = talloc_array(mem_ctx, uint32_t, list_size); + if (uids == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n")); + ret = ENOMEM; + goto done; + } + + if (allow_sss_loop) { + ret = unsetenv("_SSS_LOOPS"); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Failed to unset _SSS_LOOPS, getpwnam " + "might not find sssd users.\n")); + } + } + + for (c = 0; c < list_size; c++) { + errno = 0; + if (*list[c] == '\0') { + DEBUG(SSSDBG_OP_FAILURE, ("Empty list item.\n")); + ret = EINVAL; + goto done; + } + + uids[c] = strtouint32(list[c], &endptr, 10); + if (errno != 0 || *endptr != '\0') { + ret = errno; + if (ret == ERANGE) { + DEBUG(SSSDBG_OP_FAILURE, ("List item [%s] is out of range.\n", + list[c])); + goto done; + } + + errno = 0; + pwd = getpwnam(list[c]); + if (pwd == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("List item [%s] is neither a valid " + "UID nor a user name which cloud be " + "resolved by getpwnam().\n", list[c])); + ret = EINVAL; + goto done; + } + + uids[c] = pwd->pw_uid; + } + } + + *_uid_count = list_size; + *_uids = uids; + + ret = EOK; + +done: + if(setenv("_SSS_LOOPS", "NO", 0) != 0) { + DEBUG(SSSDBG_OP_FAILURE, ("Failed to set _SSS_LOOPS.\n")); + } + talloc_free(list); + if (ret != EOK) { + talloc_free(uids); + } + + return ret; +} + + static void client_send(struct cli_ctx *cctx) { int ret; @@ -320,6 +422,32 @@ static void accept_fd_handler(struct tevent_context *ev, "client cred may not be available.\n")); } + if (rctx->allowed_uids_count != 0) { + if (cctx->client_euid == -1) { + DEBUG(SSSDBG_CRIT_FAILURE, ("allowed_uids configured, " \ + "but platform does not support " \ + "reading peer credential from the " \ + "socket. Access denied.\n")); + close(cctx->cfd); + talloc_free(cctx); + return; + } + + ret = check_allowed_uids(cctx->client_euid, rctx->allowed_uids_count, + rctx->allowed_uids); + if (ret != EOK) { + if (ret == EACCES) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Access denied for uid [%d].\n", + cctx->client_euid)); + } else { + DEBUG(SSSDBG_OP_FAILURE, ("check_allowed_uids failed.\n")); + } + close(cctx->cfd); + talloc_free(cctx); + return; + } + } + cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd, TEVENT_FD_READ, client_fd_handler, cctx); if (!cctx->cfde) { diff --git a/src/responder/pac/pacsrv.c b/src/responder/pac/pacsrv.c index db6e6b49..348fc6f4 100644 --- a/src/responder/pac/pacsrv.c +++ b/src/responder/pac/pacsrv.c @@ -45,6 +45,7 @@ #define SSS_PAC_PIPE_NAME "pac" #define DEFAULT_PAC_FD_LIMIT 8192 +#define DEFAULT_ALLOWED_UIDS "0" struct sbus_method monitor_pac_methods[] = { { MON_CLI_METHOD_PING, monitor_common_pong }, @@ -124,6 +125,7 @@ int pac_process_init(TALLOC_CTX *mem_ctx, int ret, max_retries; enum idmap_error_code err; int fd_limit; + char *uid_str; pac_ctx = talloc_zero(mem_ctx, struct pac_ctx); if (!pac_ctx) { @@ -147,6 +149,23 @@ int pac_process_init(TALLOC_CTX *mem_ctx, } pac_ctx->rctx->pvt_ctx = pac_ctx; + + ret = confdb_get_string(pac_ctx->rctx->cdb, pac_ctx->rctx, + CONFDB_PAC_CONF_ENTRY, CONFDB_SERVICE_ALLOWED_UIDS, + DEFAULT_ALLOWED_UIDS, &uid_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to get allowed UIDs.\n")); + return ret; + } + + ret = csv_string_to_uid_array(pac_ctx->rctx, uid_str, true, + &pac_ctx->rctx->allowed_uids_count, + &pac_ctx->rctx->allowed_uids); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to set allowed UIDs.\n")); + return ret; + } + /* Enable automatic reconnection to the Data Provider */ ret = confdb_get_int(pac_ctx->rctx->cdb, CONFDB_PAC_CONF_ENTRY, |