Remove unnecessary files
This commit is contained in:
parent
3fdf10cdb4
commit
395eb16df8
File diff suppressed because it is too large
Load Diff
@ -1,446 +0,0 @@
|
|||||||
diff -up openssh-5.4p1/configure.ac.mls openssh-5.4p1/configure.ac
|
|
||||||
--- openssh-5.4p1/configure.ac.mls 2010-03-01 15:24:27.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/configure.ac 2010-03-01 15:24:28.000000000 +0100
|
|
||||||
@@ -3360,6 +3360,7 @@ AC_ARG_WITH(selinux,
|
|
||||||
SSHDLIBS="$SSHDLIBS $LIBSELINUX"
|
|
||||||
LIBS="$LIBS $LIBSELINUX"
|
|
||||||
AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level)
|
|
||||||
+ AC_CHECK_FUNCS(setkeycreatecon)
|
|
||||||
LIBS="$save_LIBS"
|
|
||||||
fi ]
|
|
||||||
)
|
|
||||||
diff -up openssh-5.4p1/misc.c.mls openssh-5.4p1/misc.c
|
|
||||||
--- openssh-5.4p1/misc.c.mls 2010-01-10 00:31:12.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/misc.c 2010-03-01 15:24:28.000000000 +0100
|
|
||||||
@@ -423,6 +423,7 @@ char *
|
|
||||||
colon(char *cp)
|
|
||||||
{
|
|
||||||
int flag = 0;
|
|
||||||
+ int start = 1;
|
|
||||||
|
|
||||||
if (*cp == ':') /* Leading colon is part of file name. */
|
|
||||||
return (0);
|
|
||||||
@@ -436,8 +437,13 @@ colon(char *cp)
|
|
||||||
return (cp+1);
|
|
||||||
if (*cp == ':' && !flag)
|
|
||||||
return (cp);
|
|
||||||
- if (*cp == '/')
|
|
||||||
- return (0);
|
|
||||||
+ if (start) {
|
|
||||||
+ /* Slash on beginning or after dots only denotes file name. */
|
|
||||||
+ if (*cp == '/')
|
|
||||||
+ return (0);
|
|
||||||
+ if (*cp != '.')
|
|
||||||
+ start = 0;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
diff -up openssh-5.4p1/openbsd-compat/port-linux.c.mls openssh-5.4p1/openbsd-compat/port-linux.c
|
|
||||||
--- openssh-5.4p1/openbsd-compat/port-linux.c.mls 2010-03-01 15:24:27.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/openbsd-compat/port-linux.c 2010-03-01 15:25:50.000000000 +0100
|
|
||||||
@@ -35,13 +35,24 @@
|
|
||||||
#include "key.h"
|
|
||||||
#include "hostfile.h"
|
|
||||||
#include "auth.h"
|
|
||||||
+#include "xmalloc.h"
|
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
|
||||||
#include <selinux/selinux.h>
|
|
||||||
#include <selinux/flask.h>
|
|
||||||
+#include <selinux/context.h>
|
|
||||||
#include <selinux/get_context_list.h>
|
|
||||||
+#include <selinux/get_default_type.h>
|
|
||||||
+#include <selinux/av_permissions.h>
|
|
||||||
+
|
|
||||||
+#ifdef HAVE_LINUX_AUDIT
|
|
||||||
+#include <libaudit.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -57,17 +68,173 @@ ssh_selinux_enabled(void)
|
|
||||||
return (enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Send audit message */
|
|
||||||
+static int
|
|
||||||
+send_audit_message(int success, security_context_t default_context,
|
|
||||||
+ security_context_t selected_context)
|
|
||||||
+{
|
|
||||||
+ int rc=0;
|
|
||||||
+#ifdef HAVE_LINUX_AUDIT
|
|
||||||
+ char *msg = NULL;
|
|
||||||
+ int audit_fd = audit_open();
|
|
||||||
+ security_context_t default_raw=NULL;
|
|
||||||
+ security_context_t selected_raw=NULL;
|
|
||||||
+ rc = -1;
|
|
||||||
+ if (audit_fd < 0) {
|
|
||||||
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
|
||||||
+ errno == EAFNOSUPPORT)
|
|
||||||
+ return 0; /* No audit support in kernel */
|
|
||||||
+ error("Error connecting to audit system.");
|
|
||||||
+ return rc;
|
|
||||||
+ }
|
|
||||||
+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
|
|
||||||
+ error("Error translating default context.");
|
|
||||||
+ default_raw = NULL;
|
|
||||||
+ }
|
|
||||||
+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
|
|
||||||
+ error("Error translating selected context.");
|
|
||||||
+ selected_raw = NULL;
|
|
||||||
+ }
|
|
||||||
+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
|
|
||||||
+ default_raw ? default_raw : (default_context ? default_context: "?"),
|
|
||||||
+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
|
|
||||||
+ error("Error allocating memory.");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
|
|
||||||
+ msg, NULL, NULL, NULL, success) <= 0) {
|
|
||||||
+ error("Error sending audit message.");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ rc = 0;
|
|
||||||
+ out:
|
|
||||||
+ free(msg);
|
|
||||||
+ freecon(default_raw);
|
|
||||||
+ freecon(selected_raw);
|
|
||||||
+ close(audit_fd);
|
|
||||||
+#endif
|
|
||||||
+ return rc;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+mls_range_allowed(security_context_t src, security_context_t dst)
|
|
||||||
+{
|
|
||||||
+ struct av_decision avd;
|
|
||||||
+ int retval;
|
|
||||||
+ unsigned int bit = CONTEXT__CONTAINS;
|
|
||||||
+
|
|
||||||
+ debug("%s: src:%s dst:%s", __func__, src, dst);
|
|
||||||
+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
|
|
||||||
+ if (retval || ((bit & avd.allowed) != bit))
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+get_user_context(const char *sename, const char *role, const char *lvl,
|
|
||||||
+ security_context_t *sc) {
|
|
||||||
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
|
||||||
+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
|
|
||||||
+ /* User may have requested a level completely outside of his
|
|
||||||
+ allowed range. We get a context just for auditing as the
|
|
||||||
+ range check below will certainly fail for default context. */
|
|
||||||
+#endif
|
|
||||||
+ if (get_default_context(sename, NULL, sc) != 0) {
|
|
||||||
+ *sc = NULL;
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ if (role != NULL && role[0]) {
|
|
||||||
+ context_t con;
|
|
||||||
+ char *type=NULL;
|
|
||||||
+ if (get_default_type(role, &type) != 0) {
|
|
||||||
+ error("get_default_type: failed to get default type for '%s'",
|
|
||||||
+ role);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ con = context_new(*sc);
|
|
||||||
+ if (!con) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ context_role_set(con, role);
|
|
||||||
+ context_type_set(con, type);
|
|
||||||
+ freecon(*sc);
|
|
||||||
+ *sc = strdup(context_str(con));
|
|
||||||
+ context_free(con);
|
|
||||||
+ if (!*sc)
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
|
||||||
+ if (lvl != NULL && lvl[0]) {
|
|
||||||
+ /* verify that the requested range is obtained */
|
|
||||||
+ context_t con;
|
|
||||||
+ security_context_t obtained_raw;
|
|
||||||
+ security_context_t requested_raw;
|
|
||||||
+ con = context_new(*sc);
|
|
||||||
+ if (!con) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ context_range_set(con, lvl);
|
|
||||||
+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
|
|
||||||
+ context_free(con);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
|
|
||||||
+ freecon(obtained_raw);
|
|
||||||
+ context_free(con);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ debug("get_user_context: obtained context '%s' requested context '%s'",
|
|
||||||
+ obtained_raw, requested_raw);
|
|
||||||
+ if (strcmp(obtained_raw, requested_raw)) {
|
|
||||||
+ /* set the context to the real requested one but fail */
|
|
||||||
+ freecon(requested_raw);
|
|
||||||
+ freecon(obtained_raw);
|
|
||||||
+ freecon(*sc);
|
|
||||||
+ *sc = strdup(context_str(con));
|
|
||||||
+ context_free(con);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ freecon(requested_raw);
|
|
||||||
+ freecon(obtained_raw);
|
|
||||||
+ context_free(con);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ return 0;
|
|
||||||
+ out:
|
|
||||||
+ freecon(*sc);
|
|
||||||
+ *sc = NULL;
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Return the default security context for the given username */
|
|
||||||
-static security_context_t
|
|
||||||
-ssh_selinux_getctxbyname(char *pwname)
|
|
||||||
+static int
|
|
||||||
+ssh_selinux_getctxbyname(char *pwname,
|
|
||||||
+ security_context_t *default_sc, security_context_t *user_sc)
|
|
||||||
{
|
|
||||||
- security_context_t sc = NULL;
|
|
||||||
char *sename, *lvl;
|
|
||||||
+ const char *reqlvl = NULL;
|
|
||||||
char *role = NULL;
|
|
||||||
- int r = 0;
|
|
||||||
+ int r = -1;
|
|
||||||
+ context_t con = NULL;
|
|
||||||
+
|
|
||||||
+ *default_sc = NULL;
|
|
||||||
+ *user_sc = NULL;
|
|
||||||
+ if (the_authctxt) {
|
|
||||||
+ if (the_authctxt->role != NULL) {
|
|
||||||
+ char *slash;
|
|
||||||
+ role = xstrdup(the_authctxt->role);
|
|
||||||
+ if ((slash = strchr(role, '/')) != NULL) {
|
|
||||||
+ *slash = '\0';
|
|
||||||
+ reqlvl = slash + 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (the_authctxt)
|
|
||||||
- role=the_authctxt->role;
|
|
||||||
#ifdef HAVE_GETSEUSERBYNAME
|
|
||||||
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
|
|
||||||
sename = NULL;
|
|
||||||
@@ -75,38 +242,63 @@ ssh_selinux_getctxbyname(char *pwname)
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
sename = pwname;
|
|
||||||
- lvl = NULL;
|
|
||||||
+ lvl = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (r == 0) {
|
|
||||||
#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
|
||||||
- if (role != NULL && role[0])
|
|
||||||
- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
|
|
||||||
- else
|
|
||||||
- r = get_default_context_with_level(sename, lvl, NULL, &sc);
|
|
||||||
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
|
|
||||||
#else
|
|
||||||
- if (role != NULL && role[0])
|
|
||||||
- r = get_default_context_with_role(sename, role, NULL, &sc);
|
|
||||||
- else
|
|
||||||
- r = get_default_context(sename, NULL, &sc);
|
|
||||||
+ r = get_default_context(sename, NULL, default_sc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (r != 0) {
|
|
||||||
- switch (security_getenforce()) {
|
|
||||||
- case -1:
|
|
||||||
- fatal("%s: ssh_selinux_getctxbyname: "
|
|
||||||
- "security_getenforce() failed", __func__);
|
|
||||||
- case 0:
|
|
||||||
- error("%s: Failed to get default SELinux security "
|
|
||||||
- "context for %s", __func__, pwname);
|
|
||||||
- break;
|
|
||||||
- default:
|
|
||||||
- fatal("%s: Failed to get default SELinux security "
|
|
||||||
- "context for %s (in enforcing mode)",
|
|
||||||
- __func__, pwname);
|
|
||||||
+ if (r == 0) {
|
|
||||||
+ /* If launched from xinetd, we must use current level */
|
|
||||||
+ if (inetd_flag && !rexeced_flag) {
|
|
||||||
+ security_context_t sshdsc=NULL;
|
|
||||||
+
|
|
||||||
+ if (getcon_raw(&sshdsc) < 0)
|
|
||||||
+ fatal("failed to allocate security context");
|
|
||||||
+
|
|
||||||
+ if ((con=context_new(sshdsc)) == NULL)
|
|
||||||
+ fatal("failed to allocate selinux context");
|
|
||||||
+ reqlvl = context_range_get(con);
|
|
||||||
+ freecon(sshdsc);
|
|
||||||
+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
|
|
||||||
+ /* we actually don't change level */
|
|
||||||
+ reqlvl = "";
|
|
||||||
+
|
|
||||||
+ debug("%s: current connection level '%s'", __func__, reqlvl);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
|
|
||||||
+ r = get_user_context(sename, role, reqlvl, user_sc);
|
|
||||||
+
|
|
||||||
+ if (r == 0 && reqlvl != NULL && reqlvl[0]) {
|
|
||||||
+ security_context_t default_level_sc = *default_sc;
|
|
||||||
+ if (role != NULL && role[0]) {
|
|
||||||
+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
|
|
||||||
+ default_level_sc = *default_sc;
|
|
||||||
+ }
|
|
||||||
+ /* verify that the requested range is contained in the user range */
|
|
||||||
+ if (mls_range_allowed(default_level_sc, *user_sc)) {
|
|
||||||
+ logit("permit MLS level %s (user range %s)", reqlvl, lvl);
|
|
||||||
+ } else {
|
|
||||||
+ r = -1;
|
|
||||||
+ error("deny MLS level %s (user range %s)", reqlvl, lvl);
|
|
||||||
+ }
|
|
||||||
+ if (default_level_sc != *default_sc)
|
|
||||||
+ freecon(default_level_sc);
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ *user_sc = *default_sc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ if (r != 0) {
|
|
||||||
+ error("%s: Failed to get default SELinux security "
|
|
||||||
+ "context for %s", __func__, pwname);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
#ifdef HAVE_GETSEUSERBYNAME
|
|
||||||
if (sename != NULL)
|
|
||||||
@@ -114,14 +306,20 @@ ssh_selinux_getctxbyname(char *pwname)
|
|
||||||
if (lvl != NULL)
|
|
||||||
xfree(lvl);
|
|
||||||
#endif
|
|
||||||
+ if (role != NULL)
|
|
||||||
+ xfree(role);
|
|
||||||
+ if (con)
|
|
||||||
+ context_free(con);
|
|
||||||
|
|
||||||
- return (sc);
|
|
||||||
+ return (r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the execution context to the default for the specified user */
|
|
||||||
void
|
|
||||||
ssh_selinux_setup_exec_context(char *pwname)
|
|
||||||
{
|
|
||||||
+ int r = 0;
|
|
||||||
+ security_context_t default_ctx = NULL;
|
|
||||||
security_context_t user_ctx = NULL;
|
|
||||||
|
|
||||||
if (!ssh_selinux_enabled())
|
|
||||||
@@ -129,22 +327,45 @@ ssh_selinux_setup_exec_context(char *pwn
|
|
||||||
|
|
||||||
debug3("%s: setting execution context", __func__);
|
|
||||||
|
|
||||||
- user_ctx = ssh_selinux_getctxbyname(pwname);
|
|
||||||
- if (setexeccon(user_ctx) != 0) {
|
|
||||||
+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
|
|
||||||
+ if (r >= 0) {
|
|
||||||
+ r = setexeccon(user_ctx);
|
|
||||||
+ if (r < 0) {
|
|
||||||
+ error("%s: Failed to set SELinux execution context %s for %s",
|
|
||||||
+ __func__, user_ctx, pwname);
|
|
||||||
+ }
|
|
||||||
+#ifdef HAVE_SETKEYCREATECON
|
|
||||||
+ else if (setkeycreatecon(user_ctx) < 0) {
|
|
||||||
+ error("%s: Failed to set SELinux keyring creation context %s for %s",
|
|
||||||
+ __func__, user_ctx, pwname);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ }
|
|
||||||
+ if (user_ctx == NULL) {
|
|
||||||
+ user_ctx = default_ctx;
|
|
||||||
+ }
|
|
||||||
+ if (r < 0 || user_ctx != default_ctx) {
|
|
||||||
+ /* audit just the case when user changed a role or there was
|
|
||||||
+ a failure */
|
|
||||||
+ send_audit_message(r >= 0, default_ctx, user_ctx);
|
|
||||||
+ }
|
|
||||||
+ if (r < 0) {
|
|
||||||
switch (security_getenforce()) {
|
|
||||||
case -1:
|
|
||||||
fatal("%s: security_getenforce() failed", __func__);
|
|
||||||
case 0:
|
|
||||||
- error("%s: Failed to set SELinux execution "
|
|
||||||
- "context for %s", __func__, pwname);
|
|
||||||
+ error("%s: SELinux failure. Continuing in permissive mode.",
|
|
||||||
+ __func__);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
- fatal("%s: Failed to set SELinux execution context "
|
|
||||||
- "for %s (in enforcing mode)", __func__, pwname);
|
|
||||||
+ fatal("%s: SELinux failure. Aborting connection.",
|
|
||||||
+ __func__);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- if (user_ctx != NULL)
|
|
||||||
+ if (user_ctx != NULL && user_ctx != default_ctx)
|
|
||||||
freecon(user_ctx);
|
|
||||||
+ if (default_ctx != NULL)
|
|
||||||
+ freecon(default_ctx);
|
|
||||||
|
|
||||||
debug3("%s: done", __func__);
|
|
||||||
}
|
|
||||||
@@ -162,7 +383,10 @@ ssh_selinux_setup_pty(char *pwname, cons
|
|
||||||
|
|
||||||
debug3("%s: setting TTY context on %s", __func__, tty);
|
|
||||||
|
|
||||||
- user_ctx = ssh_selinux_getctxbyname(pwname);
|
|
||||||
+ if (getexeccon(&user_ctx) < 0) {
|
|
||||||
+ error("%s: getexeccon: %s", __func__, strerror(errno));
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* XXX: should these calls fatal() upon failure in enforcing mode? */
|
|
||||||
|
|
||||||
diff -up openssh-5.4p1/session.c.mls openssh-5.4p1/session.c
|
|
||||||
--- openssh-5.4p1/session.c.mls 2010-01-12 09:51:48.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/session.c 2010-03-01 15:24:28.000000000 +0100
|
|
||||||
@@ -1559,10 +1559,6 @@ do_setusercontext(struct passwd *pw)
|
|
||||||
|
|
||||||
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
|
|
||||||
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
|
|
||||||
-
|
|
||||||
-#ifdef WITH_SELINUX
|
|
||||||
- ssh_selinux_setup_exec_context(pw->pw_name);
|
|
||||||
-#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
diff -up openssh-5.4p1/sshd.c.mls openssh-5.4p1/sshd.c
|
|
||||||
--- openssh-5.4p1/sshd.c.mls 2010-03-01 15:24:27.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/sshd.c 2010-03-01 15:24:28.000000000 +0100
|
|
||||||
@@ -1987,6 +1987,9 @@ main(int ac, char **av)
|
|
||||||
restore_uid();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
+#ifdef WITH_SELINUX
|
|
||||||
+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
|
|
||||||
+#endif
|
|
||||||
#ifdef USE_PAM
|
|
||||||
if (options.use_pam) {
|
|
||||||
do_pam_setcred(1);
|
|
@ -1,384 +0,0 @@
|
|||||||
diff -up openssh-5.4p1/auth2-pubkey.c.pka openssh-5.4p1/auth2-pubkey.c
|
|
||||||
--- openssh-5.4p1/auth2-pubkey.c.pka 2010-03-09 08:01:05.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/auth2-pubkey.c 2010-03-09 08:07:15.000000000 +0100
|
|
||||||
@@ -187,27 +187,15 @@ done:
|
|
||||||
|
|
||||||
/* return 1 if user allows given key */
|
|
||||||
static int
|
|
||||||
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
|
||||||
+user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
|
||||||
{
|
|
||||||
char line[SSH_MAX_PUBKEY_BYTES];
|
|
||||||
const char *reason;
|
|
||||||
int found_key = 0;
|
|
||||||
- FILE *f;
|
|
||||||
u_long linenum = 0;
|
|
||||||
Key *found;
|
|
||||||
char *fp;
|
|
||||||
|
|
||||||
- /* Temporarily use the user's uid. */
|
|
||||||
- temporarily_use_uid(pw);
|
|
||||||
-
|
|
||||||
- debug("trying public key file %s", file);
|
|
||||||
- f = auth_openkeyfile(file, pw, options.strict_modes);
|
|
||||||
-
|
|
||||||
- if (!f) {
|
|
||||||
- restore_uid();
|
|
||||||
- return 0;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
found_key = 0;
|
|
||||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
|
||||||
|
|
||||||
@@ -278,8 +266,6 @@ user_key_allowed2(struct passwd *pw, Key
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- restore_uid();
|
|
||||||
- fclose(f);
|
|
||||||
key_free(found);
|
|
||||||
if (!found_key)
|
|
||||||
debug2("key not found");
|
|
||||||
@@ -327,13 +313,153 @@ user_cert_trusted_ca(struct passwd *pw,
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* check whether given key is in .ssh/authorized_keys* */
|
|
||||||
+/* return 1 if user allows given key */
|
|
||||||
+static int
|
|
||||||
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
|
||||||
+{
|
|
||||||
+ FILE *f;
|
|
||||||
+ int found_key = 0;
|
|
||||||
+
|
|
||||||
+ /* Temporarily use the user's uid. */
|
|
||||||
+ temporarily_use_uid(pw);
|
|
||||||
+
|
|
||||||
+ debug("trying public key file %s", file);
|
|
||||||
+ f = auth_openkeyfile(file, pw, options.strict_modes);
|
|
||||||
+
|
|
||||||
+ if (f) {
|
|
||||||
+ found_key = user_search_key_in_file (f, file, key, pw);
|
|
||||||
+ fclose(f);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ restore_uid();
|
|
||||||
+ return found_key;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifdef WITH_PUBKEY_AGENT
|
|
||||||
+
|
|
||||||
+#define WHITESPACE " \t\r\n"
|
|
||||||
+
|
|
||||||
+/* return 1 if user allows given key */
|
|
||||||
+static int
|
|
||||||
+user_key_via_agent_allowed2(struct passwd *pw, Key *key)
|
|
||||||
+{
|
|
||||||
+ FILE *f;
|
|
||||||
+ int found_key = 0;
|
|
||||||
+ char *pubkey_agent_string = NULL;
|
|
||||||
+ char *tmp_pubkey_agent_string = NULL;
|
|
||||||
+ char *progname;
|
|
||||||
+ char *cp;
|
|
||||||
+ struct passwd *runas_pw;
|
|
||||||
+ struct stat st;
|
|
||||||
+
|
|
||||||
+ if (options.pubkey_agent == NULL || options.pubkey_agent[0] != '/')
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ /* get the run as identity from config */
|
|
||||||
+ runas_pw = (options.pubkey_agent_runas == NULL)? pw
|
|
||||||
+ : getpwnam (options.pubkey_agent_runas);
|
|
||||||
+ if (!runas_pw) {
|
|
||||||
+ error("%s: getpwnam(\"%s\"): %s", __func__,
|
|
||||||
+ options.pubkey_agent_runas, strerror(errno));
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Temporarily use the specified uid. */
|
|
||||||
+ if (runas_pw->pw_uid != 0)
|
|
||||||
+ temporarily_use_uid(runas_pw);
|
|
||||||
+
|
|
||||||
+ pubkey_agent_string = percent_expand(options.pubkey_agent,
|
|
||||||
+ "h", pw->pw_dir, "u", pw->pw_name, (char *)NULL);
|
|
||||||
+
|
|
||||||
+ /* Test whether agent can be modified by non root user */
|
|
||||||
+ tmp_pubkey_agent_string = xstrdup (pubkey_agent_string);
|
|
||||||
+ progname = strtok (tmp_pubkey_agent_string, WHITESPACE);
|
|
||||||
+
|
|
||||||
+ debug3("%s: checking program '%s'", __func__, progname);
|
|
||||||
+
|
|
||||||
+ if (stat (progname, &st) < 0) {
|
|
||||||
+ error("%s: stat(\"%s\"): %s", __func__,
|
|
||||||
+ progname, strerror(errno));
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
|
|
||||||
+ error("bad ownership or modes for pubkey agent \"%s\"",
|
|
||||||
+ progname);
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!S_ISREG(st.st_mode)) {
|
|
||||||
+ error("pubkey agent \"%s\" is not a regular file",
|
|
||||||
+ progname);
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Descend the path, checking that each component is a
|
|
||||||
+ * root-owned directory with strict permissions.
|
|
||||||
+ */
|
|
||||||
+ do {
|
|
||||||
+ if ((cp = strrchr(progname, '/')) == NULL)
|
|
||||||
+ break;
|
|
||||||
+ else
|
|
||||||
+ *cp = '\0';
|
|
||||||
+
|
|
||||||
+ debug3("%s: checking component '%s'", __func__, progname);
|
|
||||||
+
|
|
||||||
+ if (stat(progname, &st) != 0) {
|
|
||||||
+ error("%s: stat(\"%s\"): %s", __func__,
|
|
||||||
+ progname, strerror(errno));
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
|
|
||||||
+ error("bad ownership or modes for pubkey agent path component \"%s\"",
|
|
||||||
+ progname);
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+ if (!S_ISDIR(st.st_mode)) {
|
|
||||||
+ error("pubkey agent path component \"%s\" is not a directory",
|
|
||||||
+ progname);
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+ } while (0);
|
|
||||||
+
|
|
||||||
+ /* open the pipe and read the keys */
|
|
||||||
+ f = popen (pubkey_agent_string, "r");
|
|
||||||
+ if (!f) {
|
|
||||||
+ error("%s: popen (\"%s\", \"r\"): %s", __func__,
|
|
||||||
+ pubkey_agent_string, strerror (errno));
|
|
||||||
+ goto go_away;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ found_key = user_search_key_in_file (f, options.pubkey_agent, key, pw);
|
|
||||||
+ pclose (f);
|
|
||||||
+
|
|
||||||
+go_away:
|
|
||||||
+ if (tmp_pubkey_agent_string)
|
|
||||||
+ xfree (tmp_pubkey_agent_string);
|
|
||||||
+ if (pubkey_agent_string)
|
|
||||||
+ xfree (pubkey_agent_string);
|
|
||||||
+
|
|
||||||
+ if (runas_pw->pw_uid != 0)
|
|
||||||
+ restore_uid();
|
|
||||||
+ return found_key;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/* check whether given key is in <pkey_agent or .ssh/authorized_keys* */
|
|
||||||
int
|
|
||||||
user_key_allowed(struct passwd *pw, Key *key)
|
|
||||||
{
|
|
||||||
int success;
|
|
||||||
char *file;
|
|
||||||
|
|
||||||
+#ifdef WITH_PUBKEY_AGENT
|
|
||||||
+ success = user_key_via_agent_allowed2(pw, key);
|
|
||||||
+ if (success >= 0)
|
|
||||||
+ return success;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
if (auth_key_is_revoked(key))
|
|
||||||
return 0;
|
|
||||||
if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
|
|
||||||
diff -up openssh-5.4p1/configure.ac.pka openssh-5.4p1/configure.ac
|
|
||||||
--- openssh-5.4p1/configure.ac.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/configure.ac 2010-03-09 08:01:05.000000000 +0100
|
|
||||||
@@ -1323,6 +1323,18 @@ AC_ARG_WITH(audit,
|
|
||||||
esac ]
|
|
||||||
)
|
|
||||||
|
|
||||||
+# Check whether user wants pubkey agent support
|
|
||||||
+PKA_MSG="no"
|
|
||||||
+AC_ARG_WITH(pka,
|
|
||||||
+ [ --with-pka Enable pubkey agent support],
|
|
||||||
+ [
|
|
||||||
+ if test "x$withval" != "xno" ; then
|
|
||||||
+ AC_DEFINE([WITH_PUBKEY_AGENT], 1, [Enable pubkey agent support])
|
|
||||||
+ PKA_MSG="yes"
|
|
||||||
+ fi
|
|
||||||
+ ]
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
dnl Checks for library functions. Please keep in alphabetical order
|
|
||||||
AC_CHECK_FUNCS( \
|
|
||||||
arc4random \
|
|
||||||
@@ -4206,6 +4218,7 @@ echo " Linux audit support
|
|
||||||
echo " Smartcard support: $SCARD_MSG"
|
|
||||||
echo " S/KEY support: $SKEY_MSG"
|
|
||||||
echo " TCP Wrappers support: $TCPW_MSG"
|
|
||||||
+echo " PKA support: $PKA_MSG"
|
|
||||||
echo " MD5 password support: $MD5_MSG"
|
|
||||||
echo " libedit support: $LIBEDIT_MSG"
|
|
||||||
echo " Solaris process contract support: $SPC_MSG"
|
|
||||||
diff -up openssh-5.4p1/servconf.c.pka openssh-5.4p1/servconf.c
|
|
||||||
--- openssh-5.4p1/servconf.c.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/servconf.c 2010-03-09 09:04:57.000000000 +0100
|
|
||||||
@@ -129,6 +129,8 @@ initialize_server_options(ServerOptions
|
|
||||||
options->num_permitted_opens = -1;
|
|
||||||
options->adm_forced_command = NULL;
|
|
||||||
options->chroot_directory = NULL;
|
|
||||||
+ options->pubkey_agent = NULL;
|
|
||||||
+ options->pubkey_agent_runas = NULL;
|
|
||||||
options->zero_knowledge_password_authentication = -1;
|
|
||||||
options->revoked_keys_file = NULL;
|
|
||||||
options->trusted_user_ca_keys = NULL;
|
|
||||||
@@ -315,6 +317,7 @@ typedef enum {
|
|
||||||
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
|
||||||
sZeroKnowledgePasswordAuthentication, sHostCertificate,
|
|
||||||
sRevokedKeys, sTrustedUserCAKeys,
|
|
||||||
+ sPubkeyAgent, sPubkeyAgentRunAs,
|
|
||||||
sDeprecated, sUnsupported
|
|
||||||
} ServerOpCodes;
|
|
||||||
|
|
||||||
@@ -437,6 +440,13 @@ static struct {
|
|
||||||
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
|
|
||||||
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
|
|
||||||
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
|
|
||||||
+#ifdef WITH_PUBKEY_AGENT
|
|
||||||
+ { "pubkeyagent", sPubkeyAgent, SSHCFG_ALL },
|
|
||||||
+ { "pubkeyagentrunas", sPubkeyAgentRunAs, SSHCFG_ALL },
|
|
||||||
+#else
|
|
||||||
+ { "pubkeyagent", sUnsupported, SSHCFG_ALL },
|
|
||||||
+ { "pubkeyagentrunas", sUnsupported, SSHCFG_ALL },
|
|
||||||
+#endif
|
|
||||||
{ NULL, sBadOption, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1345,6 +1355,20 @@ process_server_config_line(ServerOptions
|
|
||||||
charptr = &options->revoked_keys_file;
|
|
||||||
goto parse_filename;
|
|
||||||
|
|
||||||
+ case sPubkeyAgent:
|
|
||||||
+ len = strspn(cp, WHITESPACE);
|
|
||||||
+ if (*activep && options->pubkey_agent == NULL)
|
|
||||||
+ options->pubkey_agent = xstrdup(cp + len);
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ case sPubkeyAgentRunAs:
|
|
||||||
+ charptr = &options->pubkey_agent_runas;
|
|
||||||
+
|
|
||||||
+ arg = strdelim(&cp);
|
|
||||||
+ if (*activep && *charptr == NULL)
|
|
||||||
+ *charptr = xstrdup(arg);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
case sDeprecated:
|
|
||||||
logit("%s line %d: Deprecated option %s",
|
|
||||||
filename, linenum, arg);
|
|
||||||
@@ -1438,6 +1462,8 @@ copy_set_server_options(ServerOptions *d
|
|
||||||
M_CP_INTOPT(gss_authentication);
|
|
||||||
M_CP_INTOPT(rsa_authentication);
|
|
||||||
M_CP_INTOPT(pubkey_authentication);
|
|
||||||
+ M_CP_STROPT(pubkey_agent);
|
|
||||||
+ M_CP_STROPT(pubkey_agent_runas);
|
|
||||||
M_CP_INTOPT(kerberos_authentication);
|
|
||||||
M_CP_INTOPT(hostbased_authentication);
|
|
||||||
M_CP_INTOPT(kbd_interactive_authentication);
|
|
||||||
@@ -1683,6 +1709,8 @@ dump_config(ServerOptions *o)
|
|
||||||
dump_cfg_string(sChrootDirectory, o->chroot_directory);
|
|
||||||
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
|
|
||||||
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
|
|
||||||
+ dump_cfg_string(sPubkeyAgent, o->pubkey_agent);
|
|
||||||
+ dump_cfg_string(sPubkeyAgentRunAs, o->pubkey_agent_runas);
|
|
||||||
|
|
||||||
/* string arguments requiring a lookup */
|
|
||||||
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
|
|
||||||
diff -up openssh-5.4p1/servconf.h.pka openssh-5.4p1/servconf.h
|
|
||||||
--- openssh-5.4p1/servconf.h.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/servconf.h 2010-03-09 09:05:29.000000000 +0100
|
|
||||||
@@ -157,6 +157,8 @@ typedef struct {
|
|
||||||
char *chroot_directory;
|
|
||||||
char *revoked_keys_file;
|
|
||||||
char *trusted_user_ca_keys;
|
|
||||||
+ char *pubkey_agent;
|
|
||||||
+ char *pubkey_agent_runas;
|
|
||||||
} ServerOptions;
|
|
||||||
|
|
||||||
void initialize_server_options(ServerOptions *);
|
|
||||||
diff -up openssh-5.4p1/sshd_config.0.pka openssh-5.4p1/sshd_config.0
|
|
||||||
--- openssh-5.4p1/sshd_config.0.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/sshd_config.0 2010-03-09 09:07:35.000000000 +0100
|
|
||||||
@@ -352,7 +352,8 @@ DESCRIPTION
|
|
||||||
KbdInteractiveAuthentication, KerberosAuthentication,
|
|
||||||
MaxAuthTries, MaxSessions, PasswordAuthentication,
|
|
||||||
PermitEmptyPasswords, PermitOpen, PermitRootLogin,
|
|
||||||
- PubkeyAuthentication, RhostsRSAAuthentication, RSAAuthentication,
|
|
||||||
+ PubkeyAuthentication, PubkeyAgent, PubkeyAgentRunAs,
|
|
||||||
+ RhostsRSAAuthentication, RSAAuthentication,
|
|
||||||
X11DisplayOffset, X11Forwarding and X11UseLocalHost.
|
|
||||||
|
|
||||||
MaxAuthTries
|
|
||||||
@@ -467,6 +468,17 @@ DESCRIPTION
|
|
||||||
this file is not readable, then public key authentication will be
|
|
||||||
refused for all users.
|
|
||||||
|
|
||||||
+ PubkeyAgent
|
|
||||||
+ Specifies which agent is used for lookup of the user's public
|
|
||||||
+ keys. Empty string means to use the authorized_keys file. By
|
|
||||||
+ default there is no PubkeyAgent set. Note that this option has
|
|
||||||
+ an effect only with PubkeyAuthentication switched on.
|
|
||||||
+
|
|
||||||
+ PubkeyAgentRunAs
|
|
||||||
+ Specifies the user under whose account the PubkeyAgent is run.
|
|
||||||
+ Empty string (the default value) means the user being authorized
|
|
||||||
+ is used.
|
|
||||||
+
|
|
||||||
RhostsRSAAuthentication
|
|
||||||
Specifies whether rhosts or /etc/hosts.equiv authentication to-
|
|
||||||
gether with successful RSA host authentication is allowed. The
|
|
||||||
diff -up openssh-5.4p1/sshd_config.5.pka openssh-5.4p1/sshd_config.5
|
|
||||||
--- openssh-5.4p1/sshd_config.5.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/sshd_config.5 2010-03-09 09:06:40.000000000 +0100
|
|
||||||
@@ -618,6 +618,9 @@ Available keywords are
|
|
||||||
.Cm KerberosAuthentication ,
|
|
||||||
.Cm MaxAuthTries ,
|
|
||||||
.Cm MaxSessions ,
|
|
||||||
+.Cm PubkeyAuthentication ,
|
|
||||||
+.Cm PubkeyAgent ,
|
|
||||||
+.Cm PubkeyAgentRunAs ,
|
|
||||||
.Cm PasswordAuthentication ,
|
|
||||||
.Cm PermitEmptyPasswords ,
|
|
||||||
.Cm PermitOpen ,
|
|
||||||
@@ -819,6 +822,16 @@ Specifies a list of revoked public keys.
|
|
||||||
Keys listed in this file will be refused for public key authentication.
|
|
||||||
Note that if this file is not readable, then public key authentication will
|
|
||||||
be refused for all users.
|
|
||||||
++.It Cm PubkeyAgent
|
|
||||||
++Specifies which agent is used for lookup of the user's public
|
|
||||||
++keys. Empty string means to use the authorized_keys file.
|
|
||||||
++By default there is no PubkeyAgent set.
|
|
||||||
++Note that this option has an effect only with PubkeyAuthentication
|
|
||||||
++switched on.
|
|
||||||
++.It Cm PubkeyAgentRunAs
|
|
||||||
++Specifies the user under whose account the PubkeyAgent is run. Empty
|
|
||||||
++string (the default value) means the user being authorized is used.
|
|
||||||
++.Dq
|
|
||||||
.It Cm RhostsRSAAuthentication
|
|
||||||
Specifies whether rhosts or /etc/hosts.equiv authentication together
|
|
||||||
with successful RSA host authentication is allowed.
|
|
||||||
diff -up openssh-5.4p1/sshd_config.pka openssh-5.4p1/sshd_config
|
|
||||||
--- openssh-5.4p1/sshd_config.pka 2010-03-09 08:01:04.000000000 +0100
|
|
||||||
+++ openssh-5.4p1/sshd_config 2010-03-09 08:01:06.000000000 +0100
|
|
||||||
@@ -45,6 +45,8 @@ SyslogFacility AUTHPRIV
|
|
||||||
#RSAAuthentication yes
|
|
||||||
#PubkeyAuthentication yes
|
|
||||||
#AuthorizedKeysFile .ssh/authorized_keys
|
|
||||||
+#PubkeyAgent none
|
|
||||||
+#PubkeyAgentRunAs nobody
|
|
||||||
|
|
||||||
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
|
||||||
#RhostsRSAAuthentication no
|
|
@ -1,157 +0,0 @@
|
|||||||
diff -up openssh-5.5p1/session.c.stderr openssh-5.5p1/session.c
|
|
||||||
--- openssh-5.5p1/session.c.stderr 2010-04-26 10:35:35.000000000 +0200
|
|
||||||
+++ openssh-5.5p1/session.c 2010-04-26 10:41:11.000000000 +0200
|
|
||||||
@@ -47,6 +47,7 @@
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
+#include <fcntl.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#ifdef HAVE_PATHS_H
|
|
||||||
#include <paths.h>
|
|
||||||
@@ -447,6 +448,9 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
#ifdef USE_PIPES
|
|
||||||
int pin[2], pout[2], perr[2];
|
|
||||||
|
|
||||||
+ if (s == NULL)
|
|
||||||
+ fatal("do_exec_no_pty: no session");
|
|
||||||
+
|
|
||||||
/* Allocate pipes for communicating with the program. */
|
|
||||||
if (pipe(pin) < 0) {
|
|
||||||
error("%s: pipe in: %.100s", __func__, strerror(errno));
|
|
||||||
@@ -458,33 +462,59 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
close(pin[1]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- if (pipe(perr) < 0) {
|
|
||||||
- error("%s: pipe err: %.100s", __func__, strerror(errno));
|
|
||||||
- close(pin[0]);
|
|
||||||
- close(pin[1]);
|
|
||||||
- close(pout[0]);
|
|
||||||
- close(pout[1]);
|
|
||||||
- return -1;
|
|
||||||
+ if (s->is_subsystem) {
|
|
||||||
+ if ((perr[1] = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
|
|
||||||
+ error("%s: open(%s): %s", __func__, _PATH_DEVNULL,
|
|
||||||
+ strerror(errno));
|
|
||||||
+ close(pin[0]);
|
|
||||||
+ close(pin[1]);
|
|
||||||
+ close(pout[0]);
|
|
||||||
+ close(pout[1]);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ perr[0] = -1;
|
|
||||||
+ } else {
|
|
||||||
+ if (pipe(perr) < 0) {
|
|
||||||
+ error("%s: pipe err: %.100s", __func__,
|
|
||||||
+ strerror(errno));
|
|
||||||
+ close(pin[0]);
|
|
||||||
+ close(pin[1]);
|
|
||||||
+ close(pout[0]);
|
|
||||||
+ close(pout[1]);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int inout[2], err[2];
|
|
||||||
|
|
||||||
+ if (s == NULL)
|
|
||||||
+ fatal("do_exec_no_pty: no session");
|
|
||||||
+
|
|
||||||
/* Uses socket pairs to communicate with the program. */
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
|
|
||||||
error("%s: socketpair #1: %.100s", __func__, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
|
|
||||||
- error("%s: socketpair #2: %.100s", __func__, strerror(errno));
|
|
||||||
- close(inout[0]);
|
|
||||||
- close(inout[1]);
|
|
||||||
- return -1;
|
|
||||||
+ if (s->is_subsystem) {
|
|
||||||
+ if ((err[0] = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
|
|
||||||
+ error("%s: open(%s): %s", __func__, _PATH_DEVNULL,
|
|
||||||
+ strerror(errno));
|
|
||||||
+ close(inout[0]);
|
|
||||||
+ close(inout[1]);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ err[1] = -1;
|
|
||||||
+ } else {
|
|
||||||
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
|
|
||||||
+ error("%s: socketpair #2: %.100s", __func__,
|
|
||||||
+ strerror(errno));
|
|
||||||
+ close(inout[0]);
|
|
||||||
+ close(inout[1]);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- if (s == NULL)
|
|
||||||
- fatal("do_exec_no_pty: no session");
|
|
||||||
-
|
|
||||||
session_proctitle(s);
|
|
||||||
|
|
||||||
/* Fork the child. */
|
|
||||||
@@ -496,13 +526,15 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
close(pin[1]);
|
|
||||||
close(pout[0]);
|
|
||||||
close(pout[1]);
|
|
||||||
- close(perr[0]);
|
|
||||||
+ if (perr[0] != -1)
|
|
||||||
+ close(perr[0]);
|
|
||||||
close(perr[1]);
|
|
||||||
#else
|
|
||||||
close(inout[0]);
|
|
||||||
close(inout[1]);
|
|
||||||
close(err[0]);
|
|
||||||
- close(err[1]);
|
|
||||||
+ if (err[1] != -1)
|
|
||||||
+ close(err[1]);
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
case 0:
|
|
||||||
@@ -536,7 +568,8 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
close(pout[1]);
|
|
||||||
|
|
||||||
/* Redirect stderr. */
|
|
||||||
- close(perr[0]);
|
|
||||||
+ if (perr[0] != -1)
|
|
||||||
+ close(perr[0]);
|
|
||||||
if (dup2(perr[1], 2) < 0)
|
|
||||||
perror("dup2 stderr");
|
|
||||||
close(perr[1]);
|
|
||||||
@@ -547,7 +580,8 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
* seem to depend on it.
|
|
||||||
*/
|
|
||||||
close(inout[1]);
|
|
||||||
- close(err[1]);
|
|
||||||
+ if (err[1] != -1)
|
|
||||||
+ close(err[1]);
|
|
||||||
if (dup2(inout[0], 0) < 0) /* stdin */
|
|
||||||
perror("dup2 stdin");
|
|
||||||
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */
|
|
||||||
@@ -595,10 +629,6 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
close(perr[1]);
|
|
||||||
|
|
||||||
if (compat20) {
|
|
||||||
- if (s->is_subsystem) {
|
|
||||||
- close(perr[0]);
|
|
||||||
- perr[0] = -1;
|
|
||||||
- }
|
|
||||||
session_set_fds(s, pin[1], pout[0], perr[0], 0);
|
|
||||||
} else {
|
|
||||||
/* Enter the interactive session. */
|
|
||||||
@@ -615,10 +645,7 @@ do_exec_no_pty(Session *s, const char *c
|
|
||||||
* handle the case that fdin and fdout are the same.
|
|
||||||
*/
|
|
||||||
if (compat20) {
|
|
||||||
- session_set_fds(s, inout[1], inout[1],
|
|
||||||
- s->is_subsystem ? -1 : err[1], 0);
|
|
||||||
- if (s->is_subsystem)
|
|
||||||
- close(err[1]);
|
|
||||||
+ session_set_fds(s, inout[1], inout[1], err[1], 0);
|
|
||||||
} else {
|
|
||||||
server_loop(pid, inout[1], inout[1], err[1]);
|
|
||||||
/* server_loop has closed inout[1] and err[1]. */
|
|
Loading…
Reference in New Issue
Block a user