Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package openssh for openSUSE:Factory checked in at 2023-11-30 21:59:01 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openssh (Old) and /work/SRC/openSUSE:Factory/.openssh.new.25432 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "openssh" Thu Nov 30 21:59:01 2023 rev:168 rq:1129646 version:9.3p2 Changes: -------- --- /work/SRC/openSUSE:Factory/openssh/openssh.changes 2023-10-25 18:02:49.458442925 +0200 +++ /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes 2023-11-30 21:59:23.260785993 +0100 @@ -1,0 +2,24 @@ +Fri Nov 3 10:44:14 UTC 2023 - Johannes Segitz <jsegitz@suse.com> + +- Enhanced SELinux functionality. Added + * openssh-7.8p1-role-mls.patch + Proper handling of MLS systems and basis for other SELinux + improvements + * openssh-6.6p1-privsep-selinux.patch + Properly set contexts during privilege separation + * openssh-6.6p1-keycat.patch + Add ssh-keycat command to allow retrival of authorized_keys + on MLS setups with polyinstantiation + * openssh-6.6.1p1-selinux-contexts.patch + Additional changes to set the proper context during privilege + separation + * openssh-7.6p1-cleanup-selinux.patch + Various changes and putting the pieces together + + For now we don't ship the ssh-keycat command, but we need the patch + for the other SELinux infrastructure + + This change fixes issues like bsc#1214788, where the ssh daemon + needs to act on behalf of a user and needs a proper context for this + +------------------------------------------------------------------- New: ---- openssh-6.6.1p1-selinux-contexts.patch openssh-6.6p1-keycat.patch openssh-6.6p1-privsep-selinux.patch openssh-7.6p1-cleanup-selinux.patch openssh-7.8p1-role-mls.patch BETA DEBUG BEGIN: New:/work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- on MLS setups with polyinstantiation /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes: * openssh-6.6.1p1-selinux-contexts.patch /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Additional changes to set the proper context during privilege New:/work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Properly set contexts during privilege separation /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes: * openssh-6.6p1-keycat.patch /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Add ssh-keycat command to allow retrival of authorized_keys New:/work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- improvements /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes: * openssh-6.6p1-privsep-selinux.patch /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Properly set contexts during privilege separation New:/work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- separation /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes: * openssh-7.6p1-cleanup-selinux.patch /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Various changes and putting the pieces together New:/work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes-- Enhanced SELinux functionality. Added /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes: * openssh-7.8p1-role-mls.patch /work/SRC/openSUSE:Factory/.openssh.new.25432/openssh.changes- Proper handling of MLS systems and basis for other SELinux BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openssh.spec ++++++ --- /var/tmp/diff_new_pack.6fInxO/_old 2023-11-30 21:59:25.196857315 +0100 +++ /var/tmp/diff_new_pack.6fInxO/_new 2023-11-30 21:59:25.200857463 +0100 @@ -119,6 +119,11 @@ # PATCH-FIx-UPSTREAM cb4ed12f.patch -- Fix build with zlib 1.3 Patch53: https://github.com/openssh/openssh-portable/commit/cb4ed12f.patch Patch100: fix-missing-lz.patch +Patch102: openssh-7.8p1-role-mls.patch +Patch103: openssh-6.6p1-privsep-selinux.patch +Patch104: openssh-6.6p1-keycat.patch +Patch105: openssh-6.6.1p1-selinux-contexts.patch +Patch106: openssh-7.6p1-cleanup-selinux.patch BuildRequires: audit-devel BuildRequires: automake BuildRequires: groff @@ -383,6 +388,9 @@ mkdir -p %{buildroot}%{_sysusersdir} install -m 644 %{SOURCE14} %{buildroot}%{_sysusersdir}/sshd.conf +rm %{buildroot}/usr/libexec/ssh/ssh-keycat +#rm -r %{buildroot}/usr/lib/debug/.build-id + # the hmac hashes - taken from openssl # # re-define the __os_install_post macro: the macro strips ++++++ openssh-6.6.1p1-selinux-contexts.patch ++++++ Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c +++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c @@ -33,6 +33,7 @@ #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ #include "servconf.h" #include "port-linux.h" +#include "misc.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" @@ -451,7 +452,7 @@ sshd_selinux_setup_exec_context(char *pw void sshd_selinux_copy_context(void) { - security_context_t *ctx; + char *ctx; if (!sshd_selinux_enabled()) return; @@ -470,6 +471,72 @@ sshd_selinux_copy_context(void) } } +void +sshd_selinux_change_privsep_preauth_context(void) +{ + int len; + char line[1024], *preauth_context = NULL, *cp, *arg; + const char *contexts_path; + FILE *contexts_file; + struct stat sb; + + contexts_path = selinux_openssh_contexts_path(); + if (contexts_path == NULL) { + debug3_f("Failed to get the path to SELinux context"); + return; + } + + if ((contexts_file = fopen(contexts_path, "r")) == NULL) { + debug_f("Failed to open SELinux context file"); + return; + } + + if (fstat(fileno(contexts_file), &sb) != 0 || + sb.st_uid != 0 || (sb.st_mode & 022) != 0) { + logit_f("SELinux context file needs to be owned by root" + " and not writable by anyone else"); + fclose(contexts_file); + return; + } + + while (fgets(line, sizeof(line), contexts_file)) { + /* Strip trailing whitespace */ + for (len = strlen(line) - 1; len > 0; len--) { + if (strchr(" \t\r\n", line[len]) == NULL) + break; + line[len] = '\0'; + } + + if (line[0] == '\0') + continue; + + cp = line; + arg = strdelim(&cp); + if (arg && *arg == '\0') + arg = strdelim(&cp); + + if (arg && strcmp(arg, "privsep_preauth") == 0) { + arg = strdelim(&cp); + if (!arg || *arg == '\0') { + debug_f("privsep_preauth is empty"); + fclose(contexts_file); + return; + } + preauth_context = xstrdup(arg); + } + } + fclose(contexts_file); + + if (preauth_context == NULL) { + debug_f("Unable to find 'privsep_preauth' option in" + " SELinux context file"); + return; + } + + ssh_selinux_change_context(preauth_context); + free(preauth_context); +} + #endif #endif Index: openssh-9.3p2/openbsd-compat/port-linux.c =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux.c +++ openssh-9.3p2/openbsd-compat/port-linux.c @@ -182,7 +182,7 @@ ssh_selinux_change_context(const char *n strlcpy(newctx + len, newname, newlen - len); if ((cx = index(cx + 1, ':'))) strlcat(newctx, cx, newlen); - debug3("%s: setting context from '%s' to '%s'", __func__, + debug_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) do_log2(log_level, "%s: setcon %s from %s failed with %s", Index: openssh-9.3p2/openbsd-compat/port-linux.h =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux.h +++ openssh-9.3p2/openbsd-compat/port-linux.h @@ -27,6 +27,7 @@ int sshd_selinux_enabled(void); void sshd_selinux_copy_context(void); void sshd_selinux_setup_exec_context(char *); int sshd_selinux_setup_env_variables(void); +void sshd_selinux_change_privsep_preauth_context(void); #endif #ifdef LINUX_OOM_ADJUST Index: openssh-9.3p2/sshd.c =================================================================== --- openssh-9.3p2.orig/sshd.c +++ openssh-9.3p2/sshd.c @@ -511,7 +511,7 @@ privsep_preauth_child(struct ssh *ssh) demote_sensitive_data(ssh); #ifdef WITH_SELINUX - ssh_selinux_change_context("sshd_net_t"); + sshd_selinux_change_privsep_preauth_context(); #endif /* Demote the child */ ++++++ openssh-6.6p1-keycat.patch ++++++ Index: openssh-9.3p2/misc.c =================================================================== --- openssh-9.3p2.orig/misc.c +++ openssh-9.3p2/misc.c @@ -2770,6 +2770,13 @@ subprocess(const char *tag, const char * error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } +#ifdef WITH_SELINUX + if (sshd_selinux_setup_env_variables() < 0) { + error ("failed to copy environment: %s", + strerror(errno)); + _exit(127); + } +#endif if (env != NULL) execve(av[0], av, env); else Index: openssh-9.3p2/HOWTO.ssh-keycat =================================================================== --- /dev/null +++ openssh-9.3p2/HOWTO.ssh-keycat @@ -0,0 +1,12 @@ +The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys +of an user in any environment. This includes environments with +polyinstantiation of home directories and SELinux MLS policy enabled. + +To use ssh-keycat, set these options in /etc/ssh/sshd_config file: + AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat + AuthorizedKeysCommandUser root + +Do not forget to enable public key authentication: + PubkeyAuthentication yes + + Index: openssh-9.3p2/Makefile.in =================================================================== --- openssh-9.3p2.orig/Makefile.in +++ openssh-9.3p2/Makefile.in @@ -24,6 +24,7 @@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign +SSH_KEYCAT=$(libexecdir)/ssh-keycat SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper @@ -57,6 +58,7 @@ CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ +KEYCATLIBS=@KEYCATLIBS@ LIBEDIT=@LIBEDIT@ LIBFIDO2=@LIBFIDO2@ LIBWTMPDB=@LIBWTMPDB@ @@ -75,7 +77,7 @@ MKDIR_P=@MKDIR_P@ .SUFFIXES: .lo -TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) TARGETS += cavstest-ctr$(EXEEXT) cavstest-kdf$(EXEEXT) @@ -245,6 +247,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o + $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) @@ -431,6 +436,7 @@ install-files: $(INSTALL) -m 0755 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ fi $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) cavstest-ctr$(EXEEXT) $(DESTDIR)$(libexecdir)/cavstest-ctr$(EXEEXT) Index: openssh-9.3p2/openbsd-compat/port-linux.h =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux.h +++ openssh-9.3p2/openbsd-compat/port-linux.h @@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const void ssh_selinux_change_context(const char *); void ssh_selinux_setfscreatecon(const char *); +int sshd_selinux_enabled(void); void sshd_selinux_copy_context(void); void sshd_selinux_setup_exec_context(char *); +int sshd_selinux_setup_env_variables(void); #endif #ifdef LINUX_OOM_ADJUST Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c +++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c @@ -53,6 +53,20 @@ extern Authctxt *the_authctxt; extern int inetd_flag; extern int rexeced_flag; +/* Wrapper around is_selinux_enabled() to log its return value once only */ +int +sshd_selinux_enabled(void) +{ + static int enabled = -1; + + if (enabled == -1) { + enabled = (is_selinux_enabled() == 1); + debug("SELinux support %s", enabled ? "enabled" : "disabled"); + } + + return (enabled); +} + /* Send audit message */ static int sshd_selinux_send_audit_message(int success, security_context_t default_context, @@ -318,7 +332,7 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int -sshd_selinux_setup_pam_variables(void) +sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) { const char *reqlvl; char *role; @@ -329,16 +343,16 @@ sshd_selinux_setup_pam_variables(void) ssh_selinux_get_role_level(&role, &reqlvl); - rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); + rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); if (inetd_flag && !rexeced_flag) { use_current = "1"; } else { use_current = ""; - rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); + rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); } - rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); + rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current); if (role != NULL) free(role); @@ -346,6 +360,24 @@ sshd_selinux_setup_pam_variables(void) return rv; } +static int +sshd_selinux_setup_pam_variables(void) +{ + return sshd_selinux_setup_variables(do_pam_putenv); +} + +static int +do_setenv(char *name, const char *value) +{ + return setenv(name, value, 1); +} + +int +sshd_selinux_setup_env_variables(void) +{ + return sshd_selinux_setup_variables(do_setenv); +} + /* Set the execution context to the default for the specified user */ void sshd_selinux_setup_exec_context(char *pwname) @@ -354,7 +386,7 @@ sshd_selinux_setup_exec_context(char *pw int r = 0; security_context_t default_ctx = NULL; - if (!ssh_selinux_enabled()) + if (!sshd_selinux_enabled()) return; if (options.use_pam) { @@ -421,7 +453,7 @@ sshd_selinux_copy_context(void) { security_context_t *ctx; - if (!ssh_selinux_enabled()) + if (!sshd_selinux_enabled()) return; if (getexeccon((security_context_t *)&ctx) != 0) { Index: openssh-9.3p2/platform.c =================================================================== --- openssh-9.3p2.orig/platform.c +++ openssh-9.3p2/platform.c @@ -100,7 +100,7 @@ platform_setusercontext(struct passwd *p { #ifdef WITH_SELINUX /* Cache selinux status for later use */ - (void)ssh_selinux_enabled(); + (void)sshd_selinux_enabled(); #endif #ifdef USE_SOLARIS_PROJECTS Index: openssh-9.3p2/ssh-keycat.c =================================================================== --- /dev/null +++ openssh-9.3p2/ssh-keycat.c @@ -0,0 +1,241 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * ALTERNATIVELY, this product may be distributed under the terms of + * the GNU Public License, in which case the provisions of the GPL are + * required INSTEAD OF the above restrictions. (This clause is + * necessary due to a potential bad interaction between the GPL and + * the restrictions contained in a BSD-style copyright.) + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 2011 Red Hat, Inc. + * Written by Tomas Mraz <tmraz@redhat.com> +*/ + +#define _GNU_SOURCE + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pwd.h> +#include <fcntl.h> +#include <unistd.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#include <security/pam_appl.h> + +#include "uidswap.h" +#include "misc.h" + +#define ERR_USAGE 1 +#define ERR_PAM_START 2 +#define ERR_OPEN_SESSION 3 +#define ERR_CLOSE_SESSION 4 +#define ERR_PAM_END 5 +#define ERR_GETPWNAM 6 +#define ERR_MEMORY 7 +#define ERR_OPEN 8 +#define ERR_FILE_MODE 9 +#define ERR_FDOPEN 10 +#define ERR_STAT 11 +#define ERR_WRITE 12 +#define ERR_PAM_PUTENV 13 +#define BUFLEN 4096 + +/* Just ignore the messages in the conversation function */ +static int +dummy_conv(int num_msg, const struct pam_message **msgm, + struct pam_response **response, void *appdata_ptr) +{ + struct pam_response *rsp; + + (void)msgm; + (void)appdata_ptr; + + if (num_msg <= 0) + return PAM_CONV_ERR; + + /* Just allocate the array as empty responses */ + rsp = calloc (num_msg, sizeof (struct pam_response)); + if (rsp == NULL) + return PAM_CONV_ERR; + + *response = rsp; + return PAM_SUCCESS; +} + +static struct pam_conv conv = { + dummy_conv, + NULL +}; + +char * +make_auth_keys_name(const struct passwd *pwd) +{ + char *fname; + + if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0) + return NULL; + + return fname; +} + +int +dump_keys(const char *user) +{ + struct passwd *pwd; + int fd = -1; + FILE *f = NULL; + char *fname = NULL; + int rv = 0; + char buf[BUFLEN]; + size_t len; + struct stat st; + + if ((pwd = getpwnam(user)) == NULL) { + return ERR_GETPWNAM; + } + + if ((fname = make_auth_keys_name(pwd)) == NULL) { + return ERR_MEMORY; + } + + temporarily_use_uid(pwd); + + if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) { + rv = ERR_OPEN; + goto fail; + } + + if (fstat(fd, &st) < 0) { + rv = ERR_STAT; + goto fail; + } + + if (!S_ISREG(st.st_mode) || + (st.st_uid != pwd->pw_uid && st.st_uid != 0)) { + rv = ERR_FILE_MODE; + goto fail; + } + + unset_nonblock(fd); + + if ((f = fdopen(fd, "r")) == NULL) { + rv = ERR_FDOPEN; + goto fail; + } + + fd = -1; + + while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { + rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0; + } + +fail: + if (fd != -1) + close(fd); + if (f != NULL) + fclose(f); + free(fname); + restore_uid(); + return rv; +} + +static const char *env_names[] = { "SELINUX_ROLE_REQUESTED", + "SELINUX_LEVEL_REQUESTED", + "SELINUX_USE_CURRENT_RANGE" +}; + +extern char **environ; + +int +set_pam_environment(pam_handle_t *pamh) +{ + int i; + size_t j; + + for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) { + int len = strlen(env_names[j]); + + for (i = 0; environ[i] != NULL; ++i) { + if (strncmp(env_names[j], environ[i], len) == 0 && + environ[i][len] == '=') { + if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS) + return ERR_PAM_PUTENV; + } + } + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + pam_handle_t *pamh = NULL; + int retval; + int ev = 0; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <user-name>\n", argv[0]); + return ERR_USAGE; + } + + retval = pam_start("ssh-keycat", argv[1], &conv, &pamh); + if (retval != PAM_SUCCESS) { + return ERR_PAM_START; + } + + ev = set_pam_environment(pamh); + if (ev != 0) + goto finish; + + retval = pam_open_session(pamh, PAM_SILENT); + if (retval != PAM_SUCCESS) { + ev = ERR_OPEN_SESSION; + goto finish; + } + + ev = dump_keys(argv[1]); + + retval = pam_close_session(pamh, PAM_SILENT); + if (retval != PAM_SUCCESS) { + ev = ERR_CLOSE_SESSION; + } + +finish: + retval = pam_end (pamh,retval); + if (retval != PAM_SUCCESS) { + ev = ERR_PAM_END; + } + return ev; +} Index: openssh-9.3p2/configure.ac =================================================================== --- openssh-9.3p2.orig/configure.ac +++ openssh-9.3p2/configure.ac @@ -3632,6 +3632,7 @@ AC_ARG_WITH([pam], PAM_MSG="yes" SSHDLIBS="$SSHDLIBS -lpam" + KEYCATLIBS="$KEYCATLIBS -lpam" AC_DEFINE([USE_PAM], [1], [Define if you want to enable PAM support]) @@ -3642,6 +3643,7 @@ AC_ARG_WITH([pam], ;; *) SSHDLIBS="$SSHDLIBS -ldl" + KEYCATLIBS="$KEYCATLIBS -ldl" ;; esac fi @@ -4875,6 +4877,7 @@ AC_ARG_WITH([selinux], fi ] ) AC_SUBST([SSHDLIBS]) +AC_SUBST([KEYCATLIBS]) # Check whether user wants Kerberos 5 support KRB5_MSG="no" @@ -5905,6 +5908,9 @@ fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi +if test ! -z "${KEYCATLIBS}"; then +echo " +for ssh-keycat: ${KEYCATLIBS}" +fi echo "" ++++++ openssh-6.6p1-privsep-selinux.patch ++++++ Index: openssh-9.3p2/openbsd-compat/port-linux.h =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux.h +++ openssh-9.3p2/openbsd-compat/port-linux.h @@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const void ssh_selinux_change_context(const char *); void ssh_selinux_setfscreatecon(const char *); +void sshd_selinux_copy_context(void); void sshd_selinux_setup_exec_context(char *); #endif Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c +++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c @@ -416,6 +416,28 @@ sshd_selinux_setup_exec_context(char *pw debug3_f("done"); } +void +sshd_selinux_copy_context(void) +{ + security_context_t *ctx; + + if (!ssh_selinux_enabled()) + return; + + if (getexeccon((security_context_t *)&ctx) != 0) { + logit_f("getexeccon failed with %s", strerror(errno)); + return; + } + if (ctx != NULL) { + /* unset exec context before we will lose this capabililty */ + if (setexeccon(NULL) != 0) + fatal_f("setexeccon failed with %s", strerror(errno)); + if (setcon(ctx) != 0) + fatal_f("setcon failed with %s", strerror(errno)); + freecon(ctx); + } +} + #endif #endif Index: openssh-9.3p2/session.c =================================================================== --- openssh-9.3p2.orig/session.c +++ openssh-9.3p2/session.c @@ -1403,7 +1403,7 @@ do_setusercontext(struct passwd *pw) platform_setusercontext(pw); - if (platform_privileged_uidswap()) { + if (platform_privileged_uidswap() && (!is_child || !use_privsep)) { #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { @@ -1435,6 +1435,9 @@ do_setusercontext(struct passwd *pw) (unsigned long long)pw->pw_uid); chroot_path = percent_expand(tmp, "h", pw->pw_dir, "u", pw->pw_name, "U", uidstr, (char *)NULL); +#ifdef WITH_SELINUX + sshd_selinux_copy_context(); +#endif safely_chroot(chroot_path, pw->pw_uid); free(tmp); free(chroot_path); @@ -1470,6 +1473,11 @@ do_setusercontext(struct passwd *pw) /* Permanently switch to the desired uid. */ permanently_set_uid(pw); #endif + +#ifdef WITH_SELINUX + if (in_chroot == 0) + sshd_selinux_copy_context(); +#endif } else if (options.chroot_directory != NULL && strcasecmp(options.chroot_directory, "none") != 0) { fatal("server lacks privileges to chroot to ChrootDirectory"); @@ -1487,9 +1495,6 @@ do_pwchange(Session *s) if (s->ttyfd != -1) { fprintf(stderr, "You must change your password now and login again!\n"); -#ifdef WITH_SELINUX - setexeccon(NULL); -#endif #ifdef PASSWD_NEEDS_USERNAME execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name, (char *)NULL); @@ -1723,9 +1728,6 @@ do_child(struct ssh *ssh, Session *s, co argv[i] = NULL; optind = optreset = 1; __progname = argv[0]; -#ifdef WITH_SELINUX - ssh_selinux_change_context("sftpd_t"); -#endif exit(sftp_server_main(i, argv, s->pw)); } Index: openssh-9.3p2/sshd.c =================================================================== --- openssh-9.3p2.orig/sshd.c +++ openssh-9.3p2/sshd.c @@ -510,6 +510,10 @@ privsep_preauth_child(struct ssh *ssh) /* Demote the private keys to public keys. */ demote_sensitive_data(ssh); +#ifdef WITH_SELINUX + ssh_selinux_change_context("sshd_net_t"); +#endif + /* Demote the child */ if (privsep_chroot) { /* Change our root directory */ @@ -602,6 +606,9 @@ privsep_postauth(struct ssh *ssh, Authct { #ifdef DISABLE_FD_PASSING if (1) { +#elif defined(WITH_SELINUX) + if (0) { + /* even root user can be confined by SELinux */ #else if (authctxt->pw->pw_uid == 0) { #endif ++++++ openssh-7.6p1-cleanup-selinux.patch ++++++ Index: openssh-9.3p2/auth2-pubkey.c =================================================================== --- openssh-9.3p2.orig/auth2-pubkey.c +++ openssh-9.3p2/auth2-pubkey.c @@ -72,6 +72,9 @@ /* import */ extern ServerOptions options; +extern int inetd_flag; +extern int rexeced_flag; +extern Authctxt *the_authctxt; static char * format_key(const struct sshkey *key) @@ -459,7 +462,8 @@ match_principals_command(struct passwd * if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, - runas_pw, temporarily_use_uid, restore_uid)) == 0) + runas_pw, temporarily_use_uid, restore_uid, + (inetd_flag && !rexeced_flag), the_authctxt)) == 0) goto out; uid_swapped = 1; @@ -727,7 +731,8 @@ user_key_command_allowed2(struct passwd if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, - runas_pw, temporarily_use_uid, restore_uid)) == 0) + runas_pw, temporarily_use_uid, restore_uid, + (inetd_flag && !rexeced_flag), the_authctxt)) == 0) goto out; uid_swapped = 1; Index: openssh-9.3p2/misc.c =================================================================== --- openssh-9.3p2.orig/misc.c +++ openssh-9.3p2/misc.c @@ -2637,7 +2637,8 @@ stdfd_devnull(int do_stdin, int do_stdou pid_t subprocess(const char *tag, const char *command, int ac, char **av, FILE **child, u_int flags, - struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) + struct passwd *pw, privdrop_fn *drop_privs, + privrestore_fn *restore_privs, int inetd, void *the_authctxt) { FILE *f = NULL; struct stat st; @@ -2771,7 +2772,7 @@ subprocess(const char *tag, const char * _exit(1); } #ifdef WITH_SELINUX - if (sshd_selinux_setup_env_variables() < 0) { + if (sshd_selinux_setup_env_variables(inetd, the_authctxt) < 0) { error ("failed to copy environment: %s", strerror(errno)); _exit(127); Index: openssh-9.3p2/misc.h =================================================================== --- openssh-9.3p2.orig/misc.h +++ openssh-9.3p2/misc.h @@ -110,7 +110,7 @@ typedef void privrestore_fn(void); #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, - struct passwd *, privdrop_fn *, privrestore_fn *); + struct passwd *, privdrop_fn *, privrestore_fn *, int, void *); typedef struct arglist arglist; struct arglist { Index: openssh-9.3p2/openbsd-compat/port-linux.h =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux.h +++ openssh-9.3p2/openbsd-compat/port-linux.h @@ -25,8 +25,8 @@ void ssh_selinux_setfscreatecon(const ch int sshd_selinux_enabled(void); void sshd_selinux_copy_context(void); -void sshd_selinux_setup_exec_context(char *); -int sshd_selinux_setup_env_variables(void); +void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int); +int sshd_selinux_setup_env_variables(int inetd, void *); void sshd_selinux_change_privsep_preauth_context(void); #endif Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c =================================================================== --- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c +++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c @@ -49,11 +49,6 @@ #include <unistd.h> #endif -extern ServerOptions options; -extern Authctxt *the_authctxt; -extern int inetd_flag; -extern int rexeced_flag; - /* Wrapper around is_selinux_enabled() to log its return value once only */ int sshd_selinux_enabled(void) @@ -223,7 +218,8 @@ get_user_context(const char *sename, con } static void -ssh_selinux_get_role_level(char **role, const char **level) +ssh_selinux_get_role_level(char **role, const char **level, + Authctxt *the_authctxt) { *role = NULL; *level = NULL; @@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role, /* Return the default security context for the given username */ static int -sshd_selinux_getctxbyname(char *pwname, - security_context_t *default_sc, security_context_t *user_sc) +sshd_selinux_getctxbyname(char *pwname, security_context_t *default_sc, + security_context_t *user_sc, int inetd, Authctxt *the_authctxt) { char *sename, *lvl; char *role; @@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, int r = 0; context_t con = NULL; - ssh_selinux_get_role_level(&role, &reqlvl); + ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt); #ifdef HAVE_GETSEUSERBYNAME if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { @@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, if (r == 0) { /* If launched from xinetd, we must use current level */ - if (inetd_flag && !rexeced_flag) { + if (inetd) { security_context_t sshdsc=NULL; if (getcon_raw(&sshdsc) < 0) @@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int -sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) +sshd_selinux_setup_variables(int(*set_it)(char *, const char *), int inetd, + Authctxt *the_authctxt) { const char *reqlvl; char *role; @@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it debug3_f("setting execution context"); - ssh_selinux_get_role_level(&role, &reqlvl); + ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt); rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); - if (inetd_flag && !rexeced_flag) { + if (inetd) { use_current = "1"; } else { use_current = ""; @@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it } static int -sshd_selinux_setup_pam_variables(void) +sshd_selinux_setup_pam_variables(int inetd, + int(pam_setenv)(char *, const char *), Authctxt *the_authctxt) { - return sshd_selinux_setup_variables(do_pam_putenv); + return sshd_selinux_setup_variables(pam_setenv, inetd, the_authctxt); } static int @@ -374,25 +372,28 @@ do_setenv(char *name, const char *value) } int -sshd_selinux_setup_env_variables(void) +sshd_selinux_setup_env_variables(int inetd, void *the_authctxt) { - return sshd_selinux_setup_variables(do_setenv); + Authctxt *authctxt = (Authctxt *) the_authctxt; + return sshd_selinux_setup_variables(do_setenv, inetd, authctxt); } /* Set the execution context to the default for the specified user */ void -sshd_selinux_setup_exec_context(char *pwname) +sshd_selinux_setup_exec_context(char *pwname, int inetd, + int(pam_setenv)(char *, const char *), void *the_authctxt, int use_pam) { security_context_t user_ctx = NULL; int r = 0; security_context_t default_ctx = NULL; + Authctxt *authctxt = (Authctxt *) the_authctxt; if (!sshd_selinux_enabled()) return; - if (options.use_pam) { + if (use_pam) { /* do not compute context, just setup environment for pam_selinux */ - if (sshd_selinux_setup_pam_variables()) { + if (sshd_selinux_setup_pam_variables(inetd, pam_setenv, authctxt)) { switch (security_getenforce()) { case -1: fatal_f("security_getenforce() failed"); @@ -408,7 +409,7 @@ sshd_selinux_setup_exec_context(char *pw debug3_f("setting execution context"); - r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); + r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx, inetd, authctxt); if (r >= 0) { r = setexeccon(user_ctx); if (r < 0) { Index: openssh-9.3p2/platform.c =================================================================== --- openssh-9.3p2.orig/platform.c +++ openssh-9.3p2/platform.c @@ -34,6 +34,9 @@ extern int use_privsep; extern ServerOptions options; +extern int inetd_flag; +extern int rexeced_flag; +extern Authctxt *the_authctxt; void platform_pre_listen(void) @@ -185,7 +188,9 @@ platform_setusercontext_post_groups(stru } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(pw->pw_name); + sshd_selinux_setup_exec_context(pw->pw_name, + (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, + options.use_pam); #endif } Index: openssh-9.3p2/sshd.c =================================================================== --- openssh-9.3p2.orig/sshd.c +++ openssh-9.3p2/sshd.c @@ -166,7 +166,7 @@ int debug_flag = 0; static int test_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ -static int inetd_flag = 0; +int inetd_flag = 0; /* Flag indicating that sshd should not detach and become a daemon. */ static int no_daemon_flag = 0; @@ -179,7 +179,7 @@ static char **saved_argv; static int saved_argc; /* re-exec */ -static int rexeced_flag = 0; +int rexeced_flag = 0; static int rexec_flag = 1; static int rexec_argc = 0; static char **rexec_argv; @@ -2396,7 +2396,9 @@ main(int ac, char **av) } #endif #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(authctxt->pw->pw_name); + sshd_selinux_setup_exec_context(authctxt->pw->pw_name, + (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, + options.use_pam); #endif #ifdef USE_PAM if (options.use_pam) { Index: openssh-9.3p2/sshconnect.c =================================================================== --- openssh-9.3p2.orig/sshconnect.c +++ openssh-9.3p2/sshconnect.c @@ -893,7 +893,7 @@ load_hostkeys_command(struct hostkeys *h if ((pid = subprocess(tag, command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| - SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) + SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0) goto out; load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); ++++++ openssh-7.8p1-role-mls.patch ++++++ ++++ 886 lines (skipped)