struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *uri, struct sockaddr_storage *addr, int addr_len, int timeout) { int ret = EOK; struct tevent_req *req; struct sss_ldap_init_state *state; req = tevent_req_create(mem_ctx, &state, struct sss_ldap_init_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n"); return NULL; } talloc_set_destructor((TALLOC_CTX *)state, sss_ldap_init_state_destructor); state->ldap = NULL; state->sd = -1; state->uri = uri; #ifdef HAVE_LDAP_INIT_FD struct tevent_req *subreq; subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout); if (subreq == NULL) { ret = ENOMEM; DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n"); goto fail; } tevent_req_set_callback(subreq, sss_ldap_init_sys_connect_done, req); return req; fail: tevent_req_error(req, ret); #else DEBUG(SSSDBG_MINOR_FAILURE, "ldap_init_fd not available, " "will use ldap_initialize with uri [%s].\n", uri); ret = ldap_initialize(&state->ldap, uri); if (ret == LDAP_SUCCESS) { tevent_req_done(req); } else { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_initialize failed [%s].\n", sss_ldap_err2string(ret)); if (ret == LDAP_SERVER_DOWN) { tevent_req_error(req, ETIMEDOUT); } else { tevent_req_error(req, EIO); } } #endif tevent_req_post(req, ev); return req; }
struct tevent_req *ctdb_conn_init_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *sock) { struct tevent_req *req, *subreq; struct ctdb_conn_init_state *state; req = tevent_req_create(mem_ctx, &state, struct ctdb_conn_init_state); if (req == NULL) { return NULL; } if (!lp_clustering()) { tevent_req_error(req, ENOSYS); return tevent_req_post(req, ev); } if (strlen(sock) >= sizeof(state->addr.sun_path)) { tevent_req_error(req, ENAMETOOLONG); return tevent_req_post(req, ev); } state->conn = talloc(state, struct ctdb_conn); if (tevent_req_nomem(state->conn, req)) { return tevent_req_post(req, ev); } state->conn->outqueue = tevent_queue_create( state->conn, "ctdb outqueue"); if (tevent_req_nomem(state->conn->outqueue, req)) { return tevent_req_post(req, ev); } state->conn->fd = socket(AF_UNIX, SOCK_STREAM, 0); if (state->conn->fd == -1) { tevent_req_error(req, errno); return tevent_req_post(req, ev); } talloc_set_destructor(state->conn, ctdb_conn_destructor); state->addr.sun_family = AF_UNIX; strncpy(state->addr.sun_path, sock, sizeof(state->addr.sun_path)); subreq = async_connect_send(state, ev, state->conn->fd, (struct sockaddr *)&state->addr, sizeof(state->addr), before_connect_cb, after_connect_cb, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, ctdb_conn_init_done, req); return req; }
void setent_notify(struct setent_req_list **list, errno_t err) { struct setent_req_list *reql; /* Notify the waiting clients */ while ((reql = *list) != NULL) { /* Each tevent_req_done() call will free * the request, removing it from the list. */ if (err == EOK) { tevent_req_done(reql->req); } else { tevent_req_error(reql->req, err); } if (reql == *list) { /* The consumer failed to free the * request. Log a bug and continue. */ DEBUG(SSSDBG_FATAL_FAILURE, ("BUG: a callback did not free its request. " "May leak memory\n")); /* Skip to the next since a memory leak is non-fatal */ *list = (*list)->next; } } }
static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_rules_refresh_state *state = NULL; char *highest_usn = NULL; size_t downloaded_rules_num; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error, &highest_usn, &downloaded_rules_num); talloc_zfree(subreq); if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) { goto done; } /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } if (downloaded_rules_num != state->num_rules) { state->error = ENOENT; } done: if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_smart_refresh_state *state = NULL; char *highest_usn = NULL; int dp_error; int error; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &dp_error, &error, &highest_usn, NULL); if (ret != EOK || dp_error != DP_ERR_OK || error != EOK) { goto done; } DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n"); /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } done: if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static void tsocket_writev_handler(struct tsocket_context *sock, void *private_data) { struct tevent_req *req = talloc_get_type(private_data, struct tevent_req); struct tsocket_writev_state *state = tevent_req_data(req, struct tsocket_writev_state); int ret; int err; bool retry; ret = tsocket_writev(state->caller.sock, state->iov, state->count); err = tsocket_error_from_errno(ret, errno, &retry); if (retry) { /* retry later */ return; } if (tevent_req_error(req, err)) { return; } state->total_written += ret; /* * we have not written everything yet, so we need to truncate * the already written bytes from our iov copy */ while (ret > 0) { if (ret < state->iov[0].iov_len) { uint8_t *base; base = (uint8_t *)state->iov[0].iov_base; base += ret; state->iov[0].iov_base = base; state->iov[0].iov_len -= ret; break; } ret -= state->iov[0].iov_len; state->iov += 1; state->count -= 1; } if (state->count > 0) { /* more to write */ return; } tevent_req_done(req); }
static void ctdb_conn_init_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); int ret, err; ret = async_connect_recv(subreq, &err); TALLOC_FREE(subreq); if (ret == -1) { tevent_req_error(req, err); return; } tevent_req_done(req); }
static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); struct sss_ldap_init_state *state = tevent_req_data(req, struct sss_ldap_init_state); int ret; int lret; ret = sssd_async_socket_init_recv(subreq, &state->sd); talloc_zfree(subreq); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init request failed: [%d]: %s.\n", ret, sss_strerror(ret)); goto fail; } /* Initialize LDAP handler */ lret = ldap_init_fd(state->sd, LDAP_PROTO_TCP, state->uri, &state->ldap); if (lret != LDAP_SUCCESS) { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_init_fd failed: %s. [%d][%s]\n", sss_ldap_err2string(lret), state->sd, state->uri); ret = lret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO; goto fail; } if (ldap_is_ldaps_url(state->uri)) { lret = ldap_install_tls(state->ldap); if (lret != LDAP_SUCCESS) { if (lret == LDAP_LOCAL_ERROR) { DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n"); } else { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_install_tls failed: %s\n", sss_ldap_err2string(lret)); ret = EIO; goto fail; } } } tevent_req_done(req); return; fail: tevent_req_error(req, ret); }
static void sbus_request_notify_error(hash_table_t *table, const char *key, struct tevent_req *req, errno_t error) { struct sbus_request_list *mainreq = NULL; struct sbus_request_list *list; struct sbus_request_list *item; list = sbus_requests_lookup(table, key); if (list == NULL) { /* This was the only request with no key generator available. */ tevent_req_error(req, error); return; } /* First notify all chained D-Bus requests. */ DLIST_FOR_EACH(item, list) { /* Remember the main request. */ if (item->req == req) { mainreq = item; continue; } /* We don't want to notify current, invalid or non D-Bus request. */ if (!item->is_dbus || item->is_invalid) { continue; } sbus_requests_finish(item, error); } /* Now we finish the main request. */ sbus_requests_finish(mainreq, error); /* And as last, we notify all await requests. */ DLIST_FOR_EACH(item, list) { if (item->is_dbus) { continue; } sbus_requests_finish(item, error); } sbus_requests_delete(list); }
static void sdap_sudo_full_refresh_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; struct sdap_sudo_full_refresh_state *state = NULL; char *highest_usn = NULL; int ret; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_full_refresh_state); ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error, &highest_usn, NULL); talloc_zfree(subreq); if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) { goto done; } state->sudo_ctx->full_refresh_done = true; /* save the time in the sysdb */ ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL)); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of " "a successful full refresh\n"); /* this is only a minor error that does not affect the functionality, * therefore there is no need to report it with tevent_req_error() * which would cause problems in the consumers */ } DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n"); /* set highest usn */ if (highest_usn != NULL) { sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn); } done: state->sudo_ctx->full_refresh_in_progress = false; if (ret != EOK) { tevent_req_error(req, ret); return; } tevent_req_done(req); }
static struct tevent_req *aio_posix_pread_send( struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct files_struct *fsp, void *data, size_t n, off_t offset) { struct tevent_req *req; struct aio_posix_state *state; struct aiocb *a; int ret; req = tevent_req_create(mem_ctx, &state, struct aio_posix_state); if (req == NULL) { return NULL; } a = &state->acb; a->aio_fildes = fsp->fh->fd; a->aio_buf = data; a->aio_nbytes = n; a->aio_offset = offset; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; a->aio_sigevent.sigev_value.sival_ptr = req; ret = aio_read(a); if (ret == 0) { talloc_set_destructor(state, aio_posix_state_destructor); return req; } if (errno == EAGAIN) { /* * aio overloaded, do the sync fallback */ state->ret = sys_pread(fsp->fh->fd, data, n, offset); if (state->ret == -1) { state->err = errno; } tevent_req_done(req); return tevent_req_post(req, ev); } tevent_req_error(req, errno); return tevent_req_post(req, ev); }
/* issue smart refresh of sudo rules */ static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; struct sdap_attr_map *map = id_ctx->opts->sudorule_map; struct sdap_server_opts *srv_opts = id_ctx->srv_opts; struct sdap_sudo_smart_refresh_state *state = NULL; char *ldap_filter = NULL; char *ldap_full_filter = NULL; const char *usn; int ret; req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); return NULL; } if (!sudo_ctx->full_refresh_done && (srv_opts == NULL || srv_opts->max_sudo_value == 0)) { /* Perform full refresh first */ DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, " "waiting for full refresh!\n"); ret = EINVAL; goto immediately; } state->id_ctx = id_ctx; state->sysdb = id_ctx->be->domain->sysdb; /* Download all rules from LDAP that are newer than usn */ usn = srv_opts->max_sudo_value; if (usn != NULL) { ldap_filter = talloc_asprintf(state, "(&(objectclass=%s)(%s>=%s)(!(%s=%s)))", map[SDAP_OC_SUDORULE].name, map[SDAP_AT_SUDO_USN].name, usn, map[SDAP_AT_SUDO_USN].name, usn); } else { /* no valid USN value known */ ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS, map[SDAP_OC_SUDORULE].name); } if (ldap_filter == NULL) { ret = ENOMEM; goto immediately; } ldap_full_filter = sdap_sudo_get_filter(state, map, sudo_ctx, ldap_filter); if (ldap_full_filter == NULL) { ret = ENOMEM; goto immediately; } /* Do not remove any rules that are already in the sysdb * sysdb_filter = NULL; */ DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules " "(USN > %s)\n", (usn == NULL ? "0" : usn)); subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts, id_ctx->conn->conn_cache, ldap_full_filter, NULL); if (subreq == NULL) { ret = ENOMEM; goto immediately; } state->subreq = subreq; tevent_req_set_callback(subreq, sdap_sudo_smart_refresh_done, req); /* free filters */ talloc_free(ldap_filter); talloc_free(ldap_full_filter); return req; immediately: if (ret == EOK) { tevent_req_done(req); } else { tevent_req_error(req, ret); } tevent_req_post(req, id_ctx->be->ev); return req; }
/* handle stdout/stderr from the child */ static void samba_runcmd_io_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct tevent_req *req = talloc_get_type_abort(private_data, struct tevent_req); struct samba_runcmd_state *state = tevent_req_data(req, struct samba_runcmd_state); int level; char *p; int n, fd; if (!(flags & TEVENT_FD_READ)) { return; } if (fde == state->fde_stdout) { level = state->stdout_log_level; fd = state->fd_stdout; } else if (fde == state->fde_stderr) { level = state->stderr_log_level; fd = state->fd_stderr; } else { int status; status = tfork_status(&state->tfork, false); if (status == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return; } DBG_ERR("Bad read on status pipe\n"); tevent_req_error(req, errno); return; } state->pid = -1; TALLOC_FREE(fde); if (WIFEXITED(status)) { status = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { status = WTERMSIG(status); } else { status = ECHILD; } DBG_NOTICE("Child %s exited %d\n", state->arg0, status); if (status != 0) { tevent_req_error(req, status); return; } tevent_req_done(req); return; } n = read(fd, &state->buf[state->buf_used], sizeof(state->buf) - state->buf_used); if (n > 0) { state->buf_used += n; } else if (n == 0) { if (fde == state->fde_stdout) { talloc_free(fde); state->fde_stdout = NULL; return; } if (fde == state->fde_stderr) { talloc_free(fde); state->fde_stderr = NULL; return; } return; } while (state->buf_used > 0 && (p = (char *)memchr(state->buf, '\n', state->buf_used)) != NULL) { int n1 = (p - state->buf)+1; int n2 = n1 - 1; /* swallow \r from child processes */ if (n2 > 0 && state->buf[n2-1] == '\r') { n2--; } DEBUG(level,("%s: %*.*s\n", state->arg0, n2, n2, state->buf)); memmove(state->buf, p+1, sizeof(state->buf) - n1); state->buf_used -= n1; } /* the buffer could have completely filled - unfortunately we have no choice but to dump it out straight away */ if (state->buf_used == sizeof(state->buf)) { DEBUG(level,("%s: %*.*s\n", state->arg0, state->buf_used, state->buf_used, state->buf)); state->buf_used = 0; } }
/* run a command as a child process, with a timeout. any stdout/stderr from the child will appear in the Samba logs with the specified log levels */ struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct timeval endtime, int stdout_log_level, int stderr_log_level, const char * const *argv0, ...) { struct tevent_req *req; struct samba_runcmd_state *state; int p1[2], p2[2], p3[2]; char **argv; va_list ap; if (argv0 == NULL) { return NULL; } req = tevent_req_create(mem_ctx, &state, struct samba_runcmd_state); if (req == NULL) { return NULL; } state->stdout_log_level = stdout_log_level; state->stderr_log_level = stderr_log_level; state->fd_stdin = -1; state->arg0 = talloc_strdup(state, argv0[0]); if (tevent_req_nomem(state->arg0, req)) { return tevent_req_post(req, ev); } if (pipe(p1) != 0) { tevent_req_error(req, errno); return tevent_req_post(req, ev); } if (pipe(p2) != 0) { close(p1[0]); close(p1[1]); tevent_req_error(req, errno); return tevent_req_post(req, ev); } if (pipe(p3) != 0) { close(p1[0]); close(p1[1]); close(p2[0]); close(p2[1]); tevent_req_error(req, errno); return tevent_req_post(req, ev); } state->tfork = tfork_create(); if (state->tfork == NULL) { close(p1[0]); close(p1[1]); close(p2[0]); close(p2[1]); close(p3[0]); close(p3[1]); tevent_req_error(req, errno); return tevent_req_post(req, ev); } state->pid = tfork_child_pid(state->tfork); if (state->pid != 0) { /* the parent */ close(p1[1]); close(p2[1]); close(p3[0]); state->fd_stdout = p1[0]; state->fd_stderr = p2[0]; state->fd_stdin = p3[1]; state->fd_status = tfork_event_fd(state->tfork); set_blocking(state->fd_stdout, false); set_blocking(state->fd_stderr, false); set_blocking(state->fd_stdin, false); set_blocking(state->fd_status, false); smb_set_close_on_exec(state->fd_stdin); smb_set_close_on_exec(state->fd_stdout); smb_set_close_on_exec(state->fd_stderr); smb_set_close_on_exec(state->fd_status); tevent_req_set_cleanup_fn(req, samba_runcmd_cleanup_fn); state->fde_stdout = tevent_add_fd(ev, state, state->fd_stdout, TEVENT_FD_READ, samba_runcmd_io_handler, req); if (tevent_req_nomem(state->fde_stdout, req)) { close(state->fd_stdout); close(state->fd_stderr); close(state->fd_status); return tevent_req_post(req, ev); } tevent_fd_set_auto_close(state->fde_stdout); state->fde_stderr = tevent_add_fd(ev, state, state->fd_stderr, TEVENT_FD_READ, samba_runcmd_io_handler, req); if (tevent_req_nomem(state->fde_stdout, req)) { close(state->fd_stdout); close(state->fd_stderr); close(state->fd_status); return tevent_req_post(req, ev); } tevent_fd_set_auto_close(state->fde_stderr); state->fde_status = tevent_add_fd(ev, state, state->fd_status, TEVENT_FD_READ, samba_runcmd_io_handler, req); if (tevent_req_nomem(state->fde_stdout, req)) { close(state->fd_stdout); close(state->fd_stderr); close(state->fd_status); return tevent_req_post(req, ev); } tevent_fd_set_auto_close(state->fde_status); if (!timeval_is_zero(&endtime)) { tevent_req_set_endtime(req, ev, endtime); } return req; } /* the child */ close(p1[0]); close(p2[0]); close(p3[1]); close(0); close(1); close(2); /* we want to ensure that all of the network sockets we had open are closed */ tevent_re_initialise(ev); /* setup for logging to go to the parents debug log */ dup2(p3[0], 0); dup2(p1[1], 1); dup2(p2[1], 2); close(p1[1]); close(p2[1]); close(p3[0]); argv = str_list_copy(state, discard_const_p(const char *, argv0)); if (!argv) { fprintf(stderr, "Out of memory in child\n"); _exit(255); } va_start(ap, argv0); while (1) { const char **l; char *arg = va_arg(ap, char *); if (arg == NULL) break; l = discard_const_p(const char *, argv); l = str_list_add(l, arg); if (l == NULL) { fprintf(stderr, "Out of memory in child\n"); _exit(255); } argv = discard_const_p(char *, l); } va_end(ap); (void)execvp(state->arg0, argv); fprintf(stderr, "Failed to exec child - %s\n", strerror(errno)); _exit(255); return NULL; }
/* handle stdout/stderr from the child */ static void samba_runcmd_io_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *private_data) { struct tevent_req *req = talloc_get_type_abort(private_data, struct tevent_req); struct samba_runcmd_state *state = tevent_req_data(req, struct samba_runcmd_state); int level; char *p; int n, fd; if (fde == state->fde_stdout) { level = state->stdout_log_level; fd = state->fd_stdout; } else if (fde == state->fde_stderr) { level = state->stderr_log_level; fd = state->fd_stderr; } else { return; } if (!(flags & TEVENT_FD_READ)) { return; } n = read(fd, &state->buf[state->buf_used], sizeof(state->buf) - state->buf_used); if (n > 0) { state->buf_used += n; } else if (n == 0) { if (fde == state->fde_stdout) { talloc_free(fde); state->fde_stdout = NULL; } if (fde == state->fde_stderr) { talloc_free(fde); state->fde_stderr = NULL; } if (state->fde_stdout == NULL && state->fde_stderr == NULL) { int status; /* the child has closed both stdout and * stderr, assume its dead */ pid_t pid = waitpid(state->pid, &status, 0); if (pid != state->pid) { if (errno == ECHILD) { /* this happens when the parent has set SIGCHLD to SIG_IGN. In that case we can only get error information for the child via its logging. We should stop using SIG_IGN on SIGCHLD in the standard process model. */ DEBUG(0, ("Error in waitpid() unexpectedly got ECHILD " "for %s child %d - %s, " "someone has set SIGCHLD to SIG_IGN!\n", state->arg0, (int)state->pid, strerror(errno))); tevent_req_error(req, errno); return; } DEBUG(0,("Error in waitpid() for child %s - %s \n", state->arg0, strerror(errno))); if (errno == 0) { errno = ECHILD; } tevent_req_error(req, errno); return; } status = WEXITSTATUS(status); DEBUG(3,("Child %s exited with status %d - %s\n", state->arg0, status, strerror(status))); if (status != 0) { tevent_req_error(req, status); return; } tevent_req_done(req); return; } return; } while (state->buf_used > 0 && (p = (char *)memchr(state->buf, '\n', state->buf_used)) != NULL) { int n1 = (p - state->buf)+1; int n2 = n1 - 1; /* swallow \r from child processes */ if (n2 > 0 && state->buf[n2-1] == '\r') { n2--; } DEBUG(level,("%s: %*.*s\n", state->arg0, n2, n2, state->buf)); memmove(state->buf, p+1, sizeof(state->buf) - n1); state->buf_used -= n1; } /* the buffer could have completely filled - unfortunately we have no choice but to dump it out straight away */ if (state->buf_used == sizeof(state->buf)) { DEBUG(level,("%s: %*.*s\n", state->arg0, state->buf_used, state->buf_used, state->buf)); state->buf_used = 0; } }
/* issue full refresh of sudo rules */ static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; struct sdap_sudo_full_refresh_state *state = NULL; char *ldap_filter = NULL; char *ldap_full_filter = NULL; char *sysdb_filter = NULL; int ret; req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_full_refresh_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); return NULL; } sudo_ctx->full_refresh_in_progress = true; state->sudo_ctx = sudo_ctx; state->id_ctx = id_ctx; state->sysdb = id_ctx->be->domain->sysdb; state->domain = id_ctx->be->domain; /* Download all rules from LDAP */ ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS, id_ctx->opts->sudorule_map[SDAP_OC_SUDORULE].name); if (ldap_filter == NULL) { ret = ENOMEM; goto immediately; } ldap_full_filter = sdap_sudo_get_filter(state, id_ctx->opts->sudorule_map, sudo_ctx, ldap_filter); if (ldap_full_filter == NULL) { ret = ENOMEM; goto immediately; } /* Remove all rules from cache */ sysdb_filter = talloc_asprintf(state, "(%s=%s)", SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC); if (sysdb_filter == NULL) { ret = ENOMEM; goto immediately; } DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n"); subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts, id_ctx->conn->conn_cache, ldap_full_filter, sysdb_filter); if (subreq == NULL) { ret = ENOMEM; goto immediately; } tevent_req_set_callback(subreq, sdap_sudo_full_refresh_done, req); /* free filters */ talloc_free(ldap_filter); talloc_free(ldap_full_filter); talloc_free(sysdb_filter); return req; immediately: if (ret == EOK) { tevent_req_done(req); } else { tevent_req_error(req, ret); } tevent_req_post(req, id_ctx->be->ev); return req; }
struct tevent_req *tsocket_writev_send(struct tsocket_context *sock, TALLOC_CTX *mem_ctx, const struct iovec *vector, size_t count) { struct tevent_req *req; struct tsocket_writev_state *state; int ret; int err; bool dummy; int to_write = 0; size_t i; req = tevent_req_create(mem_ctx, &state, struct tsocket_writev_state); if (!req) { return NULL; } state->caller.sock = sock; state->caller.vector = vector; state->caller.count = count; state->iov = NULL; state->count = count; state->total_written = 0; state->iov = talloc_array(state, struct iovec, count); if (tevent_req_nomem(state->iov, req)) { goto post; } memcpy(state->iov, vector, sizeof(struct iovec) * count); for (i=0; i < count; i++) { int tmp = to_write; tmp += state->iov[i].iov_len; if (tmp < to_write) { tevent_req_error(req, EMSGSIZE); goto post; } to_write = tmp; } if (to_write == 0) { tevent_req_done(req); goto post; } /* * this is a fast path, not waiting for the * socket to become explicit writeable gains * about 10%-20% performance in benchmark tests. */ tsocket_writev_handler(sock, req); if (!tevent_req_is_in_progress(req)) { goto post; } talloc_set_destructor(state, tsocket_writev_state_destructor); ret = tsocket_set_writeable_handler(sock, tsocket_writev_handler, req); err = tsocket_error_from_errno(ret, errno, &dummy); if (tevent_req_error(req, err)) { goto post; } return req; post: return tevent_req_post(req, sock->event.ctx); }
/* issue refresh of specific sudo rules */ static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx, struct be_ctx *be_ctx, struct sdap_options *opts, struct sdap_id_conn_cache *conn_cache, char **rules) { struct tevent_req *req = NULL; struct tevent_req *subreq = NULL; struct sdap_sudo_rules_refresh_state *state = NULL; TALLOC_CTX *tmp_ctx = NULL; char *ldap_filter = NULL; char *ldap_full_filter = NULL; char *sysdb_filter = NULL; char *safe_rule = NULL; int ret; int i; if (rules == NULL) { return NULL; } tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); return NULL; } req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); return NULL; } ldap_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */ sysdb_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */ /* Download only selected rules from LDAP */ /* Remove all selected rules from cache */ for (i = 0; rules[i] != NULL; i++) { ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule); if (ret != EOK) { ret = ENOMEM; goto immediately; } ldap_filter = talloc_asprintf_append_buffer(ldap_filter, "(%s=%s)", opts->sudorule_map[SDAP_AT_SUDO_NAME].name, safe_rule); if (ldap_filter == NULL) { ret = ENOMEM; goto immediately; } sysdb_filter = talloc_asprintf_append_buffer(sysdb_filter, "(%s=%s)", SYSDB_SUDO_CACHE_AT_CN, safe_rule); if (sysdb_filter == NULL) { ret = ENOMEM; goto immediately; } } state->id_ctx = sudo_ctx->id_ctx; state->num_rules = i; ldap_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))", opts->sudorule_map[SDAP_OC_SUDORULE].name, ldap_filter); if (ldap_filter == NULL) { ret = ENOMEM; goto immediately; } ldap_full_filter = sdap_sudo_get_filter(tmp_ctx, opts->sudorule_map, sudo_ctx, ldap_filter); if (ldap_full_filter == NULL) { ret = ENOMEM; goto immediately; } sysdb_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))", SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC, sysdb_filter); if (sysdb_filter == NULL) { ret = ENOMEM; goto immediately; } subreq = sdap_sudo_refresh_send(req, be_ctx, opts, conn_cache, ldap_full_filter, sysdb_filter); if (subreq == NULL) { ret = ENOMEM; goto immediately; } tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req); ret = EOK; immediately: talloc_free(tmp_ctx); if (ret != EOK) { tevent_req_error(req, ret); tevent_req_post(req, be_ctx->ev); } return req; }
bool tevent_req_nterror(struct tevent_req *req, NTSTATUS status) { return tevent_req_error(req, NT_STATUS_V(status)); }