diff options
-rw-r--r-- | general_network.c | 28 | ||||
-rw-r--r-- | general_network.h | 3 | ||||
-rw-r--r-- | plaintext_network.c | 1 | ||||
-rw-r--r-- | protocols.c | 1 | ||||
-rw-r--r-- | protocols.h | 1 | ||||
-rw-r--r-- | protocols/inspircd2.c | 37 | ||||
-rw-r--r-- | protocols/inspircd2.h | 4 | ||||
-rw-r--r-- | psuedoclients/haxserv.c | 67 | ||||
-rw-r--r-- | psuedoclients/haxserv.h | 3 | ||||
-rw-r--r-- | table.c | 19 | ||||
-rw-r--r-- | table.h | 3 |
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 @@ -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; +} @@ -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); |