>From 3de7ed71a833f63f4b4ad13bc373b1089febcfa5 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Wed, 6 Nov 2013 14:12:11 +0100 Subject: [PATCH 4/6] IFP: use a list of allowed_uids for authentication Similar to the PAC responder, the InfoPipe uses a list of UIDs that are allowed to communicate with the IFP responder. --- src/man/sssd-ifp.5.xml | 32 ++++++++++++++++++++++++++++++ src/responder/ifp/ifpsrv.c | 20 +++++++++++++++++++ src/responder/ifp/ifpsrv_util.c | 13 +++++++++++++ src/tests/cmocka/test_ifp.c | 43 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/src/man/sssd-ifp.5.xml b/src/man/sssd-ifp.5.xml index dfac252984f365582519c6ceb5e553633813c761..7e2ea7cfc868e56b7434f0275eeea5b792f31a5f 100644 --- a/src/man/sssd-ifp.5.xml +++ b/src/man/sssd-ifp.5.xml @@ -40,6 +40,38 @@ + + CONFIGURATION OPTIONS + + These options can be used to configure the InfoPipe responder. + + + + allowed_uids (string) + + + Specifies the comma-separated list of UID values or + user names that are allowed to access the InfoPipe + responder. User names are resolved to UIDs at + startup. + + + Default: 0 (only the root user is allowed to access + the InfoPipe responder) + + + Please note that although the UID 0 is used as the + default it will be overwritten with this option. If + you still want to allow the root user to access the + InfoPipe responder, which would be the typical + case, you have to add 0 to the list of allowed UIDs + as well. + + + + + + diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c index e76f3bdb0afb997ee2bbc0122199e127da34de84..e5b9443409154c4f46654a3536f8435f990fe90a 100644 --- a/src/responder/ifp/ifpsrv.c +++ b/src/responder/ifp/ifpsrv.c @@ -40,6 +40,8 @@ #include "responder/ifp/ifp_private.h" #include "responder/common/responder_sbus.h" +#define DEFAULT_ALLOWED_UIDS "0" + struct mon_cli_iface monitor_ifp_methods = { { &mon_cli_iface_meta, 0 }, .ping = monitor_common_pong, @@ -201,6 +203,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx, struct be_conn *iter; int ret; int max_retries; + char *uid_str; ifp_cmds = get_ifp_cmds(); ret = sss_process_init(mem_ctx, ev, cdb, @@ -236,6 +239,23 @@ int ifp_process_init(TALLOC_CTX *mem_ctx, goto fail; } + ret = confdb_get_string(ifp_ctx->rctx->cdb, ifp_ctx->rctx, + CONFDB_IFP_CONF_ENTRY, CONFDB_SERVICE_ALLOWED_UIDS, + DEFAULT_ALLOWED_UIDS, &uid_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to get allowed UIDs.\n")); + goto fail; + } + + ret = csv_string_to_uid_array(ifp_ctx->rctx, uid_str, true, + &ifp_ctx->rctx->allowed_uids_count, + &ifp_ctx->rctx->allowed_uids); + talloc_free(uid_str); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to set allowed UIDs.\n")); + goto fail; + } + /* Enable automatic reconnection to the Data Provider */ ret = confdb_get_int(ifp_ctx->rctx->cdb, CONFDB_IFP_CONF_ENTRY, diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c index 26e32f338fd9aa354ef96575852b156a52b224f0..8bec96b7403652cb582ef571ac7de4b7c2a4b9b2 100644 --- a/src/responder/ifp/ifpsrv_util.c +++ b/src/responder/ifp/ifpsrv_util.c @@ -80,6 +80,19 @@ struct ifp_req *ifp_req_create(struct sbus_request *dbus_req, goto fail; } + ret = check_allowed_uids(req->caller, ifp_ctx->rctx->allowed_uids_count, + ifp_ctx->rctx->allowed_uids); + if (ret == EACCES) { + DEBUG(SSSDBG_MINOR_FAILURE, + "User %"SPRIuid" not in ACL\n", req->caller); + goto fail; + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot check if user %"SPRIuid" is present in ACL\n", + req->caller); + goto fail; + } + return req; fail: diff --git a/src/tests/cmocka/test_ifp.c b/src/tests/cmocka/test_ifp.c index 012dad4c5ec93fe6fbdf3e82c9ee172076550b2d..60c66e12e45c19d772d975c600cdaed8cd2ddb98 100644 --- a/src/tests/cmocka/test_ifp.c +++ b/src/tests/cmocka/test_ifp.c @@ -24,6 +24,7 @@ #include "db/sysdb.h" #include "tests/cmocka/common_mock.h" +#include "tests/cmocka/common_mock_resp.h" #include "responder/ifp/ifp_private.h" #include "sbus/sssd_dbus_private.h" @@ -35,6 +36,14 @@ mock_ifp_ctx(TALLOC_CTX *mem_ctx) ifp_ctx = talloc_zero(mem_ctx, struct ifp_ctx); assert_non_null(ifp_ctx); + ifp_ctx->rctx = mock_rctx(ifp_ctx, NULL, NULL, NULL); + assert_non_null(ifp_ctx->rctx); + + ifp_ctx->rctx->allowed_uids = talloc_array(ifp_ctx->rctx, uint32_t, 1); + assert_non_null(ifp_ctx->rctx->allowed_uids); + ifp_ctx->rctx->allowed_uids[0] = geteuid(); + ifp_ctx->rctx->allowed_uids_count = 1; + ifp_ctx->sysbus = talloc_zero(ifp_ctx, struct sysbus_ctx); assert_non_null(ifp_ctx->sysbus); @@ -71,6 +80,12 @@ unsigned long __wrap_dbus_bus_get_unix_user(DBusConnection *connection, const char *name, DBusError *error) { + unsigned long uid = sss_mock_type(unsigned long); + + if (uid) { + return uid; + } + return (unsigned long) geteuid(); } @@ -98,6 +113,7 @@ void ifp_test_req_create(void **state) assert_non_null(sr); check_leaks_push(sr); + will_return(__wrap_dbus_bus_get_unix_user, 0); ireq = ifp_req_create(sr, ifp_ctx); assert_non_null(ireq); @@ -113,6 +129,32 @@ void ifp_test_req_create(void **state) assert_true(leak_check_teardown()); } +void ifp_test_req_wrong_uid(void **state) +{ + struct ifp_req *ireq; + struct sbus_request *sr; + struct ifp_ctx *ifp_ctx; + + assert_true(leak_check_setup()); + + ifp_ctx = mock_ifp_ctx(global_talloc_context); + assert_non_null(ifp_ctx); + check_leaks_push(ifp_ctx); + + sr = mock_sbus_request(ifp_ctx); + assert_non_null(sr); + + will_return(__wrap_dbus_bus_get_unix_user, geteuid()+1); + ireq = ifp_req_create(sr, ifp_ctx); + assert_null(ireq); + talloc_free(sr); + + assert_true(check_leaks_pop(ifp_ctx) == true); + talloc_free(ifp_ctx); + + assert_true(leak_check_teardown()); +} + void test_path_prefix(void **state) { const char *prefix = "foo"; @@ -202,6 +244,7 @@ int main(int argc, const char *argv[]) const UnitTest tests[] = { unit_test(ifp_test_req_create), + unit_test(ifp_test_req_wrong_uid), unit_test(test_path_prefix), unit_test(test_el_to_dict), }; -- 1.9.0