static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset) { int dooper = 0, dodeoper = 0; struct PrivilegeSet *privset = 0; if(!strcmp(new_privset, "deoper")) { if(!IsAnyOper(target_p)) { sendto_one_notice(source_p, ":You can't deoper someone who isn't an oper."); return 0; } new_privset = "default"; dodeoper = 1; sendto_one_notice(target_p, ":%s is deopering you.", source_p->name); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is deopering %s.", get_oper_name(source_p), target_p->name); } else { if(!(privset = privilegeset_get(new_privset))) { sendto_one_notice(source_p, ":There is no privilege set named '%s'.", new_privset); return 0; } if(privset == target_p->localClient->privset) { sendto_one_notice(source_p, ":%s already has privilege set %s.", target_p->name, target_p->localClient->privset->name); return 0; } } if(!dodeoper) { if(!IsAnyOper(target_p)) { sendto_one_notice(target_p, ":%s is opering you with privilege set %s", source_p->name, privset->name); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is opering %s with privilege set %s", get_oper_name(source_p), target_p->name, privset->name); dooper = 1; } else { sendto_one_notice(target_p, ":%s is changing your privilege set to %s", source_p->name, privset->name); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is changing the privilege set of %s to %s", get_oper_name(source_p), target_p->name, privset->name); } if(privilegeset_in_set(privset, "oper:staffer") && !IsOper(target_p)) { dooper = 1; if(IsHelper(target_p)) dodeoper = 1; } else if(!privilegeset_in_set(privset, "oper:staffer") && IsOper(target_p)) dooper = dodeoper = 1; } if(dodeoper) { const char *modeparv[4]; modeparv[0] = modeparv[1] = target_p->name; modeparv[2] = "-oO"; modeparv[3] = NULL; user_mode(target_p, target_p, 3, modeparv); } if(dooper) { struct oper_conf oper; oper.name = "<grant>"; oper.umodes = 0; oper.snomask = 0; oper.privset = privset; oper_up(target_p, &oper); } target_p->localClient->privset = privset; const char *modeparv[4]; modeparv[0] = modeparv[1] = target_p->name; modeparv[2] = "+"; modeparv[3] = NULL; user_mode(target_p, target_p, 3, modeparv); return 0; }
static void os_cmd_modload(sourceinfo_t *si, int parc, char *parv[]) { char *module; module_t *m; int i; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "MODLOAD"); command_fail(si, fault_needmoreparams, _("Syntax: MODLOAD <module...>")); return; } i = 0; while (i < parc) { module = parv[i++]; if (module_find_published(module)) { command_fail(si, fault_nochange, _("\2%s\2 is already loaded."), module); continue; } logcommand(si, CMDLOG_ADMIN, "MODLOAD: \2%s\2", module); m = module_load(module); if (m != NULL) command_success_nodata(si, _("Module \2%s\2 loaded."), module); else command_fail(si, fault_nosuch_target, _("Module \2%s\2 failed to load."), module); } if (conf_need_rehash) { logcommand(si, CMDLOG_ADMIN, "REHASH (MODLOAD)"); wallops("Rehashing \2%s\2 to complete module load by request of \2%s\2.", config_file, get_oper_name(si)); if (!conf_rehash()) command_fail(si, fault_nosuch_target, _("REHASH of \2%s\2 failed. Please correct any errors in the file and try again."), config_file); } }
/* * m_topic * parv[1] = channel name * parv[2] = new topic, if setting topic */ static int m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char *p = NULL; const char *name; int operspy = 0; if((p = strchr(parv[1], ','))) *p = '\0'; name = parv[1]; if(IsOperAuspex(source_p) && parv[1][0] == '!') { name++; operspy = 1; if(EmptyString(name)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "TOPIC"); return 0; } } if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsChannelName(name)) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } chptr = find_channel(name); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } /* setting topic */ if(parc > 2) { char topic_info[USERHOST_REPLYLEN]; char topic[BUFSIZE]; msptr = find_channel_membership(chptr, source_p); if(msptr == NULL) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(MyClient(source_p) && (chptr->mode.mode & MODE_TOPICLIMIT) && !is_chanop(msptr)) { if(IsOverride(source_p)) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is overriding TOPIC on [%s]", get_oper_name(source_p), chptr->chname); else { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), get_id(&me, source_p), get_id(source_p, source_p), name); return 0; } } rb_strlcpy(topic, parv[2], BUFSIZE); /* strip_colour(topic); -- draco */ rb_sprintf(topic_info, "%s!%s@%s", source_p->name, source_p->username, source_p->host); set_channel_topic(chptr, topic, topic_info, rb_current_time()); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s TOPIC %s :%s", use_id(source_p), chptr->chname, chptr->topic == NULL ? "" : chptr->topic); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s TOPIC %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, chptr->topic == NULL ? "" : chptr->topic); } else if(MyClient(source_p)) { if(operspy) report_operspy(source_p, "TOPIC", chptr->chname); if(!IsMember(source_p, chptr) && SecretChannel(chptr) && !operspy) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(chptr->topic == NULL) sendto_one(source_p, form_str(RPL_NOTOPIC), me.name, source_p->name, name); else { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } } return 0; }
/* ** mo_ojoin ** parv[1] = channel */ static int mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; int move_me = 0; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!' || *parv[1] == '~') { parv[1]++; move_me = 1; } else { sendto_one_notice(source_p, ":Unrecognised op prefix '%c'", *parv[1]); return 0; } if((chptr = find_channel(parv[1])) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } if(IsMember(source_p, chptr)) { sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]); return 0; } if(move_me == 1) parv[1]--; /* only sends stuff for #channels remotely */ if(*parv[1] == '!') { if(!ConfigChannel.use_admin) { sendto_one_notice(source_p, ":This server's configuration file does not support admin prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_ADMIN); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :!%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s", source_p->name, source_p->username, source_p->host, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '@') { add_user_to_channel(chptr, source_p, CHFL_CHANOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :@%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '%') { if(!ConfigChannel.use_halfop) { sendto_one_notice(source_p, ":This server's configuration file does not support halfop prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_HALFOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :%s%s", me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s", source_p->name, source_p->username, source_p->host, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '+') { add_user_to_channel(chptr, source_p, CHFL_VOICE); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :+%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '~') { if(!ConfigChannel.use_founder) { sendto_one_notice(source_p, ":This server's configuration file does not support founder prefix"); return 0; } add_user_to_channel(chptr, source_p, CHFL_FOUNDER); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :~%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +u %s", me.name, chptr->chname, source_p->name); } else { add_user_to_channel(chptr, source_p, CHFL_PEON); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s JOIN %ld %s +", source_p->id, (long) chptr->channelts, chptr->chname); send_channel_join(chptr, source_p); } /* send the topic... */ if(chptr->topic != NULL) { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } source_p->localClient->last_join_time = rb_current_time(); channel_member_names(chptr, source_p, 1); sendto_realops_snomask(SNO_GENERAL, L_ALL, "OJOIN called for %s by %s!%s@%s", parv[1], source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p)); return 0; }
static void cs_cmd_hold(sourceinfo_t *si, int parc, char *parv[]) { char *target = parv[0]; char *action = parv[1]; mychan_t *mc; if (!target || !action) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "HOLD"); command_fail(si, fault_needmoreparams, _("Usage: HOLD <#channel> <ON|OFF>")); return; } if (*target != '#') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "HOLD"); return; } if (!(mc = mychan_find(target))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), target); return; } if (!strcasecmp(action, "ON")) { if (mc->flags & MC_HOLD) { command_fail(si, fault_nochange, _("\2%s\2 is already held."), target); return; } mc->flags |= MC_HOLD; metadata_add(mc, "private:held:holder", get_oper_name(si)); metadata_add(mc, "private:held:timestamp", number_to_string(CURRTIME)); wallops("%s set the HOLD option for the channel \2%s\2.", get_oper_name(si), target); logcommand(si, CMDLOG_ADMIN, "HOLD:ON: \2%s\2", mc->name); command_success_nodata(si, _("\2%s\2 is now held."), target); } else if (!strcasecmp(action, "OFF")) { if (!(mc->flags & MC_HOLD)) { command_fail(si, fault_nochange, _("\2%s\2 is not held."), target); return; } mc->flags &= ~MC_HOLD; metadata_delete(mc, "private:held:holder"); metadata_delete(mc, "private:held:timestamp"); wallops("%s removed the HOLD option on the channel \2%s\2.", get_oper_name(si), target); logcommand(si, CMDLOG_ADMIN, "HOLD:OFF: \2%s\2", mc->name); command_success_nodata(si, _("\2%s\2 is no longer held."), target); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "HOLD"); command_fail(si, fault_badparams, _("Usage: HOLD <#channel> <ON|OFF>")); } }
/* ** m_undline ** added May 28th 2000 by Toby Verrall <*****@*****.**> ** based totally on m_unkline ** added to hybrid-7 7/11/2000 --is ** ** parv[0] = sender nick ** parv[1] = dline to remove */ static void mo_undline(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *addr = NULL, *user = NULL; char *target_server = NULL; if (!HasOFlag(source_p, OPER_FLAG_UNDLINE)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "undline"); return; } if (parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "UNDLINE"); return; } if (parse_aline("UNDLINE", source_p, parc, parv, 0, &user, &addr, NULL, &target_server, NULL) < 0) return; if (target_server != NULL) { sendto_match_servs(source_p, target_server, CAP_UNDLN, "UNDLINE %s %s", target_server, addr); /* Allow ON to apply local unkline as well if it matches */ if (!match(target_server, me.name)) return; } else cluster_a_line(source_p, "UNDLINE", CAP_UNDLN, SHARED_UNDLINE, "%s", addr); if (remove_tdline_match(addr)) { sendto_one(source_p, ":%s NOTICE %s :Un-Dlined [%s] from temporary D-Lines", me.name, source_p->name, addr); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the temporary D-Line for: [%s]", get_oper_name(source_p), addr); ilog(LOG_TYPE_DLINE, "%s removed temporary D-Line for [%s]", source_p->name, addr); return; } if (remove_conf_line(DLINE_TYPE, source_p, addr, NULL) > 0) { sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed", me.name, source_p->name, addr); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the D-Line for: [%s]", get_oper_name(source_p), addr); ilog(LOG_TYPE_DLINE, "%s removed D-Line for [%s]", get_oper_name(source_p), addr); } else sendto_one(source_p, ":%s NOTICE %s :No D-Line for [%s] found", me.name, source_p->name, addr); }
static void ns_cmd_sendpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; char *name = parv[0]; char *newpass = NULL; char *key; metadata_t *md; enum specialoperation op = op_none; bool ismarked = false; char cmdtext[NICKLEN + 20]; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SENDPASS"); command_fail(si, fault_needmoreparams, _("Syntax: SENDPASS <account>")); return; } if (parc > 1) { if (!strcasecmp(parv[1], "FORCE")) op = op_force; else if (!strcasecmp(parv[1], "CLEAR")) op = op_clear; else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SENDPASS"); command_fail(si, fault_badparams, _("Syntax: SENDPASS <account> [FORCE|CLEAR]")); return; } } if (!(mu = myuser_find_by_nick(name))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), name); return; } if (is_soper(mu) && !has_priv(si, PRIV_ADMIN)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (is SOPER)", name); command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to send the password."), name, PRIV_ADMIN); return; } if (mu->flags & MU_WAITAUTH) { command_fail(si, fault_badparams, _("\2%s\2 is not verified."), entity(mu)->name); return; } if ((md = metadata_find(mu, "private:mark:setter"))) { ismarked = true; if (op == op_none) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_badparams, _("This operation cannot be performed on %s, because the account has been marked by %s."), entity(mu)->name, md->value); if (has_priv(si, PRIV_MARK)) { snprintf(cmdtext, sizeof cmdtext, "SENDPASS %s FORCE", entity(mu)->name); command_fail(si, fault_badparams, _("Use %s to override this restriction."), cmdtext); } return; } else if (!has_priv(si, PRIV_MARK)) { logcommand(si, CMDLOG_ADMIN, "failed SENDPASS \2%s\2 (marked by \2%s\2)", entity(mu)->name, md->value); command_fail(si, fault_noprivs, STR_NO_PRIVILEGE, PRIV_MARK); return; } } if (op == op_clear) { if (metadata_find(mu, "private:setpass:key")) { metadata_delete(mu, "private:setpass:key"); logcommand(si, CMDLOG_ADMIN, "SENDPASS:CLEAR: \2%s\2", entity(mu)->name); command_success_nodata(si, _("The password change key for \2%s\2 has been cleared."), entity(mu)->name); } else command_fail(si, fault_nochange, _("\2%s\2 did not have a password change key outstanding."), entity(mu)->name); return; } if (MOWGLI_LIST_LENGTH(&mu->logins) > 0) { command_fail(si, fault_noprivs, _("This operation cannot be performed on %s, because someone is logged in to it."), entity(mu)->name); return; } if (metadata_find(mu, "private:freeze:freezer")) { command_success_nodata(si, _("%s has been frozen by the %s administration."), entity(mu)->name, me.netname); return; } /* alternative, safer method? */ if (command_find(si->service->commands, "SETPASS")) { if (metadata_find(mu, "private:setpass:key")) { command_fail(si, fault_alreadyexists, _("\2%s\2 already has a password change key outstanding."), entity(mu)->name); command_fail(si, fault_alreadyexists, _("Use SENDPASS %s CLEAR to clear it so that a new one can be sent."), entity(mu)->name); return; } key = random_string(12); if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SETPASS, mu->email, key)) { metadata_add(mu, "private:setpass:key", crypt_string(key, gen_salt())); logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2 (change key)", name); command_success_nodata(si, _("The password change key for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); } } else command_fail(si, fault_emailfail, _("Email send failed.")); free(key); return; } /* this is not without controversy... :) */ if (mu->flags & MU_CRYPTPASS) { command_success_nodata(si, _("The password for the account \2%s\2 is encrypted; a new password will be assigned and sent."), name); newpass = random_string(12); set_password(mu, newpass); } if (sendemail(si->su != NULL ? si->su : si->service->me, mu, EMAIL_SENDPASS, mu->email, (newpass == NULL) ? mu->pass : newpass)) { logcommand(si, CMDLOG_ADMIN, "SENDPASS: \2%s\2", name); command_success_nodata(si, _("The password for \2%s\2 has been sent to \2%s\2."), entity(mu)->name, mu->email); if (ismarked) { wallops("%s sent the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); } } else command_fail(si, fault_emailfail, _("Email send failed.")); if (newpass != NULL) free(newpass); return; }
/* parse_resv() * * inputs - source_p, NULL supported * - thing to resv * - time_t if tkline * - reason * outputs - none * side effects - parse resv, create if valid */ static void parse_resv(struct Client *source_p, char *name, int tkline_time, char *reason) { struct ConfItem *conf = NULL; int services = 0; if(IsServices(source_p)) services = 1; if(IsChanPrefix(*name)) { struct ResvChannel *resv_p; if((conf = create_channel_resv(name, reason, 0)) == NULL) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV has already been placed on channel: %s", me.name, source_p->name, name); return; } resv_p = map_to_conf(conf); if(tkline_time != 0) { if(!services) { sendto_one(source_p, ":%s NOTICE %s :A %d minute %s RESV has been placed on channel: %s", me.name, source_p->name, tkline_time / 60, (MyClient(source_p) ? "local" : "remote"), name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has placed a %d minute %s RESV on channel: %s [%s]", get_oper_name(source_p), tkline_time / 60, (MyClient(source_p) ? "local" : "remote"), resv_p->name, resv_p->reason); } ilog(L_TRACE, "%s added temporary %d min. RESV for [%s] [%s]", source_p->name, (int) tkline_time / 60, conf->name, resv_p->reason); resv_p->hold = CurrentTime + tkline_time; add_temp_line(conf); } else { if(!services) { sendto_one(source_p, ":%s NOTICE %s :A %s RESV has been placed on channel %s", me.name, source_p->name, (MyClient(source_p) ? "local" : "remote"), name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has placed a %s RESV on channel %s : [%s]", get_oper_name(source_p), (MyClient(source_p) ? "local" : "remote"), resv_p->name, resv_p->reason); } write_conf_line(source_p, conf, NULL /* not used */ , 0 /* not used */ ); } } else { struct MatchItem *resv_p = NULL; if(!valid_wild_card_simple(name) && !IsServices(source_p)) { sendto_one(source_p, ":%s NOTICE %s :Please include at least %d non-wildcard characters with the resv", me.name, source_p->name, ConfigFileEntry.min_nonwildcard_simple); return; } if(!IsAdmin(source_p) && !IsServices(source_p) && strpbrk(name, "*?#")) { sendto_one(source_p, ":%s NOTICE %s :You must be an admin to perform a " "wildcard RESV", me.name, source_p->name); return; } if((conf = create_nick_resv(name, reason, 0)) == NULL) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV has already been placed on nick %s", me.name, source_p->name, name); return; } resv_p = map_to_conf(conf); if(tkline_time != 0) { if(!services) { sendto_one(source_p, ":%s NOTICE %s :A %d minute %s RESV has been placed on nick %s : [%s]", me.name, source_p->name, tkline_time / 60, (MyClient(source_p) ? "local" : "remote"), conf->name, resv_p->reason); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has placed a %d minute %s RESV on nick %s : [%s]", get_oper_name(source_p), tkline_time / 60, (MyClient(source_p) ? "local" : "remote"), conf->name, resv_p->reason); } ilog(L_TRACE, "%s added temporary %d min. RESV for [%s] [%s]", source_p->name, (int) tkline_time / 60, conf->name, resv_p->reason); resv_p->hold = CurrentTime + tkline_time; add_temp_line(conf); } else { if(!services) { sendto_one(source_p, ":%s NOTICE %s :A %s RESV has been placed on nick %s : [%s]", me.name, source_p->name, (MyClient(source_p) ? "local" : "remote"), conf->name, resv_p->reason); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has placed a %s RESV on nick %s : [%s]", get_oper_name(source_p), (MyClient(source_p) ? "local" : "remote"), conf->name, resv_p->reason); } write_conf_line(source_p, conf, NULL /* not used */ , 0 /* not used */ ); } } }
/* ** m_okick ** parv[1] = channel ** parv[2] = client to kick ** parv[3] = kick comment */ static int mo_okick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *who; struct Client *target_p; struct Channel *chptr; struct membership *msptr; int chasing = 0; char *comment; char *name; char *p = NULL; char *user; char text[10]; static char buf[BUFSIZE]; if(*parv[2] == '\0') { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "KICK"); return 0; } if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); comment = (EmptyString(LOCAL_COPY(parv[3]))) ? LOCAL_COPY(parv[2]) : LOCAL_COPY(parv[3]); if(strlen(comment) > (size_t) TOPICLEN) comment[TOPICLEN] = '\0'; *buf = '\0'; if((p = strchr(parv[1], ','))) *p = '\0'; name = LOCAL_COPY(parv[1]); chptr = find_channel(name); if(!chptr) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } if((p = strchr(parv[2], ','))) *p = '\0'; user = LOCAL_COPY(parv[2]); // strtoken(&p2, parv[2], ","); if(!(who = find_chasing(source_p, user, &chasing))) { return 0; } if((target_p = find_client(user)) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, user); return 0; } if((msptr = find_channel_membership(chptr, target_p)) == NULL) { sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL), me.name, source_p->name, parv[1], parv[2]); return 0; } sendto_realops_snomask(SNO_GENERAL, L_ALL, "OKICK called for %s %s by %s!%s@%s", chptr->chname, target_p->name, source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OKICK called for %s %s by %s", chptr->chname, target_p->name, get_oper_name(source_p)); sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s", me.name, chptr->chname, who->name, comment); sendto_server(&me, chptr, CAP_TS6, NOCAPS, ":%s KICK %s %s :%s", me.id, chptr->chname, who->id, comment); remove_user_from_channel(msptr); rb_snprintf(text, sizeof(text), "K%s", who->id); /* we don't need to track NOREJOIN stuff unless it's our client being kicked */ if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN) channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN"); return 0; }
static void ns_cmd_register(struct sourceinfo *si, int parc, char *parv[]) { struct myuser *mu; struct mynick *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%u\2 characters."), PASSLEN); return; } if (!nicksvs.no_nick_ownership && si->su == NULL && user_find_named(account)) { command_fail(si, fault_noprivs, _("A user matching this account is already on IRC.")); return; } if (!nicksvs.no_nick_ownership && IsDigit(*account)) { command_fail(si, fault_badparams, _("For security reasons, you can't register your UID.")); command_fail(si, fault_badparams, _("Please change to a real nickname, and try again.")); return; } if (nicksvs.no_nick_ownership || si->su == NULL) { if (strchr(account, ' ') || strchr(account, '\n') || strchr(account, '\r') || account[0] == '=' || account[0] == '#' || account[0] == '@' || account[0] == '+' || account[0] == '%' || account[0] == '!' || strchr(account, ',')) { command_fail(si, fault_badparams, _("The account name \2%s\2 is invalid."), account); return; } } if (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 e-mail address."), email); return; } if (!email_within_limits(email)) { command_fail(si, fault_toomany, _("\2%s\2 has too many accounts registered."), email); return; } if (si->su && !auth_module_loaded && !crypt_get_default_provider()) (void) command_success_nodata(si, "%s", _("Warning: Your password will not be encrypted.")); 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); atheme_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.")); atheme_object_unref(mu); sfree(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.")); sfree(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."), entity(mu)->name, mu->email); 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_set_mlock(struct sourceinfo *si, int parc, char *parv[]) { struct mychan *mc; char modebuf[32], *end, c; int dir = MTYPE_NUL; int newlock_on = 0, newlock_off = 0, newlock_limit = 0, flag = 0; unsigned int mask, changed; bool mask_ext; char newlock_key[KEYLEN + 1]; char newlock_ext[ignore_mode_list_size][512]; bool newlock_ext_off[ignore_mode_list_size]; char newext[512]; char ext_plus[ignore_mode_list_size + 1]; char ext_minus[ignore_mode_list_size + 1]; size_t i; char *letters = strtok(parv[1], " "); char *arg; struct metadata *md; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, parv[0]); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { if (ircd->oper_only_modes == 0 || !has_priv(si, PRIV_CHAN_CMODES) || !has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } mask = ~ircd->oper_only_modes; mask_ext = true; } else { mask = has_priv(si, PRIV_CHAN_CMODES) ? 0 : ircd->oper_only_modes; mask_ext = false; } for (i = 0; i < ignore_mode_list_size; i++) { newlock_ext[i][0] = '\0'; newlock_ext_off[i] = false; } newlock_key[0] = '\0'; while (letters && *letters) { if (*letters != '+' && *letters != '-' && dir == MTYPE_NUL) { letters++; continue; } switch ((c = *letters++)) { case '+': dir = MTYPE_ADD; break; case '-': dir = MTYPE_DEL; break; case 'k': if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if (!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), 'k'); return; } else if (strlen(arg) > KEYLEN) { command_fail(si, fault_badparams, _("MLOCK key is too long (%zu > %u)."), strlen(arg), KEYLEN); return; } else if (strchr(arg, ',') || arg[0] == ':') { command_fail(si, fault_badparams, _("MLOCK key contains invalid characters.")); return; } mowgli_strlcpy(newlock_key, arg, sizeof newlock_key); newlock_off &= ~CMODE_KEY; } else { newlock_key[0] = '\0'; newlock_off |= CMODE_KEY; } break; case 'l': if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if(!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), 'l'); return; } if (atol(arg) <= 0) { command_fail(si, fault_badparams, _("You must specify a positive integer for limit.")); return; } newlock_limit = atol(arg); newlock_off &= ~CMODE_LIMIT; } else { newlock_limit = 0; newlock_off |= CMODE_LIMIT; } break; default: flag = mode_to_flag(c); if (flag) { if (dir == MTYPE_ADD) { newlock_on |= flag; newlock_off &= ~flag; } else { newlock_off |= flag; newlock_on &= ~flag; } break; } for (i = 0; ignore_mode_list[i].mode != '\0'; i++) { if (c == ignore_mode_list[i].mode) { if (dir == MTYPE_ADD) { arg = strtok(NULL, " "); if(!arg) { command_fail(si, fault_badparams, _("You need to specify a value for mode +%c."), c); return; } if (strlen(arg) > 350) { command_fail(si, fault_badparams, _("Invalid value \2%s\2 for mode +%c."), arg, c); return; } if ((mc->chan == NULL || mc->chan->extmodes[i] == NULL || strcmp(mc->chan->extmodes[i], arg)) && !ignore_mode_list[i].check(arg, mc->chan, mc, si->su, si->smu)) { command_fail(si, fault_badparams, _("Invalid value \2%s\2 for mode +%c."), arg, c); return; } mowgli_strlcpy(newlock_ext[i], arg, sizeof newlock_ext[i]); newlock_ext_off[i] = false; } else { newlock_ext[i][0] = '\0'; newlock_ext_off[i] = true; } } } } } // note: the following does not treat +lk and extmodes correctly changed = ((newlock_on ^ mc->mlock_on) | (newlock_off ^ mc->mlock_off)); changed &= ~mask; /* if they're only allowed to alter oper only modes, require * them to actually change such modes -- jilles */ if (!changed && mask_ext) { command_fail(si, fault_noprivs, _("You may only alter \2+%s\2 modes."), flags_to_string(~mask)); return; } // save it to mychan, leave the modes in mask unchanged -- jilles mc->mlock_on = (newlock_on & ~mask) | (mc->mlock_on & mask); mc->mlock_off = (newlock_off & ~mask) | (mc->mlock_off & mask); if (!(mask & CMODE_LIMIT)) mc->mlock_limit = newlock_limit; if (!(mask & CMODE_KEY)) { sfree(mc->mlock_key); mc->mlock_key = *newlock_key != '\0' ? sstrdup(newlock_key) : NULL; } ext_plus[0] = '\0'; ext_minus[0] = '\0'; if (mask_ext) { md = metadata_find(mc, "private:mlockext"); if (md != NULL) { arg = md->value; while (*arg != '\0') { modebuf[0] = *arg; modebuf[1] = '\0'; mowgli_strlcat(arg[1] == ' ' || arg[1] == '\0' ? ext_minus : ext_plus, modebuf, ignore_mode_list_size + 1); arg++; while (*arg != ' ' && *arg != '\0') arg++; while (*arg == ' ') arg++; } } } else { newext[0] = '\0'; for (i = 0; i < ignore_mode_list_size; i++) { if (newlock_ext[i][0] != '\0' || newlock_ext_off[i]) { if (*newext != '\0') { modebuf[0] = ' '; modebuf[1] = '\0'; mowgli_strlcat(newext, modebuf, sizeof newext); } modebuf[0] = ignore_mode_list[i].mode; modebuf[1] = '\0'; mowgli_strlcat(newext, modebuf, sizeof newext); mowgli_strlcat(newlock_ext_off[i] ? ext_minus : ext_plus, modebuf, ignore_mode_list_size + 1); if (!newlock_ext_off[i]) mowgli_strlcat(newext, newlock_ext[i], sizeof newext); } } if (newext[0] != '\0') metadata_add(mc, "private:mlockext", newext); else metadata_delete(mc, "private:mlockext"); } end = modebuf; *end = 0; if (mc->mlock_on || mc->mlock_key || mc->mlock_limit || *ext_plus) end += snprintf(end, sizeof(modebuf) - (end - modebuf), "+%s%s%s%s", flags_to_string(mc->mlock_on), mc->mlock_key ? "k" : "", mc->mlock_limit ? "l" : "", ext_plus); if (mc->mlock_off || *ext_minus) end += snprintf(end, sizeof(modebuf) - (end - modebuf), "-%s%s%s%s", flags_to_string(mc->mlock_off), mc->mlock_off & CMODE_KEY ? "k" : "", mc->mlock_off & CMODE_LIMIT ? "l" : "", ext_minus); if (*modebuf) { command_success_nodata(si, _("The MLOCK for \2%s\2 has been set to \2%s\2."), mc->name, modebuf); logcommand(si, CMDLOG_SET, "SET:MLOCK: \2%s\2 to \2%s\2", mc->name, modebuf); verbose(mc, "\2%s\2 set the mode lock to \2%s\2", get_source_name(si), modebuf); } else { command_success_nodata(si, _("The MLOCK for \2%s\2 has been removed."), mc->name); logcommand(si, CMDLOG_SET, "SET:MLOCK:NONE: \2%s\2", mc->name); } if (changed & ircd->oper_only_modes) logcommand(si, CMDLOG_SET, "SET:MLOCK: \2%s\2 to \2%s\2 by \2%s\2", mc->name, *modebuf != '\0' ? modebuf : "+", get_oper_name(si)); check_modes(mc, true); if (mc->chan != NULL) mlock_sts(mc->chan); return; }
static void 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 ns_cmd_fungroup(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn, *mn2 = NULL; myuser_t *mu; hook_user_req_t hdata; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FUNGROUP"); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> [newaccountname]")); return; } mn = mynick_find(parv[0]); if (mn == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[0]); return; } mu = mn->owner; if (!irccasecmp(mn->nick, entity(mu)->name)) { if (MOWGLI_LIST_LENGTH(&mu->nicks) <= 1 || !module_find_published("nickserv/set_accountname")) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is an account name; you may not remove it."), mn->nick); return; } if (is_conf_soper(mu)) { command_fail(si, fault_noprivs, _("You may not modify \2%s\2's account name because their operclass is defined in the configuration file."), entity(mu)->name); return; } if (parc < 2) { command_fail(si, fault_needmoreparams, _("Please specify a new account name for \2%s\2."), entity(mu)->name); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> <newaccountname>")); return; } mn2 = mynick_find(parv[1]); if (mn2 == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[1]); return; } if (mn2 == mn) { command_fail(si, fault_noprivs, _("The new account name must be different from the nick to be ungrouped.")); return; } if (mn2->owner != mu) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is not registered to \2%s\2."), mn2->nick, entity(mu)->name); return; } } else if (parc > 1) { command_fail(si, fault_badparams, _("Nick \2%s\2 is not an account name so no new account name is needed."), mn->nick); return; } if (mn2 != NULL) { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2 (new account name: \2%s\2)", mn->nick, entity(mu)->name, mn2->nick); wallops("%s dropped the nick \2%s\2 from %s, changing account name to \2%s\2", get_oper_name(si), mn->nick, entity(mu)->name, mn2->nick); myuser_rename(mu, mn2->nick); } else { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2", mn->nick, entity(mu)->name); wallops("%s dropped the nick \2%s\2 from %s", get_oper_name(si), mn->nick, entity(mu)->name); } hdata.si = si; hdata.mu = mu; hdata.mn = mn; hook_call_nick_ungroup(&hdata); holdnick_sts(si->service->me, 0, mn->nick, NULL); if (mn2 != NULL) command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2, name changed to \2%s\2."), mn->nick, entity(mu)->name, mn2->nick); else command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2."), mn->nick, entity(mu)->name); object_unref(mn); }
/* FFLAGS <channel> <user> <flags> */ static void cs_cmd_fflags(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; const char *flagstr = parv[2]; mychan_t *mc; myentity_t *mt; unsigned int addflags, removeflags; chanacs_t *ca; hook_channel_acl_req_t req; if (parc < 3) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FFLAGS"); command_fail(si, fault_needmoreparams, _("Syntax: FFLAGS <channel> <target> <flags>")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (*flagstr == '+' || *flagstr == '-' || *flagstr == '=') { flags_make_bitmasks(flagstr, &addflags, &removeflags); if (addflags == 0 && removeflags == 0) { command_fail(si, fault_badparams, _("No valid flags given, use /%s%s HELP FLAGS for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.me->disp); return; } } else { addflags = get_template_flags(mc, flagstr); if (addflags == 0) { /* Hack -- jilles */ if (*target == '+' || *target == '-' || *target == '=') command_fail(si, fault_badparams, _("Usage: FFLAGS %s <target> <flags>"), mc->name); else command_fail(si, fault_badparams, _("Invalid template name given, use /%s%s TEMPLATE %s for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.me->disp, mc->name); return; } removeflags = ca_all & ~addflags; } if (!validhostmask(target)) { if (!(mt = myentity_find_ext(target))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not registered."), target); return; } target = mt->name; ca = chanacs_open(mc, mt, NULL, true, entity(si->smu)); /* XXX this should be more like flags.c */ if (removeflags & CA_FLAGS) removeflags |= CA_FOUNDER, addflags &= ~CA_FOUNDER; else if (addflags & CA_FOUNDER) addflags |= CA_FLAGS, removeflags &= ~CA_FLAGS; if (is_founder(mc, mt) && removeflags & CA_FOUNDER && mychan_num_founders(mc) == 1) { command_fail(si, fault_noprivs, _("You may not remove the last founder.")); return; } req.ca = ca; req.oldlevel = ca->level; if (!chanacs_modify(ca, &addflags, &removeflags, ca_all, si->smu)) { /* this shouldn't happen */ command_fail(si, fault_noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2(addflags, removeflags), mt->name, mc->name); chanacs_close(ca); return; } req.newlevel = ca->level; hook_call_channel_acl_change(&req); chanacs_close(ca); } else { if (addflags & CA_FOUNDER) { command_fail(si, fault_badparams, _("You may not set founder status on a hostmask.")); return; } ca = chanacs_open(mc, NULL, target, true, entity(si->smu)); req.ca = ca; req.oldlevel = ca->level; if (!chanacs_modify(ca, &addflags, &removeflags, ca_all, si->smu)) { /* this shouldn't happen */ command_fail(si, fault_noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2(addflags, removeflags), target, mc->name); chanacs_close(ca); return; } req.newlevel = ca->level; hook_call_channel_acl_change(&req); chanacs_close(ca); } if ((addflags | removeflags) == 0) { command_fail(si, fault_nochange, _("Channel access to \2%s\2 for \2%s\2 unchanged."), channel, target); return; } flagstr = bitmask_to_flags2(addflags, removeflags); wallops("\2%s\2 is forcing flags change \2%s\2 on \2%s\2 in \2%s\2.", get_oper_name(si), flagstr, target, mc->name); command_success_nodata(si, _("Flags \2%s\2 were set on \2%s\2 in \2%s\2."), flagstr, target, channel); logcommand(si, CMDLOG_ADMIN, "FFLAGS: \2%s\2 \2%s\2 \2%s\2", mc->name, target, flagstr); verbose(mc, "\2%s\2 forced flags change \2%s\2 on \2%s\2.", get_source_name(si), flagstr, target); }
static void ns_cmd_resetpass(sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; metadata_t *md; char *name = parv[0]; char *newpass; if (!name) { command_fail(si, fault_needmoreparams, STR_INVALID_PARAMS, "RESETPASS"); command_fail(si, fault_needmoreparams, _("Syntax: RESETPASS <account>")); 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 RESETPASS \2%s\2 (is SOPER)", name); command_fail(si, fault_badparams, _("\2%s\2 belongs to a services operator; you need %s privilege to reset the password."), name, PRIV_ADMIN); return; } if ((md = metadata_find(mu, "private:mark:setter"))) { if (has_priv(si, PRIV_MARK)) { wallops("%s reset the password for the \2MARKED\2 account %s.", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "RESETPASS: \2%s\2 (overriding mark by \2%s\2)", entity(mu)->name, md->value); command_success_nodata(si, _("Overriding MARK placed by %s on the account %s."), md->value, entity(mu)->name); } else { logcommand(si, CMDLOG_ADMIN, "failed RESETPASS \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); return; } } else { wallops("%s reset the password for the account %s", get_oper_name(si), entity(mu)->name); logcommand(si, CMDLOG_ADMIN, "RESETPASS: \2%s\2", entity(mu)->name); } newpass = random_string(12); metadata_delete(mu, "private:setpass:key"); metadata_add(mu, "private:sendpass:sender", get_oper_name(si)); metadata_add(mu, "private:sendpass:timestamp", number_to_string(time(NULL))); set_password(mu, newpass); free(newpass); command_success_nodata(si, _("The password for \2%s\2 has been changed to \2%s\2."), entity(mu)->name, newpass); 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); } }
/* ** mo_ojoin ** parv[1] = channel */ static int mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; int move_me = 0; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } if(*parv[1] == '@' || *parv[1] == '+') { parv[1]++; move_me = 1; } if((chptr = find_channel(parv[1])) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } if(IsMember(source_p, chptr)) { sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]); return 0; } if(move_me == 1) parv[1]--; sendto_wallops_flags(UMODE_WALLOP, &me, "OJOIN called for %s by %s!%s@%s", parv[1], source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p)); /* only sends stuff for #channels remotely */ sendto_server(NULL, chptr, NOCAPS, NOCAPS, ":%s WALLOPS :OJOIN called for %s by %s!%s@%s", me.name, parv[1], source_p->name, source_p->username, source_p->host); if(*parv[1] == '@') { add_user_to_channel(chptr, source_p, CHFL_CHANOP); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :@%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, chptr->chname, source_p->name); } else if(*parv[1] == '+') { add_user_to_channel(chptr, source_p, CHFL_VOICE); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s SJOIN %ld %s + :+%s", me.id, (long) chptr->channelts, chptr->chname, source_p->id); send_channel_join(chptr, source_p); sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s", me.name, chptr->chname, source_p->name); } else { add_user_to_channel(chptr, source_p, CHFL_PEON); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s JOIN %ld %s +", source_p->id, (long) chptr->channelts, chptr->chname); send_channel_join(chptr, source_p); } /* send the topic... */ if(chptr->topic != NULL) { sendto_one(source_p, form_str(RPL_TOPIC), me.name, source_p->name, chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); } source_p->localClient->last_join_time = rb_current_time(); channel_member_names(chptr, source_p, 1); return 0; }
/* parse_resv() * * inputs - source_p, NULL supported * - thing to resv * - reason * outputs - none * side effects - parse resv, create if valid */ static void parse_resv (struct Client *source_p, char *name, char *reason, int cluster) { struct ConfItem *conf; if (IsChanPrefix (*name)) { struct ResvChannel *resv_p; if ((conf = create_channel_resv (name, reason, 0)) == NULL) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A RESV has already been placed on channel: %s", me.name, source_p->name, name); return; } resv_p = (struct ResvChannel *) map_to_conf (conf); if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A %s RESV has been placed on channel: %s", me.name, source_p->name, (MyClient (source_p) ? "local" : "remote"), name); sendto_realops_flags (UMODE_ALL, L_ALL, "%s has placed a %s RESV on channel: %s [%s]", get_oper_name (source_p), (MyClient (source_p) ? "local" : "remote"), resv_p->name, resv_p->reason); write_conf_line (source_p, conf, NULL /* not used */ , 0 /* not used */ ); } else if (clean_resv_nick (name)) { struct MatchItem *resv_p; if ((strchr (name, '*') || strchr (name, '?')) && !IsAdmin (source_p)) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :You must be an admin to perform a wildcard RESV", me.name, source_p->name); return; } if ((conf = create_nick_resv (name, reason, 0)) == NULL) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A RESV has already been placed on nick: %s", me.name, source_p->name, name); return; } resv_p = (struct MatchItem *) map_to_conf (conf); if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A %s RESV has been placed on nick: %s [%s]", me.name, source_p->name, (MyClient (source_p) ? "local" : "remote"), conf->name, resv_p->reason); sendto_realops_flags (UMODE_ALL, L_ALL, "%s has placed a %s RESV on nick: %s [%s]", get_oper_name (source_p), (MyClient (source_p) ? "local" : "remote"), conf->name, resv_p->reason); write_conf_line (source_p, conf, NULL /* not used */ , 0 /* not used */ ); } else if (!cluster) sendto_one (source_p, ":%s NOTICE %s :You have specified an invalid resv: [%s]", me.name, source_p->name, name); }
static void remove_resv(struct Client *source_p, const char *name) { struct ConfItem *conf = NULL; int services = 0; if(IsServices(source_p)) services = 1; if(IsChanPrefix(*name)) { struct ResvChannel *resv_p; if(resv_channel_list.head == NULL || !(resv_p = hash_find_resv(name))) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV does not exist for channel: %s", me.name, source_p->name, name); return; } if(resv_p->conf) { if(!services) sendto_one(source_p, ":%s NOTICE %s :The RESV for channel: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } delete_channel_resv(resv_p); remove_conf_line(CRESV_TYPE, source_p, name, NULL); if(!services) { sendto_one(source_p, ":%s NOTICE %s :The RESV has been removed on channel: %s", me.name, source_p->name, name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the RESV for channel: %s", get_oper_name(source_p), name); } } else { struct MatchItem *resv_p = NULL; if((conf = find_exact_name_conf(NRESV_TYPE, name, NULL, NULL, NULL)) == NULL) { if(!services) sendto_one(source_p, ":%s NOTICE %s :A RESV does not exist for nick: %s", me.name, source_p->name, name); return; } resv_p = map_to_conf(conf); if(resv_p->action) { if(!services) sendto_one(source_p, ":%s NOTICE %s :The RESV for nick: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } delete_conf_item(conf); remove_conf_line(NRESV_TYPE, source_p, name, NULL); if(!services) { sendto_one(source_p, ":%s NOTICE %s :The RESV has been removed on nick: %s", me.name, source_p->name, name); sendto_realops_flags(UMODE_ALL, L_ALL, "%s has removed the RESV for nick: %s", get_oper_name(source_p), name); } } }
static void remove_resv (struct Client *source_p, char *name, int cluster) { struct ConfItem *conf; if (IsChanPrefix (*name)) { struct ResvChannel *resv_p; if (resv_channel_list.head == NULL || !(resv_p = hash_find_resv (name))) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A RESV does not exist for channel: %s", me.name, source_p->name, name); return; } else if (resv_p->conf) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :The RESV for channel: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } else { delete_channel_resv (resv_p); (void) remove_conf_line (CRESV_TYPE, source_p, name, NULL); if (!cluster) sendto_one (source_p, ":%s NOTICE %s :The RESV has been removed on channel: %s", me.name, source_p->name, name); sendto_realops_flags (UMODE_ALL, L_ALL, "%s has removed the RESV for channel: %s", get_oper_name (source_p), name); } } else if (clean_resv_nick (name)) { struct MatchItem *resv_p; conf = find_matching_name_conf (NRESV_TYPE, name, NULL, NULL, 0); if (conf == NULL) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :A RESV does not exist for nick: %s", me.name, source_p->name, name); return; } resv_p = (struct MatchItem *) map_to_conf (conf); if (resv_p->action) { if (!cluster) sendto_one (source_p, ":%s NOTICE %s :The RESV for nick: %s is in ircd.conf and must be removed by hand.", me.name, source_p->name, name); return; } else { delete_conf_item (conf); (void) remove_conf_line (NRESV_TYPE, source_p, name, NULL); if (!cluster) sendto_one (source_p, ":%s NOTICE %s :The RESV has been removed on nick: %s", me.name, source_p->name, name); sendto_realops_flags (UMODE_ALL, L_ALL, "%s has removed the RESV for nick: %s", get_oper_name (source_p), name); } } }
/* * mo_omode - MODE command handler * parv[1] - channel */ static int mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; char params[512]; int i; int wasonchannel; /* admins only */ if(!IsOperAdmin(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin"); return 0; } /* Now, try to find the channel in question */ if(!IsChanPrefix(parv[1][0]) || !check_channel_name(parv[1])) { sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]); return 0; } chptr = find_channel(parv[1]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } /* Now know the channel exists */ msptr = find_channel_membership(chptr, source_p); wasonchannel = msptr != NULL; if (is_any_op(msptr)) { sendto_one_notice(source_p, ":Use a normal MODE you idiot"); return 0; } params[0] = '\0'; for (i = 2; i < parc; i++) { if (i != 2) rb_strlcat(params, " ", sizeof params); rb_strlcat(params, parv[i], sizeof params); } sendto_wallops_flags(UMODE_WALLOP, &me, "OMODE called for [%s] [%s] by %s!%s@%s", parv[1], params, source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OMODE called for [%s] [%s] by %s", parv[1], params, get_oper_name(source_p)); if(*chptr->chname != '&') sendto_server(NULL, NULL, NOCAPS, NOCAPS, ":%s WALLOPS :OMODE called for [%s] [%s] by %s!%s@%s", me.name, parv[1], params, source_p->name, source_p->username, source_p->host); #if 0 set_channel_mode(client_p, source_p->servptr, chptr, msptr, parc - 2, parv + 2); #else if (parc == 4 && !strcmp(parv[2], "+y") && !irccmp(parv[3], source_p->name)) { /* Ownering themselves */ if (!wasonchannel) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname); return 0; } sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +y %s", me.name, parv[1], source_p->name); sendto_server(NULL, chptr, CAP_TS6, NOCAPS, ":%s TMODE %ld %s +y %s", me.id, (long) chptr->channelts, parv[1], source_p->id); msptr->flags |= CHFL_OWNER; } else if (parc == 4 && !strcmp(parv[2], "+a") && !irccmp(parv[3], source_p->name)) { /* Admining themselves */ if (!wasonchannel) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname); return 0; } sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s", me.name, parv[1], source_p->name); sendto_server(NULL, chptr, CAP_TS6, NOCAPS, ":%s TMODE %ld %s +a %s", me.id, (long) chptr->channelts, parv[1], source_p->id); msptr->flags |= CHFL_ADMIN; } else if (parc == 4 && !strcmp(parv[2], "+o") && !irccmp(parv[3], source_p->name)) { /* Opping themselves */ if (!wasonchannel) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname); return 0; } sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s", me.name, parv[1], source_p->name); sendto_server(NULL, chptr, CAP_TS6, NOCAPS, ":%s TMODE %ld %s +o %s", me.id, (long) chptr->channelts, parv[1], source_p->id); msptr->flags |= CHFL_CHANOP; } else if (parc == 4 && !strcmp(parv[2], "+h") && !irccmp(parv[3], source_p->name)) { /* Halfopping themselves */ if (!wasonchannel) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname); return 0; } sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s", me.name, parv[1], source_p->name); sendto_server(NULL, chptr, CAP_TS6, NOCAPS, ":%s TMODE %ld %s +h %s", me.id, (long) chptr->channelts, parv[1], source_p->id); msptr->flags |= CHFL_HALFOP; } else if (ConfigChannel.use_owner) { /* I hope this is correct. * -- Kabaka */ /* Hack it so set_channel_mode() will accept */ if (wasonchannel) msptr->flags |= CHFL_OWNER; else { add_user_to_channel(chptr, source_p, CHFL_CHANOP); msptr = find_channel_membership(chptr, source_p); } set_channel_mode(client_p, source_p, chptr, msptr, parc - 2, parv + 2); if (wasonchannel) msptr->flags &= ~CHFL_OWNER; else remove_user_from_channel(msptr); } else if (ConfigChannel.use_admin) { /* Hack it so set_channel_mode() will accept */ if (wasonchannel) msptr->flags |= CHFL_ADMIN; else { add_user_to_channel(chptr, source_p, CHFL_CHANOP); msptr = find_channel_membership(chptr, source_p); } set_channel_mode(client_p, source_p, chptr, msptr, parc - 2, parv + 2); /* We know they were not opped before and they can't have opped * themselves as set_channel_mode() does not allow that * -- jilles */ if (wasonchannel) msptr->flags &= ~CHFL_ADMIN; else remove_user_from_channel(msptr); } else { /* CHFL_ADMIN is only useful if admin is enabled * so hack it with op if it is not. */ if (wasonchannel) msptr->flags |= CHFL_CHANOP; else { add_user_to_channel(chptr, source_p, CHFL_CHANOP); msptr = find_channel_membership(chptr, source_p); } set_channel_mode(client_p, source_p, chptr, msptr, parc - 2, parv + 2); /* We know they were not opped before and they can't have opped * themselves as set_channel_mode() does not allow that * -- jilles */ if (wasonchannel) msptr->flags &= ~CHFL_CHANOP; else remove_user_from_channel(msptr); } #endif return 0; }
/* * mo_rehash - REHASH message handler * */ static void mo_rehash(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { int found = 0; if (!IsOperRehash(source_p)) { sendto_one(source_p, form_str(ERR_NOPRIVILEGES), me.name, source_p->name); return; } if (parc > 1) { if (irccmp(parv[1], "DNS") == 0) { sendto_one(source_p, form_str(RPL_REHASHING), me.name, parv[0], "DNS"); sendto_realops_flags(UMODE_ALL, L_ALL, "%s is rehashing DNS", get_oper_name(source_p)); restart_resolver(); /* re-read /etc/resolv.conf AGAIN? and close/re-open res socket */ found = 1; } else if (irccmp(parv[1], "MOTD") == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s is forcing re-reading of MOTD file", get_oper_name(source_p)); read_message_file(&ConfigFileEntry.motd); found = 1; } else if (irccmp(parv[1], "OMOTD") == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s is forcing re-reading of OPER MOTD file", get_oper_name(source_p)); read_message_file(&ConfigFileEntry.opermotd); found = 1; } if (found) { ilog(L_NOTICE, "REHASH %s From %s", parv[1], get_client_name(source_p, HIDE_IP)); return; } else { sendto_one(source_p, ":%s NOTICE %s :rehash one of :DNS MOTD OMOTD", me.name, source_p->name); return; } } else { sendto_one(source_p, form_str(RPL_REHASHING), me.name, source_p->name, ConfigFileEntry.configfile); sendto_realops_flags(UMODE_ALL, L_ALL, "%s is rehashing server config file", get_oper_name(source_p)); ilog(L_NOTICE, "REHASH From %s[%s]", get_oper_name(source_p), source_p->localClient->sockhost); rehash(0); } }