X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/c9aeceb56b08ccc83ea3a9acb75bc95567cc67f9..0b401fb654b69fd9649954a9bdd5ff041971e62d:/src/proto-p10.c?ds=inline diff --git a/src/proto-p10.c b/src/proto-p10.c index abda5cc..f59039c 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -22,7 +22,6 @@ #include "chanserv.h" #include "hash.h" #include "helpfile.h" -#include "hosthiding.h" #include "proto-common.c" #include "opserv.h" @@ -80,10 +79,12 @@ #define CMD_PROTO "PROTO" #define CMD_QUIT "QUIT" #define CMD_REHASH "REHASH" +#define CMD_REMOVE "REMOVE" #define CMD_RESET "RESET" #define CMD_RESTART "RESTART" #define CMD_RPING "RPING" #define CMD_RPONG "RPONG" +#define CMD_SASL "SASL" #define CMD_SERVER "SERVER" #define CMD_SERVLIST "SERVLIST" #define CMD_SERVSET "SERVSET" @@ -95,6 +96,7 @@ #define CMD_SMO "SMO" #define CMD_SNO "SNO" #define CMD_SSHUN "SSHUN" +#define CMD_SPAMFILTER "SPAMFILTER" #define CMD_SQUERY "SQUERY" #define CMD_SQUIT "SQUIT" #define CMD_STATS "STATS" @@ -103,6 +105,7 @@ #define CMD_SVSPART "SVSPART" #define CMD_SVSQUIT "SVSQUIT" #define CMD_SWHOIS "SWHOIS" +#define CMD_TEMPSHUN "TEMPSHUN" #define CMD_TIME "TIME" #define CMD_TOPIC "TOPIC" #define CMD_TRACE "TRACE" @@ -120,6 +123,7 @@ #define CMD_WHO "WHO" #define CMD_WHOIS "WHOIS" #define CMD_WHOWAS "WHOWAS" +#define CMD_ZLINE "ZLINE" /* Tokenized commands. */ #define TOK_ACCOUNT "AC" @@ -176,10 +180,12 @@ #define TOK_PROTO "PROTO" #define TOK_QUIT "Q" #define TOK_REHASH "REHASH" +#define TOK_REMOVE "RM" #define TOK_RESET "RESET" #define TOK_RESTART "RESTART" #define TOK_RPING "RI" #define TOK_RPONG "RO" +#define TOK_SASL "SASL" #define TOK_SERVER "S" #define TOK_SERVLIST "SERVSET" #define TOK_SERVSET "SERVSET" @@ -191,6 +197,7 @@ #define TOK_SMO "SMO" #define TOK_SNO "SNO" #define TOK_SSHUN "SSU" +#define TOK_SPAMFILTER "SF" #define TOK_SQUERY "SQUERY" #define TOK_SQUIT "SQ" #define TOK_STATS "R" @@ -199,6 +206,7 @@ #define TOK_SVSPART "SP" #define TOK_SVSQUIT "SX" #define TOK_SWHOIS "SW" +#define TOK_TEMPSHUN "TS" #define TOK_TIME "TI" #define TOK_TOPIC "T" #define TOK_TRACE "TR" @@ -216,6 +224,7 @@ #define TOK_WHO "H" #define TOK_WHOIS "W" #define TOK_WHOWAS "X" +#define TOK_ZLINE "ZL" /* Protocol messages; aliased to full commands or tokens depending on compile-time configuration. ircu prefers tokens WITH THE @@ -281,10 +290,12 @@ #define P10_PROTO TYPE(PROTO) #define P10_QUIT TYPE(QUIT) #define P10_REHASH TYPE(REHASH) +#define P10_REMOVE TYPE(REMOVE) #define P10_RESET TYPE(RESET) #define P10_RESTART TYPE(RESTART) #define P10_RPING TYPE(RPING) #define P10_RPONG TYPE(RPONG) +#define P10_SASL TYPE(SASL) #define P10_SERVER CMD_SERVER #define P10_SERVLIST TYPE(SERVLIST) #define P10_SERVSET TYPE(SERVSET) @@ -296,6 +307,7 @@ #define P10_SMO TYPE(SMO) #define P10_SNO TYPE(SNO) #define P10_SSHUN TYPE(SSHUN) +#define P10_SPAMFILTER TYPE(SPAMFILTER) #define P10_SQUERY TYPE(SQUERY) #define P10_SQUIT TYPE(SQUIT) #define P10_STATS TYPE(STATS) @@ -304,6 +316,7 @@ #define P10_SVSPART TYPE(SVSPART) #define P10_SVSQUIT TYPE(SVSQUIT) #define P10_SWHOIS TYPE(SWHOIS) +#define P10_TEMPSHUN TYPE(TEMPSHUN) #define P10_TIME TYPE(TIME) #define P10_TOPIC TYPE(TOPIC) #define P10_TRACE TYPE(TRACE) @@ -320,6 +333,7 @@ #define P10_WHO TYPE(WHO) #define P10_WHOIS TYPE(WHOIS) #define P10_WHOWAS TYPE(WHOWAS) +#define P10_ZLINE TYPE(ZLINE) #define P10_EXEMPT TYPE(EXEMPT) /* Servers claiming to have a boot or link time before PREHISTORY @@ -340,6 +354,9 @@ static const char *his_servername; static const char *his_servercomment; static int extended_accounts; +/* These correspond to 1 << X: 01234567890123456789012345 */ +const char irc_user_mode_chars[] = "oOiw dkgh x BnIX azDRWHLq"; + 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; @@ -484,10 +501,10 @@ irc_server(struct server *srv) inttobase64(extranum, srv->num_mask, (srv->numeric[1] || (srv->num_mask >= 64*64)) ? 3 : 2); if (srv == self) { - putsock(P10_SERVER " %s %d " FMT_TIME_T " " FMT_TIME_T " J10 %s%s +s6 :%s", + putsock(P10_SERVER " %s %d " FMT_TIME_T " " FMT_TIME_T " J10 %s%s +s6o :%s", srv->name, srv->hops+1, srv->boot, srv->link_time, srv->numeric, extranum, srv->description); } else { - putsock("%s " P10_SERVER " %s %d " FMT_TIME_T " " FMT_TIME_T " %c10 %s%s +s6 :%s", + putsock("%s " P10_SERVER " %s %d " FMT_TIME_T " " FMT_TIME_T " %c10 %s%s +s6o :%s", self->numeric, srv->name, srv->hops+1, srv->boot, srv->link_time, (srv->self_burst ? 'J' : 'P'), srv->numeric, extranum, srv->description); } } @@ -508,7 +525,7 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input) do { if (*input == '_') { unsigned int left; - for (left = (25 - strlen(input)) / 3; left; left--) + for (left = (25 - strlen(input)) / 3 - pos; left; left--) ip->in6[pos++] = 0; input++; } else { @@ -575,41 +592,9 @@ irc_user(struct userNode *user) return; irc_p10_ntop(b64ip, &user->ip); if (user->modes) { - int modelen; char modes[32]; - modelen = 0; - if (IsOper(user)) - modes[modelen++] = 'o'; - if (IsInvisible(user)) - modes[modelen++] = 'i'; - if (IsWallOp(user)) - modes[modelen++] = 'w'; - if (IsService(user)) - modes[modelen++] = 'k'; - if (IsDeaf(user)) - modes[modelen++] = 'd'; - if (IsGlobal(user)) - modes[modelen++] = 'g'; - // sethost - reed/apples - // if (IsHelperIrcu(user)) - if (IsSetHost(user)) - modes[modelen++] = 'h'; - if (IsFakeHost(user)) - modes[modelen++] = 'f'; - if (IsHiddenHost(user)) - modes[modelen++] = 'x'; - if (IsBotM(user)) - modes[modelen++] = 'B'; - if (IsHideChans(user)) - modes[modelen++] = 'n'; - if (IsHideIdle(user)) - modes[modelen++] = 'I'; - if (IsXtraOp(user)) - modes[modelen++] = 'X'; - - modes[modelen] = 0; - + irc_user_modes(user, modes, sizeof(modes)); /* we don't need to put the + in modes because it's in the format string. */ putsock("%s " P10_NICK " %s %d " FMT_TIME_T " %s %s +%s %s %s :%s", user->uplink->numeric, user->nick, user->uplink->hops+1, user->timestamp, user->ident, user->hostname, modes, b64ip, user->numeric, user->info); @@ -847,23 +832,15 @@ irc_introduce(const char *passwd) void irc_gline(struct server *srv, struct gline *gline, int silent) { - if (gline->lastmod) - putsock("%s " P10_GLINE " %s +%s " FMT_TIME_T " " FMT_TIME_T " :%s<%s> %s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->lastmod, silent ? "AUTO " : "", gline->issuer, gline->reason); - else - putsock("%s " P10_GLINE " %s +%s " FMT_TIME_T " :%s<%s> %s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, silent ? "AUTO " : "", gline->issuer, gline->reason); + putsock("%s " P10_GLINE " %s +%s " FMT_TIME_T " " FMT_TIME_T " :%s<%s> %s", + self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, now, silent ? "AUTO " : "", gline->issuer, gline->reason); } void irc_shun(struct server *srv, struct shun *shun) { - if (shun->lastmod) - putsock("%s " P10_SHUN " %s +%s %ld %ld :%s", - self->numeric, (srv ? srv->numeric : "*"), shun->target, shun->expires-now, shun->lastmod, shun->reason); - else - putsock("%s " P10_SHUN " %s +%s %ld :%s", - self->numeric, (srv ? srv->numeric : "*"), shun->target, shun->expires-now, shun->reason); + putsock("%s " P10_SHUN " %s +%s " FMT_TIME_T " " FMT_TIME_T " :<%s> %s", + self->numeric, (srv ? srv->numeric : "*"), shun->target, shun->expires-now, now, shun->issuer, shun->reason); } void @@ -878,13 +855,13 @@ irc_settime(const char *srv_name_mask, time_t new_time) void irc_ungline(const char *mask) { - putsock("%s " P10_GLINE " * -%s", self->numeric, mask); + putsock("%s " P10_GLINE " * -%s " FMT_TIME_T, self->numeric, mask, now); } void irc_unshun(const char *mask) { - putsock("%s " P10_SHUN " * -%s", self->numeric, mask); + putsock("%s " P10_SHUN " * -%s " FMT_TIME_T, self->numeric, mask, now); } void @@ -934,6 +911,10 @@ irc_burst(struct chanNode *chan) if ((n+1)members.used) burst_line[pos++] = ','; } + + if (len > 0 && (chan->banlist.used > 0 || chan->exemptlist.used > 0)) + burst_line[pos++] = ' '; + if (chan->banlist.used) { /* dump the bans */ first_ban = 1; @@ -959,13 +940,18 @@ irc_burst(struct chanNode *chan) } } } + if (chan->exemptlist.used) { /* dump the exempts */ first_exempt = 1; for (n=0; nexemptlist.used; ) { if (first_exempt && (pos < 500)) { - burst_line[pos++] = ' '; + if (chan->banlist.used < 1) { + burst_line[pos++] = ':'; + burst_line[pos++] = '%'; + burst_line[pos++] = ' '; + } burst_line[pos++] = '~'; burst_line[pos++] = ' '; } @@ -1073,7 +1059,7 @@ irc_svspart(struct userNode *from, struct userNode *who, struct chanNode *to) } void -irc_svsquit(struct userNode *from, struct userNode *who, char *reason) +irc_svsquit(struct userNode *from, struct userNode *who, char const *reason) { putsock("%s " P10_SVSQUIT " %s :%s", from->uplink->numeric, who->numeric, reason); } @@ -1108,6 +1094,12 @@ irc_swhois(struct userNode *from, struct userNode *target, const char *message) } +void +irc_tempshun(struct userNode *from, struct userNode *target, int remove, const char *reason) +{ + putsock("%s " P10_TEMPSHUN " %s %s :%s", from->numeric, (remove ? "-" : "+"), target->numeric, reason); +} + void irc_part(struct userNode *who, struct chanNode *what, const char *reason) { @@ -1122,23 +1114,27 @@ void irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, const char *topic) { - int type = 4, host_in_topic = 0, hasident = 0; - const char *hstr, *tstr; + int type = 4, host_in_topic = 0, hasident = 0, hhtype = 0; + const char *hstr, *tstr, *hhstr, *htstr; 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); + hhstr = conf_get_data("server/hidden_host", RECDB_QSTRING); + htstr = conf_get_data("server/hidden_host_type", RECDB_QSTRING); if(tstr) type = atoi(tstr); else type = 4;/* default to 040 style topics */ + if (htstr) + hhtype = atoi(htstr); if (hstr) { - if (IsFakeHost(who)) + if (IsHiddenHost(who) && IsFakeHost(who)) safestrncpy(shost, who->fakehost, sizeof(shost)); - else if (IsSetHost(who)) { + else if (IsHiddenHost(who) && IsSetHost(who)) { hostmask = strdup(who->sethost); if ((host = (strrchr(hostmask, '@')))) { hasident = 1; @@ -1152,6 +1148,10 @@ irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, safestrncpy(sident, who->ident, sizeof(shost)); safestrncpy(shost, host, sizeof(shost)); + } else if (IsHiddenHost(who) && ((hhtype == 1) || (hhtype == 3)) && who->handle_info && hhstr) { + snprintf(shost, sizeof(shost), "%s.%s", who->handle_info->handle, hhstr); + } else if (IsHiddenHost(who) && ((hhtype == 2) || (hhtype == 3)) && who->crypthost[0]) { + safestrncpy(shost, who->crypthost, sizeof(shost)); } else safestrncpy(shost, who->hostname, sizeof(shost)); @@ -1189,6 +1189,34 @@ void irc_mark(struct userNode *user, char *mark) { char *host = user->hostname; + int type = 4; + const char *tstr = NULL; + unsigned int ii = 0; + int markfound = 0; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) + type = atoi(tstr); + else + type = 4; + + if (user->marks) + for (ii=0; iimarks->used; ii++) + if (!irccasecmp(user->marks->list[ii], mark)) + markfound = 1; + + if (!markfound) + { + if (!user->marks) + user->marks = alloc_string_list(1); + string_list_append(user->marks, strdup(mark)); + } + + if (type >= 9) + { + putsock("%s " CMD_MARK " %s MARK %s", self->numeric, user->nick, mark); + return; + } /* 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) @@ -1236,6 +1264,12 @@ void irc_sno(unsigned int mask, char const* format, ...) { putsock("%s " CMD_SNO " %d :%s", self->numeric, mask, buffer); } +void +irc_sasl(struct server* dest, const char *identifier, const char *subcmd, const char *data) +{ + putsock("%s " P10_SASL " %s %s %s %s", self->numeric, dest->numeric, identifier, subcmd, data); +} + static void send_burst(void); static void @@ -1281,7 +1315,7 @@ static CMD_FUNC(cmd_whois) else irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info); - if (IsService(who) || (from == who)) { + if (!IsService(who) || (from == who)) { struct modeNode *mn; mlen = strlen(self->name) + strlen(from->nick) + 12 + strlen(who->nick); len = 0; @@ -1320,7 +1354,6 @@ static CMD_FUNC(cmd_whois) } if (buf[0] != '\0') irc_numeric(from, RPL_WHOISCHANNELS, "%s :%s", who->nick, buf); - return 1; } if (his_servername && his_servercomment && !IsOper(from) && from != who) @@ -1401,7 +1434,6 @@ static CMD_FUNC(cmd_eob) { struct server *sender; dict_iterator_t it; - unsigned int ii; if (!(sender = GetServerH(origin))) return 0; @@ -1422,8 +1454,7 @@ static CMD_FUNC(cmd_eob) } sender->self_burst = 0; recalc_bursts(sender); - for (ii=0; ii5 ? argv[argc-1] : NULL)); + + return 1; +} + static CMD_FUNC(cmd_ping) { struct server *srv; @@ -1580,7 +1627,6 @@ 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) @@ -1590,7 +1636,7 @@ static CMD_FUNC(cmd_nick) unsplit_string(argv+6, argc-9, modes); else strcpy(modes, "+"); - nuser = AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); + AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); } return 1; } @@ -1614,7 +1660,7 @@ static CMD_FUNC(cmd_account) if(!strcmp(argv[2],"C")) { - if((hi = loc_auth(argv[4], argv[5], NULL))) + if((hi = loc_auth(NULL, argv[4], argv[5], NULL))) { /* Return a AC A */ putsock("%s " P10_ACCOUNT " %s A %s "FMT_TIME_T, self->numeric, server->numeric , argv[3], hi->registered); @@ -1630,7 +1676,21 @@ static CMD_FUNC(cmd_account) } else if(!strcmp(argv[2],"H")) /* New enhanced (host) version of C */ { - if((hi = loc_auth(argv[5], argv[6], argv[4] ))) + if((hi = loc_auth(NULL, argv[5], argv[6], argv[4] ))) + { + /* Return a AC A */ + putsock("%s " P10_ACCOUNT " %s A %s "FMT_TIME_T, self->numeric, server->numeric , argv[3], hi->registered); + } + else + { + /* Return a AC D */ + putsock("%s " P10_ACCOUNT " %s D %s", self->numeric, server->numeric , argv[3]); + } + return 1; + } + else if(!strcmp(argv[2],"S")) + { + if((hi = loc_auth(argv[5], argv[6], argv[7], argv[4]))) { /* Return a AC A */ putsock("%s " P10_ACCOUNT " %s A %s "FMT_TIME_T, self->numeric, server->numeric , argv[3], hi->registered); @@ -1677,7 +1737,8 @@ static struct { P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), P(ZLINE), P(LOCAL_ZLINE), P(WIDE_ZLINE), P(LIST_CHAN), P(WHOIS_NOTICE), P(HIDE_IDLE), P(XTRAOP), P(HIDE_CHANNELS), P(DISPLAY_MODE), - P(FREEFORM), P(REMOVE), P(SPAMFILTER), + P(FREEFORM), P(REMOVE), P(SPAMFILTER), P(ADMIN), + P(APASS_OPMODE), P(HIDE_OPER), P(REMOTE), P(SERVICE), #undef P { 0, 0 } }; @@ -1745,6 +1806,12 @@ irc_privs(struct userNode *target, char *flag, int add) putsock("%s " P10_PRIVS " %s %s%s", self->numeric, target->numeric, (add == PRIV_ADD) ? "+" : "-", flag); } +void +irc_raw_privs(struct userNode *target, const char *privs) +{ + putsock("%s " P10_PRIVS " %s %s", self->numeric, target->numeric, privs); +} + static CMD_FUNC(cmd_privs) { char *tstr = NULL; @@ -1788,7 +1855,8 @@ static CMD_FUNC(cmd_privs) for (tmp = x3_strtok(&p, argv[i], ","); tmp; tmp = x3_strtok(&p, NULL, ",")) { if (!strcmp(tmp, "PRIV_NONE")) { - clear_privs(user); + if (now > user->timestamp+5) + clear_privs(user); break; } else client_modify_priv_by_name(user, tmp, what); @@ -1811,7 +1879,9 @@ static CMD_FUNC(cmd_burst) struct modeNode *mNode; long mode; int oplevel = -1; + int type = 0; char *user, *end, sep; + char *tstr; time_t in_timestamp; char* parm = NULL; @@ -1819,6 +1889,11 @@ static CMD_FUNC(cmd_burst) return 0; modes[0] = 0; + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) { + type = atoi(tstr); + } + exemptlist[0] = 0; banlist[0] = 0; @@ -1829,7 +1904,7 @@ static CMD_FUNC(cmd_burst) int n_modes; for (pos=argv[next], n_modes = 1; *pos; pos++) if ((*pos == 'k') || (*pos == 'l') || (*pos == 'A') - || (*pos == 'U')) + || (*pos == 'U') || ((type > 7) && (*pos == 'L'))) n_modes++; if (next + n_modes > argc) n_modes = argc - next; @@ -1838,24 +1913,14 @@ static CMD_FUNC(cmd_burst) break; } case '%': { + ctype = 1; for(parm = mysep(&argv[next], " "); /* parm = first param */ parm; /* While param is not null */ parm = mysep(&argv[next], " ") /* parm = next param */ ) { - switch (parm[0]) { - case '%': { - ctype = 1; - break; - } - case '~': { - ctype = 2; - break; - } - default: { - break; - } - } + if (0 == strcmp("~", parm)) + ctype = 2; if (ctype == 1) { if (bcheck == 0) { /* strip % char off start of very first ban */ @@ -1943,36 +2008,58 @@ static CMD_FUNC(cmd_burst) return res; } -/* TODO: +/* 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) { + const char *tstr; + int type = 4; struct userNode *target; - /* + /* * log_module(MAIN_LOG, LOG_ERROR, "DEBUG: mark, user %s, type %s, arg %s", argv[1], argv[2], argv[3]); */ + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) + type = atoi(tstr); + else + type = 4;/* default to 040 style topics */ + if(argc < 4) return 0; if(!strcasecmp(argv[2], "DNSBL")) { /* DNSBL */ return 1; } - else if(!strcasecmp(argv[2], "DNSBL_DATA")) { + else if(!strcasecmp(argv[2], "DNSBL_DATA") || !strcasecmp(argv[2], "MARK")) { + int markfound = 0; + unsigned int ii = 0; /* DNSBL_DATA name */ target = GetUserH(argv[1]); if(!target) { log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose dnsbl mark is changing.", argv[1]); return 0; } - target->mark = strdup(argv[3]); + if (type >= 9) { + if (target->marks) + for (ii=0; iimarks->used; ii++) + if (!irccasecmp(target->marks->list[ii], argv[3])) + markfound = 1; + if (!markfound) + { + if (!target->marks) + target->marks = alloc_string_list(1); + string_list_append(target->marks, strdup(argv[3])); + } + } else + target->mark = strdup(argv[3]); return 1; - + } else if(!strcasecmp(argv[2], "CVERSION")) { - /* DNSBL_DATA name */ + /* CTCP VERSION mark */ target = GetUserH(argv[1]); if(!target) { log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose version mark is changing.", argv[1]); @@ -1990,6 +2077,24 @@ static CMD_FUNC(cmd_mark) return 1; } + else if(!strcasecmp(argv[2], "SSLCLIFP")) { + /* SSL fingerprint mark */ + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose SSL fingerprint mark is changing.", argv[1]); + return 0; + } + + char *sslfp = unsplit_string(argv + 3, argc - 3, NULL); + if(!sslfp) + sslfp = ""; + + target->sslfp = strdup(sslfp); + + nickserv_do_autoauth(target); + + return 1; + } /* unknown type of mark */ return 1; } @@ -2111,7 +2216,7 @@ static CMD_FUNC(cmd_clearmode) static CMD_FUNC(cmd_topic) { struct chanNode *cn; - time_t chan_ts, topic_ts; + time_t topic_ts; struct userNode *user; if (argc < 3) @@ -2124,15 +2229,12 @@ static CMD_FUNC(cmd_topic) if (argc == 5) { /* Asuka / Topic Bursting IRCu's */ user = GetUserH(origin); - chan_ts = atoi(argv[2]); topic_ts = atoi(argv[3]); } else if (argc >= 6) { /* Nefarious 0.5.0 */ user = GetUserH(strtok(argv[2], "!")); - chan_ts = atoi(argv[3]); topic_ts = atoi(argv[4]); } else { /* Regular IRCu (No Topic Bursting)*/ user = GetUserH(origin); - chan_ts = cn->timestamp; topic_ts = now; } @@ -2179,37 +2281,28 @@ static CMD_FUNC(cmd_num_topic) static CMD_FUNC(cmd_num_gline) { - time_t lastmod; if (argc < 7) { if (argc < 6) return 0; - else { - lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0; - gline_add(origin, argv[3], atoi(argv[4])-now, argv[argc - 1], now, lastmod, 0, 0); - } + else + gline_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0, 0); } else { - if (!strcmp(argv[5], "+")) { - lastmod = (argc > 6) ? strtoul(argv[5], NULL, 0) : 0; - gline_add(origin, argv[3], atoi(argv[4])-now, argv[argc - 1], now, now, 0, 0); - } + if (!strcmp(argv[5], "+")) + gline_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0, 0); } return 1; } static CMD_FUNC(cmd_num_shun) { - time_t lastmod; - if (argc < 7) { if (argc < 6) return 0; else - lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0; - shun_add(origin, argv[3], atoi(argv[4])-now, argv[argc - 1], now, now, 0); + shun_add(origin, argv[3], atoi(argv[4])-now, argv[5], now, 0); } else { if (!strcmp(argv[5], "+")) - lastmod = (argc > 6) ? strtoul(argv[5], NULL, 0) : 0; - shun_add(origin, argv[3], atoi(argv[4])-now, argv[argc - 1], now, now, 0); + shun_add(origin, argv[3], atoi(argv[4])-now, argv[6], now, 0); } return 1; } @@ -2237,9 +2330,11 @@ static CMD_FUNC(cmd_kill) * Ghost response to a KILL we sent out earlier. So we only * whine if the target is local. */ - if (!strncmp(argv[1], self->numeric, strlen(self->numeric))) + if (!strncmp(argv[1], self->numeric, strlen(self->numeric))) { log_module(MAIN_LOG, LOG_ERROR, "Unable to find kill victim %s", argv[1]); - return 0; + return 0; + } + return 1; } if (IsLocal(user) && IsService(user)) { @@ -2275,7 +2370,15 @@ static CMD_FUNC(cmd_silence) if (argc < 2) return 0; - user = GetUserN(argv[1]); + if (strncmp(argv[1], "*", 2) == 0) + { + if (!(user = GetUserH(origin))) { + log_module(MAIN_LOG, LOG_ERROR, "Could not find SILENCE origin user %s", origin); + return 0; + } + } + else + user = GetUserN(argv[1]); /* Sanity, go nuts if this happens */ if (!user) @@ -2375,14 +2478,11 @@ 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) - nuser = 1; if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) { } else { @@ -2433,15 +2533,12 @@ static CMD_FUNC(cmd_away) static CMD_FUNC(cmd_gline) { - time_t lastmod; - if (argc < 3) return 0; if (argv[2][0] == '+') { if (argc < 5) return 0; - lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0; - gline_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, lastmod, 0, 0); + gline_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, 0, 0); return 1; } else if (argv[2][0] == '-') { gline_remove(argv[2]+1, 0); @@ -2460,7 +2557,7 @@ static CMD_FUNC(cmd_sgline) if (!(sender = GetServerH(origin))) return 0; - gline_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, now, 1, 0); + gline_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1, 0); return 1; } @@ -2474,21 +2571,18 @@ static CMD_FUNC(cmd_sshun) if (!(sender = GetServerH(origin))) return 0; - shun_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, now, 1); + shun_add(origin, argv[1], strtoul(argv[2], NULL, 0), argv[argc-1], now, 1); return 1; } static CMD_FUNC(cmd_shun) { - time_t lastmod; - if (argc < 3) return 0; if (argv[2][0] == '+') { if (argc < 5) return 0; - lastmod = (argc > 5) ? strtoul(argv[5], NULL, 0) : 0; - shun_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, now, 0); + shun_add(origin, argv[2]+1, strtoul(argv[3], NULL, 0), argv[argc-1], now, 0); return 1; } else if (argv[2][0] == '-') { shun_remove(argv[2]+1, 0); @@ -2517,10 +2611,11 @@ free_user(struct userNode *user) } static void -parse_cleanup(void) +parse_cleanup(UNUSED_ARG(void *extra)) { unsigned int nn; free(of_list); + free(of_list_extra); free(privmsg_funcs); num_privmsg_funcs = 0; free(notice_funcs); @@ -2540,7 +2635,7 @@ p10_conf_reload(void) { } static void -remove_unbursted_channel(struct chanNode *cNode) { +remove_unbursted_channel(struct chanNode *cNode, UNUSED_ARG(void *extra)) { if (unbursted_channels) dict_remove(unbursted_channels, cNode->name); } @@ -2646,6 +2741,8 @@ init_parse(void) 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_TEMPSHUN, cmd_dummy); + dict_insert(irc_func_dict, TOK_TEMPSHUN, cmd_dummy); dict_insert(irc_func_dict, CMD_WHOIS, cmd_whois); dict_insert(irc_func_dict, TOK_WHOIS, cmd_whois); dict_insert(irc_func_dict, CMD_GLINE, cmd_gline); @@ -2674,6 +2771,9 @@ init_parse(void) dict_insert(irc_func_dict, CMD_RPONG, cmd_dummy); dict_insert(irc_func_dict, TOK_RPONG, cmd_dummy); + dict_insert(irc_func_dict, CMD_SASL, cmd_sasl); + dict_insert(irc_func_dict, TOK_SASL, cmd_sasl); + /* In P10, DESTRUCT doesn't do anything except be broadcast to servers. * Apparently to obliterate channels from any servers that think they * exist? @@ -2706,11 +2806,19 @@ init_parse(void) /* ignore ALIST for now */ dict_insert(irc_func_dict, TOK_ALIST, cmd_dummy); dict_insert(irc_func_dict, CMD_ALIST, cmd_dummy); + /* ignore SPAMFILTER */ + dict_insert(irc_func_dict, TOK_SPAMFILTER, cmd_dummy); + dict_insert(irc_func_dict, CMD_SPAMFILTER, cmd_dummy); /* Ignore remote luser */ dict_insert(irc_func_dict, TOK_LUSERS, cmd_dummy); /* We have reliable clock! Always! Wraaa! */ dict_insert(irc_func_dict, CMD_SETTIME, cmd_dummy); dict_insert(irc_func_dict, TOK_SETTIME, cmd_dummy); + /* Ignore ZLINE/ZL/REMOVE/RM */ + dict_insert(irc_func_dict, CMD_ZLINE, cmd_dummy); + dict_insert(irc_func_dict, TOK_ZLINE, cmd_dummy); + dict_insert(irc_func_dict, CMD_REMOVE, cmd_dummy); + dict_insert(irc_func_dict, TOK_REMOVE, cmd_dummy); /* ignore /trace and /motd commands targetted at us */ dict_insert(irc_func_dict, TOK_TRACE, cmd_dummy); @@ -2749,8 +2857,8 @@ init_parse(void) memset(notice_funcs, 0, sizeof(privmsg_func_t)*num_notice_funcs); userList_init(&dead_users); - reg_del_channel_func(remove_unbursted_channel); - reg_exit_func(parse_cleanup); + reg_del_channel_func(remove_unbursted_channel, NULL); + reg_exit_func(parse_cleanup, NULL); // reg_notice_func(opserv, check_ctcp); } @@ -2983,7 +3091,7 @@ AddLocalUser(const char *nick, const char *ident, const char *hostname, const ch if (!hostname) hostname = self->name; make_numeric(self, local_num, numeric); - return AddUser(self, nick, ident, hostname, modes, numeric, desc, now, "AAAAAA"); + return AddUser(self, nick, ident, hostname, modes, numeric, desc, timestamp, "AAAAAA"); } struct userNode * @@ -3026,9 +3134,7 @@ 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) { struct userNode *oldUser, *uNode; - unsigned int n, ignore_user, dummy; - char *tstr; - int type; + unsigned int ignore_user, dummy; if ((strlen(numeric) < 3) || (strlen(numeric) > 5)) { log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", (void*)uplink, nick, numeric); @@ -3086,17 +3192,6 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * safestrncpy(uNode->numeric, numeric, sizeof(uNode->numeric)); irc_p10_pton(&uNode->ip, realip); - tstr = conf_get_data("server/type", RECDB_QSTRING); - type = atoi(tstr); - if (type > 6) { - if (irc_in_addr_is_ipv4(uNode->ip)) { - make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip); - make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); - } else if (irc_in_addr_is_ipv6(uNode->ip)) { - 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->idle_since = timestamp; @@ -3124,8 +3219,7 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * } if (IsLocal(uNode)) irc_user(uNode); - for (n=0; (ndead; n++) - nuf_list[n](uNode); + call_new_user_funcs(uNode); if ((uNode->loc == 1) && (uNode->handle_info)) send_func_list(uNode); @@ -3137,7 +3231,6 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * void DelUser(struct userNode* user, struct userNode *killer, int announce, const char *why) { - unsigned int n; verify(user); @@ -3153,13 +3246,15 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char /* Call these in reverse order so ChanServ can update presence information before NickServ nukes the handle_info. */ - for (n = duf_used; n > 0; ) - duf_list[--n](user, killer, why); + call_del_user_funcs(user, killer, why); user->uplink->clients--; user->uplink->users[user->num_local] = NULL; - if (IsOper(user)) + if (IsOper(user)) { userList_remove(&curr_opers, user); + if (count_opers > 0 && !IsBotM(user) && !IsService(user) && !IsHideOper(user)) + count_opers--; + } /* remove from global dictionary, but not if after a collide */ if (user == dict_find(clients, user->nick, NULL)) dict_remove(clients, user->nick); @@ -3190,11 +3285,19 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char user->version_reply = NULL; } + /* Clean up SSL fingerprint data */ + if(user->sslfp) { + free(user->sslfp); + user->sslfp = NULL; + } + /* clean up mark */ if(user->mark) { free(user->mark); user->mark = NULL; } + free_string_list(user->marks); + user->marks = NULL; /* clean up geoip data if any */ if(user->country_code) free(user->country_code); @@ -3216,6 +3319,8 @@ static void call_oper_funcs(struct userNode *user); void mod_usermode(struct userNode *user, const char *mode_change) { int add = 1; + long setmodes = 0; + int donemodes = 0; const char *word = mode_change; if (!user || !mode_change) @@ -3223,12 +3328,16 @@ void mod_usermode(struct userNode *user, const char *mode_change) { call_user_mode_funcs(user, mode_change); + setmodes = user->modes; + while (*word != ' ' && *word) word++; while (*word == ' ') word++; - while (1) { + while (!donemodes) { #define do_user_mode(FLAG) do { if (add) user->modes |= FLAG; else user->modes &= ~FLAG; } while (0) switch (*mode_change++) { - case 0: case ' ': return; + case 0: case ' ': + donemodes = 1; + break; case '+': add = 1; break; case '-': add = 0; break; case 'o': @@ -3253,6 +3362,7 @@ void mod_usermode(struct userNode *user, const char *mode_change) { case 'g': do_user_mode(FLAGS_GLOBAL); break; case 'B': do_user_mode(FLAGS_BOT); break; case 'n': do_user_mode(FLAGS_HIDECHANS); break; + case 'p': do_user_mode(FLAGS_HIDECHANS); break; case 'I': do_user_mode(FLAGS_HIDEIDLE); break; case 'X': do_user_mode(FLAGS_XTRAOP); break; case 'C': do_user_mode(FLAGS_CLOAKHOST); @@ -3320,9 +3430,48 @@ void mod_usermode(struct userNode *user, const char *mode_change) { assign_fakehost(user, host, 0); } break; + case 'a': do_user_mode(FLAGS_ADMIN); break; + case 'z': do_user_mode(FLAGS_SSL); break; + case 'D': do_user_mode(FLAGS_PRIVDEAF); break; + case 'R': do_user_mode(FLAGS_ACCOUNTONLY); break; + case 'W': do_user_mode(FLAGS_WHOIS); break; + case 'H': do_user_mode(FLAGS_HIDEOPER); break; + case 'L': do_user_mode(FLAGS_NOLINK); break; + case 'q': do_user_mode(FLAGS_COMMONCHANSONLY); break; } #undef do_user_mode } + + // Set user mode +o + if (!(setmodes & FLAGS_OPER) && IsOper(user)) { + if (!IsBotM(user) && !IsService(user) && !IsHideOper(user)) + count_opers++; + } + + // Set user mode -o + if ((setmodes & FLAGS_OPER) && !IsOper(user)) { + if (count_opers > 1 && !(setmodes & FLAGS_BOT) && + !(setmodes & FLAGS_SERVICE) && !(setmodes & FLAGS_HIDEOPER)) + count_opers--; + } + + // Set +H, +k or +B + if (!(setmodes & FLAGS_HIDEOPER) && + !(setmodes & FLAGS_SERVICE) && + !(setmodes & FLAGS_BOT) && + (IsHideOper(user) || IsService(user) || IsBotM(user))) { + if ((setmodes & FLAGS_OPER) && IsOper(user) && count_opers > 0) + count_opers--; + } + + // Set -H, -k or -B + if (((setmodes & FLAGS_HIDEOPER) || + (setmodes & FLAGS_SERVICE) || + (setmodes & FLAGS_BOT)) && + !IsHideOper(user) && !IsService(user) && !IsBotM(user)) { + if ((setmodes & FLAGS_OPER) && IsOper(user)) + count_opers++; + } } static int @@ -3440,7 +3589,8 @@ mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, un case 'A': if (add) { if ((in_arg >= argc) - || keyncpy(change->new_upass, modes[in_arg++], sizeof(change->new_upass))) + || keyncpy(change->new_apass, modes[in_arg++], sizeof(change->new_apass))) + goto error; change->modes_set |= MODE_APASS; } else { change->modes_clear |= MODE_APASS; @@ -3617,6 +3767,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod DO_MODE_CHAR(NOQUITMSGS, 'Q'); DO_MODE_CHAR(NOAMSG, 'T'); DO_MODE_CHAR(OPERSONLY, 'O'); + DO_MODE_CHAR(ADMINSONLY, 'a'); DO_MODE_CHAR(REGISTERED, 'z'); DO_MODE_CHAR(SSLONLY, 'Z'); DO_MODE_CHAR(HIDEMODE, 'L'); @@ -3673,6 +3824,7 @@ mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod DO_MODE_CHAR(NOQUITMSGS, 'Q'); DO_MODE_CHAR(NOAMSG, 'T'); DO_MODE_CHAR(OPERSONLY, 'O'); + DO_MODE_CHAR(ADMINSONLY, 'a'); DO_MODE_CHAR(REGISTERED, 'z'); DO_MODE_CHAR(SSLONLY, 'Z'); DO_MODE_CHAR(HIDEMODE, 'L'); @@ -3748,6 +3900,7 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff) DO_MODE_CHAR(NOQUITMSGS, 'Q'); DO_MODE_CHAR(NOAMSG, 'T'); DO_MODE_CHAR(OPERSONLY, 'O'); + DO_MODE_CHAR(ADMINSONLY, 'a'); DO_MODE_CHAR(REGISTERED, 'z'); DO_MODE_CHAR(SSLONLY, 'Z'); DO_MODE_CHAR(HIDEMODE, 'L'); @@ -3772,62 +3925,23 @@ mod_chanmode_format(struct mod_chanmode *change, char *outbuff) DO_MODE_CHAR(NOQUITMSGS, 'Q'); DO_MODE_CHAR(NOAMSG, 'T'); DO_MODE_CHAR(OPERSONLY, 'O'); + DO_MODE_CHAR(ADMINSONLY, 'a'); DO_MODE_CHAR(REGISTERED, 'z'); DO_MODE_CHAR(SSLONLY, 'Z'); DO_MODE_CHAR(HIDEMODE, 'L'); -#undef DO_MODE_CHAR - switch (change->modes_set & (MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS)) { - /* Doing this implementation has been a pain in the arse, I hope I didn't forget a possible combination */ - case MODE_KEY|MODE_LIMIT|MODE_APASS|MODE_UPASS: - used += sprintf(outbuff+used, "lkAU %d %s %s %s", change->new_limit, change->new_key,change->new_apass, change->new_upass); - break; - case MODE_KEY|MODE_LIMIT|MODE_APASS: - used += sprintf(outbuff+used, "lkA %d %s %s", change->new_limit, change->new_key, change->new_apass); - break; - case MODE_KEY|MODE_LIMIT|MODE_UPASS: - used += sprintf(outbuff+used, "lkU %d %s %s", change->new_limit, change->new_key, change->new_upass); - break; - case MODE_KEY|MODE_APASS|MODE_UPASS: - used += sprintf(outbuff+used, "kAU %s %s %s", change->new_key, change->new_apass, change->new_upass); - break; - - case MODE_KEY|MODE_APASS: - used += sprintf(outbuff+used, "kA %s %s", change->new_key, change->new_apass); - break; - case MODE_KEY|MODE_UPASS: - used += sprintf(outbuff+used, "kU %s %s", change->new_key, change->new_upass); - break; - case MODE_KEY|MODE_LIMIT: - used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key); - break; - - case MODE_LIMIT|MODE_UPASS: - used += sprintf(outbuff+used, "lU %d %s", change->new_limit, change->new_upass); - break; - case MODE_LIMIT|MODE_APASS: - used += sprintf(outbuff+used, "lA %d %s", change->new_limit, change->new_apass); - break; - case MODE_APASS|MODE_UPASS: - used += sprintf(outbuff+used, "AU %s %s", change->new_apass, change->new_upass); - - case MODE_LIMIT|MODE_APASS|MODE_UPASS: - used += sprintf(outbuff+used, "lAU %d %s %s", change->new_limit, change->new_apass, change->new_upass); - break; + DO_MODE_CHAR(KEY, 'k'); + DO_MODE_CHAR(LIMIT, 'l'); + DO_MODE_CHAR(APASS, 'A'); + DO_MODE_CHAR(UPASS, 'U'); +#undef DO_MODE_CHAR - case MODE_APASS: - used += sprintf(outbuff+used, "A %s", change->new_apass); - break; - case MODE_UPASS: - used += sprintf(outbuff+used, "U %s", change->new_upass); - break; - case MODE_KEY: - used += sprintf(outbuff+used, "k %s", change->new_key); - break; - case MODE_LIMIT: - used += sprintf(outbuff+used, "l %d", change->new_limit); - break; - } +#define DO_MODE_PARM(BIT, PARM) if (change->modes_set & MODE_##BIT) used += sprintf(outbuff+used, " %s", PARM); + DO_MODE_PARM(KEY, change->new_key); + if (change->modes_set & MODE_LIMIT) used += sprintf(outbuff+used, " %d", change->new_limit); + DO_MODE_PARM(APASS, change->new_apass); + DO_MODE_PARM(UPASS, change->new_upass); +#undef DO_MODE_PARM } outbuff[used] = 0; return outbuff;