responder_common.c revision 422217c7ea5fbe94b386c93c19e2c1928151faa0
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher/*
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher SSSD
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher Common Responder methods
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher This program is free software; you can redistribute it and/or modify
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher it under the terms of the GNU General Public License as published by
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher the Free Software Foundation; either version 3 of the License, or
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher (at your option) any later version.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher This program is distributed in the hope that it will be useful,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher but WITHOUT ANY WARRANTY; without even the implied warranty of
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher GNU General Public License for more details.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher You should have received a copy of the GNU General Public License
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher along with this program. If not, see <http://www.gnu.org/licenses/>.
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher*/
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "config.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <stdio.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/types.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/stat.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/socket.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/un.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <string.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <sys/time.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <errno.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <fcntl.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <popt.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <dbus/dbus.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "util/util.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "util/strtonum.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "db/sysdb.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "confdb/confdb.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "sbus/sssd_dbus.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "responder/common/responder.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "responder/common/iface/responder_iface.h"
681742138b2afbbefa7f14de937beb438409208eSimo Sorce#include "responder/common/responder_packet.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "providers/data_provider.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "monitor/monitor_interfaces.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "sbus/sbus_client.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include "util/util_creds.h"
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#ifdef HAVE_SYSTEMD
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#include <systemd/sd-daemon.h>
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#endif
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
fd555d130dc733509347fa096a2cb858b014a196Simo Sorcestatic errno_t set_close_on_exec(int fd)
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce{
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce int v;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce int ferr;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher errno_t error;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Get the current flags for this file descriptor */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher v = fcntl(fd, F_GETFD, 0);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher errno = 0;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Set the close-on-exec flags on this fd */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ferr = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ferr < 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher error = errno;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Unable to set fd close-on-exec: [%d][%s]\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher error, strerror(error));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return error;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
fd555d130dc733509347fa096a2cb858b014a196Simo Sorcestatic void client_close_fn(struct tevent_context *ev,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce struct tevent_fd *fde, int fd,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce void *ptr)
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce{
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce errno_t ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_ctx *ctx = talloc_get_type(ptr, struct cli_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((ctx->cfd > 0) && close(ctx->cfd) < 0) {
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek ret = errno;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "Failed to close fd [%d]: [%s]\n",
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce ctx->cfd, strerror(ret));
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DEBUG(SSSDBG_TRACE_INTERNAL,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "Terminated client [%p][%d]\n",
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce ctx, ctx->cfd);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ctx->cfd = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic errno_t get_client_cred(struct cli_ctx *cctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher SEC_CTX secctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds = talloc_zero(cctx, struct cli_creds);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!cctx->creds) return ENOMEM;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
681742138b2afbbefa7f14de937beb438409208eSimo Sorce#ifdef HAVE_UCRED
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher socklen_t client_cred_len = sizeof(struct ucred);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->ucred.uid = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->ucred.gid = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->ucred.pid = -1;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = getsockopt(cctx->cfd, SOL_SOCKET, SO_PEERCRED, &cctx->creds->ucred,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher &client_cred_len);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce if (ret != EOK) {
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce ret = errno;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "getsock failed [%d][%s].\n", ret, strerror(ret));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (client_cred_len != sizeof(struct ucred)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "getsockopt returned unexpected message size.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ENOMSG;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_ALL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Client creds: euid[%d] egid[%d] pid[%d].\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->ucred.uid, cctx->creds->ucred.gid,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->ucred.pid);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher#endif
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = SELINUX_getpeercon(cctx->cfd, &secctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = errno;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DEBUG(SSSDBG_MINOR_FAILURE,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "The following failure is expected to happen in case SELinux is disabled:\n"
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "SELINUX_getpeercon failed [%d][%s].\n"
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "Please, consider enabling SELinux in your system.\n", ret, strerror(ret));
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce /* This is not fatal, as SELinux may simply be disabled */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->selinux_ctx = SELINUX_context_new(secctx);
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek SELINUX_freecon(secctx);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce return ret;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce}
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
fd555d130dc733509347fa096a2cb858b014a196Simo Sorceuid_t client_euid(struct cli_creds *creds)
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce{
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce if (!creds) return -1;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce return cli_creds_get_uid(creds);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
fd555d130dc733509347fa096a2cb858b014a196Simo Sorceerrno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uid_t *allowed_uids)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher size_t c;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (allowed_uids == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EINVAL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek for (c = 0; c < allowed_uids_count; c++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (uid == allowed_uids[c]) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher return EACCES;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallaghererrno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher bool allow_sss_loop,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher size_t *_uid_count, uid_t **_uids)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher size_t c;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher char **list = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int list_size;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uid_t *uids = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher char *endptr;
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = split_on_separator(mem_ctx, csv_string, ',', true, false,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher &list, &list_size);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek ret, strerror(ret));
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek goto done;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek uids = talloc_array(mem_ctx, uint32_t, list_size);
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek if (uids == NULL) {
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = ENOMEM;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto done;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (allow_sss_loop) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = unsetenv("_SSS_LOOPS");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Failed to unset _SSS_LOOPS, getpwnam "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "might not find sssd users.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher for (c = 0; c < list_size; c++) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher errno = 0;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (*list[c] == '\0') {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Empty list item.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = EINVAL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto done;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uids[c] = strtouint32(list[c], &endptr, 10);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (errno != 0 || *endptr != '\0') {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = errno;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret == ERANGE) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is out of range.\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher list[c]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto done;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = sss_user_by_name_or_uid(list[c], &uids[c], NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is neither a valid "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "UID nor a user name which could be "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "resolved by getpwnam().\n", list[c]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher sss_log(SSS_LOG_WARNING, "List item [%s] is neither a valid "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "UID nor a user name which could be "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "resolved by getpwnam().\n", list[c]);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto done;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher *_uid_count = list_size;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher *_uids = uids;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherdone:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if(setenv("_SSS_LOOPS", "NO", 0) != 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "Failed to set _SSS_LOOPS.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(list);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(uids);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void client_send(struct cli_ctx *cctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_protocol *pctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = sss_packet_send(pctx->creq->out, cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret == EAGAIN) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* not all data was sent, loop again */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* ok all sent */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher TEVENT_FD_READABLE(cctx->cfde);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_zfree(pctx->creq);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic int client_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_protocol *pctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher enum sss_cli_command cmd;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cmd = sss_packet_get_cmd(pctx->creq->in);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return sss_cmd_execute(cctx, cmd, sss_cmds);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void client_recv(struct cli_ctx *cctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_protocol *pctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pctx = talloc_get_type(cctx->protocol_ctx, struct cli_protocol);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!pctx->creq) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pctx->creq = talloc_zero(cctx, struct cli_request);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!pctx->creq) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to alloc request, aborting client!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!pctx->creq->in) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = sss_packet_new(pctx->creq, SSS_PACKET_MAX_RECV_SIZE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher 0, &pctx->creq->in);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to alloc request, aborting client!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = sss_packet_recv(pctx->creq->in, cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher switch (ret) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case EOK:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* do not read anymore */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher TEVENT_FD_NOT_READABLE(cctx->cfde);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* execute command */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = client_cmd_execute(cctx, cctx->rctx->sss_cmds);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to execute request, aborting client!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* past this point cctx can be freed at any time by callbacks
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher * in case of error, do not use it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case EAGAIN:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* need to read still some data, loop again */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case EINVAL:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_FUNC,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Invalid data from client, closing connection!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher case ENODATA:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FUNC_DATA, "Client disconnected!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher break;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher default:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_FUNC, "Failed to read request, aborting client!\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic errno_t schedule_responder_idle_timer(struct resp_ctx *rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void responder_idle_handler(struct tevent_context *ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct tevent_timer *te,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct timeval current_time,
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher void *data)
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher{
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher struct resp_ctx *rctx;
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher time_t now;
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher rctx = talloc_get_type(data, struct resp_ctx);
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher now = time(NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (rctx->last_request_time > now) {
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Time shift detected, re-scheduling the responder timeout\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto end;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((now - rctx->last_request_time) > rctx->idle_timeout) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* This responder is idle. Terminate it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Terminating idle responder [%p]\n", rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher orderly_shutdown(0);
2ca23577d3a25aead24ba759a1f6f67ffc24decfSimo Sorce }
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher "Re-scheduling the idle timeout for the responder [%p]\n", rctx);
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagherend:
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher schedule_responder_idle_timer(rctx);
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher}
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagherstatic errno_t schedule_responder_idle_timer(struct resp_ctx *rctx)
e299638926171e0e92a36122aeff6611cd52418dStephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct timeval tv;
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek tv = tevent_timeval_current_ofs(rctx->idle_timeout / 2, 0);
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek talloc_zfree(rctx->idle);
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek rctx->idle = tevent_add_timer(rctx->ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher tv,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher responder_idle_handler,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (rctx->idle == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to allocate time event: responder [%p] shutdown timeout\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ENOMEM;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Re-scheduling the idle timeout for the responder [%p]\n", rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic errno_t setup_responder_idle_timer(struct resp_ctx *rctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher errno_t ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx->last_request_time = time(NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = schedule_responder_idle_timer(rctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Error scheduling the idle timeout for the responder [%p]: "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "%d [%s]\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx, ret, sss_strerror(ret));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Setting up the idle timeout for the responder [%p]\n", rctx);
681742138b2afbbefa7f14de937beb438409208eSimo Sorce
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void client_fd_handler(struct tevent_context *ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct tevent_fd *fde,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint16_t flags, void *ptr)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher errno_t ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Always reset the idle timer on any activity */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->rctx->last_request_time = time(NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Always reset the idle timer on any activity */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = reset_client_idle_timer(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Could not create idle timer for client. "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "This connection may not auto-terminate\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Non-fatal, continue */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek if (flags & TEVENT_FD_READ) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher client_recv(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (flags & TEVENT_FD_WRITE) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher client_send(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic errno_t setup_client_idle_timer(struct cli_ctx *cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic int cli_ctx_destructor(struct cli_ctx *cctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (cctx->creds == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return 0;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (cctx->creds->selinux_ctx == NULL) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return 0;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher SELINUX_context_free(cctx->creds->selinux_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->creds->selinux_ctx = NULL;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return 0;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstruct accept_fd_ctx {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct resp_ctx *rctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher bool is_private;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher connection_setup_t connection_setup;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher};
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void accept_fd_handler(struct tevent_context *ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct tevent_fd *fde,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher uint16_t flags, void *ptr)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* accept and attach new event handler */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct accept_fd_ctx *accept_ctx =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_get_type(ptr, struct accept_fd_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct resp_ctx *rctx = accept_ctx->rctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_ctx *cctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher socklen_t len;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct stat stat_buf;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int fd = accept_ctx->is_private ? rctx->priv_lfd : rctx->lfd;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher int client_fd;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (accept_ctx->is_private) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = stat(rctx->priv_sock_name, &stat_buf);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "stat on privileged pipe failed: [%d][%s].\n", errno,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher strerror(errno));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "privileged pipe has an illegal status.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* TODO: what is the best response to this condition? Terminate? */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx = talloc_zero(rctx, struct cli_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!cctx) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct sockaddr_un addr;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Out of memory trying to setup client context%s!\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher accept_ctx->is_private ? " on privileged pipe": "");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* accept and close to signal the client we have a problem */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher memset(&addr, 0, sizeof(addr));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher len = sizeof(addr);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher client_fd = accept(fd, (struct sockaddr *)&addr, &len);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (client_fd == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher close(client_fd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_set_destructor(cctx, cli_ctx_destructor);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher len = sizeof(cctx->addr);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (cctx->cfd == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "Accept failed [%s]\n", strerror(errno));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->priv = accept_ctx->is_private;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = get_client_cred(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "get_client_cred failed, "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "client cred may not be available.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (rctx->allowed_uids_count != 0) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (client_euid(cctx->creds) == -1) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE, "allowed_uids configured, " \
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "but platform does not support " \
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "reading peer credential from the " \
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "socket. Access denied.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher close(cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
d3d297c62e0340151da1d4ce1e082dcfcb45b431Jakub Hrozek ret = check_allowed_uids(client_euid(cctx->creds), rctx->allowed_uids_count,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher rctx->allowed_uids);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret == EACCES) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Access denied for uid [%"SPRIuid"].\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher client_euid(cctx->creds));
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher } else {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE, "check_allowed_uids failed.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher close(cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
d3d297c62e0340151da1d4ce1e082dcfcb45b431Jakub Hrozek ret = accept_ctx->connection_setup(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher close(cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to setup client handler%s\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher accept_ctx->is_private ? " on privileged pipe" : "");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher TEVENT_FD_READ, cctx->cfd_handler,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!cctx->cfde) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher close(cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_free(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_OP_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Failed to queue client handler%s\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher accept_ctx->is_private ? " on privileged pipe" : "");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher tevent_fd_set_close_fn(cctx->cfde, client_close_fn);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->ev = ev;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->rctx = rctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Record the new time and set up the idle timer */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = reset_client_idle_timer(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_MINOR_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Could not create idle timer for client. "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "This connection may not auto-terminate\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Non-fatal, continue */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = setup_client_idle_timer(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_CRIT_FAILURE,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Could not create idle timer for client. "
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "This connection may not auto-terminate\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Non-fatal, continue */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_FUNC,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Client connected%s!\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher accept_ctx->is_private ? " to privileged pipe" : "");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic void client_idle_handler(struct tevent_context *ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct tevent_timer *te,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct timeval current_time,
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek void *data)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher time_t now = time(NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct cli_ctx *cctx = talloc_get_type(data, struct cli_ctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (cctx->last_request_time > now) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_IMPORTANT_INFO,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Time shift detected, re-scheduling the client timeout\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher goto done;
ae765daed93b64b9b4177466a2191561b6734e63Stephen Gallagher }
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if ((now - cctx->last_request_time) > cctx->rctx->client_idle_timeout) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* This connection is idle. Terminate it */
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_INTERNAL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Terminating idle client [%p][%d]\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx, cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* The cli_ctx destructor will handle the rest */
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek talloc_free(cctx);
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek return;
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek }
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherdone:
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher setup_client_idle_timer(cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidekerrno_t reset_client_idle_timer(struct cli_ctx *cctx)
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->last_request_time = time(NULL);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic errno_t setup_client_idle_timer(struct cli_ctx *cctx)
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek{
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct timeval tv =
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher tevent_timeval_current_ofs(cctx->rctx->client_idle_timeout/2, 0);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher talloc_zfree(cctx->idle);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, client_idle_handler, cctx);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!cctx->idle) return ENOMEM;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_TRACE_ALL,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher "Idle timer re-set for client [%p][%d]\n",
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher cctx, cctx->cfd);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return EOK;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher}
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagherstatic int sss_dp_init(struct resp_ctx *rctx,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct sbus_iface_map *sbus_iface,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher const char *cli_name,
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek struct sss_domain_info *domain)
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek{
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek struct be_conn *be_conn;
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek int ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher struct sbus_iface_map *resp_sbus_iface;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher be_conn = talloc_zero(rctx, struct be_conn);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (!be_conn) return ENOMEM;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher be_conn->cli_name = cli_name;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher be_conn->domain = domain;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher be_conn->rctx = rctx;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher /* Set up SBUS connection to the monitor */
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek ret = dp_get_sbus_address(be_conn, &be_conn->sbus_address, domain->name);
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher if (ret != EOK) {
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Could not locate DP address.\n");
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher return ret;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher }
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher ret = sbus_client_init(rctx, rctx->ev,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher be_conn->sbus_address,
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher NULL,
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher &be_conn->conn);
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher if (ret != EOK) {
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to connect to monitor services.\n");
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher return ret;
681742138b2afbbefa7f14de937beb438409208eSimo Sorce }
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher if (sbus_iface != NULL) {
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher ret = sbus_conn_register_iface_map(be_conn->conn, sbus_iface, rctx);
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher if (ret != EOK) {
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to register D-Bus interface.\n");
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce return ret;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher resp_sbus_iface = responder_get_sbus_interface();
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher if (resp_sbus_iface != NULL) {
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher ret = sbus_conn_register_iface_map(be_conn->conn,
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher resp_sbus_iface,
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher rctx);
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek if (ret != EOK) {
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce "Cannot register generic responder iface at %s: %d\n",
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce resp_sbus_iface->path, ret);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce return ret;
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce }
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher /* Identify ourselves to the DP */
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher ret = rdp_register_client(be_conn, cli_name);
fd555d130dc733509347fa096a2cb858b014a196Simo Sorce if (ret != EOK) {
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher DEBUG(SSSDBG_FATAL_FAILURE, "Failed to identify to the DP!\n");
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher return ret;
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher }
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher
1e7c355a2d36eb7b942b5111c96eb2a2285d49ccStephen Gallagher return EOK;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek}
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidekint create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek{
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek struct sockaddr_un addr;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek mode_t orig_umaskval;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek errno_t ret;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek int fd;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek fd = socket(AF_UNIX, SOCK_STREAM, 0);
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek if (fd == -1) {
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek return EIO;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek }
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek orig_umaskval = umask(umaskval);
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek ret = sss_fd_nonblocking(fd);
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek if (ret != EOK) {
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek goto done;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek }
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek ret = set_close_on_exec(fd);
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek if (ret != EOK) {
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek goto done;
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek }
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek memset(&addr, 0, sizeof(addr));
eb29ae58117ca88868491fe2240e27393c7a9068Jakub Hrozek addr.sun_family = AF_UNIX;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path) - 1);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
681742138b2afbbefa7f14de937beb438409208eSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce /* make sure we have no old sockets around */
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = unlink(sock_name);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce if (ret != 0 && errno != ENOENT) {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = errno;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce DEBUG(SSSDBG_MINOR_FAILURE,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce "Cannot remove old socket (errno=%d [%s]), bind might fail!\n",
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret, sss_strerror(ret));
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce }
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce "Unable to bind on socket '%s'\n", sock_name);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = EIO;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce goto done;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce }
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek if (listen(fd, 10) == -1) {
681742138b2afbbefa7f14de937beb438409208eSimo Sorce DEBUG(SSSDBG_FATAL_FAILURE,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce "Unable to listen on socket '%s'\n", sock_name);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = EIO;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce goto done;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce }
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce ret = EOK;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorcedone:
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce /* restore previous umask value */
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce umask(orig_umaskval);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce if (ret == EOK) {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce *_fd = fd;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce } else {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce close(fd);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce }
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce return ret;
4fcc50e133f90cd4c5931a3ac48c84cb628b16fcMichal Zidek}
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce/* create a unix socket and listen to it */
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorcestatic int set_unix_socket(struct resp_ctx *rctx,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce connection_setup_t conn_setup)
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce{
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce errno_t ret;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce struct accept_fd_ctx *accept_ctx = NULL;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce/* for future use */
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce#if 0
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce char *default_pipe;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce int ret;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce default_pipe = talloc_asprintf(rctx, "%s/%s", PIPE_PATH,
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce rctx->sss_pipe_name);
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce if (!default_pipe) {
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce return ENOMEM;
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce }
d0483eefc41ac295ed4c56e08ad76ca7b5fb3b2cSimo Sorce
ret = confdb_get_string(rctx->cdb, rctx,
rctx->confdb_socket_path, "unixSocket",
default_pipe, &rctx->sock_name);
if (ret != EOK) {
talloc_free(default_pipe);
return ret;
}
talloc_free(default_pipe);
default_pipe = talloc_asprintf(rctx, "%s/private/%s", PIPE_PATH,
rctx->sss_pipe_name);
if (!default_pipe) {
return ENOMEM;
}
ret = confdb_get_string(rctx->cdb, rctx,
rctx->confdb_socket_path, "privUnixSocket",
default_pipe, &rctx->priv_sock_name);
if (ret != EOK) {
talloc_free(default_pipe);
return ret;
}
talloc_free(default_pipe);
#endif
if (rctx->sock_name != NULL ) {
/* Set the umask so that permissions are set right on the socket.
* It must be readable and writable by anybody on the system. */
if (rctx->lfd == -1) {
ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, SCKT_RSP_UMASK);
if (ret != EOK) {
return ret;
}
}
accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
if(!accept_ctx) goto failed;
accept_ctx->rctx = rctx;
accept_ctx->is_private = false;
accept_ctx->connection_setup = conn_setup;
rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
TEVENT_FD_READ, accept_fd_handler,
accept_ctx);
if (!rctx->lfde) {
DEBUG(SSSDBG_FATAL_FAILURE, "Failed to queue handler on pipe\n");
goto failed;
}
}
if (rctx->priv_sock_name != NULL ) {
/* create privileged pipe */
if (rctx->priv_lfd == -1) {
ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd,
DFL_RSP_UMASK);
if (ret != EOK) {
goto failed;
}
}
accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
if(!accept_ctx) goto failed;
accept_ctx->rctx = rctx;
accept_ctx->is_private = true;
accept_ctx->connection_setup = conn_setup;
rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
TEVENT_FD_READ, accept_fd_handler,
accept_ctx);
if (!rctx->priv_lfde) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Failed to queue handler on privileged pipe\n");
goto failed;
}
}
return EOK;
failed:
if (rctx->lfd >= 0) close(rctx->lfd);
if (rctx->priv_lfd >= 0) close(rctx->priv_lfd);
return EIO;
}
int activate_unix_sockets(struct resp_ctx *rctx,
connection_setup_t conn_setup)
{
int ret;
#ifdef HAVE_SYSTEMD
if (rctx->lfd == -1 && rctx->priv_lfd == -1) {
int numfds = (rctx->sock_name ? 1 : 0)
+ (rctx->priv_sock_name ? 1 : 0);
/* but if systemd support is available, check if the sockets
* have been opened for us, via socket activation */
ret = sd_listen_fds(1);
if (ret < 0) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Unexpected error probing for active sockets. "
"Will proceed with no sockets. [Error %d (%s)]\n",
-ret, sss_strerror(-ret));
} else if (ret > numfds) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Too many activated sockets have been found, "
"expected %d, found %d\n", numfds, ret);
ret = E2BIG;
goto done;
}
if (ret == numfds) {
rctx->lfd = SD_LISTEN_FDS_START;
ret = sd_is_socket_unix(rctx->lfd, SOCK_STREAM, 1, NULL, 0);
if (ret < 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Activated socket is not a UNIX listening socket\n");
ret = EIO;
goto done;
}
ret = sss_fd_nonblocking(rctx->lfd);
if (ret != EOK) goto done;
if (numfds == 2) {
rctx->priv_lfd = SD_LISTEN_FDS_START + 1;
ret = sd_is_socket_unix(rctx->priv_lfd, SOCK_STREAM, 1, NULL, 0);
if (ret < 0) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Activated priv socket is not a UNIX listening socket\n");
ret = EIO;
goto done;
}
ret = sss_fd_nonblocking(rctx->priv_lfd);
if (ret != EOK) goto done;
}
}
}
#endif
ret = set_unix_socket(rctx, conn_setup);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error initializing sockets\n");
goto done;
}
done:
return ret;
}
int sss_connection_setup(struct cli_ctx *cctx)
{
cctx->protocol_ctx = talloc_zero(cctx, struct cli_protocol);
if (!cctx->protocol_ctx) {
return ENOMEM;
}
cctx->cfd_handler = client_fd_handler;
return EOK;
}
static int sss_responder_ctx_destructor(void *ptr)
{
struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
/* mark that we are shutting down the responder, so it is propagated
* into underlying contexts that are freed right before rctx */
DEBUG(SSSDBG_TRACE_FUNC, "Responder is being shut down\n");
rctx->shutting_down = true;
return 0;
}
static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
struct sss_nc_ctx **ncache)
{
uint32_t neg_timeout;
uint32_t locals_timeout;
int tmp_value;
int ret;
/* neg_timeout */
ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
CONFDB_NSS_ENTRY_NEG_TIMEOUT,
15, &tmp_value);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Fatal failure of setup negative cache timeout.\n");
ret = ENOENT;
goto done;
}
if (tmp_value < 0) {
ret = EINVAL;
goto done;
}
neg_timeout = tmp_value;
/* local_timeout */
ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT,
0, &tmp_value);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Fatal failure of setup negative cache timeout.\n");
ret = ENOENT;
goto done;
}
if (tmp_value < 0) {
ret = EINVAL;
goto done;
}
locals_timeout = tmp_value;
/* negative cache init */
ret = sss_ncache_init(mem_ctx, neg_timeout, locals_timeout, ncache);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Fatal failure of initializing negative cache.\n");
goto done;
}
ret = EOK;
done:
return ret;
}
int sss_process_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct confdb_ctx *cdb,
struct sss_cmd_table sss_cmds[],
const char *sss_pipe_name,
int pipe_fd,
const char *sss_priv_pipe_name,
int priv_pipe_fd,
const char *confdb_service_path,
const char *svc_name,
uint16_t svc_version,
struct mon_cli_iface *monitor_intf,
const char *cli_name,
struct sbus_iface_map *sbus_iface,
connection_setup_t conn_setup,
struct resp_ctx **responder_ctx)
{
struct resp_ctx *rctx;
struct sss_domain_info *dom;
int ret;
char *tmp = NULL;
rctx = talloc_zero(mem_ctx, struct resp_ctx);
if (!rctx) {
DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing resp_ctx\n");
return ENOMEM;
}
rctx->ev = ev;
rctx->cdb = cdb;
rctx->sss_cmds = sss_cmds;
rctx->sock_name = sss_pipe_name;
rctx->priv_sock_name = sss_priv_pipe_name;
rctx->lfd = pipe_fd;
rctx->priv_lfd = priv_pipe_fd;
rctx->confdb_service_path = confdb_service_path;
rctx->shutting_down = false;
rctx->socket_activated = is_socket_activated();
rctx->dbus_activated = is_dbus_activated();
talloc_set_destructor((TALLOC_CTX*)rctx, sss_responder_ctx_destructor);
ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
CONFDB_RESPONDER_CLI_IDLE_TIMEOUT,
CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT,
&rctx->client_idle_timeout);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot get the client idle timeout [%d]: %s\n",
ret, strerror(ret));
goto fail;
}
/* Ensure that the client timeout is at least ten seconds */
if (rctx->client_idle_timeout < 10) {
rctx->client_idle_timeout = 10;
}
if (rctx->socket_activated || rctx->dbus_activated) {
ret = responder_setup_idle_timeout_config(rctx);
if (ret != EOK) {
goto fail;
}
}
ret = confdb_get_bool(rctx->cdb, rctx->confdb_service_path,
CONFDB_RESPONDER_CACHE_FIRST,
false, &rctx->cache_first);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot get \"cache_first_option\".\n"
"Querying the caches first before querying the "
"Data Providers will not be enforced [%d]: %s.\n",
ret, sss_strerror(ret));
}
ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT,
GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannnot get the default domain timeout [%d]: %s\n",
ret, strerror(ret));
goto fail;
}
if (rctx->domains_timeout < 0) {
DEBUG(SSSDBG_CONF_SETTINGS, "timeout can't be set to negative value, setting default\n");
rctx->domains_timeout = GET_DOMAINS_DEFAULT_TIMEOUT;
}
ret = confdb_get_domains(rctx->cdb, &rctx->domains);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up domain map\n");
goto fail;
}
ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
&rctx->default_domain);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannnot get the default domain [%d]: %s\n",
ret, strerror(ret));
goto fail;
}
ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
CONFDB_MONITOR_OVERRIDE_SPACE, NULL,
&tmp);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannnot get the space substitution character [%d]: %s\n",
ret, strerror(ret));
goto fail;
}
if (tmp != NULL) {
if (strlen(tmp) > 1) {
DEBUG(SSSDBG_MINOR_FAILURE, "Option %s is longer than 1 character "
"only the first character %c will be used\n",
CONFDB_MONITOR_OVERRIDE_SPACE, tmp[0]);
}
rctx->override_space = tmp[0];
}
ret = confdb_get_string(rctx->cdb, rctx,
CONFDB_MONITOR_CONF_ENTRY,
CONFDB_MONITOR_DOMAIN_RESOLUTION_ORDER, NULL,
&tmp);
if (ret == EOK) {
rctx->domain_resolution_order = sss_replace_char(rctx, tmp, ',', ':');
} else {
DEBUG(SSSDBG_MINOR_FAILURE,
"Cannot get the \"domain_resolution_order\" option.\n"
"The set up lookup_order won't be followed [%d]: %s.\n",
ret, sss_strerror(ret));
}
ret = sss_monitor_init(rctx, rctx->ev, monitor_intf,
svc_name, svc_version, MT_SVC_SERVICE,
rctx, &rctx->last_request_time,
&rctx->mon_conn);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up message bus\n");
goto fail;
}
for (dom = rctx->domains; dom; dom = get_next_domain(dom, 0)) {
ret = sss_names_init(rctx->cdb, rctx->cdb, dom->name, &dom->names);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"fatal error initializing regex data for domain: %s\n",
dom->name);
goto fail;
}
/* skip local domain, it doesn't have a backend */
if (strcasecmp(dom->provider, "local") == 0) {
continue;
}
ret = sss_dp_init(rctx, sbus_iface, cli_name, dom);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"fatal error setting up backend connector\n");
goto fail;
}
}
ret = sysdb_init(rctx, rctx->domains);
if (ret != EOK) {
SYSDB_VERSION_ERROR_DAEMON(ret);
DEBUG(SSSDBG_FATAL_FAILURE,
"fatal error initializing sysdb connection\n");
goto fail;
}
/* after all initializations we are ready to listen on our socket */
ret = activate_unix_sockets(rctx, conn_setup);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing socket\n");
goto fail;
}
/* Create DP request table */
ret = sss_hash_create(rctx, 30, &rctx->dp_request_table);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Could not create hash table for the request queue\n");
goto fail;
}
ret = responder_init_ncache(rctx, rctx->cdb, &rctx->ncache);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "fatal error initializing negcache\n");
goto fail;
}
ret = sss_ad_default_names_ctx(rctx, &rctx->global_names);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_ad_default_names_ctx failed.\n");
goto fail;
}
DEBUG(SSSDBG_TRACE_FUNC,
"Responder initialization complete (%s)\n",
rctx->socket_activated ? "socket-activated" :
rctx->dbus_activated ? "dbus-activated" :
"explicitly configured");
*responder_ctx = rctx;
return EOK;
fail:
talloc_free(rctx);
return ret;
}
int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
struct be_conn **_conn)
{
struct be_conn *iter;
if (!rctx->be_conns) return ENOENT;
for (iter = rctx->be_conns; iter; iter = iter->next) {
if (strcasecmp(domain, iter->domain->name) == 0) break;
}
if (!iter) return ENOENT;
*_conn = iter;
return EOK;
}
struct sss_domain_info *
responder_get_domain(struct resp_ctx *rctx, const char *name)
{
struct sss_domain_info *dom;
struct sss_domain_info *ret_dom = NULL;
for (dom = rctx->domains; dom;
dom = get_next_domain(dom, SSS_GND_DESCEND)) {
if (sss_domain_get_state(dom) == DOM_DISABLED) {
continue;
}
if (strcasecmp(dom->name, name) == 0 ||
(dom->flat_name != NULL &&
strcasecmp(dom->flat_name, name) == 0)) {
ret_dom = dom;
break;
}
}
if (!ret_dom) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown domain [%s]\n", name);
}
return ret_dom;
}
errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
struct sss_domain_info **_ret_dom)
{
struct sss_domain_info *dom;
struct sss_domain_info *ret_dom = NULL;
size_t id_len;
size_t dom_id_len;
int ret;
if (id == NULL || _ret_dom == NULL) {
return EINVAL;
}
id_len = strlen(id);
for (dom = rctx->domains; dom;
dom = get_next_domain(dom, SSS_GND_DESCEND)) {
if (sss_domain_get_state(dom) == DOM_DISABLED ||
dom->domain_id == NULL) {
continue;
}
dom_id_len = strlen(dom->domain_id);
if ((id_len >= dom_id_len) &&
strncasecmp(dom->domain_id, id, dom_id_len) == 0) {
if (IS_SUBDOMAIN(dom) &&
((time(NULL) - dom->parent->subdomains_last_checked.tv_sec) >
rctx->domains_timeout)) {
DEBUG(SSSDBG_TRACE_FUNC, "Domain entry with id [%s] " \
"is expired.\n", id);
ret = EAGAIN;
goto done;
}
ret_dom = dom;
break;
}
}
if (ret_dom == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown domain id [%s], checking for "
"possible subdomains!\n", id);
ret = ENOENT;
} else {
*_ret_dom = ret_dom;
ret = EOK;
}
done:
return ret;
}
int responder_logrotate(struct sbus_request *dbus_req, void *data)
{
errno_t ret;
struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx);
ret = server_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
if (ret != EOK) return ret;
return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
}
void responder_set_fd_limit(rlim_t fd_limit)
{
struct rlimit current_limit, new_limit;
int limret;
/* First, let's see if we have permission to just set
* the value as-is.
*/
new_limit.rlim_cur = fd_limit;
new_limit.rlim_max = fd_limit;
limret = setrlimit(RLIMIT_NOFILE, &new_limit);
if (limret == 0) {
DEBUG(SSSDBG_CONF_SETTINGS,
"Maximum file descriptors set to [%"SPRIrlim"]\n",
new_limit.rlim_cur);
return;
}
/* We couldn't set the soft and hard limits to this
* value. Let's see how high we CAN set it.
*/
/* Determine the maximum hard limit */
limret = getrlimit(RLIMIT_NOFILE, &current_limit);
if (limret == 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Current fd limit: [%"SPRIrlim"]\n",
current_limit.rlim_cur);
/* Choose the lesser of the requested and the hard limit */
if (current_limit.rlim_max < fd_limit) {
new_limit.rlim_cur = current_limit.rlim_max;
} else {
new_limit.rlim_cur = fd_limit;
}
new_limit.rlim_max = current_limit.rlim_max;
limret = setrlimit(RLIMIT_NOFILE, &new_limit);
if (limret == 0) {
DEBUG(SSSDBG_CONF_SETTINGS,
"Maximum file descriptors set to [%"SPRIrlim"]\n",
new_limit.rlim_cur);
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not set new fd limits. Proceeding with "
"[%"SPRIrlim"]\n", current_limit.rlim_cur);
}
} else {
DEBUG(SSSDBG_CRIT_FAILURE,
"Could not determine fd limits. "
"Proceeding with system values\n");
}
}
errno_t responder_setup_idle_timeout_config(struct resp_ctx *rctx)
{
errno_t ret;
ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
CONFDB_RESPONDER_IDLE_TIMEOUT,
CONFDB_RESPONDER_IDLE_DEFAULT_TIMEOUT,
&rctx->idle_timeout);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Cannot get the responder idle timeout [%d]: %s\n",
ret, sss_strerror(ret));
goto fail;
}
/* Idle timeout set to 0 means that no timeout will be set up to
* the responder */
if (rctx->idle_timeout == 0) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Responder idle timeout won't be set up as the "
"responder_idle_timeout is set to 0");
} else {
/* Ensure that the responder timeout is at least sixty seconds */
if (rctx->idle_timeout < 60) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"responder_idle_timeout is set to a value lower than "
"the minimum allowed (60s).\n"
"The minimum allowed value will be used.");
rctx->idle_timeout = 60;
}
ret = setup_responder_idle_timer(rctx);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
"An error ocurrend when setting up the responder's idle "
"timeout for the responder [%p]: %s [%d].\n"
"The responder won't be automatically shutdown after %d "
"seconds inactive. \n",
rctx, sss_strerror(ret), ret,
rctx->idle_timeout);
}
}
ret = EOK;
fail:
return ret;
}
/* ====== Helper functions for the domain resolution order ======= */
static errno_t
sss_resp_new_cr_domains_from_ipa_id_view(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domains,
struct sysdb_ctx *sysdb,
struct cache_req_domain **_cr_domains)
{
TALLOC_CTX *tmp_ctx;
struct cache_req_domain *cr_domains = NULL;
const char *domain_resolution_order = NULL;
errno_t ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = sysdb_get_view_domain_resolution_order(tmp_ctx, sysdb,
&domain_resolution_order);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_MINOR_FAILURE,
"sysdb_get_view_cache_req_domain() failed [%d]: [%s].\n",
ret, sss_strerror(ret));
goto done;
}
if (ret == ENOENT) {
goto done;
}
ret = cache_req_domain_new_list_from_domain_resolution_order(
mem_ctx, domains, domain_resolution_order, &cr_domains);
if (ret != EOK) {
DEBUG(SSSDBG_DEFAULT,
"cache_req_domain_new_list_from_domain_resolution_order() "
"failed [%d]: [%s].\n",
ret, sss_strerror(ret));
goto done;
}
*_cr_domains = cr_domains;
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
static errno_t
sss_resp_new_cr_domains_from_ipa_config(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domains,
struct sysdb_ctx *sysdb,
const char *domain,
struct cache_req_domain **_cr_domains)
{
TALLOC_CTX *tmp_ctx;
const char *domain_resolution_order = NULL;
errno_t ret;
*_cr_domains = NULL;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = sysdb_domain_get_domain_resolution_order(tmp_ctx, sysdb, domain,
&domain_resolution_order);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_MINOR_FAILURE,
"sysdb_domain_get_cache_req_domain() failed [%d]: [%s].\n",
ret, sss_strerror(ret));
goto done;
}
if (ret == ENOENT) {
goto done;
}
ret = cache_req_domain_new_list_from_domain_resolution_order(
mem_ctx, domains, domain_resolution_order, _cr_domains);
if (ret != EOK) {
DEBUG(SSSDBG_DEFAULT,
"cache_req_domain_new_list_from_domain_resolution_order() "
"failed [%d]: [%s].\n",
ret, sss_strerror(ret));
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
errno_t sss_resp_populate_cr_domains(struct resp_ctx *rctx)
{
struct cache_req_domain *cr_domains = NULL;
struct sss_domain_info *dom;
errno_t ret;
if (rctx->domain_resolution_order != NULL) {
ret = cache_req_domain_new_list_from_domain_resolution_order(
rctx, rctx->domains,
rctx->domain_resolution_order, &cr_domains);
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC,
"Using domain_resolution_order from sssd.conf\n");
goto done;
} else {
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to use domain_resolution_order set in the config file.\n"
"Trying to fallback to use ipaDomainOrderResolution setup by "
"IPA.\n");
}
}
for (dom = rctx->domains; dom != NULL; dom = dom->next) {
if (dom->provider != NULL && strcmp(dom->provider, "ipa") == 0) {
break;
}
}
if (dom == NULL) {
ret = cache_req_domain_new_list_from_domain_resolution_order(
rctx, rctx->domains, NULL, &cr_domains);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to flatten the list of domains.\n");
}
goto done;
}
if (dom->has_views) {
ret = sss_resp_new_cr_domains_from_ipa_id_view(rctx, rctx->domains,
dom->sysdb,
&cr_domains);
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC,
"Using domain_resolution_order from IPA ID View\n");
goto done;
}
if (ret != ENOENT) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to use ipaDomainResolutionOrder set for the "
"view \"%s\".\n"
"Trying to fallback to use ipaDomainOrderResolution "
"set in ipaConfig for the domain: %s.\n",
dom->view_name, dom->name);
}
}
ret = sss_resp_new_cr_domains_from_ipa_config(rctx, rctx->domains,
dom->sysdb, dom->name,
&cr_domains);
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_FUNC,
"Using domain_resolution_order from IPA Config\n");
goto done;
}
if (ret != ENOENT) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to use ipaDomainResolutionOrder set in ipaConfig "
"for the domain: \"%s\".\n"
"No ipaDomainResolutionOrder will be followed.\n",
dom->name);
}
ret = cache_req_domain_new_list_from_domain_resolution_order(
rctx, rctx->domains, NULL, &cr_domains);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to flatten the list of domains.\n");
goto done;
}
ret = EOK;
done:
cache_req_domain_list_zfree(&rctx->cr_domains);
rctx->cr_domains = cr_domains;
return ret;
}
/**
* Helper functions to format output names
*/
int sized_output_name(TALLOC_CTX *mem_ctx,
struct resp_ctx *rctx,
const char *orig_name,
struct sss_domain_info *name_dom,
struct sized_string **_name)
{
TALLOC_CTX *tmp_ctx = NULL;
errno_t ret;
char *name_str;
struct sized_string *name;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
name = talloc_zero(tmp_ctx, struct sized_string);
if (name == NULL) {
ret = ENOMEM;
goto done;
}
ret = sss_output_fqname(mem_ctx, name_dom, orig_name,
rctx->override_space, &name_str);
if (ret != EOK) {
goto done;
}
to_sized_string(name, name_str);
*_name = talloc_steal(mem_ctx, name);
ret = EOK;
done:
talloc_zfree(tmp_ctx);
return ret;
}
int sized_domain_name(TALLOC_CTX *mem_ctx,
struct resp_ctx *rctx,
const char *member_name,
struct sized_string **_name)
{
TALLOC_CTX *tmp_ctx = NULL;
errno_t ret;
char *domname;
struct sss_domain_info *member_dom;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = sss_parse_internal_fqname(tmp_ctx, member_name, NULL, &domname);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_internal_fqname failed\n");
goto done;
}
if (domname == NULL) {
ret = ERR_WRONG_NAME_FORMAT;
goto done;
}
member_dom = find_domain_by_name(get_domains_head(rctx->domains),
domname, true);
if (member_dom == NULL) {
ret = ERR_DOMAIN_NOT_FOUND;
goto done;
}
ret = sized_output_name(mem_ctx, rctx, member_name,
member_dom, _name);
done:
talloc_free(tmp_ctx);
return ret;
}