Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Capsicum support for pkg ssh
Baptiste Daroussin committed 12 years ago
commit 6320b7619fa883cfcd151c9159673d91a70ef1db
parent c48af01
4 files changed +76 -9
modified configure.ac
@@ -101,6 +101,14 @@ AC_CHECK_HEADER([sys/sbuf.h], [
	LIBSBUF_INCLUDE="-I\$(top_srcdir)/external/libsbuf"
])

+
AC_CHECK_HEADER([sys/capability.h], [
+
        AC_CHECK_LIB(c, cap_sandboxed, [
+
                AC_DEFINE(HAVE_CAPSICUM, 1, [Define 1 if you have 'capsicum'.])
+
        ])
+

+
])
+

+

AC_SUBST([LIBELF_LIB])
AC_SUBST([LIBELF_BUNDLED])
AC_SUBST([LIBELF_INCLUDE])
@@ -128,4 +136,4 @@ AC_CONFIG_FILES(Makefile \
		scripts/completion/_pkg.zsh)
AC_CONFIG_HEADERS(pkg_config.h)

-
AC_OUTPUT

\ No newline at end of file
+
AC_OUTPUT
modified libpkg/pkg.h.in
@@ -1552,7 +1552,7 @@ int pkg_old_emit_content(struct pkg *pkg, char **dest);
int pkg_from_old(struct pkg *pkg);
int pkg_to_old(struct pkg *pkg);
int pkg_register_old(struct pkg *pkg);
-
int pkg_sshserve(void);
+
int pkg_sshserve(int fd);

int pkg_repos_total_count(void);
int pkg_repos_activated_count(void);
modified libpkg/ssh.c
@@ -24,6 +24,12 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

+
#ifdef HAVE_CONFIG_H
+
#include "pkg_config.h"
+
#endif
+
#ifdef HAVE_CAPSICUM
+
#include <sys/capability.h>
+
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
@@ -34,11 +40,12 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+
#include <fcntl.h>

#include "pkg.h"

int
-
pkg_sshserve(void)
+
pkg_sshserve(int fd)
{
	struct stat st;
	char *line = NULL;
@@ -47,7 +54,7 @@ pkg_sshserve(void)
	ssize_t linelen;
	time_t mtime = 0;
	const char *errstr;
-
	FILE *f;
+
	int ffd;
	char buf[BUFSIZ];
	char fpath[MAXPATHLEN];
	const char *restricted = NULL;
@@ -72,6 +79,10 @@ pkg_sshserve(void)
		}

		file = line + 4;
+

+
		if (*file == '/')
+
			file++;
+

		age = file;
		while (!isspace(*age)) {
			if (*age == '\0') {
@@ -108,7 +119,12 @@ pkg_sshserve(void)
			continue;
		}

+
#ifdef HAVE_CAPSICUM
+
		if (!cap_sandboxed() && restricted != NULL) {
+
#else
		if (restricted != NULL) {
+
#endif
+
			chdir(restricted);
			file = realpath(file, fpath);
			if (strncmp(file, restricted, strlen(restricted)) != 0) {
				printf("ko: file not found\n");
@@ -116,7 +132,7 @@ pkg_sshserve(void)
			}
		}

-
		if (stat(file, &st) == -1) {
+
		if (fstatat(fd, file, &st, AT_SYMLINK_NOFOLLOW) == -1) {
			printf("ko: file not found\n");
			continue;
		}
@@ -131,13 +147,17 @@ pkg_sshserve(void)
			continue;
		}

+
		if ((ffd = openat(fd, file, O_RDONLY)) == -1) {
+
			printf("ko: file not found\n");
+
			continue;
+
		}
+

		printf("ok: %" PRIdMAX "\n", (intmax_t)st.st_size);
-
		f = fopen(file, "r");

-
		while ((r = fread(buf, 1, sizeof(buf), f)) > 0)
+
		while ((r = read(ffd, buf, sizeof(buf))) > 0)
			fwrite(buf, 1, r, stdout);

-
		fclose(f);
+
		close(ffd);
	}

	free(line);
modified src/ssh.c
@@ -24,8 +24,18 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

+
#ifdef HAVE_CONFIG_H
+
#include "pkg_config.h"
+
#endif
+

+
#ifdef HAVE_CAPSICUM
+
#include <sys/capability.h>
+
#endif
+

#include <sysexits.h>
#include <stdio.h>
+
#include <fcntl.h>
+
#include <err.h>

#include <pkg.h>

@@ -41,12 +51,41 @@ usage_ssh(void)
int
exec_ssh(int argc, char **argv __unused)
{
+
	int fd = AT_FDCWD;
+
	const char *restricted = NULL;
+

+
#ifdef HAVE_CAPSICUM
+
	cap_rights_t rights;
+
#endif
+

	if (argc > 1) {
		usage_ssh();
		return (EX_USAGE);
	}

-
	if (pkg_sshserve() != EPKG_OK)
+
	pkg_config_string(PKG_CONFIG_SSH_RESTRICT_DIR, &restricted);
+
	if (restricted == NULL)
+
		restricted = "/";
+

+
	if ((fd = open(restricted, O_DIRECTORY|O_RDONLY)) < 0) {
+
		warn("Imposssible to open the restricted directory");
+
		return (EX_SOFTWARE);
+
	}
+

+
#ifdef HAVE_CAPSICUM
+
	cap_rights_init(&rights, CAP_READ, CAP_FSTATAT, CAP_FCNTL);
+
	if (cap_rights_limit(fd, &rights) < 0) {
+
		warn("cap_rights_limit() failed");
+
		return (EX_SOFTWARE);
+
	}
+

+
	if (cap_enter() < 0) {
+
		warn("cap_enter() failed");
+
		return (EX_SOFTWARE);
+
	}
+

+
#endif
+
	if (pkg_sshserve(fd) != EPKG_OK)
		return (EX_SOFTWARE);

	return (EX_OK);