>From 65b442365efca1535d0d5a908f5717b1788349da 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 85a62680fe484b205baf6312a618ef70c7d25439..c21c7922a3a7ce09248506de797e2ef3405cb43d 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_use_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 fd71c7be34ebe9f061ba51340a5cc328761859a6..bc66c47a51a40a97d5e183c37a1d5ce7192595fd 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_use_tcp', + 'dyndns_auth', 'override_gid', 'case_sensitive', 'override_homedir', @@ -860,6 +861,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): 'dyndns_refresh_interval', 'dyndns_update_ptr', 'dyndns_use_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 7305d59a8d63455069a6b3e321b87db4a20ccd71..5dab3d2f0b4e41495e2d084999617fe6c36ed07b 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_use_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 8d4058c1cef2049749339c34da22cea6f2a72fc3..9e41631f40827d0744262f03d72932ee5646a937 100644 --- a/src/providers/dp_dyndns.c +++ b/src/providers/dp_dyndns.c @@ -903,9 +903,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 use_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 use_tcp) { @@ -915,7 +919,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) { @@ -934,24 +938,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 (use_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) { @@ -961,6 +947,12 @@ struct tevent_req *be_nsupdate_send(TALLOC_CTX *mem_ctx, goto done; } + args = be_nsupdate_args(state, auth_type, use_tcp); + if (args == NULL) { + ret = ENOMEM; + goto done; + } + errno = 0; execv(NSUPDATE_PATH, args); /* The child should never end up here */ @@ -993,6 +985,58 @@ done: return req; } +static char ** +be_nsupdate_args(TALLOC_CTX *mem_ctx, + enum be_nsupdate_auth auth_type, + bool use_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 (use_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) { @@ -1100,6 +1144,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_use_tcp", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }, + { "dyndns_auth", DP_OPT_STRING, { "gss-tsig" }, NULL_STRING }, DP_OPTION_TERMINATOR }; @@ -1114,6 +1159,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; @@ -1127,6 +1173,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 bb3fc48b58494b30a2e4b5c1ed65e49d8d148cf2..91025e11056a51637cd5ae081d48b281c86c4172 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_USE_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 use_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 24a55c180ea8ba8feb0b0d453a82f26995c19be7..3cde10f67b9e4c17f95981b8b2dfa76ea6c51fdb 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -244,6 +244,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 b539ca5966236b906e093084f67424f9a8fde1b9..c4b4136269aa0be7f519b786d9c74723603229c2 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_use_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 9e0ee98624b5a3b0514068b8c4e0d6d0ec0c0222..04cf83872fde320db10bdfded8ea41a844a480b7 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_USE_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.1.4