summaryrefslogtreecommitdiffstats
path: root/src/responder
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2012-07-05 10:50:08 +0200
committerStephen Gallagher <sgallagh@redhat.com>2012-07-10 09:07:26 -0400
commit2d257ccf620ce1b611f89cec8f0a94c88c2f2881 (patch)
tree6e3c67e2922c366d3b60ae477d2e2dd8fbbd6763 /src/responder
parenta56156c13c71a96166b0a8f3921e67f36470f8d7 (diff)
downloadsssd-2d257ccf620ce1b611f89cec8f0a94c88c2f2881.tar.gz
sssd-2d257ccf620ce1b611f89cec8f0a94c88c2f2881.tar.xz
sssd-2d257ccf620ce1b611f89cec8f0a94c88c2f2881.zip
pac responder: limit access by checking UIDs
A check for allowed UIDs is added in the common responder code directly after accept(). If the platform does not support reading the UID of the peer but allowed UIDs are configured, access is denied. Currently only the PAC responder sets the allowed UIDs for a socket. The default is that only root is allowed to access the socket of the PAC responder. Fixes: https://fedorahosted.org/sssd/ticket/1382
Diffstat (limited to 'src/responder')
-rw-r--r--src/responder/common/responder.h10
-rw-r--r--src/responder/common/responder_common.c136
-rw-r--r--src/responder/pac/pacsrv.c19
3 files changed, 161 insertions, 4 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 43a4fa023..c09262d1b 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 e55774038..e44c351ad 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 db6e6b49e..348fc6f47 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,