static void ns_cmd_staff(sourceinfo_t *si, int parc, char *parv[]) { char *target = parv[0]; char *action = parv[1]; myuser_t *mu; if (!target || !action) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "STAFF"); command_fail(si, fault_needmoreparams, _("Usage: STAFF <account> <ON|OFF>")); return; } if (!(mu = myuser_find_ext(target))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), target); return; } if (!strcasecmp(action, "ON")) { if (metadata_find(mu, "private:staff:setter")) { command_fail(si, fault_badparams, _("\2%s\2 is already a member of staff."), entity(mu)->name); return; } metadata_add(mu, "private:staff:setter", get_oper_name(si)); metadata_add(mu, "private:staff:timestamp", number_to_string(CURRTIME)); wallops("%s set the STAFF option for the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "STAFF:ON: \2%s\2", entity(mu)->name); command_success_nodata(si, _("\2%s\2 is now a member of staff."), entity(mu)->name); } else if (!strcasecmp(action, "OFF")) { if (!metadata_find(mu, "private:staff:setter")) { command_fail(si, fault_badparams, _("\2%s\2 is not a member of staff."), entity(mu)->name); return; } metadata_delete(mu, "private:staff:setter"); metadata_delete(mu, "private:staff:timestamp"); wallops("%s removed the STAFF option on the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "STAFF:OFF: \2%s\2", entity(mu)->name); command_success_nodata(si, _("\2%s\2 is no longer a member of staff."), entity(mu)->name); } else { command_fail(si, fault_needmoreparams, STR_INVALID_PARAMS, "STAFF"); command_fail(si, fault_needmoreparams, _("Usage: STAFF <account> <ON|OFF>")); } }
static void bs_cmd_set_nobot(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET NOBOT"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { metadata_add(mc, "private:botserv:no-bot", "ON"); if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) { if (mc->flags & MC_GUARD && (!config_options.leave_chans || (mc->chan != NULL && LIST_LENGTH(&mc->chan->members) > 1))) join(mc->name, chansvs.nick); part(mc->name, md->value); metadata_delete(mc, "private:botserv:bot-assigned"); metadata_delete(mc, "private:botserv:bot-handle-fantasy"); } command_success_nodata(si, _("No Bot mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:no-bot"); command_success_nodata(si, _("No Bot mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET NOBOT"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); } }
/* SET PUBKEY <key> */ static void ns_cmd_set_pubkey(sourceinfo_t *si, int parc, char *parv[]) { char *newkey = parv[0]; metadata_t *md; if (!newkey) { md = metadata_find(si->smu, "private:pubkey"); if (!md) { command_fail(si, fault_nosuch_target, _("Public key was not set")); return; } metadata_delete(si->smu, "private:pubkey"); logcommand(si, CMDLOG_SET, "SET:PUBKEY:REMOVE"); command_success_nodata(si, _("Public key entry has been deleted.")); return; } md = metadata_find(si->smu, "private:pubkey"); if (md != NULL && !strcmp(md->value, newkey)) { command_fail(si, fault_nochange, _("Your public key is already set to \2%s\2."), newkey); return; } metadata_add(si->smu, "private:pubkey", newkey); logcommand(si, CMDLOG_SET, "SET:PUBKEY: \2%s\2", newkey); command_success_nodata(si, _("Your public key is now set to \2%s\2."), newkey); return; }
static void ns_cmd_vacation(sourceinfo_t *si, int parc, char *parv[]) { char tsbuf[BUFSIZE]; if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (CURRTIME < (time_t)(si->smu->registered + nicksvs.expiry)) { command_fail(si, fault_noprivs, _("You must be registered for at least \2%d\2 days in order to enable VACATION mode."), (nicksvs.expiry / 3600 / 24)); return; } snprintf(tsbuf, BUFSIZE, "%lu", (unsigned long)CURRTIME); metadata_add(si->smu, "private:vacation", tsbuf); logcommand(si, CMDLOG_SET, "VACATION"); command_success_nodata(si, _("Your account is now marked as being on vacation.\n" "Please be aware that this will be automatically removed the next time you identify to \2%s\2."), nicksvs.nick); if (nicksvs.expiry > 0) command_success_nodata(si, _("Your account will automatically expire in %d days if you do not return."), (nicksvs.expiry / 3600 / 24) * 3); }
static void user_delete_info_hook(hook_user_delete_t *hdata) { if (hdata->u->myuser == NULL) return; metadata_add(hdata->u->myuser, "private:lastquit:message", hdata->comment); }
static void make_forbid(sourceinfo_t *si, const char *account, const char *reason) { myuser_t *mu; mynick_t *mn = NULL; user_t *u; if (!nicksvs.no_nick_ownership && IsDigit(*account)) { command_fail(si, fault_badparams, "For security reasons, you can't forbid a UID."); return; } 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; } /* 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; } mu = myuser_add(account, "*", FORBID_EMAIL, MU_CRYPTPASS | MU_ENFORCE | MU_HOLD | MU_NOBURSTLOGIN); mu->registered = CURRTIME; mu->lastlogin = CURRTIME; metadata_add(mu, "private:freeze:freezer", get_oper_name(si)); metadata_add(mu, "private:freeze:reason", reason); metadata_add(mu, "private:freeze:timestamp", number_to_string(CURRTIME)); if (!nicksvs.no_nick_ownership) { mn = mynick_add(mu, entity(mu)->name); mn->registered = CURRTIME; mn->lastseen = CURRTIME; u = user_find_named(entity(mu)->name); if (u != NULL) { notice(si->service->nick, u->nick, _("The nick \2%s\2 is now forbidden."), entity(mu)->name); hook_call_nick_enforce((&(hook_nick_enforce_t){ .u = u, .mn = mn }));
static void bs_cmd_set_saycaller(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET SAYCALLER"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), mc->name); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:saycaller", md->value); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:ON: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:saycaller"); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET SAYCALLER"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); } }
static void ns_cmd_fenforce(sourceinfo_t *si, int parc, char *parv[]) { char *setting; myuser_t *mu; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FENFORCE"); command_fail(si, fault_needmoreparams, _("Syntax: FENFORCE <account> ON|OFF")); return; } mu = myuser_find_ext(parv[0]); if (!mu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), parv[0]); return; } setting = parv[1]; if (strcasecmp(setting, "ON") == 0) { if (metadata_find(mu, "private:doenforce")) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for account \2%s\2."), "ENFORCE", entity(mu)->name); } else { wallops("%s enabled ENFORCE on the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "FENFORCE:ON: \2%s\2", entity(mu)->name); metadata_add(mu, "private:doenforce", "1"); command_success_nodata(si, _("The \2%s\2 flag has been set for account \2%s\2."), "ENFORCE", entity(mu)->name); } } else if (strcasecmp(setting, "OFF") == 0) { if (metadata_find(mu, "private:doenforce")) { wallops("%s disabled ENFORCE on the account \2%s\2.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "FENFORCE:OFF: \2%s\2", entity(mu)->name); metadata_delete(mu, "private:doenforce"); command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "ENFORCE", entity(mu)->name); } else { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for account \2%s\2."), "ENFORCE", entity(mu)->name); } } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "FENFORCE"); } }
static void bs_cmd_set_fantasy(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static void bs_cmd_set_fantasy(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); logcommand(si, CMDLOG_SET, "SET:FANTASY:ON: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); logcommand(si, CMDLOG_SET, "SET:FANTASY:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static void gs_cmd_set_joinflags(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; char *joinflags = parv[1]; unsigned int flags = 0; if (!(mg = mygroup_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Group \2%s\2 does not exist."), parv[0]); return; } if (!groupacs_sourceinfo_has_flag(mg, si, GA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!joinflags || !strcasecmp("OFF", joinflags) || !strcasecmp("NONE", joinflags)) { /* not in a namespace to allow more natural use of SET PROPERTY. * they may be able to introduce spaces, though. c'est la vie. */ if (metadata_find(mg, "joinflags")) { metadata_delete(mg, "joinflags"); logcommand(si, CMDLOG_SET, "SET:JOINFLAGS:NONE: \2%s\2", entity(mg)->name); command_success_nodata(si, _("The group-specific join flags for \2%s\2 have been cleared."), parv[0]); return; } command_fail(si, fault_nochange, _("Join flags for \2%s\2 were not set."), parv[0]); return; } if (!strncasecmp(joinflags, "-", 1)) { command_fail(si, fault_badparams, _("You can't set join flags to be removed.")); return; } flags = gs_flags_parser(joinflags, 0, flags); /* we'll overwrite any existing metadata */ metadata_add(mg, "joinflags", number_to_string(flags)); logcommand(si, CMDLOG_SET, "SET:JOINFLAGS: \2%s\2 \2%s\2", entity(mg)->name, joinflags); command_success_nodata(si, _("The join flags of \2%s\2 have been set to \2%s\2."), parv[0], joinflags); }
/* SET HIDELASTLOGIN [ON|OFF] */ static void ns_cmd_set_hidelastlogin(sourceinfo_t *si, int parc, char *parv[]) { char *params = parv[0]; if (!params) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "HIDELASTLOGIN"); return; } if (!strcasecmp("ON", params)) { if (metadata_find(si->smu, "private:showlast:optout")) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for account \2%s\2."), "HIDELASTLOGIN", entity(si->smu)->name); return; } logcommand(si, CMDLOG_SET, "SET:HIDELASTLOGIN:ON"); metadata_add(si->smu, "private:showlast:optout", "ON"); command_success_nodata(si, _("The \2%s\2 flag has been set for account \2%s\2."), "HIDELASTLOGIN", entity(si->smu)->name); return; } else if (!strcasecmp("OFF", params)) { if (!metadata_find(si->smu, "private:showlast:optout")) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for account \2%s\2."), "HIDELASTLOGIN", entity(si->smu)->name); return; } logcommand(si, CMDLOG_SET, "SET:HIDELASTLOGIN:OFF"); metadata_delete(si->smu, "private:showlast:optout"); command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "HIDELASTLOGIN", entity(si->smu)->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "HIDELASTLOGIN"); return; } }
static void gs_cmd_set_email(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; char *mail = parv[1]; if (!(mg = mygroup_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("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_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!mail || !strcasecmp(mail, "NONE") || !strcasecmp(mail, "OFF")) { if (metadata_find(mg, "email")) { metadata_delete(mg, "email"); command_success_nodata(si, _("The e-mail address for group \2%s\2 was deleted."), entity(mg)->name); logcommand(si, CMDLOG_SET, "SET:EMAIL:NONE: \2%s\2", entity(mg)->name); return; } command_fail(si, fault_nochange, _("The e-mail address for group \2%s\2 was not set."), entity(mg)->name); return; } if (!validemail(mail)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid e-mail address."), mail); return; } /* we'll overwrite any existing metadata */ metadata_add(mg, "email", mail); logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 \2%s\2", entity(mg)->name, mail); command_success_nodata(si, _("The e-mail address for group \2%s\2 has been set to \2%s\2."), parv[0], mail); }
static void cs_cmd_set_url(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char *url = parv[1]; 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) || chanacs_source_has_flag(mc, si, CA_FOUNDER))) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!url || !strcasecmp("OFF", url) || !strcasecmp("NONE", url)) { /* not in a namespace to allow more natural use of SET PROPERTY. * they may be able to introduce spaces, though. c'est la vie. */ if (metadata_find(mc, "url")) { metadata_delete(mc, "url"); logcommand(si, CMDLOG_SET, "SET:URL:NONE: \2%s\2", mc->name); verbose(mc, _("\2%s\2 cleared the channel URL."), get_source_name(si)); command_success_nodata(si, _("The URL for \2%s\2 has been cleared."), mc->name); notify_channel_set_change(si, si->smu, mc, "URL", "Cleared"); return; } command_fail(si, fault_nochange, _("The URL for \2%s\2 was not set."), mc->name); return; } /* we'll overwrite any existing metadata */ metadata_add(mc, "url", url); logcommand(si, CMDLOG_SET, "SET:URL: \2%s\2 \2%s\2", mc->name, url); verbose(mc, _("\2%s\2 set the channel URL to \2%s\2"), get_source_name(si), url); command_success_nodata(si, _("The URL of \2%s\2 has been set to: \2%s\2"), mc->name, url); notify_channel_set_change(si, si->smu, mc, "URL", url); }
static void gs_cmd_set_channel(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; char *chan = parv[1]; if (!(mg = mygroup_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("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_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!chan || !strcasecmp("OFF", chan) || !strcasecmp("NONE", chan)) { /* not in a namespace to allow more natural use of SET PROPERTY. * they may be able to introduce spaces, though. c'est la vie. */ if (metadata_find(mg, "channel")) { metadata_delete(mg, "channel"); logcommand(si, CMDLOG_SET, "SET:CHANNEL:NONE: \2%s\2", entity(mg)->name); command_success_nodata(si, _("The official channel for \2%s\2 has been cleared."), parv[0]); return; } command_fail(si, fault_nochange, _("A official channel for \2%s\2 was not set."), parv[0]); return; } /* we'll overwrite any existing metadata */ metadata_add(mg, "channel", chan); logcommand(si, CMDLOG_SET, "SET:CHANNEL: \2%s\2 \2%s\2", entity(mg)->name, chan); command_success_nodata(si, _("The official channel of \2%s\2 has been set to \2%s\2."), parv[0], chan); }
static void cs_cmd_set_email(struct sourceinfo *si, int parc, char *parv[]) { struct mychan *mc; char *mail = parv[1]; 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)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!mail || !strcasecmp(mail, "NONE") || !strcasecmp(mail, "OFF")) { if (metadata_find(mc, "email")) { metadata_delete(mc, "email"); command_success_nodata(si, _("The e-mail address for channel \2%s\2 was deleted."), mc->name); logcommand(si, CMDLOG_SET, "SET:EMAIL:NONE: \2%s\2", mc->name); return; } command_fail(si, fault_nochange, _("The e-mail address for channel \2%s\2 was not set."), mc->name); return; } if (!validemail(mail)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid e-mail address."), mail); return; } // we'll overwrite any existing metadata metadata_add(mc, "email", mail); logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 \2%s\2", mc->name, mail); verbose(mc, _("\2%s\2 set the e-mail address for the channel to \2%s\2"), get_source_name(si), mail); command_success_nodata(si, _("The e-mail address for channel \2%s\2 has been set to \2%s\2."), parv[0], mail); }
static void cs_cmd_set_entrymsg(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 (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!parv[1] || !strcasecmp("OFF", parv[1]) || !strcasecmp("NONE", parv[1])) { /* entrymsg is private because users won't see it if they're AKICKED, * if the channel is +i, or if the channel is RESTRICTED */ if (metadata_find(mc, "private:entrymsg")) { metadata_delete(mc, "private:entrymsg"); logcommand(si, CMDLOG_SET, "SET:ENTRYMSG:NONE: \2%s\2", mc->name); verbose(mc, _("\2%s\2 cleared the entry message"), get_source_name(si)); command_success_nodata(si, _("The entry message for \2%s\2 has been cleared."), parv[0]); return; } command_fail(si, fault_nochange, _("The entry message for \2%s\2 was not set."), parv[0]); return; } /* we'll overwrite any existing metadata. * Why is/was this even private? There are no size/content sanity checks * and even users with no channel access can see it. --jdhore */ metadata_add(mc, "private:entrymsg", parv[1]); logcommand(si, CMDLOG_SET, "SET:ENTRYMSG: \2%s\2 \2%s\2", mc->name, parv[1]); verbose(mc, _("\2%s\2 set the entry message for the channel to \2%s\2"), get_source_name(si), parv[1]); command_success_nodata(si, _("The entry message for \2%s\2 has been set to \2%s\2"), parv[0], parv[1]); }
static void ns_cmd_set_enforcetime(sourceinfo_t *si, int parc, char *parv[]) { char *setting = parv[0]; if (!setting) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "ENFORCETIME"); command_fail(si, fault_needmoreparams, _("Syntax: SET ENFORCETIME TIME|DEFAULT")); return; } int enforcetime = atoi(parv[0]); if (strcasecmp(setting, "DEFAULT") == 0) { if (metadata_find(si->smu, "private:doenforce")) { logcommand(si, CMDLOG_SET, "SET:ENFORCETIME:DEFAULT"); metadata_delete(si->smu, "private:enforcetime"); command_success_nodata(si, _("The \2%s\2 for account \2%s\2 has been reset to default, which is \2%d\2 seconds."), "ENFORCETIME", entity(si->smu)->name, nicksvs.enforce_delay); } else { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for account \2%s\2."), "ENFORCE", entity(si->smu)->name); } } else if (enforcetime > 0 && enforcetime <= 180) { if (metadata_find(si->smu, "private:doenforce")) { logcommand(si, CMDLOG_SET, "SET:ENFORCETIME: %d", enforcetime); metadata_add(si->smu, "private:enforcetime", setting); command_success_nodata(si, _("The \2%s\2 for account \2%s\2 has been set to \2%d\2 seconds."), "ENFORCETIME", entity(si->smu)->name, enforcetime); } else { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for account \2%s\2."), "ENFORCE", entity(si->smu)->name); } } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "ENFORCETIME"); } }
static void cs_cmd_set_prefix(struct sourceinfo *si, int parc, char *parv[]) { struct mychan *mc; char *prefix = parv[1]; 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)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!prefix || !strcasecmp(prefix, "DEFAULT")) { metadata_delete(mc, "private:prefix"); logcommand(si, CMDLOG_SET, "SET:PREFIX: \2%s\2 reset", mc->name); verbose(mc, _("The fantasy prefix for the channel has been reset by \2%s\2"), get_source_name(si)); command_success_nodata(si, _("The fantasy prefix for channel \2%s\2 has been reset."), parv[0]); return; } if (!goodprefix(prefix)) { command_fail(si, fault_badparams, _("Prefix '%s' is invalid. The prefix may " "contain only printable characters, and must contain at least " "one non-space character."), prefix); return; } metadata_add(mc, "private:prefix", prefix); logcommand(si, CMDLOG_SET, "SET:PREFIX: \2%s\2 \2%s\2", mc->name, prefix); verbose(mc, _("\2%s\2 set the fantasy prefix to \2%s\2"), get_source_name(si), prefix); command_success_nodata(si, _("The fantasy prefix for channel \2%s\2 has been set to \2%s\2."), parv[0], prefix); }
static void ns_cmd_register(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mynick_t *mn = NULL; mowgli_node_t *n; const char *account; const char *pass; const 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 (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 - 1); 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 (strlen(account) >= NICKLEN) { 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 != NULL ? si->su->nick : get_source_name(si)); 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; } if (!email_within_limits(email)) { 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 = random_string(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, mu, EMAIL_REGISTER, mu->email, 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 ns_cmd_freeze(char *origin) { myuser_t *mu; user_t *source = user_find_named(origin); char *target = strtok(NULL, " "); char *action = strtok(NULL, " "); char *reason = strtok(NULL, ""); if (source == NULL) return; if (!target || !action) { notice(nicksvs.nick, origin, STR_INSUFFICIENT_PARAMS, "FREEZE"); notice(nicksvs.nick, origin, "Usage: FREEZE <username> <ON|OFF> [reason]"); return; } mu = myuser_find_ext(target); if (!mu) { notice(nicksvs.nick, origin, "\2%s\2 is not a registered nickname.", target); return; } if (!strcasecmp(action, "ON")) { if (!reason) { notice(nicksvs.nick, origin, STR_INSUFFICIENT_PARAMS, "FREEZE"); notice(nicksvs.nick, origin, "Usage: FREEZE <username> ON <reason>"); return; } if (is_soper(mu)) { notice(nicksvs.nick, origin, "The nickname \2%s\2 belongs to a services operator; it cannot be frozen.", target); return; } if (metadata_find(mu, METADATA_USER, "private:freeze:freezer")) { notice(nicksvs.nick, origin, "\2%s\2 is already frozen.", target); return; } metadata_add(mu, METADATA_USER, "private:freeze:freezer", origin); metadata_add(mu, METADATA_USER, "private:freeze:reason", reason); metadata_add(mu, METADATA_USER, "private:freeze:timestamp", itoa(CURRTIME)); wallops("%s froze the nickname \2%s\2 (%s).", origin, target, reason); logcommand(nicksvs.me, source, CMDLOG_ADMIN, "FREEZE %s ON", target); notice(nicksvs.nick, origin, "\2%s\2 is now frozen.", target); } else if (!strcasecmp(action, "OFF")) { if (!metadata_find(mu, METADATA_USER, "private:freeze:freezer")) { notice(nicksvs.nick, origin, "\2%s\2 is not frozen.", target); return; } metadata_delete(mu, METADATA_USER, "private:freeze:freezer"); metadata_delete(mu, METADATA_USER, "private:freeze:reason"); metadata_delete(mu, METADATA_USER, "private:freeze:timestamp"); wallops("%s thawed the nickname \2%s\2.", origin, target); logcommand(nicksvs.me, source, CMDLOG_ADMIN, "FREEZE %s OFF", target); notice(nicksvs.nick, origin, "\2%s\2 has been thawed", target); } else { notice(nicksvs.nick, origin, STR_INSUFFICIENT_PARAMS, "FREEZE"); notice(nicksvs.nick, origin, "Usage: FREEZE <account> <ON|OFF> [reason]"); } }
static void cs_cmd_set_fantasy(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 FANTASY"); 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])) { metadata_t *md = metadata_find(mc, "disable_fantasy"); if (!md) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "FANTASY", mc->name); return; } metadata_delete(mc, "disable_fantasy"); logcommand(si, CMDLOG_SET, "SET:FANTASY:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the FANTASY flag"), get_source_name(si)); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "FANTASY", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { metadata_t *md = metadata_find(mc, "disable_fantasy"); if (md) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "FANTASY", mc->name); return; } metadata_add(mc, "disable_fantasy", "on"); logcommand(si, CMDLOG_SET, "SET:FANTASY:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the FANTASY flag"), get_source_name(si)); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "FANTASY", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "FANTASY"); 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]; hook_user_needforce_t needforce_hdata; 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; } } needforce_hdata.si = si; needforce_hdata.mu = mu; needforce_hdata.allowed = 1; hook_call_user_needforce(&needforce_hdata); if (!needforce_hdata.allowed) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked)", entity(mu)->name); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked."), entity(mu)->name); 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)", entity(mu)->name); 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_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } 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; } if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); key = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(key); return; } metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); free(key); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); } else { if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); if (md) command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); else command_success_nodata(si, _("Overriding MARK on the account %s."), entity(mu)->name); } logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name); newpass = random_string(12); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); if (!sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, newpass)) { command_fail(si, fault_emailfail, _("Email send failed.")); free(newpass); return; } set_password(mu, newpass); free(newpass); command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (mu->flags & MU_NOPASSWORD) { mu->flags &= ~MU_NOPASSWORD; command_success_nodata(si, _("The \2%s\2 flag has been removed for account \2%s\2."), "NOPASSWORD", entity(mu)->name); } } }
static void ns_cmd_sendpass(struct sourceinfo *si, int parc, char *parv[]) { struct myuser *mu; char *name = parv[0]; char *key; enum specialoperation op = op_none; bool ismarked = false; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!has_priv(si, PRIV_USER_SENDPASS)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } else 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, STR_IS_NOT_REGISTERED, name); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if (metadata_find(mu, "private:mark:setter")) { ismarked = true; // don't want to disclose this, so just go ahead... } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); metadata_delete(mu, "private:setpass:key"); metadata_delete(mu, "private:sendpass:sender"); metadata_delete(mu, "private:sendpass:timestamp"); 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) { if (si->smu == mu) command_fail(si, fault_already_authed, _("You are logged in and can change your password using the SET PASSWORD command.")); else 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_fail(si, fault_noprivs, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } 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); if (has_priv(si, PRIV_USER_SENDPASS)) 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); const char *const hash = crypt_password(key); if (!hash) { command_fail(si, fault_internalerror, _("Hash generation for password change key failed.")); sfree(key); return; } if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { if (ismarked) wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); metadata_add(mu, "private:setpass:key", hash); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to the corresponding email address."), entity(mu)->name); } else command_fail(si, fault_emailfail, _("Email send failed.")); sfree(key); }
/* 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 (si->smu->flags & MU_WAITAUTH) { command_fail(si, fault_noprivs, _("Please verify your original registration before changing your e-mail address.")); 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 (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, EMAIL_SETEMAIL, si->smu, 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; } myuser_set_email(si->smu, email); logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2)", entity(si->smu)->name, si->smu->email, 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); }
static void cs_cmd_register(struct sourceinfo *si, int parc, char *parv[]) { struct channel *c; struct chanuser *cu; struct mychan *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 (*name != '#') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "REGISTER"); command_fail(si, fault_badparams, _("Syntax: REGISTER <#channel>")); return; } if (si->smu->flags & MU_WAITAUTH) { command_fail(si, fault_notverified, _("You need to verify your email address before you may register channels.")); return; } // make sure it isn't already registered if ((mc = mychan_find(name))) { if (! (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; } }
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 int metadata_find(const char *fname, const char *stag, unsigned int slength, off64_t *offset) { char tag[METADATA_TAG_MAX_LENGTH + 1]; int rc = -1; int n; long start = 0x4000; /* skip cryptfs metadata area */ uint32_t magic; unsigned int length = 0; if (!fname) { return -1; } auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(fname, "re+"), fclose}; if (!fp) { PERROR << "Failed to open " << fname; return -1; } /* check magic */ if (fseek(fp.get(), start, SEEK_SET) < 0 || fread(&magic, sizeof(magic), 1, fp.get()) != 1) { PERROR << "Failed to read magic from " << fname; return -1; } if (magic != METADATA_MAGIC) { magic = METADATA_MAGIC; if (fseek(fp.get(), start, SEEK_SET) < 0 || fwrite(&magic, sizeof(magic), 1, fp.get()) != 1) { PERROR << "Failed to write magic to " << fname; return -1; } rc = metadata_add(fp.get(), start + sizeof(magic), stag, slength, offset); if (rc < 0) { PERROR << "Failed to add metadata to " << fname; } return rc; } start += sizeof(magic); while (1) { n = fscanf(fp.get(), "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", tag, &length); if (n == 2 && strcmp(tag, METADATA_EOD)) { /* found a tag */ start = ftell(fp.get()); if (!strcmp(tag, stag) && length == slength) { *offset = start; return 0; } start += length; if (fseek(fp.get(), length, SEEK_CUR) < 0) { PERROR << "Failed to seek " << fname; return -1; } } else { rc = metadata_add(fp.get(), start, stag, slength, offset); if (rc < 0) { PERROR << "Failed to write metadata to " << fname; } return rc; } } }
static void cs_cmd_set_gameserv(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; const char *val; 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 (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET GAMESERV"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!strcasecmp("ALL", parv[1])) val = "ALL"; else if (!strcasecmp("VOICE", parv[1]) || !strcasecmp("VOICES", parv[1])) val = "VOICE"; else if (!strcasecmp("OP", parv[1]) || !strcasecmp("OPS", parv[1])) val = "OP"; else if (!strcasecmp("OFF", parv[1])) val = NULL; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "GAMESERV"); return; } md = metadata_find(mc, "gameserv"); if (val != NULL) { if (md != NULL && !strcasecmp(md->value, val)) { command_fail(si, fault_nochange, _("\2%s\2 is already set to %s for \2%s\2."), "GAMESERV", val, mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GAMESERV: \2%s\2 to \2%s\2", mc->name, val); verbose(mc, _("\2%s\2 set the GAMESERV flag to \2%s\2"), get_source_name(si), val); metadata_add(mc, "gameserv", val); command_success_nodata(si, _("\2%s\2 has been set to \2%s\2 for \2%s\2."), "GAMESERV", val, mc->name); return; } else { if (md == NULL) { command_fail(si, fault_nochange, _("\2%s\2 was not set for \2%s\2."), "GAMESERV", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GAMESERV:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the GAMESERV flag"), get_source_name(si)); metadata_delete(mc, "gameserv"); command_success_nodata(si, _("\2%s\2 has been disabled for \2%s\2."), "GAMESERV", mc->name); } }
static void gs_cmd_invite(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; myuser_t *mu; groupacs_t *ga; char *group = parv[0]; char *user = parv[1]; char buf[BUFSIZE], description[256]; service_t *svs; if (!group || !user) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INVITE"); command_fail(si, fault_needmoreparams, _("Syntax: INVITE <!group> <user>")); return; } if ((mg = mygroup_find(group)) == NULL) { command_fail(si, fault_nosuch_target, _("The group \2%s\2 does not exist."), group); return; } if (!groupacs_sourceinfo_has_flag(mg, si, GA_INVITE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if ((mu = myuser_find_ext(user)) == NULL) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not a registered account."), user); return; } if ((ga = groupacs_find(mg, entity(mu), 0, false)) != NULL) { command_fail(si, fault_badparams, _("\2%s\2 is already a member of: \2%s\2"), entity(mu)->name, entity(mg)->name); return; } if (metadata_find(mu, "private:groupinvite")) { command_fail(si, fault_badparams, _("\2%s\2 may not be invited to a group and already has another invitation pending."), entity(mu)->name); return; } if (MU_NEVERGROUP & mu->flags) { command_fail(si, fault_noprivs, _("\2%s\2 does not wish to belong to any groups."), entity(mu)->name); return; } metadata_add(mu, "private:groupinvite", entity(mg)->name); if ((svs = service_find("memoserv")) != NULL) { snprintf(buf, BUFSIZE, "%s [auto memo] You have been invited to the group: %s", entity(mu)->name, entity(mg)->name); command_exec_split(svs, si, "SEND", buf, svs->commands); } else { myuser_notice(si->service->nick, mu, "You have been invited to the group: %s", entity(mg)->name); } logcommand(si, CMDLOG_SET, "INVITE: \2%s\2 \2%s\2", entity(mg)->name, entity(mu)->name); command_success_nodata(si, _("\2%s\2 has been invited to \2%s\2"), entity(mu)->name, entity(mg)->name); snprintf(description, sizeof description, "Invited \2%s\2 to join.", entity(mu)->name); notify_group_misc_change(si, mg, description); }