ad_common.c revision 0051296f67bd7d8e2e3094638ddff4e641324d04
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina/*
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina SSSD
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina Authors:
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina Stephen Gallagher <sgallagh@redhat.com>
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina Copyright (C) 2012 Red Hat
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina This program is free software; you can redistribute it and/or modify
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina it under the terms of the GNU General Public License as published by
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina the Free Software Foundation; either version 3 of the License, or
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina (at your option) any later version.
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina This program is distributed in the hope that it will be useful,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina GNU General Public License for more details.
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina You should have received a copy of the GNU General Public License
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina*/
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina#include <ctype.h>
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina#include "providers/ad/ad_common.h"
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina#include "providers/ad/ad_opts.h"
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaerrno_t
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaad_get_common_options(TALLOC_CTX *mem_ctx,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct confdb_ctx *cdb,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina const char *conf_path,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct sss_domain_info *dom,
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce struct ad_options **_opts)
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina{
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina errno_t ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina int gret;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce struct ad_options *opts = NULL;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce char *domain;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina char *server;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce char *realm;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce char *ad_hostname;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina char hostname[HOST_NAME_MAX + 1];
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina opts = talloc_zero(mem_ctx, struct ad_options);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!opts) return ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = dp_get_options(opts, cdb, conf_path,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ad_basic_opts,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina AD_OPTS_BASIC,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina &opts->basic);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina /* If the AD domain name wasn't explicitly set, assume that it
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina * matches the SSSD domain name
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina */
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina domain = dp_opt_get_string(opts->basic, AD_DOMAIN);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!domain) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = dp_opt_set_string(opts->basic, AD_DOMAIN, dom->name);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina domain = dom->name;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce /* Did we get an explicit server name, or are we discovering it? */
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce server = dp_opt_get_string(opts->basic, AD_SERVER);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (!server) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("No AD server set, will use service discovery!\n"));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina /* Set the machine's hostname to the local host name if it
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina * wasn't explicitly specified.
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce */
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ad_hostname = dp_opt_get_string(opts->basic, AD_HOSTNAME);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ad_hostname == NULL) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina gret = gethostname(hostname, HOST_NAME_MAX);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (gret != 0) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = errno;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ("gethostname failed [%s].\n",
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce strerror(ret)));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina hostname[HOST_NAME_MAX] = '\0';
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("Setting ad_hostname to [%s].\n", hostname));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = dp_opt_set_string(opts->basic, AD_HOSTNAME, hostname);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("Setting ad_hostname failed [%s].\n",
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina strerror(ret)));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina /* Always use the upper-case AD domain for the kerberos realm */
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina realm = get_uppercase_realm(opts, domain);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!realm) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = dp_opt_set_string(opts->basic, AD_KRB5_REALM, realm);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (ret != EOK) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce /* Active Directory is always case-insensitive */
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce dom->case_sensitive = false;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce /* Set this in the confdb so that the responders pick it
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce * up when they start up.
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce */
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = confdb_set_bool(cdb, conf_path, "case_sensitive",
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce dom->case_sensitive);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (ret != EOK) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ("Could not set domain case-sensitive: [%s]\n",
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce strerror(ret)));
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ("Setting domain case-insensitive\n"));
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = EOK;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina *_opts = opts;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinadone:
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina talloc_zfree(opts);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina}
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic void
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaad_resolve_callback(void *private_data, struct fo_server *server);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic errno_t
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaad_servers_init(TALLOC_CTX *mem_ctx,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct be_ctx *bectx,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce const char *servers,
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce struct ad_options *options,
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce bool primary)
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce{
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce size_t i;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce errno_t ret = 0;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce char **list;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce char *ad_domain;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce TALLOC_CTX *tmp_ctx;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce tmp_ctx = talloc_new(NULL);
2b7ee2a760e7fcc70f4970a3bbee6fbf8f2ccb9dSimo Sorce if (!tmp_ctx) return ENOMEM;
2b7ee2a760e7fcc70f4970a3bbee6fbf8f2ccb9dSimo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce /* Split the server list */
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = split_on_separator(tmp_ctx, servers, ',', true, &list, NULL);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to parse server list!\n"));
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ad_domain = dp_opt_get_string(options->basic, AD_DOMAIN);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce /* Add each of these servers to the failover service */
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce for (i = 0; list[i]; i++) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (be_fo_is_srv_identifier(list[i])) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!primary) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("Failed to add server [%s] to failover service: "
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina "SRV resolution only allowed for primary servers!\n",
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina list[i]));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina continue;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = be_fo_add_srv_server(bectx, AD_SERVICE_NAME, "ldap",
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ad_domain, BE_FO_PROTO_TCP,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina false, NULL);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("Failed to add service discovery to failover: [%s]",
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina strerror(ret)));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, ("Added service discovery for AD\n"));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina continue;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = be_fo_add_server(bectx, AD_SERVICE_NAME, list[i], 0, NULL, primary);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret && ret != EEXIST) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to add server\n"));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CONF_SETTINGS, ("Added failover server %s\n", list[i]));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinadone:
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina talloc_free(tmp_ctx);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina}
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic int ad_user_data_cmp(void *ud1, void *ud2)
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina{
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return strcasecmp((char*) ud1, (char*) ud2);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina}
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaerrno_t
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina const char *primary_servers,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina const char *backup_servers,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct ad_options *options,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct ad_service **_service)
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina{
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina errno_t ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina TALLOC_CTX *tmp_ctx;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct ad_service *service;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina char *realm;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina tmp_ctx = talloc_new(mem_ctx);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!tmp_ctx) return ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina service = talloc_zero(tmp_ctx, struct ad_service);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!service) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina service->sdap = talloc_zero(service, struct sdap_service);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!service->sdap) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = ENOMEM;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce service->krb5_service = talloc_zero(service, struct krb5_service);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (!service->krb5_service) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = ENOMEM;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = be_fo_add_service(bectx, AD_SERVICE_NAME, ad_user_data_cmp);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (ret != EOK) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to create failover service!\n"));
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce service->sdap->name = talloc_strdup(service, AD_SERVICE_NAME);
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce if (!service->sdap->name) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce service->krb5_service->name = talloc_strdup(service, AD_SERVICE_NAME);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!service->krb5_service->name) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = ENOMEM;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina service->sdap->kinit_service_name = service->krb5_service->name;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina realm = dp_opt_get_string(options->basic, AD_KRB5_REALM);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!realm) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("No Kerberos realm set\n"));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = EINVAL;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina service->krb5_service->realm =
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina talloc_strdup(service->krb5_service, realm);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (!service->krb5_service->realm) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = ENOMEM;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
044868b388b4e47499f12a9105310b247bbe1ce2Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (!primary_servers) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (backup_servers) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce DEBUG(SSSDBG_TRACE_FUNC,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ("No primary servers defined but backup are present, "
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce "setting backup servers as primary\n"));
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce primary_servers = backup_servers;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina backup_servers = NULL;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce } else {
2b7ee2a760e7fcc70f4970a3bbee6fbf8f2ccb9dSimo Sorce DEBUG(SSSDBG_TRACE_FUNC,
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ("No primary or backup servers defined but backup are present, "
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce "setting backup servers as primary\n"));
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce primary_servers = BE_SRV_IDENTIFIER;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = ad_servers_init(mem_ctx, bectx, primary_servers, options, true);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (ret != EOK) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce goto done;
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce }
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (backup_servers) {
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce ret = ad_servers_init(mem_ctx, bectx, backup_servers, options, false);
4c2cf6607ddc82c5061d805c11e163de4bc1bd82Simo Sorce if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = be_fo_service_add_callback(mem_ctx, bectx, AD_SERVICE_NAME,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ad_resolve_callback, service);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ("Failed to add failover callback! [%s]\n", strerror(ret)));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina goto done;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina *_service = talloc_steal(mem_ctx, service);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = EOK;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinadone:
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina talloc_free(tmp_ctx);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina}
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic void
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinaad_resolve_callback(void *private_data, struct fo_server *server)
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina{
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina errno_t ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina TALLOC_CTX *tmp_ctx;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct ad_service *service;
struct resolv_hostent *srvaddr;
struct sockaddr_storage *sockaddr;
char *address;
const char *safe_address;
char *new_uri;
const char *srv_name;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
return;
}
service = talloc_get_type(private_data, struct ad_service);
if (!service) {
ret = EINVAL;
goto done;
}
srvaddr = fo_get_server_hostent(server);
if (!srvaddr) {
DEBUG(SSSDBG_CRIT_FAILURE,
("No hostent available for server (%s)\n",
fo_get_server_str_name(server)));
ret = EINVAL;
goto done;
}
sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT);
if (sockaddr == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("resolv_get_sockaddr_address failed.\n"));
ret = EIO;
goto done;
}
address = resolv_get_string_address(tmp_ctx, srvaddr);
if (address == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("resolv_get_string_address failed.\n"));
ret = EIO;
goto done;
}
srv_name = fo_get_server_name(server);
if (srv_name == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Could not get server host name\n"));
ret = EINVAL;
goto done;
}
new_uri = talloc_asprintf(service, "ldap://%s", srv_name);
if (!new_uri) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to copy URI\n"));
ret = ENOMEM;
goto done;
}
DEBUG(SSSDBG_CONF_SETTINGS, ("Constructed uri '%s'\n", new_uri));
/* free old one and replace with new one */
talloc_zfree(service->sdap->uri);
service->sdap->uri = new_uri;
talloc_zfree(service->sdap->sockaddr);
service->sdap->sockaddr = talloc_steal(service, sockaddr);
safe_address = sss_escape_ip_address(tmp_ctx,
srvaddr->family,
address);
if (safe_address == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("sss_escape_ip_address failed.\n"));
ret = ENOMEM;
goto done;
}
ret = write_krb5info_file(service->krb5_service->realm, safe_address,
SSS_KRB5KDC_FO_SRV);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
("write_krb5info_file failed, authentication might fail.\n"));
}
ret = EOK;
done:
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
("Error: [%s]\n", strerror(ret)));
}
talloc_free(tmp_ctx);
return;
}
errno_t
ad_set_search_bases(struct sdap_options *id_opts);
errno_t
ad_get_id_options(struct ad_options *ad_opts,
struct confdb_ctx *cdb,
const char *conf_path,
struct sdap_options **_opts)
{
errno_t ret;
TALLOC_CTX *tmp_ctx;
struct sdap_options *id_opts;
char *krb5_realm;
char *sasl_primary;
char *desired_primary;
char *sasl_realm;
char *desired_realm;
char *keytab_path;
bool primary_requested = true;
bool realm_requested = true;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
id_opts = talloc_zero(tmp_ctx, struct sdap_options);
if (!id_opts) {
ret = ENOMEM;
goto done;
}
ret = dp_get_options(id_opts, cdb, conf_path,
ad_def_ldap_opts,
SDAP_OPTS_BASIC,
&id_opts->basic);
if (ret != EOK) {
goto done;
}
/* Set up search bases if they were assigned explicitly */
ret = ad_set_search_bases(id_opts);
if (ret != EOK) goto done;
/* We only support Kerberos password policy with AD, so
* force that on.
*/
ret = dp_opt_set_string(id_opts->basic,
SDAP_PWD_POLICY,
PWD_POL_OPT_MIT);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, ("Could not set password policy\n"));
goto done;
}
/* Set the Kerberos Realm for GSSAPI */
krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
if (!krb5_realm) {
/* Should be impossible, this is set in ad_get_common_options() */
DEBUG(SSSDBG_FATAL_FAILURE, ("No Kerberos realm\n"));
ret = EINVAL;
goto done;
}
ret = dp_opt_set_string(id_opts->basic, SDAP_KRB5_REALM, krb5_realm);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
id_opts->basic[SDAP_KRB5_REALM].opt_name,
krb5_realm));
/* Configuration of SASL auth ID and realm */
desired_primary = dp_opt_get_string(id_opts->basic, SDAP_SASL_AUTHID);
if (!desired_primary) {
primary_requested = false;
desired_primary = dp_opt_get_string(ad_opts->basic, AD_HOSTNAME);
}
desired_realm = dp_opt_get_string(id_opts->basic, SDAP_SASL_REALM);
if (!desired_realm) {
realm_requested = false;
desired_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
}
keytab_path = dp_opt_get_string(ad_opts->basic, AD_KEYTAB);
if (keytab_path) {
ret = dp_opt_set_string(id_opts->basic, SDAP_KRB5_KEYTAB,
keytab_path);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
id_opts->basic[SDAP_KRB5_KEYTAB].opt_name,
keytab_path));
}
ret = select_principal_from_keytab(tmp_ctx,
desired_primary, desired_realm,
keytab_path, NULL,
&sasl_primary, &sasl_realm);
if (ret != EOK) goto done;
if ((primary_requested && strcmp(desired_primary, sasl_primary) != 0) ||
(realm_requested && strcmp(desired_realm, sasl_realm) != 0)) {
DEBUG(SSSDBG_FATAL_FAILURE,
("Configured SASL auth ID/realm not found in keytab.\n"));
ret = ENOENT;
goto done;
}
ret = dp_opt_set_string(id_opts->basic, SDAP_SASL_AUTHID, sasl_primary);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
id_opts->basic[SDAP_SASL_AUTHID].opt_name,
sasl_primary));
ret = dp_opt_set_string(id_opts->basic, SDAP_SASL_REALM, sasl_realm);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
id_opts->basic[SDAP_SASL_REALM].opt_name,
sasl_realm));
/* fix schema to AD */
id_opts->schema_type = SDAP_SCHEMA_AD;
/* Get sdap option maps */
/* General Attribute Map */
ret = sdap_get_map(id_opts,
cdb, conf_path,
ad_2008r2_attr_map,
SDAP_AT_GENERAL,
&id_opts->gen_map);
if (ret != EOK) {
goto done;
}
/* User map */
ret = sdap_get_map(id_opts,
cdb, conf_path,
ad_2008r2_user_map,
SDAP_OPTS_USER,
&id_opts->user_map);
if (ret != EOK) {
goto done;
}
/* Group map */
ret = sdap_get_map(id_opts,
cdb, conf_path,
ad_2008r2_group_map,
SDAP_OPTS_GROUP,
&id_opts->group_map);
if (ret != EOK) {
goto done;
}
/* Netgroup map */
ret = sdap_get_map(id_opts,
cdb, conf_path,
ad_netgroup_map,
SDAP_OPTS_NETGROUP,
&id_opts->netgroup_map);
if (ret != EOK) {
goto done;
}
/* Services map */
ret = sdap_get_map(id_opts,
cdb, conf_path,
ad_service_map,
SDAP_OPTS_SERVICES,
&id_opts->service_map);
if (ret != EOK) {
goto done;
}
ad_opts->id = talloc_steal(ad_opts, id_opts);
*_opts = id_opts;
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t
ad_set_search_bases(struct sdap_options *id_opts)
{
errno_t ret;
char *default_search_base;
size_t o;
const int search_base_options[] = { SDAP_USER_SEARCH_BASE,
SDAP_GROUP_SEARCH_BASE,
SDAP_NETGROUP_SEARCH_BASE,
SDAP_SERVICE_SEARCH_BASE,
-1 };
/* AD servers provide defaultNamingContext, so we will
* rely on that to specify the search base unless it has
* been specifically overridden.
*/
default_search_base =
dp_opt_get_string(id_opts->basic, SDAP_SEARCH_BASE);
if (default_search_base) {
/* set search bases if they are not */
for (o = 0; search_base_options[o] != -1; o++) {
if (NULL == dp_opt_get_string(id_opts->basic,
search_base_options[o])) {
ret = dp_opt_set_string(id_opts->basic,
search_base_options[o],
default_search_base);
if (ret != EOK) {
goto done;
}
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
id_opts->basic[search_base_options[o]].opt_name,
dp_opt_get_string(id_opts->basic,
search_base_options[o])));
}
}
} else {
DEBUG(SSSDBG_CONF_SETTINGS,
("Search base not set. SSSD will attempt to discover it later, "
"when connecting to the LDAP server.\n"));
}
/* Default search */
ret = sdap_parse_search_base(id_opts, id_opts->basic,
SDAP_SEARCH_BASE,
&id_opts->search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* User search */
ret = sdap_parse_search_base(id_opts, id_opts->basic,
SDAP_USER_SEARCH_BASE,
&id_opts->user_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Group search base */
ret = sdap_parse_search_base(id_opts, id_opts->basic,
SDAP_GROUP_SEARCH_BASE,
&id_opts->group_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Netgroup search */
ret = sdap_parse_search_base(id_opts, id_opts->basic,
SDAP_NETGROUP_SEARCH_BASE,
&id_opts->netgroup_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
/* Service search */
ret = sdap_parse_search_base(id_opts, id_opts->basic,
SDAP_SERVICE_SEARCH_BASE,
&id_opts->service_search_bases);
if (ret != EOK && ret != ENOENT) goto done;
ret = EOK;
done:
return ret;
}
errno_t
ad_get_auth_options(TALLOC_CTX *mem_ctx,
struct ad_options *ad_opts,
struct be_ctx *bectx,
struct dp_option **_opts)
{
errno_t ret;
struct dp_option *krb5_options;
const char *ad_servers;
const char *krb5_realm;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
/* Get krb5 options */
ret = dp_get_options(tmp_ctx, bectx->cdb, bectx->conf_path,
ad_def_krb5_opts, KRB5_OPTS,
&krb5_options);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
("Could not read Kerberos options from the configuration\n"));
goto done;
}
ad_servers = dp_opt_get_string(ad_opts->basic, AD_SERVER);
/* Force the krb5_servers to match the ad_servers */
ret = dp_opt_set_string(krb5_options, KRB5_KDC, ad_servers);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
krb5_options[KRB5_KDC].opt_name,
ad_servers));
/* Set krb5 realm */
/* Set the Kerberos Realm for GSSAPI */
krb5_realm = dp_opt_get_string(ad_opts->basic, AD_KRB5_REALM);
if (!krb5_realm) {
/* Should be impossible, this is set in ad_get_common_options() */
DEBUG(SSSDBG_FATAL_FAILURE, ("No Kerberos realm\n"));
ret = EINVAL;
goto done;
}
/* Force the kerberos realm to match the AD_KRB5_REALM (which may have
* been upper-cased in ad_common_options()
*/
ret = dp_opt_set_string(krb5_options, KRB5_REALM, krb5_realm);
if (ret != EOK) goto done;
DEBUG(SSSDBG_CONF_SETTINGS,
("Option %s set to %s\n",
krb5_options[KRB5_REALM].opt_name,
krb5_realm));
*_opts = talloc_steal(mem_ctx, krb5_options);
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}