static void json_getlog(struct command *cmd, const char *buffer, const jsmntok_t *params) { struct log_info info; struct log_record *lr = cmd->dstate->log_record; jsmntok_t *level; json_get_params(buffer, params, "level", &level, NULL); info.num_skipped = 0; if (!level) info.level = LOG_INFORM; else if (json_tok_streq(buffer, level, "io")) info.level = LOG_IO; else if (json_tok_streq(buffer, level, "debug")) info.level = LOG_DBG; else if (json_tok_streq(buffer, level, "info")) info.level = LOG_INFORM; else if (json_tok_streq(buffer, level, "unusual")) info.level = LOG_UNUSUAL; else { command_fail(cmd, "Invalid level param"); return; } info.response = new_json_result(cmd); json_object_start(info.response, NULL); json_add_time(info.response, "creation_time", log_init_time(lr)->ts); json_add_num(info.response, "bytes_used", (unsigned int)log_used(lr)); json_add_num(info.response, "bytes_max", (unsigned int)log_max_mem(lr)); json_object_start(info.response, "log"); log_each_line(lr, log_to_json, &info); json_object_end(info.response); json_object_end(info.response); command_success(cmd, info.response); }
static void check_registration(hook_user_register_check_t *hdata) { char buf[1024]; const char *user; const char *domain; int count; if (hdata->approved) return; strlcpy(buf, hdata->email, sizeof buf); user = strtok(buf, "@"); domain = strtok(NULL, "@"); count = count_mx(domain); if (count > 0) { /* there are MX records for this domain */ snoop("REGISTER: mxcheck: %d MX records for %s", count, domain); } else { /* no MX records or error */ struct hostent *host; /* attempt to resolve host (fallback to A) */ if((host = gethostbyname(domain)) == NULL) { snoop("REGISTER: mxcheck: no A/MX records for %s - " "REGISTER failed", domain); command_fail(hdata->si, fault_noprivs, "Sorry, \2%s\2 does not exist, " "I can't send mail there. Please check and try again.", domain); hdata->approved = 1; return; } } }
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 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 (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), mc->name); 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 && MOWGLI_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"); } logcommand(si, CMDLOG_SET, "SET:NOBOT:ON: \2%s\2", mc->name); 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"); logcommand(si, CMDLOG_SET, "SET:NOBOT:OFF: \2%s\2", mc->name); 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}")); } }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "UNBAN"); return; } if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel>")); return; } if (target && irccasecmp(target, si->su->nick)) { command_fail(si, fault_noprivs, _("You may only unban yourself via %s."), si->service->nick); if (validhostmask(target)) command_fail(si, fault_noprivs, _("Try \2/mode %s -b %s\2"), channel, target); return; } target = si->su->nick; if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } tu = si->su; { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 \2%s\2 (for user \2%s\2)", mc->name, cb->mask, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } if (!target) { if (si->su == NULL) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } target = si->su->nick; } if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE) && (si->su == NULL || !chanacs_source_has_flag(mc, si, CA_EXEMPT) || irccasecmp(target, si->su->nick))) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if ((tu = user_find_named(target))) { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2 (for user \2%s\2)", cb->mask, mc->name, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } else if ((cb = chanban_find(c, target, 'b')) != NULL || validhostmask(target)) { if (cb) { modestack_mode_param(chansvs.nick, c, MTYPE_DEL, 'b', target); chanban_delete(cb); logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2", target, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2."), target, channel); } else command_fail(si, fault_nosuch_key, _("No such ban \2%s\2 on \2%s\2."), target, channel); return; } else { command_fail(si, fault_badparams, _("Invalid nickname/hostmask provided: \2%s\2"), target); command_fail(si, fault_badparams, _("Syntax: UNBAN <#channel> [nickname|hostmask]")); return; } }
static void command_nwod(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char *arg_dice, *arg_rerollflag; int ii = 0; int dice, reroll; int roll, total, roll_count = 0, i; int success = 0, failure = 0, botches = 0, rerolls = 0; static char buf[BUFSIZE]; char *end_p; if (!gs_do_parameters(si, &parc, &parv, &mc)) return; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "NWOD"); command_fail(si, fault_needmoreparams, _("Syntax: NWOD [-chance] <dice> [-reroll] [reroll]")); return; } arg_dice = parv[ii++]; arg_rerollflag = parv[ii++]; while (roll_count < 3 && arg_dice != NULL) { success = 0, failure = 0, botches = 0, rerolls = 0; roll_count++; dice = atoi(arg_dice); if (dice == 0 && !strcasecmp(arg_dice, "-chance")) { roll = (arc4random() % 10) + 1; if (roll == 1) botches++; if (roll == 10) success++; gs_command_report(si, _("%s rolls a chance die: %d"), si->su->nick, roll); gs_command_report(si, _("Successes: %d, Failures: %d, Botches: %d."), success, failure, botches); return; } if (dice > 30 || dice < 1) { command_fail(si, fault_badparams, _("Only 1-30 dice may be thrown at one time.")); return; } if (arg_rerollflag != NULL && !strcasecmp(arg_rerollflag, "-reroll") && parv[ii + 1] != NULL) reroll = atoi(parv[ii++]); else reroll = 10; { end_p = buf; for (i = 0; i < dice; i++) { roll = (arc4random() % 10) + 1; end_p += snprintf(end_p, BUFSIZE - (end_p - buf), "%d ", roll); if (roll == 1) { botches++; continue; } else if (roll >= reroll) rerolls++; if (roll >= 8) success++; else failure++; } rerolls = rerolls - botches; total = success - botches; gs_command_report(si, _("%s rolls %d dice: %s"), si->su->nick, dice, buf); if (rerolls > 0) gs_command_report(si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d. You may reroll %d."), success, failure, botches, total, rerolls); else gs_command_report(si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d."), success, failure, botches, total); } /* prepare for another go. */ arg_dice = parv[ii++]; arg_rerollflag = parv[ii++]; } }
/* FFLAGS <channel> <user> <flags> */ static void cs_cmd_fflags(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *target = parv[1]; char *flagstr = parv[2]; mychan_t *mc; myuser_t *tmu; unsigned int addflags, removeflags; 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, chanacs_flags, &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 (!(tmu = myuser_find_ext(target))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), target); return; } target = tmu->name; /* 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, tmu) && removeflags & CA_FOUNDER && mychan_num_founders(mc) == 1) { command_fail(si, fault_noprivs, _("You may not remove the last founder.")); return; } if (!chanacs_change(mc, tmu, NULL, &addflags, &removeflags, ca_all)) { /* 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, chanacs_flags), tmu->name, mc->name); return; } } else { if (addflags & CA_FOUNDER) { command_fail(si, fault_badparams, _("You may not set founder status on a hostmask.")); return; } if (!chanacs_change(mc, NULL, target, &addflags, &removeflags, ca_all)) { /* 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, chanacs_flags), target, mc->name); return; } } 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, chanacs_flags); 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); snoop("FFLAGS: \2%s\2 \2%s\2 \2%s\2 by \2%s\2", channel, target, flagstr, get_oper_name(si)); 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, "%s FFLAGS %s %s", 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 parse_request(struct json_connection *jcon, const jsmntok_t tok[]) { const jsmntok_t *method, *id, *params; const struct json_command *cmd; assert(!jcon->current); if (tok[0].type != JSMN_OBJECT) { json_command_malformed(jcon, "null", "Expected {} for json command"); return; } method = json_get_member(jcon->buffer, tok, "method"); params = json_get_member(jcon->buffer, tok, "params"); id = json_get_member(jcon->buffer, tok, "id"); if (!id) { json_command_malformed(jcon, "null", "No id"); return; } if (id->type != JSMN_STRING && id->type != JSMN_PRIMITIVE) { json_command_malformed(jcon, "null", "Expected string/primitive for id"); return; } /* This is a convenient tal parent for durarion of command * (which may outlive the conn!). */ jcon->current = tal(jcon->dstate, struct command); jcon->current->jcon = jcon; jcon->current->dstate = jcon->dstate; jcon->current->id = tal_strndup(jcon->current, json_tok_contents(jcon->buffer, id), json_tok_len(id)); if (!method || !params) { command_fail(jcon->current, method ? "No params" : "No method"); return; } if (method->type != JSMN_STRING) { command_fail(jcon->current, "Expected string for method"); return; } cmd = find_cmd(jcon->buffer, method); if (!cmd) { command_fail(jcon->current, "Unknown command '%.*s'", (int)(method->end - method->start), jcon->buffer + method->start); return; } if (params->type != JSMN_ARRAY && params->type != JSMN_OBJECT) { command_fail(jcon->current, "Expected array or object for params"); return; } cmd->dispatch(jcon->current, jcon->buffer, params); }
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 (!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 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 cs_cmd_owner(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; char *nicklist; char *strtokctx; if (ircd->uses_owner == false) { command_fail(si, fault_noprivs, _("The IRCd software you are running does not support this feature.")); return; } if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "OWNER"); command_fail(si, fault_needmoreparams, _("Syntax: OWNER <#channel> [nickname] [...]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_USEOWNER)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } nicklist = (!nick ? strdup(si->su->nick) : strdup(nick)); nick = strtok_r(nicklist, " ", &strtokctx); do { if (invert_purpose(si, parc, chan, &nick, '-', &cs_cmd_deowner)) continue; /* figure out who we're going to op */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); continue; } if (is_internal_client(tu)) continue; /* SECURE check; we can skip this if sender == target, because we already verified */ if ((si->su != tu) && (mc->flags & MC_SECURE) && !chanacs_user_has_flag(mc, tu, CA_OP) && !chanacs_user_has_flag(mc, tu, CA_AUTOOP)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); command_fail(si, fault_noprivs, _("\2%s\2 has the SECURE option enabled, and \2%s\2 does not have appropriate access."), mc->name, tu->nick); continue; } cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); continue; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(tu)); cu->modes |= CSTATUS_OWNER; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been set as owner on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "OWNER: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been set as owner on \2%s\2."), tu->nick, mc->name); } while ((nick = strtok_r(NULL, " ", &strtokctx)) != NULL); free(nicklist); }
static void ns_cmd_setpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; metadata_t *md; char *nick = parv[0]; char *key = parv[1]; char *password = parv[2]; if (!nick || !key || !password) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SETPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SETPASS <account> <key> <newpass>")); return; } if (strchr(password, ' ')) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SETPASS"); command_fail(si, fault_badparams, _("Syntax: SETPASS <account> <key> <newpass>")); return; } if (!(mu = myuser_find(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), nick); return; } if (strlen(password) >= PASSLEN) { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SETPASS"); command_fail(si, fault_badparams, _("Registration passwords may not be longer than \2%d\2 characters."), PASSLEN - 1); return; } if (!strcasecmp(password, entity(mu)->name)) { command_fail(si, fault_badparams, _("You cannot use your nickname as a password.")); command_fail(si, fault_badparams, _("Syntax: SETPASS <account> <key> <newpass>")); return; } md = metadata_find(mu, "private:setpass:key"); if (md != NULL && crypt_verify_password(key, md->value) != NULL) { logcommand(si, CMDLOG_SET, "SETPASS: \2%s\2", entity(mu)->name); set_password(mu, password); metadata_delete(mu, "private:setpass:key"); command_success_nodata(si, _("The password for \2%s\2 has been changed to \2%s\2."), entity(mu)->name, password); return; } if (md != NULL) { logcommand(si, CMDLOG_SET, "failed SETPASS (invalid key)"); } command_fail(si, fault_badparams, _("Verification failed. Invalid key for \2%s\2."), entity(mu)->name); return; }
static void gs_cmd_join(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; groupacs_t *ga; metadata_t *md, *md2; unsigned int flags = 0; bool invited = false; groupinvite_t *gi; if (!parv[0]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "JOIN"); command_fail(si, fault_needmoreparams, _("Syntax: JOIN <!groupname>")); return; } if (!(mg = mygroup_find(parv[0]))) { command_fail(si, fault_alreadyexists, _("Group \2%s\2 does not exist."), parv[0]); return; } if ((gi = groupinvite_find(mg, entity(si->smu))) != NULL) { invited = true; } else { /* Legacy code - Search old invite and delete it */ if ((md2 = metadata_find(si->smu, "private:groupinvite"))) { if (!strcasecmp(md2->value, parv[0])) { invited = true; metadata_delete(si->smu, "private:groupinvite"); } } } if (groupacs_sourceinfo_has_flag(mg, si, 0)) { command_fail(si, fault_nochange, _("You are already a member of group \2%s\2."), parv[0]); return; } if (!(mg->flags & MG_OPEN) && !invited) { command_fail(si, fault_noprivs, _("Group \2%s\2 is not open to anyone joining."), parv[0]); return; } if (groupacs_sourceinfo_has_flag(mg, si, GA_BAN)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (MOWGLI_LIST_LENGTH(&mg->acs) > gs_config->maxgroupacs && (!(mg->flags & MG_ACSNOLIMIT)) && !invited) { command_fail(si, fault_toomany, _("Group \2%s\2 access list is full."), entity(mg)->name); return; } if ((md = metadata_find(mg, "joinflags"))) flags = atoi(md->value); else flags = gs_flags_parser(gs_config->join_flags, 0, flags); ga = groupacs_add(mg, entity(si->smu), flags); if (invited) groupinvite_delete(mg, entity(si->smu)); command_success_nodata(si, _("You are now a member of \2%s\2."), entity(mg)->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); }
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_INSUFFICIENT_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, _("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; } 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 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) || chanacs_source_has_flag(mc, si, CA_FOUNDER))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); 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_kick(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; char *reason = parv[2]; mychan_t *mc; user_t *tu; chanuser_t *cu; char reasonbuf[BUFSIZE]; if (!chan || !nick) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "KICK"); command_fail(si, fault_needmoreparams, _("Syntax: KICK <#channel> <nickname> [reason]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } /* figure out who we're going to kick */ if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } /* if target is a service, bail. --nenolod */ if (is_internal_client(tu)) return; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } if (cu->modes & CSTATUS_OWNER || cu->modes & CSTATUS_PROTECT) { command_fail(si, fault_noprivs, _("\2%s\2 is protected from kicks; you cannot kick them."), tu->nick); return; } snprintf(reasonbuf, BUFSIZE, "(%s) %s", get_source_name(si), reason ? reason : "No reason given"); try_kick(chansvs.me->me, mc->chan, tu, reasonbuf); logcommand(si, CMDLOG_DO, "KICK: \2%s!%s@%s\2 from \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (si->su != tu && !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been kicked from \2%s\2."), tu->nick, mc->name); }
static void 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); }
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 command_wod(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char *arg_dice, *arg_difficulty; int ii = 0; int dice, difficulty; int roll, total, roll_count = 0, i; int success = 0, failure = 0, botches = 0, rerolls = 0; static char buf[BUFSIZE]; char *end_p; if (!gs_do_parameters(si, &parc, &parv, &mc)) return; if (parc < 2) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "WOD"); command_fail(si, fault_needmoreparams, _("Syntax: WOD <dice> <difficulty>")); return; } arg_dice = parv[ii++]; arg_difficulty = parv[ii++]; while (roll_count < 3 && arg_dice != NULL && arg_difficulty != NULL) { success = 0, failure = 0, botches = 0, rerolls = 0; roll_count++; dice = atoi(arg_dice); difficulty = atoi(arg_difficulty); if (dice > 30 || dice < 1) { command_fail(si, fault_badparams, _("Only 1-30 dice may be thrown at one time.")); return; } else if (difficulty > 10 || difficulty < 1) { command_fail(si, fault_badparams, _("Difficulty setting must be between 1 and 10.")); return; } else { end_p = buf; for (i = 0; i < dice; i++) { roll = (arc4random() % 10) + 1; end_p += snprintf(end_p, BUFSIZE - (end_p - buf), "%d ", roll); if (roll == 1) { botches++; continue; } else if (roll == 10) rerolls++; if (roll >= difficulty) success++; else failure++; } rerolls = rerolls - botches; total = success - botches; gs_command_report(si, _("%s rolls %d dice at difficulty %d: %s"), si->su->nick, dice, difficulty, buf); if (rerolls > 0) gs_command_report(si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d. You may reroll %d if you have a specialty."), success, failure, botches, total, rerolls); else gs_command_report(si, _("Successes: %d, Failures: %d, Botches: %d, Total: %d."), success, failure, botches, total); } /* prepare for another go. */ arg_dice = parv[ii++]; arg_difficulty = parv[ii++]; } }
static void cs_cmd_set_topiclock(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 TOPICLOCK"); 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_TOPICLOCK & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "TOPICLOCK", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:TOPICLOCK:ON: \2%s\2", mc->name); mc->flags |= MC_KEEPTOPIC | MC_TOPICLOCK; topiclock_sts(mc->chan); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "TOPICLOCK", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_TOPICLOCK & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "TOPICLOCK", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:TOPICLOCK:OFF: \2%s\2", mc->name); mc->flags &= ~MC_TOPICLOCK; topiclock_sts(mc->chan); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "TOPICLOCK", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "TOPICLOCK"); return; } }
static void cs_cmd_ban(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *target = parv[1]; char *newtarget; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; if (!channel || !target) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "BAN"); command_fail(si, fault_needmoreparams, _("Syntax: BAN <#channel> <nickname|hostmask>")); return; } if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { 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."), channel); return; } if ((tu = user_find_named(target))) { char hostbuf[BUFSIZE]; hostbuf[0] = '\0'; mowgli_strlcat(hostbuf, "*!*@", BUFSIZE); mowgli_strlcat(hostbuf, tu->vhost, BUFSIZE); modestack_mode_param(chansvs.nick, c, MTYPE_ADD, 'b', hostbuf); chanban_add(c, hostbuf, 'b'); logcommand(si, CMDLOG_DO, "BAN: \2%s\2 on \2%s\2 (for user \2%s!%s@%s\2)", hostbuf, mc->name, tu->nick, tu->user, tu->vhost); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Banned \2%s\2 on \2%s\2."), target, channel); return; } else if ((is_extban(target) && (newtarget = target)) || ((newtarget = pretty_mask(target)) && validhostmask(newtarget))) { modestack_mode_param(chansvs.nick, c, MTYPE_ADD, 'b', newtarget); chanban_add(c, newtarget, 'b'); logcommand(si, CMDLOG_DO, "BAN: \2%s\2 on \2%s\2", newtarget, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Banned \2%s\2 on \2%s\2."), newtarget, channel); return; } else { command_fail(si, fault_badparams, _("Invalid nickname/hostmask provided: \2%s\2"), target); command_fail(si, fault_badparams, _("Syntax: BAN <#channel> <nickname|hostmask>")); return; } }
static void cs_cmd_drop(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; 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 <#channel>")); return; } if (*name != '#') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "DROP"); command_fail(si, fault_badparams, _("Syntax: DROP <#channel>")); return; } if (!(mc = mychan_find(name))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), name); return; } if (si->c != NULL) { command_fail(si, fault_noprivs, _("For security reasons, you may not drop a channel registration with a fantasy command.")); return; } if (!is_founder(mc, entity(si->smu))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:close:closer")) { logcommand(si, CMDLOG_REGISTER, "DROP: \2%s\2 failed to drop (closed)", mc->name); command_fail(si, fault_noprivs, _("The channel \2%s\2 is closed; it cannot be dropped."), mc->name); return; } if (mc->flags & MC_HOLD) { command_fail(si, fault_noprivs, _("The channel \2%s\2 is held; it cannot be dropped."), mc->name); return; } if (si->su != NULL) { if (!key) { create_challenge(si, mc->name, 0, key0); snprintf(fullcmd, sizeof fullcmd, "/%s%s DROP %s %s", (ircd->uses_rcommand == false) ? "msg " : "", chansvs.me->disp, mc->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, mc->name, 0, key0); create_challenge(si, mc->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", mc->name); hook_call_channel_drop(mc); if (mc->chan != NULL && !(mc->chan->flags & CHAN_LOG)) part(mc->name, chansvs.nick); object_unref(mc); command_success_nodata(si, _("The channel \2%s\2 has been dropped."), name); 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 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; } }
void ns_cmd_regain(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *target = parv[0]; char *password = parv[1]; user_t *target_u; mynick_t *mn; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "REGAIN"); return; } if (!target) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REGAIN"); command_fail(si, fault_needmoreparams, _("Syntax: REGAIN <target> [password]")); return; } if (nicksvs.no_nick_ownership) mn = NULL, mu = myuser_find(target); else { mn = mynick_find(target); mu = mn != NULL ? mn->owner : NULL; } target_u = user_find_named(target); if (!mu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not a registered nickname."), target); return; } if (!target_u) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), target); return; } else if (target_u == si->su) { command_fail(si, fault_badparams, _("You may not ghost yourself.")); return; } if ((!nicksvs.no_nick_ownership && mn && mu == si->smu) || /* we're identified under their nick's account */ (!nicksvs.no_nick_ownership && password && mn && verify_password(mu, password))) /* we have their nick's password */ { logcommand(si, CMDLOG_DO, "REGAIN %s!%s@%s", target_u->nick, target_u->user, target_u->vhost); kill_user(si->service->me, target_u, "REGAIN command used by %s", si->su != NULL && !strcmp(si->su->user, target_u->user) && !strcmp(si->su->vhost, target_u->vhost) ? si->su->nick : get_source_mask(si)); command_success_nodata(si, _("\2%s\2 has been regained."), target); fnc_sts(si->service->me, si->su, target, FNC_REGAIN); /* don't update the nick's last seen time */ mu->lastlogin = CURRTIME; return; } if (password && mu) { logcommand(si, CMDLOG_DO, "failed REGAIN %s (bad password)", target); command_fail(si, fault_authfail, _("Invalid password for \2%s\2."), mu->name); } else { logcommand(si, CMDLOG_DO, "failed REGAIN %s (invalid login)", target); command_fail(si, fault_noprivs, _("You may not regain \2%s\2."), target); } }
/* 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 gs_cmd_info(sourceinfo_t *si, int parc, char *parv[]) { mygroup_t *mg; struct tm tm; char buf[BUFSIZE], strfbuf[BUFSIZE]; metadata_t *md; if (!parv[0]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INFO"); command_fail(si, fault_needmoreparams, _("Syntax: INFO <!groupname>")); return; } if (!(mg = mygroup_find(parv[0]))) { command_fail(si, fault_alreadyexists, _("Group \2%s\2 does not exist."), parv[0]); return; } tm = *localtime(&mg->regtime); strftime(strfbuf, sizeof strfbuf, TIME_FORMAT, &tm); command_success_nodata(si, _("Information for \2%s\2:"), parv[0]); command_success_nodata(si, _("Registered : %s (%s ago)"), strfbuf, time_ago(mg->regtime)); if (config_options.show_entity_id || has_priv(si, PRIV_GROUP_AUSPEX)) command_success_nodata(si, _("Entity ID : %s"), entity(mg)->id); if (mg->flags & MG_PUBLIC || (si->smu != NULL && groupacs_sourceinfo_has_flag(mg, si, 0) && !groupacs_sourceinfo_has_flag(mg, si, GA_BAN)) || has_priv(si, PRIV_GROUP_AUSPEX)) command_success_nodata(si, _("Founder : %s"), mygroup_founder_names(mg)); if ((md = metadata_find(mg, "description"))) command_success_nodata(si, _("Description : %s"), md->value); if ((md = metadata_find(mg, "channel"))) command_success_nodata(si, _("Channel : %s"), md->value); if ((md = metadata_find(mg, "url"))) command_success_nodata(si, _("URL : %s"), md->value); if ((md = metadata_find(mg, "email"))) command_success_nodata(si, _("Email : %s"), md->value); *buf = '\0'; if (mg->flags & MG_REGNOLIMIT) mowgli_strlcat(buf, "REGNOLIMIT", BUFSIZE); if (mg->flags & MG_ACSNOLIMIT) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "ACSNOLIMIT", BUFSIZE); } if (mg->flags & MG_OPEN) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "OPEN", BUFSIZE); } if (mg->flags & MG_PUBLIC) { if (*buf) mowgli_strlcat(buf, " ", BUFSIZE); mowgli_strlcat(buf, "PUBLIC", BUFSIZE); } if (*buf) command_success_nodata(si, _("Flags : %s"), buf); command_success_nodata(si, _("\2*** End of Info ***\2")); logcommand(si, CMDLOG_GET, "INFO: \2%s\2", parv[0]); }
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; }