static void os_akill_newuser(hook_user_nick_t *data) { struct user *u = data->u; struct kline *k; // If the user has been killed, don't do anything. if (!u) return; if (is_internal_client(u)) return; k = kline_find_user(u); if (k != NULL) { /* Server didn't have that kline, send it again. * To ensure kline exempt works on akills too, do * not send a KILL. -- jilles */ char reason[BUFSIZE]; snprintf(reason, sizeof(reason), "[#%lu] %s", k->number, k->reason); if (! (u->flags & UF_KLINESENT)) { kline_sts("*", k->user, k->host, k->duration ? k->expires - CURRTIME : 0, reason); u->flags |= UF_KLINESENT; } } }
static void connavg_newuser(hook_user_nick_t *data) { user_t *u = data->u; /* If the user has been killed, don't do anything. */ if (!(u)) return; /* If the user is an internal client, still don't do anything. */ if (is_internal_client(u)) return; /* Most likely, we will have a massive influx in connections when bursts happen; skip those. */ if (me.bursting) return; s.connections++; if (s.connections > safe_connections) { /* Send a warning every five connects greater than the "safe" connection allowence. */ if (s.connections % 5 == 0) { wallops("WARNING! Connections in the last minute was %d, which is above the maxium safe connections of %d per minute!", s.connections, safe_connections); s.alert_time = time(NULL); } } if (s.connections > s.peak_conn) { s.peak_conn = s.connections; s.peak_time = time(NULL); } }
static void cs_cmd_devoice(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DEVOICE"); command_fail(si, fault_needmoreparams, _("Syntax: DEVOICE <#channel> [nickname]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_VOICE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } /* figure out who we're going to devoice */ if (!nick) tu = si->su; else { if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } } if (is_internal_client(tu)) return; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, 'v', CLIENT_NAME(tu)); cu->modes &= ~CSTATUS_VOICE; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been devoiced on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "DEVOICE: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (!chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been devoiced on \2%s\2."), tu->nick, mc->name); }
static user_t *pick_a_sucker(channel_t *c) { int slot = arc4random() % MOWGLI_LIST_LENGTH(&c->members); chanuser_t *cu; cu = (chanuser_t *) mowgli_node_nth_data(&c->members, slot); while (cu != NULL && is_internal_client(cu->user)) { slot = arc4random() % MOWGLI_LIST_LENGTH(&c->members); cu = (chanuser_t *) mowgli_node_nth_data(&c->members, slot); } return cu != NULL ? cu->user : NULL; }
static void aknl_nickhook(hook_user_nick_t *data) { return_if_fail(data != NULL); if (! data->u) return; user_t *const u = data->u; if (is_internal_client(u)) return; if (is_autokline_exempt(u)) return; if (u->flags & UF_KLINESENT) return; const char *username = u->user; if (*username == '~') username++; bool doit = false; if (mowgli_patricia_retrieve(akillnicklist, u->nick)) doit = true; else if (mowgli_patricia_retrieve(akilluserlist, username)) doit = true; else if (mowgli_patricia_retrieve(akillreallist, u->gecos)) doit = true; else if (mowgli_patricia_retrieve(akillalllist, u->nick)) doit = true; else if (mowgli_patricia_retrieve(akillalllist, username)) doit = true; else if (mowgli_patricia_retrieve(akillalllist, u->gecos)) doit = true; else return; slog(LG_INFO, "AKNL: k-lining \2%s\2!%s@%s [%s] due to appearing to be a possible spambot", u->nick, u->user, u->host, u->gecos); kline_add(u->user, u->host, "Possible spambot", 86400, "*"); u->flags |= UF_KLINESENT; }
static void aknl_nickhook(hook_user_nick_t *data) { user_t *u; bool doit = false; const char *username; return_if_fail(data != NULL); if (!data->u) return; u = data->u; if (is_internal_client(u)) return; if (is_autokline_exempt(u)) return; username = u->user; if (*username == '~') username++; if (mowgli_patricia_retrieve(akillalllist, u->nick) != NULL && mowgli_patricia_retrieve(akillalllist, username) != NULL && mowgli_patricia_retrieve(akillalllist, u->gecos) != NULL) doit = true; if (mowgli_patricia_retrieve(akillnicklist, u->nick) != NULL) doit = true; if (mowgli_patricia_retrieve(akilluserlist, username) != NULL) doit = true; if (mowgli_patricia_retrieve(akillreallist, u->gecos) != NULL) doit = true; if (!doit) return; slog(LG_INFO, "AKNL: k-lining \2%s\2!%s@%s [%s] due to appearing to be a possible spambot", u->nick, u->user, u->host, u->gecos); kline_sts("*", "*", u->host, 86400, "Possible spambot"); }
static void cs_cmd_kick(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; char *reason = parv[2]; mychan_t *mc; user_t *tu; chanuser_t *cu; char reasonbuf[BUFSIZE]; if (!chan || !nick) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "KICK"); command_fail(si, fault_needmoreparams, _("Syntax: KICK <#channel> <nickname> [reason]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to kick */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } /* if target is a service, bail. --nenolod */ if (is_internal_client(tu)) return; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } if (cu->modes & CSTATUS_OWNER || cu->modes & CSTATUS_PROTECT) { command_fail(si, fault_noprivs, _("\2%s\2 is protected from kicks; you cannot kick them."), tu->nick); return; } snprintf(reasonbuf, BUFSIZE, "(%s) %s", get_source_name(si), reason ? reason : "No reason given"); try_kick(chansvs.me->me, mc->chan, tu, reasonbuf); logcommand(si, CMDLOG_DO, "KICK: \2%s!%s@%s\2 from \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su != tu && !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been kicked from \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_owner(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; char *nicklist; char *strtokctx; if (ircd->uses_owner == false) { command_fail(si, fault_noprivs, _("The IRCd software you are running does not support this feature.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "OWNER"); command_fail(si, fault_needmoreparams, _("Syntax: OWNER <#channel> [nickname] [...]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_USEOWNER)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '-', &cs_cmd_deowner)) continue; /* figure out who we're going to op */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); continue; } if (is_internal_client(tu)) continue; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((si->su != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_OP) && !chanacs_user_has_flag(mc, tu, CA_AUTOOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); command_fail(si, fault_noprivs, _("\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access."), mc->name, tu->nick); continue; } cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); continue; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(tu)); cu->modes |= CSTATUS_OWNER; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been set as owner on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "OWNER: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been set as owner on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }
static void cs_cmd_halfop(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; if (!ircd->uses_halfops) { command_fail(si, fault_noprivs, _("Your IRC server does not support halfops.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "HALFOP"); command_fail(si, fault_needmoreparams, _("Syntax: HALFOP <#channel> [nickname]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_HALFOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to halfop */ if (!nick) tu = si->su; else { if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } } if (is_internal_client(tu)) return; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((si->su != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_HALFOP) && !chanacs_user_has_flag(mc, tu, CA_AUTOHALFOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); command_fail(si, fault_noprivs, _("\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access."), mc->name, tu->nick); return; } cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, 'h', CLIENT_NAME(tu)); cu->modes |= ircd->halfops_mode; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been halfopped on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "HALFOP: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (!chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been halfopped on \2%s\2."), tu->nick, mc->name); }
static void os_cmd_specs(sourceinfo_t *si, int parc, char *parv[]) { user_t *tu = NULL; operclass_t *cl = NULL; const char *targettype = parv[0]; const char *target = parv[1]; unsigned int i; int j, n; if (!has_any_privs(si)) { command_fail(si, fault_noprivs, _("You are not authorized to use %s."), si->service->nick); return; } if (targettype != NULL) { if (!has_priv(si, PRIV_VIEWPRIVS)) { command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_VIEWPRIVS); return; } if (target == NULL) target = "?"; if (!strcasecmp(targettype, "USER")) { tu = user_find_named(target); if (tu == NULL) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on IRC."), target); return; } if (!has_any_privs_user(tu)) { command_success_nodata(si, _("\2%s\2 is unprivileged."), tu->nick); return; } if (is_internal_client(tu)) { command_fail(si, fault_noprivs, _("\2%s\2 is an internal client."), tu->nick); return; } } else if (!strcasecmp(targettype, "OPERCLASS") || !strcasecmp(targettype, "CLASS")) { cl = operclass_find(target); if (cl == NULL) { command_fail(si, fault_nosuch_target, _("No such oper class \2%s\2."), target); return; } } else { command_fail(si, fault_badparams, _("Valid target types: USER, OPERCLASS.")); return; } } else tu = si->su; if (targettype == NULL) command_success_nodata(si, _("Privileges for \2%s\2:"), get_source_name(si)); else if (tu) command_success_nodata(si, _("Privileges for \2%s\2:"), tu->nick); else command_success_nodata(si, _("Privileges for oper class \2%s\2:"), cl->name); for (i = 0; i < ARRAY_SIZE(priv_categories); i++) { struct priv_category *cat = priv_categories[i]; command_success_nodata(si, "\2%s\2:", _(cat->name)); for (j = n = 0; cat->privs[j].priv != NULL; j++) { if (targettype == NULL ? has_priv(si, cat->privs[j].priv) : (tu ? has_priv_user(tu, cat->privs[j].priv) : has_priv_operclass(cl, cat->privs[j].priv))) { command_success_nodata(si, " %s (%s)", cat->privs[j].priv, _(cat->privs[j].desc)); ++n; } } if (!n) command_success_nodata(si, " %s", _("(no privileges held)")); } command_success_nodata(si, _("End of privileges")); if (targettype == NULL) logcommand(si, CMDLOG_ADMIN, "SPECS"); else if (tu) logcommand(si, CMDLOG_ADMIN, "SPECS:USER: \2%s!%s@%s\2", tu->nick, tu->user, tu->vhost); else logcommand(si, CMDLOG_ADMIN, "SPECS:OPERCLASS: \2%s\2", cl->name); }
static void cs_cmd_deowner(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; if (ircd->uses_owner == false) { command_fail(si, fault_noprivs, _("The IRCd software you are running does not support this feature.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DEOWNER"); command_fail(si, fault_needmoreparams, _("Syntax: DEOWNER <#channel> [nickname]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_USEOWNER)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to deop */ if (!nick) tu = si->su; else { if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } } if (is_internal_client(tu)) return; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, ircd->owner_mchar[1], CLIENT_NAME(tu)); cu->modes &= ~CSTATUS_OWNER; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been unset as owner on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "DEOWNER: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been unset as owner on \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_halfop(char *origin) { char *chan = strtok(NULL, " "); char *nick = strtok(NULL, " "); mychan_t *mc; user_t *u, *tu; chanuser_t *cu; if (!ircd->uses_halfops) { notice(chansvs.nick, origin, "Your IRC server does not support halfops."); return; } if (!chan) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "HALFOP"); notice(chansvs.nick, origin, "Syntax: HALFOP <#channel> [nickname]"); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } u = user_find_named(origin); if (!chanacs_user_has_flag(mc, u, CA_HALFOP)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer")) { notice(chansvs.nick, origin, "\2%s\2 is closed.", chan); return; } /* figure out who we're going to halfop */ if (!nick) tu = u; else { if (!(tu = user_find_named(nick))) { notice(chansvs.nick, origin, "\2%s\2 is not online.", nick); return; } } if (is_internal_client(tu)) return; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((u != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_HALFOP) && !chanacs_user_has_flag(mc, tu, CA_AUTOHALFOP)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation.", mc->name); notice(chansvs.nick, origin, "\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access.", mc->name, tu->nick); return; } cu = chanuser_find(mc->chan, tu); if (!cu) { notice(chansvs.nick, origin, "\2%s\2 is not on \2%s\2.", tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, chan, MTYPE_ADD, 'h', CLIENT_NAME(tu)); cu->modes |= ircd->halfops_mode; /* TODO: Add which username had access to perform the command */ if (tu != u) notice(chansvs.nick, tu->nick, "You have been halfopped on %s by %s", mc->name, origin); logcommand(chansvs.me, u, CMDLOG_SET, "%s HALFOP %s!%s@%s", mc->name, tu->nick, tu->user, tu->vhost); if (!chanuser_find(mc->chan, u)) notice(chansvs.nick, origin, "\2%s\2 has been halfopped on \2%s\2.", tu->nick, mc->name); }
static void cs_fcmd_dehalfop(char *origin, char *chan) { char *nick; mychan_t *mc; user_t *u, *tu; chanuser_t *cu; if (!ircd->uses_halfops) { notice(chansvs.nick, origin, "Your IRC server does not support halfops."); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } u = user_find_named(origin); if (!chanacs_user_has_flag(mc, u, CA_HALFOP)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer")) { notice(chansvs.nick, origin, "\2%s\2 is closed.", chan); return; } /* figure out who we're going to dehalfop */ nick = strtok(NULL, " "); do { if (!nick) tu = u; else { if (!(tu = user_find_named(nick))) { notice(chansvs.nick, origin, "\2%s\2 is not online.", nick); continue; } } if (is_internal_client(tu)) continue; cu = chanuser_find(mc->chan, tu); if (!cu) { notice(chansvs.nick, origin, "\2%s\2 is not on \2%s\2.", tu->nick, mc->name); continue; } modestack_mode_param(chansvs.nick, chan, MTYPE_DEL, 'h', CLIENT_NAME(tu)); cu->modes &= ~ircd->halfops_mode; logcommand(chansvs.me, u, CMDLOG_SET, "%s DEHALFOP %s!%s@%s", mc->name, tu->nick, tu->user, tu->vhost); } while ((nick = strtok(NULL, " ")) != NULL); }
static void cs_cmd_voice(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; char *nicklist; char *strtokctx; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "VOICE"); command_fail(si, fault_needmoreparams, _("Syntax: VOICE <#channel> [nickname] [...]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '-', &cs_cmd_devoice)) continue; /* figure out who we're going to voice */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); continue; } if (!chanacs_source_has_flag(mc, si, CA_VOICE) && (tu != si->su || !chanacs_source_has_flag(mc, si, CA_AUTOVOICE))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); continue; } if (is_internal_client(tu)) continue; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); continue; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, 'v', CLIENT_NAME(tu)); cu->modes |= CSTATUS_VOICE; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been voiced on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "VOICE: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been voiced on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }
static void os_cmd_specs(char *origin) { user_t *u = user_find_named(origin), *tu = NULL; operclass_t *cl = NULL; char *targettype = strtok(NULL, " "); char *target = strtok(NULL, " "); char nprivs[BUFSIZE], cprivs[BUFSIZE], gprivs[BUFSIZE], oprivs[BUFSIZE]; int i; if (!has_any_privs(u)) { notice(opersvs.nick, origin, "You are not authorized to use %s.", opersvs.nick); return; } if (targettype != NULL) { if (!has_priv(u, PRIV_VIEWPRIVS)) { notice(opersvs.nick, origin, "You do not have %s privilege.", PRIV_VIEWPRIVS); return; } if (target == NULL) target = "?"; if (!strcasecmp(targettype, "USER")) { tu = user_find_named(target); if (tu == NULL) { notice(opersvs.nick, origin, "\2%s\2 is not on IRC.", target); return; } if (!has_any_privs(tu)) { notice(opersvs.nick, origin, "\2%s\2 is unprivileged.", tu->nick); return; } if (is_internal_client(tu)) { notice(opersvs.nick, origin, "\2%s\2 is an internal client.", tu->nick); return; } } else if (!strcasecmp(targettype, "OPERCLASS") || !strcasecmp(targettype, "CLASS")) { cl = operclass_find(target); if (cl == NULL) { notice(opersvs.nick, origin, "No such oper class \2%s\2.", target); return; } } else { notice(opersvs.nick, origin, "Valid target types: USER, OPERCLASS."); return; } } else tu = u; i = 0; *nprivs = *cprivs = *gprivs = *oprivs = '\0'; while (privnames[i].priv != NULL) { if (tu ? has_priv(tu, privnames[i].priv) : has_priv_operclass(cl, privnames[i].priv)) { if (privnames[i].npriv != NULL) { if (*nprivs) strcat(nprivs, ", "); strcat(nprivs, privnames[i].npriv); } if (privnames[i].cpriv != NULL) { if (*cprivs) strcat(cprivs, ", "); strcat(cprivs, privnames[i].cpriv); } if (privnames[i].gpriv != NULL) { if (*gprivs) strcat(gprivs, ", "); strcat(gprivs, privnames[i].gpriv); } if (privnames[i].opriv != NULL) { if (*oprivs) strcat(oprivs, ", "); strcat(oprivs, privnames[i].opriv); } } i++; } if (tu) notice(opersvs.nick, origin, "Privileges for \2%s\2:", tu->nick); else notice(opersvs.nick, origin, "Privileges for oper class \2%s\2:", cl->name); if (*nprivs) notice(opersvs.nick, origin, "\2Nicknames/accounts\2: %s", nprivs); if (*cprivs) notice(opersvs.nick, origin, "\2Channels\2: %s", cprivs); if (*gprivs) notice(opersvs.nick, origin, "\2General\2: %s", gprivs); if (*oprivs) notice(opersvs.nick, origin, "\2OperServ\2: %s", oprivs); notice(opersvs.nick, origin, "End of privileges"); if (tu) logcommand(opersvs.me, user_find_named(origin), CMDLOG_ADMIN, "SPECS USER %s!%s@%s", tu->nick, tu->user, tu->vhost); else logcommand(opersvs.me, user_find_named(origin), CMDLOG_ADMIN, "SPECS OPERCLASS %s", cl->name); }