/* SSSD IPA Provider Initialization functions Authors: Simo Sorce Copyright (C) 2009 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 . */ #include #include #include #include #include "util/child_common.h" #include "providers/ipa/ipa_common.h" #include "providers/krb5/krb5_auth.h" #include "providers/krb5/krb5_init_shared.h" #include "providers/ipa/ipa_id.h" #include "providers/ipa/ipa_auth.h" #include "providers/ipa/ipa_access.h" #include "providers/ipa/ipa_hostid.h" #include "providers/ipa/ipa_dyndns.h" #include "providers/ipa/ipa_selinux.h" #include "providers/ldap/sdap_access.h" #include "providers/ldap/sdap_idmap.h" #include "providers/ipa/ipa_subdomains.h" #include "providers/ipa/ipa_srv.h" #include "providers/be_dyndns.h" #define DNS_SRV_MISCONFIGURATION "SRV discovery is enabled on the IPA " \ "server while using custom dns_discovery_domain. DNS discovery of " \ "trusted AD domain will likely fail. It is recommended not to use " \ "SRV discovery or the dns_discovery_domain option for the IPA " \ "domain while running on the server itself\n" #define PREAUTH_INDICATOR_ERROR "Failed to create preauth indicator file, " \ "special password prompting might not be available.\n" struct ipa_init_ctx { struct ipa_options *options; struct ipa_id_ctx *id_ctx; struct ipa_auth_ctx *auth_ctx; }; static bool srv_in_server_list(const char *servers) { TALLOC_CTX *tmp_ctx; char **list = NULL; int ret = 0; bool has_srv = false; if (servers == NULL) return true; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return false; } /* split server parm into a list */ ret = split_on_separator(tmp_ctx, servers, ',', true, true, &list, NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse server list!\n"); goto done; } for (int i = 0; list[i]; i++) { has_srv = be_fo_is_srv_identifier(list[i]); if (has_srv == true) { break; } } done: talloc_free(tmp_ctx); return has_srv; } static errno_t ipa_init_options(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options **_ipa_options) { struct ipa_options *ipa_options; const char *ipa_servers; const char *ipa_backup_servers; errno_t ret; ret = ipa_get_options(mem_ctx, be_ctx->cdb, be_ctx->conf_path, be_ctx->domain, &ipa_options); if (ret != EOK) { return ret; } ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); ipa_backup_servers = dp_opt_get_string(ipa_options->basic, IPA_BACKUP_SERVER); ret = ipa_service_init(ipa_options, be_ctx, ipa_servers, ipa_backup_servers, ipa_options, &ipa_options->service); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to init IPA service [%d]: %s\n", ret, sss_strerror(ret)); talloc_free(ipa_options); return ret; } *_ipa_options = ipa_options; return EOK; } static errno_t ipa_init_id_ctx(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx **_ipa_id_ctx) { struct ipa_id_ctx *ipa_id_ctx = NULL; struct sdap_id_ctx *sdap_id_ctx = NULL; errno_t ret; ipa_id_ctx = talloc_zero(mem_ctx, struct ipa_id_ctx); if (ipa_id_ctx == NULL) { ret = ENOMEM; goto done; } sdap_id_ctx = sdap_id_ctx_new(mem_ctx, be_ctx, ipa_options->service->sdap); if (sdap_id_ctx == NULL) { ret = ENOMEM; goto done; } ipa_id_ctx->ipa_options = ipa_options; ipa_id_ctx->sdap_id_ctx = sdap_id_ctx; ipa_options->id_ctx = ipa_id_ctx; ret = ipa_get_id_options(ipa_options, be_ctx->cdb, be_ctx->conf_path, &sdap_id_ctx->opts); if (ret != EOK) { goto done; } *_ipa_id_ctx = ipa_id_ctx; ret = EOK; done: if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init id context [%d]: %s\n", ret, sss_strerror(ret)); talloc_free(ipa_id_ctx); talloc_free(sdap_id_ctx); } return ret; } static errno_t ipa_init_dyndns(struct be_ctx *be_ctx, struct ipa_options *ipa_options) { bool enabled; errno_t ret; ret = ipa_get_dyndns_options(be_ctx, ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get dyndns options [%d]: %s\n", ret, sss_strerror(ret)); return ret; } enabled = dp_opt_get_bool(ipa_options->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE); if (!enabled) { DEBUG(SSSDBG_CONF_SETTINGS, "Dynamic DNS updates are of.\n"); return EOK; } /* Perform automatic DNS updates when the IP address changes. * Register a callback for successful LDAP reconnections. * This is the easiest way to identify that we have gone online. */ DEBUG(SSSDBG_CONF_SETTINGS, "Dynamic DNS updates are on. Checking for nsupdate...\n"); ret = be_nsupdate_check(); if (ret != EOK) { DEBUG(SSSDBG_CONF_SETTINGS, "nsupdate is not availabe, " "dynamic DNS updates will not work\n"); return EOK; } DEBUG(SSSDBG_CONF_SETTINGS, "nsupdate is available\n"); ret = ipa_dyndns_init(be_ctx, ipa_options); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Failure setting up automatic DNS update\n"); /* We will continue without DNS updating */ } return EOK; } static errno_t ipa_init_server_mode(struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx *ipa_id_ctx) { const char *ipa_servers; const char *dnsdomain; const char *hostname; bool sites_enabled; errno_t ret; ipa_id_ctx->view_name = talloc_strdup(ipa_id_ctx, SYSDB_DEFAULT_VIEW_NAME); if (ipa_id_ctx->view_name == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup() failed.\n"); return ENOMEM; } ret = sysdb_update_view_name(be_ctx->domain->sysdb, ipa_id_ctx->view_name); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add/update view name to sysdb.\n"); return ret; } hostname = dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME); ipa_servers = dp_opt_get_string(ipa_options->basic, IPA_SERVER); sites_enabled = dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES); dnsdomain = dp_opt_get_string(be_ctx->be_res->opts, DP_RES_OPT_DNS_DOMAIN); if (srv_in_server_list(ipa_servers) || sites_enabled) { DEBUG(SSSDBG_MINOR_FAILURE, "SRV resolution or IPA sites enabled " "on the IPA server. Site discovery of trusted AD servers " "might not work.\n"); /* If SRV discovery is enabled on the server and * dns_discovery_domain is set explicitly, then * the current failover code would use the dns_discovery * domain to try to find AD servers and fail. */ if (dnsdomain != NULL) { sss_log(SSS_LOG_ERR, DNS_SRV_MISCONFIGURATION); DEBUG(SSSDBG_CRIT_FAILURE, DNS_SRV_MISCONFIGURATION); } ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, hostname); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } return EOK; } else { /* In server mode we need to ignore the dns_discovery_domain if set * and only discover servers based on AD domains. */ ret = dp_opt_set_string(be_ctx->be_res->opts, DP_RES_OPT_DNS_DOMAIN, NULL); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Could not reset the " "dns_discovery_domain, trusted AD domains discovery " "might fail. Please remove dns_discovery_domain " "from the config file and restart the SSSD\n"); } else { DEBUG(SSSDBG_CONF_SETTINGS, "The value of dns_discovery_domain " "will be ignored in ipa_server_mode\n"); } } return EOK; } static errno_t ipa_init_client_mode(struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx *ipa_id_ctx) { struct ipa_srv_plugin_ctx *srv_ctx; const char *ipa_domain; const char *hostname; bool sites_enabled; errno_t ret; ret = sysdb_get_view_name(ipa_id_ctx, be_ctx->domain->sysdb, &ipa_id_ctx->view_name); if (ret == ENOENT) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find view name in the cache. " "Will do online lookup later.\n"); } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name() failed [%d]: %s\n", ret, sss_strerror(ret)); return ret; } hostname = dp_opt_get_string(ipa_options->basic, IPA_HOSTNAME); sites_enabled = dp_opt_get_bool(ipa_options->basic, IPA_ENABLE_DNS_SITES); if (sites_enabled) { /* use IPA plugin */ ipa_domain = dp_opt_get_string(ipa_options->basic, IPA_DOMAIN); srv_ctx = ipa_srv_plugin_ctx_init(be_ctx, be_ctx->be_res->resolv, hostname, ipa_domain); if (srv_ctx == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n"); return ENOMEM; } be_fo_set_srv_lookup_plugin(be_ctx, ipa_srv_plugin_send, ipa_srv_plugin_recv, srv_ctx, "IPA"); } else { /* fall back to standard plugin on clients. */ ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, hostname); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin " "[%d]: %s\n", ret, strerror(ret)); return ret; } } return EOK; } static errno_t ipa_init_ipa_auth_ctx(TALLOC_CTX *mem_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx *ipa_id_ctx, struct ipa_auth_ctx **_ipa_auth_ctx) { struct ipa_auth_ctx *ipa_auth_ctx; errno_t ret; ipa_auth_ctx = talloc_zero(mem_ctx, struct ipa_auth_ctx); if (ipa_auth_ctx == NULL) { return ENOMEM; } ipa_auth_ctx->sdap_id_ctx = ipa_id_ctx->sdap_id_ctx; ret = dp_copy_options(ipa_auth_ctx, ipa_options->basic, IPA_OPTS_BASIC, &ipa_auth_ctx->ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_copy_options failed.\n"); talloc_free(ipa_auth_ctx); return ret; } *_ipa_auth_ctx = ipa_auth_ctx; return EOK; } static errno_t ipa_init_krb5_auth_ctx(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct krb5_ctx **_krb5_auth_ctx) { struct krb5_ctx *krb5_auth_ctx; bool server_mode; errno_t ret; krb5_auth_ctx = talloc_zero(mem_ctx, struct krb5_ctx); if (krb5_auth_ctx == NULL) { return ENOMEM; } krb5_auth_ctx->service = ipa_options->service->krb5_service; server_mode = dp_opt_get_bool(ipa_options->basic, IPA_SERVER_MODE); krb5_auth_ctx->config_type = server_mode ? K5C_IPA_SERVER : K5C_IPA_CLIENT; ret = ipa_get_auth_options(ipa_options, be_ctx->cdb, be_ctx->conf_path, &krb5_auth_ctx->opts); if (ret != EOK) { talloc_free(krb5_auth_ctx); return ret; } *_krb5_auth_ctx = krb5_auth_ctx; return EOK; } static errno_t ipa_init_sdap_auth_ctx(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct sdap_auth_ctx **_sdap_auth_ctx) { struct sdap_auth_ctx *sdap_auth_ctx; sdap_auth_ctx = talloc_zero(mem_ctx, struct sdap_auth_ctx); if (sdap_auth_ctx == NULL) { return ENOMEM; } sdap_auth_ctx->be = be_ctx; sdap_auth_ctx->service = ipa_options->service->sdap; if (ipa_options->id == NULL) { talloc_free(sdap_auth_ctx); return EINVAL; } sdap_auth_ctx->opts = ipa_options->id; *_sdap_auth_ctx = sdap_auth_ctx; return EOK; } static void cleanup_ipa_preauth_indicator(void) { int ret; ret = unlink(PAM_PREAUTH_INDICATOR); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Failed to remove preauth indicator file [%s].\n", PAM_PREAUTH_INDICATOR); } } static errno_t create_ipa_preauth_indicator(void) { TALLOC_CTX *tmp_ctx; errno_t ret; int fd; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); return ENOMEM; } fd = open(PAM_PREAUTH_INDICATOR, O_CREAT | O_EXCL | O_WRONLY | O_NOFOLLOW, 0644); if (fd < 0) { if (errno != EEXIST) { DEBUG(SSSDBG_OP_FAILURE, "Failed to create preauth indicator file [%s].\n", PAM_PREAUTH_INDICATOR); ret = EOK; goto done; } DEBUG(SSSDBG_CRIT_FAILURE, "Preauth indicator file [%s] already exists. " "Maybe it is left after an unplanned exit. Continuing.\n", PAM_PREAUTH_INDICATOR); } else { close(fd); } ret = atexit(cleanup_ipa_preauth_indicator); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "atexit failed. Continuing.\n"); } ret = EOK; done: talloc_free(tmp_ctx); return ret; } static struct sdap_ext_member_ctx * ipa_create_ext_members_ctx(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *id_ctx) { struct sdap_ext_member_ctx *ext_ctx = NULL; ext_ctx = talloc_zero(mem_ctx, struct sdap_ext_member_ctx); if (ext_ctx == NULL) { return NULL; } ext_ctx->pvt = id_ctx; ext_ctx->ext_member_resolve_send = ipa_ext_group_member_send; ext_ctx->ext_member_resolve_recv = ipa_ext_group_member_recv; return ext_ctx; } static errno_t ipa_init_auth_ctx(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx *id_ctx, struct ipa_auth_ctx **_auth_ctx) { struct sdap_auth_ctx *sdap_auth_ctx; struct ipa_auth_ctx *ipa_auth_ctx; struct krb5_ctx *krb5_auth_ctx; errno_t ret; ret = ipa_init_ipa_auth_ctx(mem_ctx, ipa_options, id_ctx, &ipa_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init IPA auth context\n"); return ret; } ipa_options->auth_ctx = ipa_auth_ctx; ret = ipa_init_krb5_auth_ctx(ipa_auth_ctx, be_ctx, ipa_options, &krb5_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init KRB5 auth context\n"); goto done; } ipa_options->auth_ctx->krb5_auth_ctx = krb5_auth_ctx; ret = ipa_init_sdap_auth_ctx(ipa_auth_ctx, be_ctx, ipa_options, &sdap_auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init SDAP auth context\n"); goto done; } ipa_options->auth_ctx->sdap_auth_ctx = sdap_auth_ctx; ret = setup_tls_config(sdap_auth_ctx->opts->basic); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "setup_tls_config failed [%d]: %s\n", ret, sss_strerror(ret)); goto done; } /* Initialize features needed by the krb5_child */ ret = krb5_child_init(krb5_auth_ctx, be_ctx); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Could not initialize krb5_child " "settings [%d]: %s\n", ret, sss_strerror(ret)); goto done; } ret = create_ipa_preauth_indicator(); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, PREAUTH_INDICATOR_ERROR); sss_log(SSSDBG_CRIT_FAILURE, PREAUTH_INDICATOR_ERROR); } *_auth_ctx = ipa_auth_ctx; ret = EOK; done: if (ret != EOK) { talloc_free(ipa_auth_ctx); } return ret; } static errno_t ipa_init_misc(struct be_ctx *be_ctx, struct ipa_options *ipa_options, struct ipa_id_ctx *ipa_id_ctx, struct sdap_id_ctx *sdap_id_ctx) { errno_t ret; ret = ipa_init_dyndns(be_ctx, ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init dyndns [%d]: %s\n", ret, sss_strerror(ret)); return ret; } ret = setup_tls_config(sdap_id_ctx->opts->basic); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get TLS options [%d]: %s\n", ret, sss_strerror(ret)); return ret; } ret = ipa_idmap_init(sdap_id_ctx, sdap_id_ctx, &sdap_id_ctx->opts->idmap_ctx); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Could not initialize ID mapping. In case ID mapping properties " "changed on the server, please remove the SSSD database\n"); return ret; } ret = ldap_id_setup_tasks(sdap_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup background tasks " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } ret = sdap_setup_child(); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup sdap child [%d]: %s\n", ret, sss_strerror(ret)); return ret; } if (dp_opt_get_bool(ipa_options->basic, IPA_SERVER_MODE)) { ret = ipa_init_server_mode(be_ctx, ipa_options, ipa_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init server mode " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } } else { ret = ipa_init_client_mode(be_ctx, ipa_options, ipa_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init client mode " "[%d]: %s\n", ret, sss_strerror(ret)); return ret; } } ret = sdap_refresh_init(be_ctx->refresh_ctx, sdap_id_ctx); if (ret != EOK && ret != EEXIST) { DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh " "will not work [%d]: %s\n", ret, sss_strerror(ret)); } ipa_id_ctx->sdap_id_ctx->opts->ext_ctx = ipa_create_ext_members_ctx( ipa_id_ctx->sdap_id_ctx->opts, ipa_id_ctx); if (ipa_id_ctx->sdap_id_ctx->opts->ext_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set the extrernal group ctx\n"); return ENOMEM; } return EOK; } errno_t sssm_ipa_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct data_provider *provider, const char *module_name, void **_module_data) { struct ipa_init_ctx *init_ctx; errno_t ret; init_ctx = talloc_zero(mem_ctx, struct ipa_init_ctx); if (init_ctx == NULL) { return ENOMEM; } /* Always initialize options since it is needed everywhere. */ ret = ipa_init_options(init_ctx, be_ctx, &init_ctx->options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init IPA options " "[%d]: %s\n", ret, sss_strerror(ret)); goto done; } /* Always initialize id_ctx since it is needed everywhere. */ ret = ipa_init_id_ctx(init_ctx, be_ctx, init_ctx->options, &init_ctx->id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init IPA ID context " "[%d]: %s\n", ret, sss_strerror(ret)); goto done; } /* Setup miscellaneous things. */ ret = ipa_init_misc(be_ctx, init_ctx->options, init_ctx->id_ctx, init_ctx->id_ctx->sdap_id_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init IPA module " "[%d]: %s\n", ret, sss_strerror(ret)); goto done; } /* Initialize auth_ctx only if one of the target is enabled. */ if (dp_target_enabled(provider, module_name, DPT_AUTH, DPT_CHPASS)) { ret = ipa_init_auth_ctx(init_ctx, be_ctx, init_ctx->options, init_ctx->id_ctx, &init_ctx->auth_ctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init IPA auth context " "[%d]: %s\n", ret, sss_strerror(ret)); goto done; } } *_module_data = init_ctx; ret = EOK; done: if (ret != EOK) { talloc_free(init_ctx); } return ret; } errno_t sssm_ipa_id_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { struct ipa_init_ctx *init_ctx; struct ipa_id_ctx *id_ctx; init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); id_ctx = init_ctx->id_ctx; dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER, ipa_account_info_handler_send, ipa_account_info_handler_recv, id_ctx, struct ipa_id_ctx, struct be_acct_req, struct dp_reply_std); dp_set_method(dp_methods, DPM_CHECK_ONLINE, sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx->sdap_id_ctx, struct sdap_id_ctx, void, struct dp_reply_std); return EOK; } errno_t sssm_ipa_auth_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { struct ipa_init_ctx *init_ctx; struct ipa_auth_ctx *auth_ctx; init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); auth_ctx = init_ctx->auth_ctx; dp_set_method(dp_methods, DPM_AUTH_HANDLER, ipa_pam_auth_handler_send, ipa_pam_auth_handler_recv, auth_ctx, struct ipa_auth_ctx, struct pam_data, struct pam_data *); return EOK; } errno_t sssm_ipa_chpass_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { return sssm_ipa_auth_init(mem_ctx, be_ctx, module_data, dp_methods); } errno_t sssm_ipa_access_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { struct ipa_access_ctx *access_ctx; struct ipa_init_ctx *init_ctx; struct ipa_id_ctx *id_ctx; errno_t ret; init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); id_ctx = init_ctx->id_ctx; access_ctx = talloc_zero(mem_ctx, struct ipa_access_ctx); if (access_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed.\n"); return ENOMEM; } access_ctx->sdap_ctx = id_ctx->sdap_id_ctx; access_ctx->host_map = id_ctx->ipa_options->host_map; access_ctx->hostgroup_map = id_ctx->ipa_options->hostgroup_map; access_ctx->host_search_bases = id_ctx->ipa_options->host_search_bases; access_ctx->hbac_search_bases = id_ctx->ipa_options->hbac_search_bases; ret = dp_copy_options(access_ctx, id_ctx->ipa_options->basic, IPA_OPTS_BASIC, &access_ctx->ipa_options); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "dp_copy_options() failed.\n"); goto done; } /* Set up an sdap_access_ctx for checking expired/locked accounts. */ access_ctx->sdap_access_ctx = talloc_zero(access_ctx, struct sdap_access_ctx); if (access_ctx->sdap_access_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n"); ret = ENOMEM; goto done; } access_ctx->sdap_access_ctx->id_ctx = access_ctx->sdap_ctx; access_ctx->sdap_access_ctx->access_rule[0] = LDAP_ACCESS_EXPIRE; access_ctx->sdap_access_ctx->access_rule[1] = LDAP_ACCESS_EMPTY; dp_set_method(dp_methods, DPM_ACCESS_HANDLER, ipa_pam_access_handler_send, ipa_pam_access_handler_recv, access_ctx, struct ipa_access_ctx, struct pam_data, struct pam_data *); ret = EOK; done: if (ret != EOK) { talloc_free(access_ctx); } return ret; } errno_t sssm_ipa_selinux_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { #if defined HAVE_SELINUX && defined HAVE_SELINUX_LOGIN_DIR struct ipa_selinux_ctx *selinux_ctx; struct ipa_init_ctx *init_ctx; struct ipa_options *opts; init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); opts = init_ctx->options; selinux_ctx = talloc_zero(mem_ctx, struct ipa_selinux_ctx); if (selinux_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed.\n"); return ENOMEM; } selinux_ctx->id_ctx = init_ctx->id_ctx; selinux_ctx->hbac_search_bases = opts->hbac_search_bases; selinux_ctx->host_search_bases = opts->host_search_bases; selinux_ctx->selinux_search_bases = opts->selinux_search_bases; dp_set_method(dp_methods, DPM_SELINUX_HANDLER, ipa_selinux_handler_send, ipa_selinux_handler_recv, selinux_ctx, struct ipa_selinux_ctx, struct pam_data, struct pam_data *); return EOK; #else DEBUG(SSSDBG_MINOR_FAILURE, "SELinux init handler called but SSSD is " "built without SSH support, ignoring\n"); return EOK; #endif } errno_t sssm_ipa_hostid_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { #ifdef BUILD_SSH struct ipa_hostid_ctx *hostid_ctx; struct ipa_init_ctx *init_ctx; init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); hostid_ctx = talloc_zero(mem_ctx, struct ipa_hostid_ctx); if (hostid_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); return ENOMEM; } hostid_ctx->sdap_id_ctx = init_ctx->id_ctx->sdap_id_ctx; hostid_ctx->host_search_bases = init_ctx->options->host_search_bases; hostid_ctx->ipa_opts = init_ctx->options; dp_set_method(dp_methods, DPM_HOSTID_HANDLER, ipa_hostid_handler_send, ipa_hostid_handler_recv, hostid_ctx, struct ipa_hostid_ctx, struct dp_hostid_data, struct dp_reply_std); return EOK; #else DEBUG(SSSDBG_MINOR_FAILURE, "HostID init handler called but SSSD is " "built without SSH support, ignoring\n"); return EOK; #endif } errno_t sssm_ipa_autofs_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { #ifdef BUILD_AUTOFS struct ipa_init_ctx *init_ctx; DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing IPA autofs handler\n"); init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); return ipa_autofs_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods); #else DEBUG(SSSDBG_MINOR_FAILURE, "Autofs init handler called but SSSD is " "built without autofs support, ignoring\n"); return EOK; #endif } errno_t sssm_ipa_subdomains_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { struct ipa_init_ctx *init_ctx; DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing IPA subdomains handler\n"); init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); return ipa_subdomains_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods); } errno_t sssm_ipa_sudo_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, struct dp_method *dp_methods) { #ifdef BUILD_SUDO struct ipa_init_ctx *init_ctx; DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing IPA sudo handler\n"); init_ctx = talloc_get_type(module_data, struct ipa_init_ctx); return ipa_sudo_init(mem_ctx, be_ctx, init_ctx->id_ctx, dp_methods); #else DEBUG(SSSDBG_MINOR_FAILURE, "Sudo init handler called but SSSD is " "built without sudo support, ignoring\n"); return EOK; #endif }