X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/89d871d8a38dd8862d4da7a0c58f7236dda1b392..e0ee1ed8a1244740d4cad80273e0f4603e9cf744:/src/proto-p10.c diff --git a/src/proto-p10.c b/src/proto-p10.c index 0b4ba3b..f55dd7e 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -93,7 +93,9 @@ #define CMD_SQUERY "SQUERY" #define CMD_SQUIT "SQUIT" #define CMD_STATS "STATS" +#define CMD_SVSJOIN "SVSJOIN" #define CMD_SVSNICK "SVSNICK" +#define CMD_SVSPART "SVSPART" #define CMD_SWHOIS "SWHOIS" #define CMD_TIME "TIME" #define CMD_TOPIC "TOPIC" @@ -181,7 +183,9 @@ #define TOK_SQUERY "SQUERY" #define TOK_SQUIT "SQ" #define TOK_STATS "R" +#define TOK_SVSJOIN "SJ" #define TOK_SVSNICK "SN" +#define TOK_SVSPART "SP" #define TOK_SWHOIS "SW" #define TOK_TIME "TI" #define TOK_TOPIC "T" @@ -279,7 +283,9 @@ #define P10_SQUERY TYPE(SQUERY) #define P10_SQUIT TYPE(SQUIT) #define P10_STATS TYPE(STATS) +#define P10_SVSJOIN TYPE(SVSJOIN) #define P10_SVSNICK TYPE(SVSNICK) +#define P10_SVSPART TYPE(SVSPART) #define P10_SWHOIS TYPE(SWHOIS) #define P10_TIME TYPE(TIME) #define P10_TOPIC TYPE(TOPIC) @@ -323,8 +329,6 @@ extern int off_channel; extern int DefConLevel; extern int DefConTimeOut; extern char *DefConChanModes; -extern FILE *gfp; -extern FILE *sgfp; static int parse_oplevel(char *str); @@ -376,6 +380,32 @@ GetUserN(const char *numeric) /* using numeric */ return un; } +extern struct userNode *opserv; +static void +check_ctcp(struct userNode *user, struct userNode *bot, char *text, UNUSED_ARG(int server_qualified)) +{ + char *cmd; + /* if its a version reply, do an alert check (only alerts with version=something) */ + if(bot == opserv) { + if(text[0] == '\001') { + text++; + cmd = mysep(&text, " "); + if(!irccasecmp(cmd, "VERSION")) { + char *version = mysep(&text, "\n"); + if(!version) + version = ""; + /* opserv_debug("Opserv got CTCP VERSION Notice from %s: %s", user->nick, version); */ + /* TODO: setup a ctcp_funcs thing to handle this and other CTCPS properly */ + user->version_reply = strdup(version); + /* TODO: put this in the db */ + if(match_ircglob(version, "WebTV;*")) + user->no_notice = true; /* webbies cant see notices */ + } + } + } +} + + static void privmsg_user_helper(struct userNode *un, void *data) { @@ -387,6 +417,7 @@ privmsg_user_helper(struct userNode *un, void *data) } } else { if ((num < num_notice_funcs) && notice_funcs[num]) { + check_ctcp(pd->user, un, pd->text, pd->is_qualified); notice_funcs[num](pd->user, un, pd->text, pd->is_qualified); } } @@ -658,6 +689,7 @@ irc_wallops(const char *format, ...) putsock("%s " P10_WALLOPS " :%s", self->numeric, buffer); } + void irc_notice(struct userNode *from, const char *to, const char *message) { @@ -676,6 +708,18 @@ irc_privmsg(struct userNode *from, const char *to, const char *message) putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message); } +void +irc_privmsg_user(struct userNode *from, struct userNode *to, const char *message) +{ + putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to->numeric, message); +} + +void +irc_version_user(struct userNode *from, struct userNode *to) +{ + irc_privmsg_user(from, to, "\001VERSION\001"); +} + void irc_eob(void) { @@ -698,17 +742,12 @@ irc_eob_ack(void) if (DefConTimeOut > 0) timeq_add(now + DefConTimeOut, defcon_timeout, NULL); } +} - if (gfp) { - fprintf (gfp, "\n"); - fclose(gfp); - } - - - if (sgfp) { - fprintf (sgfp, "\n"); - fclose(sgfp); - } +void +irc_rpong(const char *from1, const char *from2, const char *pingtime, const char *clientinfo) +{ + putsock("%s " P10_RPONG " %s %s %s :%s", self->numeric, from1, from2, pingtime, clientinfo); } void @@ -820,6 +859,7 @@ irc_burst(struct chanNode *chan) pos = base_len; last_mode = -1; } + memcpy(burst_line+pos, mn->user->numeric, strlen(mn->user->numeric)); pos += strlen(mn->user->numeric); if (mn->modes && (mn->modes != last_mode)) { @@ -963,6 +1003,18 @@ irc_join(struct userNode *who, struct chanNode *what) } } +void +irc_svsjoin(struct userNode *from, struct userNode *who, struct chanNode *to) +{ + putsock("%s " P10_SVSJOIN " %s %s "FMT_TIME_T, from->uplink->numeric, who->numeric, to->name, now); +} + +void +irc_svspart(struct userNode *from, struct userNode *who, struct chanNode *to) +{ + putsock("%s " P10_SVSPART " %s %s", from->uplink->numeric, who->numeric, to->name); +} + void irc_kick(struct userNode *who, struct userNode *target, struct chanNode *channel, const char *msg) { @@ -1039,7 +1091,7 @@ irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, host_in_topic = atoi(hstr); } - if (type == 5) { + if (type >= 5) { putsock("%s " P10_TOPIC " %s %s%s%s%s%s " FMT_TIME_T " " FMT_TIME_T " :%s", service->numeric, what->name, who->nick, host_in_topic ? "!" : "", host_in_topic ? (IsSetHost(who) ? sident : who->ident) : "", host_in_topic ? "@" : "", host_in_topic ? shost : "", what->timestamp, now, topic); @@ -1066,6 +1118,48 @@ irc_numeric(struct userNode *user, unsigned int num, const char *format, ...) putsock(":%s %03d %s %s", self->name, num, user->nick, buffer); } +void +irc_mark(struct userNode *user, char *mark) +{ + char *host = user->hostname; + + /* TODO: Allow mark overwrite. If they are marked, and their fakehost is oldmark.hostname, update it to newmark.hostname so mark can be called multiple times. Probably requires ircd modification also */ + if(user->mark) + return; + + /* if the mark will put us over the host length, clip some off the left hand side + * to make room... + */ + if(strlen(host) + 1 + strlen(mark) > HOSTLEN) + host += 1 + ( (strlen(host) + 1 + strlen(mark)) - HOSTLEN ); + putsock("%s " CMD_MARK " %s DNSBL +m %s.%s", self->numeric, user->nick, mark, host); + putsock("%s " CMD_MARK " %s DNSBL_DATA %s", self->numeric, user->nick, mark); + + /* Save it in the user */ + user->mark = strdup(mark); + + /* If they are not otherwise marked, mark their host with fakehost */ + if(!IsFakeHost(user) && !IsSetHost(user) && !(IsHiddenHost(user) && user->handle_info) ) + { + struct modeNode *mn = NULL; + char fakehost[HOSTLEN]; + unsigned int count = 0; + unsigned int n = 0; + + putsock("%s " CMD_FAKEHOST " %s %s.%s", self->numeric, user->numeric, mark, host); + putsock("%s " CMD_MODE " %s +x", self->numeric, user->nick); + + snprintf(fakehost, sizeof(fakehost), "%s.%s", mark, host); + safestrncpy(user->fakehost, fakehost, sizeof(user->fakehost)); + + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + if (strlen(mn->channel->name) >= 1) /* Sanity */ + check_bans(user, mn->channel->name); + } + } +} + static void send_burst(void); static void @@ -1189,7 +1283,8 @@ static CMD_FUNC(cmd_eob) /* now that we know who our uplink is, * we can center the routing map and activate auto-routing. */ - activate_routing(NULL, NULL, NULL); + //activate_routing(NULL, NULL, NULL); + routing_init(); } sender->self_burst = 0; recalc_bursts(sender); @@ -1215,6 +1310,19 @@ static CMD_FUNC(cmd_eob_ack) return 1; } +static CMD_FUNC(cmd_rping) +{ + struct server *dest; + + if (!(dest = GetServerN(argv[1]))) + return 0; + + if (dest == self) + irc_rpong(argv[2], argv[3], argv[4], argv[5]); + + return 1; +} + static CMD_FUNC(cmd_ping) { struct server *srv; @@ -1299,6 +1407,22 @@ static CMD_FUNC(cmd_join) return 1; } +static CMD_FUNC(cmd_svsjoin) +{ + struct create_desc cd; + + if (!(cd.user = GetUserH(argv[1]))) + return 0; + if (argc < 3) + return 0; + else if (argc < 4) + cd.when = now; + else + cd.when = atoi(argv[3]); + parse_foreach(argv[2], join_helper, create_helper, NULL, NULL, &cd); + return 1; +} + static CMD_FUNC(cmd_pong) { if (argc < 3) @@ -1440,6 +1564,25 @@ int client_modify_priv_by_name(struct userNode *who, char *priv, int what) { return 0; } +int check_priv(char *priv) +{ + int i; + + for (i = 0; privtab[i].name; i++) { + if (0 == strcmp(privtab[i].name, priv)) { + return 1; + } + } + return 0; +} + +void +irc_privs(struct userNode *target, char *flag, int add) +{ + client_modify_priv_by_name(target, flag, add); + putsock("%s " P10_PRIVS " %s %s%s", self->numeric, target->numeric, (add == PRIV_ADD) ? "+" : "-", flag); +} + static CMD_FUNC(cmd_privs) { char *tstr = NULL; @@ -1614,6 +1757,38 @@ static CMD_FUNC(cmd_burst) return res; } +/* TODO: + * This is a stub that doesn't actually do anything. It should be completed + * so that bans on *!*@markname.* match users as it does in nefarious + */ +static CMD_FUNC(cmd_mark) +{ + struct userNode *target; + /* + * log_module(MAIN_LOG, LOG_ERROR, "DEBUG: mark, user %s, type %s, arg %s", argv[1], argv[2], argv[3]); + */ + + if(argc < 4) + return 0; + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose mark is changing.", argv[1]); + return 0; + } + if(!strcasecmp(argv[2], "DNSBL")) { + /* DNSBL */ + return 1; + } + else if(!strcasecmp(argv[2], "DNSBL_DATA")) { + /* DNSBL_DATA name */ + target->mark = strdup(argv[3]); + return 1; + + } + /* unknown type of mark */ + return 1; +} + static CMD_FUNC(cmd_mode) { struct chanNode *cn; @@ -1864,6 +2039,19 @@ static CMD_FUNC(cmd_part) return 1; } +static CMD_FUNC(cmd_svspart) +{ + struct userNode *user; + + if (argc < 3) + return 0; + user = GetUserN(argv[1]); + if (!user) + return 0; + parse_foreach(argv[2], part_helper, NULL, NULL, NULL, user); + return 1; +} + static CMD_FUNC(cmd_silence) { struct userNode *user; @@ -1966,6 +2154,7 @@ static CMD_FUNC(cmd_privmsg) pd.is_notice = 0; pd.text = argv[2]; parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); + return 1; } @@ -2164,6 +2353,8 @@ init_parse(void) dict_insert(irc_func_dict, TOK_EOB_ACK, cmd_eob_ack); dict_insert(irc_func_dict, CMD_MODE, cmd_mode); dict_insert(irc_func_dict, TOK_MODE, cmd_mode); + dict_insert(irc_func_dict, CMD_MARK, cmd_mark); + dict_insert(irc_func_dict, TOK_MARK, cmd_mark); dict_insert(irc_func_dict, CMD_NICK, cmd_nick); dict_insert(irc_func_dict, TOK_NICK, cmd_nick); dict_insert(irc_func_dict, CMD_ACCOUNT, cmd_account); @@ -2204,8 +2395,12 @@ init_parse(void) dict_insert(irc_func_dict, TOK_NOTICE, cmd_notice); dict_insert(irc_func_dict, CMD_STATS, cmd_stats); dict_insert(irc_func_dict, TOK_STATS, cmd_stats); + dict_insert(irc_func_dict, CMD_SVSJOIN, cmd_svsjoin); + dict_insert(irc_func_dict, TOK_SVSJOIN, cmd_svsjoin); dict_insert(irc_func_dict, CMD_SVSNICK, cmd_svsnick); dict_insert(irc_func_dict, TOK_SVSNICK, cmd_svsnick); + dict_insert(irc_func_dict, CMD_SVSPART, cmd_svspart); + dict_insert(irc_func_dict, TOK_SVSPART, cmd_svspart); dict_insert(irc_func_dict, CMD_SWHOIS, cmd_dummy); dict_insert(irc_func_dict, TOK_SWHOIS, cmd_dummy); dict_insert(irc_func_dict, CMD_WHOIS, cmd_whois); @@ -2223,6 +2418,11 @@ init_parse(void) dict_insert(irc_func_dict, CMD_ADMIN, cmd_admin); dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin); + dict_insert(irc_func_dict, CMD_RPING, cmd_rping); + dict_insert(irc_func_dict, TOK_RPING, cmd_rping); + dict_insert(irc_func_dict, CMD_RPONG, cmd_dummy); + dict_insert(irc_func_dict, TOK_RPONG, cmd_dummy); + /* In P10, DESTRUCT doesn't do anything except be broadcast to servers. * Apparently to obliterate channels from any servers that think they * exist? @@ -2250,7 +2450,6 @@ init_parse(void) dict_insert(irc_func_dict, TOK_WALLUSERS, cmd_dummy); /* Ignore dnsbl exemptions */ dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy); - dict_insert(irc_func_dict, TOK_MARK, cmd_dummy); dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs); dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs); /* Ignore remote luser */ @@ -2296,6 +2495,7 @@ init_parse(void) userList_init(&dead_users); reg_del_channel_func(remove_unbursted_channel); reg_exit_func(parse_cleanup); + // reg_notice_func(opserv, check_ctcp); } int @@ -2624,6 +2824,9 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); } + if (!uNode->crypthost && uNode->cryptip) + snprintf(uNode->crypthost, sizeof(uNode->crypthost), "%s", strdup(uNode->cryptip)); + uNode->timestamp = timestamp; modeList_init(&uNode->channels); uNode->uplink = uplink; @@ -2698,6 +2901,25 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char } modeList_clean(&user->channels); + + /* Clean up version data */ + if(user->version_reply) { + free(user->version_reply); + user->version_reply = NULL; + } + + /* clean up mark */ + if(user->mark) { + free(user->mark); + user->mark = NULL; + } + + /* clean up geoip data if any */ + if(user->country_code) free(user->country_code); + if(user->city) free(user->city); + if(user->region) free(user->region); + if(user->postal_code) free(user->postal_code); + /* We don't free them, in case we try to privmsg them or something * (like when a stupid oper kills themself). We just put them onto * a list of clients that get freed after processing each line.