>From 25b1162bb334b1c59137fdce27e2f4d763e9725a Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 9 Apr 2013 14:20:28 +0200 Subject: [PATCH 2/2] Convert IPA-specific options to be back-end agnostic This patch introduces new options for dynamic DNS updates that are not specific to any back end. The current ipa dyndns options are still usable, just with a deprecation warning. --- Makefile.am | 3 +- src/config/SSSDConfig/__init__.py.in | 3 ++ src/config/SSSDConfigTest.py | 6 +++ src/config/etc/sssd.api.conf | 5 ++ src/man/sssd-ipa.5.xml | 28 +++++++++-- src/providers/dp_dyndns.c | 57 +++++++++++++++++++++ src/providers/dp_dyndns.h | 24 +++++++++ src/providers/ipa/ipa_common.c | 96 ++++++++++++++++++++++++++++++++++++ src/providers/ipa/ipa_common.h | 7 +-- src/providers/ipa/ipa_dyndns.c | 9 ++-- src/providers/ipa/ipa_init.c | 29 +++++------ src/providers/ipa/ipa_opts.h | 10 ++-- src/tests/cmocka/test_dyndns.c | 2 +- 13 files changed, 244 insertions(+), 35 deletions(-) diff --git a/Makefile.am b/Makefile.am index b6fdeb5d0345314ac5ad6c212b9b2b1e1ead8c9c..f3da506777bf87d1ffc36ba736b0184f5101be80 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1265,7 +1265,8 @@ dyndns_tests_SOURCES = \ $(TEST_MOCK_OBJ) \ $(SSSD_RESOLV_OBJ) \ src/tests/common_tev.c \ - src/tests/cmocka/test_dyndns.c + src/tests/cmocka/test_dyndns.c \ + src/providers/data_provider_opts.c dyndns_tests_CFLAGS = \ $(AM_CFLAGS) \ -DDYNDNS_TIMEOUT=2 diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 256c4b3147c3dcccc2df60e7fa7a18976231bbae..9f11d31c2dab4583cf6ebb956940fd17d890c985 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -125,6 +125,9 @@ option_strings = { 'entry_cache_service_timeout' : _('Entry cache timeout length (seconds)'), 'entry_cache_autofs_timeout' : _('Entry cache timeout length (seconds)'), 'entry_cache_sudo_timeout' : _('Entry cache timeout length (seconds)'), + 'dyndns_update' : _("Whether to automatically update the client's DNS entry"), + 'dyndns_ttl' : _("The TTL to apply to the client's DNS entry after updating it"), + 'dyndns_iface' : _("The interface whose IP should be used for dynamic DNS updates"), # [provider/ipa] 'ipa_domain' : _('IPA domain'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 6ae458b1a438ff0bb7b2e10765b1fff3f5494163..c0d4a1476a0e08f04e7aa24ecc5293992cced3ca 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -507,6 +507,9 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'account_cache_expiration', 'dns_resolver_timeout', 'dns_discovery_domain', + 'dyndns_update', + 'dyndns_ttl', + 'dyndns_iface', 'override_gid', 'case_sensitive', 'override_homedir', @@ -850,6 +853,9 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'lookup_family_order', 'dns_resolver_timeout', 'dns_discovery_domain', + 'dyndns_update', + 'dyndns_ttl', + 'dyndns_iface', 'override_gid', 'case_sensitive', 'override_homedir', diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index 3ed9d583ccbfd8f148d5a2c79f9c658d8fd7d8f1..02e2a0a6625445f1361dceea866a32b916bea01a 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -121,6 +121,11 @@ entry_cache_service_timeout = int, None, false entry_cache_autofs_timeout = int, None, false entry_cache_sudo_timeout = int, None, false +# Dynamic DNS updates +dyndns_update = bool, None, false +dyndns_ttl = int, None, false +dyndns_iface = str, None, false + # Special providers [provider/permit] diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml index f8cb0939daba2daa49318d098a9fa1be307fc910..bedb1107234bf69e60cc174b1086a181fa80f806 100644 --- a/src/man/sssd-ipa.5.xml +++ b/src/man/sssd-ipa.5.xml @@ -113,7 +113,7 @@ - ipa_dyndns_update (boolean) + dyndns_update (boolean) Optional. This option tells SSSD to automatically @@ -126,34 +126,52 @@ realm must be set properly in /etc/krb5.conf + NOTE: While it is still possible to use the old + ipa_dyndns_update option, users + should migrate to using dyndns_update + in their config file. + + Default: false - ipa_dyndns_ttl (integer) + dyndns_ttl (integer) The TTL to apply to the client DNS record when updating it. - If ipa_dyndns_update is false this has no effect. This will + If dyndns_update is false this has no effect. This will override the TTL serverside if set by an administrator. + NOTE: While it is still possible to use the old + ipa_dyndns_ttl option, users + should migrate to using dyndns_ttl + in their config file. + + Default: 1200 (seconds) - ipa_dyndns_iface (string) + dyndns_iface (string) - Optional. Applicable only when ipa_dyndns_update + Optional. Applicable only when dyndns_update is true. Choose the interface whose IP address should be used for dynamic DNS updates. + NOTE: While it is still possible to use the old + ipa_dyndns_iface option, users + should migrate to using dyndns_iface + in their config file. + + Default: Use the IP address of the IPA LDAP connection diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c index 7e5cc690e1d199f9c00b0b3d18168e5987ffc31f..81228d5cfb59e472167b50dda819ec4ae49a928c 100644 --- a/src/providers/dp_dyndns.c +++ b/src/providers/dp_dyndns.c @@ -878,3 +878,60 @@ be_nsupdate_recv(struct tevent_req *req, int *child_status) return EOK; } + +errno_t +be_nsupdate_check(void) +{ + errno_t ret; + struct stat stat_buf; + + /* Ensure that nsupdate exists */ + errno = 0; + ret = stat(NSUPDATE_PATH, &stat_buf); + if (ret == -1) { + ret = errno; + if (ret == ENOENT) { + DEBUG(SSSDBG_MINOR_FAILURE, + ("%s does not exist. Dynamic DNS updates disabled\n", + NSUPDATE_PATH)); + } else { + DEBUG(SSSDBG_OP_FAILURE, + ("Could not set up dynamic DNS updates: [%d][%s]\n", + ret, strerror(ret))); + } + } + + return ret; +} + +static struct dp_option default_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, + + DP_OPTION_TERMINATOR +}; + +errno_t +be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, + struct dp_option *defopts, struct be_nsupdate_ctx **_ctx) +{ + errno_t ret; + struct dp_option *src_opts; + struct be_nsupdate_ctx *ctx; + + ctx = talloc(mem_ctx, struct be_nsupdate_ctx); + if (ctx == NULL) return ENOMEM; + + src_opts = defopts ? defopts : default_dyndns_opts; + + ret = dp_get_options(ctx, be_ctx->cdb, be_ctx->conf_path, + src_opts, DP_OPT_DYNDNS, &ctx->opts); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot retrieve dynamic DNS options\n")); + return ret; + } + + *_ctx = ctx; + return EOK; +} diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h index b0020560a8accf8811f311c592a6bf436111156a..95403a3ae73fc47c6a9b5240c640325da1045e39 100644 --- a/src/providers/dp_dyndns.h +++ b/src/providers/dp_dyndns.h @@ -22,12 +22,34 @@ along with this program. If not, see . */ + +#ifndef DP_DYNDNS_H_ +#define DP_DYNDNS_H_ + /* dynamic dns helpers */ struct sss_iface_addr; +struct be_nsupdate_ctx { + struct dp_option *opts; +}; + +enum dp_dyndns_opts { + DP_OPT_DYNDNS_UPDATE, + DP_OPT_DYNDNS_IFACE, + DP_OPT_DYNDNS_TTL, + + DP_OPT_DYNDNS /* attrs counter */ +}; + #define DYNDNS_REMOVE_A 0x1 #define DYNDNS_REMOVE_AAAA 0x2 +errno_t be_nsupdate_check(void); + +errno_t +be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, + struct dp_option *defopts, struct be_nsupdate_ctx **ctx); + errno_t sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, struct sss_iface_addr **_addrlist); @@ -66,3 +88,5 @@ struct tevent_req * nsupdate_get_addrs_send(TALLOC_CTX *mem_ctx, errno_t nsupdate_get_addrs_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, char ***_addrlist); + +#endif /* DP_DYNDNS_H_ */ diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index be1bd1d2f8c42143d7ff1fe205ffb774ffe19dd0..51750b2af3e679dafee8cb88081839c11a261757 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -29,6 +29,7 @@ #include "db/sysdb_selinux.h" #include "providers/ipa/ipa_common.h" #include "providers/ldap/sdap_async_private.h" +#include "providers/dp_dyndns.h" #include "util/sss_krb5.h" #include "db/sysdb_services.h" #include "db/sysdb_autofs.h" @@ -1008,3 +1009,98 @@ done: talloc_free(tmp_ctx); return ret; } + +errno_t ipa_get_dyndns_options(struct be_ctx *be_ctx, + struct ipa_options *ctx) +{ + errno_t ret; + char *val; + bool update; + int ttl; + + ret = be_nsupdate_init(ctx, be_ctx, ipa_dyndns_opts, &ctx->dyndns_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("Cannot initialize IPA dyndns opts [%d]: %s\n", + ret, sss_strerror(ret))); + return ret; + } + + if (ctx->basic == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, ("IPA basic options not (yet) " + "initialized, cannot copy legacy options\n")); + return EOK; + } + + /* Reuse legacy option values */ + ret = confdb_get_string(be_ctx->cdb, ctx, be_ctx->conf_path, + "ipa_dyndns_update", NULL, &val); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot get the value of %s\n", + "ipa_dyndns_update")); + /* Not fatal */ + } else if (ret == EOK && val) { + if (strcasecmp(val, "FALSE") == 0) { + update = false; + } else if (strcasecmp(val, "TRUE") == 0) { + update = true; + } else { + DEBUG(SSSDBG_MINOR_FAILURE, + ("ipa_dyndns_update value is not a boolean!\n")); + talloc_free(val); + return EINVAL; + } + + DEBUG(SSSDBG_MINOR_FAILURE, ("Deprecation warning: The option %s is " + "deprecated and should not be used in favor of %s\n", + "ipa_dyndns_update", "dyndns_update")); + + ret = dp_opt_set_bool(ctx->dyndns_ctx->opts, + DP_OPT_DYNDNS_UPDATE, update); + talloc_free(val); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot set option value\n")); + return ret; + } + } + + ret = confdb_get_int(be_ctx->cdb, be_ctx->conf_path, + "ipa_dyndns_ttl", -1, &ttl); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot get the value of %s\n", + "ipa_dyndns_ttl")); + /* Not fatal */ + } else if (ret == EOK && ttl != -1) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Deprecation warning: The option %s is " + "deprecated and should not be used in favor of %s\n", + "ipa_dyndns_ttl", "dyndns_ttl")); + + ret = dp_opt_set_int(ctx->dyndns_ctx->opts, DP_OPT_DYNDNS_TTL, ttl); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot set option value\n")); + return ret; + } + } + + /* Reuse legacy option values */ + ret = confdb_get_string(be_ctx->cdb, ctx, be_ctx->conf_path, + "ipa_dyndns_iface", NULL, &val); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot get the value of %s\n", + "ipa_dyndns_iface")); + /* Not fatal */ + } else if (ret == EOK && val) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Deprecation warning: The option %s is " + "deprecated and should not be used in favor of %s\n", + "ipa_dyndns_iface", "dyndns_iface")); + + ret = dp_opt_set_string(ctx->dyndns_ctx->opts, + DP_OPT_DYNDNS_IFACE, val); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Cannot set option value\n")); + return ret; + } + } + + return EOK; +} diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h index 52a0afe19ccfbfd143e4787b3cd05527291ac3d6..2784eeed3d134b2212e57dc88d1e2a391b468fd4 100644 --- a/src/providers/ipa/ipa_common.h +++ b/src/providers/ipa/ipa_common.h @@ -37,9 +37,6 @@ enum ipa_basic_opt { IPA_SERVER, IPA_BACKUP_SERVER, IPA_HOSTNAME, - IPA_DYNDNS_UPDATE, - IPA_DYNDNS_TTL, - IPA_DYNDNS_IFACE, IPA_HBAC_SEARCH_BASE, IPA_HOST_SEARCH_BASE, IPA_SELINUX_SEARCH_BASE, @@ -139,6 +136,7 @@ struct ipa_options { struct sdap_options *id; struct ipa_id_ctx *id_ctx; struct be_resolv_ctx *be_res; + struct be_nsupdate_ctx *dyndns_ctx; /* auth and chpass provider */ struct dp_option *auth; @@ -169,6 +167,9 @@ int ipa_get_autofs_options(struct ipa_options *ipa_opts, const char *conf_path, struct sdap_options **_opts); +errno_t ipa_get_dyndns_options(struct be_ctx *be_ctx, + struct ipa_options *ctx); + int ipa_autofs_init(struct be_ctx *be_ctx, struct ipa_id_ctx *id_ctx, struct bet_ops **ops, diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index 79918a261be9c15a4f86c2885ac8723b5ed51cb6..8023b5336b0800b6bb019afe5a6337f43a3f2a82 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -28,6 +28,7 @@ #include "providers/ipa/ipa_common.h" #include "providers/ipa/ipa_dyndns.h" #include "providers/data_provider.h" +#include "providers/dp_dyndns.h" void ipa_dyndns_update(void *pvt); @@ -135,16 +136,16 @@ ipa_dyndns_update_send(struct ipa_options *ctx) subreq = sdap_dyndns_update_send(state, sdap_ctx->be->ev, sdap_ctx->be, sdap_ctx, - dp_opt_get_string(ctx->basic, - IPA_DYNDNS_IFACE), + dp_opt_get_string(ctx->dyndns_ctx->opts, + DP_OPT_DYNDNS_IFACE), dp_opt_get_string(ctx->basic, IPA_HOSTNAME), dns_zone, dp_opt_get_string(ctx->basic, IPA_KRB5_REALM), servername, - dp_opt_get_int(ctx->basic, - IPA_DYNDNS_TTL), + dp_opt_get_int(ctx->dyndns_ctx->opts, + DP_OPT_DYNDNS_TTL), true); if (!subreq) { ret = EIO; diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c index b65a6cea1ddd05272a8ae522be5c8b070a93ac1e..404bf53e4362da12df3008bdde78229a7288f678 100644 --- a/src/providers/ipa/ipa_init.c +++ b/src/providers/ipa/ipa_init.c @@ -40,6 +40,7 @@ #include "providers/ldap/sdap_access.h" #include "providers/ipa/ipa_subdomains.h" #include "providers/ipa/ipa_srv.h" +#include "providers/dp_dyndns.h" struct ipa_options *ipa_options = NULL; @@ -110,11 +111,9 @@ int sssm_ipa_id_init(struct be_ctx *bectx, { struct ipa_id_ctx *ipa_ctx; struct sdap_id_ctx *sdap_ctx; - struct stat stat_buf; const char *hostname; const char *ipa_domain; struct ipa_srv_plugin_ctx *srv_ctx; - errno_t err; int ret; if (!ipa_options) { @@ -153,7 +152,12 @@ int sssm_ipa_id_init(struct be_ctx *bectx, goto done; } - if(dp_opt_get_bool(ipa_options->basic, IPA_DYNDNS_UPDATE)) { + ret = ipa_get_dyndns_options(bectx, ipa_options); + if (ret != EOK) { + goto done; + } + + if (dp_opt_get_bool(ipa_options->dyndns_ctx->opts, DP_OPT_DYNDNS_UPDATE)) { /* Perform automatic DNS updates when the * IP address changes. * Register a callback for successful LDAP @@ -161,21 +165,10 @@ int sssm_ipa_id_init(struct be_ctx *bectx, * identify that we have gone online. */ - /* Ensure that nsupdate exists */ - errno = 0; - ret = stat(NSUPDATE_PATH, &stat_buf); - if (ret == -1) { - err = errno; - if (err == ENOENT) { - DEBUG(0, ("%s does not exist. Dynamic DNS updates disabled\n", - NSUPDATE_PATH)); - } - else { - DEBUG(0, ("Could not set up dynamic DNS updates: [%d][%s]\n", - err, strerror(err))); - } - } - else { + DEBUG(SSSDBG_CONF_SETTINGS, + ("Dynamic DNS updates are on. Checking for nsupdate..\n")); + ret = be_nsupdate_check(); + if (ret == EOK) { /* nsupdate is available. Dynamic updates * are supported */ diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 6adbdd96a907c26938b8cb80d22f156b09bbacc3..392fcd86fbe57c7b699390ed68918208886ffaab 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -35,9 +35,6 @@ struct dp_option ipa_basic_opts[] = { { "ipa_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_backup_server", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_hostname", DP_OPT_STRING, NULL_STRING, NULL_STRING }, - { "ipa_dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, - { "ipa_dyndns_ttl", DP_OPT_NUMBER, { .number = 1200}, NULL_NUMBER}, - { "ipa_dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING}, { "ipa_hbac_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING}, { "ipa_host_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ipa_selinux_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING }, @@ -54,6 +51,13 @@ struct dp_option ipa_basic_opts[] = { DP_OPTION_TERMINATOR }; +struct dp_option ipa_dyndns_opts[] = { + { "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, + DP_OPTION_TERMINATOR +}; + struct dp_option ipa_def_ldap_opts[] = { { "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_backup_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING }, diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c index fd92404388e52bfb9b7be544e9a3ffae923ebeb7..93d3373a49ecc96d0f32edab5e99ab8d5d45911d 100644 --- a/src/tests/cmocka/test_dyndns.c +++ b/src/tests/cmocka/test_dyndns.c @@ -81,7 +81,7 @@ void __wrap_execv(const char *path, char *const argv[]) int __wrap_getifaddrs(struct ifaddrs **_ifap) { - struct ifaddrs *ifap; + struct ifaddrs *ifap = NULL; struct ifaddrs *ifap_prev = NULL; struct ifaddrs *ifap_head = NULL; char *name; -- 1.8.2.1