|
|
9f2ebf |
From 73a04a5c53c0e7701aa7753fd459ffbea52e28b8 Mon Sep 17 00:00:00 2001
|
|
|
9f2ebf |
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
9f2ebf |
Date: Mon, 23 Oct 2017 18:08:12 +0200
|
|
|
9f2ebf |
Subject: [PATCH 48/57] TOOLS: Add a new sssctl command access-report
|
|
|
9f2ebf |
MIME-Version: 1.0
|
|
|
9f2ebf |
Content-Type: text/plain; charset=UTF-8
|
|
|
9f2ebf |
Content-Transfer-Encoding: 8bit
|
|
|
9f2ebf |
|
|
|
9f2ebf |
Resolves:
|
|
|
9f2ebf |
https://pagure.io/SSSD/sssd/issue/2840
|
|
|
9f2ebf |
|
|
|
9f2ebf |
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
|
|
9f2ebf |
Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
|
|
|
9f2ebf |
(cherry picked from commit 3ee8659bc6a77a78bc6c61b9650a36bd18ea95c8)
|
|
|
9f2ebf |
---
|
|
|
9f2ebf |
Makefile.am | 1 +
|
|
|
9f2ebf |
src/tools/sssctl/sssctl.c | 1 +
|
|
|
9f2ebf |
src/tools/sssctl/sssctl.h | 5 +
|
|
|
9f2ebf |
src/tools/sssctl/sssctl_access_report.c | 435 ++++++++++++++++++++++++++++++++
|
|
|
9f2ebf |
4 files changed, 442 insertions(+)
|
|
|
9f2ebf |
create mode 100644 src/tools/sssctl/sssctl_access_report.c
|
|
|
9f2ebf |
|
|
|
9f2ebf |
diff --git a/Makefile.am b/Makefile.am
|
|
|
9f2ebf |
index 16bcb4efc028b05c1196249245f4f3091b9366af..5917bd904054055a259eb69217282e4fb914c700 100644
|
|
|
9f2ebf |
--- a/Makefile.am
|
|
|
9f2ebf |
+++ b/Makefile.am
|
|
|
9f2ebf |
@@ -1754,6 +1754,7 @@ sssctl_SOURCES = \
|
|
|
9f2ebf |
src/tools/sssctl/sssctl_sifp.c \
|
|
|
9f2ebf |
src/tools/sssctl/sssctl_config.c \
|
|
|
9f2ebf |
src/tools/sssctl/sssctl_user_checks.c \
|
|
|
9f2ebf |
+ src/tools/sssctl/sssctl_access_report.c \
|
|
|
9f2ebf |
$(SSSD_TOOLS_OBJ) \
|
|
|
9f2ebf |
$(NULL)
|
|
|
9f2ebf |
sssctl_LDADD = \
|
|
|
9f2ebf |
diff --git a/src/tools/sssctl/sssctl.c b/src/tools/sssctl/sssctl.c
|
|
|
9f2ebf |
index 1e061c00d2238bf34adff4183e560dc127dd62c7..eee2d613966a5dda81627d2e225bfdc9bade4041 100644
|
|
|
9f2ebf |
--- a/src/tools/sssctl/sssctl.c
|
|
|
9f2ebf |
+++ b/src/tools/sssctl/sssctl.c
|
|
|
9f2ebf |
@@ -264,6 +264,7 @@ int main(int argc, const char **argv)
|
|
|
9f2ebf |
SSS_TOOL_COMMAND("domain-list", "List available domains", 0, sssctl_domain_list),
|
|
|
9f2ebf |
SSS_TOOL_COMMAND("domain-status", "Print information about domain", 0, sssctl_domain_status),
|
|
|
9f2ebf |
SSS_TOOL_COMMAND("user-checks", "Print information about a user and check authentication", 0, sssctl_user_checks),
|
|
|
9f2ebf |
+ SSS_TOOL_COMMAND("access-report", "Generate access report for a domain", 0, sssctl_access_report),
|
|
|
9f2ebf |
SSS_TOOL_DELIMITER("Information about cached content:"),
|
|
|
9f2ebf |
SSS_TOOL_COMMAND("user-show", "Information about cached user", 0, sssctl_user_show),
|
|
|
9f2ebf |
SSS_TOOL_COMMAND("group-show", "Information about cached group", 0, sssctl_group_show),
|
|
|
9f2ebf |
diff --git a/src/tools/sssctl/sssctl.h b/src/tools/sssctl/sssctl.h
|
|
|
9f2ebf |
index 22ca5d41e2c084e64b58bc5aa066414b002e7e8b..70fc19eff07317c264978a1ecb9159ae3acdfced 100644
|
|
|
9f2ebf |
--- a/src/tools/sssctl/sssctl.h
|
|
|
9f2ebf |
+++ b/src/tools/sssctl/sssctl.h
|
|
|
9f2ebf |
@@ -133,4 +133,9 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline,
|
|
|
9f2ebf |
errno_t sssctl_user_checks(struct sss_cmdline *cmdline,
|
|
|
9f2ebf |
struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
void *pvt);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+errno_t sssctl_access_report(struct sss_cmdline *cmdline,
|
|
|
9f2ebf |
+ struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
+ void *pvt);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
#endif /* _SSSCTL_H_ */
|
|
|
9f2ebf |
diff --git a/src/tools/sssctl/sssctl_access_report.c b/src/tools/sssctl/sssctl_access_report.c
|
|
|
9f2ebf |
new file mode 100644
|
|
|
9f2ebf |
index 0000000000000000000000000000000000000000..11172329817b4dedaca480ab8a4537149853c330
|
|
|
9f2ebf |
--- /dev/null
|
|
|
9f2ebf |
+++ b/src/tools/sssctl/sssctl_access_report.c
|
|
|
9f2ebf |
@@ -0,0 +1,435 @@
|
|
|
9f2ebf |
+/*
|
|
|
9f2ebf |
+ Copyright (C) 2017 Red Hat
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ This program is free software; you can redistribute it and/or modify
|
|
|
9f2ebf |
+ it under the terms of the GNU Lesser General Public License as published by
|
|
|
9f2ebf |
+ the Free Software Foundation; either version 3 of the License, or
|
|
|
9f2ebf |
+ (at your option) any later version.
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ This program is distributed in the hope that it will be useful,
|
|
|
9f2ebf |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
9f2ebf |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
9f2ebf |
+ GNU Lesser General Public License for more details.
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ You should have received a copy of the GNU Lesser General Public License
|
|
|
9f2ebf |
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
9f2ebf |
+*/
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#include <security/pam_appl.h>
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#include "util/util.h"
|
|
|
9f2ebf |
+#include "tools/common/sss_tools.h"
|
|
|
9f2ebf |
+#include "tools/sssctl/sssctl.h"
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+/*
|
|
|
9f2ebf |
+ * We're searching the cache directly..
|
|
|
9f2ebf |
+ */
|
|
|
9f2ebf |
+#include "providers/ipa/ipa_hbac_private.h"
|
|
|
9f2ebf |
+#include "providers/ipa/ipa_rules_common.h"
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#ifdef HAVE_SECURITY_PAM_MISC_H
|
|
|
9f2ebf |
+# include <security/pam_misc.h>
|
|
|
9f2ebf |
+#elif defined(HAVE_SECURITY_OPENPAM_H)
|
|
|
9f2ebf |
+# include <security/openpam.h>
|
|
|
9f2ebf |
+#endif
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#ifdef HAVE_SECURITY_PAM_MISC_H
|
|
|
9f2ebf |
+static struct pam_conv conv = {
|
|
|
9f2ebf |
+ misc_conv,
|
|
|
9f2ebf |
+ NULL
|
|
|
9f2ebf |
+};
|
|
|
9f2ebf |
+#elif defined(HAVE_SECURITY_OPENPAM_H)
|
|
|
9f2ebf |
+static struct pam_conv conv = {
|
|
|
9f2ebf |
+ openpam_ttyconv,
|
|
|
9f2ebf |
+ NULL
|
|
|
9f2ebf |
+};
|
|
|
9f2ebf |
+#else
|
|
|
9f2ebf |
+# error "Missing text based pam conversation function"
|
|
|
9f2ebf |
+#endif
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#ifndef DEFAULT_SERVICE
|
|
|
9f2ebf |
+#define DEFAULT_SERVICE "system-auth"
|
|
|
9f2ebf |
+#endif /* DEFAULT_SERVICE */
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+#ifndef DEFAULT_USER
|
|
|
9f2ebf |
+#define DEFAULT_USER "admin"
|
|
|
9f2ebf |
+#endif /* DEFAULT_USER */
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+typedef errno_t (*sssctl_dom_access_reporter_fn)(struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
+ const char *user,
|
|
|
9f2ebf |
+ const char *service,
|
|
|
9f2ebf |
+ struct sss_domain_info *domain);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t run_pam_acct(struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
+ const char *user,
|
|
|
9f2ebf |
+ const char *service,
|
|
|
9f2ebf |
+ struct sss_domain_info *domain)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ pam_handle_t *pamh;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = pam_start(service, user, &conv, &pamh);
|
|
|
9f2ebf |
+ if (ret != PAM_SUCCESS) {
|
|
|
9f2ebf |
+ ERROR("pam_start failed: %s\n", pam_strerror(pamh, ret));
|
|
|
9f2ebf |
+ return EIO;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = pam_acct_mgmt(pamh, 0);
|
|
|
9f2ebf |
+ pam_end(pamh, ret);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t get_rdn_value(TALLOC_CTX *mem_ctx,
|
|
|
9f2ebf |
+ struct sss_domain_info *dom,
|
|
|
9f2ebf |
+ const char *dn_attr,
|
|
|
9f2ebf |
+ const char **_rdn_value)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ TALLOC_CTX *tmp_ctx;
|
|
|
9f2ebf |
+ struct ldb_dn *dn = NULL;
|
|
|
9f2ebf |
+ const struct ldb_val *rdn_val;
|
|
|
9f2ebf |
+ const char *rdn_str;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tmp_ctx = talloc_new(NULL);
|
|
|
9f2ebf |
+ if (tmp_ctx == NULL) {
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(dom->sysdb), dn_attr);
|
|
|
9f2ebf |
+ if (dn == NULL) {
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ rdn_val = ldb_dn_get_rdn_val(dn);
|
|
|
9f2ebf |
+ if (rdn_val == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_OP_FAILURE, "No RDN value?\n");
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ rdn_str = talloc_strndup(tmp_ctx,
|
|
|
9f2ebf |
+ (const char *)rdn_val->data,
|
|
|
9f2ebf |
+ rdn_val->length);
|
|
|
9f2ebf |
+ if (rdn_str == NULL) {
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = EOK;
|
|
|
9f2ebf |
+ *_rdn_value = talloc_steal(mem_ctx, rdn_str);
|
|
|
9f2ebf |
+done:
|
|
|
9f2ebf |
+ talloc_zfree(tmp_ctx);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t is_member_group(struct sss_domain_info *dom,
|
|
|
9f2ebf |
+ const char *dn_attr,
|
|
|
9f2ebf |
+ const char *group_rdn,
|
|
|
9f2ebf |
+ bool *_is_group)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ const char *comp_name;
|
|
|
9f2ebf |
+ const struct ldb_val *comp_val;
|
|
|
9f2ebf |
+ TALLOC_CTX *tmp_ctx;
|
|
|
9f2ebf |
+ bool is_group = false;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ struct ldb_dn *dn = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tmp_ctx = talloc_new(NULL);
|
|
|
9f2ebf |
+ if (tmp_ctx == NULL) {
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ dn = ldb_dn_new(tmp_ctx, sysdb_ctx_get_ldb(dom->sysdb), dn_attr);
|
|
|
9f2ebf |
+ if (dn == NULL) {
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ comp_name = ldb_dn_get_component_name(dn, 1);
|
|
|
9f2ebf |
+ comp_val = ldb_dn_get_component_val(dn, 1);
|
|
|
9f2ebf |
+ if (strcasecmp("cn", comp_name) == 0
|
|
|
9f2ebf |
+ && strncasecmp(group_rdn,
|
|
|
9f2ebf |
+ (const char *) comp_val->data,
|
|
|
9f2ebf |
+ comp_val->length) == 0) {
|
|
|
9f2ebf |
+ is_group = true;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = EOK;
|
|
|
9f2ebf |
+done:
|
|
|
9f2ebf |
+ *_is_group = is_group;
|
|
|
9f2ebf |
+ talloc_zfree(tmp_ctx);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void print_category(struct sss_domain_info *domain,
|
|
|
9f2ebf |
+ struct ldb_message *rule_msg,
|
|
|
9f2ebf |
+ const char *category_attr_name,
|
|
|
9f2ebf |
+ const char *category_label)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ldb_message_element *category_attr;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ category_attr = ldb_msg_find_element(rule_msg, category_attr_name);
|
|
|
9f2ebf |
+ if (category_attr == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot find %s\n", category_attr_name);
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (category_attr->num_values > 0) {
|
|
|
9f2ebf |
+ PRINT("\t%s: ", category_label);
|
|
|
9f2ebf |
+ for (unsigned i = 0; i < category_attr->num_values; i++) {
|
|
|
9f2ebf |
+ PRINT("%s%s",
|
|
|
9f2ebf |
+ i > 0 ? ", " : "",
|
|
|
9f2ebf |
+ (const char *) category_attr->values[i].data);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ PRINT("\n");
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void print_member_attr(struct sss_domain_info *domain,
|
|
|
9f2ebf |
+ struct ldb_message *rule_msg,
|
|
|
9f2ebf |
+ const char *member_attr_name,
|
|
|
9f2ebf |
+ const char *group_rdn,
|
|
|
9f2ebf |
+ const char *object_label,
|
|
|
9f2ebf |
+ const char *group_label)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ TALLOC_CTX *tmp_ctx = NULL;
|
|
|
9f2ebf |
+ const char **member_names = NULL;
|
|
|
9f2ebf |
+ size_t name_count = 0;
|
|
|
9f2ebf |
+ const char **member_group_names = NULL;
|
|
|
9f2ebf |
+ size_t group_count = 0;
|
|
|
9f2ebf |
+ struct ldb_message_element *member_attr = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tmp_ctx = talloc_new(NULL);
|
|
|
9f2ebf |
+ if (tmp_ctx == NULL) {
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ member_attr = ldb_msg_find_element(rule_msg, member_attr_name);
|
|
|
9f2ebf |
+ if (member_attr == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot find %s\n", member_attr_name);
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ member_names = talloc_zero_array(tmp_ctx,
|
|
|
9f2ebf |
+ const char *,
|
|
|
9f2ebf |
+ member_attr->num_values + 1);
|
|
|
9f2ebf |
+ member_group_names = talloc_zero_array(tmp_ctx,
|
|
|
9f2ebf |
+ const char *,
|
|
|
9f2ebf |
+ member_attr->num_values + 1);
|
|
|
9f2ebf |
+ if (member_names == NULL || member_group_names == NULL) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "OOM?\n");
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ for (size_t i = 0; i < member_attr->num_values; i++) {
|
|
|
9f2ebf |
+ bool is_group;
|
|
|
9f2ebf |
+ const char *rdn_string;
|
|
|
9f2ebf |
+ const char *dn_attr;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ dn_attr = (const char *) member_attr->values[i].data;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = is_member_group(domain, dn_attr, group_rdn, &is_group);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ continue;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = get_rdn_value(tmp_ctx, domain, dn_attr, &rdn_string);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ continue;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (is_group == false) {
|
|
|
9f2ebf |
+ member_names[name_count] = talloc_steal(member_names,
|
|
|
9f2ebf |
+ rdn_string);
|
|
|
9f2ebf |
+ if (member_names[name_count] == NULL) {
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ name_count++;
|
|
|
9f2ebf |
+ } else {
|
|
|
9f2ebf |
+ member_group_names[group_count] = talloc_strdup(member_group_names,
|
|
|
9f2ebf |
+ rdn_string);
|
|
|
9f2ebf |
+ if (member_group_names[group_count] == NULL) {
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ group_count++;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (member_names[0] != NULL) {
|
|
|
9f2ebf |
+ PRINT("\t%s: ", object_label);
|
|
|
9f2ebf |
+ for (int i = 0; member_names[i]; i++) {
|
|
|
9f2ebf |
+ PRINT("%s%s", i > 0 ? ", " : "", member_names[i]);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ PRINT("\n");
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (member_group_names[0] != NULL) {
|
|
|
9f2ebf |
+ PRINT("\t%s: ", group_label);
|
|
|
9f2ebf |
+ for (int i = 0; member_group_names[i]; i++) {
|
|
|
9f2ebf |
+ PRINT("%s%s", i > 0 ? ", " : "", member_group_names[i]);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+ PRINT("\n");
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+done:
|
|
|
9f2ebf |
+ talloc_free(tmp_ctx);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static void print_ipa_hbac_rule(struct sss_domain_info *domain,
|
|
|
9f2ebf |
+ struct ldb_message *rule_msg)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ struct ldb_message_element *el;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ el = ldb_msg_find_element(rule_msg, IPA_CN);
|
|
|
9f2ebf |
+ if (el == NULL || el->num_values < 1) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_MINOR_FAILURE, "A rule with no name\n");
|
|
|
9f2ebf |
+ return;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ PRINT("Rule name: %1$s\n", el->values[0].data);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ print_member_attr(domain,
|
|
|
9f2ebf |
+ rule_msg,
|
|
|
9f2ebf |
+ IPA_MEMBER_USER,
|
|
|
9f2ebf |
+ "groups",
|
|
|
9f2ebf |
+ _("Member users"),
|
|
|
9f2ebf |
+ _("Member groups"));
|
|
|
9f2ebf |
+ print_category(domain,
|
|
|
9f2ebf |
+ rule_msg,
|
|
|
9f2ebf |
+ IPA_USER_CATEGORY,
|
|
|
9f2ebf |
+ _("User category"));
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ print_member_attr(domain,
|
|
|
9f2ebf |
+ rule_msg,
|
|
|
9f2ebf |
+ IPA_MEMBER_SERVICE,
|
|
|
9f2ebf |
+ "hbacservicegroups",
|
|
|
9f2ebf |
+ _("Member services"),
|
|
|
9f2ebf |
+ _("Member service groups"));
|
|
|
9f2ebf |
+ print_category(domain,
|
|
|
9f2ebf |
+ rule_msg,
|
|
|
9f2ebf |
+ IPA_SERVICE_CATEGORY,
|
|
|
9f2ebf |
+ _("Service category"));
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ PRINT("\n");
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+static errno_t sssctl_ipa_access_report(struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
+ const char *user,
|
|
|
9f2ebf |
+ const char *service,
|
|
|
9f2ebf |
+ struct sss_domain_info *domain)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ TALLOC_CTX *tmp_ctx = NULL;
|
|
|
9f2ebf |
+ const char *filter = NULL;
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ const char *attrs[] = {
|
|
|
9f2ebf |
+ OBJECTCLASS,
|
|
|
9f2ebf |
+ IPA_CN,
|
|
|
9f2ebf |
+ IPA_MEMBER_USER,
|
|
|
9f2ebf |
+ IPA_USER_CATEGORY,
|
|
|
9f2ebf |
+ IPA_MEMBER_SERVICE,
|
|
|
9f2ebf |
+ IPA_SERVICE_CATEGORY,
|
|
|
9f2ebf |
+ IPA_MEMBER_HOST,
|
|
|
9f2ebf |
+ IPA_HOST_CATEGORY,
|
|
|
9f2ebf |
+ NULL,
|
|
|
9f2ebf |
+ };
|
|
|
9f2ebf |
+ size_t rule_count;
|
|
|
9f2ebf |
+ struct ldb_message **msgs = NULL;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* Run the pam account phase to make sure the rules are fetched by SSSD */
|
|
|
9f2ebf |
+ ret = run_pam_acct(tool_ctx, user, service, domain);
|
|
|
9f2ebf |
+ if (ret != PAM_SUCCESS && ret != PAM_PERM_DENIED) {
|
|
|
9f2ebf |
+ ERROR("Cannot run the PAM account phase, reporting stale rules\n");
|
|
|
9f2ebf |
+ /* Non-fatal */
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ tmp_ctx = talloc_new(tool_ctx);
|
|
|
9f2ebf |
+ if (tmp_ctx == NULL) {
|
|
|
9f2ebf |
+ return ENOMEM;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ filter = talloc_asprintf(tmp_ctx, "(objectClass=%s)", IPA_HBAC_RULE);
|
|
|
9f2ebf |
+ if (filter == NULL) {
|
|
|
9f2ebf |
+ ret = ENOMEM;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sysdb_search_custom(tmp_ctx, domain, filter,
|
|
|
9f2ebf |
+ HBAC_RULES_SUBDIR, attrs,
|
|
|
9f2ebf |
+ &rule_count, &msgs);
|
|
|
9f2ebf |
+ if (ret != EOK && ret != ENOENT) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up HBAC rules\n");
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ if (ret == ENOENT) {
|
|
|
9f2ebf |
+ PRINT("No cached rules. All users will be denied access\n");
|
|
|
9f2ebf |
+ ret = EOK;
|
|
|
9f2ebf |
+ goto done;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ PRINT("%1$zu rules cached\n\n", rule_count);
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ for (size_t i = 0; i < rule_count; i++) {
|
|
|
9f2ebf |
+ print_ipa_hbac_rule(domain, msgs[i]);
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = EOK;
|
|
|
9f2ebf |
+done:
|
|
|
9f2ebf |
+ talloc_zfree(tmp_ctx);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+sssctl_dom_access_reporter_fn get_report_fn(const char *provider)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ if (strcmp(provider, "ipa") == 0) {
|
|
|
9f2ebf |
+ return sssctl_ipa_access_report;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return NULL;
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+errno_t sssctl_access_report(struct sss_cmdline *cmdline,
|
|
|
9f2ebf |
+ struct sss_tool_ctx *tool_ctx,
|
|
|
9f2ebf |
+ void *pvt)
|
|
|
9f2ebf |
+{
|
|
|
9f2ebf |
+ errno_t ret;
|
|
|
9f2ebf |
+ const char *domname = NULL;
|
|
|
9f2ebf |
+ sssctl_dom_access_reporter_fn reporter;
|
|
|
9f2ebf |
+ struct sss_domain_info *dom;
|
|
|
9f2ebf |
+ const char *user = DEFAULT_USER;
|
|
|
9f2ebf |
+ const char *service = DEFAULT_SERVICE;
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ /* Parse command line. */
|
|
|
9f2ebf |
+ struct poptOption options[] = {
|
|
|
9f2ebf |
+ { "user", 'u', POPT_ARG_STRING, &user, 0,
|
|
|
9f2ebf |
+ _("PAM user, default: " DEFAULT_USER), NULL },
|
|
|
9f2ebf |
+ { "service", 's', POPT_ARG_STRING, &service, 0,
|
|
|
9f2ebf |
+ _("PAM service, default: " DEFAULT_SERVICE), NULL },
|
|
|
9f2ebf |
+ POPT_TABLEEND
|
|
|
9f2ebf |
+ };
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ ret = sss_tool_popt_ex(cmdline, options, SSS_TOOL_OPT_OPTIONAL,
|
|
|
9f2ebf |
+ NULL, NULL, "DOMAIN", _("Specify domain name."),
|
|
|
9f2ebf |
+ &domname, NULL);
|
|
|
9f2ebf |
+ if (ret != EOK) {
|
|
|
9f2ebf |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ dom = find_domain_by_name(tool_ctx->domains, domname, true);
|
|
|
9f2ebf |
+ if (dom == NULL) {
|
|
|
9f2ebf |
+ ERROR("Cannot find domain %1$s\n", domname);
|
|
|
9f2ebf |
+ return ERR_DOMAIN_NOT_FOUND;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ reporter = get_report_fn(dom->provider);
|
|
|
9f2ebf |
+ if (reporter == NULL) {
|
|
|
9f2ebf |
+ ERROR("Access report not implemented for domains of type %1$s\n",
|
|
|
9f2ebf |
+ dom->provider);
|
|
|
9f2ebf |
+ return ret;
|
|
|
9f2ebf |
+ }
|
|
|
9f2ebf |
+
|
|
|
9f2ebf |
+ return reporter(tool_ctx, user, service, dom);
|
|
|
9f2ebf |
+}
|
|
|
9f2ebf |
--
|
|
|
9f2ebf |
2.14.3
|
|
|
9f2ebf |
|