summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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