5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose Sumit Bose <sbose@redhat.com>
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose Copyright (C) 2016 Red Hat
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose This program is free software; you can redistribute it and/or modify
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose it under the terms of the GNU General Public License as published by
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose the Free Software Foundation; either version 3 of the License, or
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose (at your option) any later version.
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose This program is distributed in the hope that it will be useful,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose GNU General Public License for more details.
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose You should have received a copy of the GNU General Public License
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosestatic errno_t get_adcli_extra_args(const char *ad_domain,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Missing AD domain or hostname.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose renewal_data->prog_path = talloc_strdup(renewal_data, RENEWAL_PROG_PATH);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose args = talloc_array(renewal_data, const char *, 8);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose /* extra_args are added in revers order */
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose /* first add NULL as a placeholder for the server name which is determined
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose * at runtime */
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose args[c++] = talloc_asprintf(args, "--computer-password-lifetime=%zu",
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose args[c++] = talloc_asprintf(args, "--host-fqdn=%s", ad_hostname);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose args[c++] = talloc_asprintf(args, "--host-keytab=%s", ad_keytab);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose args[c++] = talloc_asprintf(args, "--domain=%s", ad_domain);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose "talloc failed while copying arguments.\n");
77e5c3fc26085f18277a70ffbd6351a8130963e7Yuri Chornoivan } while (c != 1); /* it is expected that the first element is NULL */
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosestatic void ad_machine_account_password_renewal_done(struct tevent_req *subreq);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosead_machine_account_password_renewal_timeout(struct tevent_context *ev,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosestatic struct tevent_req *
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosead_machine_account_password_renewal_send(TALLOC_CTX *mem_ctx,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose req = tevent_req_create(mem_ctx, &state, struct renewal_state);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose renewal_data = talloc_get_type(pvt, struct renewal_data);
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek state->io = talloc(state, struct child_io_fds);
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek talloc_set_destructor((void *) state->io, child_io_destructor);
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose server_name = be_fo_get_active_server_name(be_ctx, AD_SERVICE_NAME);
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose renewal_data->extra_args[0] = talloc_asprintf(renewal_data->extra_args,
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose "--domain-controller=%s",
8167761a1e1d7575d49babcea45937fc9cd45fdcSumit Bose /* if talloc_asprintf() fails we let adcli try to find a server */
de8815aba87d08b6b7ac5d502dcb1755787e0857Jakub Hrozek exec_child_ex(state, pipefd_to_child, pipefd_from_child,
de8815aba87d08b6b7ac5d502dcb1755787e0857Jakub Hrozek /* We should never get here */
de8815aba87d08b6b7ac5d502dcb1755787e0857Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Could not exec renewal child\n");
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek state->io->read_from_child_fd = pipefd_from_child[0];
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek sss_fd_nonblocking(state->io->read_from_child_fd);
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek state->io->write_to_child_fd = pipefd_to_child[1];
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek sss_fd_nonblocking(state->io->write_to_child_fd);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose /* Set up SIGCHLD handler */
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose ret = child_handler_setup(ev, child_pid, NULL, NULL, &state->child_ctx);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "Could not set up child handlers [%d]: %s\n",
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose /* Set up timeout handler */
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose tv = tevent_timeval_current_ofs(be_ptask_get_timeout(be_ptask), 0);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose state->timeout_handler = tevent_add_timer(ev, req, tv,
518f5b83fd546e3188da01e4743ddb27a574e08fJakub Hrozek subreq = read_pipe_send(state, ev, state->io->read_from_child_fd);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "read_pipe_send failed.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose /* Now either wait for the timeout to fire or the child
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose } else { /* error */
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "fork failed [%d][%s].\n",
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosestatic void ad_machine_account_password_renewal_done(struct tevent_req *subreq)
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose struct tevent_req *req = tevent_req_callback_data(subreq,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose struct renewal_state *state = tevent_req_data(req, struct renewal_state);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose ret = read_pipe_recv(subreq, state, &buf, &buf_len);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_TRACE_LIBS, "--- adcli output start---\n"
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose "---adcli output end---\n",
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosead_machine_account_password_renewal_timeout(struct tevent_context *ev,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose struct renewal_state *state = tevent_req_data(req, struct renewal_state);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Timeout reached for AD renewal child.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bosead_machine_account_password_renewal_recv(struct tevent_req *req)
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Boseerrno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx,
030b821b3704771b15f58293e2b1259a2c0fc32fJakub Hrozek "The helper program ["RENEWAL_PROG_PATH"] for renewal "
030b821b3704771b15f58293e2b1259a2c0fc32fJakub Hrozek "doesn't exist [%d]: %s\n", ret, strerror(ret));
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CONF_SETTINGS, "Automatic machine account renewal disabled.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose "Illegal value [%d] for password lifetime.\n", lifetime);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose renewal_data = talloc(be_ctx, struct renewal_data);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose ret = split_on_separator(renewal_data, dummy, ':', true, false,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Wrong number of renewal options.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose if (errno != 0 || *endptr != '\0' || opt_list[0] == endptr) {
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse first renewal option.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose initial_delay = strtouint32(opt_list[1], &endptr, 10);
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose if (errno != 0 || *endptr != '\0' || opt_list[0] == endptr) {
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse second renewal option.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose ret = get_adcli_extra_args(dp_opt_get_cstring(ad_opts->basic, AD_DOMAIN),
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose dp_opt_get_cstring(ad_opts->id_ctx->sdap_id_ctx->opts->basic,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "get_adcli_extra_args failed.\n");
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose ret = be_ptask_create(be_ctx, be_ctx, period, initial_delay, 0, 0, 60,
5f7cd30c865046a7ea69944f7e07c85b4c43465aSumit Bose DEBUG(SSSDBG_OP_FAILURE, "be_ptask_create failed.\n");