X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/a6a4707efec425579538e4591381924408044411..075d79322a27a1e04807a9f4b85a52c7eb7c3ede:/src/proto-p10.c diff --git a/src/proto-p10.c b/src/proto-p10.c index 264c858..05c92a0 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -20,8 +20,11 @@ #include "nickserv.h" #include "chanserv.h" +#include "hash.h" +#include "helpfile.h" #include "hosthiding.h" #include "proto-common.c" +#include "opserv.h" /* Full commands. */ #define CMD_ACCOUNT "ACCOUNT" @@ -90,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" @@ -178,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" @@ -276,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) @@ -302,6 +311,8 @@ */ #define PREHISTORY 780000000 +#define MODELEN 40 + KEYLEN + static struct server *servers_num[64*64]; static privmsg_func_t *privmsg_funcs; static unsigned int num_privmsg_funcs; @@ -315,9 +326,14 @@ static int extended_accounts; static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, time_t timestamp, const char *realip); extern int off_channel; +extern int DefConLevel; +extern int DefConTimeOut; +extern char *DefConChanModes; static int parse_oplevel(char *str); +char privbuf[512] = ""; + /* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the * server and Y's indentifying the client on that server. */ struct server* @@ -380,6 +396,43 @@ privmsg_user_helper(struct userNode *un, void *data) } } +/* equiv to user doing /connect server port target */ +void irc_connect(struct userNode *user, char *server, unsigned int port, struct server *target) +{ + putsock("%s " P10_CONNECT " %s %d %s", user->numeric, server, port, target->numeric); +} + +void +irc_squit_route(struct server *srv, const char *message, ...) +{ + va_list arg_list; + char buffer[MAXLEN]; + va_start(arg_list, message); + vsnprintf(buffer, MAXLEN-2, message, arg_list); + buffer[MAXLEN-1] = 0; + + /* When would we squit ourselves exactly?? -Rubin */ + if(srv == self && cManager.uplink->state == CONNECTED ) { + unsigned int i; + + /* Quit all clients linked to me. */ + for(i = 0; i <= self->num_mask; i++) { + if(!self->users[i]) + continue; + irc_quit(self->users[i], buffer); + } + } + + putsock("%s " P10_SQUIT " %s %d :%s", self->numeric, srv->name, 0, buffer); + + if(srv == self) { + /* Force a reconnect to the currently selected server. */ + cManager.uplink->tries = 0; + log_module(MAIN_LOG, LOG_INFO, "Squitting from uplink: %s", buffer); + close_socket(); + } +} + void irc_server(struct server *srv) { @@ -598,6 +651,17 @@ irc_wallchops(struct userNode *from, const char *to, const char *message) putsock("%s " P10_WALLCHOPS " %s :%s", from->numeric, to, message); } +void +irc_wallops(const char *format, ...) +{ + va_list arg_list; + char buffer[MAXLEN]; + va_start(arg_list, format); + vsnprintf(buffer, MAXLEN-2, format, arg_list); + buffer[MAXLEN-1] = 0; + putsock("%s " P10_WALLOPS " :%s", self->numeric, buffer); +} + void irc_notice(struct userNode *from, const char *to, const char *message) { @@ -626,6 +690,18 @@ void irc_eob_ack(void) { putsock("%s " P10_EOB_ACK, self->numeric); + + char *nick; + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + nick = strdup(str); + + if (nick && (DefConLevel < 5)) { + DefConProcess(GetUserH(nick)); + + if (DefConTimeOut > 0) + timeq_add(now + DefConTimeOut, defcon_timeout, NULL); + } } void @@ -726,6 +802,8 @@ irc_burst(struct chanNode *chan) if (len) burst_line[pos++] = ' '; + if(chan->members.used < 1) + return; /* dont burst empty channels (created by discrims) */ /* dump the users */ for (n=0; nmembers.used; n++) { mn = chan->members.list[n]; @@ -878,6 +956,12 @@ 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_kick(struct userNode *who, struct userNode *target, struct chanNode *channel, const char *msg) { @@ -923,15 +1007,41 @@ irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, { int type = 4; - const char *str; - str = conf_get_data("server/type", RECDB_QSTRING); - if(str) - type = atoi(str); + int host_in_topic = 0; + const char *hstr, *tstr; + char *host, *hostmask; + char shost[MAXLEN]; + char sident[MAXLEN]; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + hstr = conf_get_data("server/host_in_topic", RECDB_QSTRING); + if(tstr) + type = atoi(tstr); else type = 4;/* default to 040 style topics */ - if (type == 5) { - putsock("%s " P10_TOPIC " %s %s " FMT_TIME_T " " FMT_TIME_T " :%s", service->numeric, what->name, who->nick, what->timestamp, now, topic); + if (hstr) { + if (IsFakeHost(who)) + safestrncpy(shost, who->fakehost, sizeof(shost)); + else if (IsSetHost(who)) { + hostmask = strdup(who->sethost); + if ((host = (strrchr(hostmask, '@')))) + *host++ = '\0'; + else + host = hostmask; + + safestrncpy(sident, hostmask, sizeof(shost)); + safestrncpy(shost, host, sizeof(shost)); + } else + safestrncpy(shost, who->hostname, sizeof(shost)); + + host_in_topic = atoi(hstr); + } + + 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); } else { who = service; putsock("%s " P10_TOPIC " %s :%s", who->numeric, what->name, topic); @@ -1057,6 +1167,7 @@ static CMD_FUNC(cmd_server) return 1; } + static CMD_FUNC(cmd_eob) { struct server *sender; @@ -1073,11 +1184,21 @@ static CMD_FUNC(cmd_eob) unbursted_channels = NULL; irc_eob(); irc_eob_ack(); + + /* now that we know who our uplink is, + * we can center the routing map and activate auto-routing. + */ + activate_routing(NULL, NULL, NULL); } sender->self_burst = 0; recalc_bursts(sender); for (ii=0; iiuplink != self) + routing_handle_connect(sender->name, sender->uplink->name); return 1; } @@ -1177,6 +1298,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) @@ -1200,6 +1337,7 @@ static CMD_FUNC(cmd_nick) NickChange(user, argv[1], 1); } else { struct server *serv; + struct userNode *nuser; char modes[MAXLEN]; /* new nick */ if (argc < 9) @@ -1209,7 +1347,7 @@ static CMD_FUNC(cmd_nick) unsplit_string(argv+6, argc-9, modes); else strcpy(modes, "+"); - AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); + nuser = AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); } return 1; } @@ -1265,6 +1403,118 @@ static CMD_FUNC(cmd_fakehost) return 1; } +static struct { + char *name; + unsigned int priv; +} privtab[] = { +#define P(priv) { #priv, PRIV_ ## priv } + P(CHAN_LIMIT), P(MODE_LCHAN), P(WALK_LCHAN), P(DEOP_LCHAN), + P(SHOW_INVIS), P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL), + P(LOCAL_KILL), P(REHASH), P(RESTART), P(DIE), + P(GLINE), P(LOCAL_GLINE), P(JUPE), P(LOCAL_JUPE), + P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX), + P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), + P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(FORCE_OPMODE), + P(FORCE_LOCAL_OPMODE), P(REMOTEREHASH), P(CHECK), P(SEE_SECRET_CHAN), + P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), +#undef P + { 0, 0 } +}; + +char *client_report_privs(struct userNode *client) +{ + int i; + + privbuf[0] = '\0'; + for (i = 0; privtab[i].name; i++) { + if (HasPriv(client, privtab[i].priv)) { + strcat(privbuf, privtab[i].name); + strcat(privbuf, " "); + } + } + + privbuf[strlen(privbuf)] = 0; + + return privbuf; +} + +int client_modify_priv_by_name(struct userNode *who, char *priv, int what) { + int i = 0; + assert(0 != priv); + assert(0 != who); + + for (i = 0; privtab[i].name; i++) { + if (0 == strcmp(privtab[i].name, priv)) { + if (what == PRIV_ADD) + GrantPriv(who, privtab[i].priv); + else if (what == PRIV_DEL) { + RevokePriv(who, privtab[i].priv); + } + } + } + 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; + int type = 0; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) + type = atoi(tstr); + + if (type < 6) + return 1; /* silently ignore */ + + struct userNode *user = argc > 1 ? GetUserN(argv[1]) : NULL; + char buf[512] = ""; + int what = PRIV_ADD; + char *p = 0; + char *tmp; + unsigned int i; + + if (argc < 3) + return 0; + + if (!user) + return 0; + + for (i=1; itimestamp = atoi(argv[argc-1]); } + if (checkDefCon(DEFCON_NO_MODE_CHANGE) && !IsOper(un)) { + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + if (str) { + char modes[MODELEN]; + struct userNode *opserv = GetUserH(str); + + send_message_type(4, un, opserv, "Channel modes cannot be changed due to DefCon level %d in effect, please try again soon", DefConLevel); + irc_make_chanmode(cn, modes); + irc_mode(opserv, cn, modes); + irc_mode(opserv, cn, DefConChanModes); + } + return 1; + } + + return mod_chanmode(un, cn, argv+2, argc-2, MCP_ALLOW_OVB|MCP_FROM_SERVER|(un ? MC_NOTIFY : 0)); } @@ -1632,10 +1898,24 @@ static CMD_FUNC(cmd_part) return 1; } +static CMD_FUNC(cmd_svspart) +{ + struct userNode *user; + + if (argc < 3) + return 0; + user = GetUserH(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; char *mask; + char *new_mask; unsigned int i; if (argc < 2) @@ -1655,7 +1935,7 @@ static CMD_FUNC(cmd_silence) if (!user->handle_info) return 1; - mask = strdup(argv[2]); + mask = argv[2]; if (*mask == '-') { for (i=0; ihandle_info->ignores->used; i++) { @@ -1668,9 +1948,9 @@ static CMD_FUNC(cmd_silence) return 1; /* Already on the users NickServ ignore list, safely ignore */ } - string_list_append(user->handle_info->ignores, mask+1); + new_mask = strdup(mask+1); + string_list_append(user->handle_info->ignores, new_mask); } - return 1; } @@ -1685,6 +1965,7 @@ static CMD_FUNC(cmd_kick) static CMD_FUNC(cmd_squit) { struct server *server; + char *uplink; if (argc < 4) return 0; @@ -1699,7 +1980,13 @@ static CMD_FUNC(cmd_squit) return 1; } + uplink = strdup(server->uplink->name); DelServer(server, 0, argv[3]); + /* if its a pingout and pingout connecting is enabled + or its a read error and readerror connecting is enabled + or were doing a "N" and i need to connect that server somewhere */ + routing_handle_squit(argv[1], uplink, argv[3]); + free(uplink); return 1; } @@ -1711,6 +1998,18 @@ static CMD_FUNC(cmd_privmsg) pd.user = GetUserH(origin); if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) return 1; + + if (checkDefCon(DEFCON_OPER_ONLY) && !IsOper(pd.user)) { + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + if (str) + send_message_type(4, pd.user, GetUserH(str), "Services are currently not available, please try again soon"); + return 1; + } + + if (checkDefCon(DEFCON_SILENT_OPER_ONLY) && !IsOper(pd.user)) + return 1; /* Silently Ignore */ + pd.is_notice = 0; pd.text = argv[2]; parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); @@ -1720,14 +2019,46 @@ static CMD_FUNC(cmd_privmsg) static CMD_FUNC(cmd_notice) { struct privmsg_desc pd; + struct server *srv; + int nuser = 0; + if (argc != 3) return 0; + pd.user = GetUserH(origin); - if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) - return 1; - pd.is_notice = 1; - pd.text = argv[2]; - parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); + if(!pd.user) + nuser = 1; + if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) { + } + else { + pd.is_notice = 1; + pd.text = argv[2]; + parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); + } + + srv = GetServerH(origin); + if(srv) { + char *sargv[MAXNUMPARAMS]; + int sargc; + + sargc = split_line(argv[2], true, MAXNUMPARAMS, sargv); + + if(!strcasecmp(sargv[0], "Connect:")) { + /* :Connect: Host shoe.loxxin.net not listed in ircd.conf */ + if(!strcasecmp(sargv[3], "not") && !strcasecmp(sargv[4], "listed")) { + routing_handle_connect_failure(srv, sargv[2], unsplit_string(sargv+3, sargc-3, NULL)); + } + } + else if(!strcasecmp(sargv[0], "Link")) { + /* :Link with mephisto.etheria.cx cancelled: Server mephisto.etheria.cx[216.46.33.71] + * + * :Link with laptop.afternet.org cancelled: Connection refused + */ + if(!strcasecmp(sargv[3], "cancelled:")) { + routing_handle_connect_failure(srv, sargv[2], unsplit_string(sargv+4, sargc-4, NULL)); + } + } + } return 1; } @@ -1920,8 +2251,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); @@ -1967,8 +2302,8 @@ init_parse(void) /* Ignore dnsbl exemptions */ dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy); dict_insert(irc_func_dict, TOK_MARK, cmd_dummy); - /* Ignore privs */ - dict_insert(irc_func_dict, TOK_PRIVS, cmd_dummy); + dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs); + dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs); /* Ignore remote luser */ dict_insert(irc_func_dict, TOK_LUSERS, cmd_dummy); /* We have reliable clock! Always! Wraaa! */ @@ -2340,6 +2675,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; @@ -2349,6 +2687,9 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * uNode->num_local = base64toint(numeric+strlen(uNode->uplink->numeric), 3) & uNode->uplink->num_mask; uNode->uplink->users[uNode->num_local] = uNode; mod_usermode(uNode, modes); + + set_geoip_info(uNode); + if (ignore_user) return uNode;