URL: https://github.com/SSSD/sssd/pull/32 Author: fidencio Title: #32: Requesting a pull to SSSD:master from fidencio:wip/#3138 Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/32/head:pr32 git checkout pr32
From f5b484056e3e07bc61390fd0ac9112143e9c1086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Thu, 22 Sep 2016 18:02:30 +0200 Subject: [PATCH 1/4] SPEC: Don't restart sssd-secrets service on %postun MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As sssd-secrets is a socket-activated service, just restarting the sssd-secrets.socket is enough. The service will be re-started on demand when needed. Related: https://fedorahosted.org/sssd/ticket/3138 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- contrib/sssd.spec.in | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index a0937d5..4f7cd48 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -1140,7 +1140,6 @@ getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "Us %postun common %systemd_postun_with_restart sssd.service %systemd_postun_with_restart sssd-secrets.socket -%systemd_postun_with_restart sssd-secrets.service %else # sysv From 5bc66d1248632f034b12590b0f3dc85f6239d7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Fri, 16 Sep 2016 17:32:12 +0200 Subject: [PATCH 2/4] UPDATE_CONFDB: Add a new service to refresh configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently confdb is only refreshed when sssd starts. It may cause issues with socket-activated services (like sssd-secrets) that may end up reading a not up-to-date configuration from confdb. This socket-activated service does a very simple task: writes the configuration to confdb and exists. The way it's implemented now is: - receives a single byte from the service that wants to have the configuration file updated; - writes the configuration to confdb; - sends a single byte back to the service; - exits; For now it's being placed where it is simply for a lack of a better place. And it's being built only when sssd-secrets is built because, at least for now, sssd-secrets will be the only responder using it. Tests for this new service are needed as well, but are not implemented yet (they will be part of a later on series). Last note is that it *must* be executed as root in order to read sssd.conf and write the confdb file. Related: https://fedorahosted.org/sssd/ticket/3138 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- Makefile.am | 27 +++ contrib/sssd.spec.in | 6 + src/confdb/confdb.h | 2 + src/responder/update_confdb/update_confdb.c | 307 +++++++++++++++++++++++++ src/sysv/systemd/sssd-update-confdb.service.in | 8 + src/sysv/systemd/sssd-update-confdb.socket.in | 8 + 6 files changed, 358 insertions(+) create mode 100644 src/responder/update_confdb/update_confdb.c create mode 100644 src/sysv/systemd/sssd-update-confdb.service.in create mode 100644 src/sysv/systemd/sssd-update-confdb.socket.in diff --git a/Makefile.am b/Makefile.am index 4385268..b001c6c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -175,6 +175,7 @@ endif endif if BUILD_SECRETS sssdlibexec_PROGRAMS += sssd_secrets +sssdlibexec_PROGRAMS += sssd_update_confdb endif if BUILD_PAC_RESPONDER @@ -474,6 +475,7 @@ AM_CPPFLAGS = \ -DSSS_PAC_SOCKET_NAME=\"$(pipepath)/pac\" \ -DSSS_PAM_PRIV_SOCKET_NAME=\"$(pipepath)/private/pam\" \ -DSSS_SEC_SOCKET_NAME=\"$(runstatedir)/secrets.socket\" \ + -DSSS_UPDATE_CONFDB_SOCKET_NAME=\"$(runstatedir)/update-confdb.socket\" \ -DSSS_SUDO_SOCKET_NAME=\"$(pipepath)/sudo\" \ -DSSS_AUTOFS_SOCKET_NAME=\"$(pipepath)/autofs\" \ -DSSS_SSH_SOCKET_NAME=\"$(pipepath)/ssh\" \ @@ -1392,6 +1394,17 @@ sssd_secrets_LDADD = \ $(CARES_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ $(NULL) + +sssd_update_confdb_SOURCES = \ + src/responder/update_confdb/update_confdb.c \ + $(SSSD_RESPONDER_OBJ) \ + $(SSSD_TOOLS_OBJ) \ + $(NULL) +sssd_update_confdb_LDADD = \ + $(SSSD_LIBS) \ + $(SYSTEMD_DAEMON_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + $(NULL) endif sssd_be_SOURCES = \ @@ -3896,6 +3909,8 @@ if HAVE_SYSTEMD_UNIT src/sysv/systemd/sssd.service \ src/sysv/systemd/sssd-secrets.socket \ src/sysv/systemd/sssd-secrets.service \ + src/sysv/systemd/sssd-update-confdb.socket \ + src/sysv/systemd/sssd-update-confdb.service \ $(NULL) if WITH_JOURNALD systemdconf_DATA += \ @@ -3949,6 +3964,8 @@ EXTRA_DIST += \ src/sysv/systemd/journal.conf.in \ src/sysv/systemd/sssd-secrets.socket.in \ src/sysv/systemd/sssd-secrets.service.in \ + src/sysv/systemd/sssd-update-confdb.socket.in \ + src/sysv/systemd/sssd-update-confdb.service.in \ $(NULL) src/sysv/systemd/sssd.service: src/sysv/systemd/sssd.service.in Makefile @@ -3967,6 +3984,14 @@ src/sysv/systemd/sssd-secrets.service: src/sysv/systemd/sssd-secrets.service.in @$(MKDIR_P) src/sysv/systemd/ $(replace_script) +src/sysv/systemd/sssd-update-confdb.socket: src/sysv/systemd/sssd-update-confdb.socket.in Makefile + @$(MKDIR_P) src/sysv/systemd/ + $(replace_script) + +src/sysv/systemd/sssd-update-confdb.service: src/sysv/systemd/sssd-update-confdb.service.in Makefile + @$(MKDIR_P) src/sysv/systemd/ + $(replace_script) + SSSD_USER_DIRS = \ $(DESTDIR)$(dbpath) \ $(DESTDIR)$(keytabdir) \ @@ -4184,6 +4209,8 @@ endif rm -f $(builddir)/src/sysv/systemd/sssd.service rm -f $(builddir)/src/sysv/systemd/sssd-secrets.socket rm -f $(builddir)/src/sysv/systemd/sssd-secrets.service + rm -f $(builddir)/src/sysv/systemd/sssd-update-confdb.socket + rm -f $(builddir)/src/sysv/systemd/sssd-update-confdb.service rm -f $(builddir)/src/sysv/systemd/journal.conf CLEANFILES += *.X */*.X */*/*.X diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index 4f7cd48..78088f2 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -799,6 +799,8 @@ done %{_unitdir}/sssd.service %{_unitdir}/sssd-secrets.socket %{_unitdir}/sssd-secrets.service +%{_unitdir}/sssd-update-confdb.socket +%{_unitdir}/sssd-update-confdb.service %else %{_initrddir}/%{name} %endif @@ -811,6 +813,7 @@ done %{_libexecdir}/%{servicename}/sssd_secrets %{_libexecdir}/%{servicename}/sssd_ssh %{_libexecdir}/%{servicename}/sssd_sudo +%{_libexecdir}/%{servicename}/sssd_update_confdb %{_libexecdir}/%{servicename}/p11_child %dir %{_libdir}/%{name} @@ -1131,14 +1134,17 @@ getent passwd sssd >/dev/null || useradd -r -g sssd -d / -s /sbin/nologin -c "Us # systemd %post common %systemd_post sssd.service +%systemd_post sssd-update-confdb.socket %systemd_post sssd-secrets.socket %preun common %systemd_preun sssd.service +%systemd_preun sssd-update-confdb.socket %systemd_preun sssd-secrets.socket %postun common %systemd_postun_with_restart sssd.service +%systemd_postun_with_restart sssd-update-confdb.socket %systemd_postun_with_restart sssd-secrets.socket %else diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 36a2f21..3f2b9d6 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -224,6 +224,8 @@ /* Secrets Service */ #define CONFDB_SEC_CONF_ENTRY "config/secrets" +/* Update confdb Service */ +#define CONFDB_UPDATE_CONF_ENTRY "config/updateconfdb" struct confdb_ctx; struct config_file_ctx; diff --git a/src/responder/update_confdb/update_confdb.c b/src/responder/update_confdb/update_confdb.c new file mode 100644 index 0000000..f6617c0 --- /dev/null +++ b/src/responder/update_confdb/update_confdb.c @@ -0,0 +1,307 @@ +/* + Authors: + Fabiano Fidêncio <fiden...@redhat.com> + + Copyright (C) 2016 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 <popt.h> + +#include "util/util.h" +#include "confdb/confdb_setup.h" +#include "responder/common/responder.h" + + +/* Dummy, not used here but required to link to other responder files */ +struct cli_protocol_version *register_cli_protocol_version(void) +{ + return NULL; +} + +static errno_t update_confdb_update(struct cli_ctx *cctx) +{ + TALLOC_CTX *tmp_ctx; + struct confdb_ctx *confdb; + char *path; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + path = talloc_asprintf(tmp_ctx, "%s/%s", DB_PATH, CONFDB_FILE); + if (path == NULL) { + return ENOMEM; + } + + ret = confdb_setup(tmp_ctx, path, SSSD_CONFIG_FILE, CONFDB_DEFAULT_CONFIG_DIR, &confdb); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to setup ConfDB [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = EOK; + + TEVENT_FD_WRITEABLE(cctx->cfde); + +done: + talloc_free(tmp_ctx); + return ret; +} + +static int update_confdb_send_data(int fd) +{ + char data = '1'; + ssize_t len; + + errno = 0; + len = send(fd, &data, 1, 0); + if (len == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + return EAGAIN; + } else { + return errno; + } + } + + if (len == 0) { + return EIO; + } + + return EOK; +} + +static void update_confdb_send(struct cli_ctx *cctx) +{ + int ret; + + ret = update_confdb_send_data(cctx->cfd); + if (ret == EAGAIN) { + /* not all data was sent, loop again */ + return; + } + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n"); + talloc_free(cctx); + + return; + } + + /* ok all sent */ + TEVENT_FD_NOT_WRITEABLE(cctx->cfde); + TEVENT_FD_READABLE(cctx->cfde); + + exit(0); +} + +static int update_confdb_recv_data(int fd) +{ + char data; + ssize_t len; + + errno = 0; + len = recv(fd, &data, 1, 0); + if (len == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + return EAGAIN; + } else { + return errno; + } + } + + if (len == 0) { + return ENODATA; + } + + return EOK; +} + +static void update_confdb_recv(struct cli_ctx *cctx) +{ + int ret; + + ret = update_confdb_recv_data(cctx->cfd); + switch(ret) { + case ENODATA: + DEBUG(SSSDBG_TRACE_ALL, + "Client closed connection\n"); + talloc_free(cctx); + return; + case EAGAIN: + DEBUG(SSSDBG_TRACE_ALL, + "Interrupted before any data could be read, retry later\n"); + return; + case EOK: + /* all fine */ + break; + default: + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to receive data (%d, %s), aborting client!\n", + ret, strerror(ret)); + talloc_free(cctx); + return; + } + + TEVENT_FD_NOT_READABLE(cctx->cfde); + update_confdb_update(cctx); + + return; +} + +static void update_confdb_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *ptr) +{ + errno_t ret; + struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx); + + /* Always reset the idle timer on any activity */ + ret = reset_idle_timer(cctx); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not create idle timer for client. " + "This connection may not auto-terminate\n"); + /* Non-fatal, continue */ + } + + if (flags & TEVENT_FD_READ) { + update_confdb_recv(cctx); + return; + } + + if (flags & TEVENT_FD_WRITE) { + update_confdb_send(cctx); + return; + } +} + +static int update_confdb_connection_setup(struct cli_ctx *cctx) +{ + cctx->cfd_handler = update_confdb_fd_handler; + + return EOK; +} + +static int update_confdb_ctx_destructor(void *ptr) +{ + struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx); + + /* mark that we are shutting down the service, so it is propagated + * into underlying contexts that are freed right before rctx */ + DEBUG(SSSDBG_TRACE_FUNC, "Service is being shutdown\n"); + rctx->shutting_down = true; + + return 0; +} + +static int update_confdb_process_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb) +{ + struct resp_ctx *rctx; + int ret; + + rctx = talloc_zero(mem_ctx, struct resp_ctx); + if (rctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing resp_ctx\n"); + + return ENOMEM; + } + + rctx->ev = ev; + rctx->cdb = cdb; + rctx->sock_name = SSS_UPDATE_CONFDB_SOCKET_NAME; + rctx->shutting_down = false; + rctx->client_idle_timeout = CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT; + + talloc_set_destructor((TALLOC_CTX *)rctx, update_confdb_ctx_destructor); + + ret = activate_unix_sockets(rctx, update_confdb_connection_setup); + if (ret != EOK) { + goto fail; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Update ConfDB socket activation complete\n"); + + return EOK; + +fail: + talloc_free(rctx); + return ret; +} + +int main (int argc, const char *argv[]) +{ + int opt; + poptContext pc; + struct main_context *main_ctx; + int ret; + + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_MAIN_OPTS + POPT_TABLEEND + }; + + /* Set debug level to invalid value so we can decide if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + + poptFreeContext(pc); + + DEBUG_INIT(debug_level); + + /* set up things like debug, signals, daemonizations, etc ... */ + debug_log_file = "sssd_update_confdb"; + + ret = server_setup("update_confdb", 0, 0, 0, + CONFDB_UPDATE_CONF_ENTRY, &main_ctx); + if (ret != EOK) { + return 2; + } + + ret = die_if_parent_died(); + if (ret != EOK) { + /* This is not fatal, don't return. */ + DEBUG(SSSDBG_OP_FAILURE, + "Could not set up to exit when parent process does\n"); + } + + ret = update_confdb_process_init(main_ctx, + main_ctx->event_ctx, + main_ctx->confdb_ctx); + if (ret != EOK) { + return 3; + } + + /* loop on main */ + server_loop(main_ctx); + + return 0; +} diff --git a/src/sysv/systemd/sssd-update-confdb.service.in b/src/sysv/systemd/sssd-update-confdb.service.in new file mode 100644 index 0000000..7ae0852 --- /dev/null +++ b/src/sysv/systemd/sssd-update-confdb.service.in @@ -0,0 +1,8 @@ +[Unit] +Description=SSSD Update ConfDB Service + +[Install] +Also=sssd-update-confdb.socket + +[Service] +ExecStart=@libexecdir@/sssd/sssd_update_confdb --debug-to-files diff --git a/src/sysv/systemd/sssd-update-confdb.socket.in b/src/sysv/systemd/sssd-update-confdb.socket.in new file mode 100644 index 0000000..7802e1d --- /dev/null +++ b/src/sysv/systemd/sssd-update-confdb.socket.in @@ -0,0 +1,8 @@ +[Unit] +Description=SSSD Update ConfDB socket + +[Socket] +ListenStream=@localstatedir@/run/update-confdb.socket + +[Install] +WantedBy=sockets.target From 0155a978c6a7dc4092ccedec66d8ad1788016748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Mon, 19 Sep 2016 12:03:46 +0200 Subject: [PATCH 3/4] UTIL: Make set_fd_common_opts() friendly to Unix sockets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TCP_NODELAY is not supported when dealing with AF_UNIX family. Related: https://fedorahosted.org/sssd/ticket/#3138 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/util/sss_sockets.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/util/sss_sockets.c b/src/util/sss_sockets.c index 5e9be9e..1daebbf 100644 --- a/src/util/sss_sockets.c +++ b/src/util/sss_sockets.c @@ -74,7 +74,7 @@ static errno_t set_fcntl_flags(int fd, int fd_flags, int fl_flags) return EOK; } -static errno_t set_fd_common_opts(int fd) +static errno_t set_fd_common_opts(int fd, sa_family_t sa_family) { int dummy = 1; int ret; @@ -89,12 +89,14 @@ static errno_t set_fd_common_opts(int fd) strerror(ret)); } - ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy)); - if (ret != 0) { - ret = errno; - DEBUG(SSSDBG_FUNC_DATA, - "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret, + if (sa_family != AF_UNIX) { + ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy)); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_FUNC_DATA, + "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret, strerror(ret)); + } } return EOK; @@ -264,7 +266,7 @@ struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx, goto fail; } - ret = set_fd_common_opts(state->sd); + ret = set_fd_common_opts(state->sd, addr->ss_family); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_common_opts failed.\n"); goto fail; From 9c3a2800890ef697a58d9a78e4b22dee290459c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fiden...@redhat.com> Date: Mon, 19 Sep 2016 20:01:36 +0200 Subject: [PATCH 4/4] SECRETS: Update confdb when starting the process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to get up-to-date configurations let's update the confdb file when initializing secrets service. It's done by socket-activating sssd-update-confdb process, which is implemented now as: - sends a single byte to the sssd-update-confdb socket, which will trigger the service - waits till one byte comes back - initialize secrets service as it was done before Related: https://fedorahosted.org/sssd/ticket/3138 Signed-off-by: Fabiano Fidêncio <fiden...@redhat.com> --- src/responder/secrets/secsrv.c | 282 ++++++++++++++++++++++++++++++++++++++++- src/tests/intg/test_secrets.py | 30 ++++- 2 files changed, 303 insertions(+), 9 deletions(-) diff --git a/src/responder/secrets/secsrv.c b/src/responder/secrets/secsrv.c index eb194a1..9ddb1d9 100644 --- a/src/responder/secrets/secsrv.c +++ b/src/responder/secrets/secsrv.c @@ -28,8 +28,19 @@ #include "responder/secrets/secsrv.h" #include "resolv/async_resolv.h" +#include "util/sss_sockets.h" + #define DEFAULT_SEC_FD_LIMIT 2048 +struct sec_update_confdb_state { + struct TALLOC_CTX *mem_ctx; + struct tevent_context *ev; + struct confdb_ctx *cdb; + + int sd; + struct tevent_fd *fde; +}; + static int sec_get_config(struct sec_ctx *sctx) { int ret; @@ -137,6 +148,271 @@ static int sec_process_init(TALLOC_CTX *mem_ctx, return ret; } +static int sec_update_confdb_state_destructor(void *data) +{ + struct sec_update_confdb_state *state; + + state = talloc_get_type(data, struct sec_update_confdb_state); + + if (!state) return 0 ; + + if (state->sd != -1) { + DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd); + close(state->sd); + state->sd = -1; + } + + state->mem_ctx = NULL; + state->ev = NULL; + state->cdb = NULL; + + return 0; +} + +static int sec_update_confdb_fd_send_data(int fd) +{ + char data = '1'; + ssize_t len; + + errno = 0; + len = send(fd, &data, 1, 0); + if (len == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + return EAGAIN; + } else { + return errno; + } + } + + if (len == 0) { + return EIO; + } + + return EOK; +} + +static void sec_update_confdb_fd_send(void *data) +{ + struct tevent_req *req; + struct sec_update_confdb_state *state; + int ret; + + req = talloc_get_type(data, struct tevent_req); + state = tevent_req_data(req, struct sec_update_confdb_state); + + ret = sec_update_confdb_fd_send_data(state->sd); + if (ret == EAGAIN) { + /* not all data was sent, loop again */ + return; + } + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n"); + + tevent_req_error(req, ret); + return; + } + + /* ok all sent */ + TEVENT_FD_NOT_WRITEABLE(state->fde); + TEVENT_FD_READABLE(state->fde); +} + +static int sec_update_confdb_fd_recv_data(int fd) +{ + char data; + ssize_t len; + + errno = 0; + len = recv(fd, &data, 1, 0); + if (len == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + return EAGAIN; + } else { + return errno; + } + } + + if (len == 0) { + return ENODATA; + } + + return EOK; +} + +static void sec_update_confdb_fd_recv(void *data) +{ + struct tevent_req *req; + struct sec_update_confdb_state *state; + int ret; + + req = talloc_get_type(data, struct tevent_req); + state = tevent_req_data(req, struct sec_update_confdb_state); + + ret = sec_update_confdb_fd_recv_data(state->sd); + + switch(ret) { + case ENODATA: + DEBUG(SSSDBG_TRACE_ALL, + "Client closed connection\n"); + tevent_req_error(req, EIO); + return; + case EAGAIN: + DEBUG(SSSDBG_TRACE_ALL, + "Interrupted before any data could be read, retry later\n"); + return; + case EOK: + /* all fine */ + break; + default: + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to receive data (%d, %s), aborting client\n", + ret, strerror(ret)); + tevent_req_error(req, ret); + return; + } + + + TEVENT_FD_NOT_READABLE(state->fde); + + ret = sec_process_init(state->mem_ctx, state->ev, state->cdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sec_process_init failed: [%d]: %s.\n", + ret, strerror(ret)); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +static void sec_update_confdb_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *data) +{ + if (flags & TEVENT_FD_READ) { + sec_update_confdb_fd_recv(data); + return; + } + + if (flags & TEVENT_FD_WRITE) { + sec_update_confdb_fd_send(data); + return; + } +} + +static void sec_update_confdb_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sec_update_confdb_state *state; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sec_update_confdb_state); + + 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, strerror(ret)); + + tevent_req_error(req, ret); + return; + } + + /* EOK */ + + state->fde = tevent_add_fd(state->ev, state, state->sd, + TEVENT_FD_WRITE, + sec_update_confdb_fd_handler, req); + if (!state->fde) { + tevent_req_error(req, EIO); + return; + } + + tevent_req_done(req); +} + +static struct tevent_req * +sec_update_confdb_connect(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb, + struct sockaddr_storage *addr, + int addr_len, int timeout) +{ + struct tevent_req *req, *subreq; + struct sec_update_confdb_state *state; + + req = tevent_req_create(mem_ctx, &state, struct sec_update_confdb_state); + if (!req) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n"); + return NULL; + } + + talloc_set_destructor((TALLOC_CTX *)state, sec_update_confdb_state_destructor); + + state->mem_ctx = mem_ctx; + state->ev = ev; + state->cdb = cdb; + state->sd = -1; + + subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout); + if (!subreq) { + DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n"); + + tevent_req_error(req, ENOMEM); + tevent_req_post(req, ev); + + goto end; + } + + tevent_req_set_callback(subreq, sec_update_confdb_connect_done, req); + +end: + return req; +} + +static int sec_update_confdb(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb) +{ + struct tevent_req *req; + struct sockaddr_storage *sockaddr; + + sockaddr = talloc_zero(mem_ctx, struct sockaddr_storage); + if (sockaddr == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); + return ENOMEM; + } + + /* Updating confdb will be done in a few steps: + * + * 1) Connect to the update-confdb.socket + * 2) Send a single byte to update-confdb.socket, + * which will actually trigger the update. + * 3) Receive a single byte as a confirmation that + * the update happened without issues + * 4) Finish the initialization using the up-to-date + * values from the confdb. + */ + + ((struct sockaddr_un *)sockaddr)->sun_family = AF_UNIX; + memcpy(&((struct sockaddr_un *) sockaddr)->sun_path, + SSS_UPDATE_CONFDB_SOCKET_NAME, + strlen(SSS_UPDATE_CONFDB_SOCKET_NAME)); + + req = sec_update_confdb_connect(mem_ctx, ev, cdb, sockaddr, + SUN_LEN((struct sockaddr_un *) sockaddr), + CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT); + + if (!req) return ENOMEM; + + return EOK; +} + int main(int argc, const char *argv[]) { int opt; @@ -187,9 +463,9 @@ int main(int argc, const char *argv[]) "Could not set up to exit when parent process does\n"); } - ret = sec_process_init(main_ctx, - main_ctx->event_ctx, - main_ctx->confdb_ctx); + ret = sec_update_confdb(main_ctx, + main_ctx->event_ctx, + main_ctx->confdb_ctx); if (ret != EOK) return 3; /* loop on main */ diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py index e394d12..ba32185 100644 --- a/src/tests/intg/test_secrets.py +++ b/src/tests/intg/test_secrets.py @@ -40,11 +40,27 @@ def create_conf_fixture(request, contents): def create_sssd_secrets_fixture(request): - if subprocess.call(['sssd', "--genconf"]) != 0: - raise Exception("failed to regenerate confdb") + # Starting the process manually and waiting till the socket is + # created is something that has to be done as we cannot rely on + # systemd's socket-activation for the integration tests. + update_confdb_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_update_confdb") + update_confdb_pid = os.fork() + if update_confdb_pid == 0: + if subprocess.call(update_confdb_path) != 0: + raise Exception("sssd_secrets failed to start") - resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_secrets") + sock_path = os.path.join(config.RUNSTATEDIR, "update-confdb.socket") + sck = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + for _ in range(1, 10): + try: + sck.connect(udpdate_cdb_path) + except: + time.sleep(0.1) + else: + break + sck.close() + resp_path = os.path.join(config.LIBEXEC_PATH, "sssd", "sssd_secrets") secpid = os.fork() if secpid == 0: if subprocess.call([resp_path, "--uid=0", "--gid=0"]) != 0: @@ -62,10 +78,12 @@ def create_sssd_secrets_fixture(request): sck.close() def sec_teardown(): - if secpid == 0: - return + if secpid != 0: + os.kill(secpid, signal.SIGTERM) + + if update_confdb_pid != 0: + os.kill(update_confdb_pid, signal.SIGTERM) - os.kill(secpid, signal.SIGTERM) for secdb_file in os.listdir(config.SECDB_PATH): os.unlink(config.SECDB_PATH + "/" + secdb_file) request.addfinalizer(sec_teardown)
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org