diff options
-rw-r--r-- | src/config/SSSDConfig/__init__.py.in | 1 | ||||
-rwxr-xr-x | src/config/SSSDConfigTest.py | 2 | ||||
-rw-r--r-- | src/config/etc/sssd.api.conf | 1 | ||||
-rw-r--r-- | src/providers/dp_dyndns.c | 94 | ||||
-rw-r--r-- | src/providers/dp_dyndns.h | 8 | ||||
-rw-r--r-- | src/providers/ipa/ipa_dyndns.c | 1 | ||||
-rw-r--r-- | src/providers/ipa/ipa_opts.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_dyndns.c | 8 | ||||
-rw-r--r-- | src/providers/ldap/sdap_dyndns.h | 2 | ||||
-rw-r--r-- | src/tests/cmocka/test_dyndns.c | 3 |
10 files changed, 100 insertions, 21 deletions
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index c5475ffd..bc7bb0a7 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 21b4db70..9de4b2b4 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 013fa9fe..54cd703e 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 36cce458..a7bf54f9 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 a1e31e45..14b2dd08 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 bb38d105..b752f116 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 97dd6ea9..de9592b8 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 1c400f65..fbeb6a3d 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) { @@ -406,7 +410,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) } /* Fork a child process to perform the DNS update */ - subreq = be_nsupdate_send(state, state->ev, + subreq = be_nsupdate_send(state, state->ev, state->auth_type, state->update_msg, dp_opt_get_bool(state->opts, DP_OPT_DYNDNS_FORCE_TCP)); diff --git a/src/providers/ldap/sdap_dyndns.h b/src/providers/ldap/sdap_dyndns.h index a18a71fc..66de64a5 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 6b52347b..3ff5a30b 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); |