aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--general_network.c28
-rw-r--r--general_network.h3
-rw-r--r--plaintext_network.c1
-rw-r--r--protocols.c1
-rw-r--r--protocols.h1
-rw-r--r--protocols/inspircd2.c37
-rw-r--r--protocols/inspircd2.h4
-rw-r--r--psuedoclients/haxserv.c67
-rw-r--r--psuedoclients/haxserv.h3
-rw-r--r--table.c19
-rw-r--r--table.h3
11 files changed, 156 insertions, 11 deletions
diff --git a/general_network.c b/general_network.c
index 2b055c2..a5251c6 100644
--- a/general_network.c
+++ b/general_network.c
@@ -273,9 +273,12 @@ int add_user(struct string from, struct string attached_to, struct string uid, s
if (str_clone(&(new_info->address), address) != 0)
goto add_user_free_host;
- if (set_table_index(&user_list, uid, new_info) != 0)
+ if (str_clone(&(new_info->oper_type), STRING("")) != 0)
goto add_user_free_address;
+ if (set_table_index(&user_list, uid, new_info) != 0)
+ goto add_user_free_oper_type;
+
if (set_table_index(&(attached->user_list), uid, new_info) != 0)
goto add_user_remove_user_list;
@@ -295,6 +298,8 @@ int add_user(struct string from, struct string attached_to, struct string uid, s
add_user_remove_user_list:
remove_table_index(&user_list, uid);
+ add_user_free_oper_type:
+ free(new_info->oper_type.data);
add_user_free_address:
free(new_info->address.data);
add_user_free_host:
@@ -379,6 +384,7 @@ void remove_user(struct string from, struct user_info *user, struct string reaso
free(user->vhost.data);
free(user->host.data);
free(user->address.data);
+ free(user->oper_type.data);
free(user);
}
@@ -412,6 +418,26 @@ int kill_user(struct string from, struct string source, struct user_info *user,
return 0;
}
+int oper_user(struct string from, struct user_info *user, struct string type) {
+ struct string tmp;
+ if (str_clone(&tmp, type) != 0)
+ return 1;
+
+#ifdef USE_SERVER
+#ifdef USE_HAXIRCD_PROTOCOL
+ protocols[HAXIRCD_PROTOCOL].propagate_oper_user(from, user, type);
+#endif
+#ifdef USE_INSPIRCD2_PROTOCOL
+ protocols[INSPIRCD2_PROTOCOL].propagate_oper_user(from, user, type);
+#endif
+#endif
+
+ free(user->oper_type.data);
+ user->oper_type = tmp;
+
+ return 0;
+}
+
int set_channel(struct string from, struct string name, size_t timestamp, size_t user_count, struct user_info **users) {
char is_new_channel;
struct channel_info *channel = get_table_index(channel_list, name);
diff --git a/general_network.h b/general_network.h
index a5713c0..889e653 100644
--- a/general_network.h
+++ b/general_network.h
@@ -86,6 +86,8 @@ struct user_info {
size_t user_ts;
size_t nick_ts;
+ struct string oper_type;
+
struct string server;
struct table channel_list;
@@ -121,6 +123,7 @@ int add_user(struct string from, struct string attached_to, struct string uid, s
int rename_user(struct string from, struct user_info *user, struct string nick, size_t timestamp);
void remove_user(struct string from, struct user_info *user, struct string reason, char propagate);
int kill_user(struct string from, struct string source, struct user_info *user, struct string reason);
+int oper_user(struct string from, struct user_info *user, struct string type);
int set_channel(struct string from, struct string name, size_t timestamp, size_t user_count, struct user_info **users);
int join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users, char propagate);
diff --git a/plaintext_network.c b/plaintext_network.c
index 9ba8999..38348af 100644
--- a/plaintext_network.c
+++ b/plaintext_network.c
@@ -52,6 +52,7 @@ int plaintext_send(void *fd, struct string msg) {
} while (res == -1 && (errno == EINTR));
if (res < 0 || (size_t)res > msg.len) { // res > len shouldn't be possible, but is still an error
+ plaintext_shutdown(fd);
return 1;
} else if (res > 0) {
msg.len -= (size_t)res;
diff --git a/protocols.c b/protocols.c
index afdbca5..55fb238 100644
--- a/protocols.c
+++ b/protocols.c
@@ -48,6 +48,7 @@ struct protocol protocols[NUM_PROTOCOLS] = {
.propagate_rename_user = inspircd2_protocol_propagate_rename_user,
.propagate_remove_user = inspircd2_protocol_propagate_remove_user,
.propagate_kill_user = inspircd2_protocol_propagate_kill_user,
+ .propagate_oper_user = inspircd2_protocol_propagate_oper_user,
.propagate_set_channel = inspircd2_protocol_propagate_set_channel,
.propagate_join_channel = inspircd2_protocol_propagate_join_channel,
diff --git a/protocols.h b/protocols.h
index 6d8a240..4665dad 100644
--- a/protocols.h
+++ b/protocols.h
@@ -45,6 +45,7 @@ struct protocol {
void (*propagate_rename_user)(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
void (*propagate_remove_user)(struct string from, struct user_info *info, struct string reason);
void (*propagate_kill_user)(struct string from, struct string source, struct user_info *info, struct string reason);
+ void (*propagate_oper_user)(struct string from, struct user_info *info, struct string type);
void (*propagate_set_channel)(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
void (*propagate_join_channel)(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users);
diff --git a/protocols/inspircd2.c b/protocols/inspircd2.c
index 5f546c7..688fb02 100644
--- a/protocols/inspircd2.c
+++ b/protocols/inspircd2.c
@@ -138,6 +138,7 @@ int init_inspircd2_protocol(void) {
set_table_index(&inspircd2_protocol_commands, STRING("NICK"), &inspircd2_protocol_handle_nick);
set_table_index(&inspircd2_protocol_commands, STRING("QUIT"), &inspircd2_protocol_handle_quit);
set_table_index(&inspircd2_protocol_commands, STRING("KILL"), &inspircd2_protocol_handle_kill);
+ set_table_index(&inspircd2_protocol_commands, STRING("OPERTYPE"), &inspircd2_protocol_handle_opertype);
set_table_index(&inspircd2_protocol_commands, STRING("FJOIN"), &inspircd2_protocol_handle_fjoin);
set_table_index(&inspircd2_protocol_commands, STRING("PART"), &inspircd2_protocol_handle_part);
@@ -489,6 +490,7 @@ void inspircd2_protocol_propagate(struct string from, struct server_info *self,
}
}
+// [:source] SERVER <name> <password> <always 0> <sid> <fullname>
void inspircd2_protocol_propagate_new_server(struct string from, struct string attached_to, struct server_info *info) {
struct server_info *self = get_table_index(server_list, SID);
@@ -527,6 +529,7 @@ void inspircd2_protocol_propagate_new_server(struct string from, struct string a
inspircd2_protocol_propagate(from, self, STRING(" ENDBURST\n"));
}
+// [:source] SQUIT <sid> [<reason>?]
void inspircd2_protocol_propagate_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol) {
struct server_info *source;
struct server_info *target;
@@ -616,6 +619,17 @@ void inspircd2_protocol_propagate_kill_user(struct string from, struct string so
inspircd2_protocol_propagate(from, self, STRING("\n"));
}
+// :source OPERTYPE <type>
+void inspircd2_protocol_propagate_oper_user(struct string from, struct user_info *user, struct string type) {
+ struct server_info *self = get_table_index(server_list, SID);
+
+ inspircd2_protocol_propagate(from, self, STRING(":"));
+ inspircd2_protocol_propagate(from, self, user->uid);
+ inspircd2_protocol_propagate(from, self, STRING(" OPERTYPE :"));
+ inspircd2_protocol_propagate(from, self, type);
+ inspircd2_protocol_propagate(from, self, STRING("\n"));
+}
+
// [:source] FJOIN <channel> <timestamp> <modes> [<mode args>] <userlist: modes,uid [...]>
void inspircd2_protocol_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_server, size_t user_count, struct user_info **users) {
struct server_info *self = get_table_index(server_list, SID);
@@ -1014,6 +1028,10 @@ int inspircd2_protocol_handle_ping(struct string source, size_t argc, struct str
}
}
+ struct server_info *reply = get_table_index(server_list, argv[0]);
+ if (!reply || !STRING_EQ(reply->next, config->sid))
+ return 0;
+
networks[net].send(handle, STRING(":"));
networks[net].send(handle, argv[1]);
networks[net].send(handle, STRING(" PONG "));
@@ -1299,6 +1317,25 @@ int inspircd2_protocol_handle_kill(struct string source, size_t argc, struct str
return 0;
}
+// :source OPERTYPE <type>
+int inspircd2_protocol_handle_opertype(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming) {
+ if (argc < 1) {
+ WRITES(2, STRING("[InspIRCd v2] Invalid OPERTYPE recieved! (Missing parameters)\r\n"));
+ return -1;
+ }
+
+ struct user_info *user = get_table_index(user_list, source);
+ if (!user)
+ return 0;
+
+ if (oper_user(config->sid, user, argv[0]) != 0) {
+ WRITES(2, STRING("[InspIRCd v2] ERROR: Unable to set oper type!\r\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
// [:source] FJOIN <channel> <timestamp> <modes> [<mode args>] <userlist: modes,uid [...]>
int inspircd2_protocol_handle_fjoin(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming) {
if (argc < 4) {
diff --git a/protocols/inspircd2.h b/protocols/inspircd2.h
index a7ac588..3309582 100644
--- a/protocols/inspircd2.h
+++ b/protocols/inspircd2.h
@@ -41,6 +41,8 @@ void * inspircd2_protocol_connection(void *type);
void * inspircd2_protocol_autoconnect(void *type);
void inspircd2_protocol_update_propagations(void);
+void inspircd2_protocol_propagate(struct string from, struct server_info *self, struct string msg);
+
void inspircd2_protocol_propagate_new_server(struct string from, struct string attached_to, struct server_info *info);
void inspircd2_protocol_propagate_unlink_server(struct string from, struct server_info *a, struct server_info *b, size_t protocol);
@@ -48,6 +50,7 @@ void inspircd2_protocol_propagate_new_user(struct string from, struct user_info
void inspircd2_protocol_propagate_rename_user(struct string from, struct user_info *info, struct string nick, size_t timestamp, struct string timestamp_str);
void inspircd2_protocol_propagate_remove_user(struct string from, struct user_info *info, struct string reason);
void inspircd2_protocol_propagate_kill_user(struct string from, struct string source, struct user_info *info, struct string reason);
+void inspircd2_protocol_propagate_oper_user(struct string from, struct user_info *info, struct string type);
void inspircd2_protocol_propagate_set_channel(struct string from, struct channel_info *channel, char is_new_channel, size_t user_count, struct user_info **users);
void inspircd2_protocol_propagate_join_channel(struct string from, struct channel_info *channel, size_t user_count, struct user_info **users);
@@ -77,6 +80,7 @@ int inspircd2_protocol_handle_uid(struct string source, size_t argc, struct stri
int inspircd2_protocol_handle_nick(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
int inspircd2_protocol_handle_quit(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
int inspircd2_protocol_handle_kill(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
+int inspircd2_protocol_handle_opertype(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
int inspircd2_protocol_handle_fjoin(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
int inspircd2_protocol_handle_part(struct string source, size_t argc, struct string *argv, size_t net, void *handle, struct server_config *config, char is_incoming);
diff --git a/psuedoclients/haxserv.c b/psuedoclients/haxserv.c
index 2d80a2a..4a1de8a 100644
--- a/psuedoclients/haxserv.c
+++ b/psuedoclients/haxserv.c
@@ -38,7 +38,12 @@
#include "haxserv.h"
+#ifdef USE_INSPIRCD2_PROTOCOL
+#include "../protocols/inspircd2.h"
+#endif
+
struct table haxserv_psuedoclient_commands = {0};
+struct table haxserv_psuedoclient_prefixes = {0};
// TODO: Potentially leaky on failure
int haxserv_psuedoclient_init(void) {
@@ -73,6 +78,11 @@ int haxserv_psuedoclient_init(void) {
haxserv_psuedoclient_clear_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
if (set_table_index(&haxserv_psuedoclient_commands, STRING("CLEAR"), &haxserv_psuedoclient_clear_command_def) != 0)
return 1;
+#ifdef USE_INSPIRCD2_PROTOCOL
+ haxserv_psuedoclient_raw_inspircd2_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_psuedoclient_prefixes, STRING(":"), &haxserv_psuedoclient_raw_inspircd2_command_def) != 0)
+ return 1;
+#endif
return 0;
}
@@ -140,24 +150,45 @@ void haxserv_psuedoclient_handle_privmsg(struct string from, struct string sourc
msg.data += prefix.len;
msg.len -= prefix.len;
- struct string command_str = {.len = argv[0].len};
+
struct command_def *cmd;
- command_str.data = malloc(command_str.len);
- if (command_str.data) {
- for (size_t i = 0; i < command_str.len; i++)
- command_str.data[i] = CASEMAP(argv[0].data[i]);
- cmd = get_table_index(haxserv_psuedoclient_commands, command_str);
+ struct string case_str = {.len = argv[0].len};
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(argv[0].data[i]);
- free(command_str.data);
+ cmd = get_table_index(haxserv_psuedoclient_commands, case_str);
+
+ free(case_str.data);
} else {
- cmd = get_table_index(haxserv_psuedoclient_commands, command_str);
+ cmd = get_table_index(haxserv_psuedoclient_commands, argv[0]);
+ }
+
+ if (!cmd) {
+ case_str.len = msg.len;
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(msg.data[i]);
+
+ cmd = get_table_prefix(haxserv_psuedoclient_prefixes, case_str);
+
+ free(case_str.data);
+ } else {
+ cmd = get_table_prefix(haxserv_psuedoclient_prefixes, msg);
+ }
}
if (cmd) {
if (cmd->privs.len != 0 && !(!has_table_index(user_list, source) && has_table_index(server_list, source))) {
- notice(SID, HAXSERV_UID, respond_to, STRING("You are not authorized to execute this command."));
- return;
+ struct user_info *user = get_table_index(user_list, source);
+ // TODO: Multiple privilege levels
+ if (!STRING_EQ(user->oper_type, cmd->privs)) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("You are not authorized to execute this command."));
+ return;
+ }
}
cmd->func(from, source, msg, respond_to, argc - 1, &(argv[1]));
@@ -291,3 +322,19 @@ struct command_def haxserv_psuedoclient_clear_command_def = {
.summary = STRING("Clears a channel."),
.name = STRING("clear"),
};
+
+#ifdef USE_INSPIRCD2_PROTOCOL
+int haxserv_psuedoclient_raw_inspircd2_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ struct server_info *self = get_table_index(server_list, SID);
+
+ inspircd2_protocol_propagate(SID, self, original_message);
+ inspircd2_protocol_propagate(SID, self, STRING("\n"));
+
+ return 0;
+}
+struct command_def haxserv_psuedoclient_raw_inspircd2_command_def = {
+ .func = haxserv_psuedoclient_raw_inspircd2_command,
+ .summary = STRING("Sends a raw message to all InspIRCd v2 links."),
+ .name = STRING(":"),
+};
+#endif
diff --git a/psuedoclients/haxserv.h b/psuedoclients/haxserv.h
index d94df4f..5302b35 100644
--- a/psuedoclients/haxserv.h
+++ b/psuedoclients/haxserv.h
@@ -49,3 +49,6 @@ extern struct command_def haxserv_psuedoclient_help_command_def;
extern struct command_def haxserv_psuedoclient_sus_command_def;
extern struct command_def haxserv_psuedoclient_cr_command_def;
extern struct command_def haxserv_psuedoclient_clear_command_def;
+#ifdef USE_INSPIRCD2_PROTOCOL
+extern struct command_def haxserv_psuedoclient_raw_inspircd2_command_def;
+#endif
diff --git a/table.c b/table.c
index c69bc9c..76c31b5 100644
--- a/table.c
+++ b/table.c
@@ -179,3 +179,22 @@ void clear_table(struct table *tbl) {
size_t get_table_offset(struct table tbl, struct string name, char *exists) {
return search(tbl, name, exists);
}
+
+void * get_table_prefix(struct table tbl, struct string name) {
+ char exists;
+ size_t index = search(tbl, name, &exists);
+ if (exists)
+ return tbl.array[index].ptr;
+
+ if (index == 0)
+ return 0;
+
+ size_t len = tbl.array[index - 1].name.len;
+ if (len > name.len)
+ return 0;
+
+ if (memcmp(tbl.array[index - 1].name.data, name.data, len) != 0)
+ return 0;
+
+ return tbl.array[index - 1].ptr;
+}
diff --git a/table.h b/table.h
index 5281e5d..61cc1d4 100644
--- a/table.h
+++ b/table.h
@@ -46,3 +46,6 @@ extern char has_table_index(struct table tbl, struct string name);
extern void * remove_table_index(struct table *tbl, struct string name); // returns same as get_table_index
extern void clear_table(struct table *tbl);
extern size_t get_table_offset(struct table tbl, struct string name, char *exists);
+
+// Longest index that <name> starts with
+extern void * get_table_prefix(struct table tbl, struct string name);