void unload_all_unused_umodes() { long removed_umode = 0; int i; aClient *cptr; for (i = 0; i < UMODETABLESZ; i++) { if (Usermode_Table[i].unloaded) removed_umode |= Usermode_Table[i].mode; } if (!removed_umode) /* Nothing was unloaded */ return; for (cptr = client; cptr; cptr = cptr->next) { long oldumode = 0; if (!IsPerson(cptr)) continue; oldumode = cptr->umodes; cptr->umodes &= ~(removed_umode); if (MyClient(cptr)) send_umode_out(cptr, cptr, oldumode); } for (i = 0; i < UMODETABLESZ; i++) { if (Usermode_Table[i].unloaded) { AllUmodes &= ~(Usermode_Table[i].mode); SendUmodes &= ~(Usermode_Table[i].mode); Usermode_Table[i].flag = '\0'; Usermode_Table[i].unloaded = 0; } } make_umodestr(); }
int m_svso(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; long fLag; if (!IsULine(sptr)) return 0; if (parc < 3) return 0; if (!(acptr = find_person(parv[1], (aClient *)NULL))) return 0; if (!MyClient(acptr)) { sendto_one(acptr, ":%s SVSO %s %s", parv[0], parv[1], parv[2]); return 0; } if (*parv[2] == '+') { int *i, flag; char *m = NULL; for (m = (parv[2] + 1); *m; m++) { for (i = oper_access; (flag = *i); i += 2) { if (*m == (char) *(i + 1)) { acptr->oflag |= flag; break; } } } } if (*parv[2] == '-') { fLag = acptr->umodes; if (IsOper(acptr) && !IsHideOper(acptr)) { IRCstats.operators--; VERIFY_OPERCOUNT(acptr, "svso"); } if (IsAnOper(acptr)) delfrom_fdlist(acptr->slot, &oper_fdlist); acptr->umodes &= ~(UMODE_OPER | UMODE_LOCOP | UMODE_HELPOP |UMODE_SERVICES | UMODE_SADMIN | UMODE_ADMIN | UMODE_COADMIN); acptr->umodes &= ~(UMODE_NETADMIN | UMODE_WHOIS); acptr->umodes &= ~(UMODE_KIX | UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM); acptr->oflag = 0; remove_oper_snomasks(acptr); RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0); send_umode_out(acptr, acptr, fLag); } return 0; }
/*! \brief Blindly opers up given source_p, using conf info. * All checks on passwords have already been done. * \param source_p Pointer to given client to oper * \param conf operator {} configuration record */ static void oper_up(struct Client *source_p, const struct MaskItem *conf) { const unsigned int old = source_p->umodes; ++Count.oper; SetOper(source_p); if (conf->modes) AddUMode(source_p, conf->modes); else if (ConfigGeneral.oper_umodes) AddUMode(source_p, ConfigGeneral.oper_umodes); if (!(old & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; else if ((old & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) --Count.invisi; assert(dlinkFind(&oper_list, source_p) == NULL); dlinkAdd(source_p, make_dlink_node(), &oper_list); AddOFlag(source_p, conf->port); if (HasOFlag(source_p, OPER_FLAG_ADMIN)) AddUMode(source_p, UMODE_ADMIN); if (!EmptyString(conf->whois)) { svstag_attach(&source_p->svstags, RPL_WHOISOPERATOR, "+", conf->whois); sendto_server(NULL, 0, 0, ":%s SVSTAG %s %ju %u + :%s", me.id, source_p->id, source_p->tsinfo, RPL_WHOISOPERATOR, conf->whois); } ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", conf->name, source_p->name, source_p->username, source_p->host); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is now an operator", get_oper_name(source_p)); sendto_server(NULL, 0, 0, ":%s GLOBOPS :%s is now an operator", me.id, get_oper_name(source_p)); send_umode_out(source_p, old); sendto_one_numeric(source_p, &me, RPL_YOUREOPER); }
void m_svscloak(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; char *hostname, *target; user_modes old; if(parc < 3 || EmptyString(parv[2])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0]); return; } target = parv[1]; hostname = parv[2]; if ((target_p= find_person(target))) { if(MyClient(target_p) && irccmp(target_p->virthost, hostname) != 0) { sendto_one(target_p, ":%s NOTICE %s :Activating Cloak: %s", me.name, target_p->name, hostname); } else sendto_server(client_p, NOCAPS, NOCAPS, ":%s SVSCLOAK %s :%s", parv[0], parv[1], parv[2]); strncpy(target_p->virthost, hostname, HOSTLEN); CopyUmodes(old, target_p->umodes); SetUmode(target_p, UMODE_CLOAK); send_umode_out(target_p, target_p, &old); target_p->flags |= FLAGS_USERCLOAK; /* set the usercloak flag so that in the * future, the server will burst the new vhost * in case of netsplit. * --nenolod */ off_history(target_p); } else { sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, target); return; } return; }
/* * m_sethost - generic message handler * * mimic old lain syntax: * * (Oper) /SETHOST ident host.cc [quit-message] * (User) /SETHOST host.cc password * (Both) /SETHOST undo * * check for undo, prepend parv w. <nick> -h or +h */ int m_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char hostmask[512]; struct Flags setflags; /* Back up the flags first */ setflags = cli_flags(sptr); if (parc < 2) return need_more_params(sptr, "SETHOST"); if (0 == ircd_strcmp("undo", parv[1])) { set_hostmask(sptr, sptr, NULL, NULL); } else { if (parc<3) return need_more_params(sptr, "SETHOST"); if (IsAnOper(sptr)) { ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 1, "%s@%s", parv[1], parv[2]); if (!is_hostmask(hostmask)) { send_reply(sptr, ERR_BADHOSTMASK, hostmask); return 0; } if (set_hostmask(sptr, sptr, hostmask, NULL)) FlagClr(&setflags, FLAG_SETHOST); } else { if (!is_hostmask(parv[1])) { send_reply(sptr, ERR_BADHOSTMASK, parv[1]); return 0; } if (set_hostmask(sptr, sptr, parv[1], parv[2])) FlagClr(&setflags, FLAG_SETHOST); } } send_umode_out(cptr, sptr, &setflags, 0); return 0; }
void UmodeDel(Umode *umode) { if (loop.ircd_rehashing) umode->unloaded = 1; else { aClient *cptr; for (cptr = client; cptr; cptr = cptr->next) { long oldumode = 0; if (!IsPerson(cptr)) continue; oldumode = cptr->umodes; cptr->umodes &= ~umode->mode; if (MyClient(cptr)) send_umode_out(cptr, cptr, oldumode); } umode->flag = '\0'; AllUmodes &= ~(umode->mode); SendUmodes &= ~(umode->mode); make_umodestr(); } if (umode->owner) { ModuleObject *umodeobj; for (umodeobj = umode->owner->objects; umodeobj; umodeobj = umodeobj->next) { if (umodeobj->type == MOBJ_UMODE && umodeobj->object.umode == umode) { DelListItem(umodeobj, umode->owner->objects); MyFree(umodeobj); break; } } umode->owner = NULL; } return; }
int m_challenge(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { #ifdef USE_SSL struct ConfItem *aconf; RSA *rsa_public_key; BIO *file = NULL; char *challenge = NULL; char *name; char *tmpname; char chan[CHANNELLEN-1]; char* join[2]; int nl; struct Flags old_mode = cli_flags(sptr); if (!MyUser(sptr)) return 0; if (parc < 2) return need_more_params(sptr, "CHALLENGE"); if (parc > 2) { /* This is a remote OPER Request */ struct Client *srv; if (!string_has_wildcards(parv[1])) srv = FindServer(parv[1]); else srv = find_match_server(parv[1]); if (!feature_bool(FEAT_REMOTE_OPER)) return send_reply(sptr, ERR_NOOPERHOST); if (!srv) return send_reply(sptr, ERR_NOOPERHOST); if (IsMe(srv)) { parv[1] = parv[2]; } else { sendcmdto_one(sptr, CMD_CHALLENGE, srv, "%C %s", srv, parv[2]); return 0; } } /* if theyre an oper, reprint oper motd and ignore */ if (IsOper(sptr)) { send_reply(sptr, RPL_YOUREOPER); if (feature_bool(FEAT_OPERMOTD)) m_opermotd(sptr, sptr, 1, parv); } if (*parv[1] == '+') { /* Ignore it if we aren't expecting this... -A1kmm */ if (cli_user(sptr)->response == NULL) return 0; if (ircd_strcmp(cli_user(sptr)->response, ++parv[1])) { send_reply(sptr, ERR_PASSWDMISMATCH); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (Password Incorrect)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); tmpname = strdup(cli_user(sptr)->auth_oper); failed_challenge_notice(sptr, tmpname, "challenge failed"); return 0; } name = strdup(cli_user(sptr)->auth_oper); aconf = find_conf_exact(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, MyUser(sptr) ? cli_sockhost(sptr) : cli_user(sptr)->realhost, CONF_OPS); if (!aconf) aconf = find_conf_exact(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, ircd_ntoa((const char*) &(cli_ip(sptr))), CONF_OPS); if (!aconf) aconf = find_conf_cidr(cli_user(sptr)->auth_oper, cli_user(sptr)->realusername, cli_ip(sptr), CONF_OPS); if (!aconf) { send_reply(sptr, ERR_NOOPERHOST); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (No O:line)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); return 0; } if (CONF_LOCOP == aconf->status) { ClearOper(sptr); SetLocOp(sptr); } else { /* * prevent someone from being both oper and local oper */ ClearLocOp(sptr); if (!feature_bool(FEAT_OPERFLAGS) || !(aconf->port & OFLAG_ADMIN)) { /* Global Oper */ SetOper(sptr); ClearAdmin(sptr); } else { /* Admin */ SetOper(sptr); OSetGlobal(sptr); SetAdmin(sptr); } ++UserStats.opers; } cli_handler(cptr) = OPER_HANDLER; if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_WHOIS)) { OSetWhois(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_IDLE)) { OSetIdle(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_XTRAOP)) { OSetXtraop(sptr); } if (!feature_bool(FEAT_OPERFLAGS) || (aconf->port & OFLAG_HIDECHANS)) { OSetHideChans(sptr); } SetFlag(sptr, FLAG_WALLOP); SetFlag(sptr, FLAG_SERVNOTICE); SetFlag(sptr, FLAG_DEBUG); if (!IsAdmin(sptr)) cli_oflags(sptr) = aconf->port; set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD); client_set_privs(sptr, aconf); cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */ send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); send_reply(sptr, RPL_YOUREOPER); if (IsAdmin(sptr)) { sendto_allops(&me, SNO_OLDSNO, "%s (%s@%s) is now an IRC Administrator", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); /* Autojoin admins to admin channel and oper channel (if enabled) */ if (feature_bool(FEAT_AUTOJOIN_ADMIN)) { if (feature_bool(FEAT_AUTOJOIN_ADMIN_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_ADMIN_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_ADMIN_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } if (feature_bool(FEAT_AUTOJOIN_OPER) && IsOper(sptr)) { if (feature_bool(FEAT_AUTOJOIN_OPER_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_OPER_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_OPER_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } } else { sendto_allops(&me, SNO_OLDSNO, "%s (%s@%s) is now an IRC Operator (%c)", parv[0], cli_user(sptr)->username, cli_sockhost(sptr), IsOper(sptr) ? 'O' : 'o'); if (feature_bool(FEAT_AUTOJOIN_OPER) && IsOper(sptr)) { if (feature_bool(FEAT_AUTOJOIN_OPER_NOTICE)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, feature_str(FEAT_AUTOJOIN_OPER_NOTICE_VALUE)); ircd_strncpy(chan, feature_str(FEAT_AUTOJOIN_OPER_CHANNEL), CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; m_join(sptr, sptr, 2, join); } } if (feature_bool(FEAT_OPERMOTD)) m_opermotd(sptr, sptr, 1, parv); log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", name, sptr); ircd_snprintf(0, cli_user(sptr)->response, BUFSIZE+1, "%s", ""); return 0; } ircd_snprintf(0, cli_user(sptr)->response, BUFSIZE+1, "%s", ""); ircd_snprintf(0, cli_user(sptr)->auth_oper, NICKLEN+1, "%s", ""); aconf = find_conf_exact(parv[1], cli_user(sptr)->realusername, cli_user(sptr)->realhost, CONF_OPS); if (!aconf) aconf = find_conf_exact(parv[1], cli_user(sptr)->realusername, ircd_ntoa((const char*) &(cli_ip(sptr))), CONF_OPS); if (!aconf) aconf = find_conf_cidr(parv[1], cli_user(sptr)->realusername, cli_ip(sptr), CONF_OPS); if (aconf == NULL) { send_reply(sptr, ERR_NOOPERHOST); failed_challenge_notice(sptr, parv[1], "No o:line"); sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (No O:line)", parv[0], cli_user(sptr)->realusername, cli_sockhost(sptr)); return 0; } if (!(aconf->port & OFLAG_RSA)) { send_reply(sptr, RPL_NO_CHALL); return 0; } if (!verify_sslclifp(sptr, aconf)) { sendto_allops(&me, SNO_OLDREALOP, "Failed OPER attempt by %s (%s@%s) (SSL Fingerprint Missmatch)", parv[0], cli_user(sptr)->realusername, cli_user(sptr)->realhost); send_reply(sptr, ERR_SSLCLIFP); return 0; } if ((file = BIO_new_file(aconf->passwd, "r")) == NULL) { send_reply(sptr, RPL_NO_KEY); return 0; } rsa_public_key = (RSA *)PEM_read_bio_RSA_PUBKEY(file, NULL, 0, NULL); if (rsa_public_key == NULL) return send_reply(sptr, RPL_INVALID_KEY); if (!generate_challenge(&challenge, rsa_public_key, sptr)) { Debug((DEBUG_DEBUG, "generating challenge sum (%s)", challenge)); send_reply(sptr, RPL_RSACHALLENGE, challenge); ircd_snprintf(0, cli_user(sptr)->auth_oper, NICKLEN + 1, "%s", aconf->name); } nl = BIO_set_close(file, BIO_CLOSE); BIO_free(file); return 1; #else return 1; #endif }
/* * m_oper - generic message handler */ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct ConfItem* aconf; char* name; char* password; assert(0 != cptr); assert(cptr == sptr); name = parc > 1 ? parv[1] : 0; password = parc > 2 ? parv[2] : 0; if (EmptyString(name) || EmptyString(password)) return need_more_params(sptr, "OPER"); aconf = find_conf_exact(name, sptr, CONF_OPERATOR); if (!aconf || IsIllegal(aconf)) { send_reply(sptr, ERR_NOOPERHOST); sendto_opmask_butone(0, SNO_OLDREALOP, "Failed staff authentication attempt by %s (%s@%s)", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); return 0; } assert(0 != (aconf->status & CONF_OPERATOR)); if (oper_password_match(password, aconf->passwd)) { struct Flags old_mode = cli_flags(sptr); if (ACR_OK != attach_conf(sptr, aconf)) { send_reply(sptr, ERR_NOOPERHOST); sendto_opmask_butone(0, SNO_OLDREALOP, "Failed staff authentication attempt by %s " "(%s@%s)", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); return 0; } SetLocOp(sptr); client_set_privs(sptr, aconf); if (HasPriv(sptr, PRIV_PROPAGATE)) { ClearLocOp(sptr); SetOper(sptr); ++UserStats.opers; } cli_handler(cptr) = OPER_HANDLER; SetFlag(sptr, FLAG_WALLOP); SetFlag(sptr, FLAG_SERVNOTICE); SetFlag(sptr, FLAG_DEBUG); set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD); cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */ send_umode_out(cptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); send_reply(sptr, RPL_YOUREOPER); sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) has authenticated as staff", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", name, sptr); } else { send_reply(sptr, ERR_PASSWDMISMATCH); sendto_opmask_butone(0, SNO_OLDREALOP, "Failed staff authentication attempt by %s (%s@%s)", parv[0], cli_user(sptr)->username, cli_sockhost(sptr)); } return 0; }
/* mo_flags() * * parv[0] = sender prefix * parv[1] = parameter */ static void mo_flags(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { int i,j; int isadd; int isgood; unsigned int setflags; char *p; char *flag; if (parc < 2) { /* Generate a list of what flags you have and what you are missing, ** and send it to the user */ sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); return; } /* Preserve the current flags */ setflags = source_p->umodes; /* XXX - change this to support a multiple last parameter like ISON */ for (i = 1; i < parc; i++) { for (flag = strtoken(&p, parv[i], " "); flag; flag = strtoken(&p, NULL, " ")) { /* We default to being in ADD mode */ isadd = 1; /* We default to being in BAD mode */ isgood = 0; if (!isalpha(*flag)) { if (*flag == '-') isadd = 0; else if (*flag == '+') isadd = 1; ++flag; } /* support ALL here */ if (!irccmp(flag, "ALL")) { if (isadd) source_p->umodes |= FL_ALL_OPER_FLAGS; else source_p->umodes &= ~FL_ALL_OPER_FLAGS; sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); send_umode_out(client_p, source_p, setflags); return; } if (!irccmp(flag, "NICKCHANGES")) { if (!IsOperN(source_p)) { sendto_one(source_p, ":%s NOTICE %s :*** You have no nick_changes flag;", me.name,parv[0]); continue; } if (isadd) source_p->umodes |= UMODE_NCHANGE; else source_p->umodes &= ~UMODE_NCHANGE; isgood = 1; continue; } for (j = 0; flag_table[j].name; j++) { if (!irccmp(flag, flag_table[j].name)) { if (isadd) source_p->umodes |= flag_table[j].mode; else source_p->umodes &= ~ (flag_table[j].mode); isgood = 1; continue; } } /* This for ended without matching a valid FLAG, here is where * I want to operate differently than ircd-comstud, and just ignore * the invalid flag, send a warning and go on. */ if (!isgood) sendto_one(source_p, ":%s NOTICE %s :Invalid FLAGS: %s (IGNORING)", me.name, parv[0], flag); } } /* All done setting the flags, print the notices out to the user ** telling what flags they have and what flags they are missing */ sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); send_umode_out(client_p, source_p, setflags); }
/* set_user_mode() * * added 15/10/91 By Darren Reed. * parv[0] - command * parv[1] - username to change mode for * parv[2] - modes to change */ static void set_user_mode(struct Client *source_p, const int parc, char *parv[]) { const struct user_modes *tab = NULL; const unsigned int setmodes = source_p->umodes; const struct Client *target_p = NULL; int what = MODE_ADD, badmode = 0; if ((target_p = find_person(source_p, parv[1])) == NULL) { if (MyConnect(source_p)) sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]); return; } if (source_p != target_p) { sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH); return; } if (parc < 3) { char buf[IRCD_BUFSIZE] = ""; char *m = buf; *m++ = '+'; for (tab = umode_tab; tab->c; ++tab) if (HasUMode(source_p, tab->flag)) *m++ = tab->c; *m = '\0'; sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf); return; } /* Parse user mode change string */ for (const char *m = parv[2]; *m; ++m) { switch (*m) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; case 'o': if (what == MODE_ADD) { if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER)) { ++Count.oper; SetOper(source_p); } } else { if (!HasUMode(source_p, UMODE_OPER)) break; ClearOper(source_p); --Count.oper; if (MyConnect(source_p)) { dlink_node *node = NULL; detach_conf(source_p, CONF_OPER); ClrOFlag(source_p); DelUMode(source_p, ConfigGeneral.oper_only_umodes); if ((node = dlinkFindDelete(&oper_list, source_p))) free_dlink_node(node); } } break; case 'S': /* Only servers may set +S in a burst */ case 'W': /* Only servers may set +W in a burst */ case 'r': /* Only services may set +r */ case 'x': /* Only services may set +x */ break; default: if ((tab = umode_map[(unsigned char)*m])) { if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) && (ConfigGeneral.oper_only_umodes & tab->flag)) badmode = 1; else { if (what == MODE_ADD) AddUMode(source_p, tab->flag); else DelUMode(source_p, tab->flag); } } else if (MyConnect(source_p)) badmode = 1; break; } } if (badmode) sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG); if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) && !HasOFlag(source_p, OPER_FLAG_ADMIN)) { sendto_one_notice(source_p, &me, ":*** You have no admin flag;"); DelUMode(source_p, UMODE_ADMIN); } if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) --Count.invisi; /* * Compare new modes with old modes and send string which will cause * servers to update correctly. */ send_umode_out(source_p, setmodes); }
/* ** m_flags ** parv[0] = sender prefix ** parv[1] = parameter */ static int m_flags(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { int i, j; int isadd; int setflags; int isgood; char *p; char *flag; if(parc < 2) { /* Generate a list of what flags you have and what you are missing, ** and send it to the user */ sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); return 1; } /* Preserve the current flags */ setflags = source_p->umodes; /* XXX - change this to support a multiple last parameter like ISON */ for(i = 1; i < parc; i++) { char *s = LOCAL_COPY(parv[i]); for(flag = strtok_r(s, " ", &p); flag; flag = strtok_r(NULL, " ", &p)) { /* We default to being in ADD mode */ isadd = 1; /* We default to being in BAD mode */ isgood = 0; if(!isalpha(flag[0])) { if(flag[0] == '-') isadd = 0; else if(flag[0] == '+') isadd = 1; flag++; } /* support ALL here */ if(!irccmp(flag, "ALL")) { if(isadd) source_p->umodes |= FL_ALL_USER_FLAGS; else source_p->umodes &= ~FL_ALL_USER_FLAGS; sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); send_umode_out(client_p, source_p, setflags); return 1; } for(j = 0; flag_table[j].name; j++) { if(!flag_table[j].oper && !irccmp(flag, flag_table[j].name)) { if(isadd) source_p->umodes |= flag_table[j].mode; else source_p->umodes &= ~(flag_table[j].mode); isgood = 1; continue; } } /* This for ended without matching a valid FLAG, here is where ** I want to operate differently than ircd-comstud, and just ignore ** the invalid flag, send a warning and go on. */ if(!isgood) sendto_one(source_p, ":%s NOTICE %s :Invalid FLAGS: %s (IGNORING)", me.name, parv[0], flag); } } /* All done setting the flags, print the notices out to the user ** telling what flags they have and what flags they are missing */ sendto_one(source_p, ":%s NOTICE %s :Current flags:%s", me.name, parv[0], set_flags_to_string(source_p)); sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s", me.name, parv[0], unset_flags_to_string(source_p)); send_umode_out(client_p, source_p, setflags); return 0; }
void do_oper(struct Client* cptr, struct Client* sptr, struct ConfItem* aconf) { struct Flags old_mode = cli_flags(sptr); char* modes; char* parv[2]; char* join[3]; char chan[CHANNELLEN-1]; char* ajoinchan; char* ajoinnotice; unsigned int snomask = 0; parv[0] = cli_name(sptr); parv[1] = NULL; SetOper(sptr); client_set_privs(sptr, aconf); ClearOper(sptr); snomask = ConfSnoMask(aconf) & SNO_ALL; snomask |= aconf->snomask & SNO_ALL; ajoinchan = ConfAjoinChan(aconf); ajoinnotice = ConfAjoinNotice(aconf); if (MyUser(sptr)) { SetLocOp(sptr); if (HasPriv(sptr, PRIV_PROPAGATE)) { ClearLocOp(sptr); SetOper(sptr); if (HasPriv(sptr, PRIV_ADMIN)) SetAdmin(sptr); if (!IsHideOper(sptr) && !IsChannelService(sptr) && !IsBot(sptr)) ++UserStats.opers; } cli_handler(sptr) = OPER_HANDLER; SetFlag(sptr, FLAG_WALLOP); SetFlag(sptr, FLAG_SERVNOTICE); SetFlag(sptr, FLAG_DEBUG); if (snomask) set_snomask(sptr, snomask, SNO_ADD); else set_snomask(sptr, feature_int(FEAT_SNOMASK_OPERDEFAULT), SNO_ADD); cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */ cli_max_recvq(sptr) = 0; /* Get the recvq from the oper's class */ cli_lag_min(sptr) = -2; /* Get the fake lag minimum from the oper's class */ cli_lag_factor(sptr) = -2; /* Get the fake lag factor from the oper's class */ send_umode_out(sptr, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); } else { client_send_privs(&me, sptr, sptr); if (HasPriv(sptr, PRIV_PROPAGATE)) { modes = (HasPriv(sptr, PRIV_ADMIN) ? "aowsg" : "owsg"); } else { modes = "Owsg"; } sendcmdto_one(&me, CMD_MODE, sptr, "%s %s", cli_name(sptr), modes); } modes = ConfUmode(aconf); if (modes) { if (MyUser(sptr)) { char *umodev[] = { NULL, NULL, NULL, NULL }; umodev[1] = cli_name(sptr); umodev[2] = modes; old_mode = cli_flags(sptr); set_user_mode(sptr, sptr, 3, umodev, ALLOWMODES_ANY); send_umode(NULL, sptr, &old_mode, HasPriv(sptr, PRIV_PROPAGATE)); if ((cli_snomask(sptr) != feature_int(FEAT_SNOMASK_OPERDEFAULT)) && HasFlag(sptr, FLAG_SERVNOTICE)) send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr)); } else { if (snomask) sendcmdto_one(&me, CMD_MODE, sptr, "%s %s+s +%d", cli_name(sptr), modes, snomask); else sendcmdto_one(&me, CMD_MODE, sptr, "%s %s", cli_name(sptr), modes); } } send_reply(sptr, RPL_YOUREOPER); if ((feature_int(FEAT_HOST_HIDING_STYLE) == 1) || (feature_int(FEAT_HOST_HIDING_STYLE) == 3)) hide_hostmask(sptr); if (!EmptyString(ajoinchan)) { if (!EmptyString(ajoinnotice)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, ajoinnotice); ircd_strncpy(chan, ajoinchan, CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; join[2] = NULL; m_join(sptr, sptr, 2, join); } if (!EmptyString(aconf->autojoinchan)) { if (!EmptyString(aconf->autojoinnotice)) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s", sptr, aconf->autojoinnotice); ircd_strncpy(chan, aconf->autojoinchan, CHANNELLEN-1); join[0] = cli_name(sptr); join[1] = chan; join[2] = NULL; m_join(sptr, sptr, 2, join); } sendto_opmask_butone_global((MyUser(sptr) ? &me : NULL), SNO_OLDSNO, "%s (%s@%s) is now operator (%c)", cli_name(sptr), cli_user(sptr)->username, cli_user(sptr)->realhost, IsOper(sptr) ? 'O' : 'o'); if (feature_bool(FEAT_OPERMOTD)) m_opermotd(sptr, sptr, 1, parv); log_write(LS_OPER, L_INFO, 0, "OPER (%s) by (%#C)", aconf->name, sptr); }