>From 25c6b6ad42b7e19b9e1f220b3cc5243a45a83fa6 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 16 Apr 2013 15:11:38 +0200 Subject: [PATCH 5/5] dyndns: new option dyndns_auth This options is mostly provided for future expansion. Currently it is undocumented and both IPA and AD dynamic DNS updates default to GSS-TSIG. Allowed values are GSS-TSIG and none. --- src/config/SSSDConfig/__init__.py.in | 1 + src/config/SSSDConfigTest.py | 2 + src/config/etc/sssd.api.conf | 1 + src/providers/dp_dyndns.c | 94 ++++++++++++++++++++++++++++-------- src/providers/dp_dyndns.h | 8 +++ src/providers/ipa/ipa_dyndns.c | 1 + src/providers/ipa/ipa_opts.h | 1 + src/providers/ldap/sdap_dyndns.c | 6 ++- src/providers/ldap/sdap_dyndns.h | 2 + src/tests/cmocka/test_dyndns.c | 3 ++ 10 files changed, 99 insertions(+), 20 deletions(-) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index c5475ffd8b599d3f60d7f1c992847d3ce00847b7..bc7bb0a781a64b264d350a7766cf45de869273cf 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -131,6 +131,7 @@ option_strings = { 'dyndns_refresh_interval' : _("How often to periodically update the client's DNS entry"), 'dyndns_update_ptr' : _("Whether the provider should explicitly update the PTR record as well"), 'dyndns_force_tcp' : _("Whether the nsupdate utility should default to using TCP"), + 'dyndns_auth' : _("What kind of authentication should be used to perform the DNS update"), # [provider/ipa] 'ipa_domain' : _('IPA domain'), diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 13418b90669a881721cf172314c0674afa77ec2c..237db070d61ed29f9254160eafe74c8e5f00dbb2 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -513,6 +513,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'dyndns_refresh_interval', 'dyndns_update_ptr', 'dyndns_force_tcp', + 'dyndns_auth', 'override_gid', 'case_sensitive', 'override_homedir', @@ -862,6 +863,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'dyndns_refresh_interval', 'dyndns_update_ptr', 'dyndns_force_tcp', + 'dyndns_auth', 'override_gid', 'case_sensitive', 'override_homedir', diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index 013fa9fe5a38bdd5c3dd1aa648287c56a0aa4211..54cd703e34eb11ac5f11d5ed344b1ac3102c57a0 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -128,6 +128,7 @@ dyndns_iface = str, None, false dyndns_refresh_interval = int, None, false dyndns_update_ptr = bool, None, false dyndns_force_tcp = bool, None, false +dyndns_auth = str, None, false # Special providers [provider/permit] diff --git a/src/providers/dp_dyndns.c b/src/providers/dp_dyndns.c index 36cce458216b51ab6a9b233b6c7dde29705828eb..a7bf54f9b0fc9b33caf2de9d838ea0b2da6b0c42 100644 --- a/src/providers/dp_dyndns.c +++ b/src/providers/dp_dyndns.c @@ -932,9 +932,13 @@ struct be_nsupdate_state { }; static void be_nsupdate_done(struct tevent_req *subreq); +static char **be_nsupdate_args(TALLOC_CTX *mem_ctx, + enum be_nsupdate_auth auth_type, + bool force_tcp); struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + enum be_nsupdate_auth auth_type, char *nsupdate_msg, bool force_tcp) { @@ -944,7 +948,7 @@ struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct be_nsupdate_state *state; - char *args[4]; + char **args; req = tevent_req_create(mem_ctx, &state, struct be_nsupdate_state); if (req == NULL) { @@ -963,24 +967,6 @@ struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, child_pid = fork(); if (child_pid == 0) { /* child */ - memset(args, 0, 4 * sizeof(char *)); - - args[0] = talloc_strdup(state, NSUPDATE_PATH); - args[1] = talloc_strdup(state, "-g"); - if (args[0] == NULL || args[1] == NULL) { - ret = ENOMEM; - goto done; - } - - if (force_tcp) { - DEBUG(SSSDBG_FUNC_DATA, ("TCP is set to on\n")); - args[2] = talloc_strdup(state, "-v"); - if (args[2] == NULL) { - ret = ENOMEM; - goto done; - } - } - close(pipefd_to_child[1]); ret = dup2(pipefd_to_child[0], STDIN_FILENO); if (ret == -1) { @@ -990,6 +976,12 @@ struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, goto done; } + args = be_nsupdate_args(state, auth_type, force_tcp); + if (args == NULL) { + ret = ENOMEM; + goto done; + } + errno = 0; execv(NSUPDATE_PATH, args); /* The child should never end up here */ @@ -1022,6 +1014,58 @@ done: return req; } +static char ** +be_nsupdate_args(TALLOC_CTX *mem_ctx, + enum be_nsupdate_auth auth_type, + bool force_tcp) +{ + char **argv; + int argc = 0; + + argv = talloc_zero_array(mem_ctx, char *, 4); + if (argv == NULL) { + return NULL; + } + + argv[argc] = talloc_strdup(argv, NSUPDATE_PATH); + if (argv[argc] == NULL) { + goto fail; + } + argc++; + + switch (auth_type) { + case BE_NSUPDATE_AUTH_NONE: + DEBUG(SSSDBG_FUNC_DATA, ("nsupdate auth type: none\n")); + break; + case BE_NSUPDATE_AUTH_GSS_TSIG: + DEBUG(SSSDBG_FUNC_DATA, ("nsupdate auth type: GSS-TSIG\n")); + argv[argc] = talloc_strdup(argv, "-g"); + if (argv[argc] == NULL) { + goto fail; + } + argc++; + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, ("Unknown nsupdate auth type\n")); + goto fail; + } + + if (force_tcp) { + DEBUG(SSSDBG_FUNC_DATA, ("TCP is set to on\n")); + argv[argc] = talloc_strdup(argv, "-v"); + if (argv[argc] == NULL) { + goto fail; + } + argc++; + } + + return argv; + +fail: + talloc_free(argv); + return NULL; +} + static void be_nsupdate_done(struct tevent_req *subreq) { @@ -1129,6 +1173,7 @@ static struct dp_option default_dyndns_opts[] = { { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_TRUE, BOOL_FALSE }, { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, DP_OPTION_TERMINATOR }; @@ -1143,6 +1188,7 @@ be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, errno_t ret; struct dp_option *src_opts; struct be_nsupdate_ctx *ctx; + char *strauth; ctx = talloc_zero(mem_ctx, struct be_nsupdate_ctx); if (ctx == NULL) return ENOMEM; @@ -1156,6 +1202,16 @@ be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, return ret; } + strauth = dp_opt_get_string(ctx->opts, DP_OPT_DYNDNS_AUTH); + if (strcasecmp(strauth, "gss-tsig") == 0) { + ctx->auth_type = BE_NSUPDATE_AUTH_GSS_TSIG; + } else if (strcasecmp(strauth, "none") == 0) { + ctx->auth_type = BE_NSUPDATE_AUTH_NONE; + } else { + DEBUG(SSSDBG_OP_FAILURE, ("Uknown dyndns auth type %s\n", strauth)); + return EINVAL; + } + ctx->timer_callback = timer_callback; ctx->timer_pvt = timer_pvt; be_nsupdate_timer_schedule(be_ctx->ev, ctx); diff --git a/src/providers/dp_dyndns.h b/src/providers/dp_dyndns.h index a1e31e450c10f64abf8bc1ec86d408abfcd557e8..14b2dd08b03a422b2c0bc5bc5b184baf54491bca 100644 --- a/src/providers/dp_dyndns.h +++ b/src/providers/dp_dyndns.h @@ -31,8 +31,14 @@ struct sss_iface_addr; typedef void (*nsupdate_timer_fn_t)(void *pvt); +enum be_nsupdate_auth { + BE_NSUPDATE_AUTH_NONE, + BE_NSUPDATE_AUTH_GSS_TSIG, +}; + struct be_nsupdate_ctx { struct dp_option *opts; + enum be_nsupdate_auth auth_type; time_t last_refresh; bool timer_in_progress; @@ -48,6 +54,7 @@ enum dp_dyndns_opts { DP_OPT_DYNDNS_TTL, DP_OPT_DYNDNS_UPDATE_PTR, DP_OPT_DYNDNS_FORCE_TCP, + DP_OPT_DYNDNS_AUTH, DP_OPT_DYNDNS /* attrs counter */ }; @@ -104,6 +111,7 @@ be_nsupdate_create_ptr_msg(TALLOC_CTX *mem_ctx, const char *realm, */ struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + enum be_nsupdate_auth auth_type, char *nsupdate_msg, bool force_tcp); errno_t be_nsupdate_recv(struct tevent_req *req, int *child_status); diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index bb38d105f41b46cf26f0f11c399a23f2a9642a92..b752f116f5149f1c576a017afd1091a225d8277a 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -245,6 +245,7 @@ ipa_dyndns_update_send(struct ipa_options *ctx) sdap_ctx->be, ctx->dyndns_ctx->opts, sdap_ctx, + ctx->dyndns_ctx->auth_type, dp_opt_get_string(ctx->dyndns_ctx->opts, DP_OPT_DYNDNS_IFACE), dp_opt_get_string(ctx->basic, diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h index 97dd6ea9fd1444ed1661240efc8e95773d160380..de9592b85c50ced32b7ab1c19c5f59eef89d6354 100644 --- a/src/providers/ipa/ipa_opts.h +++ b/src/providers/ipa/ipa_opts.h @@ -58,6 +58,7 @@ struct dp_option ipa_dyndns_opts[] = { { "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER }, { "dyndns_update_ptr", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, { "dyndns_force_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 3be34a490396058f8ccd237b733e41b0e4b63cdb..fbeb6a3d4fd5a53c70584daf4e40f74d8f9799e4 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -57,6 +57,7 @@ struct sdap_dyndns_update_state { bool update_ptr; bool check_diff; + enum be_nsupdate_auth auth_type; bool use_server_with_nsupdate; char *update_msg; }; @@ -76,6 +77,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_option *opts, struct sdap_id_ctx *sdap_ctx, + enum be_nsupdate_auth auth_type, const char *ifname, const char *hostname, const char *dns_zone, @@ -104,6 +106,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, state->be_res = be_ctx->be_res; state->ev = ev; state->opts = opts; + state->auth_type = auth_type; if (ifname) { /* Unless one family is restricted, just replace all @@ -323,7 +326,8 @@ sdap_dyndns_update_step(struct tevent_req *req) } /* Fork a child process to perform the DNS update */ - subreq = be_nsupdate_send(state, state->ev, state->update_msg, + subreq = be_nsupdate_send(state, state->ev, state->auth_type, + state->update_msg, dp_opt_get_bool(state->opts, DP_OPT_DYNDNS_FORCE_TCP)); if (subreq == NULL) { diff --git a/src/providers/ldap/sdap_dyndns.h b/src/providers/ldap/sdap_dyndns.h index a18a71fc9d62d2de8f9cc574cf376a959d7a4c99..66de64a59c9b5408641b7f4c32a3e1dc814c80af 100644 --- a/src/providers/ldap/sdap_dyndns.h +++ b/src/providers/ldap/sdap_dyndns.h @@ -27,6 +27,7 @@ #include "util/util.h" #include "providers/dp_backend.h" +#include "providers/dp_dyndns.h" #include "providers/ldap/ldap_common.h" struct tevent_req * @@ -35,6 +36,7 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_option *opts, struct sdap_id_ctx *sdap_ctx, + enum be_nsupdate_auth auth_type, const char *ifname, const char *hostname, const char *dns_zone, diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c index cb79df98fc136d1d552d22e6cd7832af20ab866b..9b3d636c54539926433d323562a7d620d94a15f3 100644 --- a/src/tests/cmocka/test_dyndns.c +++ b/src/tests/cmocka/test_dyndns.c @@ -210,6 +210,7 @@ void dyndns_test_ok(void **state) dyndns_test_ctx->state = MOCK_NSUPDATE_OK; req = be_nsupdate_send(tmp_ctx, dyndns_test_ctx->tctx->ev, + BE_NSUPDATE_AUTH_GSS_TSIG, discard_const("test message"), false); assert_non_null(req); tevent_req_set_callback(req, dyndns_test_done, dyndns_test_ctx); @@ -240,6 +241,7 @@ void dyndns_test_error(void **state) dyndns_test_ctx->state = MOCK_NSUPDATE_ERR; req = be_nsupdate_send(tmp_ctx, dyndns_test_ctx->tctx->ev, + BE_NSUPDATE_AUTH_GSS_TSIG, discard_const("test message"), false); assert_non_null(req); tevent_req_set_callback(req, dyndns_test_done, dyndns_test_ctx); @@ -270,6 +272,7 @@ void dyndns_test_timeout(void **state) dyndns_test_ctx->state = MOCK_NSUPDATE_TIMEOUT; req = be_nsupdate_send(tmp_ctx, dyndns_test_ctx->tctx->ev, + BE_NSUPDATE_AUTH_GSS_TSIG, discard_const("test message"), false); assert_non_null(req); tevent_req_set_callback(req, dyndns_test_done, dyndns_test_ctx); -- 1.8.2.1