summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-06-16 22:19:51 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-06-16 22:19:51 +0100
commit87b890b501a9ed7bfbfbe0fabde6ca1ca4c15086 (patch)
tree81792cec7a472be37b1e59f89e6a13e1ccc880e4
parent67fd69854489a088bc8d90702ba37cecccd6f169 (diff)
Handle very long lines and very short lines. Print to terminal if we fail to connect to server at startup. Don't print to terminal if sending to a client or to the server fails.
-rw-r--r--TODO2
-rw-r--r--blabouncer.c22
-rw-r--r--functions.c29
3 files changed, 41 insertions, 12 deletions
diff --git a/TODO b/TODO
index d0d4bf8..c5a5517 100644
--- a/TODO
+++ b/TODO
@@ -6,5 +6,3 @@ Add various auto replay options:
- All logs since the current client last disconnected (track clients with some special token the client auto sends on connect)
Might need to #include <limits.h> in blabouncer.c to make some operating systems and/or compilers happy.
-
-What happens if an extremely long line is received?
diff --git a/blabouncer.c b/blabouncer.c
index c9a91aa..3b0a538 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -274,6 +274,11 @@ int processrawstring(SSL *server_ssl, char *str, int source, struct client *clie
if (*token == '\0') continue; // Skip consecutive matches
if (messagecount >= MAXTOKENS) break; // Too many tokens
debugprint(DEBUG_FULL, "String Token: \"%s\", length %zd.\n", token, strlen(token));
+ // Make sure it's not too long
+ if (strlen(token) > MAXDATASIZE - 1) {
+ debugprint(DEBUG_CRIT, "Token too long, discarding.\n");
+ continue;
+ }
// Copy into the token array (strlen + 1 to get the NULL terminator)
strncpy(messages[messagecount], token, strlen(token) + 1);
messagecount++;
@@ -297,7 +302,7 @@ int processrawstring(SSL *server_ssl, char *str, int source, struct client *clie
// If the final characters of the raw string weren't \r\n then assume the final token is a truncated message
// Copy to a holding area for continuation next time
// (Only if source was the server since we always strip \r\n from client messages when recving - TODO - Should we be doing that?
- if ((str[strlen(str)-2] != 13 || str[strlen(str)-1] != 10) && source == SOURCE_SERVER) {
+ if (strlen(str) > 2 && (str[strlen(str)-2] != 13 || str[strlen(str)-1] != 10) && source == SOURCE_SERVER) {
debugprint(DEBUG_FULL, "processrawstring(): Truncated message detected, storing final token '%s' for later.\n", messages[messagecount - 1]);
strncpy(ircdstate->currentmsg, messages[messagecount - 1], strlen(messages[messagecount - 1]));
ircdstate->currentmsg[strlen(messages[messagecount - 1])] = '\0';
@@ -762,7 +767,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
} else {
debugprint(DEBUG_FULL, "...previous connection!\n");
// handle data from a client
- if ((clientnumbytes = sockread(clients[arrindex(clients, i)].ssl, clientbuf, sizeof clientbuf, settings->clienttls)) <= 0) {
+ if ((clientnumbytes = sockread(clients[arrindex(clients, i)].ssl, clientbuf, MAXRCVSIZE - 1, settings->clienttls)) <= 0) {
// got error or connection closed by client
if (clientnumbytes == 0) {
// connection closed
@@ -777,6 +782,16 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
debugprint(DEBUG_FULL, "bouncer-client: total client connections: %d\n", numclients(clients));
} else {
// we got some data from a client
+
+ // Make sure it's not too long
+ if (clientnumbytes > MAXRCVSIZE - 1) {
+ debugprint(DEBUG_CRIT, "bouncer-client: too many bytes received (%d out of a max of %d).\n", clientnumbytes, MAXRCVSIZE - 1);
+ // Clear clientbuf since it's overflowed
+ clientbuf[0] = '\0';
+ // And go back to the top of the loop
+ continue;
+ }
+
// null terminate that baby
clientbuf[clientnumbytes] = '\0'; // TODO make sure this can't overrun if some super long line (max bytes?) was received
// clear up any newlines - TODO - Should we be doing this? If not, we can stop only doing truncation checks for the server in processrawstring().
@@ -1141,8 +1156,9 @@ int main(int argc, char *argv[]) {
// Create server socket
int serversockfd;
if ((serversockfd = createserversocket(settings.ircserver, settings.ircserverport)) == -1) {
+ fprintf(stderr, "main(): Couldn't connect to server, exiting.\n");
debugprint(DEBUG_CRIT, "main(): Couldn't connect to server, exiting.\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
// Create client socket (after server so we can use its fd number later as fdmax)
diff --git a/functions.c b/functions.c
index 82a98eb..3aa474f 100644
--- a/functions.c
+++ b/functions.c
@@ -387,6 +387,12 @@ int arrindex(struct client *clients, int clientfd) {
// Send whatever string to a specific client by providing the FD
// If "bypass" == 1 then permit sending to client even if unauthenticated (for instance for a CAP LS response)
int sendtoclient(int fd, char *strsrc, struct client *clients, struct settings *settings, int bypass) {
+ if (strlen(strsrc) > MAXDATASIZE) {
+ // String is too long!
+ debugprint(DEBUG_CRIT, "sendtoclient(): strsrc '%s' was too long (%d out of a max of %d characters).\n", strsrc, strlen(strsrc), MAXDATASIZE);
+ return 0;
+ }
+
// Copy to new string for passing to appendcrlf() to avoid overrun in appendcrlf()
char str[MAXDATASIZE];
strcpy(str, strsrc);
@@ -409,7 +415,6 @@ int sendtoclient(int fd, char *strsrc, struct client *clients, struct settings *
debugprint(DEBUG_SOME, "sendtoclient(): sending \"%s\" (length %zd) to client with fd %d.\n", str, strlen(str), fd);
if (socksend(clients[i].ssl, str, strlen(str), settings->clienttls) == -1) {
- perror("error: sendtoclient() socksend()\n");
debugprint(DEBUG_CRIT, "error: sendtoclient() socksend() error sending to client with fd '%d', errno '%d'.\n", fd, errno);
return 0;
}
@@ -421,9 +426,14 @@ int sendtoclient(int fd, char *strsrc, struct client *clients, struct settings *
// "except" is used to send to all clients _except_ the fd provided (except = 0 (EXCEPT_NONE) avoids this, i.e. sends to all)
// "except" is really the "sourcefd" and is also used as part of the authentication check - this is messy and they should perhaps be two separate arguments.
int sendtoallclients(struct client *clients, char *strsrc, int except, struct settings *settings) {
-
char *sendertype;
+ if (strlen(strsrc) > MAXDATASIZE) {
+ // String is too long!
+ debugprint(DEBUG_CRIT, "sendtoallclients(): strsrc '%s' was too long (%d out of a max of %d characters).\n", strsrc, strlen(strsrc), MAXDATASIZE);
+ return 0;
+ }
+
// Copy to new string for passing to appendcrlf() to avoid overrun in appendcrlf()
char str[MAXDATASIZE];
strcpy(str, strsrc);
@@ -470,7 +480,6 @@ int sendtoallclients(struct client *clients, char *strsrc, int except, struct se
}
debugprint(DEBUG_SOME, "sendtoallclients(): %s: sending '%s' to client with fd %d.\n", sendertype, str, clients[i].fd);
if (socksend(clients[i].ssl, str, strlen(str), settings->clienttls) == -1) {
- perror("error: sendtoallclients() socksend()\n");
debugprint(DEBUG_CRIT, "error: sendtoallclients() socksend() error sending to client with fd '%d', errno '%d'.\n", clients[i].fd, errno);
}
}
@@ -483,7 +492,14 @@ int sendtoallclients(struct client *clients, char *strsrc, int except, struct se
// Client FD and arrays needed to make sure anything relayed from a client is from an authenticated client.
// clientfd of "0" means trusted, used when we are sending things ourselves that weren't relayed
// from a real client.
+// Returns 1 on success or 0 on failure. - TODO - Make callers care about this.
int sendtoserver(SSL *server_ssl, char *strsrc, int str_len, int clientfd, struct client *clients, struct settings *settings) {
+ if (strlen(strsrc) > MAXDATASIZE) {
+ // String is too long!
+ debugprint(DEBUG_CRIT, "sendtoserver(): strsrc '%s' was too long (%d out of a max of %d characters).\n", strsrc, strlen(strsrc), MAXDATASIZE);
+ return 0;
+ }
+
// Copy to new string for passing to appendcrlf() to avoid overrun in appendcrlf()
char str[MAXDATASIZE];
strcpy(str, strsrc);
@@ -502,19 +518,18 @@ int sendtoserver(SSL *server_ssl, char *strsrc, int str_len, int clientfd, struc
// Found client in array, check authentication status
if (!clients[i].authed) {
debugprint(DEBUG_SOME, "sendtoserver(): skipping unauthenticated client with fd %d.\n", clients[i].fd);
- return 0;
+ return 1;
}
}
}
debugprint(DEBUG_SOME, "sendtoserver(): sending '%s' to IRC server (length %d).\n", str, str_len);
if (socksend(server_ssl, str, str_len, settings->servertls) == -1) {
- printf("error: sendtoserver() socksend()\n");
debugprint(DEBUG_CRIT, "error: sendtoserver() socksend() error sending to server, errno '%d'.\n", clientfd, errno);
- return 0;
+ return 1;
}
- return 1;
+ return 0;
}
// Disconnect the client fd "fd" by close()ing it and remove