summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Bratch <luke@bratch.co.uk>2019-05-27 12:37:46 +0100
committerLuke Bratch <luke@bratch.co.uk>2019-05-27 12:37:46 +0100
commitf0936ca1b231df3c5cb7cf80a1d6a88d7ea980af (patch)
tree0ab81634a4858c9b10cc7cdf830f1bf2537d7c18
parentab84512bc06ade328169d38ffb64f3820aa80dc4 (diff)
Only do CAP multi-prefix negotiation with clients if the server approved it in the first place.
-rw-r--r--TODO4
-rw-r--r--blabouncer.c26
2 files changed, 26 insertions, 4 deletions
diff --git a/TODO b/TODO
index 54b889f..5eee410 100644
--- a/TODO
+++ b/TODO
@@ -21,8 +21,4 @@ Test CTCP.
Reconnect server if we get disconnected for some reason.
-Only do CAP multi-prefix negotiation with client if server approved it in the first place.
-
Change default certfile and keyfile to be basedir/ instead of $HOME.
-
-Connecting to Miau has some sort of corruption and doesn't get channels.
diff --git a/blabouncer.c b/blabouncer.c
index db0d384..efb2474 100644
--- a/blabouncer.c
+++ b/blabouncer.c
@@ -76,6 +76,7 @@ struct ircdstrings {
char ircusername[MAXUSERNAMELEN];
char currentmsg[MAXDATASIZE]; // Holding area for the current server-received IRC message being processed in case it needs building across multiple reads (i.e. a truncated/split message)
char mode[MAXDATASIZE];
+ int capmultiprefix; // Whether the server approved our CAP multi-prefix request
};
// Structure of settings either to be read from the configuration file or set/changed at runtime
@@ -1260,6 +1261,21 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
free(strcopyPtr);
return 1;
}
+
+ // Server CAP received?
+ if (strncmp(tokens[1], "CAP", strlen(tokens[1])) == 0) {
+ printf("Server CAP found and it is: %s with length %zd! Analysing...\n", tokens[1], strlen(tokens[1]));
+ // If the server said "CAP <ournick> ACK :multi-prefix" then it must have approved our CAP multi-prefix request
+ if (counter == 5) {
+ if (strncmp(tokens[2], ircdstrings->ircnick, strlen(tokens[2])) == 0 &&
+ strncmp(tokens[3], "ACK", strlen(tokens[3])) == 0 &&
+ strncmp(tokens[4], ":multi-prefix", strlen(tokens[4])) == 0) {
+ ircdstrings->capmultiprefix = 1;
+ }
+ }
+ // We didn't handle it
+ printf("Unhandled server CAP response.\n");
+ }
}
// Don't return if we got here because this means we didn't process something above
@@ -1305,6 +1321,14 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli
// CAP received? Clients can send CAP before PASS so we have to deal with this even if they are not authenticated yet.
if (strncasecmp(tokens[0], "CAP", strlen(tokens[0])) == 0) {
+ // But only do something if the real server told us it had a CAP (only multi-prefix for now)
+ if (ircdstrings->capmultiprefix == 1) {
+ printf("Client CAP received and the server supports CAPs, continuing.\n");
+ } else {
+ printf("Client CAP received but the server doesn't support CAPs, returning.\n");
+ free(strcopyPtr);
+ return 1;
+ }
// Get the real IRC server name from greeting001
// They are now pending CAP negotiation
clients[arrindex(clients, sourcefd)].pendingcap = 1;
@@ -1875,6 +1899,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {
ircdstrings.ircusername[0] = '\0';
ircdstrings.currentmsg[0] = '\0';
ircdstrings.mode[0] = '\0';
+ // And set non-string things to zero (TODO - Rename this from ircdstrings since it's not all strings any more)
+ ircdstrings.capmultiprefix = 0;
// Populate nick and username from our configuration file for now, real IRCd may change them later (TODO - Is this true of username?)
strcpy(ircdstrings.ircnick, settings->ircnick);