diff options
Diffstat (limited to 'server/providers/ldap/sdap_child_helpers.c')
-rw-r--r-- | server/providers/ldap/sdap_child_helpers.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/server/providers/ldap/sdap_child_helpers.c b/server/providers/ldap/sdap_child_helpers.c deleted file mode 100644 index 0a95c8a0..00000000 --- a/server/providers/ldap/sdap_child_helpers.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - SSSD - - LDAP Backend Module -- child helpers - - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <sys/types.h> -#include <sys/wait.h> -#include <pwd.h> -#include <unistd.h> -#include <fcntl.h> - -#include "util/util.h" -#include "providers/ldap/ldap_common.h" -#include "providers/child_common.h" - -#ifndef SSSD_LIBEXEC_PATH -#error "SSSD_LIBEXEC_PATH not defined" -#else -#define LDAP_CHILD SSSD_LIBEXEC_PATH"/ldap_child" -#endif - -#ifndef LDAP_CHILD_USER -#define LDAP_CHILD_USER "nobody" -#endif - -struct sdap_child { - /* child info */ - pid_t pid; - int read_from_child_fd; - int write_to_child_fd; -}; - -static void sdap_close_fd(int *fd) -{ - int ret; - - if (*fd == -1) { - DEBUG(6, ("fd already closed\n")); - return; - } - - ret = close(*fd); - if (ret) { - ret = errno; - DEBUG(2, ("Closing fd %d, return error %d (%s)\n", - *fd, ret, strerror(ret))); - } - - *fd = -1; -} - -static int sdap_child_destructor(void *ptr) -{ - struct sdap_child *child = talloc_get_type(ptr, struct sdap_child); - - child_cleanup(child->read_from_child_fd, child->write_to_child_fd); - - return 0; -} - -static errno_t sdap_fork_child(struct sdap_child *child) -{ - int pipefd_to_child[2]; - int pipefd_from_child[2]; - pid_t pid; - int ret; - errno_t err; - - ret = pipe(pipefd_from_child); - if (ret == -1) { - err = errno; - DEBUG(1, ("pipe failed [%d][%s].\n", err, strerror(err))); - return err; - } - ret = pipe(pipefd_to_child); - if (ret == -1) { - err = errno; - DEBUG(1, ("pipe failed [%d][%s].\n", err, strerror(err))); - return err; - } - - pid = fork(); - - if (pid == 0) { /* child */ - err = exec_child(child, - pipefd_to_child, pipefd_from_child, - LDAP_CHILD, ldap_child_debug_fd); - if (err != EOK) { - DEBUG(1, ("Could not exec LDAP child: [%d][%s].\n", - err, strerror(err))); - return err; - } - } else if (pid > 0) { /* parent */ - child->pid = pid; - child->read_from_child_fd = pipefd_from_child[0]; - close(pipefd_from_child[1]); - child->write_to_child_fd = pipefd_to_child[1]; - close(pipefd_to_child[0]); - fd_nonblocking(child->read_from_child_fd); - fd_nonblocking(child->write_to_child_fd); - - } else { /* error */ - err = errno; - DEBUG(1, ("fork failed [%d][%s].\n", err, strerror(err))); - return err; - } - - return EOK; -} - -static errno_t create_tgt_req_send_buffer(TALLOC_CTX *mem_ctx, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - struct io_buffer **io_buf) -{ - struct io_buffer *buf; - size_t rp; - - buf = talloc(mem_ctx, struct io_buffer); - if (buf == NULL) { - DEBUG(1, ("talloc failed.\n")); - return ENOMEM; - } - - buf->size = 3 * sizeof(uint32_t); - if (realm_str) { - buf->size += strlen(realm_str); - } - if (princ_str) { - buf->size += strlen(princ_str); - } - if (keytab_name) { - buf->size += strlen(keytab_name); - } - - DEBUG(7, ("buffer size: %d\n", buf->size)); - - buf->data = talloc_size(buf, buf->size); - if (buf->data == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - talloc_free(buf); - return ENOMEM; - } - - rp = 0; - - /* realm */ - if (realm_str) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(realm_str), rp); - COPY_MEM(&buf->data[rp], realm_str, rp, strlen(realm_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - /* principal */ - if (princ_str) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(princ_str), rp); - COPY_MEM(&buf->data[rp], princ_str, rp, strlen(princ_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - /* keytab */ - if (keytab_name) { - COPY_UINT32_VALUE(&buf->data[rp], strlen(keytab_name), rp); - COPY_MEM(&buf->data[rp], keytab_name, rp, strlen(realm_str)); - } else { - COPY_UINT32_VALUE(&buf->data[rp], 0, rp); - } - - *io_buf = buf; - return EOK; -} - -static int parse_child_response(TALLOC_CTX *mem_ctx, - uint8_t *buf, ssize_t size, - int *result, char **ccache) -{ - size_t p = 0; - uint32_t len; - uint32_t res; - char *ccn; - - /* operation result code */ - COPY_UINT32_CHECK(&res, buf + p, p, size); - - /* ccache name size */ - COPY_UINT32_CHECK(&len, buf + p, p, size); - - if ((p + len ) > size) return EINVAL; - - ccn = talloc_size(mem_ctx, sizeof(char) * (len + 1)); - if (ccn == NULL) { - DEBUG(1, ("talloc_size failed.\n")); - return ENOMEM; - } - memcpy(ccn, buf+p, sizeof(char) * (len + 1)); - ccn[len] = '\0'; - - *result = res; - *ccache = ccn; - return EOK; -} - -/* ==The-public-async-interface============================================*/ - -struct sdap_get_tgt_state { - struct tevent_context *ev; - struct sdap_child *child; - ssize_t len; - uint8_t *buf; -}; - -static errno_t set_tgt_child_timeout(struct tevent_req *req, - struct tevent_context *ev, - int timeout); -static void sdap_get_tgt_step(struct tevent_req *subreq); -static void sdap_get_tgt_done(struct tevent_req *subreq); - -struct tevent_req *sdap_get_tgt_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const char *realm_str, - const char *princ_str, - const char *keytab_name, - int timeout) -{ - struct tevent_req *req, *subreq; - struct sdap_get_tgt_state *state; - struct io_buffer *buf; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct sdap_get_tgt_state); - if (!req) { - return NULL; - } - - state->ev = ev; - - state->child = talloc_zero(state, struct sdap_child); - if (!state->child) { - ret = ENOMEM; - goto fail; - } - - state->child->read_from_child_fd = -1; - state->child->write_to_child_fd = -1; - talloc_set_destructor((TALLOC_CTX *)state->child, sdap_child_destructor); - - /* prepare the data to pass to child */ - ret = create_tgt_req_send_buffer(state, - realm_str, princ_str, keytab_name, - &buf); - if (ret != EOK) { - DEBUG(1, ("create_tgt_req_send_buffer failed.\n")); - goto fail; - } - - ret = sdap_fork_child(state->child); - if (ret != EOK) { - DEBUG(1, ("sdap_fork_child failed.\n")); - goto fail; - } - - ret = set_tgt_child_timeout(req, ev, timeout); - if (ret != EOK) { - DEBUG(1, ("activate_child_timeout_handler failed.\n")); - goto fail; - } - - subreq = write_pipe_send(state, ev, buf->data, buf->size, - state->child->write_to_child_fd); - if (!subreq) { - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_get_tgt_step, req); - - return req; - -fail: - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void sdap_get_tgt_step(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - ret = write_pipe_recv(subreq); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - sdap_close_fd(&state->child->write_to_child_fd); - - subreq = read_pipe_send(state, state->ev, - state->child->read_from_child_fd); - if (!subreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(subreq, sdap_get_tgt_done, req); -} - -static void sdap_get_tgt_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - ret = read_pipe_recv(subreq, state, &state->buf, &state->len); - talloc_zfree(subreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - sdap_close_fd(&state->child->read_from_child_fd); - - tevent_req_done(req); -} - -int sdap_get_tgt_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - int *result, - char **ccname) -{ - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - char *ccn; - int res; - int ret; - - TEVENT_REQ_RETURN_ON_ERROR(req); - - ret = parse_child_response(mem_ctx, state->buf, state->len, &res, &ccn); - if (ret != EOK) { - DEBUG(1, ("Cannot parse child response: [%d][%s]\n", ret, strerror(ret))); - return ret; - } - - DEBUG(6, ("Child responded: %d [%s]\n", res, ccn)); - *result = res; - *ccname = ccn; - return EOK; -} - - - -static void get_tgt_timeout_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); - struct sdap_get_tgt_state *state = tevent_req_data(req, - struct sdap_get_tgt_state); - int ret; - - DEBUG(9, ("timeout for tgt child [%d] reached.\n", state->child->pid)); - - ret = kill(state->child->pid, SIGKILL); - if (ret == -1) { - DEBUG(1, ("kill failed [%d][%s].\n", errno, strerror(errno))); - } - - tevent_req_error(req, ETIMEDOUT); -} - -static errno_t set_tgt_child_timeout(struct tevent_req *req, - struct tevent_context *ev, - int timeout) -{ - struct tevent_timer *te; - struct timeval tv; - - DEBUG(6, ("Setting %d seconds timeout for tgt child\n", timeout)); - - tv = tevent_timeval_current_ofs(timeout, 0); - - te = tevent_add_timer(ev, req, tv, get_tgt_timeout_handler, req); - if (te == NULL) { - DEBUG(1, ("tevent_add_timer failed.\n")); - return ENOMEM; - } - - return EOK; -} - - - -/* Setup child logging */ -int setup_child(struct sdap_id_ctx *ctx) -{ - int ret; - const char *mech; - struct tevent_signal *sige; - unsigned v; - FILE *debug_filep; - - mech = dp_opt_get_string(ctx->opts->basic, - SDAP_SASL_MECH); - if (!mech) { - return EOK; - } - - sige = tevent_add_signal(ctx->be->ev, ctx, SIGCHLD, SA_SIGINFO, - child_sig_handler, NULL); - if (sige == NULL) { - DEBUG(1, ("tevent_add_signal failed.\n")); - return ENOMEM; - } - - if (debug_to_file != 0 && ldap_child_debug_fd == -1) { - ret = open_debug_file_ex("ldap_child", &debug_filep); - if (ret != EOK) { - DEBUG(0, ("Error setting up logging (%d) [%s]\n", - ret, strerror(ret))); - return ret; - } - - ldap_child_debug_fd = fileno(debug_filep); - if (ldap_child_debug_fd == -1) { - DEBUG(0, ("fileno failed [%d][%s]\n", errno, strerror(errno))); - ret = errno; - return ret; - } - - v = fcntl(ldap_child_debug_fd, F_GETFD, 0); - fcntl(ldap_child_debug_fd, F_SETFD, v & ~FD_CLOEXEC); - } - - return EOK; -} |