From ef28a3bdc50d0da6fab86b0d27e4c548ac61a749 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 28 May 2018 21:49:41 +0200 Subject: [PATCH] TESTS: Add a helper binary that can trigger the SIGPIPE to authorizedkeys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a test tool that simulates the behaviour of OpenSSH in the sense that it starts to read the output from the sss_ssh_authorizedkeys tool, but then closes the pipe before reading the whole output. Related: https://pagure.io/SSSD/sssd/issue/3747 Reviewed-by: Fabiano FidĂȘncio (cherry picked from commit 909c16edb26a3c48b10a49e7919a35d13d31c52e) --- Makefile.am | 15 +++- src/tests/test_ssh_client.c | 133 ++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 src/tests/test_ssh_client.c diff --git a/Makefile.am b/Makefile.am index 9055130ed74057987795285c243ff47584cf8316..99974cf0e94e1ec6086a53585042653ec5966c2c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -331,6 +331,7 @@ endif # HAVE_CMOCKA check_PROGRAMS = \ stress-tests \ krb5-child-test \ + test_ssh_client \ $(non_interactive_cmocka_based_tests) \ $(non_interactive_check_based_tests) @@ -2291,6 +2292,18 @@ krb5_child_test_LDADD = \ $(SSSD_INTERNAL_LTLIBS) \ libsss_test_common.la +test_ssh_client_SOURCES = \ + src/tests/test_ssh_client.c \ + $(NULL) +test_ssh_client_CFLAGS = \ + $(AM_CFLAGS) \ + -DSSH_CLIENT_DIR=\"$(abs_top_builddir)\" \ + $(NULL) +test_ssh_client_LDADD = \ + $(SSSD_INTERNAL_LTLIBS) \ + $(SSSD_LIBS) \ + $(NULL) + if BUILD_DBUS_TESTS sbus_tests_SOURCES = \ @@ -3446,7 +3459,6 @@ test_iobuf_LDADD = \ $(SSSD_LIBS) \ $(NULL) - EXTRA_simple_access_tests_DEPENDENCIES = \ $(ldblib_LTLIBRARIES) simple_access_tests_SOURCES = \ @@ -3655,6 +3667,7 @@ intgcheck-prepare: $(INTGCHECK_CONFIGURE_FLAGS) \ CFLAGS="-O2 -g $$CFLAGS -DKCM_PEER_UID=$$(id -u)"; \ $(MAKE) $(AM_MAKEFLAGS) ; \ + $(MAKE) $(AM_MAKEFLAGS) test_ssh_client; \ : Force single-thread install to workaround concurrency issues; \ $(MAKE) $(AM_MAKEFLAGS) -j1 install; \ : Remove .la files from LDB module directory to avoid loader warnings; \ diff --git a/src/tests/test_ssh_client.c b/src/tests/test_ssh_client.c new file mode 100644 index 0000000000000000000000000000000000000000..8f963941f3249561178436d6f6dfc376780a4cda --- /dev/null +++ b/src/tests/test_ssh_client.c @@ -0,0 +1,133 @@ +/* + Copyright (C) 2018 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 . +*/ + +#include +#include +#include "util/util.h" + +#ifdef SSH_CLIENT_DIR +#define SSH_AK_CLIENT_PATH SSH_CLIENT_DIR"/sss_ssh_authorizedkeys" +#else +#error "The path to the ssh authorizedkeys helper is not defined" +#endif /* SSH_CLIENT_DIR */ + +int main(int argc, const char *argv[]) +{ + poptContext pc; + int opt; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + POPT_TABLEEND + }; + struct stat sb; + int ret; + int status; + int p[2]; + pid_t pid; + const char *pc_user = NULL; + char *av[3]; + char buf[5]; /* Ridiculously small buffer by design */ + + /* 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); + poptSetOtherOptionHelp(pc, "USER"); + 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 3; + } + } + + pc_user = poptGetArg(pc); + if (pc_user == NULL) { + fprintf(stderr, "No user specified\n"); + return 3; + } + + poptFreeContext(pc); + + DEBUG_CLI_INIT(debug_level); + + ret = stat(SSH_AK_CLIENT_PATH, &sb); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not stat %s [%d]: %s\n", + SSH_AK_CLIENT_PATH, ret, strerror(ret)); + return 3; + } + + ret = pipe(p); + if (ret != 0) { + perror("pipe"); + return 3; + } + + switch (pid = fork()) { + case -1: + ret = errno; + close(p[0]); + close(p[1]); + DEBUG(SSSDBG_CRIT_FAILURE, "fork failed: %d\n", ret); + return 3; + case 0: + /* child */ + av[0] = discard_const(SSH_AK_CLIENT_PATH); + av[1] = discard_const(pc_user); + av[2] = NULL; + + close(p[0]); + ret = dup2(p[1], STDOUT_FILENO); + if (ret == -1) { + perror("dup2"); + return 3; + } + + execv(av[0], av); + return 3; + default: + /* parent */ + break; + } + + close(p[1]); + read(p[0], buf, sizeof(buf)); + close(p[0]); + + pid = waitpid(pid, &status, 0); + if (pid == -1) { + perror("waitpid"); + return 3; + } + + if (WIFEXITED(status)) { + printf("sss_ssh_authorizedkeys exited with return code %d\n", WEXITSTATUS(status)); + return 0; + } else if (WIFSIGNALED(status)) { + printf("sss_ssh_authorizedkeys exited with signal %d\n", WTERMSIG(status)); + return 1; + } + + printf("sss_ssh_authorizedkeys exited for another reason\n"); + return 2; +} -- 2.17.1