diff options
Diffstat (limited to '')
-rw-r--r-- | src/tools/sssctl/sssctl_domains.c | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/src/tools/sssctl/sssctl_domains.c b/src/tools/sssctl/sssctl_domains.c new file mode 100644 index 0000000..ee8cb13 --- /dev/null +++ b/src/tools/sssctl/sssctl_domains.c @@ -0,0 +1,408 @@ +/* + Authors: + Pavel Březina <pbrezina@redhat.com> + + Copyright (C) 2016 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <popt.h> +#include <stdio.h> +#include <talloc.h> + +#include "util/util.h" +#include "tools/common/sss_tools.h" +#include "tools/sssctl/sssctl.h" +#include "sbus/sbus_opath.h" +#include "responder/ifp/ifp_iface/ifp_iface_sync.h" + +static errno_t +sssctl_domain_list_get_properties(TALLOC_CTX *mem_ctx, + struct sbus_sync_connection *conn, + const char *path, + const char **_name, + bool *_is_subdom) +{ + errno_t ret; + + if (_name != NULL) { + ret = sbus_get_ifp_domains_name(mem_ctx, conn, IFP_BUS, path, _name); + if (ret != EOK) { + goto done; + } + } + + if (_is_subdom != NULL) { + ret = sbus_get_ifp_domains_subdomain(conn, IFP_BUS, path, _is_subdom); + if (ret != EOK) { + goto done; + } + } + + ret = EOK; + +done: + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain property [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + } + + return ret; +} + +errno_t sssctl_domain_list(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) +{ + TALLOC_CTX *tmp_ctx; + struct sbus_sync_connection *conn; + const char **paths; + const char *name; + bool is_subdom; + int start = 0; + int verbose = 0; + errno_t ret; + int i; + + /* Parse command line. */ + struct poptOption options[] = { + {"start", 's', POPT_ARG_NONE, &start, 0, _("Start SSSD if it is not running"), NULL }, + {"verbose", 'v', POPT_ARG_NONE, &verbose, 0, _("Show domain list including primary or trusted domain type"), NULL }, + POPT_TABLEEND + }; + + ret = sss_tool_popt(cmdline, options, SSS_TOOL_OPT_OPTIONAL, NULL, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); + return ret; + } + + if (!sssctl_start_sssd(start)) { + return ERR_SSSD_NOT_RUNNING; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n"); + return ENOMEM; + } + + conn = sbus_sync_connect_system(tmp_ctx, NULL); + if (conn == NULL) { + ERROR("Unable to connect to system bus!\n"); + ret = EIO; + goto done; + } + + ret = sbus_call_ifp_ListDomains(tmp_ctx, conn, IFP_BUS, IFP_PATH, &paths); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to list domains [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + goto done; + } + + if (verbose) { + for (i = 0; paths[i] != NULL; i++) { + ret = sssctl_domain_list_get_properties(tmp_ctx, conn, paths[i], + &name, &is_subdom); + if (ret != EOK) { + goto done; + } + + if (is_subdom) { + printf("Trusted domain: %s\n", name); + } else { + printf("Primary domain: %s\n", name); + } + } + + return EOK; + } + + for (i = 0; paths[i] != NULL; i++) { + ret = sssctl_domain_list_get_properties(tmp_ctx, conn, paths[i], + &name, NULL); + if (ret != EOK) { + goto done; + } + + puts(name); + } + +done: + talloc_free(tmp_ctx); + + return ret; +} + +static errno_t +sssctl_domain_status_online(struct sbus_sync_connection *conn, + const char *domain_path) +{ + bool is_online; + errno_t ret; + + ret = sbus_call_ifp_domain_IsOnline(conn, IFP_BUS, domain_path, &is_online); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain status [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + return ret; + } + + PRINT("Online status: %s\n", is_online ? _("Online") : _("Offline")); + + return EOK; +} + +static const char *proper_service_name(const char *service) +{ + if (strcasecmp(service, "AD_GC") == 0) { + return "AD Global Catalog"; + } else if (strcasecmp(service, "AD") == 0) { + return "AD Domain Controller"; + } else if (strncasecmp(service, "sd_gc_", strlen("sd_gc_")) == 0) { + return "AD Global Catalog"; + } else if (strncasecmp(service, "sd_", strlen("sd_")) == 0) { + return "AD Domain Controller"; + } + + return service; +} + +static errno_t +sssctl_domain_status_active_server(struct sbus_sync_connection *conn, + const char *domain_path) +{ + TALLOC_CTX *tmp_ctx; + const char *server; + const char **services; + errno_t ret; + int i; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + ret = sbus_call_ifp_domain_ListServices(tmp_ctx, conn, IFP_BUS, + domain_path, &services); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain services [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + goto done; + } + + if (services == NULL) { + PRINT("This domain has no active servers.\n"); + ret = EOK; + goto done; + } + + PRINT("Active servers:\n"); + for (i = 0; services[i] != NULL; i++) { + ret = sbus_call_ifp_domain_ActiveServer(tmp_ctx, conn, IFP_BUS, + domain_path, services[i], &server); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get active server [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + goto done; + } + + /* SBUS_REQ_STRING_DEFAULT handles (server == NULL) case gracefully */ + server = SBUS_REQ_STRING_DEFAULT(server, _("not connected")); + printf("%s: %s\n", proper_service_name(services[i]), server); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t +sssctl_domain_status_server_list(struct sbus_sync_connection *conn, + const char *domain_path) +{ + TALLOC_CTX *tmp_ctx; + const char **servers; + const char **services; + errno_t ret; + int i, j; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + ret = sbus_call_ifp_domain_ListServices(tmp_ctx, conn, IFP_BUS, + domain_path, &services); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain services [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + goto done; + } + + if (services == NULL) { + PRINT("No servers discovered.\n"); + ret = EOK; + goto done; + } + + for (i = 0; services[i] != NULL; i++) { + PRINT("Discovered %s servers:\n", proper_service_name(services[i])); + + ret = sbus_call_ifp_domain_ListServers(tmp_ctx, conn, IFP_BUS, + domain_path, services[i], &servers); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain servers [%d]: %s\n", + ret, sss_strerror(ret)); + PRINT_IFP_WARNING(ret); + goto done; + } + + if (servers == NULL || servers[0] == NULL) { + PRINT("None so far.\n"); + continue; + } + + for (j = 0; servers[j] != NULL; j++) { + printf("- %s\n", servers[j]); + } + + printf("\n"); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +struct sssctl_domain_status_opts { + const char *domain; + int online; + int last; + int active; + int servers; + int force_start; +}; + +errno_t sssctl_domain_status(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) +{ + TALLOC_CTX *tmp_ctx = NULL; + struct sssctl_domain_status_opts opts = {0}; + struct sbus_sync_connection *conn; + const char *path; + bool opt_set; + errno_t ret; + + /* Parse command line. */ + struct poptOption options[] = { + {"online", 'o', POPT_ARG_NONE , &opts.online, 0, _("Show online status"), NULL }, + {"active-server", 'a', POPT_ARG_NONE, &opts.active, 0, _("Show information about active server"), NULL }, + {"servers", 'r', POPT_ARG_NONE, &opts.servers, 0, _("Show list of discovered servers"), NULL }, + {"start", 's', POPT_ARG_NONE, &opts.force_start, 0, _("Start SSSD if it is not running"), NULL }, + POPT_TABLEEND + }; + + ret = sss_tool_popt_ex(cmdline, options, SSS_TOOL_OPT_OPTIONAL, + NULL, NULL, "DOMAIN", _("Specify domain name."), + SSS_TOOL_OPT_REQUIRED, &opts.domain, &opt_set); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n"); + goto done; + } + + if (opt_set == false) { + opts.online = true; + opts.last = true; + opts.active = true; + opts.servers = true; + } + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + path = sbus_opath_compose(tmp_ctx, IFP_PATH_DOMAINS, opts.domain); + if (path == NULL) { + PRINT("Out of memory!\n"); + ret = ENOMEM; + goto done; + } + + if (!sssctl_start_sssd(opts.force_start)) { + ret = ERR_SSSD_NOT_RUNNING; + goto done; + } + + conn = sbus_sync_connect_system(tmp_ctx, NULL); + if (conn == NULL) { + ERROR("Unable to connect to system bus!\n"); + ret = EIO; + goto done; + } + + if (opts.online) { + ret = sssctl_domain_status_online(conn, path); + if (ret != EOK) { + ERROR("Unable to get online status\n"); + goto done; + } + + printf("\n"); + } + + if (opts.active) { + ret = sssctl_domain_status_active_server(conn, path); + if (ret != EOK) { + ERROR("Unable to get online status\n"); + goto done; + } + + printf("\n"); + } + + if (opts.servers) { + ret = sssctl_domain_status_server_list(conn, path); + if (ret != EOK) { + ERROR("Unable to get server list\n"); + goto done; + } + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + free(discard_const(opts.domain)); + + return ret; +} |