DLLFUNC CMD_FUNC(m_svsfline) { if (!IsServer(sptr)) return 0; if (parc < 2) return 0; switch (*parv[1]) { /* Allow non-U:lines to send ONLY SVSFLINE +, but don't send it out * unless it is from a U:line -- codemastr */ case '+': { if (parc < 4) return 0; if (!Find_deny_dcc(parv[2])) DCCdeny_add(parv[2], parv[3], DCCDENY_HARD, CONF_BAN_TYPE_AKILL); if (IsULine(sptr)) sendto_serv_butone_token(cptr, sptr->name, MSG_SVSFLINE, TOK_SVSFLINE, "+ %s :%s", parv[2], parv[3]); break; } case '-': { ConfigItem_deny_dcc *deny; if (!IsULine(sptr)) return 0; if (parc < 3) return 0; if (!(deny = Find_deny_dcc(parv[2]))) break; DCCdeny_del(deny); sendto_serv_butone_token(cptr, sptr->name, MSG_SVSFLINE, TOK_SVSFLINE, "%s", parv[2]); break; } case '*': { if (!IsULine(sptr)) return 0; dcc_wipe_services(); sendto_serv_butone_token(cptr, sptr->name, MSG_SVSFLINE, TOK_SVSFLINE, "*"); break; } } return 0; }
// Parts all insecure users on a +z channel (NOT KICK) void f_part_insecure_users (aChannel *chptr) { Member *member, *mb2; aClient *cptr; char *comment = "Insecure user not allowed on secure channel (+z)"; for (member = chptr->members; member; member = mb2) { mb2 = member->next; cptr = member->cptr; if (MyClient(cptr) && !IsSecureConnect(cptr) && !IsULine(cptr)) { RunHook4(HOOKTYPE_LOCAL_PART, cptr, &me, chptr, comment); if ((chptr->mode.mode & MODE_AUDITORIUM) && is_chanownprotop(cptr, chptr)) { sendto_chanops_butone(cptr, chptr, ":%s!%s@%s PART %s :%s", cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment); sendto_prefix_one(cptr, &me, ":%s!%s@%s PART %s :%s", cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment); } else { sendto_channel_butserv(chptr, &me, ":%s!%s@%s PART %s :%s", cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment); } sendto_one(cptr, err_str(ERR_SECUREONLYCHAN), me.name, cptr->name, chptr->chname); sendto_serv_butone_token(&me, cptr->name, MSG_PART, TOK_PART, "%s :%s", chptr->chname, comment); remove_user_from_channel(cptr, chptr); } } }
/* * SVSLOGIN message * * parv[0]: source * parv[1]: propagation mask * parv[2]: target PUID * parv[3]: ESVID */ static int m_svslogin(aClient *cptr, aClient *sptr, int parc, char *parv[]) { if (!SASL_SERVER || MyClient(sptr) || (parc < 3) || !parv[3]) return 0; if (!stricmp(parv[1], me.name)) { aClient *target_p; /* is the PUID valid? */ if ((target_p = decode_puid(parv[2])) == NULL) return 0; if (target_p->user == NULL) make_user(target_p); strlcpy(target_p->user->svid, parv[3], sizeof(target_p->user->svid)); sendto_one(target_p, err_str(RPL_LOGGEDIN), me.name, BadPtr(target_p->name) ? "*" : target_p->name, BadPtr(target_p->name) ? "*" : target_p->name, BadPtr(target_p->user->username) ? "*" : target_p->user->username, BadPtr(target_p->user->realhost) ? "*" : target_p->user->realhost, target_p->user->svid, target_p->user->svid); return 0; } /* not for us; propagate. */ sendto_serv_butone_token(cptr, parv[0], MSG_SVSLOGIN, TOK_SVSLOGIN, "%s %s %s", parv[1], parv[2], parv[3]); return 0; }
static int abort_sasl(struct Client *cptr) { if (cptr->sasl_out == 0 || cptr->sasl_complete) return 0; cptr->sasl_out = cptr->sasl_complete = 0; sendto_one(cptr, err_str(ERR_SASLABORTED), me.name, BadPtr(cptr->name) ? "*" : cptr->name); if (*cptr->sasl_agent) { aClient *agent_p = find_client(cptr->sasl_agent, NULL); if (agent_p != NULL) { sendto_serv_butone_token(NULL, me.name, MSG_SASL, TOK_SASL, "%s %s D A", AGENT_SID(agent_p), encode_puid(cptr)); return 0; } } sendto_serv_butone_token(NULL, me.name, MSG_SASL, TOK_SASL, "* %s D A", encode_puid(cptr)); return 0; }
/* * AUTHENTICATE message * * parv[0]: prefix * parv[1]: data */ static int m_authenticate(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *agent_p = NULL; /* Failing to use CAP REQ for sasl is a protocol violation. */ if (!SASL_SERVER || !MyConnect(sptr) || BadPtr(parv[1]) || !CHECKPROTO(sptr, PROTO_SASL)) return 0; if (sptr->sasl_complete) { sendto_one(sptr, err_str(ERR_SASLALREADY), me.name, BadPtr(sptr->name) ? "*" : sptr->name); return 0; } if ((parv[1][0] == ':') || strchr(parv[1], ' ')) { sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, "*", "AUTHENTICATE", "Invalid parameter"); return 0; } if (strlen(parv[1]) > 400) { sendto_one(sptr, err_str(ERR_SASLTOOLONG), me.name, BadPtr(sptr->name) ? "*" : sptr->name); return 0; } if (*sptr->sasl_agent) agent_p = find_client(sptr->sasl_agent, NULL); if (agent_p == NULL) sendto_serv_butone_token(NULL, me.name, MSG_SASL, TOK_SASL, "%s %s S %s", SASL_SERVER, encode_puid(sptr), parv[1]); else sendto_serv_butone_token(NULL, me.name, MSG_SASL, TOK_SASL, "%s %s C %s", AGENT_SID(agent_p), encode_puid(sptr), parv[1]); sptr->sasl_out++; return 0; }
/* * EOS (End Of Sync) command. * Type: Broadcast * Purpose: Broadcasted over a network if a server is synced (after the users, channels, * etc are introduced). Makes us able to know if a server is linked. * History: Added in beta18 (in cvs since 2003-08-11) by Syzop */ DLLFUNC CMD_FUNC(m_eos) { if (!IsServer(sptr)) return 0; sptr->serv->flags.synced = 1; /* pass it on ^_- */ #ifdef DEBUGMODE ircd_log(LOG_ERROR, "[EOSDBG] m_eos: got sync from %s (path:%s)", sptr->name, cptr->name); ircd_log(LOG_ERROR, "[EOSDBG] m_eos: broadcasting it back to everyone except route from %s", cptr->name); #endif sendto_serv_butone_token(cptr, parv[0], MSG_EOS, TOK_EOS, "", NULL); return 0; }
int m_sdesc(aClient *cptr, aClient *sptr, int parc, char *parv[]) { if (!IsAdmin(sptr) && !IsCoAdmin(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name); return 0; } if (parc < 2) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "SDESC"); return 0; } if (strlen(parv[1]) < 1) if (MyConnect(sptr)) { sendto_one(sptr, ":%s NOTICE %s :*** Nothing to change to (SDESC)", me.name, sptr->name); return 0; } if (strlen(parv[1]) > (REALLEN)) { if (MyConnect(sptr)) { sendto_one(sptr, ":%s NOTICE %s :*** /SDESC Error: \"Server info\" may maximum be %i characters of length", me.name, sptr->name, REALLEN); } return 0; } ircsprintf(sptr->srvptr->info, "%s", parv[1]); sendto_serv_butone_token(cptr, sptr->name, MSG_SDESC, TOK_SDESC, ":%s", parv[1]); if (MyConnect(sptr)) { sendto_one(sptr, ":%s NOTICE %s :Your \"server description\" is now set to be %s - you have to set it manually to undo it", me.name, parv[0], parv[1]); return 0; } sendto_ops("Server description for %s is now '%s' changed by %s", sptr->srvptr->name, sptr->srvptr->info, parv[0]); return 0; }
/* ** m_svsnick ** parv[0] = sender ** parv[1] = old nickname ** parv[2] = new nickname ** parv[3] = timestamp */ int m_svsnick(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; aClient *ocptr; /* Other client */ if (!IsULine(sptr) || parc < 4 || (strlen(parv[2]) > NICKLEN)) return -1; /* This looks like an error anyway -Studded */ if (hunt_server_token(cptr, sptr, MSG_SVSNICK, TOK_SVSNICK, "%s %s :%s", 1, parc, parv) != HUNTED_ISME) return 0; /* Forwarded, done */ if (do_nick_name(parv[2]) == 0) return 0; if (!(acptr = find_person(parv[1], NULL))) return 0; /* User not found, bail out */ if ((ocptr = find_client(parv[2], NULL)) && ocptr != acptr) /* Collision */ { exit_client(acptr, acptr, sptr, "Nickname collision due to Services enforced " "nickname change, your nick was overruled"); return 0; } if (acptr != ocptr) acptr->umodes &= ~UMODE_REGNICK; acptr->lastnick = TS2ts(parv[3]); sendto_common_channels(acptr, ":%s NICK :%s", parv[1], parv[2]); add_history(acptr, 1); sendto_serv_butone_token(NULL, parv[1], MSG_NICK, TOK_NICK, "%s :%ld", parv[2], TS2ts(parv[3])); (void)del_from_client_hash_table(acptr->name, acptr); hash_check_watch(acptr, RPL_LOGOFF); sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has been forced to change his/her nickname to %s", acptr->name, acptr->user->username, acptr->user->realhost, parv[2]); RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, acptr, parv[2]); strlcpy(acptr->name, parv[2], sizeof acptr->name); add_to_client_hash_table(parv[2], acptr); hash_check_watch(acptr, RPL_LOGON); return 0; }
/* ** m_sendsno - Written by Syzop, bit based on SENDUMODE from Stskeeps ** parv[0] = sender prefix ** parv[1] = target snomask ** parv[2] = message text ** Servers can use this to: ** :server.unreal.net SENDSNO e :Hiiiii */ DLLFUNC int m_sendsno(aClient *cptr, aClient *sptr, int parc, char *parv[]) { char *sno, *msg, *p; long snomask = 0; int i; #ifndef NO_FDLIST int j; #endif aClient *acptr; if ((parc < 3) || BadPtr(parv[2])) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SENDSNO"); return 0; } sno = parv[1]; msg = parv[2]; /* Forward to others... */ sendto_serv_butone_token(cptr, sptr->name, MSG_SENDSNO, TOK_SENDSNO, "%s :%s", parv[1], parv[2]); for (p = sno; *p; p++) { for(i = 0; i <= Snomask_highest; i++) { if (Snomask_Table[i].flag == *p) { snomask |= Snomask_Table[i].mode; break; } } } #ifdef NO_FDLIST for(i = 0; i <= LastSlot; i++) #else for (i = oper_fdlist.entry[j = 1]; j <= oper_fdlist.last_entry; i = oper_fdlist.entry[++j]) #endif if ((acptr = local[i]) && IsPerson(acptr) && IsAnOper(acptr) && (acptr->user->snomask & snomask)) { sendto_one(acptr, ":%s NOTICE %s :%s", me.name, acptr->name, msg); } return 0; }
/* * SASL message * * parv[0]: prefix * parv[1]: distribution mask * parv[2]: target PUID * parv[3]: mode/state * parv[4]: data * parv[5]: out-of-bound data */ static int m_sasl(aClient *cptr, aClient *sptr, int parc, char *parv[]) { if (!SASL_SERVER || MyClient(sptr) || (parc < 4) || !parv[4]) return 0; if (!stricmp(parv[1], me.name)) { aClient *target_p; /* is the PUID valid? */ if ((target_p = decode_puid(parv[2])) == NULL) return 0; if (target_p->user == NULL) make_user(target_p); /* reject if another SASL agent is answering */ if (*target_p->sasl_agent && stricmp(parv[0], target_p->sasl_agent)) return 0; else strlcpy(target_p->sasl_agent, parv[0], sizeof(target_p->sasl_agent)); if (*parv[3] == 'C') sendto_one(target_p, "AUTHENTICATE %s", parv[4]); else if (*parv[3] == 'D') { if (*parv[4] == 'F') sendto_one(target_p, err_str(ERR_SASLFAIL), me.name, BadPtr(target_p->name) ? "*" : target_p->name); else if (*parv[4] == 'S') { target_p->sasl_complete++; sendto_one(target_p, err_str(RPL_SASLSUCCESS), me.name, BadPtr(target_p->name) ? "*" : target_p->name); } *target_p->sasl_agent = '\0'; } return 0; } /* not for us; propagate. */ sendto_serv_butone_token(cptr, parv[0], MSG_SASL, TOK_SASL, "%s %s %c %s %s", parv[1], parv[2], *parv[3], parv[4], parc > 5 ? parv[5] : ""); return 0; }
/* ** m_globops (write to opers who are +g currently online) ** parv[0] = sender prefix ** parv[1] = message text */ DLLFUNC CMD_FUNC(m_globops) { char *message; message = parc > 1 ? parv[1] : NULL; if (BadPtr(message)) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "GLOBOPS"); return 0; } if (MyClient(sptr) && !OPCanGlobOps(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } sendto_serv_butone_token(IsServer(cptr) ? cptr : NULL, parv[0], MSG_GLOBOPS, TOK_GLOBOPS, ":%s", message); sendto_failops_whoare_opers("from %s: %s", parv[0], message); return 0; }
/* ** m_part ** parv[0] = sender prefix ** parv[1] = channel ** parv[2] = comment (added by Lefler) */ DLLFUNC CMD_FUNC(m_part) { aChannel *chptr; Membership *lp; char *p = NULL, *name; char *commentx = (parc > 2 && parv[2]) ? parv[2] : NULL; char *comment; int n; if (parc < 2 || parv[1][0] == '\0') { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PART"); return 0; } if (MyClient(sptr)) { if (IsShunned(sptr)) commentx = NULL; if (STATIC_PART) { if (!strcasecmp(STATIC_PART, "yes") || !strcmp(STATIC_PART, "1")) commentx = NULL; else if (!strcasecmp(STATIC_PART, "no") || !strcmp(STATIC_PART, "0")) ; /* keep original reason */ else commentx = STATIC_PART; } if (commentx) { n = dospamfilter(sptr, commentx, SPAMF_PART, parv[1], 0, NULL); if (n == FLUSH_BUFFER) return n; if (n < 0) commentx = NULL; } } for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL) { chptr = get_channel(sptr, name, 0); if (!chptr) { sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name); continue; } if (check_channelmask(sptr, cptr, name)) continue; /* 'commentx' is the general part msg, but it can be changed * per-channel (eg some chans block badwords, strip colors, etc) * so we copy it to 'comment' and use that in this for loop :) */ comment = commentx; if (!(lp = find_membership_link(sptr->user->channel, chptr))) { /* Normal to get get when our client did a kick ** for a remote client (who sends back a PART), ** so check for remote client or not --Run */ if (MyClient(sptr)) sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], name); continue; } if (!IsAnOper(sptr) && !is_chanownprotop(sptr, chptr)) { #ifdef STRIPBADWORDS int blocked = 0; #endif /* Banned? No comment allowed ;) */ if (comment && is_banned(sptr, chptr, BANCHK_MSG)) comment = NULL; /* And other things... */ if ((chptr->mode.mode & MODE_NOCOLOR) && comment) { if (strchr((char *)comment, 3) || strchr((char *)comment, 27)) { comment = NULL; } } if ((chptr->mode.mode & MODE_MODERATED) && comment && !has_voice(sptr, chptr) && !is_halfop(sptr, chptr)) { comment = NULL; } if ((chptr->mode.mode & MODE_STRIP) && comment) { comment = (char *)StripColors(comment); } #ifdef STRIPBADWORDS #ifdef STRIPBADWORDS_CHAN_ALWAYS if (comment) { comment = (char *)stripbadwords_channel(comment, &blocked); } #else if ((chptr->mode.extmode & EXTMODE_STRIPBADWORDS) && comment) { comment = (char *)stripbadwords_channel(comment, &blocked); } #endif #endif } /* +M and not logged in to services? */ if ((chptr->mode.mode & MODE_MODREG) && !IsLoggedIn(sptr) && !IsAnOper(sptr)) comment = NULL; if (MyConnect(sptr)) { Hook *tmphook; for (tmphook = Hooks[HOOKTYPE_PRE_LOCAL_PART]; tmphook; tmphook = tmphook->next) { comment = (*(tmphook->func.pcharfunc))(sptr, chptr, comment); if (!comment) break; } } /* Send to other servers... */ if (!comment) sendto_serv_butone_token(cptr, parv[0], MSG_PART, TOK_PART, "%s", chptr->chname); else sendto_serv_butone_token(cptr, parv[0], MSG_PART, TOK_PART, "%s :%s", chptr->chname, comment); if (1) { if ((chptr->mode.mode & MODE_AUDITORIUM) && !is_chanownprotop(sptr, chptr)) { if (!comment) { sendto_chanops_butone(NULL, chptr, ":%s!%s@%s PART %s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); if (!is_chan_op(sptr, chptr) && MyClient(sptr)) sendto_one(sptr, ":%s!%s@%s PART %s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); } else { sendto_chanops_butone(NULL, chptr, ":%s!%s@%s PART %s %s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname, comment); if (!is_chan_op(cptr, chptr) && MyClient(sptr)) sendto_one(sptr, ":%s!%s@%s PART %s %s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname, comment); } } else { if (!comment) sendto_channel_butserv(chptr, sptr, PARTFMT, parv[0], chptr->chname); else sendto_channel_butserv(chptr, sptr, PARTFMT2, parv[0], chptr->chname, comment); } if (MyClient(sptr)) RunHook4(HOOKTYPE_LOCAL_PART, cptr, sptr, chptr, comment); else RunHook4(HOOKTYPE_REMOTE_PART, cptr, sptr, chptr, comment); remove_user_from_channel(sptr, chptr); } } return 0; }
int check_for_chan_flood(aClient *cptr, aClient *sptr, aChannel *chptr) { Membership *lp; MembershipL *lp2; int c_limit, t_limit, banthem; if (!MyClient(sptr)) return 0; if (IsOper(sptr) || IsULine(sptr)) return 0; if (is_skochanop(sptr, chptr)) return 0; if (!(lp = find_membership_link(sptr->user->channel, chptr))) return 0; lp2 = (MembershipL *) lp; #ifdef NEWCHFLOODPROT if (!chptr->mode.floodprot || !chptr->mode.floodprot->l[FLD_TEXT]) return 0; c_limit = chptr->mode.floodprot->l[FLD_TEXT]; t_limit = chptr->mode.floodprot->per; banthem = (chptr->mode.floodprot->a[FLD_TEXT] == 'b') ? 1 : 0; #else if ((chptr->mode.msgs < 1) || (chptr->mode.per < 1)) return 0; c_limit = chptr->mode.msgs; t_limit = chptr->mode.per; banthem = chptr->mode.kmode; #endif /* if current - firstmsgtime >= mode.per, then reset, * if nummsg > mode.msgs then kick/ban */ Debug((DEBUG_ERROR, "Checking for flood +f: firstmsg=%d (%ds ago), new nmsgs: %d, limit is: %d:%d", lp2->flood.firstmsg, TStime() - lp2->flood.firstmsg, lp2->flood.nmsg + 1, c_limit, t_limit)); if ((TStime() - lp2->flood.firstmsg) >= t_limit) { /* reset */ lp2->flood.firstmsg = TStime(); lp2->flood.nmsg = 1; return 0; /* forget about it.. */ } /* increase msgs */ lp2->flood.nmsg++; if ((lp2->flood.nmsg) > c_limit) { char comment[1024], mask[1024]; ircsprintf(comment, "Flooding (Limit is %i lines per %i seconds)", c_limit, t_limit); if (banthem) { /* ban. */ ircsprintf(mask, "*!*@%s", GetHost(sptr)); add_listmode(&chptr->banlist, &me, chptr, mask); sendto_serv_butone(&me, ":%s MODE %s +b %s 0", me.name, chptr->chname, mask); sendto_channel_butserv(chptr, &me, ":%s MODE %s +b %s", me.name, chptr->chname, mask); } sendto_channel_butserv(chptr, &me, ":%s KICK %s %s :%s", me.name, chptr->chname, sptr->name, comment); sendto_serv_butone_token(cptr, me.name, MSG_KICK, TOK_KICK, "%s %s :%s", chptr->chname, sptr->name, comment); remove_user_from_channel(sptr, chptr); return 1; } return 0; }
int m_chgident(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; char *s; int legalident = 1; if (MyClient(sptr) && !IsAnOper(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } #ifdef DISABLE_USERMOD if (MyClient(sptr)) { sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGIDENT", "This command is disabled on this server"); return 0; } #endif if ((parc < 3) || !*parv[2]) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "CHGIDENT"); return 0; } if (strlen(parv[2]) > (USERLEN)) { sendnotice(sptr, "*** ChgIdent Error: Requested ident too long -- rejected."); return 0; } /* illegal?! */ for (s = parv[2]; *s; s++) { if ((*s == '~') && (s == parv[2])) continue; if (!isallowed(*s)) { legalident = 0; } } if (legalident == 0) { sendnotice(sptr, "*** /ChgIdent Error: A ident may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them"); return 0; } if ((acptr = find_person(parv[1], NULL))) { DYN_LOCAL(char, did_parts, acptr->user->joined); switch (UHOST_ALLOWED) { case UHALLOW_NEVER: if (MyClient(sptr)) { sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGIDENT", "This command is disabled on this server"); DYN_FREE(did_parts); return 0; } break; case UHALLOW_ALWAYS: break; case UHALLOW_NOCHANS: if (IsPerson(acptr) && MyClient(sptr) && acptr->user->joined) { sendnotice(sptr, "*** /ChgIdent can not be used while %s is on a channel", acptr->name); DYN_FREE(did_parts); return 0; } break; case UHALLOW_REJOIN: rejoin_doparts(acptr, did_parts); /* join sent later when the ident has been changed */ break; } if (!IsULine(sptr)) { sendto_snomask(SNO_EYES, "%s changed the virtual ident of %s (%s@%s) to be %s", sptr->name, acptr->name, acptr->user->username, GetHost(acptr), parv[2]); /* Logging ability added by XeRXeS */ ircd_log(LOG_CHGCMDS, "CHGIDENT: %s changed the virtual ident of %s (%s@%s) to be %s", sptr->name, acptr->name, acptr->user->username, GetHost(acptr), parv[2]); } sendto_serv_butone_token(cptr, sptr->name, MSG_CHGIDENT, TOK_CHGIDENT, "%s %s", acptr->name, parv[2]); ircsprintf(acptr->user->username, "%s", parv[2]); if (UHOST_ALLOWED == UHALLOW_REJOIN) rejoin_dojoinandmode(acptr, did_parts); DYN_FREE(did_parts); return 0; }
/* m_sajoin() - Lamego - Wed Jul 21 20:04:48 1999 Copied off PTlink IRCd (C) PTlink coders team. Coded for Sadmin by Stskeeps also Modified by NiQuiL ([email protected]) parv[0] - sender parv[1] - nick to make join parv[2] - channel(s) to join */ DLLFUNC CMD_FUNC(m_sajoin) { aClient *acptr; char jbuf[BUFSIZE]; int did_anything = 0; if (!IsSAdmin(sptr) && !IsULine(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (parc < 3) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SAJOIN"); return 0; } if (!(acptr = find_person(parv[1], NULL))) { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]); return 0; } if (MyClient(acptr)) { char *name, *p = NULL; int i, parted = 0; *jbuf = 0; /* Now works like m_join */ for (i = 0, name = strtoken(&p, parv[2], ","); name; name = strtoken(&p, NULL, ",")) { aChannel *chptr; Membership *lp; if (strlen(name) > CHANNELLEN) name[CHANNELLEN] = 0; clean_channelname(name); if (*name == '0' && !atoi(name)) { (void)strcpy(jbuf, "0"); i = 1; parted = 1; continue; } if (check_channelmask(sptr, cptr, name) == -1 || *name == '0' || !IsChannelName(name)) { sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name); continue; } chptr = get_channel(acptr, name, 0); if (!parted && chptr && (lp = find_membership_link(acptr->user->channel, chptr))) { sendto_one(sptr, err_str(ERR_USERONCHANNEL), me.name, parv[0], parv[1], name); continue; } if (*jbuf) (void)strlcat(jbuf, ",", sizeof jbuf); (void)strlncat(jbuf, name, sizeof jbuf, sizeof(jbuf) - i - 1); i += strlen(name) + 1; } if (!*jbuf) return -1; i = 0; strcpy(parv[2], jbuf); *jbuf = 0; for (name = strtoken(&p, parv[2], ","); name; name = strtoken(&p, NULL, ",")) { int flags; aChannel *chptr; Membership *lp; if (*name == '0' && !atoi(name)) { did_anything = 1; while ((lp = acptr->user->channel)) { chptr = lp->chptr; sendto_channel_butserv(chptr, acptr, ":%s PART %s :%s", acptr->name, chptr->chname, "Left all channels"); if (MyConnect(acptr)) RunHook4(HOOKTYPE_LOCAL_PART, acptr, acptr, chptr, "Left all channels"); remove_user_from_channel(acptr, chptr); } sendto_serv_butone_token(acptr, acptr->name, MSG_JOIN, TOK_JOIN, "0"); strcpy(jbuf, "0"); i = 1; continue; } flags = (ChannelExists(name)) ? CHFL_DEOPPED : CHFL_CHANOP; chptr = get_channel(acptr, name, CREATE); if (chptr && (lp = find_membership_link(acptr->user->channel, chptr))) continue; if ((chptr->mode.mode & MODE_ONLYSECURE) && !IsSecure(acptr)) { sendnotice(sptr, "You cannot SAJOIN %s to %s because the channel is +z and the user is not connected via SSL", acptr->name, chptr->chname); continue; } join_channel(chptr, acptr, acptr, flags); did_anything = 1; if (*jbuf) (void)strlcat(jbuf, ",", sizeof jbuf); (void)strlncat(jbuf, name, sizeof jbuf, sizeof(jbuf) - i - 1); i += strlen(name) + 1; } if (did_anything) { sendnotice(acptr, "*** You were forced to join %s", jbuf); sendto_realops("%s used SAJOIN to make %s join %s", sptr->name, acptr->name, jbuf); sendto_serv_butone(&me, ":%s GLOBOPS :%s used SAJOIN to make %s join %s", me.name, sptr->name, acptr->name, jbuf); /* Logging function added by XeRXeS */ ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s", sptr->name, parv[1], jbuf); } } else { sendto_one(acptr, ":%s SAJOIN %s %s", parv[0], parv[1], parv[2]); /* Logging function added by XeRXeS */ ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s", sptr->name, parv[1], parv[2]); } return 0; }
/* ** m_nick ** parv[0] = sender prefix ** parv[1] = nickname ** if from new client -taz ** parv[2] = nick password ** if from server: ** parv[2] = hopcount ** parv[3] = timestamp ** parv[4] = username ** parv[5] = hostname ** parv[6] = servername ** if NICK version 1: ** parv[7] = servicestamp ** parv[8] = info ** if NICK version 2: ** parv[7] = servicestamp ** parv[8] = umodes ** parv[9] = virthost, * if none ** parv[10] = info ** if NICKIP: ** parv[10] = ip ** parv[11] = info */ DLLFUNC CMD_FUNC(m_nick) { aTKline *tklban; int ishold; aClient *acptr, *serv = NULL; aClient *acptrs; char nick[NICKLEN + 2], *s; Membership *mp; time_t lastnick = (time_t) 0; int differ = 1, update_watch = 1; unsigned char newusr = 0, removemoder = 1; /* * If the user didn't specify a nickname, complain */ if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } strncpyzt(nick, parv[1], NICKLEN + 1); if (MyConnect(sptr) && sptr->user && !IsAnOper(sptr)) { if ((sptr->user->flood.nick_c >= NICK_COUNT) && (TStime() - sptr->user->flood.nick_t < NICK_PERIOD)) { /* Throttle... */ sendto_one(sptr, err_str(ERR_NCHANGETOOFAST), me.name, sptr->name, nick, (int)(NICK_PERIOD - (TStime() - sptr->user->flood.nick_t))); return 0; } } /* For a local clients, do proper nickname checking via do_nick_name() * and reject the nick if it returns false. * For remote clients, do a quick check by using do_remote_nick_name(), * if this returned false then reject and kill it. -- Syzop */ if ((IsServer(cptr) && !do_remote_nick_name(nick)) || (!IsServer(cptr) && !do_nick_name(nick))) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], parv[1], "Illegal characters"); if (IsServer(cptr)) { ircstp->is_kill++; sendto_failops("Bad Nick: %s From: %s %s", parv[1], parv[0], get_client_name(cptr, FALSE)); sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])", me.name, parv[1], me.name, parv[1], nick, cptr->name); if (sptr != cptr) { /* bad nick change */ sendto_serv_butone(cptr, ":%s KILL %s :%s (%s <- %s!%s@%s)", me.name, parv[0], me.name, get_client_name(cptr, FALSE), parv[0], sptr->user ? sptr->username : "", sptr->user ? sptr->user->server : cptr->name); sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "BadNick"); } } return 0; } /* Kill quarantined opers early... */ if (IsServer(cptr) && (sptr->from->flags & FLAGS_QUARANTINE) && (parc >= 11) && strchr(parv[8], 'o')) { ircstp->is_kill++; /* Send kill to uplink only, hasn't been broadcasted to the rest, anyway */ sendto_one(cptr, ":%s KILL %s :%s (Quarantined: no global oper privileges allowed)", me.name, parv[1], me.name); sendto_realops("QUARANTINE: Oper %s on server %s killed, due to quarantine", parv[1], sptr->name); /* (nothing to exit_client or to free, since user was never added) */ return 0; } /* ** Protocol 4 doesn't send the server as prefix, so it is possible ** the server doesn't exist (a lagged net.burst), in which case ** we simply need to ignore the NICK. Also when we got that server ** name (again) but from another direction. --Run */ /* ** We should really only deal with this for msgs from servers. ** -- Aeto */ if (IsServer(cptr) && (parc > 7 && (!(serv = (aClient *)find_server_b64_or_real(parv[6])) || serv->from != cptr->from))) { sendto_realops("Cannot find server %s (%s)", parv[6], backupbuf); return 0; } /* ** Check against nick name collisions. ** ** Put this 'if' here so that the nesting goes nicely on the screen :) ** We check against server name list before determining if the nickname ** is present in the nicklist (due to the way the below for loop is ** constructed). -avalon */ /* I managed to f**k this up i guess --stskeeps */ if ((acptr = find_server(nick, NULL))) { if (MyConnect(sptr)) { #ifdef GUEST if (IsUnknown(sptr)) { RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv); return 0; } #endif sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick); return 0; /* NICK message ignored */ } } /* ** Check for a Q-lined nickname. If we find it, and it's our ** client, just reject it. -Lefler ** Allow opers to use Q-lined nicknames. -Russell */ if (!stricmp("ircd", nick)) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, "Reserved for internal IRCd purposes"); return 0; } if (!stricmp("irc", nick)) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, "Reserved for internal IRCd purposes"); return 0; } if (MyClient(sptr)) /* local client changin nick afterwards.. */ { int xx; spamfilter_build_user_string(spamfilter_user, nick, sptr); xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL); if (xx < 0) return xx; } if (!IsULine(sptr) && (tklban = find_qline(sptr, nick, &ishold))) { if (IsServer(sptr) && !ishold) /* server introducing new client */ { acptrs = (aClient *)find_server_b64_or_real(sptr->user == NULL ? (char *)parv[6] : (char *)sptr->user-> server); /* (NEW: no unregistered q:line msgs anymore during linking) */ if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced)) sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, (*sptr->name != 0 && !IsServer(sptr) ? sptr->name : "<unregistered>"), acptrs ? acptrs->name : "unknown server"); } if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */ { sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, sptr->name, sptr->srvptr ? sptr->srvptr->name : "<unknown>"); } if (!IsServer(cptr)) /* local */ { if (ishold) { sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, tklban->reason); return 0; } if (!IsOper(cptr)) { sptr->since += 4; /* lag them up */ sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, BadPtr(parv[0]) ? "*" : parv[0], nick, tklban->reason); sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.", nick, get_client_name(cptr, FALSE)); return 0; /* NICK message ignored */ } } } /* ** acptr already has result from previous find_server() */ if (acptr) { /* ** We have a nickname trying to use the same name as ** a server. Send out a nick collision KILL to remove ** the nickname. As long as only a KILL is sent out, ** there is no danger of the server being disconnected. ** Ultimate way to jupiter a nick ? >;-). -avalon */ sendto_failops("Nick collision on %s(%s <- %s)", sptr->name, acptr->from->name, get_client_name(cptr, FALSE)); ircstp->is_kill++; sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)", me.name, sptr->name, me.name, acptr->from->name, /* NOTE: Cannot use get_client_name ** twice here, it returns static ** string pointer--the other info ** would be lost */ get_client_name(cptr, FALSE)); sptr->flags |= FLAGS_KILLED; return exit_client(cptr, sptr, &me, "Nick/Server collision"); } if (MyClient(cptr) && !IsOper(cptr)) cptr->since += 3; /* Nick-flood prot. -Donwulff */ if (!(acptr = find_client(nick, NULL))) goto nickkilldone; /* No collisions, all clear... */ /* ** If the older one is "non-person", the new entry is just ** allowed to overwrite it. Just silently drop non-person, ** and proceed with the nick. This should take care of the ** "dormant nick" way of generating collisions... */ /* Moved before Lost User Field to fix some bugs... -- Barubary */ if (IsUnknown(acptr) && MyConnect(acptr)) { /* This may help - copying code below */ if (acptr == cptr) return 0; acptr->flags |= FLAGS_KILLED; exit_client(NULL, acptr, &me, "Overridden"); goto nickkilldone; } /* A sanity check in the user field... */ if (acptr->user == NULL) { /* This is a Bad Thing */ sendto_failops("Lost user field for %s in change from %s", acptr->name, get_client_name(cptr, FALSE)); ircstp->is_kill++; sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; /* Here's the previous versions' desynch. If the old one is messed up, trash the old one and accept the new one. Remember - at this point there is a new nick coming in! Handle appropriately. -- Barubary */ exit_client(NULL, acptr, &me, "Lost user field"); goto nickkilldone; } /* ** If acptr == sptr, then we have a client doing a nick ** change between *equivalent* nicknames as far as server ** is concerned (user is changing the case of his/her ** nickname or somesuch) */ if (acptr == sptr) { if (strcmp(acptr->name, nick) != 0) { /* Allows change of case in his/her nick */ removemoder = 0; /* don't set the user -r */ goto nickkilldone; /* -- go and process change */ } else /* ** This is just ':old NICK old' type thing. ** Just forget the whole thing here. There is ** no point forwarding it to anywhere, ** especially since servers prior to this ** version would treat it as nick collision. */ return 0; /* NICK Message ignored */ } /* ** Note: From this point forward it can be assumed that ** acptr != sptr (point to different client structures). */ /* ** Decide, we really have a nick collision and deal with it */ if (!IsServer(cptr)) { /* ** NICK is coming from local client connection. Just ** send error reply and ignore the command. */ #ifdef GUEST if (IsUnknown(sptr)) { RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv); return 0; } #endif sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), /* parv[0] is empty when connecting */ me.name, BadPtr(parv[0]) ? "*" : parv[0], nick); return 0; /* NICK message ignored */ } /* ** NICK was coming from a server connection. ** This means we have a race condition (two users signing on ** at the same time), or two net fragments reconnecting with ** the same nick. ** The latter can happen because two different users connected ** or because one and the same user switched server during a ** net break. ** If we have the old protocol (no TimeStamp and no user@host) ** or if the TimeStamps are equal, we kill both (or only 'new' ** if it was a "NICK new"). Otherwise we kill the youngest ** when user@host differ, or the oldest when they are the same. ** --Run ** */ if (IsServer(sptr)) { /* ** A new NICK being introduced by a neighbouring ** server (e.g. message type "NICK new" received) */ if (parc > 3) { lastnick = TS2ts(parv[3]); if (parc > 5) differ = (mycmp(acptr->user->username, parv[4]) || mycmp(acptr->user->realhost, parv[5])); } sendto_failops("Nick collision on %s (%s %ld <- %s %ld)", acptr->name, acptr->from->name, acptr->lastnick, cptr->name, lastnick); /* ** I'm putting the KILL handling here just to make it easier ** to read, it's hard to follow it the way it used to be. ** Basically, this is what it will do. It will kill both ** users if no timestamp is given, or they are equal. It will ** kill the user on our side if the other server is "correct" ** (user@host differ and their user is older, or user@host are ** the same and their user is younger), otherwise just kill the ** user an reintroduce our correct user. ** The old code just sat there and "hoped" the other server ** would kill their user. Not anymore. ** -- binary */ if (!(parc > 3) || (acptr->lastnick == lastnick)) { ircstp->is_kill++; sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; (void)exit_client(NULL, acptr, &me, "Nick collision with no timestamp/equal timestamps"); return 0; /* We killed both users, now stop the process. */ } if ((differ && (acptr->lastnick > lastnick)) || (!differ && (acptr->lastnick < lastnick)) || acptr->from == cptr) /* we missed a QUIT somewhere ? */ { ircstp->is_kill++; sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, acptr->name, me.name); acptr->flags |= FLAGS_KILLED; (void)exit_client(NULL, acptr, &me, "Nick collision"); goto nickkilldone; /* OK, we got rid of the "wrong" user, ** now we're going to add the user the ** other server introduced. */ } if ((differ && (acptr->lastnick < lastnick)) || (!differ && (acptr->lastnick > lastnick))) { /* * Introduce our "correct" user to the other server */ sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, parv[1], me.name); send_umode(NULL, acptr, 0, SEND_UMODES, buf); sendto_one_nickcmd(cptr, acptr, buf); if (acptr->user->away) sendto_one(cptr, ":%s AWAY :%s", acptr->name, acptr->user->away); send_user_joins(cptr, acptr); return 0; /* Ignore the NICK */ } return 0; } else { /* ** A NICK change has collided (e.g. message type ":old NICK new"). */ if (parc > 2) lastnick = TS2ts(parv[2]); differ = (mycmp(acptr->user->username, sptr->user->username) || mycmp(acptr->user->realhost, sptr->user->realhost)); sendto_failops ("Nick change collision from %s to %s (%s %ld <- %s %ld)", sptr->name, acptr->name, acptr->from->name, acptr->lastnick, sptr->from->name, lastnick); if (!(parc > 2) || lastnick == acptr->lastnick) { ircstp->is_kill += 2; sendto_serv_butone(NULL, /* First kill the new nick. */ ":%s KILL %s :%s (Self Collision)", me.name, acptr->name, me.name); sendto_serv_butone(cptr, /* Tell my servers to kill the old */ ":%s KILL %s :%s (Self Collision)", me.name, sptr->name, me.name); sptr->flags |= FLAGS_KILLED; acptr->flags |= FLAGS_KILLED; (void)exit_client(NULL, sptr, &me, "Self Collision"); (void)exit_client(NULL, acptr, &me, "Self Collision"); return 0; /* Now that I killed them both, ignore the NICK */ } if ((differ && (acptr->lastnick > lastnick)) || (!differ && (acptr->lastnick < lastnick))) { /* sptr (their user) won, let's kill acptr (our user) */ ircstp->is_kill++; sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick collision: %s <- %s)", me.name, acptr->name, me.name, acptr->from->name, sptr->from->name); acptr->flags |= FLAGS_KILLED; (void)exit_client(NULL, acptr, &me, "Nick collision"); goto nickkilldone; /* their user won, introduce new nick */ } if ((differ && (acptr->lastnick < lastnick)) || (!differ && (acptr->lastnick > lastnick))) { /* acptr (our user) won, let's kill sptr (their user), ** and reintroduce our "correct" user */ ircstp->is_kill++; /* Kill the user trying to change their nick. */ sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick collision: %s <- %s)", me.name, sptr->name, me.name, sptr->from->name, acptr->from->name); sptr->flags |= FLAGS_KILLED; (void)exit_client(NULL, sptr, &me, "Nick collision"); /* * Introduce our "correct" user to the other server */ /* Kill their user. */ sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, parv[1], me.name); send_umode(NULL, acptr, 0, SEND_UMODES, buf); sendto_one_nickcmd(cptr, acptr, buf); if (acptr->user->away) sendto_one(cptr, ":%s AWAY :%s", acptr->name, acptr->user->away); send_user_joins(cptr, acptr); return 0; /* their user lost, ignore the NICK */ } } return 0; /* just in case */ nickkilldone: if (IsServer(sptr)) { /* A server introducing a new client, change source */ sptr = make_client(cptr, serv); add_client_to_list(sptr); if (parc > 2) sptr->hopcount = TS2ts(parv[2]); if (parc > 3) sptr->lastnick = TS2ts(parv[3]); else /* Little bit better, as long as not all upgraded */ sptr->lastnick = TStime(); if (sptr->lastnick < 0) { sendto_realops ("Negative timestamp recieved from %s, resetting to TStime (%s)", cptr->name, backupbuf); sptr->lastnick = TStime(); } newusr = 1; } else if (sptr->name[0] && IsPerson(sptr)) { /* ** If the client belongs to me, then check to see ** if client is currently on any channels where it ** is currently banned. If so, do not allow the nick ** change to occur. ** Also set 'lastnick' to current time, if changed. */ if (MyClient(sptr)) { for (mp = sptr->user->channel; mp; mp = mp->next) { if (!is_skochanop(sptr, mp->chptr) && is_banned(sptr, mp->chptr, BANCHK_NICK)) { sendto_one(sptr, err_str(ERR_BANNICKCHANGE), me.name, parv[0], mp->chptr->chname); return 0; } if (CHECK_TARGET_NICK_BANS && !is_skochanop(sptr, mp->chptr) && is_banned_with_nick(sptr, mp->chptr, BANCHK_NICK, nick)) { sendto_one(sptr, ":%s 437 %s %s :Cannot change to a nickname banned on channel", me.name, parv[0], mp->chptr->chname); return 0; } if (!IsOper(sptr) && !IsULine(sptr) && mp->chptr->mode.mode & MODE_NONICKCHANGE && !is_chanownprotop(sptr, mp->chptr)) { sendto_one(sptr, err_str(ERR_NONICKCHANGE), me.name, parv[0], mp->chptr->chname); return 0; } } if (TStime() - sptr->user->flood.nick_t >= NICK_PERIOD) { sptr->user->flood.nick_t = TStime(); sptr->user->flood.nick_c = 1; } else sptr->user->flood.nick_c++; sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s", sptr->name, sptr->user->username, sptr->user->realhost, nick); RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, sptr, nick); } else { if (!IsULine(sptr)) sendto_snomask(SNO_FNICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s", sptr->name, sptr->user->username, sptr->user->realhost, nick); RunHook3(HOOKTYPE_REMOTE_NICKCHANGE, cptr, sptr, nick); } /* * Client just changing his/her nick. If he/she is * on a channel, send note of change to all clients * on that channel. Propagate notice to other servers. */ if (mycmp(parv[0], nick) || /* Next line can be removed when all upgraded --Run */ (!MyClient(sptr) && parc > 2 && TS2ts(parv[2]) < sptr->lastnick)) sptr->lastnick = (MyClient(sptr) || parc < 3) ? TStime() : TS2ts(parv[2]); if (sptr->lastnick < 0) { sendto_realops("Negative timestamp (%s)", backupbuf); sptr->lastnick = TStime(); } add_history(sptr, 1); sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); sendto_serv_butone_token(cptr, parv[0], MSG_NICK, TOK_NICK, "%s %ld", nick, sptr->lastnick); if (removemoder) sptr->umodes &= ~UMODE_REGNICK; } else if (!sptr->name[0]) { #ifdef NOSPOOF /* * Client setting NICK the first time. * * Generate a random string for them to pong with. */ sptr->nospoof = getrandom32(); if (PINGPONG_WARNING) sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems" " connecting due to ping timeouts, please" " type /quote pong %X or /raw pong %X now.", me.name, nick, sptr->nospoof, sptr->nospoof); sendto_one(sptr, "PING :%X", sptr->nospoof); #endif /* NOSPOOF */ #ifdef CONTACT_EMAIL sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with a" " connection problem, please email " CONTACT_EMAIL " with the name and version of the client you are" " using, and the server you tried to connect to: %s", me.name, nick, me.name); #endif /* CONTACT_EMAIL */ #ifdef CONTACT_URL sendto_one(sptr, ":%s NOTICE %s :*** If you need assistance with" " connecting to this server, %s, please refer to: " CONTACT_URL, me.name, nick, me.name); #endif /* CONTACT_URL */ /* Copy password to the passwd field if it's given after NICK * - originally by taz, modified by Wizzu */ if ((parc > 2) && (strlen(parv[2]) <= PASSWDLEN) && !(sptr->listener->umodes & LISTENER_JAVACLIENT)) { if (sptr->passwd) MyFree(sptr->passwd); sptr->passwd = MyMalloc(strlen(parv[2]) + 1); (void)strcpy(sptr->passwd, parv[2]); } /* This had to be copied here to avoid problems.. */ (void)strcpy(sptr->name, nick); if (sptr->user && IsNotSpoof(sptr)) { /* ** USER already received, now we have NICK. ** *NOTE* For servers "NICK" *must* precede the ** user message (giving USER before NICK is possible ** only for local client connection!). register_user ** may reject the client and call exit_client for it ** --must test this and exit m_nick too!!! */ #ifndef NOSPOOF if (USE_BAN_VERSION && MyConnect(sptr)) sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1", me.name, nick); #endif sptr->lastnick = TStime(); /* Always local client */ if (register_user(cptr, sptr, nick, sptr->user->username, NULL, NULL, NULL) == FLUSH_BUFFER) return FLUSH_BUFFER; strcpy(nick, sptr->name); /* don't ask, but I need this. do not remove! -- Syzop */ update_watch = 0; newusr = 1; } } /* * Finally set new nick name. */ if (update_watch && sptr->name[0]) { (void)del_from_client_hash_table(sptr->name, sptr); if (IsPerson(sptr)) hash_check_watch(sptr, RPL_LOGOFF); } (void)strcpy(sptr->name, nick); (void)add_to_client_hash_table(nick, sptr); if (IsServer(cptr) && parc > 7) { parv[3] = nick; do_cmd(cptr, sptr, "USER", parc - 3, &parv[3]); if (GotNetInfo(cptr) && !IsULine(sptr)) sendto_fconnectnotice(sptr->name, sptr->user, sptr, 0, NULL); } else if (IsPerson(sptr) && update_watch) hash_check_watch(sptr, RPL_LOGON); #ifdef NEWCHFLOODPROT if (sptr->user && !newusr && !IsULine(sptr)) { for (mp = sptr->user->channel; mp; mp = mp->next) { aChannel *chptr = mp->chptr; if (chptr && !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT)) && chptr->mode.floodprot && do_chanflood(chptr->mode.floodprot, FLD_NICK) && MyClient(sptr)) { do_chanflood_action(chptr, FLD_NICK, "nick"); } } } #endif if (newusr && !MyClient(sptr) && IsPerson(sptr)) { RunHook(HOOKTYPE_REMOTE_CONNECT, sptr); } return 0; }
/* Routine that actually makes a user join the channel * this does no actual checking (banned, etc.) it just adds the user */ DLLFUNC void _join_channel(aChannel *chptr, aClient *cptr, aClient *sptr, int flags) { char *parv[] = { 0, 0 }; /* ** Complete user entry to the new channel (if any) */ add_user_to_channel(chptr, sptr, flags); /* ** notify all other users on the new channel */ if (chptr->mode.mode & MODE_AUDITORIUM) { if (MyClient(sptr)) sendto_one(sptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); sendto_chanops_butone(NULL, chptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); } else sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", sptr->name, chptr->chname); sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, sptr->name, MSG_JOIN, TOK_JOIN, "%s", chptr->chname); #ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN if ((MyClient(sptr) && !(flags & CHFL_CHANOP)) || !MyClient(sptr)) sendto_serv_butone_token_opt(cptr, OPT_SJ3, sptr->name, MSG_JOIN, TOK_JOIN, "%s", chptr->chname); if (flags && !(flags & CHFL_DEOPPED)) { #endif /* I _know_ that the "@%s " look a bit wierd with the space and all .. but its to get around a SJOIN bug --stskeeps */ sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_SJB64, me.name, MSG_SJOIN, TOK_SJOIN, "%B %s :%s%s ", (long)chptr->creationtime, chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name); sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_NOT_SJB64, me.name, MSG_SJOIN, TOK_SJOIN, "%li %s :%s%s ", chptr->creationtime, chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name); #ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN } #endif if (MyClient(sptr)) { /* ** Make a (temporal) creationtime, if someone joins ** during a net.reconnect : between remote join and ** the mode with TS. --Run */ if (chptr->creationtime == 0) { chptr->creationtime = TStime(); sendto_serv_butone_token(cptr, me.name, MSG_MODE, TOK_MODE, "%s + %lu", chptr->chname, chptr->creationtime); } del_invite(sptr, chptr); if (flags && !(flags & CHFL_DEOPPED)) { #ifndef PREFIX_AQ if ((flags & CHFL_CHANOWNER) || (flags & CHFL_CHANPROT)) { /* +ao / +qo for when PREFIX_AQ is off */ sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, me.name, MSG_MODE, TOK_MODE, "%s +o%c %s %s %lu", chptr->chname, chfl_to_chanmode(flags), sptr->name, sptr->name, chptr->creationtime); } else { #endif /* +v/+h/+o (and +a/+q if PREFIX_AQ is on) */ sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, me.name, MSG_MODE, TOK_MODE, "%s +%c %s %lu", chptr->chname, chfl_to_chanmode(flags), sptr->name, chptr->creationtime); #ifndef PREFIX_AQ } #endif } if (chptr->topic) { sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, sptr->name, chptr->chname, chptr->topic); sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, sptr->name, chptr->chname, chptr->topic_nick, chptr->topic_time); } if (chptr->users == 1 && (MODES_ON_JOIN #ifdef EXTCMODE || iConf.modes_on_join.extmodes) #endif ) { #ifdef EXTCMODE int i; chptr->mode.extmode = iConf.modes_on_join.extmodes; /* Param fun */ for (i = 0; i <= Channelmode_highest; i++) { if (!Channelmode_Table[i].flag || !Channelmode_Table[i].paracount) continue; if (chptr->mode.extmode & Channelmode_Table[i].mode) { CmodeParam *p; p = Channelmode_Table[i].put_param(NULL, iConf.modes_on_join.extparams[i]); AddListItem(p, chptr->mode.extmodeparam); } } #endif chptr->mode.mode = MODES_ON_JOIN; #ifdef NEWCHFLOODPROT if (iConf.modes_on_join.floodprot.per) { chptr->mode.floodprot = MyMalloc(sizeof(ChanFloodProt)); memcpy(chptr->mode.floodprot, &iConf.modes_on_join.floodprot, sizeof(ChanFloodProt)); } #else chptr->mode.kmode = iConf.modes_on_join.kmode; chptr->mode.per = iConf.modes_on_join.per; chptr->mode.msgs = iConf.modes_on_join.msgs; #endif *modebuf = *parabuf = 0; channel_modes(sptr, modebuf, parabuf, chptr); /* This should probably be in the SJOIN stuff */ sendto_serv_butone_token(&me, me.name, MSG_MODE, TOK_MODE, "%s %s %s %lu", chptr->chname, modebuf, parabuf, chptr->creationtime); sendto_one(sptr, ":%s MODE %s %s %s", me.name, chptr->chname, modebuf, parabuf); } parv[0] = sptr->name; parv[1] = chptr->chname; do_cmd(cptr, sptr, "NAMES", 2, parv); RunHook4(HOOKTYPE_LOCAL_JOIN, cptr, sptr,chptr,parv); } else { RunHook4(HOOKTYPE_REMOTE_JOIN, cptr, sptr, chptr, parv); /* (rarely used) */ } #ifdef NEWCHFLOODPROT /* I'll explain this only once: * 1. if channel is +f * 2. local client OR synced server * 3. then, increase floodcounter * 4. if we reached the limit AND only if source was a local client.. do the action (+i). * Nr 4 is done because otherwise you would have a noticeflood with 'joinflood detected' * from all servers. */ if (chptr->mode.floodprot && (MyClient(sptr) || sptr->srvptr->serv->flags.synced) && !IsULine(sptr) && do_chanflood(chptr->mode.floodprot, FLD_JOIN) && MyClient(sptr)) { do_chanflood_action(chptr, FLD_JOIN, "join"); } #endif }
DLLFUNC int m_rmtkl(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aTKline *tk, *next = NULL; TKLType *tkltype; char *types, *uhmask, *cmask, *p; char gmt[256], flag; int tklindex; if (!IsULine(sptr) && !(IsPerson(sptr) && IsAnOper(sptr))) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return -1; } if (IsNotParam(1)) return dumpit(sptr, rmtkl_help); if (IsNotParam(2)) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RMTKL"); sendnotice(sptr, "Type '/RMTKL' for help"); return 0; } types = parv[1]; uhmask = parv[2]; cmask = IsParam(3) ? parv[3] : NULL; /* I don't add 'q' and 'Q' here. They are different. */ if (strchr(types, '*')) types = "KzGZs"; /* check access */ if (!IsULine(sptr)) for (p = types; *p; p++) { tkltype = find_TKLType_by_flag(*p); if (!tkltype->type) continue; if (((tkltype->type & TKL_GLOBAL) && !IsOper(sptr)) || !(sptr->oflag & tkltype->oflag)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return -1; } } for (tkltype = tkl_types; tkltype->type; tkltype++) { flag = tkltype->flag; tklindex = tkl_hash(flag); if (!strchr(types, flag)) continue; for (tk = tklines[tklindex]; tk; tk = next) { next = tk->next; if (tk->type != tkltype->type) continue; if (tk->type & TKL_NICK) { /* * If it's a services hold (ie. NickServ is holding * a nick), it's better not to touch it */ if (*tk->usermask == 'H') continue; if (match(uhmask, tk->hostmask)) continue; } else if (match(uhmask, make_user_host(tk->usermask, tk->hostmask))) continue; if (cmask && _match(cmask, tk->reason)) continue; strncpyzt(gmt, asctime(gmtime((TS *)&tk->set_at)), sizeof gmt); iCstrip(gmt); if (tk->type & TKL_NICK) { sendto_snomask(SNO_TKL, "%s removed %s %s (set at %s " "- reason: %s)", sptr->name, tkltype->txt, tk->hostmask, gmt, tk->reason); ircd_log(LOG_TKL, "%s removed %s %s (set at %s " "- reason: %s)", sptr->name, tkltype->txt, tk->hostmask, gmt, tk->reason); } else { sendto_snomask(SNO_TKL, "%s removed %s %s@%s (set at " "%s - reason: %s)", sptr->name, tkltype->txt, tk->usermask, tk->hostmask, gmt, tk->reason); ircd_log(LOG_TKL, "%s removed %s %s@%s (set at " "%s - reason: %s)", sptr->name, tkltype->txt, tk->usermask, tk->hostmask, gmt, tk->reason); } if ((tk->type & TKL_GLOBAL) && flag) sendto_serv_butone_token(&me, me.name, MSG_TKL, TOK_TKL, "- %c %s %s %s", flag, tk->usermask, tk->hostmask, parv[0]); if (tk->type & TKL_SHUN) tkl_check_local_remove_shun(tk); my_tkl_del_line(tk, tklindex); } } return 0; }