-
-
Save slingamn/28b6e5658c48ead403d903fb3d29dce3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 01b54d12a38e050d5563dd6fe199eaafe9534680 | |
Author: Shivaram Lingamneni <slingamn@cs.stanford.edu> | |
Date: Thu Aug 31 13:33:18 2017 -0400 | |
fixes to irc buffer handling | |
* #12562: consume all available SSL data before returning to event loop | |
* use a constant-sized read buffer to prevent a DoS attack | |
diff --git a/libpurple/protocols/irc/irc.c b/libpurple/protocols/irc/irc.c | |
index f101cbe..c3edfa1 100644 | |
--- a/libpurple/protocols/irc/irc.c | |
+++ b/libpurple/protocols/irc/irc.c | |
@@ -346,6 +346,7 @@ static void irc_login(PurpleAccount *account) | |
gc->proto_data = irc = g_new0(struct irc_conn, 1); | |
irc->fd = -1; | |
irc->account = account; | |
+ irc->inbuf = g_malloc(IRC_BUFSIZE); | |
irc->outbuf = purple_circ_buffer_new(512); | |
userparts = g_strsplit(username, "@", 2); | |
@@ -674,6 +675,7 @@ static void irc_input_cb_ssl(gpointer data, PurpleSslConnection *gsc, | |
PurpleConnection *gc = data; | |
struct irc_conn *irc = gc->proto_data; | |
+ int read_len; | |
int len; | |
if(!g_list_find(purple_connections_get_all(), gc)) { | |
@@ -681,45 +683,57 @@ static void irc_input_cb_ssl(gpointer data, PurpleSslConnection *gsc, | |
return; | |
} | |
- if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { | |
- irc->inbuflen += IRC_INITIAL_BUFSIZE; | |
- irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); | |
- } | |
+ while (1) { | |
+ /* IRC messages are at most 1024 bytes; if the buffer is full | |
+ of "leftover" data that hasn't been parsed into a complete | |
+ IRC message, it's the server's fault. */ | |
+ read_len = (IRC_BUFSIZE - irc->inbufused) - 1; | |
+ if (read_len < 1) { | |
+ purple_connection_error_reason (gc, | |
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
+ _("Invalid response from server")); | |
+ return; | |
+ } | |
+ len = purple_ssl_read(gsc, irc->inbuf + irc->inbufused, read_len); | |
- len = purple_ssl_read(gsc, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); | |
+ if (len < 0 && errno == EAGAIN) { | |
+ /* Try again later */ | |
+ return; | |
+ } else if (len < 0) { | |
+ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), | |
+ g_strerror(errno)); | |
+ purple_connection_error_reason (gc, | |
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); | |
+ g_free(tmp); | |
+ return; | |
+ } else if (len == 0) { | |
+ purple_connection_error_reason (gc, | |
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
+ _("Server closed the connection")); | |
+ return; | |
+ } | |
- if (len < 0 && errno == EAGAIN) { | |
- /* Try again later */ | |
- return; | |
- } else if (len < 0) { | |
- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), | |
- g_strerror(errno)); | |
- purple_connection_error_reason (gc, | |
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); | |
- g_free(tmp); | |
- return; | |
- } else if (len == 0) { | |
- purple_connection_error_reason (gc, | |
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
- _("Server closed the connection")); | |
- return; | |
+ read_input(irc, len); | |
} | |
- | |
- read_input(irc, len); | |
} | |
static void irc_input_cb(gpointer data, gint source, PurpleInputCondition cond) | |
{ | |
PurpleConnection *gc = data; | |
struct irc_conn *irc = gc->proto_data; | |
+ int read_len; | |
int len; | |
- if (irc->inbuflen < irc->inbufused + IRC_INITIAL_BUFSIZE) { | |
- irc->inbuflen += IRC_INITIAL_BUFSIZE; | |
- irc->inbuf = g_realloc(irc->inbuf, irc->inbuflen); | |
+ read_len = (IRC_BUFSIZE - irc->inbufused) - 1; | |
+ /* see irc_input_cb_ssl */ | |
+ if (read_len < 1) { | |
+ purple_connection_error_reason (gc, | |
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, | |
+ _("Invalid response from server")); | |
+ return; | |
} | |
- len = read(irc->fd, irc->inbuf + irc->inbufused, IRC_INITIAL_BUFSIZE - 1); | |
+ len = read(irc->fd, irc->inbuf + irc->inbufused, read_len); | |
if (len < 0 && errno == EAGAIN) { | |
return; | |
} else if (len < 0) { | |
diff --git a/libpurple/protocols/irc/irc.h b/libpurple/protocols/irc/irc.h | |
index 7e74ae8..25ac550 100644 | |
--- a/libpurple/protocols/irc/irc.h | |
+++ b/libpurple/protocols/irc/irc.h | |
@@ -44,7 +44,8 @@ | |
#define IRC_DEFAULT_QUIT "Leaving." | |
-#define IRC_INITIAL_BUFSIZE 1024 | |
+/* IRCv3 maximum message length is half this */ | |
+#define IRC_BUFSIZE 2048 | |
#define IRC_MAX_MSG_SIZE 512 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket, os, fcntl, logging, select | |
serversocket = socket.socket( | |
socket.AF_INET, socket.SOCK_STREAM) | |
serversocket.bind(('127.0.0.1', 7777)) | |
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
serversocket.listen(5) | |
while 1: | |
(clientsocket, address) = serversocket.accept() | |
fcntl.fcntl(clientsocket, fcntl.F_SETFL, os.O_NONBLOCK) | |
sl = [clientsocket] | |
while 1: | |
r, w, e = select.select(sl, sl, sl) | |
try: | |
if r: | |
clientsocket.recv(1024) | |
if w: | |
clientsocket.send('\1' * 1024) | |
except socket.error as e: | |
logging.exception(e) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment