static void ns_cmd_fungroup(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn, *mn2 = NULL; myuser_t *mu; hook_user_req_t hdata; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FUNGROUP"); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> [newaccountname]")); return; } mn = mynick_find(parv[0]); if (mn == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[0]); return; } mu = mn->owner; if (!irccasecmp(mn->nick, entity(mu)->name)) { if (MOWGLI_LIST_LENGTH(&mu->nicks) <= 1 || !module_find_published("nickserv/set_accountname")) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is an account name; you may not remove it."), mn->nick); return; } if (is_conf_soper(mu)) { command_fail(si, fault_noprivs, _("You may not modify \2%s\2's account name because their operclass is defined in the configuration file."), entity(mu)->name); return; } if (parc < 2) { command_fail(si, fault_needmoreparams, _("Please specify a new account name for \2%s\2."), entity(mu)->name); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> <newaccountname>")); return; } mn2 = mynick_find(parv[1]); if (mn2 == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[1]); return; } if (mn2 == mn) { command_fail(si, fault_noprivs, _("The new account name must be different from the nick to be ungrouped.")); return; } if (mn2->owner != mu) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is not registered to \2%s\2."), mn2->nick, entity(mu)->name); return; } } else if (parc > 1) { command_fail(si, fault_badparams, _("Nick \2%s\2 is not an account name so no new account name is needed."), mn->nick); return; } if (mn2 != NULL) { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2 (new account name: \2%s\2)", mn->nick, entity(mu)->name, mn2->nick); wallops("%s dropped the nick \2%s\2 from %s, changing account name to \2%s\2", get_oper_name(si), mn->nick, entity(mu)->name, mn2->nick); myuser_rename(mu, mn2->nick); } else { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2", mn->nick, entity(mu)->name); wallops("%s dropped the nick \2%s\2 from %s", get_oper_name(si), mn->nick, entity(mu)->name); } hdata.si = si; hdata.mu = mu; hdata.mn = mn; hook_call_nick_ungroup(&hdata); holdnick_sts(si->service->me, 0, mn->nick, NULL); if (mn2 != NULL) command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2, name changed to \2%s\2."), mn->nick, entity(mu)->name, mn2->nick); else command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2."), mn->nick, entity(mu)->name); object_unref(mn); }
static void gs_cmd_set_public(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; if (!parv[0] || !parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "PUBLIC"); command_fail(si, fault_needmoreparams, _("Syntax: PUBLIC <!group> <ON|OFF>")); return; } if ((mg = mygroup_find(parv[0])) == NULL) { command_fail(si, fault_nosuch_target, _("The group \2%s\2 does not exist."), parv[0]); return; } if (si->smu == NULL) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!groupacs_sourceinfo_has_flag(mg, si, GA_FOUNDER)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!strcasecmp(parv[1], "ON")) { if (mg->flags & MG_PUBLIC) { command_fail(si, fault_nochange, _("\2%s\2 is already public."), entity(mg)->name); return; } mg->flags |= MG_PUBLIC; logcommand(si, CMDLOG_SET, "PUBLIC:ON: \2%s\2", entity(mg)->name); command_success_nodata(si, _("\2%s\2 is now public."), entity(mg)->name); } else if (!strcasecmp(parv[1], "OFF")) { if (!(mg->flags & MG_PUBLIC)) { command_fail(si, fault_nochange, _("\2%s\2 is not public already."), entity(mg)->name); return; } mg->flags &= ~MG_PUBLIC; logcommand(si, CMDLOG_SET, "PUBLIC:OFF: \2%s\2", entity(mg)->name); command_success_nodata(si, _("\2%s\2 is no longer public."), entity(mg)->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "PUBLIC"); command_fail(si, fault_badparams, _("Syntax: PUBLIC <!group> <ON|OFF>")); } }
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; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "VOICE"); command_fail(si, fault_needmoreparams, _("Syntax: VOICE <#channel> [nickname]")); return; } if (nick && *nick == '-') { parv[1]++; cs_cmd_devoice(si, parc, parv); 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; } /* figure out who we're going to voice */ 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 (!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.")); 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_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 (!chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been voiced on \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_set_verbose(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET VERBOSE"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1]) || !strcasecmp("ALL", parv[1])) { if (MC_VERBOSE & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "VERBOSE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:VERBOSE:ON: \2%s\2", mc->name); mc->flags &= ~MC_VERBOSE_OPS; mc->flags |= MC_VERBOSE; verbose(mc, _("\2%s\2 enabled the VERBOSE flag"), get_source_name(si)); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "VERBOSE", mc->name); return; } else if (!strcasecmp("OPS", parv[1])) { if (MC_VERBOSE_OPS & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "VERBOSE_OPS", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:VERBOSE:OPS: \2%s\2", mc->name); if (mc->flags & MC_VERBOSE) { verbose(mc, _("\2%s\2 restricted VERBOSE to chanops"), get_source_name(si)); mc->flags &= ~MC_VERBOSE; mc->flags |= MC_VERBOSE_OPS; } else { mc->flags |= MC_VERBOSE_OPS; verbose(mc, _("\2%s\2 enabled the VERBOSE_OPS flag"), get_source_name(si)); } command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "VERBOSE_OPS", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!((MC_VERBOSE | MC_VERBOSE_OPS) & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "VERBOSE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:VERBOSE:OFF: \2%s\2", mc->name); if (mc->flags & MC_VERBOSE) verbose(mc, _("\2%s\2 disabled the VERBOSE flag"), get_source_name(si)); else verbose(mc, _("\2%s\2 disabled the VERBOSE_OPS flag"), get_source_name(si)); mc->flags &= ~(MC_VERBOSE | MC_VERBOSE_OPS); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "VERBOSE", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "VERBOSE"); return; } }
static void ns_cmd_restrict(sourceinfo_t *si, int parc, char *parv[]) { char *target = parv[0]; char *action = parv[1]; char *info = parv[2]; myuser_t *mu; myuser_name_t *mun; if (!target || !action) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "RESTRICT"); command_fail(si, fault_needmoreparams, _("Usage: RESTRICT <target> <ON|OFF> [note]")); return; } if (!(mu = myuser_find_ext(target))) { mun = myuser_name_find(target); if (mun != NULL && !strcasecmp(action, "OFF")) { object_unref(mun); wallops("%s unrestricted the name \2%s\2.", get_oper_name(si), target); logcommand(si, CMDLOG_ADMIN, "RESTRICT:OFF: \2%s\2", target); command_success_nodata(si, _("\2%s\2 is now unrestricted."), target); return; } command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), target); return; } if (!strcasecmp(action, "ON")) { if (!info) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "RESTRICT"); command_fail(si, fault_needmoreparams, _("Usage: RESTRICT <target> ON <note>")); return; } if (metadata_find(mu, "private:restrict:setter")) { command_fail(si, fault_badparams, _("\2%s\2 is already restricted."), entity(mu)->name); return; } metadata_add(mu, "private:restrict:setter", get_oper_name(si)); metadata_add(mu, "private:restrict:reason", info); metadata_add(mu, "private:restrict:timestamp", number_to_string(time(NULL))); wallops("%s restricted the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "RESTRICT:ON: \2%s\2 (reason: \2%s\2)", entity(mu)->name, info); command_success_nodata(si, _("\2%s\2 is now restricted."), entity(mu)->name); } else if (!strcasecmp(action, "OFF")) { if (!metadata_find(mu, "private:restrict:setter")) { command_fail(si, fault_badparams, _("\2%s\2 is not restricted."), entity(mu)->name); return; } metadata_delete(mu, "private:restrict:setter"); metadata_delete(mu, "private:restrict:reason"); metadata_delete(mu, "private:restrict:timestamp"); wallops("%s unrestricted the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "RESTRICT:OFF: \2%s\2", entity(mu)->name); command_success_nodata(si, _("\2%s\2 is now unrestricted."), entity(mu)->name); } else { command_fail(si, fault_needmoreparams, STR_INVALID_PARAMS, "RESTRICT"); command_fail(si, fault_needmoreparams, _("Usage: RESTRICT <target> <ON|OFF> [note]")); } }
static void cs_cmd_protect(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_protect == 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, "PROTECT"); command_fail(si, fault_needmoreparams, _("Syntax: PROTECT <#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_USEPROTECT)) { 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 op */ 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_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); 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, ircd->protect_mchar[1], CLIENT_NAME(tu)); cu->modes |= CSTATUS_PROTECT; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been set as protected on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "PROTECT: \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 protected on \2%s\2."), tu->nick, mc->name); }
static void cs_cmd_register(sourceinfo_t *si, int parc, char *parv[]) { channel_t *c; chanuser_t *cu; mychan_t *mc; char *name = parv[0]; char str[21]; hook_channel_register_check_t hdatac; hook_channel_req_t hdata; unsigned int fl; /* This command is not useful on registered channels, ignore it if * it is a fantasy command so users can program bots to react on * it without interference from ChanServ. */ if (si->c != NULL) return; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGISTER"); command_fail(si, fault_needmoreparams, _("To register a channel: REGISTER <#channel>")); return; } if (!VALID_REG_CHANNEL_PFX(name)) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER"); command_fail(si, fault_badparams, _("Syntax: REGISTER <#channel>")); return; } /* make sure it isn't already registered */ if ((mc = mychan_find(name))) { if (!use_channel_private || !(mc->flags & MC_PRIVATE)) command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered to \2%s\2."), mc->name, mychan_founder_names(mc)); else command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered."), mc->name); return; } /* make sure the channel exists */ if (!(c = channel_find(name))) { command_fail(si, fault_nosuch_target, _("The channel \2%s\2 must exist in order to register it."), name); return; } /* make sure they're in it */ if (!(cu = chanuser_find(c, si->su))) { command_fail(si, fault_noprivs, _("You must be in \2%s\2 in order to register it."), name); return; } /* make sure they're opped (or protected/owner on unreal/inspircd) */ if (!((CSTATUS_OP | CSTATUS_PROTECT | CSTATUS_OWNER) & cu->modes)) { command_fail(si, fault_noprivs, _("You must be a channel operator in \2%s\2 in order to register it."), name); return; } if (metadata_find(si->smu, "private:restrict:setter")) { command_fail(si, fault_noprivs, _("You have been restricted from registering channels by network staff.")); return; } if ((unsigned int)(CURRTIME - ratelimit_firsttime) > config_options.ratelimit_period) ratelimit_count = 0, ratelimit_firsttime = CURRTIME; if (ratelimit_count > config_options.ratelimit_uses && !has_priv(si, PRIV_FLOOD)) { command_fail(si, fault_toomany, _("The system is currently too busy to process your registration, please try again later.")); slog(LG_INFO, "CHANSERV:REGISTER:THROTTLED: \2%s\2 by \2%s\2", name, entity(si->smu)->name); return; } hdatac.si = si; hdatac.name = name; hdatac.chan = c; hdatac.approved = 0; hook_call_channel_can_register(&hdatac); if (hdatac.approved != 0) return; if (!myentity_can_register_channel(entity(si->smu))) { command_fail(si, fault_toomany, _("You have too many channels registered.")); return; } if (config_options.ratelimit_uses && config_options.ratelimit_period) ratelimit_count++; logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2", name); mc = mychan_add(name); mc->registered = CURRTIME; mc->used = CURRTIME; mc->mlock_on |= (CMODE_NOEXT | CMODE_TOPIC); if (c->limit == 0) mc->mlock_off |= CMODE_LIMIT; if (c->key == NULL) mc->mlock_off |= CMODE_KEY; mc->flags |= config_options.defcflags; chanacs_add(mc, entity(si->smu), custom_founder_check(), CURRTIME, entity(si->smu)); if (c->ts > 0) { snprintf(str, sizeof str, "%lu", (unsigned long)c->ts); metadata_add(mc, "private:channelts", str); } if (chansvs.deftemplates != NULL && *chansvs.deftemplates != '\0') metadata_add(mc, "private:templates", chansvs.deftemplates); command_success_nodata(si, _("\2%s\2 is now registered to \2%s\2."), mc->name, entity(si->smu)->name); hdata.si = si; hdata.mc = mc; hook_call_channel_register(&hdata); /* Allow the hook to override this. */ fl = chanacs_source_flags(mc, si); cu = chanuser_find(mc->chan, si->su); if (cu == NULL) ; else if (ircd->uses_owner && fl & CA_USEOWNER && fl & CA_AUTOOP && !(cu->modes & CSTATUS_OWNER)) { modestack_mode_param(si->service->nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(si->su)); cu->modes |= CSTATUS_OWNER; } else if (ircd->uses_protect && fl & CA_USEPROTECT && fl & CA_AUTOOP && !(cu->modes & CSTATUS_PROTECT)) { modestack_mode_param(si->service->nick, mc->chan, MTYPE_ADD, ircd->protect_mchar[1], CLIENT_NAME(si->su)); cu->modes |= CSTATUS_PROTECT; } }
/* SET EMAIL <new address> */ static void ns_cmd_set_email(sourceinfo_t *si, int parc, char *parv[]) { char *email = parv[0]; metadata_t *md; if (!email) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "EMAIL"); command_fail(si, fault_needmoreparams, _("Syntax: SET EMAIL <new e-mail>")); return; } if (!strcasecmp(si->smu->email, email)) { md = metadata_find(si->smu, "private:verify:emailchg:newemail"); if (md != NULL) { command_success_nodata(si, _("The email address change to \2%s\2 has been cancelled."), md->value); metadata_delete(si->smu, "private:verify:emailchg:key"); metadata_delete(si->smu, "private:verify:emailchg:newemail"); metadata_delete(si->smu, "private:verify:emailchg:timestamp"); } else command_fail(si, fault_nochange, _("The email address for account \2%s\2 is already set to \2%s\2."), entity(si->smu)->name, si->smu->email); return; } if (!validemail(email)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid email address."), email); return; } if (!email_within_limits(email)) { command_fail(si, fault_toomany, _("\2%s\2 has too many accounts registered."), email); return; } if (me.auth == AUTH_EMAIL) { unsigned long key = makekey(); metadata_add(si->smu, "private:verify:emailchg:key", number_to_string(key)); metadata_add(si->smu, "private:verify:emailchg:newemail", email); metadata_add(si->smu, "private:verify:emailchg:timestamp", number_to_string(CURRTIME)); if (!sendemail(si->su != NULL ? si->su : si->service->me, si->smu, EMAIL_SETEMAIL, email, number_to_string(key))) { command_fail(si, fault_emailfail, _("Sending email failed, sorry! Your email address is unchanged.")); metadata_delete(si->smu, "private:verify:emailchg:key"); metadata_delete(si->smu, "private:verify:emailchg:newemail"); metadata_delete(si->smu, "private:verify:emailchg:timestamp"); return; } logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2) (awaiting verification)", entity(si->smu)->name, si->smu->email, email); command_success_nodata(si, _("An email containing email changing instructions has been sent to \2%s\2."), email); command_success_nodata(si, _("Your email address will not be changed until you follow these instructions.")); return; } logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2)", entity(si->smu)->name, si->smu->email, email); myuser_set_email(si->smu, email); command_success_nodata(si, _("The email address for account \2%s\2 has been changed to \2%s\2."), entity(si->smu)->name, si->smu->email); }
/* FFLAGS <channel> <user> <flags> */ static void cs_cmd_fflags(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; const char *flagstr = parv[2]; mychan_t *mc; myentity_t *mt; unsigned int addflags, removeflags; chanacs_t *ca; hook_channel_acl_req_t req; if (parc < 3) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FFLAGS"); command_fail(si, fault_needmoreparams, _("Syntax: FFLAGS <channel> <target> <flags>")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (*flagstr == '+' || *flagstr == '-' || *flagstr == '=') { flags_make_bitmasks(flagstr, &addflags, &removeflags); if (addflags == 0 && removeflags == 0) { command_fail(si, fault_badparams, _("No valid flags given, use /%s%s HELP FLAGS for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.me->disp); return; } } else { addflags = get_template_flags(mc, flagstr); if (addflags == 0) { /* Hack -- jilles */ if (*target == '+' || *target == '-' || *target == '=') command_fail(si, fault_badparams, _("Usage: FFLAGS %s <target> <flags>"), mc->name); else command_fail(si, fault_badparams, _("Invalid template name given, use /%s%s TEMPLATE %s for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.me->disp, mc->name); return; } removeflags = ca_all & ~addflags; } if (!validhostmask(target)) { if (!(mt = myentity_find_ext(target))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), target); return; } target = mt->name; ca = chanacs_open(mc, mt, NULL, true, entity(si->smu)); /* XXX this should be more like flags.c */ if (removeflags & CA_FLAGS) removeflags |= CA_FOUNDER, addflags &= ~CA_FOUNDER; else if (addflags & CA_FOUNDER) addflags |= CA_FLAGS, removeflags &= ~CA_FLAGS; if (is_founder(mc, mt) && removeflags & CA_FOUNDER && mychan_num_founders(mc) == 1) { command_fail(si, fault_noprivs, _("You may not remove the last founder.")); return; } req.ca = ca; req.oldlevel = ca->level; if (!chanacs_modify(ca, &addflags, &removeflags, ca_all, si->smu)) { /* this shouldn't happen */ command_fail(si, fault_noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2(addflags, removeflags), mt->name, mc->name); chanacs_close(ca); return; } req.newlevel = ca->level; hook_call_channel_acl_change(&req); chanacs_close(ca); } else { if (addflags & CA_FOUNDER) { command_fail(si, fault_badparams, _("You may not set founder status on a hostmask.")); return; } ca = chanacs_open(mc, NULL, target, true, entity(si->smu)); req.ca = ca; req.oldlevel = ca->level; if (!chanacs_modify(ca, &addflags, &removeflags, ca_all, si->smu)) { /* this shouldn't happen */ command_fail(si, fault_noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2(addflags, removeflags), target, mc->name); chanacs_close(ca); return; } req.newlevel = ca->level; hook_call_channel_acl_change(&req); chanacs_close(ca); } if ((addflags | removeflags) == 0) { command_fail(si, fault_nochange, _("Channel access to \2%s\2 for \2%s\2 unchanged."), channel, target); return; } flagstr = bitmask_to_flags2(addflags, removeflags); wallops("\2%s\2 is forcing flags change \2%s\2 on \2%s\2 in \2%s\2.", get_oper_name(si), flagstr, target, mc->name); command_success_nodata(si, _("Flags \2%s\2 were set on \2%s\2 in \2%s\2."), flagstr, target, channel); logcommand(si, CMDLOG_ADMIN, "FFLAGS: \2%s\2 \2%s\2 \2%s\2", mc->name, target, flagstr); verbose(mc, _("\2%s\2 forced flags change \2%s\2 on \2%s\2"), get_source_name(si), flagstr, target); }
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); }
static void cs_cmd_set_pubacl(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET PUBACL"); return; } if (!(chanacs_source_has_flag(mc, si, CA_SET) || chanacs_source_has_flag(mc, si, CA_FOUNDER))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1]) || !strcasecmp("1", parv[1]) || !strcasecmp("TRUE", parv[1])) { if (MC_PUBACL & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel: \2%s\2"), "PUBACL", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PUBACL:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the PUBACL flag."), get_source_name(si)); mc->flags |= MC_PUBACL; command_success_nodata(si, _("The \2%s\2 flag has been set for channel: \2%s\2"), "PUBACL", mc->name); notify_channel_set_change(si, si->smu, mc, "PUBACL", "ON"); return; } else if (!strcasecmp("OFF", parv[1]) || !strcasecmp("0", parv[1]) || !strcasecmp("FALSE", parv[1])) { if (!(MC_PUBACL & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel: \2%s\2"), "PUBACL", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PUBACL:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the PUBACL flag."), get_source_name(si)); mc->flags &= ~MC_PUBACL; command_success_nodata(si, _("The \2%s\2 flag has been removed for channel: \2%s\2"), "PUBACL", mc->name); notify_channel_set_change(si, si->smu, mc, "PUBACL", "OFF"); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "PUBACL"); return; } }
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *name = parv[0]; char *newpass = NULL; char *key; metadata_t *md; enum specialoperation op = op_none; bool ismarked = false; char cmdtext[NICKLEN + 20]; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!strcasecmp(parv[1], "FORCE")) op = op_force; else if (!strcasecmp(parv[1], "CLEAR")) op = op_clear; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS"); command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]")); return; } } if (!(mu = myuser_find_by_nick(name))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name); return; } if (is_soper(mu) && !has_priv(si, PRIV_ADMIN)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (is SOPER)", name); command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to send the password."), name, PRIV_ADMIN); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if ((md = metadata_find(mu, "private:mark:setter"))) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked by %s."), entity(mu)->name, md->value); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { metadata_delete(mu, "private:setpass:key"); metadata_delete(mu, "private:sendpass:sender"); metadata_delete(mu, "private:sendpass:timestamp"); logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name); } else command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name); return; } if (MOWGLI_LIST_LENGTH(&mu->logins) > 0) { command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_success_nodata(si, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } /* alternative, safer method? */ if (command_find(si->service->commands, "SETPASS")) { if (metadata_find(mu, "private:setpass:key")) { command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name); command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name); return; } key = random_string(12); if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); } } else command_fail(si, fault_emailfail, _("Email send failed.")); free(key); return; } /* this is not without controversy... :) */ if (mu->flags & MU_CRYPTPASS) { command_success_nodata(si, _("The password for the account \2%s\2 is encrypted; a new password will be assigned and sent."), name); newpass = random_string(12); set_password(mu, newpass); } if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, (newpass == NULL) ? mu->pass : newpass)) { logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name); command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); } metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); } else command_fail(si, fault_emailfail, _("Email send failed.")); if (newpass != NULL) free(newpass); return; }
static void cs_cmd_topic(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *topic = parv[1]; mychan_t *mc; channel_t *c; const char *topicsetter; time_t prevtopicts; if (!chan || !topic) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "TOPIC"); command_fail(si, fault_needmoreparams, _("Syntax: TOPIC <#channel> <topic>")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } c = channel_find(chan); if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_TOPIC)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!validtopic(topic)) { command_fail(si, fault_badparams, _("The new topic is invalid or too long.")); return; } if (si->su != NULL) topicsetter = si->su->nick; else if (si->smu != NULL) topicsetter = entity(si->smu)->name; else topicsetter = "unknown"; prevtopicts = c->topicts; handle_topic(c, topicsetter, CURRTIME, topic); topic_sts(c, si->service->me, topicsetter, CURRTIME, prevtopicts, topic); logcommand(si, CMDLOG_DO, "TOPIC: \2%s\2", mc->name); if (si->su == NULL || !chanuser_find(c, si->su)) command_success_nodata(si, _("Topic set to \2%s\2 on \2%s\2."), topic, chan); }
static void cs_cmd_topicswap(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *topic = parv[1]; mychan_t *mc; channel_t *c; const char *topicsetter; time_t prevtopicts; char topicbuf[BUFSIZE]; char commbuf[BUFSIZE]; char *pos = NULL; char *search = NULL; char *replace = NULL; size_t search_size = 0; size_t replace_size = 0; size_t copylen = 0; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "TOPICSWAP"); command_fail(si, fault_needmoreparams, _("Syntax: TOPICSWAP <#channel> <search>:[<replace>]")); return; } mowgli_strlcpy(commbuf, parv[1], BUFSIZE); search = commbuf; pos = strrchr(commbuf, ':'); if (!pos || pos == commbuf) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "TOPICSWAP"); command_fail(si, fault_badparams, _("Syntax: TOPICSWAP <#channel> <search>:[<replace>]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } c = channel_find(chan); if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_TOPIC)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } if (!c->topic) topicbuf[0] = '\0'; else mowgli_strlcpy(topicbuf, c->topic, BUFSIZE); *pos = '\0'; replace = pos + 1; search_size = strlen(search); replace_size = strlen(replace); pos = strstr(topicbuf, search); if (!pos) { command_fail(si, fault_badparams, _("Channel \2%s\2 does not have \2%s\2 in its topic."), chan, search); return; } copylen = strlen(pos + search_size) + 1; if (pos - topicbuf + replace_size + copylen > BUFSIZE) goto invalid_error; memmove(pos + search_size + (replace_size - search_size), pos + search_size, copylen); memcpy(pos, replace, replace_size); if (!validtopic(topicbuf)) { invalid_error: command_fail(si, fault_badparams, _("The new topic is invalid or too long.")); return; } if (si->su != NULL) topicsetter = si->su->nick; else if (si->smu != NULL) topicsetter = entity(si->smu)->name; else topicsetter = "unknown"; prevtopicts = c->topicts; handle_topic(c, topicsetter, CURRTIME, topicbuf); topic_sts(c, si->service->me, topicsetter, CURRTIME, prevtopicts, topicbuf); logcommand(si, CMDLOG_DO, "TOPICSWAP: \2%s\2", mc->name); if (si->su == NULL || !chanuser_find(c, si->su)) command_success_nodata(si, _("Topic set to \2%s\2 on \2%s\2."), c->topic, chan); }
static void ns_cmd_group(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn; hook_user_req_t hdata; hook_user_register_check_t hdata_reg; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "GROUP"); return; } if (nicksvs.no_nick_ownership) { command_fail(si, fault_noprivs, _("Nickname ownership is disabled.")); return; } if (MOWGLI_LIST_LENGTH(&si->smu->nicks) >= nicksvs.maxnicks && !has_priv(si, PRIV_REG_NOLIMIT)) { command_fail(si, fault_noprivs, _("You have too many nicks registered already.")); return; } mn = mynick_find(si->su->nick); if (mn != NULL) { if (mn->owner == si->smu) command_fail(si, fault_nochange, _("Nick \2%s\2 is already registered to your account."), mn->nick); else command_fail(si, fault_alreadyexists, _("Nick \2%s\2 is already registered to \2%s\2."), mn->nick, entity(mn->owner)->name); return; } if (IsDigit(si->su->nick[0])) { command_fail(si, fault_badparams, _("For security reasons, you can't register your UID.")); return; } if (metadata_find(si->smu, "private:restrict:setter")) { command_fail(si, fault_noprivs, _("You have been restricted from grouping nicks by network staff.")); return; } hdata_reg.si = si; hdata_reg.account = si->su->nick; hdata_reg.email = si->smu->email; hdata_reg.approved = 0; hook_call_nick_can_register(&hdata_reg); if (hdata_reg.approved != 0) return; logcommand(si, CMDLOG_REGISTER, "GROUP: \2%s\2 to \2%s\2", si->su->nick, entity(si->smu)->name); mn = mynick_add(si->smu, si->su->nick); mn->registered = CURRTIME; mn->lastseen = CURRTIME; command_success_nodata(si, _("Nick \2%s\2 is now registered to your account."), mn->nick); hdata.si = si; hdata.mu = si->smu; hdata.mn = mn; hook_call_nick_group(&hdata); }
static void cs_cmd_set_limitflags(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET LIMITFLAGS"); return; } if ((chanacs_source_flags(mc, si) & CA_HIGHPRIVS) != CA_HIGHPRIVS) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { if (MC_LIMITFLAGS & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for \2%s\2."), "LIMITFLAGS", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:LIMITFLAGS:ON: \2%s\2", mc->name); mc->flags |= MC_LIMITFLAGS; command_success_nodata(si, _("The \2%s\2 flag has been set for \2%s\2."), "LIMITFLAGS", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_LIMITFLAGS & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for \2%s\2."), "LIMITFLAGS", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:LIMITFLAGS:OFF: \2%s\2", mc->name); mc->flags &= ~MC_LIMITFLAGS; command_success_nodata(si, _("The \2%s\2 flag has been removed for \2%s\2."), "LIMITFLAGS", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "LIMITFLAGS"); return; } }
static void cs_cmd_set_mlock(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char modebuf[32], *end, c; int dir = MTYPE_NUL; int newlock_on = 0, newlock_off = 0, newlock_limit = 0, flag = 0; unsigned int mask, changed; bool mask_ext; char newlock_key[KEYLEN]; char newlock_ext[ignore_mode_list_size][512]; bool newlock_ext_off[ignore_mode_list_size]; char newext[512]; char ext_plus[ignore_mode_list_size + 1]; char ext_minus[ignore_mode_list_size + 1]; size_t i; char *letters = strtok(parv[1], " "); char *arg; metadata_t *md; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { if (ircd->oper_only_modes == 0 || !has_priv(si, PRIV_CHAN_CMODES) || !has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } mask = ~ircd->oper_only_modes; mask_ext = true; } else { mask = has_priv(si, PRIV_CHAN_CMODES) ? 0 : ircd->oper_only_modes; mask_ext = false; } for (i = 0; i < ignore_mode_list_size; i++) { newlock_ext[i][0] = '\0'; newlock_ext_off[i] = false; } newlock_key[0] = '\0'; while (letters && *letters) { if (*letters != '+' && *letters != '-' && dir == MTYPE_NUL) { letters++; continue; } switch ((c = *letters++)) { case '+': dir = MTYPE_ADD; break; case '-': dir = MTYPE_DEL; break; case 'k': if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if (!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), 'k'); return; } else if (strlen(arg) >= KEYLEN) { command_fail(si, fault_badparams, _("MLOCK key is too long (%d > %d)."), (int)strlen(arg), KEYLEN - 1); return; } else if (strchr(arg, ',') || arg[0] == ':') { command_fail(si, fault_badparams, _("MLOCK key contains invalid characters.")); return; } strlcpy(newlock_key, arg, sizeof newlock_key); newlock_off &= ~CMODE_KEY; } else { newlock_key[0] = '\0'; newlock_off |= CMODE_KEY; } break; case 'l': if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if(!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), 'l'); return; } if (atol(arg) <= 0) { command_fail(si, fault_badparams, _("You must specify a positive integer for limit.")); return; } newlock_limit = atol(arg); newlock_off &= ~CMODE_LIMIT; } else { newlock_limit = 0; newlock_off |= CMODE_LIMIT; } break; default: flag = mode_to_flag(c); if (flag) { if (dir == MTYPE_ADD) newlock_on |= flag, newlock_off &= ~flag; else newlock_off |= flag, newlock_on &= ~flag; break; } for (i = 0; ignore_mode_list[i].mode != '\0'; i++) { if (c == ignore_mode_list[i].mode) { if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if(!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), c); return; } if (strlen(arg) > 350) { command_fail(si, fault_badparams, _("Invalid value \2%s\2 for mode +%c."), arg, c); return; } if ((mc->chan == NULL || mc->chan->extmodes[i] == NULL || strcmp(mc->chan->extmodes[i], arg)) && !ignore_mode_list[i].check(arg, mc->chan, mc, si->su, si->smu)) { command_fail(si, fault_badparams, _("Invalid value \2%s\2 for mode +%c."), arg, c); return; } strlcpy(newlock_ext[i], arg, sizeof newlock_ext[i]); newlock_ext_off[i] = false; } else { newlock_ext[i][0] = '\0'; newlock_ext_off[i] = true; } } } } } /* note: the following does not treat +lk and extmodes correctly */ changed = ((newlock_on ^ mc->mlock_on) | (newlock_off ^ mc->mlock_off)); changed &= ~mask; /* if they're only allowed to alter oper only modes, require * them to actually change such modes -- jilles */ if (!changed && mask_ext) { command_fail(si, fault_noprivs, _("You may only alter \2+%s\2 modes."), flags_to_string(~mask)); return; } /* save it to mychan */ /* leave the modes in mask unchanged -- jilles */ mc->mlock_on = (newlock_on & ~mask) | (mc->mlock_on & mask); mc->mlock_off = (newlock_off & ~mask) | (mc->mlock_off & mask); if (!(mask & CMODE_LIMIT)) mc->mlock_limit = newlock_limit; if (!(mask & CMODE_KEY)) { free(mc->mlock_key); mc->mlock_key = *newlock_key != '\0' ? sstrdup(newlock_key) : NULL; } ext_plus[0] = '\0'; ext_minus[0] = '\0'; if (mask_ext) { md = metadata_find(mc, "private:mlockext"); if (md != NULL) { arg = md->value; while (*arg != '\0') { modebuf[0] = *arg; modebuf[1] = '\0'; strlcat(arg[1] == ' ' || arg[1] == '\0' ? ext_minus : ext_plus, modebuf, ignore_mode_list_size + 1); arg++; while (*arg != ' ' && *arg != '\0') arg++; while (*arg == ' ') arg++; } } } else { newext[0] = '\0'; for (i = 0; i < ignore_mode_list_size; i++) { if (newlock_ext[i][0] != '\0' || newlock_ext_off[i]) { if (*newext != '\0') { modebuf[0] = ' '; modebuf[1] = '\0'; strlcat(newext, modebuf, sizeof newext); } modebuf[0] = ignore_mode_list[i].mode; modebuf[1] = '\0'; strlcat(newext, modebuf, sizeof newext); strlcat(newlock_ext_off[i] ? ext_minus : ext_plus, modebuf, ignore_mode_list_size + 1); if (!newlock_ext_off[i]) strlcat(newext, newlock_ext[i], sizeof newext); } } if (newext[0] != '\0') metadata_add(mc, "private:mlockext", newext); else metadata_delete(mc, "private:mlockext"); } end = modebuf; *end = 0; if (mc->mlock_on || mc->mlock_key || mc->mlock_limit || *ext_plus) end += snprintf(end, sizeof(modebuf) - (end - modebuf), "+%s%s%s%s", flags_to_string(mc->mlock_on), mc->mlock_key ? "k" : "", mc->mlock_limit ? "l" : "", ext_plus); if (mc->mlock_off || *ext_minus) end += snprintf(end, sizeof(modebuf) - (end - modebuf), "-%s%s%s%s", flags_to_string(mc->mlock_off), mc->mlock_off & CMODE_KEY ? "k" : "", mc->mlock_off & CMODE_LIMIT ? "l" : "", ext_minus); if (*modebuf) { command_success_nodata(si, _("The MLOCK for \2%s\2 has been set to \2%s\2."), mc->name, modebuf); logcommand(si, CMDLOG_SET, "SET:MLOCK: \2%s\2 to \2%s\2", mc->name, modebuf); } else { command_success_nodata(si, _("The MLOCK for \2%s\2 has been removed."), mc->name); logcommand(si, CMDLOG_SET, "SET:MLOCK:NONE: \2%s\2", mc->name); } if (changed & ircd->oper_only_modes) logcommand(si, CMDLOG_SET, _("SET:MLOCK: \2%s\2 to \2%s\2 by \2%s\2"), mc->name, *modebuf != '\0' ? modebuf : "+", get_oper_name(si)); check_modes(mc, true); if (mc->chan != NULL) mlock_sts(mc->chan); return; }
static void cs_cmd_set_secure(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET SECURE"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (chanacs_source_has_flag(mc, si, CA_SUSPENDED)) { command_fail(si, fault_noprivs, _("Your access in %s is \2suspended\2."), parv[0]); return; } if (!strcasecmp("ON", parv[1])) { if (MC_SECURE & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "SECURE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:SECURE:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the SECURE flag"), get_source_name(si)); mc->flags |= MC_SECURE; command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "SECURE", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_SECURE & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "SECURE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:SECURE:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the SECURE flag"), get_source_name(si)); mc->flags &= ~MC_SECURE; command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "SECURE", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SECURE"); return; } }
static void cs_cmd_set_guard(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET GUARD"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { if (MC_GUARD & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "GUARD", mc->name); return; } if (metadata_find(mc, "private:botserv:bot-assigned") && module_find_published("botserv/main")) { command_fail(si, fault_noprivs, _("Channel \2%s\2 already has a BotServ bot assigned to it. You need to unassign it first."), mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GUARD:ON: \2%s\2", mc->name); mc->flags |= MC_GUARD; if (!(mc->flags & MC_INHABIT)) join(mc->name, chansvs.nick); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "GUARD", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_GUARD & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "GUARD", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GUARD:OFF: \2%s\2", mc->name); mc->flags &= ~MC_GUARD; if (mc->chan != NULL && !(mc->flags & MC_INHABIT) && !(mc->chan->flags & CHAN_LOG)) part(mc->name, chansvs.nick); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "GUARD", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "GUARD"); return; } }
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 (!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 gs_cmd_drop(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; char *name = parv[0]; char *key = parv[1]; char fullcmd[512]; char key0[80], key1[80]; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DROP"); command_fail(si, fault_needmoreparams, _("Syntax: DROP <!group>")); return; } if (*name != '!') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "DROP"); command_fail(si, fault_badparams, _("Syntax: DROP <!group>")); return; } if (!(mg = mygroup_find(name))) { command_fail(si, fault_nosuch_target, _("Group \2%s\2 does not exist."), name); return; } if (!groupacs_sourceinfo_has_flag(mg, si, GA_FOUNDER)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (si->su != NULL) { if (!key) { create_challenge(si, entity(mg)->name, 0, key0); snprintf(fullcmd, sizeof fullcmd, "/%s%s DROP %s %s", (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp, entity(mg)->name, key0); command_success_nodata(si, _("To avoid accidental use of this command, this operation has to be confirmed. Please confirm by replying with \2%s\2"), fullcmd); return; } /* accept current and previous key */ create_challenge(si, entity(mg)->name, 0, key0); create_challenge(si, entity(mg)->name, 1, key1); if (strcmp(key, key0) && strcmp(key, key1)) { command_fail(si, fault_badparams, _("Invalid key for %s."), "DROP"); return; } } logcommand(si, CMDLOG_REGISTER, "DROP: \2%s\2", entity(mg)->name); remove_group_chanacs(mg); object_unref(mg); command_success_nodata(si, _("The group \2%s\2 has been dropped."), name); return; }
static void cs_cmd_set_private(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET PRIVATE"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!strcasecmp("ON", parv[1])) { if (MC_PRIVATE & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for \2%s\2."), "PRIVATE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PRIVATE:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the PRIVATE flag"), get_source_name(si)); mc->flags |= MC_PRIVATE; command_success_nodata(si, _("The \2%s\2 flag has been set for \2%s\2."), "PRIVATE", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_PRIVATE & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for \2%s\2."), "PRIVATE", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PRIVATE:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the PRIVATE flag"), get_source_name(si)); mc->flags &= ~MC_PRIVATE; command_success_nodata(si, _("The \2%s\2 flag has been removed for \2%s\2."), "PRIVATE", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "PRIVATE"); return; } }
static void cs_cmd_invite(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; mychan_t *mc; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "INVITE"); return; } /* This command is not useful if the user is already in the channel, * ignore it if it is a fantasy command so users can program bots to * react on it without interference from ChanServ. */ if (si->c != NULL) return; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INVITE"); command_fail(si, fault_needmoreparams, _("Syntax: INVITE <#channel>")); 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:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_INVITE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), mc->name); return; } if (chanuser_find(mc->chan, si->su)) { command_fail(si, fault_noprivs, _("You're already on \2%s\2."), mc->name); return; } invite_sts(si->service->me, si->su, mc->chan); logcommand(si, CMDLOG_DO, "INVITE: \2%s\2", mc->name); command_success_nodata(si, _("You have been invited to \2%s\2."), mc->name); }
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; char *nicklist; char *strtokctx; 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; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '+', &cs_cmd_voice)) continue; /* figure out who we're going to devoice */ 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; 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_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 (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been devoiced on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }
static void ns_cmd_register(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mynick_t *mn = NULL; mowgli_node_t *n; char *account; char *pass; char *email; char lau[BUFSIZE], lao[BUFSIZE]; hook_user_register_check_t hdata; hook_user_req_t req; if (si->smu) { command_fail(si, fault_already_authed, _("You are already logged in as \2%s\2."), entity(si->smu)->name); if (si->su != NULL && !mynick_find(si->su->nick) && command_find(si->service->commands, "GROUP")) command_fail(si, fault_already_authed, _("Use %s to register %s to your account."), "GROUP", si->su->nick); return; } if (nicksvs.no_nick_ownership || si->su == NULL) account = parv[0], pass = parv[1], email = parv[2]; else account = si->su->nick, pass = parv[0], email = parv[1]; if (!account || !pass || !email) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGISTER"); if (nicksvs.no_nick_ownership || si->su == NULL) command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>")); else command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>")); return; } if (!crypto_module_loaded && strlen(pass) > PASSLEN) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER"); command_fail(si, fault_badparams, _("Registration passwords may not be longer than \2%d\2 characters."), PASSLEN); return; } if (!nicksvs.no_nick_ownership && si->su == NULL && user_find_named(account)) { command_fail(si, fault_noprivs, _("A user matching this account is already on IRC.")); return; } if (!nicksvs.no_nick_ownership && IsDigit(*account)) { command_fail(si, fault_badparams, _("For security reasons, you can't register your UID.")); command_fail(si, fault_badparams, _("Please change to a real nickname, and try again.")); return; } if (nicksvs.no_nick_ownership || si->su == NULL) { if (strchr(account, ' ') || strchr(account, '\n') || strchr(account, '\r') || account[0] == '=' || account[0] == '#' || account[0] == '@' || account[0] == '+' || account[0] == '%' || account[0] == '!' || strchr(account, ',')) { command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account); return; } } if ((si->su != NULL && !strcasecmp(pass, si->su->nick)) || !strcasecmp(pass, account)) { command_fail(si, fault_badparams, _("You cannot use your nickname as a password.")); if (nicksvs.no_nick_ownership || si->su == NULL) command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <account> <password> <email>")); else command_fail(si, fault_needmoreparams, _("Syntax: REGISTER <password> <email>")); return; } /* make sure it isn't registered already */ if (nicksvs.no_nick_ownership ? myuser_find(account) != NULL : mynick_find(account) != NULL) { command_fail(si, fault_alreadyexists, _("\2%s\2 is already registered."), account); return; } if ((unsigned int)(CURRTIME - ratelimit_firsttime) > config_options.ratelimit_period) ratelimit_count = 0, ratelimit_firsttime = CURRTIME; /* Still do flood priv checking because the user may be in the ircop operclass */ if (ratelimit_count > config_options.ratelimit_uses && !has_priv(si, PRIV_FLOOD)) { command_fail(si, fault_toomany, _("The system is currently too busy to process your registration, please try again later.")); slog(LG_INFO, "NICKSERV:REGISTER:THROTTLED: \2%s\2 by \2%s\2", account, si->su->nick); return; } hdata.si = si; hdata.account = account; hdata.email = email; hdata.password = pass; hdata.approved = 0; hook_call_user_can_register(&hdata); if (hdata.approved != 0) return; if (!nicksvs.no_nick_ownership) { hook_call_nick_can_register(&hdata); if (hdata.approved != 0) return; } if (!validemail(email)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid email address."), email); return; } /* make sure they're within limits */ if (me.maxusers > 0) { tcnt = 0; myentity_foreach_t(ENT_USER, register_foreach_cb, email); if (tcnt >= me.maxusers) { command_fail(si, fault_toomany, _("\2%s\2 has too many accounts registered."), email); return; } } mu = myuser_add(account, auth_module_loaded ? "*" : pass, email, config_options.defuflags | MU_NOBURSTLOGIN | (auth_module_loaded ? MU_CRYPTPASS : 0)); mu->registered = CURRTIME; mu->lastlogin = CURRTIME; if (!nicksvs.no_nick_ownership) { mn = mynick_add(mu, entity(mu)->name); mn->registered = CURRTIME; mn->lastseen = CURRTIME; } if (config_options.ratelimit_uses && config_options.ratelimit_period) ratelimit_count++; if (auth_module_loaded) { if (!verify_password(mu, pass)) { command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), entity(mu)->name); bad_password(si, mu); object_unref(mu); return; } } if (me.auth == AUTH_EMAIL) { char *key = gen_pw(12); mu->flags |= MU_WAITAUTH; metadata_add(mu, "private:verify:register:key", key); metadata_add(mu, "private:verify:register:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, EMAIL_REGISTER, mu, key)) { command_fail(si, fault_emailfail, _("Sending email failed, sorry! Registration aborted.")); object_unref(mu); free(key); return; } command_success_nodata(si, _("An email containing nickname activation instructions has been sent to \2%s\2."), mu->email); command_success_nodata(si, _("If you do not complete registration within one day, your nickname will expire.")); free(key); } if (si->su != NULL) { si->su->myuser = mu; n = mowgli_node_create(); mowgli_node_add(si->su, n, &mu->logins); if (!(mu->flags & MU_WAITAUTH)) /* only grant ircd registered status if it's verified */ ircd_on_login(si->su, mu, NULL); } command_add_flood(si, FLOOD_MODERATE); if (!nicksvs.no_nick_ownership && si->su != NULL) logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2", account, email); else logcommand(si, CMDLOG_REGISTER, "REGISTER: \2%s\2 to \2%s\2 by \2%s\2", account, email, si->su != NULL ? si->su->nick : get_source_name(si)); if (is_soper(mu)) { wallops("%s registered the nick \2%s\2 and gained services operator privileges.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "SOPER: \2%s\2 as \2%s\2", get_oper_name(si), entity(mu)->name); } command_success_nodata(si, _("\2%s\2 is now registered to \2%s\2, with the password \2%s\2."), entity(mu)->name, mu->email, pass); hook_call_user_register(mu); if (si->su != NULL) { snprintf(lau, BUFSIZE, "%s@%s", si->su->user, si->su->vhost); metadata_add(mu, "private:host:vhost", lau); snprintf(lao, BUFSIZE, "%s@%s", si->su->user, si->su->host); metadata_add(mu, "private:host:actual", lao); } if (!(mu->flags & MU_WAITAUTH)) { req.si = si; req.mu = mu; req.mn = mn; hook_call_user_verify_register(&req); } }
static void gs_cmd_set_open(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; if (!parv[0] || !parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "OPEN"); command_fail(si, fault_needmoreparams, _("Syntax: OPEN <!group> <ON|OFF>")); return; } if ((mg = mygroup_find(parv[0])) == NULL) { command_fail(si, fault_nosuch_target, _("The group \2%s\2 does not exist."), parv[0]); return; } if (si->smu == NULL) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!groupacs_sourceinfo_has_flag(mg, si, GA_FOUNDER)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!strcasecmp(parv[1], "ON")) { if (!enable_open_groups) { command_fail(si, fault_nochange, _("Setting groups as open has been administratively disabled.")); return; } if (mg->flags & MG_OPEN) { command_fail(si, fault_nochange, _("\2%s\2 is already open to anyone joining."), entity(mg)->name); return; } mg->flags |= MG_OPEN; logcommand(si, CMDLOG_SET, "OPEN:ON: \2%s\2", entity(mg)->name); command_success_nodata(si, _("\2%s\2 is now open to anyone joining."), entity(mg)->name); } else if (!strcasecmp(parv[1], "OFF")) { if (!(mg->flags & MG_OPEN)) { command_fail(si, fault_nochange, _("\2%s\2 is already not open to anyone joining."), entity(mg)->name); return; } mg->flags &= ~MG_OPEN; logcommand(si, CMDLOG_SET, "OPEN:OFF: \2%s\2", entity(mg)->name); command_success_nodata(si, _("\2%s\2 is no longer open to anyone joining."), entity(mg)->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "OPEN"); command_fail(si, fault_badparams, _("Syntax: OPEN <!group> <ON|OFF>")); } }