From f468008b25c7218a03cc0b327082d4d69d5481ef Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 25 Jul 2017 19:39:15 +0100 Subject: [PATCH 01/26] Make autotools detect Capsicum. Signed-off-by: Edward Tomasz Napierala --- configure.ac | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/configure.ac b/configure.ac index c7c8edef..f0c4cc5d 100644 --- a/configure.ac +++ b/configure.ac @@ -166,6 +166,15 @@ AC_ARG_ENABLE(gregex, fi, want_gregex=yes) +AC_ARG_WITH(capsicum, +[ --with-capsicum Build with Capsicum support], + if test x$withval = xno; then + want_capsicum=no + else + want_capsicum=yes + fi, + want_capsicum=yes) + dnl ** dnl ** just some generic stuff... dnl ** @@ -499,6 +508,18 @@ if test "$want_perl" != "no"; then fi fi +dnl ** +dnl ** check for capsicum +dnl ** + +if test "x$want_capsicum" = "xyes"; then + AC_CHECK_LIB(c, cap_enter, [ + AC_DEFINE(HAVE_CAPSICUM,, Build with Capsicum support) + ], [ + want_capsicum="no, cap_enter not found" + ]) +fi + dnl ** check what we want to build AM_CONDITIONAL(BUILD_TEXTUI, test "$want_textui" = "yes") AM_CONDITIONAL(BUILD_IRSSIBOT, test "$want_irssibot" = "yes") @@ -713,6 +734,7 @@ echo echo "Building with 64bit DCC support .. : $offt_64bit" echo "Building with true color support.. : $want_truecolor" echo "Building with GRegex ............. : $want_gregex" +echo "Building with Capsicum ........... : $want_capsicum" echo echo "If there are any problems, read the INSTALL file." From 56c94570b420dea28b253af5f2c91184423acee1 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 25 Jul 2017 20:15:14 +0100 Subject: [PATCH 02/26] Implement /cap_enter. Signed-off-by: Edward Tomasz Napierala --- configure.ac | 3 ++- src/core/Makefile.am | 5 +++++ src/core/capsicum.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/core/capsicum.h | 7 +++++++ src/core/core.c | 3 +++ 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/core/capsicum.c create mode 100644 src/core/capsicum.h diff --git a/configure.ac b/configure.ac index f0c4cc5d..773f9eea 100644 --- a/configure.ac +++ b/configure.ac @@ -167,7 +167,7 @@ AC_ARG_ENABLE(gregex, want_gregex=yes) AC_ARG_WITH(capsicum, -[ --with-capsicum Build with Capsicum support], +[ --with-capsicum Build with Capsicum support], if test x$withval = xno; then want_capsicum=no else @@ -526,6 +526,7 @@ AM_CONDITIONAL(BUILD_IRSSIBOT, test "$want_irssibot" = "yes") AM_CONDITIONAL(BUILD_IRSSIFUZZER, test "$want_irssifuzzer" = "yes") AM_CONDITIONAL(BUILD_IRSSIPROXY, test "$want_irssiproxy" = "yes") AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no") +AM_CONDITIONAL(HAVE_CAPSICUM, test "x$want_capsicum" = "xyes") AM_CONDITIONAL(USE_GREGEX, test "x$want_gregex" = "xyes") # move LIBS to PROG_LIBS so they're not tried to be used when linking eg. perl libraries diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 91daba3f..f3bc1674 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -56,6 +56,11 @@ libcore_a_SOURCES = \ tls.c \ write-buffer.c +if HAVE_CAPSICUM +libcore_a_SOURCES += \ + capsicum.c +endif + structure_headers = \ channel-rec.h \ channel-setup-rec.h \ diff --git a/src/core/capsicum.c b/src/core/capsicum.c new file mode 100644 index 00000000..702b895a --- /dev/null +++ b/src/core/capsicum.c @@ -0,0 +1,46 @@ +/* + capsicum.c : Capsicum sandboxing support + + Copyright (C) 2017 Edward Tomasz Napierala + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "module.h" +#include "signals.h" +#include "commands.h" + +#include +#include + +static void cmd_cap_enter(void) +{ + int error; + + error = cap_enter(); + if (error != 0) + g_error("cap_enter(2) failed: %s", strerror(errno)); +} + +void capsicum_init(void) +{ + + command_bind("cap_enter", NULL, (SIGNAL_FUNC) cmd_cap_enter); +} + +void capsicum_deinit(void) +{ + command_unbind("cap_enter", (SIGNAL_FUNC) cmd_cap_enter); +} diff --git a/src/core/capsicum.h b/src/core/capsicum.h new file mode 100644 index 00000000..75c70080 --- /dev/null +++ b/src/core/capsicum.h @@ -0,0 +1,7 @@ +#ifndef __CAPSICUM_H +#define __CAPSICUM_H + +void capsicum_init(void); +void capsicum_deinit(void); + +#endif diff --git a/src/core/core.c b/src/core/core.c index bf7cdd6b..72631f91 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -29,6 +29,7 @@ #include "signals.h" #include "settings.h" #include "session.h" +#include "capsicum.h" #include "chat-protocols.h" #include "servers.h" @@ -235,6 +236,7 @@ void core_init(void) commands_init(); nickmatch_cache_init(); session_init(); + capsicum_init(); chat_protocols_init(); chatnets_init(); @@ -292,6 +294,7 @@ void core_deinit(void) chatnets_deinit(); chat_protocols_deinit(); + capsicum_deinit(); session_deinit(); nickmatch_cache_deinit(); commands_deinit(); From d5d45c29b8e00c304a6b6656983cafee84fe6bc8 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 26 Jul 2017 01:00:25 +0100 Subject: [PATCH 03/26] Add capability mode error/success messages. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 24 +++++++++++- src/fe-common/core/Makefile.am | 5 +++ src/fe-common/core/fe-capsicum.c | 60 +++++++++++++++++++++++++++++ src/fe-common/core/fe-capsicum.h | 7 ++++ src/fe-common/core/fe-common-core.c | 3 ++ src/fe-common/core/module-formats.c | 3 ++ src/fe-common/core/module-formats.h | 3 ++ 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 src/fe-common/core/fe-capsicum.c create mode 100644 src/fe-common/core/fe-capsicum.h diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 702b895a..eb30fef3 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -30,17 +30,37 @@ static void cmd_cap_enter(void) int error; error = cap_enter(); - if (error != 0) - g_error("cap_enter(2) failed: %s", strerror(errno)); + if (error != 0) { + signal_emit("capability mode failed", 1, strerror(errno)); + } else { + signal_emit("capability mode enabled", 0); + } +} + +static void cmd_cap_getmode(void) +{ + u_int mode; + int error; + + error = cap_getmode(&mode); + if (error != 0) { + signal_emit("capability mode failed", 1, strerror(errno)); + } else if (mode == 0) { + signal_emit("capability mode disabled", 0); + } else { + signal_emit("capability mode enabled", 0); + } } void capsicum_init(void) { command_bind("cap_enter", NULL, (SIGNAL_FUNC) cmd_cap_enter); + command_bind("cap_getmode", NULL, (SIGNAL_FUNC) cmd_cap_getmode); } void capsicum_deinit(void) { command_unbind("cap_enter", (SIGNAL_FUNC) cmd_cap_enter); + command_unbind("cap_getmode", (SIGNAL_FUNC) cmd_cap_getmode); } diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index 6efff411..08e41520 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -38,6 +38,11 @@ libfe_common_core_a_SOURCES = \ windows-layout.c \ fe-windows.c +if HAVE_CAPSICUM +libfe_common_core_a_SOURCES += \ + fe-capsicum.c +endif + pkginc_fe_common_coredir=$(pkgincludedir)/src/fe-common/core pkginc_fe_common_core_HEADERS = \ command-history.h \ diff --git a/src/fe-common/core/fe-capsicum.c b/src/fe-common/core/fe-capsicum.c new file mode 100644 index 00000000..5816b223 --- /dev/null +++ b/src/fe-common/core/fe-capsicum.c @@ -0,0 +1,60 @@ +/* + fe-capsicum.c : irssi + + Copyright (C) 2017 Edward Tomasz Napierala + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "printtext.h" + +#include "levels.h" +#include "servers.h" + +static void capability_mode_enabled(void) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CAPSICUM_ENABLED); +} + +static void capability_mode_disabled(void) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CAPSICUM_DISABLED); +} + +static void capability_mode_failed(gchar *msg) +{ + + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CAPSICUM_FAILED, msg); +} + +void fe_capsicum_init(void) +{ + + signal_add("capability mode enabled", (SIGNAL_FUNC) capability_mode_enabled); + signal_add("capability mode disabled", (SIGNAL_FUNC) capability_mode_disabled); + signal_add("capability mode failed", (SIGNAL_FUNC) capability_mode_failed); +} + +void fe_capsicum_deinit(void) +{ + signal_remove("capability mode enabled", (SIGNAL_FUNC) capability_mode_enabled); + signal_remove("capability mode disabled", (SIGNAL_FUNC) capability_mode_disabled); + signal_remove("capability mode failed", (SIGNAL_FUNC) capability_mode_failed); +} diff --git a/src/fe-common/core/fe-capsicum.h b/src/fe-common/core/fe-capsicum.h new file mode 100644 index 00000000..a7cb743b --- /dev/null +++ b/src/fe-common/core/fe-capsicum.h @@ -0,0 +1,7 @@ +#ifndef __FE_CAPSICUM_H +#define __FE_CAPSICUM_H + +void fe_capsicum_init(void); +void fe_capsicum_deinit(void); + +#endif diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 512fc84c..a0388827 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -32,6 +32,7 @@ #include "special-vars.h" #include "fe-core-commands.h" #include "fe-queries.h" +#include "fe-capsicum.h" #include "hilight-text.h" #include "command-history.h" #include "completion.h" @@ -179,6 +180,7 @@ void fe_common_core_init(void) fe_server_init(); fe_settings_init(); fe_tls_init(); + fe_capsicum_init(); windows_init(); window_activity_init(); window_commands_init(); @@ -221,6 +223,7 @@ void fe_common_core_deinit(void) fe_server_deinit(); fe_settings_deinit(); fe_tls_deinit(); + fe_capsicum_deinit(); windows_deinit(); window_activity_deinit(); window_commands_deinit(); diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index da9705be..eb0ddb61 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -290,6 +290,9 @@ FORMAT_REC fecommon_core_formats[] = { { "completion_header", "%#Key Value Auto", 0 }, { "completion_line", "%#$[10]0 $[!40]1 $2", 3, { 0, 0, 0 } }, { "completion_footer", "", 0 }, + { "capsicum_enabled", "Capability mode enabled", 0 }, + { "capsicum_disabled", "Capability mode not enabled", 0 }, + { "capsicum_failed", "Capability mode failed: $0", 1, { 0 } }, /* ---- */ { NULL, "TLS", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index a9ed28c5..4e2f72d9 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -255,6 +255,9 @@ enum { TXT_COMPLETION_HEADER, TXT_COMPLETION_LINE, TXT_COMPLETION_FOOTER, + TXT_CAPSICUM_ENABLED, + TXT_CAPSICUM_DISABLED, + TXT_CAPSICUM_FAILED, TLS_FILL_15, From 3200c381dbcb02e99c7667bd955c90ee859d15a0 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 26 Jul 2017 02:11:46 +0100 Subject: [PATCH 04/26] Rename to "/capability enter" and "/capability status". Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index eb30fef3..69a379e2 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -25,7 +25,12 @@ #include #include -static void cmd_cap_enter(void) +static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) +{ + command_runsub("capsicum", data, server, item); +} + +static void cmd_capsicum_enter(void) { int error; @@ -37,7 +42,7 @@ static void cmd_cap_enter(void) } } -static void cmd_cap_getmode(void) +static void cmd_capsicum_status(void) { u_int mode; int error; @@ -55,12 +60,14 @@ static void cmd_cap_getmode(void) void capsicum_init(void) { - command_bind("cap_enter", NULL, (SIGNAL_FUNC) cmd_cap_enter); - command_bind("cap_getmode", NULL, (SIGNAL_FUNC) cmd_cap_getmode); + command_bind("capsicum", NULL, (SIGNAL_FUNC) cmd_capsicum); + command_bind("capsicum enter", NULL, (SIGNAL_FUNC) cmd_capsicum_enter); + command_bind("capsicum status", NULL, (SIGNAL_FUNC) cmd_capsicum_status); } void capsicum_deinit(void) { - command_unbind("cap_enter", (SIGNAL_FUNC) cmd_cap_enter); - command_unbind("cap_getmode", (SIGNAL_FUNC) cmd_cap_getmode); + command_unbind("capsicum", (SIGNAL_FUNC) cmd_capsicum); + command_unbind("capsicum enter", (SIGNAL_FUNC) cmd_capsicum_enter); + command_unbind("capsicum status", (SIGNAL_FUNC) cmd_capsicum_status); } From cec68557aa436b4f16505d2095af02f83d154eda Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 27 Jul 2017 14:20:47 +0100 Subject: [PATCH 05/26] /connect works - although only with IP addresses. --- configure.ac | 7 ++- src/core/capsicum.c | 126 ++++++++++++++++++++++++++++++++++++++++++++ src/core/capsicum.h | 3 ++ src/core/network.c | 33 ++++++++++-- src/core/network.h | 2 + 5 files changed, 165 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 773f9eea..9c026c5d 100644 --- a/configure.ac +++ b/configure.ac @@ -514,7 +514,12 @@ dnl ** if test "x$want_capsicum" = "xyes"; then AC_CHECK_LIB(c, cap_enter, [ - AC_DEFINE(HAVE_CAPSICUM,, Build with Capsicum support) + AC_CHECK_LIB(nv, nvlist_create, [ + AC_DEFINE(HAVE_CAPSICUM,, Build with Capsicum support) + LIBS="$LIBS -lnv" + ], [ + want_capsicum="no, nvlist_create not found" + ]) ], [ want_capsicum="no, cap_enter not found" ]) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 69a379e2..19ca858e 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -19,21 +19,147 @@ */ #include "module.h" +#include "network.h" #include "signals.h" #include "commands.h" +#include #include +#include +#include +#include #include +static int symbiontfds[2]; + +gboolean capsicum_enabled(void) +{ + u_int mode; + int error; + + error = cap_getmode(&mode); + if (error != 0) + return FALSE; + + if (mode == 0) + return FALSE; + + return TRUE; +} + +int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +{ + nvlist_t *nvl; + int error, saved_errno, sock; + + /* Send request to the symbiont. */ + nvl = nvlist_create(0); + nvlist_add_binary(nvl, "ip", ip, sizeof(*ip)); + nvlist_add_number(nvl, "port", port); + if (my_ip != NULL) { + /* nvlist_add_binary(3) can't handle NULL values. */ + nvlist_add_binary(nvl, "my_ip", my_ip, sizeof(*my_ip)); + } + error = nvlist_send(symbiontfds[1], nvl); + nvlist_destroy(nvl); + if (error != 0) { + g_warning("nvlist_send: %s", strerror(errno)); + return -1; + } + + /* Receive response. */ + nvl = nvlist_recv(symbiontfds[1], 0); + if (nvl == NULL) { + g_warning("nvlist_recv: %s", strerror(errno)); + return -1; + } + if (nvlist_exists_descriptor(nvl, "sock")) { + sock = nvlist_take_descriptor(nvl, "sock"); + } else { + sock = -1; + } + saved_errno = nvlist_get_number(nvl, "errno"); + nvlist_destroy(nvl); + errno = saved_errno; + + return sock; +} + static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) { command_runsub("capsicum", data, server, item); } +static int start_symbiont(void) +{ + pid_t pid; + nvlist_t *nvl; + IPADDR *ip, *my_ip; + int childfd, error, port, saved_errno, sock; + + error = socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, symbiontfds); + if (error != 0) { + g_warning("socketpair: %s", strerror(errno)); + return 1; + } + + pid = pdfork(&childfd, PD_CLOEXEC); + if (pid < 0) { + g_warning("pdfork: %s", strerror(errno)); + return 1; + } + + if (pid > 0) { + close(symbiontfds[0]); + return 0; + } + + /* We're the child, running outside the Capsicum sandbox. */ + setproctitle("capsicum symbiont"); + close(symbiontfds[1]); + close(0); + close(1); + close(2); + for (;;) { + /* Receive parameters from the main irssi process. */ + nvl = nvlist_recv(symbiontfds[0], 0); + if (nvl == NULL) + exit(1); + ip = nvlist_get_binary(nvl, "ip", NULL); + port = (int)nvlist_get_number(nvl, "port"); + if (nvlist_exists(nvl, "my_ip")) + my_ip = nvlist_get_binary(nvl, "my_ip", NULL); + else + my_ip = NULL; + + /* Connect. */ + sock = net_connect_ip_handle(ip, port, my_ip); + saved_errno = errno; + + /* Send back the socket fd. */ + nvlist_destroy(nvl); + nvl = nvlist_create(0); + + if (sock != -1) + nvlist_move_descriptor(nvl, "sock", sock); + nvlist_add_number(nvl, "errno", saved_errno); + error = nvlist_send(symbiontfds[0], nvl); + if (error != 0) + exit(1); + nvlist_destroy(nvl); + } +} + static void cmd_capsicum_enter(void) { int error; + error = start_symbiont(); + if (error != 0) { + signal_emit("capability mode failed", 1, strerror(errno)); + return; + } + error = cap_enter(); if (error != 0) { signal_emit("capability mode failed", 1, strerror(errno)); diff --git a/src/core/capsicum.h b/src/core/capsicum.h index 75c70080..f8cec28e 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -1,6 +1,9 @@ #ifndef __CAPSICUM_H #define __CAPSICUM_H +gboolean capsicum_enabled(void); +int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); + void capsicum_init(void); void capsicum_deinit(void); diff --git a/src/core/network.c b/src/core/network.c index 3e1b7c70..b182d19f 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -20,6 +20,9 @@ #include "module.h" #include "network.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include @@ -144,8 +147,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) return net_connect_ip(ip, port, my_ip); } -/* Connect to socket with ip address */ -GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +int net_connect_ip_handle(IPADDR *ip, int port, IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; @@ -161,7 +163,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) handle = socket(ip->family, SOCK_STREAM, 0); if (handle == -1) - return NULL; + return -1; /* set socket options */ fcntl(handle, F_SETFL, O_NONBLOCK); @@ -176,7 +178,7 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) close(handle); errno = old_errno; - return NULL; + return -1; } } @@ -190,9 +192,30 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) int old_errno = errno; close(handle); errno = old_errno; - return NULL; + return -1; } + return handle; +} + + +/* Connect to socket with ip address */ +GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) +{ + int handle = -1; + +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + handle = capsicum_net_connect_ip(ip, port, my_ip); + else + handle = net_connect_ip_handle(ip, port, my_ip); +#else + handle = net_connect_ip_handle(ip, port, my_ip); +#endif + + if (handle == -1) + return (NULL); + return g_io_channel_new(handle); } diff --git a/src/core/network.h b/src/core/network.h index 8757f78c..5ccacc0d 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -36,6 +36,8 @@ GIOChannel *g_io_channel_new(int handle); /* returns 1 if IPADDRs are the same */ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); +int net_connect_ip_handle(IPADDR *ip, int port, IPADDR *my_ip); + /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) G_GNUC_DEPRECATED; /* Connect to socket with ip address and SSL*/ From 925240155e5c0c20569bcb5fafe4d3047055768a Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 27 Jul 2017 14:56:35 +0100 Subject: [PATCH 06/26] Config file support for "capsicum" parameter. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 19ca858e..7674ca4d 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -19,9 +19,10 @@ */ #include "module.h" -#include "network.h" -#include "signals.h" #include "commands.h" +#include "network.h" +#include "settings.h" +#include "signals.h" #include #include @@ -183,8 +184,17 @@ static void cmd_capsicum_status(void) } } +void sig_init_finished(void) +{ + if (settings_get_bool("capsicum")) + cmd_capsicum_enter(); +} + void capsicum_init(void) { + settings_add_bool("misc", "capsicum", FALSE); + + signal_add("irssi init finished", (SIGNAL_FUNC) sig_init_finished); command_bind("capsicum", NULL, (SIGNAL_FUNC) cmd_capsicum); command_bind("capsicum enter", NULL, (SIGNAL_FUNC) cmd_capsicum_enter); @@ -193,6 +203,8 @@ void capsicum_init(void) void capsicum_deinit(void) { + signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished); + command_unbind("capsicum", (SIGNAL_FUNC) cmd_capsicum); command_unbind("capsicum enter", (SIGNAL_FUNC) cmd_capsicum_enter); command_unbind("capsicum status", (SIGNAL_FUNC) cmd_capsicum_status); From f4546be7ecb8a0801fb0d30415586c15d721494a Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 27 Jul 2017 15:35:14 +0100 Subject: [PATCH 07/26] Reorder functions. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 7674ca4d..a0375077 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -86,11 +86,6 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) return sock; } -static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) -{ - command_runsub("capsicum", data, server, item); -} - static int start_symbiont(void) { pid_t pid; @@ -151,6 +146,11 @@ static int start_symbiont(void) } } +static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) +{ + command_runsub("capsicum", data, server, item); +} + static void cmd_capsicum_enter(void) { int error; From 509eca76f0755e94b5981f464f9f9a882499180a Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 28 Jul 2017 02:21:40 +0100 Subject: [PATCH 08/26] Make DNS work in capability mode. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 173 ++++++++++++++++++++++++++++++++++---------- src/core/capsicum.h | 1 + src/core/network.c | 5 ++ 3 files changed, 142 insertions(+), 37 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index a0375077..99f7ff0f 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -31,6 +31,9 @@ #include #include +#define OPCODE_CONNECT 1 +#define OPCODE_GETHOSTBYNAME 2 + static int symbiontfds[2]; gboolean capsicum_enabled(void) @@ -55,6 +58,7 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) /* Send request to the symbiont. */ nvl = nvlist_create(0); + nvlist_add_number(nvl, "opcode", OPCODE_CONNECT); nvlist_add_binary(nvl, "ip", ip, sizeof(*ip)); nvlist_add_number(nvl, "port", port); if (my_ip != NULL) { @@ -86,12 +90,139 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) return sock; } +int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) +{ + nvlist_t *nvl; + IPADDR *received_ip4, *received_ip6; + int error, ret, saved_errno; + + /* Send request to the symbiont. */ + nvl = nvlist_create(0); + nvlist_add_number(nvl, "opcode", OPCODE_GETHOSTBYNAME); + nvlist_add_string(nvl, "addr", addr); + error = nvlist_send(symbiontfds[1], nvl); + nvlist_destroy(nvl); + if (error != 0) { + g_warning("nvlist_send: %s", strerror(errno)); + return -1; + } + + /* Receive response. */ + nvl = nvlist_recv(symbiontfds[1], 0); + if (nvl == NULL) { + g_warning("nvlist_recv: %s", strerror(errno)); + return -1; + } + + received_ip4 = nvlist_get_binary(nvl, "ip4", NULL); + received_ip6 = nvlist_get_binary(nvl, "ip6", NULL); + memcpy(ip4, received_ip4, sizeof(*ip4)); + memcpy(ip6, received_ip6, sizeof(*ip6)); + + ret = nvlist_get_number(nvl, "ret"); + saved_errno = nvlist_get_number(nvl, "errno"); + nvlist_destroy(nvl); + errno = saved_errno; + + return ret; +} + +nvlist_t *symbiont_connect(const nvlist_t *request) +{ + nvlist_t *response; + IPADDR *ip, *my_ip; + int port, saved_errno, sock; + + ip = nvlist_get_binary(request, "ip", NULL); + port = (int)nvlist_get_number(request, "port"); + if (nvlist_exists(request, "my_ip")) + my_ip = nvlist_get_binary(request, "my_ip", NULL); + else + my_ip = NULL; + + /* Connect. */ + sock = net_connect_ip_handle(ip, port, my_ip); + saved_errno = errno; + + /* Send back the socket fd. */ + response = nvlist_create(0); + + if (sock != -1) + nvlist_move_descriptor(response, "sock", sock); + nvlist_add_number(response, "errno", saved_errno); + + return (response); +} + +nvlist_t *symbiont_gethostbyname(const nvlist_t *request) +{ + nvlist_t *response; + IPADDR ip4, ip6; + const char *addr; + int ret, saved_errno; + + addr = nvlist_get_string(request, "addr"); + + /* Connect. */ + ret = net_gethostbyname(addr, &ip4, &ip6); + saved_errno = errno; + + /* Send back the IPs. */ + response = nvlist_create(0); + + nvlist_add_number(response, "ret", ret); + nvlist_add_number(response, "errno", saved_errno); + nvlist_add_binary(response, "ip4", &ip4, sizeof(ip4)); + nvlist_add_binary(response, "ip6", &ip6, sizeof(ip6)); + + return (response); +} + +/* + * Child process, running outside the Capsicum sandbox. + */ +_Noreturn static void symbiont(void) +{ + nvlist_t *request, *response; + int error, opcode; + + setproctitle("capsicum symbiont"); + close(symbiontfds[1]); + close(0); + close(1); + close(2); + + for (;;) { + /* Receive parameters from the main irssi process. */ + request = nvlist_recv(symbiontfds[0], 0); + if (request == NULL) + exit(1); + + opcode = nvlist_get_number(request, "opcode"); + switch (opcode) { + case OPCODE_CONNECT: + response = symbiont_connect(request); + break; + case OPCODE_GETHOSTBYNAME: + response = symbiont_gethostbyname(request); + break; + default: + exit(1); + } + + /* Send back the response. */ + error = nvlist_send(symbiontfds[0], response); + if (error != 0) + exit(1); + nvlist_destroy(request); + nvlist_destroy(response); + } +} + static int start_symbiont(void) { + int childfd, error; pid_t pid; - nvlist_t *nvl; - IPADDR *ip, *my_ip; - int childfd, error, port, saved_errno, sock; error = socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, symbiontfds); if (error != 0) { @@ -110,40 +241,8 @@ static int start_symbiont(void) return 0; } - /* We're the child, running outside the Capsicum sandbox. */ - setproctitle("capsicum symbiont"); - close(symbiontfds[1]); - close(0); - close(1); - close(2); - for (;;) { - /* Receive parameters from the main irssi process. */ - nvl = nvlist_recv(symbiontfds[0], 0); - if (nvl == NULL) - exit(1); - ip = nvlist_get_binary(nvl, "ip", NULL); - port = (int)nvlist_get_number(nvl, "port"); - if (nvlist_exists(nvl, "my_ip")) - my_ip = nvlist_get_binary(nvl, "my_ip", NULL); - else - my_ip = NULL; - - /* Connect. */ - sock = net_connect_ip_handle(ip, port, my_ip); - saved_errno = errno; - - /* Send back the socket fd. */ - nvlist_destroy(nvl); - nvl = nvlist_create(0); - - if (sock != -1) - nvlist_move_descriptor(nvl, "sock", sock); - nvlist_add_number(nvl, "errno", saved_errno); - error = nvlist_send(symbiontfds[0], nvl); - if (error != 0) - exit(1); - nvlist_destroy(nvl); - } + symbiont(); + /* NOTREACHED */ } static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) diff --git a/src/core/capsicum.h b/src/core/capsicum.h index f8cec28e..2733c1ea 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -3,6 +3,7 @@ gboolean capsicum_enabled(void); int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); +int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); void capsicum_init(void); void capsicum_deinit(void); diff --git a/src/core/network.c b/src/core/network.c index b182d19f..2954af54 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -406,6 +406,11 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) struct addrinfo hints, *ai, *ailist; int ret, count_v4, count_v6, use_v4, use_v6; +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + return (capsicum_net_gethostbyname(addr, ip4, ip6)); +#endif + g_return_val_if_fail(addr != NULL, -1); memset(ip4, 0, sizeof(IPADDR)); From 1f57ceec4c4e7c3d42f341921e36fe4aab612e57 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 28 Jul 2017 18:10:45 +0100 Subject: [PATCH 09/26] Prevent the user from calling "/capsicum enter" twice. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 99f7ff0f..f44b326d 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -252,8 +252,15 @@ static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) static void cmd_capsicum_enter(void) { + u_int mode; int error; + error = cap_getmode(&mode); + if (error == 0 && mode != 0) { + g_warning("Already in capability mode"); + return; + } + error = start_symbiont(); if (error != 0) { signal_emit("capability mode failed", 1, strerror(errno)); From 939371aa1dfdbf11fe98648e1eafc4c95e80bb9e Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 28 Jul 2017 18:44:18 +0100 Subject: [PATCH 10/26] Fix warnings. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 4 ++-- src/core/network.c | 2 +- src/core/network.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index f44b326d..5a59adcd 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -93,7 +93,7 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) { nvlist_t *nvl; - IPADDR *received_ip4, *received_ip6; + const IPADDR *received_ip4, *received_ip6; int error, ret, saved_errno; /* Send request to the symbiont. */ @@ -130,7 +130,7 @@ int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) nvlist_t *symbiont_connect(const nvlist_t *request) { nvlist_t *response; - IPADDR *ip, *my_ip; + const IPADDR *ip, *my_ip; int port, saved_errno, sock; ip = nvlist_get_binary(request, "ip", NULL); diff --git a/src/core/network.c b/src/core/network.c index 2954af54..01e56eb5 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -147,7 +147,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) return net_connect_ip(ip, port, my_ip); } -int net_connect_ip_handle(IPADDR *ip, int port, IPADDR *my_ip) +int net_connect_ip_handle(const IPADDR *ip, int port, const IPADDR *my_ip) { union sockaddr_union so; int handle, ret, opt = 1; diff --git a/src/core/network.h b/src/core/network.h index 5ccacc0d..d1582a2e 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -36,7 +36,7 @@ GIOChannel *g_io_channel_new(int handle); /* returns 1 if IPADDRs are the same */ int net_ip_compare(IPADDR *ip1, IPADDR *ip2); -int net_connect_ip_handle(IPADDR *ip, int port, IPADDR *my_ip); +int net_connect_ip_handle(const IPADDR *ip, int port, const IPADDR *my_ip); /* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) G_GNUC_DEPRECATED; From 241dd66ac11d54b37c671cd56f1320fe5b83803d Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 28 Jul 2017 05:08:34 +0100 Subject: [PATCH 11/26] Working /log and /rawlog. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 33 +++++++++++++++++++++++++++++++++ src/core/capsicum.h | 1 + src/core/log.c | 15 ++++++++++++++- src/core/log.h | 2 ++ src/core/network.c | 1 - src/core/rawlog.c | 17 +++++++++++++++-- 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 5a59adcd..6667276c 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -20,6 +20,8 @@ #include "module.h" #include "commands.h" +#include "log.h" +#include "misc.h" #include "network.h" #include "settings.h" #include "signals.h" @@ -34,6 +36,9 @@ #define OPCODE_CONNECT 1 #define OPCODE_GETHOSTBYNAME 2 +static char *irclogs_path; +static size_t irclogs_path_len; +static int irclogs_fd; static int symbiontfds[2]; gboolean capsicum_enabled(void) @@ -127,6 +132,23 @@ int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) return ret; } +int capsicum_open(const char *path, int flags, int mode) +{ + int fd; + + /* +1 is for slash separating irclogs_path and the rest. */ + if (strlen(path) > irclogs_path_len + 1 && strncmp(path, irclogs_path, irclogs_path_len) == 0) { + fd = openat(irclogs_fd, path + irclogs_path_len + 1, flags, mode); + } else { + fd = open(path, flags, mode); + } + + if (fd < 0 && (errno == ENOTCAPABLE || errno == ECAPMODE)) + g_warning("File system access restricted to %s due to capability mode", irclogs_path); + + return (fd); +} + nvlist_t *symbiont_connect(const nvlist_t *request) { nvlist_t *response; @@ -261,6 +283,16 @@ static void cmd_capsicum_enter(void) return; } + irclogs_path = convert_home(settings_get_str("capsicum_irclogs_path")); + g_mkdir_with_parents(irclogs_path, log_dir_create_mode); + irclogs_path_len = strlen(irclogs_path); + irclogs_fd = open(irclogs_path, O_DIRECTORY | O_CLOEXEC); + if (irclogs_fd < 0) { + g_warning("Unable to open %s: %s", irclogs_path, strerror(errno)); + signal_emit("capability mode failed", 1, strerror(errno)); + return; + } + error = start_symbiont(); if (error != 0) { signal_emit("capability mode failed", 1, strerror(errno)); @@ -299,6 +331,7 @@ void sig_init_finished(void) void capsicum_init(void) { settings_add_bool("misc", "capsicum", FALSE); + settings_add_str("misc", "capsicum_irclogs_path", "~/irclogs"); signal_add("irssi init finished", (SIGNAL_FUNC) sig_init_finished); diff --git a/src/core/capsicum.h b/src/core/capsicum.h index 2733c1ea..ca35fd05 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -4,6 +4,7 @@ gboolean capsicum_enabled(void); int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); +int capsicum_open(const char *path, int flags, int mode); void capsicum_init(void); void capsicum_deinit(void); diff --git a/src/core/log.c b/src/core/log.c index cee1dab5..00686bee 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -26,6 +26,9 @@ #include "servers.h" #include "log.h" #include "write-buffer.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "lib-config/iconfig.h" #include "settings.h" @@ -73,6 +76,16 @@ static void log_write_timestamp(int handle, const char *format, if (text != NULL) write_buffer(handle, text, strlen(text)); } +static int log_open_wrapper(const char *path, int flags, int mode) +{ +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + return capsicum_open(path, flags, mode); +#endif + + return open(path, flags, mode); +} + static char *log_filename(LOG_REC *log) { char *str, fname[1024]; @@ -119,7 +132,7 @@ int log_start_logging(LOG_REC *log) } log->handle = log->real_fname == NULL ? -1 : - open(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, + log_open_wrapper(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); if (log->handle == -1) { signal_emit("log create failed", 1, log); diff --git a/src/core/log.h b/src/core/log.h index 5a07859b..52660bb9 100644 --- a/src/core/log.h +++ b/src/core/log.h @@ -38,6 +38,8 @@ extern GSList *logs; extern int log_file_create_mode; extern int log_dir_create_mode; +extern int log_dir_create_mode; + /* Create log record - you still need to call log_update() to actually add it into log list */ LOG_REC *log_create_rec(const char *fname, int level); diff --git a/src/core/network.c b/src/core/network.c index 01e56eb5..4494dbc6 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -198,7 +198,6 @@ int net_connect_ip_handle(const IPADDR *ip, int port, const IPADDR *my_ip) return handle; } - /* Connect to socket with ip address */ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) { diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 2ec155fa..5df02981 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -27,12 +27,25 @@ #include "misc.h" #include "write-buffer.h" #include "settings.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "servers.h" static int rawlog_lines; static int signal_rawlog; +static int rawlog_open_wrapper(const char *path, int flags, int mode) +{ +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + return capsicum_open(path, flags, mode); +#endif + + return open(path, flags, mode); +} + RAWLOG_REC *rawlog_create(void) { RAWLOG_REC *rec; @@ -126,7 +139,7 @@ void rawlog_open(RAWLOG_REC *rawlog, const char *fname) return; path = convert_home(fname); - rawlog->handle = open(path, O_WRONLY | O_APPEND | O_CREAT, + rawlog->handle = rawlog_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); g_free(path); @@ -158,7 +171,7 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) g_free(dir); path = convert_home(fname); - f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); + f = rawlog_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); g_free(path); if (f < 0) { From e777ae986d64863a444132885b160ab2e9c7458e Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 10:32:24 +0100 Subject: [PATCH 12/26] Working autolog. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 51 ++++++++++++++++++++++++++++++++++--- src/core/capsicum.h | 1 + src/core/log.c | 7 +++++ src/core/rawlog.c | 9 ++++++- src/fe-common/core/fe-log.c | 10 ++++++++ 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 6667276c..c554fcf7 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -136,19 +136,62 @@ int capsicum_open(const char *path, int flags, int mode) { int fd; - /* +1 is for slash separating irclogs_path and the rest. */ - if (strlen(path) > irclogs_path_len + 1 && strncmp(path, irclogs_path, irclogs_path_len) == 0) { - fd = openat(irclogs_fd, path + irclogs_path_len + 1, flags, mode); + /* +1 is for the slash separating irclogs_path and the rest. */ + if (strlen(path) > irclogs_path_len + 1 && + strncmp(path, irclogs_path, irclogs_path_len) == 0) { + fd = openat(irclogs_fd, path + irclogs_path_len + 1, + flags, mode); } else { fd = open(path, flags, mode); } if (fd < 0 && (errno == ENOTCAPABLE || errno == ECAPMODE)) - g_warning("File system access restricted to %s due to capability mode", irclogs_path); + g_warning("File system access restricted to %s " + "due to capability mode", irclogs_path); return (fd); } +void capsicum_mkdir_with_parents(const char *path, int mode) +{ + char *component, *copy, *tofree; + int error, fd, newfd; + + /* +1 is for the slash separating irclogs_path and the rest. */ + if (strlen(path) <= irclogs_path_len + 1 || + strncmp(path, irclogs_path, irclogs_path_len) != 0) { + g_warning("Cannot create %s: file system access restricted " + "to %s due to capability mode", path, irclogs_path); + return; + } + + copy = tofree = g_strdup(path + irclogs_path_len + 1); + fd = irclogs_fd; + for (;;) { + component = strsep(©, "/"); + if (component == NULL) + break; + error = mkdirat(fd, component, mode); + if (error != 0 && errno != EEXIST) { + g_warning("cannot create %s: %s", + component, strerror(errno)); + break; + } + newfd = openat(fd, component, O_DIRECTORY); + if (newfd < 0) { + g_warning("cannot open %s: %s", + component, strerror(errno)); + break; + } + if (fd != irclogs_fd) + close(fd); + fd = newfd; + } + g_free(tofree); + if (fd != irclogs_fd) + close(fd); +} + nvlist_t *symbiont_connect(const nvlist_t *request) { nvlist_t *response; diff --git a/src/core/capsicum.h b/src/core/capsicum.h index ca35fd05..1eb56402 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -5,6 +5,7 @@ gboolean capsicum_enabled(void); int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); int capsicum_open(const char *path, int flags, int mode); +void capsicum_mkdir_with_parents(const char *path, int mode); void capsicum_init(void); void capsicum_deinit(void); diff --git a/src/core/log.c b/src/core/log.c index 00686bee..9394263f 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -127,7 +127,14 @@ int log_start_logging(LOG_REC *log) /* path may contain variables (%time, $vars), make sure the directory is created */ dir = g_path_get_dirname(log->real_fname); +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + capsicum_mkdir_with_parents(dir, log_dir_create_mode); + else + g_mkdir_with_parents(dir, log_dir_create_mode); +#else g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); } diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 5df02981..dd86af7c 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -167,7 +167,14 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) int f; dir = g_path_get_dirname(fname); - g_mkdir_with_parents(dir, log_dir_create_mode); +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + capsicum_mkdir_with_parents(dir, log_dir_create_mode); + else + g_mkdir_with_parents(dir, log_dir_create_mode); +#else + g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); path = convert_home(fname); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 37b29990..deb70991 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -30,6 +30,9 @@ #include "special-vars.h" #include "settings.h" #include "lib-config/iconfig.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "fe-windows.h" #include "window-items.h" @@ -451,7 +454,14 @@ static void autolog_open(SERVER_REC *server, const char *server_tag, log_item_add(log, LOG_ITEM_TARGET, target, server_tag); dir = g_path_get_dirname(log->real_fname); +#ifdef HAVE_CAPSICUM + if (capsicum_enabled()) + capsicum_mkdir_with_parents(dir, log_dir_create_mode); + else + g_mkdir_with_parents(dir, log_dir_create_mode); +#else g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); log->temp = TRUE; From c00d4753aee732b5a815f12dda3c9fced41ef1f5 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 11:41:56 +0100 Subject: [PATCH 13/26] Restrict port range available in capability mode. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index c554fcf7..e87704dd 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -40,6 +40,8 @@ static char *irclogs_path; static size_t irclogs_path_len; static int irclogs_fd; static int symbiontfds[2]; +static int port_min; +static int port_max; gboolean capsicum_enabled(void) { @@ -90,6 +92,13 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip) } saved_errno = nvlist_get_number(nvl, "errno"); nvlist_destroy(nvl); + + if (sock == -1 && (port < port_min || port > port_max)) { + g_warning("Access restricted to ports between %d and %d " + "due to capability mode", + port_min, port_max); + } + errno = saved_errno; return sock; @@ -205,9 +214,19 @@ nvlist_t *symbiont_connect(const nvlist_t *request) else my_ip = NULL; - /* Connect. */ - sock = net_connect_ip_handle(ip, port, my_ip); - saved_errno = errno; + /* + * Check if the port is in allowed range. This is to minimize + * the chance of the attacker rooting another system in case of + * compromise. + */ + if (port < port_min || port > port_max) { + sock = -1; + saved_errno = EPERM; + } else { + /* Connect. */ + sock = net_connect_ip_handle(ip, port, my_ip); + saved_errno = errno; + } /* Send back the socket fd. */ response = nvlist_create(0); @@ -326,6 +345,9 @@ static void cmd_capsicum_enter(void) return; } + port_min = settings_get_int("capsicum_port_min"); + port_max = settings_get_int("capsicum_port_max"); + irclogs_path = convert_home(settings_get_str("capsicum_irclogs_path")); g_mkdir_with_parents(irclogs_path, log_dir_create_mode); irclogs_path_len = strlen(irclogs_path); @@ -375,6 +397,8 @@ void capsicum_init(void) { settings_add_bool("misc", "capsicum", FALSE); settings_add_str("misc", "capsicum_irclogs_path", "~/irclogs"); + settings_add_int("misc", "capsicum_port_min", 6667); + settings_add_int("misc", "capsicum_port_max", 6697); signal_add("irssi init finished", (SIGNAL_FUNC) sig_init_finished); From 12e2c46d6a778f131c1ca6a7134af1cd5e722dbe Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 12:28:49 +0100 Subject: [PATCH 14/26] Add wrappers to reduce #ifdefs. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 17 +++++++++++++++++ src/core/capsicum.h | 12 +++++++++++- src/core/log.c | 23 ++--------------------- src/core/rawlog.c | 29 ++++++----------------------- src/fe-common/core/fe-log.c | 11 +---------- 5 files changed, 37 insertions(+), 55 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index e87704dd..99a4e795 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -161,6 +161,14 @@ int capsicum_open(const char *path, int flags, int mode) return (fd); } +int capsicum_open_wrapper(const char *path, int flags, int mode) +{ + if (capsicum_enabled()) { + return capsicum_open(path, flags, mode); + } + return open(path, flags, mode); +} + void capsicum_mkdir_with_parents(const char *path, int mode) { char *component, *copy, *tofree; @@ -201,6 +209,15 @@ void capsicum_mkdir_with_parents(const char *path, int mode) close(fd); } +void capsicum_mkdir_with_parents_wrapper(const char *path, int mode) +{ + if (capsicum_enabled()) { + capsicum_mkdir_with_parents(path, mode); + return; + } + g_mkdir_with_parents(path, mode); +} + nvlist_t *symbiont_connect(const nvlist_t *request) { nvlist_t *response; diff --git a/src/core/capsicum.h b/src/core/capsicum.h index 1eb56402..3c1234e1 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -7,7 +7,17 @@ int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); int capsicum_open(const char *path, int flags, int mode); void capsicum_mkdir_with_parents(const char *path, int mode); +#ifdef HAVE_CAPSICUM +int capsicum_open_wrapper(const char *path, int flags, int mode); +void capsicum_mkdir_with_parents_wrapper(const char *path, int mode); +#else +#define capsicum_open_wrapper(P, F, M) \ + open(P, F, M) +#define capsicum_mkdir_with_parents_wrapper(P, M) \ + g_mkdir_with_parents(P, M) +#endif + void capsicum_init(void); void capsicum_deinit(void); -#endif +#endif /* !__CAPSICUM_H */ diff --git a/src/core/log.c b/src/core/log.c index 9394263f..ea2f1a1d 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -26,9 +26,7 @@ #include "servers.h" #include "log.h" #include "write-buffer.h" -#ifdef HAVE_CAPSICUM #include "capsicum.h" -#endif #include "lib-config/iconfig.h" #include "settings.h" @@ -76,16 +74,6 @@ static void log_write_timestamp(int handle, const char *format, if (text != NULL) write_buffer(handle, text, strlen(text)); } -static int log_open_wrapper(const char *path, int flags, int mode) -{ -#ifdef HAVE_CAPSICUM - if (capsicum_enabled()) - return capsicum_open(path, flags, mode); -#endif - - return open(path, flags, mode); -} - static char *log_filename(LOG_REC *log) { char *str, fname[1024]; @@ -127,19 +115,12 @@ int log_start_logging(LOG_REC *log) /* path may contain variables (%time, $vars), make sure the directory is created */ dir = g_path_get_dirname(log->real_fname); -#ifdef HAVE_CAPSICUM - if (capsicum_enabled()) - capsicum_mkdir_with_parents(dir, log_dir_create_mode); - else - g_mkdir_with_parents(dir, log_dir_create_mode); -#else - g_mkdir_with_parents(dir, log_dir_create_mode); -#endif + capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); g_free(dir); } log->handle = log->real_fname == NULL ? -1 : - log_open_wrapper(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, + capsicum_open_wrapper(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); if (log->handle == -1) { signal_emit("log create failed", 1, log); diff --git a/src/core/rawlog.c b/src/core/rawlog.c index dd86af7c..8f674e6b 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -27,25 +27,13 @@ #include "misc.h" #include "write-buffer.h" #include "settings.h" -#ifdef HAVE_CAPSICUM #include "capsicum.h" -#endif #include "servers.h" static int rawlog_lines; static int signal_rawlog; -static int rawlog_open_wrapper(const char *path, int flags, int mode) -{ -#ifdef HAVE_CAPSICUM - if (capsicum_enabled()) - return capsicum_open(path, flags, mode); -#endif - - return open(path, flags, mode); -} - RAWLOG_REC *rawlog_create(void) { RAWLOG_REC *rec; @@ -139,8 +127,9 @@ void rawlog_open(RAWLOG_REC *rawlog, const char *fname) return; path = convert_home(fname); - rawlog->handle = rawlog_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, - log_file_create_mode); + rawlog->handle = capsicum_open_wrapper(path, + O_WRONLY | O_APPEND | O_CREAT, + log_file_create_mode); g_free(path); if (rawlog->handle == -1) { @@ -167,18 +156,12 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) int f; dir = g_path_get_dirname(fname); -#ifdef HAVE_CAPSICUM - if (capsicum_enabled()) - capsicum_mkdir_with_parents(dir, log_dir_create_mode); - else - g_mkdir_with_parents(dir, log_dir_create_mode); -#else - g_mkdir_with_parents(dir, log_dir_create_mode); -#endif + capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); g_free(dir); path = convert_home(fname); - f = rawlog_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); + f = capsicum_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, + log_file_create_mode); g_free(path); if (f < 0) { diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index deb70991..3d8910c9 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -30,9 +30,7 @@ #include "special-vars.h" #include "settings.h" #include "lib-config/iconfig.h" -#ifdef HAVE_CAPSICUM #include "capsicum.h" -#endif #include "fe-windows.h" #include "window-items.h" @@ -454,14 +452,7 @@ static void autolog_open(SERVER_REC *server, const char *server_tag, log_item_add(log, LOG_ITEM_TARGET, target, server_tag); dir = g_path_get_dirname(log->real_fname); -#ifdef HAVE_CAPSICUM - if (capsicum_enabled()) - capsicum_mkdir_with_parents(dir, log_dir_create_mode); - else - g_mkdir_with_parents(dir, log_dir_create_mode); -#else - g_mkdir_with_parents(dir, log_dir_create_mode); -#endif + capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); g_free(dir); log->temp = TRUE; From 8c04c2be14fc053bd7b5ff03b8e4ba8cb5023700 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 12:30:27 +0100 Subject: [PATCH 15/26] Fix build without Capsicum. Signed-off-by: Edward Tomasz Napierala --- src/core/core.c | 4 ++++ src/fe-common/core/fe-common-core.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/core/core.c b/src/core/core.c index 72631f91..c95879de 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -236,7 +236,9 @@ void core_init(void) commands_init(); nickmatch_cache_init(); session_init(); +#ifdef HAVE_CAPSICUM capsicum_init(); +#endif chat_protocols_init(); chatnets_init(); @@ -294,7 +296,9 @@ void core_deinit(void) chatnets_deinit(); chat_protocols_deinit(); +#ifdef HAVE_CAPSICUM capsicum_deinit(); +#endif session_deinit(); nickmatch_cache_deinit(); commands_deinit(); diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index a0388827..67c9e20c 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -180,7 +180,9 @@ void fe_common_core_init(void) fe_server_init(); fe_settings_init(); fe_tls_init(); +#ifdef HAVE_CAPSICUM fe_capsicum_init(); +#endif windows_init(); window_activity_init(); window_commands_init(); @@ -223,7 +225,9 @@ void fe_common_core_deinit(void) fe_server_deinit(); fe_settings_deinit(); fe_tls_deinit(); +#ifdef HAVE_CAPSICUM fe_capsicum_deinit(); +#endif windows_deinit(); window_activity_deinit(); window_commands_deinit(); From 7f2697d30744d1f33cf67430aa48013b8f4ae9cd Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 12:38:06 +0100 Subject: [PATCH 16/26] Cosmetics. Signed-off-by: Edward Tomasz Napierala --- src/core/log.h | 2 -- src/core/rawlog.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/log.h b/src/core/log.h index 52660bb9..5a07859b 100644 --- a/src/core/log.h +++ b/src/core/log.h @@ -38,8 +38,6 @@ extern GSList *logs; extern int log_file_create_mode; extern int log_dir_create_mode; -extern int log_dir_create_mode; - /* Create log record - you still need to call log_update() to actually add it into log list */ LOG_REC *log_create_rec(const char *fname, int level); diff --git a/src/core/rawlog.c b/src/core/rawlog.c index 8f674e6b..a95b9a92 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -156,7 +156,7 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) int f; dir = g_path_get_dirname(fname); - capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); + capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); g_free(dir); path = convert_home(fname); From a29eeaa9f2e85630b08fc46b3a2b8749b9719efd Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 29 Jul 2017 20:04:28 +0100 Subject: [PATCH 17/26] Fix trailing slash handling for capsicum_irclogs_path. This is mostly an anti-footshooting measure, but still. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 99a4e795..01f5f95c 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -147,6 +147,7 @@ int capsicum_open(const char *path, int flags, int mode) /* +1 is for the slash separating irclogs_path and the rest. */ if (strlen(path) > irclogs_path_len + 1 && + path[irclogs_path_len] == '/' && strncmp(path, irclogs_path, irclogs_path_len) == 0) { fd = openat(irclogs_fd, path + irclogs_path_len + 1, flags, mode); @@ -176,6 +177,7 @@ void capsicum_mkdir_with_parents(const char *path, int mode) /* +1 is for the slash separating irclogs_path and the rest. */ if (strlen(path) <= irclogs_path_len + 1 || + path[irclogs_path_len] != '/' || strncmp(path, irclogs_path, irclogs_path_len) != 0) { g_warning("Cannot create %s: file system access restricted " "to %s due to capability mode", path, irclogs_path); @@ -366,8 +368,15 @@ static void cmd_capsicum_enter(void) port_max = settings_get_int("capsicum_port_max"); irclogs_path = convert_home(settings_get_str("capsicum_irclogs_path")); - g_mkdir_with_parents(irclogs_path, log_dir_create_mode); irclogs_path_len = strlen(irclogs_path); + + /* Strip trailing slashes, if any. */ + while (irclogs_path_len > 0 && irclogs_path[irclogs_path_len - 1] == '/') { + irclogs_path[irclogs_path_len - 1] = '\0'; + irclogs_path_len--; + } + + g_mkdir_with_parents(irclogs_path, log_dir_create_mode); irclogs_fd = open(irclogs_path, O_DIRECTORY | O_CLOEXEC); if (irclogs_fd < 0) { g_warning("Unable to open %s: %s", irclogs_path, strerror(errno)); From 8bb392a3f47d74cccb9e2d7e3633e3e534306968 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sun, 30 Jul 2017 01:27:33 +0100 Subject: [PATCH 18/26] Hook up capsicum.h and fe-capsicum.h to autotools. This hopefully fixes Travis build. Signed-off-by: Edward Tomasz Napierala --- src/core/Makefile.am | 1 + src/fe-common/core/Makefile.am | 1 + 2 files changed, 2 insertions(+) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index f3bc1674..983f7e32 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -74,6 +74,7 @@ structure_headers = \ pkginc_coredir=$(pkgincludedir)/src/core pkginc_core_HEADERS = \ args.h \ + capsicum.h \ channels.h \ channels-setup.h \ commands.h \ diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index 08e41520..29cc941a 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -48,6 +48,7 @@ pkginc_fe_common_core_HEADERS = \ command-history.h \ chat-completion.h \ completion.h \ + fe-capsicum.h \ fe-channels.h \ fe-common-core.h \ fe-core-commands.h \ From 5551b4fe9504f5d5b4e81a680741cab72bec82e9 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sun, 30 Jul 2017 11:47:08 +0100 Subject: [PATCH 19/26] Update copyrights. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 4 ++++ src/fe-common/core/fe-capsicum.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 01f5f95c..b5f704f7 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -3,6 +3,10 @@ Copyright (C) 2017 Edward Tomasz Napierala + This software was developed by SRI International and the University of + Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + ("CTSRD"), as part of the DARPA CRASH research programme. + 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 2 of the License, or diff --git a/src/fe-common/core/fe-capsicum.c b/src/fe-common/core/fe-capsicum.c index 5816b223..4666eda7 100644 --- a/src/fe-common/core/fe-capsicum.c +++ b/src/fe-common/core/fe-capsicum.c @@ -3,6 +3,10 @@ Copyright (C) 2017 Edward Tomasz Napierala + This software was developed by SRI International and the University of + Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + ("CTSRD"), as part of the DARPA CRASH research programme. + 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 2 of the License, or From aeaa420ad330a528391ed149371b55581a808655 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 1 Aug 2017 01:15:25 +0100 Subject: [PATCH 20/26] Clean up includes a bit. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 1 + src/fe-common/core/fe-capsicum.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/capsicum.c b/src/core/capsicum.c index b5f704f7..06cb8d9b 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -23,6 +23,7 @@ */ #include "module.h" +#include "capsicum.h" #include "commands.h" #include "log.h" #include "misc.h" diff --git a/src/fe-common/core/fe-capsicum.c b/src/fe-common/core/fe-capsicum.c index 4666eda7..54a43d27 100644 --- a/src/fe-common/core/fe-capsicum.c +++ b/src/fe-common/core/fe-capsicum.c @@ -23,12 +23,11 @@ */ #include "module.h" -#include "module-formats.h" -#include "signals.h" -#include "printtext.h" - +#include "fe-capsicum.h" #include "levels.h" -#include "servers.h" +#include "module-formats.h" +#include "printtext.h" +#include "signals.h" static void capability_mode_enabled(void) { From 96f4fe10c6081cf441122039c39eb6422eef13e8 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 1 Aug 2017 01:47:45 +0100 Subject: [PATCH 21/26] Change the way we load default CA certificates so it works with Capsicum. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.c | 8 ++++++++ src/core/network-openssl.c | 23 ++++++++++++++++++++--- src/core/network-openssl.h | 6 ++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/core/network-openssl.h diff --git a/src/core/capsicum.c b/src/core/capsicum.c index 06cb8d9b..79db780a 100644 --- a/src/core/capsicum.c +++ b/src/core/capsicum.c @@ -28,6 +28,7 @@ #include "log.h" #include "misc.h" #include "network.h" +#include "network-openssl.h" #include "settings.h" #include "signals.h" @@ -361,6 +362,7 @@ static void cmd_capsicum(const char *data, SERVER_REC *server, void *item) static void cmd_capsicum_enter(void) { u_int mode; + gboolean inited; int error; error = cap_getmode(&mode); @@ -369,6 +371,12 @@ static void cmd_capsicum_enter(void) return; } + inited = irssi_ssl_init(); + if (!inited) { + signal_emit("capability mode failed", 1, strerror(errno)); + return; + } + port_min = settings_get_int("capsicum_port_min"); port_max = settings_get_int("capsicum_port_max"); diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 4de3cb3c..78bdcce4 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -20,6 +20,7 @@ #include "module.h" #include "network.h" +#include "network-openssl.h" #include "net-sendbuffer.h" #include "misc.h" #include "servers.h" @@ -58,6 +59,7 @@ typedef struct } GIOSSLChannel; static int ssl_inited = FALSE; +static X509_STORE *store = NULL; static void irssi_ssl_free(GIOChannel *handle) { @@ -362,8 +364,10 @@ static GIOFuncs irssi_ssl_channel_funcs = { irssi_ssl_get_flags }; -static gboolean irssi_ssl_init(void) +gboolean irssi_ssl_init(void) { + int success; + #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) if (!OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL)) { g_error("Could not initialize OpenSSL"); @@ -374,6 +378,20 @@ static gboolean irssi_ssl_init(void) SSL_load_error_strings(); OpenSSL_add_all_algorithms(); #endif + store = X509_STORE_new(); + if (store == NULL) { + g_error("Could not initialize OpenSSL: X509_STORE_new() failed"); + return FALSE; + } + + success = X509_STORE_set_default_paths(store); + if (success == 0) { + g_error("Could not load default certificates"); + X509_STORE_free(store); + store = NULL; + return FALSE; + } + ssl_inited = TRUE; return TRUE; @@ -492,8 +510,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ g_free(scapath); verify = TRUE; } else { - if (!SSL_CTX_set_default_verify_paths(ctx)) - g_warning("Could not load default certificates"); + SSL_CTX_set_cert_store(ctx, store); } if(!(ssl = SSL_new(ctx))) diff --git a/src/core/network-openssl.h b/src/core/network-openssl.h new file mode 100644 index 00000000..4cd6d711 --- /dev/null +++ b/src/core/network-openssl.h @@ -0,0 +1,6 @@ +#ifndef __NETWORK_OPENSSL_H +#define __NETWORK_OPENSSL_H + +gboolean irssi_ssl_init(void); + +#endif /* !__NETWORK_OPENSSL_H */ From 5db6caee0d17eb125d8c7f3090c325ffbee35920 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Tue, 1 Aug 2017 01:50:16 +0100 Subject: [PATCH 22/26] Attempt to fix build by adding the forgotten header. Signed-off-by: Edward Tomasz Napierala --- src/core/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 983f7e32..f64d9e2e 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -95,6 +95,7 @@ pkginc_core_HEADERS = \ net-nonblock.h \ net-sendbuffer.h \ network.h \ + network-openssl.h \ nick-rec.h \ nicklist.h \ nickmatch-cache.h \ From 0c49a84ffb8d74506a13653183bfa1ef8ffd2554 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 9 Aug 2017 11:06:36 +0100 Subject: [PATCH 23/26] Add back some ifdefs. Signed-off-by: Edward Tomasz Napierala --- src/core/capsicum.h | 10 +--------- src/core/core.c | 2 ++ src/core/log.c | 12 ++++++++++++ src/core/rawlog.c | 16 ++++++++++++++++ src/fe-common/core/fe-common-core.c | 2 ++ src/fe-common/core/fe-log.c | 6 ++++++ 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/core/capsicum.h b/src/core/capsicum.h index 3c1234e1..7d89f2aa 100644 --- a/src/core/capsicum.h +++ b/src/core/capsicum.h @@ -5,17 +5,9 @@ gboolean capsicum_enabled(void); int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip); int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6); int capsicum_open(const char *path, int flags, int mode); -void capsicum_mkdir_with_parents(const char *path, int mode); - -#ifdef HAVE_CAPSICUM int capsicum_open_wrapper(const char *path, int flags, int mode); +void capsicum_mkdir_with_parents(const char *path, int mode); void capsicum_mkdir_with_parents_wrapper(const char *path, int mode); -#else -#define capsicum_open_wrapper(P, F, M) \ - open(P, F, M) -#define capsicum_mkdir_with_parents_wrapper(P, M) \ - g_mkdir_with_parents(P, M) -#endif void capsicum_init(void); void capsicum_deinit(void); diff --git a/src/core/core.c b/src/core/core.c index c95879de..506d6a13 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -29,7 +29,9 @@ #include "signals.h" #include "settings.h" #include "session.h" +#ifdef HAVE_CAPSICUM #include "capsicum.h" +#endif #include "chat-protocols.h" #include "servers.h" diff --git a/src/core/log.c b/src/core/log.c index ea2f1a1d..f7741d3d 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -26,7 +26,9 @@ #include "servers.h" #include "log.h" #include "write-buffer.h" +#ifdef HAVE_CAPSICUM #include "capsicum.h" +#endif #include "lib-config/iconfig.h" #include "settings.h" @@ -115,13 +117,23 @@ int log_start_logging(LOG_REC *log) /* path may contain variables (%time, $vars), make sure the directory is created */ dir = g_path_get_dirname(log->real_fname); +#ifdef HAVE_CAPSICUM capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); +#else + g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); } +#ifdef HAVE_CAPSICUM log->handle = log->real_fname == NULL ? -1 : capsicum_open_wrapper(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); +#else + log->handle = log->real_fname == NULL ? -1 : + open(log->real_fname, O_WRONLY | O_APPEND | O_CREAT, + log_file_create_mode); +#endif if (log->handle == -1) { signal_emit("log create failed", 1, log); log->failed = TRUE; diff --git a/src/core/rawlog.c b/src/core/rawlog.c index a95b9a92..fdd51241 100644 --- a/src/core/rawlog.c +++ b/src/core/rawlog.c @@ -27,7 +27,9 @@ #include "misc.h" #include "write-buffer.h" #include "settings.h" +#ifdef HAVE_CAPSICUM #include "capsicum.h" +#endif #include "servers.h" @@ -127,9 +129,15 @@ void rawlog_open(RAWLOG_REC *rawlog, const char *fname) return; path = convert_home(fname); +#ifdef HAVE_CAPSICUM rawlog->handle = capsicum_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); +#else + rawlog->handle = open(path, O_WRONLY | O_APPEND | O_CREAT, + log_file_create_mode); +#endif + g_free(path); if (rawlog->handle == -1) { @@ -156,12 +164,20 @@ void rawlog_save(RAWLOG_REC *rawlog, const char *fname) int f; dir = g_path_get_dirname(fname); +#ifdef HAVE_CAPSICUM capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); +#else + g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); path = convert_home(fname); +#ifdef HAVE_CAPSICUM f = capsicum_open_wrapper(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); +#else + f = open(path, O_WRONLY | O_APPEND | O_CREAT, log_file_create_mode); +#endif g_free(path); if (f < 0) { diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 67c9e20c..a3b7364c 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -32,7 +32,9 @@ #include "special-vars.h" #include "fe-core-commands.h" #include "fe-queries.h" +#ifdef HAVE_CAPSICUM #include "fe-capsicum.h" +#endif #include "hilight-text.h" #include "command-history.h" #include "completion.h" diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 3d8910c9..0fed8642 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -30,7 +30,9 @@ #include "special-vars.h" #include "settings.h" #include "lib-config/iconfig.h" +#ifdef HAVE_CAPSICUM #include "capsicum.h" +#endif #include "fe-windows.h" #include "window-items.h" @@ -452,7 +454,11 @@ static void autolog_open(SERVER_REC *server, const char *server_tag, log_item_add(log, LOG_ITEM_TARGET, target, server_tag); dir = g_path_get_dirname(log->real_fname); +#ifdef HAVE_CAPSICUM capsicum_mkdir_with_parents_wrapper(dir, log_dir_create_mode); +#else + g_mkdir_with_parents(dir, log_dir_create_mode); +#endif g_free(dir); log->temp = TRUE; From edee0ba587069a860eac43f9219f8ecfa49fe1fa Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Thu, 10 Aug 2017 14:35:34 +0100 Subject: [PATCH 24/26] Don't error out on failure to load default certificate store. This restores the previous behaviour. Signed-off-by: Edward Tomasz Napierala --- src/core/network-openssl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 78bdcce4..2054f28a 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -386,10 +386,10 @@ gboolean irssi_ssl_init(void) success = X509_STORE_set_default_paths(store); if (success == 0) { - g_error("Could not load default certificates"); + g_warning("Could not load default certificates"); X509_STORE_free(store); store = NULL; - return FALSE; + /* Don't return an error; the user might have their own cafile/capath. */ } ssl_inited = TRUE; @@ -509,7 +509,7 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_ g_free(scafile); g_free(scapath); verify = TRUE; - } else { + } else if (store != NULL) { SSL_CTX_set_cert_store(ctx, store); } From 245a3fd4c1afb86b38eb17477a42c60c52cef793 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Mon, 28 Aug 2017 06:13:28 +0100 Subject: [PATCH 25/26] Add docs/capsicum.txt. Signed-off-by: Edward Tomasz Napierala --- docs/Makefile.am | 1 + docs/capsicum.txt | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 docs/capsicum.txt diff --git a/docs/Makefile.am b/docs/Makefile.am index 861a2ca4..32722391 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -2,6 +2,7 @@ man_MANS = \ irssi.1 doc_DATA = \ + capsicum.txt \ design.txt \ formats.txt \ manual.txt \ diff --git a/docs/capsicum.txt b/docs/capsicum.txt new file mode 100644 index 00000000..3093bfe5 --- /dev/null +++ b/docs/capsicum.txt @@ -0,0 +1,30 @@ +Capsicum is a lightweight OS capability and sandbox framework provided +by FreeBSD. When built with Capsicum support - which is the default under +FreeBSD - Irssi can enter a Capsicum capability mode (a sandbox), greatly +limiting possible consequences of a potential security hole in Irssi +or the libraries it depends on. + +To make Irssi enter capability mode on startup, add + +capsicum = "yes"; + +to your ~/.irssi/config and restart the client. Alternatively you can +enter it "by hand", using the "/capsicum enter" command. From the security +point of view it's strongly preferable to use the former method, to avoid +establishing connections without the sandbox protection; the "/capsicum" +command is only intended for experimentation, and in cases where you need +to do something that's not possible in capability mode - run scripts, +for example - before continuing. + +There is no way to leave the capability mode, apart from exiting Irssi. +When running in capability mode, there are certain restrictions - Irssi +won't be able to access any files outside the directory pointed to by +capsicum_irclogs_path (which defaults to ~/irclogs/). If you change +the path when already in capability mode it won't be effective until +you restart Irssi. Capability mode also makes it impossible to use +the "/save" command. + +Currently there is no way to use custom SSL certificates. As a workaround +you can establish connections and enter the capability mode afterwards +using the "/capsicum enter" command. + From b529e1a9df134bbc5618752abcf19af0110b6868 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Fri, 1 Sep 2017 10:39:14 +0100 Subject: [PATCH 26/26] Fix /back in Capsicum capability mode. Signed-off-by: Edward Tomasz Napierala --- src/fe-common/core/fe-core-commands.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index 97a246ec..fb98cc25 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -28,6 +28,9 @@ #include "settings.h" #include "irssi-version.h" #include "servers.h" +#ifdef HAVE_CAPSICUM +#include "capsicum.h" +#endif #include "fe-windows.h" #include "printtext.h" @@ -120,6 +123,9 @@ static void cmd_cat(const char *data) GIOChannel *handle; GString *buf; gsize tpos; +#ifdef HAVE_CAPSICUM + int fd; +#endif if (!cmd_get_params(data, &free_arg, 2, &fname, &fposstr)) return; @@ -128,7 +134,15 @@ static void cmd_cat(const char *data) fpos = atoi(fposstr); cmd_params_free(free_arg); +#ifdef HAVE_CAPSICUM + fd = capsicum_open_wrapper(fname, O_RDONLY, 0); + if (fd > 0) + handle = g_io_channel_unix_new(fd); + else + handle = NULL; +#else handle = g_io_channel_new_file(fname, "r", NULL); +#endif g_free(fname); if (handle == NULL) {