int is_services_root(User * u) { if ((NSStrictPrivileges && !is_oper(u)) || (!skeleton && !nick_identified(u))) return 0; if (skeleton || (u->na->nc->flags & NI_SERVICES_ROOT)) return 1; return 0; }
/** * The suspend command. * @param u The user who issued the command * @param ci The channel we will be suspending. * @param reason The reason given for suspending the channel. * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ int do_suspend(User * u, ChannelInfo *ci, char *reason) { Channel *c; if (!ci) { moduleNoticeLang(ci->bi->nick, u, LANG_SUSPEND_SYNTAX); return MOD_CONT; } if (ForceForbidReason && !reason) { moduleNoticeLang(ci->bi->nick, u, LANG_SUSPEND_NO_REASON); return MOD_CONT; } if (readonly) { notice_lang(ci->bi->nick, u, READ_ONLY_MODE); return MOD_CONT; } ci->flags |= CI_SUSPENDED; ci->forbidby = sstrdup(u->nick); if (reason) ci->forbidreason = sstrdup(reason); if ((c = findchan(ci->name))) { struct c_userlist *cu, *next; char *av[3]; for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) continue; av[0] = c->name; av[1] = cu->user->nick; av[2] = reason ? reason : "CHAN_SUSPEND_REASON"; xanadu_cmd_kick(ci->bi->nick, av[0], av[1], av[2]); do_kick(ci->bi->nick, 3, av); } } if (WallForbid) xanadu_cmd_global(ci->bi->nick, "\2%s\2 used SUSPEND on channel \2%s\2", u->nick, ci->name); alog("%s: %s set SUSPEND for channel %s", ci->bi->nick, u->nick, ci->name); notice_lang(ci->bi->nick, u, CHAN_SUSPEND_SUCCEEDED, ci->name); send_event(EVENT_CHAN_SUSPENDED, 1, ci->name); return MOD_CONT; }
int list_global_opers(Channel *c, User *u) { int j, i , carryon, count = 0; User *u2; char *access; noticeLang(c->ci->bi->nick, u, LANG_GOLIST_HEADER); for (j = 0; j < 1024; j++) { for (u2 = userlist[j]; u2; u2 = u2->next) { carryon = 0; /* Prevent listing of users with +H */ if (finduser((u2->nick)) && !has_umode_H(u2) && !has_umode_B(u2) && !is_ulined(u2->server->name)) { i = 0; while (i < excempt_nr) { if (!ListExempts[i] || !u2->nick) break; if (my_match_wild_nocase(ListExempts[i], u2->nick)) { carryon = 1; break; } i++; } if (carryon) continue; if (is_oper(u2)) { count++; access = getLangString(u->na, LANG_GOLIST_OPER_ONLY); if (is_services_oper(u2)) access = getLangString(u->na, LANG_GOLIST_OPER_AND_SO); if (is_services_admin(u2)) access = getLangString(u->na, LANG_GOLIST_OPER_AND_SA); if (is_services_root(u2)) access = getLangString(u->na, LANG_GOLIST_OPER_AND_SRA); notice(c->ci->bi->nick, u->nick, "%-15s - %s", u2->nick, access); } } } } if (count == 0) noticeLang(c->ci->bi->nick, u, LANG_GOLIST_NONE); noticeLang(c->ci->bi->nick, u, LANG_GOLIST_FOOTER, count); return MOD_CONT; }
int list_admins(Channel *c, User *u) { int j, i , carryon, count = 0; User *u2; noticeLang(c->ci->bi->nick, u, LANG_ADLIST_HEADER); for (j = 0; j < 1024; j++) { for (u2 = userlist[j]; u2; u2 = u2->next) { carryon = 0; /* Prevent listing of users with +H */ if (finduser((u2->nick)) && !has_umode_H(u2) && !has_umode_B(u2) && !is_ulined(u2->server->name)) { i = 0; while (i < excempt_nr) { if (!ListExempts[i] || !u2->nick) break; if (!stricmp(u2->nick, ListExempts[i])) carryon = 1; i++; } if (carryon) continue; if (is_oper(u2)) { if (is_services_root(u2)) { count++; notice(c->ci->bi->nick, u->nick, "%-15s - %s", u2->nick, getLangString(u->na, LANG_ADLIST_SRA)); continue; } if (is_services_admin(u2)) { count++; notice(c->ci->bi->nick, u->nick, "%-15s - %s", u2->nick, getLangString(u->na, LANG_ADLIST_SA)); } } } } } if (count == 0) noticeLang(c->ci->bi->nick, u, LANG_ADLIST_NONE); noticeLang(c->ci->bi->nick, u, LANG_ADLIST_FOOTER, count); return MOD_CONT; }
/** * The /bs botlist command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ int do_botlist(User * u) { int i, count = 0; BotInfo *bi; if (!nbots) { notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); return MOD_CONT; } for (i = 0; i < 256; i++) { for (bi = botlists[i]; bi; bi = bi->next) { if (!(bi->flags & BI_PRIVATE)) { if (!count) notice_lang(s_BotServ, u, BOT_BOTLIST_HEADER); count++; notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, bi->user, bi->host); } } } if (is_oper(u) && count < nbots) { notice_lang(s_BotServ, u, BOT_BOTLIST_PRIVATE_HEADER); for (i = 0; i < 256; i++) { for (bi = botlists[i]; bi; bi = bi->next) { if (bi->flags & BI_PRIVATE) { notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, bi->user, bi->host); count++; } } } } if (!count) notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); else notice_lang(s_BotServ, u, BOT_BOTLIST_FOOTER, count); return MOD_CONT; }
/** * Check and enforce SQlines * @param mask of the sqline * @param reason for the sqline * @return void */ void sqline(char *mask, char *reason) { int i; Channel *c, *next; char *av[3]; struct c_userlist *cu, *cunext; if (ircd->chansqline) { if (*mask == '#') { xanadu_cmd_sqline(mask, reason); for (i = 0; i < 1024; i++) { for (c = chanlist[i]; c; c = next) { next = c->next; if (!match_wild_nocase(mask, c->name)) { continue; } for (cu = c->users; cu; cu = cunext) { cunext = cu->next; if (is_oper(cu->user)) { continue; } av[0] = c->name; av[1] = cu->user->nick; av[2] = reason; xanadu_cmd_kick(s_OperServ, av[0], av[1], "Q-Lined: %s", av[2]); do_kick(s_ChanServ, 3, av); } } } } else { xanadu_cmd_sqline(mask, reason); } } else { xanadu_cmd_sqline(mask, reason); } }
/** * The /bs assign command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ int do_assign(User * u) { char *chan = strtok(NULL, " "); char *nick = strtok(NULL, " "); BotInfo *bi; ChannelInfo *ci; if (readonly) notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); else if (!chan || !nick) syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); else if (!(bi = findbot(nick))) notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); else if (bi->flags & BI_PRIVATE && !is_oper(u)) notice_lang(s_BotServ, u, PERMISSION_DENIED); else if (!(ci = cs_findchan(chan))) notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); else if (ci->flags & CI_VERBOTEN) notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); else if ((ci->botflags & BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) notice_lang(s_BotServ, u, PERMISSION_DENIED); else { if (ci->bi) unassign(u, ci); ci->bi = bi; bi->chancount++; if (ci->c && ci->c->usercount >= BSMinUsers) { bot_join(ci); } notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); send_event(EVENT_BOT_ASSIGN, 2, ci->name, bi->nick); } return MOD_CONT; }
/** * ChanKill - Akill an entire channel (got botnet?) * * /msg OperServ ChanKill +expire #channel reason * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. * **/ int do_chankill(User * u) { char *expiry, *channel, *reason; time_t expires; char breason[BUFSIZE]; char mask[USERMAX + HOSTMAX + 2]; struct c_userlist *cu, *next; Channel *c; channel = strtok(NULL, " "); if (channel && *channel == '+') { expiry = channel; channel = strtok(NULL, " "); } else { expiry = NULL; } expires = expiry ? dotime(expiry) : ChankillExpiry; if (expiry && isdigit(expiry[strlen(expiry) - 1])) expires *= 86400; if (expires != 0 && expires < 60) { notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); return MOD_CONT; } else if (expires > 0) { expires += time(NULL); } if (channel && (reason = strtok(NULL, ""))) { if (AddAkiller) { snprintf(breason, sizeof(breason), "[%s] %s", u->nick, reason); reason = sstrdup(breason); } if ((c = findchan(channel))) { for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) { continue; } (void) strncpy(mask, "*@", 3); /* Use *@" for the akill's, */ strncat(mask, cu->user->host, HOSTMAX); add_akill(NULL, mask, s_OperServ, expires, reason); check_akill(cu->user->nick, cu->user->username, cu->user->host, NULL, NULL); } if (WallOSAkill) { xanadu_cmd_global(s_OperServ, "%s used CHANKILL on %s (%s)", u->nick, channel, reason); } } else { notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, channel); } if (AddAkiller) { free(reason); } } else { syntax_error(s_OperServ, u, "CHANKILL", OPER_CHANKILL_SYNTAX); } return MOD_CONT; }
int add_sgline(User * u, char *mask, const char *by, const time_t expires, const char *reason) { int deleted = 0, i; SXLine *entry; User *u2, *next; char buf[BUFSIZE]; *buf = '\0'; /* Checks whether there is an SGLINE that already covers * the one we want to add, and whether there are SGLINEs * that would be covered by this one. * If so, warn the user in the first case and cleanup * the useless SGLINEs in the second. */ if (!mask) { return -1; } if (sglines.count > 0) { for (i = sglines.count - 1; i >= 0; i--) { entry = sglines.list[i]; if (!entry) continue; if (!stricmp(entry->mask, mask)) { if (entry->expires >= expires || entry->expires == 0) { if (u) notice_lang(s_OperServ, u, OPER_SGLINE_EXISTS, mask); return -1; } else { entry->expires = expires; if (u) notice_lang(s_OperServ, u, OPER_SGLINE_CHANGED, entry->mask); return -2; } } if (match_wild_nocase(entry->mask, mask) && (entry->expires >= expires || entry->expires == 0)) { if (u) notice_lang(s_OperServ, u, OPER_SGLINE_ALREADY_COVERED, mask, entry->mask); return -1; } if (match_wild_nocase(mask, entry->mask) && (entry->expires <= expires || expires == 0)) { slist_delete(&sglines, i); deleted++; } } } /* We can now check whether the list is full or not. */ if (slist_full(&sglines)) { if (u) notice_lang(s_OperServ, u, OPER_SGLINE_REACHED_LIMIT, sglines.limit); return -1; } /* We can now (really) add the SGLINE. */ entry = scalloc(sizeof(SXLine), 1); if (!entry) return -1; entry->mask = sstrdup(mask); entry->by = sstrdup(by); entry->reason = sstrdup(reason); entry->seton = time(NULL); entry->expires = expires; slist_add(&sglines, entry); xanadu_cmd_sgline(entry->mask, entry->reason); if (KillonSGline && !ircd->sglineenforce) { snprintf(buf, (BUFSIZE - 1), "G-Lined: %s", entry->reason); u2 = firstuser(); while (u2) { next = nextuser(); if (!is_oper(u2)) { if (match_wild_nocase(entry->mask, u2->realname)) { kill_user(ServerName, u2->nick, buf); } } u2 = next; } } return deleted; }
int do_core_kickban(User * u, Channel *c, char *target, char *reason) { ChannelInfo *ci = c->ci; User *u2; int is_same, exists; char *av[2]; if (!target) target = u->nick; is_same = (target == u->nick) ? 1 : (stricmp(target, u->nick) == 0); if (is_same) { u2 = u; exists = 1; } else exists = ((u2 = finduser(target)) ? 1 : 0); if (!is_same ? !check_access(u, ci, CA_BAN) : !check_access(u, ci, CA_BANME)) { notice_lang(ci->bi->nick, u, ACCESS_DENIED); } else if (!is_same && exists && (ci->flags & CI_PEACE) && (get_access(u2, ci) >= get_access(u, ci))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); } else if (exists && ((ircd->protectedumode && is_protected(u2)) && !is_founder(u, ci))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); /** * Dont ban the user on channels where he is excepted * to prevent services <-> server wars. **/ } else if (exists && (ircd->except && is_excepted(ci, u2))) { notice_lang(ci->bi->nick, u, CHAN_EXCEPTED, u2->nick, ci->name); } else if (!exists && (ircd->except && is_excepted_mask(ci, target))) { notice_lang(ci->bi->nick, u, CHAN_EXCEPTED, target, ci->name); } else if (exists && RestrictKB && ((!is_founder(u, ci) && is_services_oper(u2)) || (is_founder(u, ci) && is_services_admin(u2)))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); } else if (stricmp(target, ci->bi->nick) == 0) { bot_raw_ban(u, ci, u->nick, "Oops!"); } else { if (exists) { if (is_on_chan(ci->c, u2)) { if (!reason) bot_raw_ban(u, ci, target, "Requested"); else bot_raw_ban(u, ci, target, reason); } } else if (my_match_wild_nocase("*@*", target)) { char mask[BUFSIZE]; /* If we get a *@* target we need to add the *!... */ if (!my_match_wild_nocase("*!*@*", target)) snprintf(mask, BUFSIZE, "*!%s", target); else snprintf(mask, BUFSIZE, "%s", target); /* Only continue if the mask doesn't match an exception or is otherwise prohibited.. */ if (check_banmask(u, c, mask)) { struct c_userlist *cu = NULL, *next = NULL; av[0] = "+b"; av[1] = mask; anope_cmd_mode(ci->bi->nick, c->name, "+b %s", av[1]); chan_set_modes(ci->bi->nick, c, 2, av, 1); cu = c->users; while (cu) { next = cu->next; /* This only checks against the cloacked host & vhost for normal users. * IPs are only checked when triggered by an oper.. */ if (is_oper(u) ? match_usermask_full(mask, cu->user, true) : match_usermask(mask, cu->user)) { if (!reason) bot_raw_kick(u, ci, cu->user->nick, "Requested"); else bot_raw_kick(u, ci, cu->user->nick, reason); } cu = next; } } } else noticeLang(ci->bi->nick, u, LANG_REQ_NICK_OR_MASK); } return MOD_CONT; }
int do_core_kick(User * u, Channel *c, char *target, char *reason) { ChannelInfo *ci = c->ci; User *u2; int is_same, exists; if (!target) target = u->nick; is_same = (target == u->nick) ? 1 : (stricmp(target, u->nick) == 0); if (is_same) { u2 = u; exists = 1; } else exists = ((u2 = finduser(target)) ? 1 : 0); if (!is_same ? !check_access(u, ci, CA_KICK) : !check_access(u, ci, CA_KICKME)) { notice_lang(ci->bi->nick, u, ACCESS_DENIED); } else if (!is_same && exists && (ci->flags & CI_PEACE) && (get_access(u2, ci) >= get_access(u, ci))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); } else if (exists && ((ircd->protectedumode && is_protected(u2)) && !is_founder(u, ci))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); } else if (exists && RestrictKB && ((!is_founder(u, ci) && is_services_oper(u2)) || (is_founder(u, ci) && is_services_admin(u2)))) { notice_lang(ci->bi->nick, u, PERMISSION_DENIED); } else if (stricmp(target, ci->bi->nick) == 0) { bot_raw_kick(u, ci, u->nick, "Oops!"); } else { if (exists) { if (is_on_chan(ci->c, u2)) { if (!reason) bot_raw_kick(u, ci, target, "Requested"); else bot_raw_kick(u, ci, target, reason); } } else { char mask[BUFSIZE]; struct c_userlist *cu = NULL, *next = NULL; if (my_match_wild_nocase("*!*@*", target)) snprintf(mask, BUFSIZE, "%s", target); /* If we get a *@* target we need to add the *!... */ else if (my_match_wild_nocase("*@*", target)) snprintf(mask, BUFSIZE, "*!%s", target); else if (my_match_wild_nocase("*!*", target)) snprintf(mask, BUFSIZE, "%s@*", target); /* If we get a * target we need to add the !*@* (assume nick)... */ else snprintf(mask, BUFSIZE, "%s!*@*", target); cu = c->users; while (cu) { next = cu->next; /* This only checks against the cloacked host & vhost for normal users. * IPs are only checked when triggered by an oper.. */ if (is_oper(u) ? match_usermask_full(mask, cu->user, true) : match_usermask(mask, cu->user)) { /* Check whether we are allowed to kick this matching user.. */ if (!((ircd->protectedumode && is_protected(cu->user) && !is_founder(u, ci)) || ((ci->flags & CI_PEACE) && (get_access(cu->user, ci) >= get_access(u, ci))) || (RestrictKB && ((!is_founder(u, ci) && is_services_oper(cu->user)) || (is_founder(u, ci) && is_services_admin(cu->user)))))) { if (!reason) bot_raw_kick(u, ci, cu->user->nick, "Requested"); else bot_raw_kick(u, ci, cu->user->nick, reason); } } cu = next; } } } return MOD_CONT; }
IgnoreData *get_ignore(const char *nick) { IgnoreData *ign, *prev; time_t now = time(NULL); IgnoreData **whichlist = &ignore[tolower(nick[0])]; User *u = finduser(nick); IgnoreData **whichlist2 = NULL; /* Bleah, this doesn't work. I need a way to get the first char of u->username. /if (u) whichlist2 = &ignore[tolower(u->username[0])]; */ IgnoreData **whichlistast = &ignore[42]; /* * */ IgnoreData **whichlistqst = &ignore[63]; /* ? */ int finished = 0; /* User has disabled the IGNORE system */ if (!allow_ignore) { return NULL; } /* if an oper gets on the ignore list we let them privmsg, this will allow them in places we call get_ignore to get by */ if (u && is_oper(u)) { return NULL; } for (ign = *whichlist, prev = NULL; ign; prev = ign, ign = ign->next) { if (stricmp(ign->who, nick) == 0) { finished = 1; break; } } /* We can only do the next checks if we have an actual user -GD */ if (u) { if (!finished && whichlist2) { for (ign = *whichlist2, prev = NULL; ign; prev = ign, ign = ign->next) { if (match_usermask(ign->who, u)) { finished = 1; break; } } } if (!finished) { for (ign = *whichlistast, prev = NULL; ign; prev = ign, ign = ign->next) { if (match_usermask(ign->who, u)) { finished = 1; break; } } } if (!finished) { for (ign = *whichlistqst, prev = NULL; ign; prev = ign, ign = ign->next) { if (match_usermask(ign->who, u)) { finished = 1; break; } } } } if (ign && ign->time <= now) { if (prev) prev->next = ign->next; else *whichlist = ign->next; free(ign); ign = NULL; } return ign; }
void delete_user(User * user) { struct u_chanlist *c, *c2; struct u_chaninfolist *ci, *ci2; char *realname; if (LogUsers) { realname = normalizeBuffer(user->realname); if (ircd->vhost) { alog("LOGUSERS: %s (%s@%s => %s) (%s) left the network (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), realname, user->server->name); } else { alog("LOGUSERS: %s (%s@%s) (%s) left the network (%s).", user->nick, user->username, user->host, realname, user->server->name); } free(realname); } send_event(EVENT_USER_LOGOFF, 1, user->nick); if (debug >= 2) alog("debug: delete_user() called"); usercnt--; if (is_oper(user)) opcnt--; if (debug >= 2) alog("debug: delete_user(): free user data"); free(user->username); free(user->host); if (user->chost) free(user->chost); if (user->vhost) free(user->vhost); if (user->vident) free(user->vident); if (user->uid) { free(user->uid); } Anope_Free(user->realname); Anope_Free(user->hostip); if (debug >= 2) { alog("debug: delete_user(): remove from channels"); } c = user->chans; while (c) { c2 = c->next; chan_deluser(user, c->chan); free(c); c = c2; } /* This called only here now */ cancel_user(user); if (user->na) user->na->u = NULL; if (debug >= 2) alog("debug: delete_user(): free founder data"); ci = user->founder_chans; while (ci) { ci2 = ci->next; free(ci); ci = ci2; } if (user->nickTrack) free(user->nickTrack); moduleCleanStruct(&user->moduleData); if (debug >= 2) alog("debug: delete_user(): delete from list"); if (user->prev) user->prev->next = user->next; else userlist[HASH(user->nick)] = user->next; if (user->next) user->next->prev = user->prev; if (debug >= 2) alog("debug: delete_user(): free user structure"); free(user); if (debug >= 2) alog("debug: delete_user() done"); }
int do_resetpass(User * u) { char *buffer = NULL; char *nick = NULL; char *email = NULL; char passcode[PASSCODELEN]; char *callBackinfo[1]; NickAlias *na = NULL; if ((RestrictReset == 1) && !(is_oper(u))) { notice_lang(s_NickServ, u, ACCESS_DENIED); return MOD_CONT; } buffer = moduleGetLastBuffer(); nick = myStrGetToken(buffer, ' ', 0); email = myStrGetToken(buffer, ' ', 1); if (!nick) { moduleNoticeLang(s_NickServ, u, RESETPASS_SYNTAX); } else if (!anope_valid_nick(nick)) { notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick); } else if (!(na = findnick(nick))) { notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); } else if (na->status & NS_VERBOTEN) { notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); } else if (na->nc->flags & NI_SUSPENDED) { notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); } else if (!na->nc->email) { notice_user(s_NickServ, u, "%s has no email associated with their account.", na->nick); } else if (moduleGetData(&na->nc->moduleData, MODULEDATAKEY)) { moduleNoticeLang(s_NickServ, u, RESETPASS_ALREADY_REQUESTED1, na->nick); moduleNoticeLang(s_NickServ, u, RESETPASS_ALREADY_REQUESTED2); } else if (!email && !is_oper(u) && !is_helpop(u)) { notice(s_NickServ, u->nick, "You need to provide the e-mail address associated with the account you are trying to reset the password on."); notice(s_NickServ, u->nick, "Syntax: /ns resetpass <nickname> <e-mail>"); } else if (!is_oper(u) && !is_helpop(u) && strcasecmp(email, na->nc->email)) { notice(s_NickServ, u->nick, "The e-mail address %s does not match the one associated with account %s.", email, na->nc->display); } else { generatePassCode(passcode); moduleAddData(&na->nc->moduleData, MODULEDATAKEY, passcode); if (do_sendmail(u, na) != 0) { alog(LOG_COULDNT_SENDMAIL, MYNAME, na->nick); moduleDelData(&na->nc->moduleData, MODULEDATAKEY); } else { callBackinfo[0] = na->nick; moduleAddCallback(MYNAME, time(NULL) + ExpirePassCode, expirePassCode, 1, callBackinfo); alog(LOG_RESETPASS_REQUESTED, MYNAME, u->nick, na->nick); moduleNoticeLang(s_NickServ, u, RESETPASS_SUCCESS, na->nick); moduleNoticeLang(s_NickServ, u, RESETPASS_INSTRUC); } } if (nick) free(nick); if (email) free(email); return MOD_CONT; }
/** * The /ns list command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ static int do_list(User * u) { /* SADMINS can search for nicks based on their NS_VERBOTEN and NS_NO_EXPIRE * status. The keywords FORBIDDEN and NOEXPIRE represent these two states * respectively. These keywords should be included after the search pattern. * Multiple keywords are accepted and should be separated by spaces. Only one * of the keywords needs to match a nick's state for the nick to be displayed. * Forbidden nicks can be identified by "[Forbidden]" appearing in the last * seen address field. Nicks with NOEXPIRE set are preceeded by a "!". Only * SADMINS will be shown forbidden nicks and the "!" indicator. * Syntax for sadmins: LIST pattern [FORBIDDEN] [NOEXPIRE] * -TheShadow * * UPDATE: SUSPENDED keyword is now accepted as well. */ char *pattern = strtok(NULL, " "); char *keyword; NickAlias *na; NickCore *mync; int nnicks, i; char buf[BUFSIZE]; int is_servadmin = is_services_admin(u); int16 matchflags = 0; NickRequest *nr = NULL; int nronly = 0; int susp_keyword = 0; char noexpire_char = ' '; int count = 0, from = 0, to = 0, tofree = 0; char *tmp = NULL; char *s = NULL; if (!(!NSListOpersOnly || (is_oper(u)))) { /* reverse the help logic */ notice_lang(s_NickServ, u, ACCESS_DENIED); return MOD_STOP; } if (!pattern) { syntax_error(s_NickServ, u, "LIST", is_servadmin ? NICK_LIST_SERVADMIN_SYNTAX : NICK_LIST_SYNTAX); } else { if (pattern) { if (pattern[0] == '#') { tmp = myStrGetOnlyToken((pattern + 1), '-', 0); /* Read FROM out */ if (!tmp) { notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE); return MOD_CONT; } for (s = tmp; *s; s++) { if (!isdigit(*s)) { free(tmp); notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE); return MOD_CONT; } } from = atoi(tmp); free(tmp); tmp = myStrGetTokenRemainder(pattern, '-', 1); /* Read TO out */ if (!tmp) { notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE); return MOD_CONT; } for (s = tmp; *s; s++) { if (!isdigit(*s)) { free(tmp); notice_lang(s_ChanServ, u, LIST_INCORRECT_RANGE); return MOD_CONT; } } to = atoi(tmp); free(tmp); pattern = sstrdup("*"); tofree = 1; } } nnicks = 0; while (is_servadmin && (keyword = strtok(NULL, " "))) { if (stricmp(keyword, "FORBIDDEN") == 0) matchflags |= NS_VERBOTEN; if (stricmp(keyword, "NOEXPIRE") == 0) matchflags |= NS_NO_EXPIRE; if (stricmp(keyword, "SUSPENDED") == 0) susp_keyword = 1; if (stricmp(keyword, "UNCONFIRMED") == 0) nronly = 1; } mync = (nick_identified(u) ? u->na->nc : NULL); notice_lang(s_NickServ, u, NICK_LIST_HEADER, pattern); if (nronly != 1) { for (i = 0; i < 1024; i++) { for (na = nalists[i]; na; na = na->next) { /* Don't show private and forbidden nicks to non-services admins. */ if ((na->status & NS_VERBOTEN) && !is_servadmin) continue; if ((na->nc->flags & NI_PRIVATE) && !is_servadmin && na->nc != mync) continue; if ((matchflags != 0) && !(na->status & matchflags) && (susp_keyword == 0)) continue; else if ((susp_keyword == 1) && !(na->nc->flags & NI_SUSPENDED)) continue; /* We no longer compare the pattern against the output buffer. * Instead we build a nice nick!user@host buffer to compare. * The output is then generated separately. -TheShadow */ snprintf(buf, sizeof(buf), "%s!%s", na->nick, (na->last_usermask && !(na->status & NS_VERBOTEN)) ? na-> last_usermask : "*@*"); if (stricmp(pattern, na->nick) == 0 || match_wild_nocase(pattern, buf)) { if ((((count + 1 >= from) && (count + 1 <= to)) || ((from == 0) && (to == 0))) && (++nnicks <= NSListMax)) { if (is_servadmin && (na->status & NS_NO_EXPIRE)) noexpire_char = '!'; else { noexpire_char = ' '; } if ((na->nc->flags & NI_HIDE_MASK) && !is_servadmin && na->nc != mync) { snprintf(buf, sizeof(buf), "%-20s [Hostname Hidden]", na->nick); } else if (na->status & NS_VERBOTEN) { snprintf(buf, sizeof(buf), "%-20s [Forbidden]", na->nick); } else if (na->nc->flags & NI_SUSPENDED) { snprintf(buf, sizeof(buf), "%-20s [Suspended]", na->nick); } else { snprintf(buf, sizeof(buf), "%-20s %s", na->nick, na->last_usermask); } notice_user(s_NickServ, u, " %c%s", noexpire_char, buf); } count++; } } } } if (nronly == 1 || (is_servadmin && matchflags == 0 && susp_keyword == 0)) { noexpire_char = ' '; for (i = 0; i < 1024; i++) { for (nr = nrlists[i]; nr; nr = nr->next) { snprintf(buf, sizeof(buf), "%s!*@*", nr->nick); if (stricmp(pattern, nr->nick) == 0 || match_wild_nocase(pattern, buf)) { if (++nnicks <= NSListMax) { snprintf(buf, sizeof(buf), "%-20s [UNCONFIRMED]", nr->nick); notice_user(s_NickServ, u, " %c%s", noexpire_char, buf); } } } } } notice_lang(s_NickServ, u, NICK_LIST_RESULTS, nnicks > NSListMax ? NSListMax : nnicks, nnicks); } if (tofree) free(pattern); return MOD_CONT; }
/** * Add the help response to anopes /ns help output. * @param u The user who is requesting help **/ static void myNickServHelp(User * u) { if (!NSListOpersOnly || (is_oper(u))) { notice_lang(s_NickServ, u, NICK_HELP_CMD_LIST); } }
/** * Add the help response to anopes /os help output. * @param u The user who is requesting help **/ void myOperServHelp(User * u) { if (is_oper(u)) { notice_lang(s_OperServ, u, OPER_HELP_CMD_ADMIN); } }
/** * The /cs forbid command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ static int do_forbid(User * u) { Channel *c; ChannelInfo *ci; char *chan = strtok(NULL, " "); char *reason = strtok(NULL, ""); Entry *cur, *enext; /* Assumes that permission checking has already been done. */ if (!chan || (ForceForbidReason && !reason)) { syntax_error(s_ChanServ, u, "FORBID", (ForceForbidReason ? CHAN_FORBID_SYNTAX_REASON : CHAN_FORBID_SYNTAX)); return MOD_CONT; } if (*chan != '#') { notice_lang(s_ChanServ, u, CHAN_SYMBOL_REQUIRED); return MOD_CONT; } else if (!anope_valid_chan(chan)) { notice_lang(s_ChanServ, u, CHAN_X_INVALID, chan); return MOD_CONT; } if (readonly) notice_lang(s_ChanServ, u, READ_ONLY_MODE); if ((ci = cs_findchan(chan)) != NULL) { delchan(ci); send_event(EVENT_CHAN_DROP, 1, chan); } ci = makechan(chan); if (ci) { ci->flags |= CI_VERBOTEN; ci->forbidby = sstrdup(u->nick); if (reason) ci->forbidreason = sstrdup(reason); if ((c = findchan(ci->name))) { struct c_userlist *cu, *next; char *av[3]; /* Before banning everyone, it might be prudent to clear +e and +I lists.. * to prevent ppl from rejoining.. ~ Viper */ if (ircd->except && c->excepts && c->excepts->count) { av[0] = sstrdup("-e"); for (cur = c->excepts->entries; cur; cur = enext) { enext = cur->next; av[1] = sstrdup(cur->mask); anope_cmd_mode(whosends(ci), chan, "-e %s", cur->mask); chan_set_modes(whosends(ci), c, 2, av, 0); free(av[1]); } free(av[0]); } if (ircd->invitemode && c->invites && c->invites->count) { av[0] = sstrdup("-I"); for (cur = c->invites->entries; cur; cur = enext) { enext = cur->next; av[1] = sstrdup(cur->mask); anope_cmd_mode(whosends(ci), chan, "-I %s", cur->mask); chan_set_modes(whosends(ci), c, 2, av, 0); free(av[1]); } free(av[0]); } for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) continue; av[0] = c->name; av[1] = cu->user->nick; av[2] = reason ? reason : "CHAN_FORBID_REASON"; anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]); do_kick(s_ChanServ, 3, av); } } if (WallForbid) anope_cmd_global(s_ChanServ, "\2%s\2 used FORBID on channel \2%s\2", u->nick, ci->name); if (ircd->chansqline) { anope_cmd_sqline(ci->name, ((reason) ? reason : "Forbidden")); } alog("%s: %s set FORBID for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan); send_event(EVENT_CHAN_FORBIDDEN, 1, chan); } else { alog("%s: Valid FORBID for %s by %s failed", s_ChanServ, ci->name, u->nick); notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan); } return MOD_CONT; }
int do_addnick(User * u) { NickAlias *na, *target; NickCore *nc; char *nick = strtok(NULL, " "); char *pass = strtok(NULL, " "); int i; char tsbuf[16]; char modes[512]; int len; if (NSEmailReg && (findrequestnick(u->nick))) { notice_lang(s_NickServ, u, NS_REQUESTED); return MOD_CONT; } if (readonly) { notice_lang(s_NickServ, u, NS_ADDNICK_DISABLED); return MOD_CONT; } if (checkDefCon(DEFCON_NO_NEW_NICKS)) { notice_lang(s_NickServ, u, OPER_DEFCON_DENIED); return MOD_CONT; } if (RestrictOperNicks) { for (i = 0; i < RootNumber; i++) { if (stristr(u->nick, ServicesRoots[i]) && !is_oper(u)) { notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); return MOD_CONT; } } for (i = 0; i < servadmins.count && (nc = servadmins.list[i]); i++) { if (stristr(u->nick, nc->display) && !is_oper(u)) { notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); return MOD_CONT; } } for (i = 0; i < servopers.count && (nc = servopers.list[i]); i++) { if (stristr(u->nick, nc->display) && !is_oper(u)) { notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); return MOD_CONT; } } } if (!nick || !pass) { syntax_error(s_NickServ, u, "ADDNICK", NS_ADDNICK_SYNTAX); } else if (!(target = findnick(nick))) { notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); } else if (time(NULL) < u->lastnickreg + NSRegDelay) { notice_lang(s_NickServ, u, NS_ADDNICK_PLEASE_WAIT, NSRegDelay); } else if (u->na && (u->na->status & NS_VERBOTEN)) { alog("%s: %s@%s tried to use ADDNICK from forbidden nick %s.", s_NickServ, u->username, u->host, u->nick); notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u->nick); } else if (u->na && (u->na->nc->flags & NI_SUSPENDED)) { alog("%s: %s!%s@%s tried to use ADDNICK from suspended nick %s.", s_NickServ, u->nick, u->username, u->host, target->nick); notice_lang(s_NickServ, u, NICK_X_SUSPENDED, u->nick); } else if (u->na && NSNoGroupChange) { notice_lang(s_NickServ, u, NS_ADDNICK_CHANGE_DISABLED, s_NickServ); } else if (u->na && !nick_identified(u)) { notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); } else if (target && (target->nc->flags & NI_SUSPENDED)) { alog("%s: %s!%s@%s tried to use GROUP from SUSPENDED nick %s", s_NickServ, u->nick, u->username, u->host, target->nick); notice_lang(s_NickServ, u, NICK_X_SUSPENDED, target->nick); } else if (target->status & NS_VERBOTEN) { notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick); } else if (u->na && target->nc == u->na->nc) { notice_lang(s_NickServ, u, NS_ADDNICK_SAME, target->nick); } else if (NSMaxAliases && (target->nc->aliases.count >= NSMaxAliases) && !nick_is_services_admin(target->nc)) { notice_lang(s_NickServ, u, NS_ADDNICK_TOO_MANY, target->nick, s_NickServ, s_NickServ); } else if (enc_check_password(pass, target->nc->pass) != 1) { alog("%s: Failed ADDNICK for %s!%s@%s (invalid password).", s_NickServ, u->nick, u->username, u->host); notice_lang(s_NickServ, u, PASSWORD_INCORRECT); bad_password(u); } else { /* If the nick is already registered, drop it. * If not, check that it is valid. */ if (u->na) { delnick(u->na); } else { int prefixlen = strlen(NSGuestNickPrefix); int nicklen = strlen(u->nick); if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && stristr(u->nick, NSGuestNickPrefix) == u->nick && strspn(u->nick + prefixlen, "1234567890") == nicklen - prefixlen) { notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); return MOD_CONT; } } na = makealias(u->nick, target->nc); if (na) { na->last_usermask = scalloc(strlen(common_get_vident(u)) + strlen(common_get_vhost(u)) + 2, 1); sprintf(na->last_usermask, "%s@%s", common_get_vident(u), common_get_vhost(u)); na->last_realname = sstrdup(u->realname); na->time_registered = na->last_seen = time(NULL); na->status = (int16) (NS_IDENTIFIED | NS_RECOGNIZED); if (!(na->nc->flags & NI_SERVICES_ROOT)) { for (i = 0; i < RootNumber; i++) { if (!stricmp(ServicesRoots[i], u->nick)) { na->nc->flags |= NI_SERVICES_ROOT; break; } } } u->na = na; na->u = u; #ifdef USE_RDB /* Is this really needed? Since this is a new alias it will get * its unique id on the next update, since it was previously * deleted by delnick. Must observe... */ if (rdb_open()) { rdb_save_ns_alias(na); rdb_close(); } #endif send_event(EVENT_GROUP, 1, u->nick); alog("%s: %s!%s@%s makes %s join group of %s (%s) (e-mail: %s)", s_NickServ, u->nick, u->username, u->host, u->nick, target->nick, target->nc->display, (target->nc->email ? target->nc->email : "none")); notice_lang(s_NickServ, u, NS_ADDNICK_SUCCESS, target->nick); u->lastnickreg = time(NULL); snprintf(tsbuf, sizeof(tsbuf), "%lu", (unsigned long int) u->timestamp); if (ircd->modeonreg) { len = strlen(ircd->modeonreg); strncpy(modes,ircd->modeonreg,512); if(ircd->rootmodeonid && is_services_root(u)) { strncat(modes,ircd->rootmodeonid,512-len); } else if(ircd->adminmodeonid && is_services_admin(u)) { strncat(modes,ircd->adminmodeonid,512-len); } else if(ircd->opermodeonid && is_services_oper(u)) { strncat(modes,ircd->opermodeonid,512-len); } if (ircd->tsonmode) { common_svsmode(u, modes, tsbuf); } else { common_svsmode(u, modes, NULL); } } check_memos(u); } else { alog("%s: makealias(%s) failed", s_NickServ, u->nick); notice_lang(s_NickServ, u, NS_ADDNICK_FAILED); } } return MOD_CONT; }
/** * Handle STATS commands * * @param source is the nick of the person whom sent the stats command * @param ac is the parameter count * @param av is the parameter array * * @return always returns MOD_CONT */ int m_stats(char *source, int ac, char **av) { User *u; Dadmin *a; int i; if (ac < 1) return MOD_CONT; switch (*av[0]) { case 'l': u = user_find(source); if (u && is_oper(u)) { denora_cmd_numeric (source, 211, "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime"); denora_cmd_numeric(source, 211, "%s %d %d %d %d %d %d %ld", RemoteServer, write_buffer_len(), total_written, total_recmsg, read_buffer_len(), total_read, total_sendmsg, time(NULL) - denora->start_time); } denora_cmd_219(source, NULL); break; case 'o': case 'O': /* Check whether the user is an operator */ u = user_find(source); if (u && !is_oper(u) && HideStatsO) { denora_cmd_219(source, av[0]); } else { for (i = 0; i < 1024; i++) { for (a = adminlists[i]; a; a = a->next) { denora_cmd_numeric(source, 243, "O * * %s Admin 0", a->name); } } denora_cmd_219(source, av[0]); } break; case 'u':{ int uptime = time(NULL) - denora->start_time; denora_cmd_numeric(source, 242, ":Stats up %d day%s, %02d:%02d:%02d", uptime / 86400, (uptime / 86400 == 1) ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60); denora_cmd_numeric(source, 250, ":Current users: %d (%d ops); maximum %d", stats->users, stats->opers, stats->users_max); denora_cmd_219(source, av[0]); break; } /* case 'u' */ default: denora_cmd_219(source, av[0]); break; } return MOD_CONT; }
/** * Adds a new user to anopes internal userlist. * * If the SVID passed is 2, the user will not be marked registered or requested to ID. * This is an addition to accomodate IRCds where we cannot determine this based on the NICK * or UID command. Some IRCd's keep +r on when changing nicks and do not use SVID (ex. InspIRCd 1.2). * Instead we get a METADATA command containing the accountname the user was last identified to. * Since this is received after the user is introduced to us we should not yet mark the user * as identified or ask him to identify. We will mark him as recognized for the time being and let * him keep his +r if he has it. * It is the responsibility of the protocol module to make sure that this is either invalidated, * or changed to identified. ~ Viper **/ User *do_nick(const char *source, char *nick, char *username, char *host, char *server, char *realname, time_t ts, uint32 svid, uint32 ip, char *vhost, char *uid) { User *user = NULL; char *tmp = NULL; NickAlias *old_na; /* Old nick rec */ int nc_changed = 1; /* Did nick core change? */ int status = 0; /* Status to apply */ char mask[USERMAX + HOSTMAX + 2]; char *logrealname; char *oldnick; if (!*source) { char ipbuf[16]; struct in_addr addr; if (ircd->nickvhost) { if (vhost) { if (!strcmp(vhost, "*")) { vhost = NULL; if (debug) alog("debug: new user�with no vhost in NICK command: %s", nick); } } } /* This is a new user; create a User structure for it. */ if (debug) alog("debug: new user: %s", nick); if (ircd->nickip) { addr.s_addr = htonl(ip); ntoa(addr, ipbuf, sizeof(ipbuf)); } if (LogUsers) { /** * Ugly swap routine for Flop's bug :) **/ if (realname) { tmp = strchr(realname, '%'); while (tmp) { *tmp = '-'; tmp = strchr(realname, '%'); } } logrealname = normalizeBuffer(realname); /** * End of ugly swap **/ if (ircd->nickvhost) { if (ircd->nickip) { alog("LOGUSERS: %s (%s@%s => %s) (%s) [%s] connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, ipbuf, server); } else { alog("LOGUSERS: %s (%s@%s => %s) (%s) connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, server); } } else { if (ircd->nickip) { alog("LOGUSERS: %s (%s@%s) (%s) [%s] connected to the network (%s).", nick, username, host, logrealname, ipbuf, server); } else { alog("LOGUSERS: %s (%s@%s) (%s) connected to the network (%s).", nick, username, host, logrealname, server); } } Anope_Free(logrealname); } /* We used to ignore the ~ which a lot of ircd's use to indicate no * identd response. That caused channel bans to break, so now we * just take what the server gives us. People are still encouraged * to read the RFCs and stop doing anything to usernames depending * on the result of an identd lookup. */ /* First check for AKILLs. */ /* DONT just return null if its an akill match anymore - yes its more efficent to, however, now that ircd's are * starting to use things like E/F lines, we cant be 100% sure the client will be removed from the network :/ * as such, create a user_struct, and if the client is removed, we'll delete it again when the QUIT notice * comes in from the ircd. **/ if (check_akill(nick, username, host, vhost, ipbuf)) { /* return NULL; */ } /** * DefCon AKILL system, if we want to akill all connecting user's here's where to do it * then force check_akill again on them... **/ /* don't akill on netmerges -Certus */ /* don't akill clients introduced by ulines. -Viper */ if (is_sync(findserver(servlist, server)) && checkDefCon(DEFCON_AKILL_NEW_CLIENTS) && !is_ulined(server)) { strncpy(mask, "*@", 3); strncat(mask, host, HOSTMAX); alog("DEFCON: adding akill for %s", mask); add_akill(NULL, mask, s_OperServ, time(NULL) + dotime(DefConAKILL), DefConAkillReason ? DefConAkillReason : "DEFCON AKILL"); if (check_akill(nick, username, host, vhost, ipbuf)) { /* return NULL; */ } } /* SGLINE */ if (ircd->sgline) { if (check_sgline(nick, realname)) return NULL; } /* SQLINE */ if (ircd->sqline) { if (check_sqline(nick, 0)) return NULL; } /* SZLINE */ if (ircd->szline && ircd->nickip) { if (check_szline(nick, ipbuf)) return NULL; } /* Now check for session limits */ if (LimitSessions && !is_ulined(server) && !add_session(nick, host, ipbuf)) return NULL; /* Allocate User structure and fill it in. */ user = new_user(nick); user->username = sstrdup(username); user->host = sstrdup(host); user->server = findserver(servlist, server); user->realname = sstrdup(realname); user->timestamp = ts; user->my_signon = time(NULL); user->chost = vhost ? sstrdup(vhost) : sstrdup(host); user->vhost = vhost ? sstrdup(vhost) : sstrdup(host); if (uid) { user->uid = sstrdup(uid); /* p10/ts6 stuff */ } else { user->uid = NULL; } user->vident = sstrdup(username); /* We now store the user's ip in the user_ struct, * because we will use it in serveral places -- DrStein */ if (ircd->nickip) { user->hostip = sstrdup(ipbuf); } else { user->hostip = NULL; } if (svid == 0) { display_news(user, NEWS_LOGON); display_news(user, NEWS_RANDOM); } if (svid == 2 && user->na) { /* We do not yet know if the user should be identified or not. * mark him as recognized for now. * It s up to the protocol module to make sure this either becomes ID'd or * is invalidated. ~ Viper */ if (debug) alog("debug: Marking %s as recognized..", user->nick); user->svid = 1; user->na->status |= NS_RECOGNIZED; nc_changed = 0; } else if (svid == ts && user->na) { /* Timestamp and svid match, and nick is registered; automagically identify the nick */ user->svid = svid; user->na->status |= NS_IDENTIFIED; check_memos(user); nc_changed = 0; /* Start nick tracking if available */ if (NSNickTracking) nsStartNickTracking(user); } else if (svid != 1) { /* Resets the svid because it doesn't match */ user->svid = 1; anope_cmd_svid_umode(user->nick, user->timestamp); } else { user->svid = 1; } send_event(EVENT_NEWNICK, 1, nick); } else { /* An old user changing nicks. */ if (UseTS6 && ircd->ts6) user = find_byuid(source); if (!user) user = finduser(source); if (!user) { alog("user: NICK from nonexistent nick %s", source); return NULL; } user->isSuperAdmin = 0; /* Dont let people nick change and stay SuperAdmins */ if (debug) alog("debug: %s changes nick to %s", source, nick); if (LogUsers) { logrealname = normalizeBuffer(user->realname); if (ircd->vhost) { alog("LOGUSERS: %s (%s@%s => %s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), logrealname, nick, user->server->name); } else { alog("LOGUSERS: %s (%s@%s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, logrealname, nick, user->server->name); } if (logrealname) { free(logrealname); } } user->timestamp = ts; if (stricmp(nick, user->nick) == 0) { /* No need to redo things */ change_user_nick(user, nick); nc_changed = 0; } else { /* Update this only if nicks aren't the same */ user->my_signon = time(NULL); old_na = user->na; if (old_na) { if (nick_recognized(user)) user->na->last_seen = time(NULL); status = old_na->status & NS_TRANSGROUP; cancel_user(user); } oldnick = sstrdup(user->nick); change_user_nick(user, nick); if ((old_na ? old_na->nc : NULL) == (user->na ? user->na->nc : NULL)) nc_changed = 0; if (!nc_changed && (user->na)) user->na->status |= status; else { anope_cmd_nc_change(user); } send_event(EVENT_CHANGE_NICK, 2, nick, oldnick); free(oldnick); } if (ircd->sqline) { if (!is_oper(user) && check_sqline(user->nick, 1)) return NULL; } } /* if (!*source) */ /* Check for nick tracking to bypass identification */ if (NSNickTracking && nsCheckNickTracking(user)) { user->na->status |= NS_IDENTIFIED; nc_changed = 0; } if (nc_changed || !nick_recognized(user)) { if (validate_user(user)) check_memos(user); } else { if (nick_identified(user)) { char tsbuf[16]; user->na->last_seen = time(NULL); if (user->na->last_usermask) free(user->na->last_usermask); user->na->last_usermask = smalloc(strlen(common_get_vident(user)) + strlen(common_get_vhost(user)) + 2); sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user), common_get_vhost(user)); snprintf(tsbuf, sizeof(tsbuf), "%lu", (unsigned long int) user->timestamp); anope_cmd_svid_umode2(user, tsbuf); alog("%s: %s!%s@%s automatically identified for nick %s", s_NickServ, user->nick, user->username, user->host, user->nick); } } /* Bahamut sets -r on every nick changes, so we must test it even if nc_changed == 0 */ if (ircd->check_nick_id) { if (nick_identified(user)) { char tsbuf[16]; snprintf(tsbuf, sizeof(tsbuf), "%lu", (unsigned long int) user->timestamp); anope_cmd_svid_umode3(user, tsbuf); } } return user; }
/** * The /cs (un)suspend command. * @param u The user who issued the command * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. **/ static int do_suspend(User * u) { ChannelInfo *ci; char *chan = strtok(NULL, " "); char *reason = strtok(NULL, ""); Channel *c; /* Assumes that permission checking has already been done. */ if (!chan || (ForceForbidReason && !reason)) { syntax_error(s_ChanServ, u, "SUSPEND", (ForceForbidReason ? CHAN_SUSPEND_SYNTAX_REASON : CHAN_SUSPEND_SYNTAX)); return MOD_CONT; } if (chan[0] != '#') { notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_ERROR); return MOD_CONT; } /* Only SUSPEND existing channels, otherwise use FORBID (bug #54) */ if ((ci = cs_findchan(chan)) == NULL) { notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); return MOD_CONT; } /* You should not SUSPEND a FORBIDEN channel */ if (ci->flags & CI_VERBOTEN) { notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan); return MOD_CONT; } if (readonly) notice_lang(s_ChanServ, u, READ_ONLY_MODE); if (ci) { ci->flags |= CI_SUSPENDED; ci->forbidby = sstrdup(u->nick); if (reason) ci->forbidreason = sstrdup(reason); if ((c = findchan(ci->name))) { struct c_userlist *cu, *next; char *av[3]; for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) continue; av[0] = c->name; av[1] = cu->user->nick; av[2] = reason ? reason : getstring(cu->user->na, CHAN_SUSPEND_REASON); anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]); do_kick(s_ChanServ, 3, av); } } if (WallForbid) anope_cmd_global(s_ChanServ, "\2%s\2 used SUSPEND on channel \2%s\2", u->nick, ci->name); alog("%s: %s set SUSPEND for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan); send_event(EVENT_CHAN_SUSPENDED, 1, chan); } else { alog("%s: Valid SUSPEND for %s by %s failed", s_ChanServ, ci->name, u->nick); notice_lang(s_ChanServ, u, CHAN_SUSPEND_FAILED, chan); } return MOD_CONT; }