diff --git a/.gitignore b/.gitignore index ea2cd7ba..ab43b18b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,11 @@ lt~obsolete.m4 pm_to_blib stamp-h1 MYMETA.* +/irssi-1.pc +/irssi +ID +tags +/build/ docs/help/Makefile.am docs/help/[a-z]* @@ -33,6 +38,7 @@ docs/help/in/Makefile.am src/fe-text/irssi src/fe-fuzz/irssi-fuzz +src/fe-none/botti src/fe-fuzz/irc/core/event-get-params-fuzz src/fe-fuzz/fe-common/core/theme-load-fuzz diff --git a/docs/help/in/otr.in b/docs/help/in/otr.in index fcfcd875..3ab42ade 100644 --- a/docs/help/in/otr.in +++ b/docs/help/in/otr.in @@ -108,4 +108,3 @@ files: computer. If unsure, just ignore this file. For more information on OTR, see https://otr.cypherpunks.ca/ - diff --git a/m4/libotr.m4 b/m4/libotr.m4 new file mode 100644 index 00000000..214c6086 --- /dev/null +++ b/m4/libotr.m4 @@ -0,0 +1,133 @@ +dnl +dnl Off-the-Record Messaging library +dnl Copyright (C) 2004-2007 Ian Goldberg, Chris Alexander, Nikita Borisov +dnl +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of version 2.1 of the GNU Lesser General +dnl Public License as published by the Free Software Foundation. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +dnl + +dnl AM_PATH_LIBOTR([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libotr, and define LIBOTR_CFLAGS and LIBOTR_LIBS as appropriate. +dnl enables arguments --with-libotr-prefix= +dnl --with-libotr-inc-prefix= +dnl +dnl You must already have found libgcrypt with AM_PATH_LIBGCRYPT +dnl +dnl Adapted from alsa.m4, originally by +dnl Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela + +AC_DEFUN([AM_PATH_LIBOTR], +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +libotr_save_CFLAGS="$CFLAGS" +libotr_save_LDFLAGS="$LDFLAGS" +libotr_save_LIBS="$LIBS" +libotr_found=yes + +dnl +dnl Get the cflags and libraries for libotr +dnl +AC_ARG_WITH(libotr-prefix, +[ --with-libotr-prefix=PFX Prefix where libotr is installed(optional)], +[libotr_prefix="$withval"], [libotr_prefix=""]) + +AC_ARG_WITH(libotr-inc-prefix, +[ --with-libotr-inc-prefix=PFX Prefix where libotr includes are (optional)], +[libotr_inc_prefix="$withval"], [libotr_inc_prefix=""]) + +dnl Add any special include directories +AC_MSG_CHECKING(for libotr CFLAGS) +if test "$libotr_inc_prefix" != "" ; then + LIBOTR_CFLAGS="$LIBOTR_CFLAGS -I$libotr_inc_prefix" + CFLAGS="$CFLAGS $LIBOTR_CFLAGS" +fi +AC_MSG_RESULT($LIBOTR_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for libotr LIBS) +if test "$libotr_prefix" != "" ; then + LIBOTR_LIBS="$LIBOTR_LIBS -L$libotr_prefix" + LDFLAGS="$LDFLAGS $LIBOTR_LIBS" +fi + +dnl add the libotr library +LIBOTR_LIBS="$LIBOTR_LIBS -lotr" +LIBS="$LIBOTR_LIBS $LIBS" +AC_MSG_RESULT($LIBOTR_LIBS) + +dnl Check for a working version of libotr that is of the right version. +min_libotr_version=ifelse([$1], ,3.0.0,$1) +no_libotr="" + libotr_min_major_version=`echo $min_libotr_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + libotr_min_minor_version=`echo $min_libotr_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + libotr_min_sub_version=`echo $min_libotr_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` +AC_MSG_CHECKING(for libotr headers version $libotr_min_major_version.x >= $min_libotr_version) + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +#include +], [ +# if(OTRL_VERSION_MAJOR != $libotr_min_major_version) +# error not present +# else + +# if(OTRL_VERSION_MINOR > $libotr_min_minor_version) + exit(0); +# else +# if(OTRL_VERSION_MINOR < $libotr_min_minor_version) +# error not present +# endif + +# if(OTRL_VERSION_SUB < $libotr_min_sub_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libotr not found.)]) + libotr_found=no] +) +AC_LANG_RESTORE + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +AC_CHECK_LIB([otr], [otrl_message_receiving],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libotr was found.)]) + libotr_found=no], + $LIBGCRYPT_LIBS +) + +LDFLAGS="$libotr_save_LDFLAGS" +LIBS="$libotr_save_LIBS" + +if test "x$libotr_found" = "xyes" ; then + ifelse([$2], , :, [$2]) +else + LIBOTR_CFLAGS="" + LIBOTR_LIBS="" + ifelse([$3], , :, [$3]) +fi + +dnl That should be it. Now just export our symbols: +AC_SUBST(LIBOTR_CFLAGS) +AC_SUBST(LIBOTR_LIBS) +]) diff --git a/meson.build b/meson.build index 9b54bc01..19c03e03 100644 --- a/meson.build +++ b/meson.build @@ -511,6 +511,11 @@ if want_capsicum endif endif +dependency('libseccomp', version : '>= 2.3.1', required : true) +libseccomp = cc.find_library('seccomp', required : true) + +dep += libseccomp + # dependency helper sets dep_cflagsonly = [] foreach d : dep @@ -538,7 +543,6 @@ headers = [ 'sys/ioctl.h', 'sys/resource.h', 'sys/time.h', - 'sys/utsname.h', 'dirent.h', 'term.h', 'unistd.h', @@ -566,6 +570,13 @@ add_project_arguments(cc.get_supported_arguments('-Werror=declaration-after-stat #### personality #### add_project_arguments(cc.get_supported_arguments('-fno-strict-aliasing'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-D_FORTIFY_SOURCE=3'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-fstack-protector-strong'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-fstack-clash-protection'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-fPIE'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-fcf-protection=full'), language : 'c') +add_project_arguments(cc.get_supported_arguments('-fsanitize=safe-stack,scudo'), language : 'c') +add_project_arguments(cc.get_supported_arguments('--param=ssp-buffer-size=4'), language : 'c') if get_option('buildtype').contains('debug') add_project_arguments(cc.get_supported_arguments('-fno-omit-frame-pointer'), language : 'c') endif diff --git a/src/common.h b/src/common.h index e51c24db..1b688cda 100644 --- a/src/common.h +++ b/src/common.h @@ -60,6 +60,18 @@ const char *get_irssi_config(void); /* max. size for %d */ #define MAX_INT_STRLEN ((sizeof(int) * CHAR_BIT + 2) / 3 + 1) +/* Force a compilation error if condition is true, but also produce a + result (of value 0 and type size_t), so the expression can be used + e.g. in a structure initializer (or where-ever else comma expressions + aren't permitted). */ +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) +#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) + +# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +/* &a[0] degrades to a pointer: a different type from an array */ +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) + #define g_free_not_null(a) g_free(a) #define g_free_and_null(a) \ diff --git a/src/core/expandos.c b/src/core/expandos.c index 0f317e51..1f30f29d 100644 --- a/src/core/expandos.c +++ b/src/core/expandos.c @@ -441,25 +441,25 @@ static char *expando_realname(SERVER_REC *server, void *item, int *free_ret) static char *expando_time(SERVER_REC *server, void *item, int *free_ret) { time_t now; - struct tm *tm; + struct tm tm; char str[256]; char *format; now = current_time != (time_t) -1 ? current_time : time(NULL); - tm = localtime(&now); + localtime_r(&now, &tm); format = timestamp_format; if (reference_time != (time_t) -1) { time_t ref = reference_time; struct tm tm_ref; if (localtime_r(&ref, &tm_ref)) { - if (tm_ref.tm_yday != tm->tm_yday || tm_ref.tm_year != tm->tm_year) { + if (tm_ref.tm_yday != tm.tm_yday || tm_ref.tm_year != tm.tm_year) { format = timestamp_format_alt; } } } - if (strftime(str, sizeof(str), format, tm) == 0) + if (strftime(str, sizeof(str), format, &tm) == 0) return ""; *free_ret = TRUE; @@ -605,9 +605,6 @@ static void read_settings(void) void expandos_init(void) { -#ifdef HAVE_SYS_UTSNAME_H - struct utsname un; -#endif settings_add_str("misc", "STATUS_OPER", "*"); settings_add_str("lookandfeel", "timestamp_format", "%H:%M"); settings_add_str("lookandfeel", "timestamp_format_alt", "%a %e %b %H:%M"); @@ -618,13 +615,6 @@ void expandos_init(void) last_timestamp = 0; sysname = sysrelease = sysarch = NULL; -#ifdef HAVE_SYS_UTSNAME_H - if (uname(&un) >= 0) { - sysname = g_strdup(un.sysname); - sysrelease = g_strdup(un.release); - sysarch = g_strdup(un.machine); - } -#endif memset(char_expandos, 0, sizeof(char_expandos)); expandos = g_hash_table_new((GHashFunc) g_str_hash, diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c index 643884ee..0152d64e 100644 --- a/src/core/net-nonblock.c +++ b/src/core/net-nonblock.c @@ -50,9 +50,6 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int reverse_l "Using blocking resolving"); } - /* child */ - srand(time(NULL)); - memset(&rec, 0, sizeof(rec)); rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6); if (rec.error == 0) { diff --git a/src/core/network-openssl.c b/src/core/network-openssl.c index 9956f217..a3f722e8 100644 --- a/src/core/network-openssl.c +++ b/src/core/network-openssl.c @@ -121,6 +121,40 @@ static const char *tls_dns_name(const GENERAL_NAME * gn) return dnsname; } +typedef struct { + unsigned int id; + void *ptr; +} osslitems; + +static const osslitems standard_name2type[] = { + { EVP_PKEY_RSA, "RSA" }, + { EVP_PKEY_RSA_PSS, "RSA-PSS" }, + { EVP_PKEY_EC, "EC" }, + { EVP_PKEY_ED25519, "ED25519" }, + { EVP_PKEY_ED448, "ED448" }, + { EVP_PKEY_X25519, "X25519" }, + { EVP_PKEY_X448, "X448" }, + { EVP_PKEY_SM2, "SM2" }, + { EVP_PKEY_DH, "DH" }, + { EVP_PKEY_DHX, "X9.42 DH" }, + { EVP_PKEY_DHX, "DHX" }, + { EVP_PKEY_DSA, "DSA" }, +}; + +static const char *evp_pkey_type2name(int type) +{ + size_t i; + const char *p; + + for (i = 0; i < ARRAY_SIZE(standard_name2type); i++) { + if (type == (int)standard_name2type[i].id) + return standard_name2type[i].ptr; + } + + p = OBJ_nid2sn(type); + return (p) ?: "Unknown"; +} + /* tls_text_name - extract certificate property value by name */ static char *tls_text_name(X509_NAME *name, int nid) { @@ -601,7 +635,9 @@ static void set_cipher_info(TLS_REC *tls, SSL *ssl) tls_rec_set_cipher_size(tls, SSL_get_cipher_bits(ssl, NULL)); } -static gboolean set_pubkey_info(TLS_REC *tls, X509 *cert, unsigned char *cert_fingerprint, size_t cert_fingerprint_size, unsigned char *public_key_fingerprint, size_t public_key_fingerprint_size) +static gboolean set_pubkey_info(TLS_REC *tls, X509 *cert, unsigned char *cert_fingerprint, + size_t cert_fingerprint_size, unsigned char *public_key_fingerprint, + size_t public_key_fingerprint_size) { gboolean ret = TRUE; EVP_PKEY *pubkey = NULL; @@ -620,26 +656,7 @@ static gboolean set_pubkey_info(TLS_REC *tls, X509 *cert, unsigned char *cert_fi cert_fingerprint_hex = binary_to_hex(cert_fingerprint, cert_fingerprint_size); tls_rec_set_certificate_fingerprint(tls, cert_fingerprint_hex); tls_rec_set_certificate_fingerprint_algorithm(tls, "SHA256"); - - /* Show algorithm. */ - switch (EVP_PKEY_id(pubkey)) { - case EVP_PKEY_RSA: - tls_rec_set_public_key_algorithm(tls, "RSA"); - break; - - case EVP_PKEY_DSA: - tls_rec_set_public_key_algorithm(tls, "DSA"); - break; - - case EVP_PKEY_EC: - tls_rec_set_public_key_algorithm(tls, "EC"); - break; - - default: - tls_rec_set_public_key_algorithm(tls, "Unknown"); - break; - } - + tls_rec_set_public_key_algorithm(tls, evp_pkey_type2name(EVP_PKEY_id(pubkey))); public_key_fingerprint_hex = binary_to_hex(public_key_fingerprint, public_key_fingerprint_size); tls_rec_set_public_key_fingerprint(tls, public_key_fingerprint_hex); tls_rec_set_public_key_size(tls, EVP_PKEY_bits(pubkey)); @@ -756,41 +773,12 @@ static void set_server_temporary_key_info(TLS_REC *tls, SSL *ssl) #ifndef OPENSSL_NO_EC EC_KEY *ec_key = NULL; #endif - char *ephemeral_key_algorithm = NULL; - char *cname = NULL; - int nid; - g_return_if_fail(tls != NULL); g_return_if_fail(ssl != NULL); if (SSL_get_server_tmp_key(ssl, &ephemeral_key)) { - switch (EVP_PKEY_id(ephemeral_key)) { - case EVP_PKEY_DH: - tls_rec_set_ephemeral_key_algorithm(tls, "DH"); - tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); - break; - -#ifndef OPENSSL_NO_EC - case EVP_PKEY_EC: - ec_key = EVP_PKEY_get1_EC_KEY(ephemeral_key); - nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)); - EC_KEY_free(ec_key); - cname = (char *)OBJ_nid2sn(nid); - ephemeral_key_algorithm = g_strdup_printf("ECDH: %s", cname); - - tls_rec_set_ephemeral_key_algorithm(tls, ephemeral_key_algorithm); - tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); - - g_free_and_null(ephemeral_key_algorithm); - break; -#endif - - default: - tls_rec_set_ephemeral_key_algorithm(tls, "Unknown"); - tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); - break; - } - + tls_rec_set_ephemeral_key_algorithm(tls, evp_pkey_type2name(EVP_PKEY_id(ephemeral_key))); + tls_rec_set_ephemeral_key_size(tls, EVP_PKEY_bits(ephemeral_key)); EVP_PKEY_free(ephemeral_key); } #endif /* SSL_get_server_tmp_key. */ diff --git a/src/core/network.c b/src/core/network.c index 85fe9896..8f482fd3 100644 --- a/src/core/network.c +++ b/src/core/network.c @@ -433,8 +433,8 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6) return HOST_NOT_FOUND; /* shouldn't happen? */ /* if there are multiple addresses, return random one */ - use_v4 = count_v4 <= 1 ? 0 : rand() % count_v4; - use_v6 = count_v6 <= 1 ? 0 : rand() % count_v6; + use_v4 = count_v4 <= 1 ? 0 : g_random_int_range(0, count_v4); + use_v6 = count_v6 <= 1 ? 0 : g_random_int_range(0, count_v6); count_v4 = count_v6 = 0; for (ai = ailist; ai != NULL; ai = ai->ai_next) { diff --git a/src/core/session.c b/src/core/session.c index 5fe481fb..c6284503 100644 --- a/src/core/session.c +++ b/src/core/session.c @@ -50,9 +50,13 @@ void session_upgrade(void) if (session_args == NULL) return; +#if 0 execv(session_args[0], session_args); fprintf(stderr, "exec failed: %s: %s\n", session_args[0], g_strerror(errno)); +#else + fprintf(stderr, "exec* syscalls disabled by seccomp rules\n"); +#endif } /* SYNTAX: UPGRADE [] */ diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index f5fb3b22..61d9b33d 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -49,10 +49,12 @@ void fe_dcc_server_deinit(void); char *dcc_get_size_str(uoff_t size) { if (size < 1024) - return g_strdup_printf("%"PRIuUOFF_T"B", size); + return g_strdup_printf("%"PRIuUOFF_T" B", size); if (size < 1024*1024) - return g_strdup_printf("%"PRIuUOFF_T"kB", (size+1023) / 1024); - return g_strdup_printf("%"PRIuUOFF_T"MB", size / (1024*1024)); + return g_strdup_printf("%"PRIuUOFF_T" KiB", (size+1023) / 1024); + if (size < 1024*1024*1024) + return g_strdup_printf("%"PRIuUOFF_T" MiB", size / (1024*1024)); + return g_strdup_printf("%"PRIuUOFF_T" GiB", size / (1024*1024*1024)); } static void dcc_request(DCC_REC *dcc) diff --git a/src/fe-common/irc/dcc/module-formats.c b/src/fe-common/irc/dcc/module-formats.c index f973cd9e..0ada013c 100644 --- a/src/fe-common/irc/dcc/module-formats.c +++ b/src/fe-common/irc/dcc/module-formats.c @@ -49,11 +49,11 @@ FORMAT_REC fecommon_irc_dcc_formats[] = { { "dcc_send_not_found", "{dcc DCC not sending file {dccfile $1} to {nick $0}}", 2, { 0, 0 } }, { "dcc_send_file_open_error", "{dcc DCC can't open file {dccfile $0}: $1}", 2, { 0, 0 } }, { "dcc_send_connected", "{dcc DCC sending file {dccfile $0} for {nick $1} [$2 port $3]}", 4, { 0, 0, 0, 1 } }, - { "dcc_send_complete", "{dcc DCC sent file {dccfile $0} [{hilight $1}] for {nick $2} in {hilight $3} [{hilight $4kB/s}]}", 5, { 0, 0, 0, 0, 3 } }, + { "dcc_send_complete", "{dcc DCC sent file {dccfile $0} [{hilight $1}] for {nick $2} in {hilight $3} [{hilight $4 KiB/s}]}", 5, { 0, 0, 0, 0, 3 } }, { "dcc_send_aborted", "{dcc DCC aborted sending file {dccfile $0} for {nick $1}}", 2, { 0, 0 } }, { "dcc_get_not_found", "{dcc DCC no file offered by {nick $0}}", 1, { 0 } }, { "dcc_get_connected", "{dcc DCC receiving file {dccfile $0} from {nick $1} [$2 port $3]}", 4, { 0, 0, 0, 1 } }, - { "dcc_get_complete", "{dcc DCC received file {dccfile $0} [$1] from {nick $2} in {hilight $3} [$4kB/s]}", 5, { 0, 0, 0, 0, 3 } }, + { "dcc_get_complete", "{dcc DCC received file {dccfile $0} [$1] from {nick $2} in {hilight $3} [$4 KiB/s]}", 5, { 0, 0, 0, 0, 3 } }, { "dcc_get_aborted", "{dcc DCC aborted receiving file {dccfile $0} from {nick $1}}", 2, { 0, 0 } }, { "dcc_get_write_error", "{dcc DCC error writing to file {dccfile $0}: {comment $1}", 2, { 0, 0 } }, { "dcc_unknown_ctcp", "{dcc DCC unknown ctcp {hilight $0} from {nick $1} [$2]}", 3, { 0, 0, 0 } }, @@ -68,7 +68,7 @@ FORMAT_REC fecommon_irc_dcc_formats[] = { { "dcc_lowport", "{dcc Warning: Port sent with DCC request is a lowport ({hilight $0, $1}) - this isn't normal. It is possible the address/port is faked (or maybe someone is just trying to bypass firewall)}", 2, { 1, 0 } }, { "dcc_list_header", "{dcc DCC connections}", 0 }, { "dcc_list_line_chat", "{dcc $0 $1}", 2, { 0, 0 } }, - { "dcc_list_line_file", "{dcc $0 $1: %|$2 of $3 ($4%%) - $5kB/s - ETA $7 - $6}", 8, { 0, 0, 0, 0, 1, 3, 0, 0 } }, + { "dcc_list_line_file", "{dcc $0 $1: %|$2 of $3 ($4%%) - $5 KiB/s - ETA $7 - $6}", 8, { 0, 0, 0, 0, 1, 3, 0, 0 } }, { "dcc_list_line_queued_send", "{dcc - $0 $2 (queued)}", 3, { 0, 0, 0 } }, { "dcc_list_footer", "", 0 }, { "dcc_list_line_server", "{dcc $0: Port($1) - Send($2) - Chat($3) - Fserve($4)}", 5, { 0, 1, 0, 0, 0 } }, diff --git a/src/fe-common/irc/irc-modules.c b/src/fe-common/irc/irc-modules.c new file mode 100644 index 00000000..4839ae68 --- /dev/null +++ b/src/fe-common/irc/irc-modules.c @@ -0,0 +1,5 @@ +/* this file is automatically generated by configure - don't change */ +void fe_irc_dcc_init(void);void fe_irc_notifylist_init(void); +void fe_irc_notifylist_deinit(void);void fe_irc_dcc_deinit(void); +void fe_irc_modules_init(void) { fe_irc_dcc_init(); fe_irc_notifylist_init(); } +void fe_irc_modules_deinit(void) { fe_irc_notifylist_deinit(); fe_irc_dcc_deinit(); } diff --git a/src/fe-none/irssi.c b/src/fe-none/irssi.c index c442bd7f..37a3447a 100644 --- a/src/fe-none/irssi.c +++ b/src/fe-none/irssi.c @@ -60,8 +60,6 @@ static void autoload_modules(void) void noui_init(void) { - srand(time(NULL)); - irssi_gui = IRSSI_GUI_NONE; core_init(); diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 9952f748..d826d991 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -18,6 +18,10 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + #include "module.h" #include #include @@ -45,6 +49,9 @@ #include #include +#include +#include +#include void gui_expandos_init(void); void gui_expandos_deinit(void); @@ -296,8 +303,6 @@ int main(int argc, char **argv) return 0; } - srand(time(NULL)); - quitting = FALSE; core_preinit(argv[0]); @@ -313,6 +318,7 @@ int main(int argc, char **argv) furthermore to get the users's charset with g_get_charset() properly you have to call setlocale(LC_ALL, "") */ setlocale(LC_ALL, ""); + tzset(); /* Temporarily raise the fatal level to abort on config errors. */ loglev = critical_fatal_section_begin(); @@ -326,6 +332,130 @@ int main(int argc, char **argv) critical_fatal_section_end(loglev); textui_finish_init(); + if (!getenv("IRSSI_NO_SECCOMP")) { + scmp_filter_ctx ctx; + int rc = 0; + + ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM)); + //ctx = seccomp_init(SCMP_ACT_KILL_PROCESS); + if (ctx) { + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); /* glibc resolv */ +#ifdef __SNR_clone3 + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone3), 0); +#endif + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_create), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_create1), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(eventfd2), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmod), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fdatasync), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fsync), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getegid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(geteuid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getgid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpgrp), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getppid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrandom), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrusage), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockname), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getuid), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(link), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(listen), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pipe), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pipe2), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ppoll), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pread64), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(pselect6), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readlink), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvmsg), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(restart_syscall), 0); +#ifdef __SNR_rseq + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rseq), 0); +#endif + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(select), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmmsg), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statfs), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sysinfo), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(umask), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(uname), 0); /* glic resolv */ + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(wait4), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); +#ifdef __SNR_epoll_pwait2 + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait2), 0); +#endif + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill), 1, SCMP_A1(SCMP_CMP_EQ, SIGTSTP)); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ)); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCGETS)); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCSETSW)); + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCSETSF)); +#ifdef FIONREAD + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, FIONREAD)); +#endif +#ifdef FIONWRITE + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, FIONWRITE)); +#endif +#ifdef FIONSPACE + rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, FIONSPACE)); +#endif + + fprintf(stderr, "rc=%d Adding seccomp rules... ", rc); + if (seccomp_load(ctx) == 0) { + fprintf(stderr, "OK.\n"); + } else { + fprintf(stderr, "FAIL.\n"); + } + seccomp_release(ctx); + } else { + fprintf(stderr, "seccomp failed\n"); + } + } + main_loop = g_main_loop_new(NULL, TRUE); /* Does the same as g_main_run(main_loop), except we @@ -341,7 +471,7 @@ int main(int argc, char **argv) if (settings_get_bool("quit_on_hup")) { signal_emit("gui exit", 0); - } + } else { signal_emit("command reload", 1, ""); } diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index 2439d101..f0bc1405 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -509,7 +509,7 @@ STATUSBAR_REC *statusbar_create(STATUSBAR_GROUP_REC *group, mainwindow_set_statusbar_lines(parent_window, config->placement == STATUSBAR_TOP, config->placement == STATUSBAR_BOTTOM); - theme = parent_window != NULL && parent_window->active != NULL && + theme = parent_window != NULL && parent_window->active != NULL && parent_window->active->theme != NULL ? parent_window->active->theme : current_theme; } diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index 68da0e27..1c8a0003 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -18,6 +18,8 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include + #include "module.h" #include #include @@ -447,7 +449,6 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) IPADDR own_ip; GIOChannel *handle; GHashTable *optlist; - int p_id; char *nick, host[MAX_IP_LEN]; int port; @@ -524,15 +525,14 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) signal_emit("dcc request send", 1, dcc); /* generate a random id */ - p_id = rand() % 64; - dcc->pasv_id = p_id; + dcc->pasv_id = g_random_int() % INT32_MAX; /* 16843009 is the long format of 1.1.1.1, we use a fake IP since the other side shouldn't care of it: they will send the address for us to connect to in the reply */ irc_send_cmdv(server, "PRIVMSG %s :\001DCC CHAT CHAT 16843009 0 %d\001", - nick, p_id); + nick, dcc->pasv_id); } cmd_params_free(free_arg); } diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c index 0214387b..2062d456 100644 --- a/src/irc/dcc/dcc-get.c +++ b/src/irc/dcc/dcc-get.c @@ -57,7 +57,10 @@ static void sig_dcc_destroyed(GET_DCC_REC *dcc) if (!IS_DCC_GET(dcc)) return; g_free_not_null(dcc->file); - if (dcc->fhandle != -1) close(dcc->fhandle); + if (dcc->fhandle != -1) { + fsync(dcc->fhandle); + close(dcc->fhandle); + } } char *dcc_get_download_path(const char *fname) @@ -191,8 +194,7 @@ static void sig_dccget_receive(GET_DCC_REC *dcc) void sig_dccget_connected(GET_DCC_REC *dcc) { struct stat statbuf; - char *fname, *tempfname, *str; - int ret, ret_errno, temphandle, old_umask; + char *fname, *str; if (!dcc->from_dccserver) { if (net_geterror(dcc->handle) != 0) { @@ -207,7 +209,7 @@ void sig_dccget_connected(GET_DCC_REC *dcc) } g_free_not_null(dcc->file); - dcc->file = dcc_get_download_path(dcc->arg); + dcc->file = g_utf8_make_valid(dcc_get_download_path(dcc->arg), -1); /* if some plugin wants to change the file name/path here.. */ signal_emit("dcc get receive", 1, dcc); @@ -221,60 +223,11 @@ void sig_dccget_connected(GET_DCC_REC *dcc) } if (dcc->get_type != DCC_GET_RESUME) { - int dcc_file_create_mode = octal2dec(settings_get_int("dcc_file_create_mode")); - - /* we want to overwrite the file, remove it here. - if it gets created after this, we'll fail. */ - unlink(dcc->file); - - /* just to make sure we won't run into race conditions - if download_path is in some global temp directory */ - tempfname = g_strconcat(dcc->file, ".XXXXXX", NULL); - - old_umask = umask(0077); - temphandle = mkstemp(tempfname); - umask(old_umask); - - if (temphandle == -1) - ret = -1; - else { - if (fchmod(temphandle, dcc_file_create_mode) != 0) - g_warning("fchmod(3) failed: %s", strerror(errno)); - /* proceed even if chmod fails */ - ret = 0; - } - - close(temphandle); - - if (ret != -1) { - ret = link(tempfname, dcc->file); - - if (ret == -1 && - /* Linux */ - (errno == EPERM || - /* FUSE */ - errno == ENOSYS || errno == EACCES || - /* BSD */ - errno == EOPNOTSUPP)) { - /* hard links aren't supported - some people - want to download stuff to FAT/NTFS/etc - partitions, so fallback to rename() */ - ret = rename(tempfname, dcc->file); - } - } - - /* if ret = 0, we're the file owner now */ - dcc->fhandle = ret == -1 ? -1 : - open(dcc->file, O_WRONLY | O_TRUNC); - - /* close/remove the temp file */ - ret_errno = errno; - unlink(tempfname); - g_free(tempfname); - + dcc->fhandle = open(dcc->file, O_WRONLY | O_EXCL | O_CLOEXEC | O_CREAT, + octal2dec(settings_get_int("dcc_file_create_mode"))); if (dcc->fhandle == -1) { signal_emit("dcc error file create", 3, - dcc, dcc->file, g_strerror(ret_errno)); + dcc, dcc->file, g_strerror(errno)); dcc_destroy(DCC(dcc)); return; } diff --git a/src/irc/dcc/dcc-send.c b/src/irc/dcc/dcc-send.c index eccb8d37..2526e8f4 100644 --- a/src/irc/dcc/dcc-send.c +++ b/src/irc/dcc/dcc-send.c @@ -18,6 +18,8 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include + #include "module.h" #include #include @@ -438,7 +440,7 @@ static int dcc_send_one_file(int queue, const char *target, const char *fname, /* Generate an ID for this send if using passive protocol */ if (passive) { - dcc->pasv_id = rand() % 64; + dcc->pasv_id = g_random_int() % INT32_MAX; } /* send DCC request */ diff --git a/src/irc/irc.c b/src/irc/irc.c new file mode 100644 index 00000000..ba3791e8 --- /dev/null +++ b/src/irc/irc.c @@ -0,0 +1,6 @@ +/* this file is automatically generated by configure - don't change */ +void irc_core_init(void); void irc_core_deinit(void); +void irc_dcc_init(void);void irc_flood_init(void);void irc_notifylist_init(void); +void irc_notifylist_deinit(void);void irc_flood_deinit(void);void irc_dcc_deinit(void); +void irc_init(void) { irc_core_init(); irc_dcc_init(); irc_flood_init(); irc_notifylist_init(); } +void irc_deinit(void) { irc_notifylist_deinit(); irc_flood_deinit(); irc_dcc_deinit(); irc_core_deinit(); } diff --git a/src/irc/notifylist/notifylist.c b/src/irc/notifylist/notifylist.c index 73737b37..b1127d30 100644 --- a/src/irc/notifylist/notifylist.c +++ b/src/irc/notifylist/notifylist.c @@ -149,6 +149,8 @@ static IRC_SERVER_REC *notifylist_ison_serverlist(const char *nick, const char * g_return_val_if_fail(taglist != NULL, NULL); list = g_strsplit(taglist, " ", -1); + if (list == NULL) + return NULL; server = NULL; for (tmp = list; *tmp != NULL; tmp++) {