From 9c44d7baf400e2addebfb5343c99cf753cebf7eb Mon Sep 17 00:00:00 2001 From: James Clarke Date: Wed, 1 Jan 2020 20:37:39 +0000 Subject: Avoid prioritising MODE queries for channels with hyphens in their name If a user has a large number of channels containing hyphens in their names, the initial MODE queries will have the same high priority as any PINGs, and so will block the PINGs from being sent, causing the connection to time out due to a lack of PONGs received. --- src/common/server.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'src/common/server.c') diff --git a/src/common/server.c b/src/common/server.c index 3db0a963..f7fa8b96 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -200,13 +200,35 @@ tcp_send_len (server *serv, char *buf, int len) } else { - /* WHO/MODE get the lowest priority */ - if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0 || - /* but only MODE queries, not changes */ - (g_ascii_strncasecmp (dbuf + 1, "MODE", 4) == 0 && - strchr (dbuf, '-') == NULL && - strchr (dbuf, '+') == NULL)) + /* WHO gets the lowest priority */ + if (g_ascii_strncasecmp (dbuf + 1, "WHO ", 4) == 0) dbuf[0] = 0; + /* as do MODE queries (but not changes) */ + else if (g_ascii_strncasecmp (dbuf + 1, "MODE ", 5) == 0) + { + char *mode_str, *mode_str_end, *loc; + /* skip spaces before channel/nickname */ + for (mode_str = dbuf + 5; *mode_str == ' '; ++mode_str); + /* skip over channel/nickname */ + mode_str = strchr (mode_str, ' '); + if (mode_str) + { + /* skip spaces before mode string */ + for (; *mode_str == ' '; ++mode_str); + /* find spaces after end of mode string */ + mode_str_end = strchr (mode_str, ' '); + /* look for +/- within the mode string */ + loc = strchr (mode_str, '-'); + if (loc && (!mode_str_end || loc < mode_str_end)) + goto keep_priority; + loc = strchr (mode_str, '+'); + if (loc && (!mode_str_end || loc < mode_str_end)) + goto keep_priority; + } + dbuf[0] = 0; +keep_priority: + ; + } } serv->outbound_queue = g_slist_append (serv->outbound_queue, dbuf); -- cgit 1.4.1 From 7b950eb0218a19620b9b885818ac031d29ecab09 Mon Sep 17 00:00:00 2001 From: DjLegolas Date: Sat, 11 Apr 2020 13:01:35 +0300 Subject: Fixed proxy user/password buffer overflow By using a dedicated buffer for sending the username and password for the SOCKS5 proxy, there will be no overflow when copying them to the buffer. And therefore, RFC 1929 is fully supported. --- src/common/server.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'src/common/server.c') diff --git a/src/common/server.c b/src/common/server.c index f7fa8b96..c6fa1ced 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -1116,6 +1116,7 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port) if (auth) { int len_u=0, len_p=0; + unsigned char *u_p_buf; /* authentication sub-negotiation (RFC1929) */ if (buf[1] != 2) /* UPA not supported by server */ @@ -1124,18 +1125,22 @@ traverse_socks5 (int print_fd, int sok, char *serverAddr, int port) return 1; } - memset (buf, 0, sizeof(buf)); - /* form the UPA request */ len_u = strlen (prefs.hex_net_proxy_user); len_p = strlen (prefs.hex_net_proxy_pass); - buf[0] = 1; - buf[1] = len_u; - memcpy (buf + 2, prefs.hex_net_proxy_user, len_u); - buf[2 + len_u] = len_p; - memcpy (buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p); - send (sok, buf, 3 + len_u + len_p, 0); + packetlen = 2 + len_u + 1 + len_p; + u_p_buf = g_malloc0 (packetlen); + + u_p_buf[0] = 1; + u_p_buf[1] = len_u; + memcpy (u_p_buf + 2, prefs.hex_net_proxy_user, len_u); + u_p_buf[2 + len_u] = len_p; + memcpy (u_p_buf + 3 + len_u, prefs.hex_net_proxy_pass, len_p); + + send (sok, u_p_buf, packetlen, 0); + g_free(u_p_buf); + if ( recv (sok, buf, 2, 0) != 2 ) goto read_error; if ( buf[1] != 0 ) -- cgit 1.4.1 From 37118a4d2b70c11a76c732346975c2745d3cc4c6 Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Mon, 24 May 2021 02:53:28 +0100 Subject: Implement support for the IRCv3 account-tag specification. (#2572) Co-authored-by: Patrick --- src/common/hexchat.h | 1 + src/common/inbound.c | 3 +++ src/common/proto-irc.c | 19 +++++++++++++++++++ src/common/proto-irc.h | 4 ++++ src/common/server.c | 1 + src/common/userlist.c | 12 +++++++----- 6 files changed, 35 insertions(+), 5 deletions(-) (limited to 'src/common/server.c') diff --git a/src/common/hexchat.h b/src/common/hexchat.h index f7cacfcc..f9ca006b 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -569,6 +569,7 @@ typedef struct server unsigned int have_idmsg:1; /* freenode's IDENTIFY-MSG */ unsigned int have_accnotify:1; /* cap account-notify */ unsigned int have_extjoin:1; /* cap extended-join */ + unsigned int have_account_tag:1; /* cap account-tag */ unsigned int have_server_time:1; /* cap server-time */ unsigned int have_sasl:1; /* SASL capability */ unsigned int have_except:1; /* ban exemptions +e */ diff --git a/src/common/inbound.c b/src/common/inbound.c index 3a26dce9..7175b2ae 100644 --- a/src/common/inbound.c +++ b/src/common/inbound.c @@ -1671,6 +1671,8 @@ inbound_toggle_caps (server *serv, const char *extensions_str, gboolean enable) serv->have_server_time = enable; else if (!strcmp (extension, "away-notify")) serv->have_awaynotify = enable; + else if (!strcmp (extension, "account-tag")) + serv->have_account_tag = enable; else if (!strcmp (extension, "sasl")) { serv->have_sasl = enable; @@ -1726,6 +1728,7 @@ static const char * const supported_caps[] = { "chghost", "setname", "invite-notify", + "account-tag", /* ZNC */ "znc.in/server-time-iso", diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index 57eda88a..cfe76361 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -1010,6 +1010,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], const message_tags_data *tags_data) { server *serv = sess->server; + char *account; char ip[128], nick[NICKLEN]; char *text, *ex; int len = strlen (type); @@ -1028,6 +1029,14 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], ex[0] = '!'; } + + /** Update the account for this message's source. */ + if (serv->have_account_tag) + { + account = tags_data->account && *tags_data->account ? tags_data->account : "*"; + inbound_account (serv, nick, account, tags_data); + } + if (len == 4) { guint32 t; @@ -1522,6 +1531,9 @@ handle_message_tags (server *serv, const char *tags_str, *value = '\0'; value++; + if (serv->have_account_tag && !strcmp (key, "account")) + tags_data->account = g_strdup (value); + if (serv->have_server_time && !strcmp (key, "time")) handle_message_tag_time (value, tags_data); } @@ -1619,9 +1631,16 @@ irc_inline (server *serv, char *buf, int len) } xit: + message_tags_data_free (&tags_data); g_free (pdibuf); } +void +message_tags_data_free (message_tags_data *tags_data) +{ + g_clear_pointer (&tags_data->account, g_free); +} + void proto_fill_her_up (server *serv) { diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h index 6c075795..0f72c644 100644 --- a/src/common/proto-irc.h +++ b/src/common/proto-irc.h @@ -25,6 +25,7 @@ #define MESSAGE_TAGS_DATA_INIT \ { \ + NULL, /* account name */ \ (time_t)0, /* timestamp */ \ } @@ -36,9 +37,12 @@ */ typedef struct { + char *account; time_t timestamp; } message_tags_data; +void message_tags_data_free (message_tags_data *tags_data); + void proto_fill_her_up (server *serv); #endif diff --git a/src/common/server.c b/src/common/server.c index c6fa1ced..5c645eb5 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -1784,6 +1784,7 @@ server_set_defaults (server *serv) serv->have_idmsg = FALSE; serv->have_accnotify = FALSE; serv->have_extjoin = FALSE; + serv->have_account_tag = FALSE; serv->have_server_time = FALSE; serv->have_sasl = FALSE; serv->have_except = FALSE; diff --git a/src/common/userlist.c b/src/common/userlist.c index 17719ff6..5f2d67f2 100644 --- a/src/common/userlist.c +++ b/src/common/userlist.c @@ -101,13 +101,15 @@ userlist_set_account (struct session *sess, char *nick, char *account) user = userlist_find (sess, nick); if (user) { - g_free (user->account); - if (strcmp (account, "*") == 0) - user->account = NULL; - else + { + g_clear_pointer (&user->account, g_free); + } else if (g_strcmp0 (user->account, account)) + { + g_free (user->account); user->account = g_strdup (account); - + } + /* gui doesnt currently reflect login status, maybe later fe_userlist_rehash (sess, user); */ } -- cgit 1.4.1