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; }
static void make_who_status(aClient *sptr, aClient *acptr, aChannel *channel, Member *cm, char *status, int cansee) { int i = 0; if (acptr->user->away) status[i++] = 'G'; else status[i++] = 'H'; if (IsARegNick(acptr)) status[i++] = 'r'; if (acptr->umodes & UMODE_BOT) status[i++] = 'B'; if (IsAnOper(acptr) && (!IsHideOper(acptr) || sptr == acptr || IsAnOper(sptr))) status[i++] = '*'; if (IsAnOper(acptr) && (IsHideOper(acptr) && sptr != acptr && IsAnOper(sptr))) status[i++] = '!'; if (cansee & WHO_OPERSEE) status[i++] = '?'; if (cm) { #ifdef PREFIX_AQ if (cm->flags & CHFL_CHANOWNER) status[i++] = '~'; else if (cm->flags & CHFL_CHANPROT) status[i++] = '&'; else #endif if (cm->flags & CHFL_CHANOP) status[i++] = '@'; else if (cm->flags & CHFL_HALFOP) status[i++] = '%'; else if (cm->flags & CHFL_VOICE) status[i++] = '+'; } status[i] = '\0'; }
/* * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce * the need for complicated requests like WHOIS. It returns user/host * information only (no spurious AWAY labels or channels). * Re-written by Dianora 1999 */ DLLFUNC CMD_FUNC(m_userhost) { char *p; /* scratch end pointer */ char *cn; /* current name */ struct Client *acptr; char response[5][NICKLEN * 2 + CHANNELLEN + USERLEN + HOSTLEN + 30]; int i; /* loop counter */ if (parc < 2) { sendto_one(sptr, rpl_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERHOST"); return 0; } /* The idea is to build up the response string out of pieces * none of this strlen() nonsense. * 5 * (NICKLEN*2+CHANNELLEN+USERLEN+HOSTLEN+30) is still << sizeof(buf) * and our ircsprintf() truncates it to fit anyway. There is * no danger of an overflow here. -Dianora */ response[0][0] = response[1][0] = response[2][0] = response[3][0] = response[4][0] = '\0'; cn = parv[1]; for (i = 0; (i < 5) && cn; i++) { if ((p = strchr(cn, ' '))) *p = '\0'; if ((acptr = find_person(cn, NULL))) { ircsprintf(response[i], "%s%s=%c%s@%s", acptr->name, (IsAnOper(acptr) && (!IsHideOper(acptr) || sptr == acptr || IsAnOper(sptr))) ? "*" : "", (acptr->user->away) ? '-' : '+', acptr->user->username, ((acptr != sptr) && !IsOper(sptr) && IsHidden(acptr) ? acptr->user->virthost : acptr->user->realhost)); } if (p) p++; cn = p; } sendto_one(sptr, rpl_str(RPL_USERHOST), me.name, parv[0], response[0], response[1], response[2], response[3], response[4]); return 0; }
static int can_see(aClient *sptr, aClient *acptr, aChannel *channel) { int ret = 0; char has_common_chan = 0; do { /* can only see people */ if (!IsPerson(acptr)) return WHO_CANTSEE; /* can only see opers if thats what they want */ if (who_flags & WF_OPERONLY) { if (!IsAnOper(acptr)) return ret | WHO_CANTSEE; if (IsHideOper(acptr)) { if (IsAnOper(sptr)) ret |= WHO_OPERSEE; else return ret | WHO_CANTSEE; } } /* if they only want people who are away */ if ((wfl.want_away == WHO_WANT && !acptr->user->away) || (wfl.want_away == WHO_DONTWANT && acptr->user->away)) return WHO_CANTSEE; /* if they only want people on a certain channel. */ if (wfl.want_channel != WHO_DONTCARE) { aChannel *chan = find_channel(wfl.channel, NULL); if (!chan && wfl.want_channel == WHO_WANT) return WHO_CANTSEE; if ((wfl.want_channel == WHO_WANT) && !IsMember(acptr, chan)) return WHO_CANTSEE; if ((wfl.want_channel == WHO_DONTWANT) && IsMember(acptr, chan)) return WHO_CANTSEE; } /* if they only want people with a certain gecos */ if (wfl.want_gecos != WHO_DONTCARE) { if (((wfl.want_gecos == WHO_WANT) && match(wfl.gecos, acptr->info)) || ((wfl.want_gecos == WHO_DONTWANT) && !match(wfl.gecos, acptr->info))) { return WHO_CANTSEE; } } /* if they only want people with a certain server */ if (wfl.want_server != WHO_DONTCARE) { if (((wfl.want_server == WHO_WANT) && stricmp(wfl.server, acptr->user->server)) || ((wfl.want_server == WHO_DONTWANT) && !stricmp(wfl.server, acptr->user->server))) { return WHO_CANTSEE; } } /* if they only want people with a certain host */ if (wfl.want_host != WHO_DONTCARE) { char *host; if (IsAnOper(sptr)) host = acptr->user->realhost; else host = GetHost(acptr); if (((wfl.want_host == WHO_WANT) && match(wfl.host, host)) || ((wfl.want_host == WHO_DONTWANT) && !match(wfl.host, host))) { return WHO_CANTSEE; } } /* if they only want people with a certain IP */ if (wfl.want_ip != WHO_DONTCARE) { char *ip; ip = acptr->user->ip_str; if (!ip) return WHO_CANTSEE; if (((wfl.want_ip == WHO_WANT) && match(wfl.ip, ip)) || ((wfl.want_ip == WHO_DONTWANT) && !match(wfl.ip, ip))) { return WHO_CANTSEE; } } /* if they only want people with a certain nick.. */ if (wfl.want_nick != WHO_DONTCARE) { if (((wfl.want_nick == WHO_WANT) && match(wfl.nick, acptr->name)) || ((wfl.want_nick == WHO_DONTWANT) && !match(wfl.nick, acptr->name))) { return WHO_CANTSEE; } } /* if they only want people with a certain username */ if (wfl.want_user != WHO_DONTCARE) { if (((wfl.want_user == WHO_WANT) && match(wfl.user, acptr->user->username)) || ((wfl.want_user == WHO_DONTWANT) && !match(wfl.user, acptr->user->username))) { return WHO_CANTSEE; } } /* if they only want people with a certain umode */ if (wfl.umodes_want) { if (!(acptr->umodes & wfl.umodes_want) || (!IsAnOper(sptr) && (acptr->umodes & UMODE_HIDEOPER))) return WHO_CANTSEE; } if (wfl.umodes_dontwant) { if ((acptr->umodes & wfl.umodes_dontwant) && (!(acptr->umodes & UMODE_HIDEOPER) || IsAnOper(sptr))) return WHO_CANTSEE; } /* if they only want common channels */ if (wfl.common_channels_only) { if (!has_common_channels(sptr, acptr)) return WHO_CANTSEE; has_common_chan = 1; } if (channel) { int member = who_flags & WF_ONCHANNEL; if (SecretChannel(channel) || HiddenChannel(channel)) { /* if they aren't on it.. they can't see it */ if (!(who_flags & WF_ONCHANNEL)) break; } if (IsInvisible(acptr) && !member) break; if ((channel->mode.mode & MODE_AUDITORIUM) && !is_chan_op(acptr, channel) && !is_chan_op(sptr, channel)) break; } else { /* a user/mask who */ /* If the common channel info hasn't been set, set it now */ if (!wfl.common_channels_only) has_common_chan = has_common_channels(sptr, acptr); if (IsInvisible(acptr) && !has_common_chan) { /* don't show them unless it's an exact match or it is the user requesting the /who */ if ((who_flags & WF_WILDCARD) && sptr != acptr) break; } } /* phew.. show them. */ return WHO_CANSEE; } while (0); /* if we get here, it's oper-dependant. */ if (IsAnOper(sptr)) return ret | WHO_OPERSEE | WHO_CANSEE; else { if (sptr == acptr) return ret | WHO_CANSEE; else return ret | WHO_CANTSEE; } }
/* * m_userip is based on m_userhost * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce * the need for complicated requests like WHOIS. It returns user/host * information only (no spurious AWAY labels or channels). * Re-written by Dianora 1999 */ DLLFUNC CMD_FUNC(m_userip) { char *p; /* scratch end pointer */ char *cn; /* current name */ char *ip, ipbuf[HOSTLEN+1]; struct Client *acptr; char response[5][NICKLEN * 2 + CHANNELLEN + USERLEN + HOSTLEN + 30]; int i; /* loop counter */ if (!MyClient(sptr)) return -1; if (parc < 2) { sendto_one(sptr, rpl_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERIP"); return 0; } /* The idea is to build up the response string out of pieces * none of this strlen() nonsense. * 5 * (NICKLEN*2+CHANNELLEN+USERLEN+HOSTLEN+30) is still << sizeof(buf) * and our ircsprintf() truncates it to fit anyway. There is * no danger of an overflow here. -Dianora */ response[0][0] = response[1][0] = response[2][0] = response[3][0] = response[4][0] = '\0'; cn = parv[1]; for (i = 0; (i < 5) && cn; i++) { if ((p = strchr(cn, ' '))) *p = '\0'; if ((acptr = find_person(cn, NULL))) { if (!(ip = GetIP(acptr))) ip = "<unknown>"; if (sptr != acptr && !IsOper(sptr) && IsHidden(acptr)) { make_virthost(acptr, GetIP(acptr), ipbuf, 0); ip = ipbuf; } ircsprintf(response[i], "%s%s=%c%s@%s", acptr->name, (IsAnOper(acptr) && (!IsHideOper(acptr) || sptr == acptr || IsAnOper(sptr))) ? "*" : "", (acptr->user->away) ? '-' : '+', acptr->user->username, ip); /* add extra fakelag (penalty) because of all the work we need to do: 1s per entry: */ sptr->since += 1; } if (p) p++; cn = p; } sendto_one(sptr, rpl_str(RPL_USERIP), me.name, parv[0], response[0], response[1], response[2], response[3], response[4]); return 0; }
/* ** m_ircops() By Claudio ** Rewritten by HAMLET ** Lists online IRCOps ** */ int m_ircops(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *acptr; char *status; char buf[BUFSIZE]; int locals = 0, globals = 0; if (!IRCopsForAll && !IsPrivileged(cptr)) { sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } strcpy(buf, "========================================================================================"); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); strcpy(buf, "\2Nick Status Server\2"); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); strcpy(buf, "----------------------------------------------------------------------------------------"); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); for (acptr = GlobalClientList; acptr; acptr = acptr->next) { if (!IsService(acptr) && !IsStealth(acptr) && IsAnOper(acptr) && (!IsHideOper(acptr) || IsAnOper(sptr)) ) { if (!acptr->user) continue; if (IsTechAdmin(acptr)) status = "Technical Administrator"; else if (IsNetAdmin(acptr)) status = "Network Administrator"; else if (IsSAdmin(acptr)) status = "Services Administrator"; else if (IsAdmin(acptr)) status = "Server Administrator"; else if(IsOper(acptr)) status = "Global IRC Operator"; else status = "Local IRC Operator"; /* vlinks on /IRCops * code by openglx * idea to this by Midnight_Commander */ if (acptr->user && acptr->user->vlink) { ircsprintf(buf, "\2%-29s\2 %-23s %-6s %s", acptr->name ? acptr->name : "<unknown>", status, acptr->user->away ? "(AWAY)" : "", acptr->user->vlink->name); } else { ircsprintf(buf, "\2%-29s\2 %-23s %-6s %s", acptr->name ? acptr->name : "<unknown>", status, acptr->user->away ? "(AWAY)" : "", acptr->user->server); } /* end of the vlink support code */ sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], "-"); if (IsOper(acptr)) globals++; else locals++; } } ircsprintf(buf, "Total: \2%d\2 IRCOp%s connected - \2%d\2 Globa%s, \2%d\2 Loca%s", globals+locals, (globals+locals) > 1 ? "s" : "", globals, globals > 1 ? "ls" : "l", locals, locals > 1 ? "ls" : "l"); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); strcpy(buf, "========================================================================================"); sendto_one(sptr, form_str(RPL_LISTS), me.name, parv[0], buf); sendto_one(sptr, form_str(RPL_ENDOFLISTS), me.name, parv[0], "IRCOPS"); return 0; }
/* ** m_whois ** parv[0] = sender prefix ** parv[1] = nickname masklist */ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Membership *lp; anUser *user; aClient *acptr, *a2cptr; aChannel *chptr; char *nick, *tmp, *name; char *p = NULL; int found, len, mlen, cnt = 0; char querybuf[BUFSIZE]; if (IsServer(sptr)) return 0; if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (parc > 2) { if (hunt_server(cptr, sptr, ":%s WHOIS %s :%s", 1, parc, parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } strcpy(querybuf, parv[1]); for (tmp = canonize(parv[1]); (nick = strtok_r(tmp, ",", &p)); tmp = NULL) { unsigned char invis, showchannel, member, wilds, hideoper; /* <- these are all boolean-alike */ if (++cnt > MAXTARGETS) break; found = 0; /* We do not support "WHOIS *" */ wilds = (index(nick, '?') || index(nick, '*')); if (wilds) continue; if ((acptr = find_client(nick, NULL))) { if (IsServer(acptr)) continue; /* * I'm always last :-) and acptr->next == NULL!! */ if (IsMe(acptr)) break; /* * 'Rules' established for sending a WHOIS reply: * - only send replies about common or public channels * the target user(s) are on; */ if (!IsPerson(acptr)) continue; user = acptr->user; name = (!*acptr->name) ? "?" : acptr->name; invis = acptr != sptr && IsInvisible(acptr); member = (user->channel) ? 1 : 0; a2cptr = find_server_quick(user->server); hideoper = 0; if (IsHideOper(acptr) && (acptr != sptr) && !IsAnOper(sptr)) hideoper = 1; if (IsWhois(acptr) && (sptr != acptr)) { sendnotice(acptr, "*** %s (%s@%s) did a /whois on you.", sptr->name, sptr->user->username, sptr->user->realhost); } sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, parv[0], name, user->username, IsHidden(acptr) ? user->virthost : user->realhost, acptr->info); if (IsOper(sptr) || acptr == sptr) { char sno[512]; strcpy(sno, get_sno_str(acptr)); /* send the target user's modes */ sendto_one(sptr, rpl_str(RPL_WHOISMODES), me.name, parv[0], name, get_mode_str(acptr), sno[1] == 0 ? "" : sno); } if ((acptr == sptr) || IsAnOper(sptr)) { sendto_one(sptr, rpl_str(RPL_WHOISHOST), me.name, parv[0], acptr->name, (MyConnect(acptr) && strcmp(acptr->username, "unknown")) ? acptr->username : "******", user->realhost, user->ip_str ? user->ip_str : ""); } if (IsARegNick(acptr)) sendto_one(sptr, rpl_str(RPL_WHOISREGNICK), me.name, parv[0], name); found = 1; mlen = strlen(me.name) + strlen(parv[0]) + 10 + strlen(name); for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next) { chptr = lp->chptr; showchannel = 0; if (ShowChannel(sptr, chptr)) showchannel = 1; if (OPCanSeeSecret(sptr)) showchannel = 1; if ((acptr->umodes & UMODE_HIDEWHOIS) && !IsMember(sptr, chptr) && !IsAnOper(sptr)) showchannel = 0; if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr)) showchannel = 0; if (acptr == sptr) showchannel = 1; /* Hey, if you are editting here... don't forget to change the webtv w_whois ;p. */ if (showchannel) { long access; if (len + strlen(chptr->chname) > (size_t)BUFSIZE - 4 - mlen) { sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISCHANNELS, parv[0], name, buf); *buf = '\0'; len = 0; } #ifdef SHOW_SECRET if (IsAnOper(sptr) #else if (IsNetAdmin(sptr) #endif && SecretChannel(chptr) && !IsMember(sptr, chptr)) *(buf + len++) = '?'; if (acptr->umodes & UMODE_HIDEWHOIS && !IsMember(sptr, chptr) && IsAnOper(sptr)) *(buf + len++) = '!'; access = get_access(acptr, chptr); if (!SupportNAMESX(sptr)) { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; else if (access & CHFL_CHANPROT) *(buf + len++) = '&'; else #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; else if (access & CHFL_HALFOP) *(buf + len++) = '%'; else if (access & CHFL_VOICE) *(buf + len++) = '+'; } else { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; if (access & CHFL_CHANPROT) *(buf + len++) = '&'; #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; if (access & CHFL_HALFOP) *(buf + len++) = '%'; if (access & CHFL_VOICE) *(buf + len++) = '+'; } if (len) *(buf + len) = '\0'; (void)strcpy(buf + len, chptr->chname); len += strlen(chptr->chname); (void)strcat(buf + len, " "); len++; } } if (buf[0] != '\0') sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, parv[0], name, buf); if (!(IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES)) sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], name, user->server, a2cptr ? a2cptr->info : "*Not On This Net*"); if (user->away) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, user->away); /* makesure they aren't +H (we'll also check before we display a helpop or IRCD Coder msg) -- codemastr */ if ((IsAnOper(acptr) || IsServices(acptr)) && !hideoper) { buf[0] = '\0'; if (IsNetAdmin(acptr)) strlcat(buf, "a Network Administrator", sizeof buf); else if (IsSAdmin(acptr)) strlcat(buf, "a Services Administrator", sizeof buf); else if (IsAdmin(acptr) && !IsCoAdmin(acptr)) strlcat(buf, "a Server Administrator", sizeof buf); else if (IsCoAdmin(acptr)) strlcat(buf, "a Co Administrator", sizeof buf); else if (IsServices(acptr)) strlcat(buf, "a Network Service", sizeof buf); else if (IsOper(acptr)) strlcat(buf, "an IRC Operator", sizeof buf); else strlcat(buf, "a Local IRC Operator", sizeof buf); if (buf[0]) { if (IsOper(sptr) && MyClient(acptr)) sendto_one(sptr, ":%s 313 %s %s :is %s (%s)", me.name, parv[0], name, buf, acptr->user->operlogin); else sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR), me.name, parv[0], name, buf); } } if (IsHelpOp(acptr) && !hideoper && !user->away) sendto_one(sptr, rpl_str(RPL_WHOISHELPOP), me.name, parv[0], name); if (acptr->umodes & UMODE_BOT) sendto_one(sptr, rpl_str(RPL_WHOISBOT), me.name, parv[0], name, ircnetwork); if (acptr->umodes & UMODE_SECURE) sendto_one(sptr, rpl_str(RPL_WHOISSECURE), me.name, parv[0], name, "is using a Secure Connection"); if (!BadPtr(user->swhois) && !hideoper) sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISSPECIAL, parv[0], name, acptr->user->swhois); /* * display services account name if it's actually a services account name and * not a legacy timestamp. --nenolod */ if (!isdigit(*user->svid)) sendto_one(sptr, rpl_str(RPL_WHOISLOGGEDIN), me.name, parv[0], name, user->svid); /* * Umode +I hides an oper's idle time from regular users. * -Nath. */ if (MyConnect(acptr) && (IsAnOper(sptr) || !(acptr->umodes & UMODE_HIDLE))) { sendto_one(sptr, rpl_str(RPL_WHOISIDLE), me.name, parv[0], name, TStime() - acptr->last, acptr->firsttime); } } if (!found) sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick); } sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], querybuf); return 0; }
/* ** m_whois ** parv[0] = sender prefix ** parv[1] = nickname masklist */ int m_whois(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { static anUser UnknownUser = { NULL, /* next */ NULL, /* channel */ NULL, /* invited */ NULL, /* silence */ NULL, /* away */ 0, /* last */ 1, /* refcount */ 0, /* joined */ "<Unknown>" /* server */ }; static char rpl_oper[] = "an IRC Operator"; static char rpl_locop[] = "an IRC Operator - Local IRC Operator"; static char rpl_sadmin[] = "an IRC Operator - Services Administrator"; static char rpl_admin[] = "an IRC Operator - Server Administrator"; static char rpl_tadmin[] = "an IRC Operator - Technical Administrator"; static char rpl_nadmin[] = "an IRC Operator - Network Administrator"; Link *lp; anUser *user; struct Client *acptr, *a2cptr; aChannel *chptr; char *nick, *name; /* char *tmp; */ char *p = NULL; int found, len, mlen; static time_t last_used=0L; char *nick_match=NULL, *user_match=NULL, *host_match=NULL, *server_match=NULL; char *name_match=NULL; int found_mode; int hits = 0; char *mename = me.name; if(sptr->user && sptr->user->vlink) mename = sptr->user->vlink->name; if (parc < 2) { sendto_one(sptr, form_str(ERR_NONICKNAMEGIVEN), mename, parv[0]); return 0; } if(parc > 2) { if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } if(!IsAnOper(sptr) && !MyConnect(sptr)) /* pace non local requests */ { if((last_used + WHOIS_WAIT) > CurrentTime) { /* Unfortunately, returning anything to a non local * request =might= increase sendq to be usable in a split hack * Sorry gang ;-( - Dianora */ return 0; } else { last_used = CurrentTime; } } /* Multiple whois from remote hosts, can be used * to flood a server off. One could argue that multiple whois on * local server could remain. Lets think about that, for now * removing it totally. * -Dianora */ /* for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL) */ nick = parv[1]; p = strchr(parv[1],','); if(p) *p = '\0'; { int invis, member, wilds; found = 0; (void)collapse(nick); wilds = (nick[0]=='$' || strchr(nick, '?') || strchr(nick, '*')); /* ** We're no longer allowing remote users to generate ** requests with wildcards. */ if (wilds && !IsAnOper(sptr)) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename, parv[0], nick); return 0; } /* continue; */ /* If the nick doesn't have any wild cards in it, * then just pick it up from the hash table * - Dianora */ if(!wilds) { acptr = hash_find_client(nick,(struct Client *)NULL); if(!acptr) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename, parv[0], nick); sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]); return 0; /* continue; */ } if(IsStealth(acptr)) { sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename, parv[0], nick); return 0; // Add by ^Stinger^ after the idea of Soldier (: } if(!IsPerson(acptr)) { sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]); return 0; } /* continue; */ user = acptr->user ? acptr->user : &UnknownUser; name = (!*acptr->name) ? "?" : acptr->name; invis = IsInvisible(acptr); member = (user->channel) ? 1 : 0; a2cptr = find_server(user->server); sendto_one(sptr, form_str(RPL_WHOISUSER), mename, parv[0], name, acptr->username, acptr->host, acptr->info); if((IsOper(sptr) || (acptr == sptr)) && WhoisExtension) { sendto_one(sptr, form_str(RPL_WHOISREALHOST), mename, parv[0], name, acptr->realhost); } mlen = strlen(mename) + strlen(parv[0]) + 6 + strlen(name); *buf = '\0'; if (IsSsl(acptr)) { sendto_one(sptr, form_str(RPL_WHOISSECURE), mename, parv[0], parv[1]); } if(((!IsPrivate(acptr) || IsOper(sptr)) || (acptr==sptr)) && !IsStealth(acptr)) for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next) { chptr = lp->value.chptr; if (ShowChannel(sptr, chptr)) { if (len + strlen(chptr->chname) > (size_t) BUFSIZE - 4 - mlen) { sendto_one(sptr, ":%s %d %s %s :%s", mename, RPL_WHOISCHANNELS, parv[0], name, buf); *buf = '\0'; len = 0; } found_mode = user_channel_mode(acptr, chptr); #ifdef HIDE_OPS if(is_chan_op(sptr,chptr)) #endif { if(found_mode & CHFL_CHANOP) *(buf + len++) = '@'; #ifdef HALFOPS else if (found_mode & CHFL_HALFOP) *(buf + len++) = '%'; #endif else if (found_mode & CHFL_VOICE) *(buf + len++) = '+'; } if (len) *(buf + len) = '\0'; (void)strcpy(buf + len, chptr->chname); len += strlen(chptr->chname); (void)strcat(buf + len, " "); len++; } } if (buf[0] != '\0') sendto_one(sptr, form_str(RPL_WHOISCHANNELS), mename, parv[0], name, buf); if(IsAnOper(sptr) || !HideServerOnWhois) { #ifdef SERVERHIDE if (!(IsAnOper(sptr) || acptr == sptr)) sendto_one(sptr, form_str(RPL_WHOISSERVER), mename, parv[0], name, NetworkName, NetworkDesc); else #endif if(acptr->user && acptr->user->vlink) sendto_one(sptr, form_str(RPL_WHOISSERVER), mename, parv[0], name, user->vlink->name, user->vlink->passwd); else { if(!IsService(acptr) || IsAnOper(sptr) || !HideServicesServer) sendto_one(sptr, form_str(RPL_WHOISSERVER), mename, parv[0], name, user->server, a2cptr?a2cptr->info:"*Not On This Net*"); } } /* if(IsAnOper(sptr) || HideServerOnWhois) */ if (IsIdentified(acptr)) sendto_one(sptr, form_str(RPL_WHOISIDENTIFIED), mename, parv[0], name); if (IsHelper(acptr)) sendto_one(sptr, form_str(RPL_WHOISHELPOP), mename, parv[0], name); if(IsOper(sptr) && WhoisExtension) { sendto_one(sptr, form_str(RPL_WHOISMODE), mename, parv[0], name, get_mode_string(acptr)); } if (user->away) sendto_one(sptr, form_str(RPL_AWAY), mename, parv[0], name, user->away); if(!IsHideOper(acptr) || IsOper(sptr)) { if (IsNetAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_nadmin); else if (IsTechAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_tadmin); else if (IsSAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_sadmin); else if (IsAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_admin); else if (IsOper(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_oper); else if (IsLocOp(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_locop); } #ifdef WHOIS_NOTICE if ((IsOper(acptr)) && ((acptr)->umodes & UMODE_SPY) && (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr) && !is_silenced(sptr, acptr)) sendto_one(acptr, ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.", me.name, acptr->name, parv[0], sptr->username, sptr->realhost); #endif /* #ifdef WHOIS_NOTICE */ if ((acptr->user #ifdef SERVERHIDE && IsAnOper(sptr) #endif && MyConnect(acptr))) sendto_one(sptr, form_str(RPL_WHOISIDLE), mename, parv[0], name, CurrentTime - user->last, acptr->firsttime); sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]); return 0; /* continue; */ } /* wild is true so here we go */ if(nick[0]==':') /* real name match */ { name_match = &nick[1]; nick_match = NULL; } else if(nick[0]=='$') /* server name match */ { server_match = &nick[1]; nick_match = NULL; } else { host_match = strchr(nick,'@'); if(host_match) { if(*host_match) *(host_match++) = '\0'; user_match=nick; if(host_match=='\0') host_match="*"; if(user_match=='\0') user_match="*"; } else nick_match = nick; } for (acptr = GlobalClientList; acptr; acptr = acptr->next) { if (IsServer(acptr)) continue; /* * I'm always last :-) and acptr->next == NULL!! */ if (IsMe(acptr)) break; /* * 'Rules' established for sending a WHOIS reply: * * * - if wildcards are being used dont send a reply if * the querier isnt any common channels and the * client in question is invisible and wildcards are * in use (allow exact matches only); * * - only send replies about common or public channels * the target user(s) are on; */ /* If its an unregistered client, ignore it, it can be "seen" on a /trace anyway -Dianora */ if(!IsRegistered(acptr)) continue; user = acptr->user ? acptr->user : &UnknownUser; name = (!*acptr->name) ? "?" : acptr->name; if( (server_match && !match(server_match, user->server)) || (nick_match && !match(nick, name)) || (host_match && !match(host_match, acptr->realhost) && !match(host_match, acptr->host)) || (user_match && !match(user_match, acptr->username)) || (name_match && !match(name_match, acptr->info)) ) continue; ++hits; a2cptr = find_server(user->server); sendto_one(sptr, form_str(RPL_WHOISUSER), mename, parv[0], name, acptr->username, IsOper(sptr) ? acptr->realhost : acptr->host, acptr->info); found = 1; mlen = strlen(mename) + strlen(parv[0]) + 6 + strlen(name); for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next) { chptr = lp->value.chptr; if (ShowChannel(sptr, chptr)) { if (len + strlen(chptr->chname) > (size_t) BUFSIZE - 4 - mlen) { sendto_one(sptr, ":%s %d %s %s :%s", mename, RPL_WHOISCHANNELS, parv[0], name, buf); *buf = '\0'; len = 0; } found_mode = user_channel_mode(acptr, chptr); #ifdef HIDE_OPS if(is_chan_op(sptr,chptr)) #endif { if (found_mode & CHFL_CHANOP) *(buf + len++) = '@'; #ifdef HALFOPS else if (found_mode & CHFL_HALFOP) *(buf + len++) = '%'; #endif else if (found_mode & CHFL_VOICE) *(buf + len++) = '+'; } if (len) *(buf + len) = '\0'; (void)strcpy(buf + len, chptr->chname); len += strlen(chptr->chname); (void)strcat(buf + len, " "); len++; } } if (buf[0] != '\0') sendto_one(sptr, form_str(RPL_WHOISCHANNELS), mename, parv[0], name, buf); #ifdef SERVERHIDE if (!(IsAnOper(sptr) || acptr == sptr)) sendto_one(sptr, form_str(RPL_WHOISSERVER), mename, parv[0], name, NetworkName, NetworkDesc); else #endif sendto_one(sptr, form_str(RPL_WHOISSERVER), mename, parv[0], name, user->server, a2cptr?a2cptr->info:"*Not On This Net*"); if (user->away) sendto_one(sptr, form_str(RPL_AWAY), mename, parv[0], name, user->away); if (IsNetAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_nadmin); else if (IsTechAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_tadmin); else if (IsSAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_sadmin); else if (IsAdmin(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_admin); else if (IsAnOper(acptr)) sendto_one(sptr, form_str(RPL_WHOISOPERATOR), mename, parv[0], name, rpl_oper); #ifdef WHOIS_NOTICE if ((MyOper(acptr)) && ((acptr)->umodes & UMODE_SPY) && (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr)) sendto_one(acptr, ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.", mename, acptr->name, parv[0], sptr->username, sptr->realhost); #endif /* #ifdef WHOIS_NOTICE */ if ((acptr->user #ifdef SERVERHIDE && IsAnOper(sptr) #endif && MyConnect(acptr))) sendto_one(sptr, form_str(RPL_WHOISIDLE), mename, parv[0], name, CurrentTime - user->last, acptr->firsttime); if(hits>50) { sendto_one(sptr,":%s NOTICE %s :Aborting /whois output as flood prevention", mename, sptr->name); break; } } if (!found) sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename, parv[0], nick); else sendto_one(sptr,":%s NOTICE %s :This /whois matched \2%i\2 user(s)", mename, sptr->name,hits); /* if (p) p[-1] = ','; */ } sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]); 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); }
/* Rewritten by Run - 24 sept 94 */ static void exit_one_client(struct Client* bcptr, const char* comment) { struct SLink *lp; struct Ban *bp; if (cli_serv(bcptr) && cli_serv(bcptr)->client_list) /* Was SetServerYXX called ? */ ClearServerYXX(bcptr); /* Removes server from server_list[] */ if (IsUser(bcptr)) { /* * clear out uping requests */ if (IsUPing(bcptr)) uping_cancel(bcptr, 0); /* * Stop a running /LIST clean */ if (MyUser(bcptr) && cli_listing(bcptr)) { MyFree(cli_listing(bcptr)); cli_listing(bcptr) = NULL; } /* * If a person is on a channel, send a QUIT notice * to every client (person) on the same channel (so * that the client can show the "**signoff" message). * (Note: The notice is to the local clients *only*) */ sendcmdto_common_channels_butone(bcptr, CMD_QUIT, NULL, ":%s", comment); remove_user_from_all_channels(bcptr); /* Clean up invitefield */ while ((lp = cli_user(bcptr)->invited)) del_invite(bcptr, lp->value.chptr); /* Clean up silencefield */ while ((bp = cli_user(bcptr)->silence)) { cli_user(bcptr)->silence = bp->next; free_ban(bp); } /* Clean up smarks field */ del_marks(bcptr); /* Clean up watch lists */ if (MyUser(bcptr)) del_list_watch(bcptr); /* Notify Logout */ check_status_watch(bcptr, RPL_LOGOFF); /* Clean up snotice lists */ if (MyUser(bcptr)) set_snomask(bcptr, ~0, SNO_DEL); if (IsInvisible(bcptr)) { assert(UserStats.inv_clients > 0); --UserStats.inv_clients; } if (IsOper(bcptr) && !IsHideOper(bcptr) && !IsChannelService(bcptr) && !IsBot(bcptr)) { assert(UserStats.opers > 0); --UserStats.opers; } if (MyConnect(bcptr)) Count_clientdisconnects(bcptr, UserStats); else Count_remoteclientquits(UserStats, bcptr); } else if (IsServer(bcptr)) { /* Remove downlink list node of uplink */ remove_dlink(&(cli_serv(cli_serv(bcptr)->up))->down, cli_serv(bcptr)->updown); cli_serv(bcptr)->updown = 0; if (MyConnect(bcptr)) Count_serverdisconnects(UserStats); else Count_remoteserverquits(UserStats); } else if (IsMe(bcptr)) { sendto_opmask_butone(0, SNO_OLDSNO, "ERROR: tried to exit me! : %s", comment); return; /* ...must *never* exit self! */ } else if (IsUnknown(bcptr) || IsConnecting(bcptr) || IsHandshake(bcptr)) Count_unknowndisconnects(UserStats); /* * Update IPregistry */ if (IsIPChecked(bcptr)) IPcheck_disconnect(bcptr); /* * Remove from serv->client_list * NOTE: user is *always* NULL if this is a server */ if (cli_user(bcptr)) { assert(!IsServer(bcptr)); /* bcptr->user->server->serv->client_list[IndexYXX(bcptr)] = NULL; */ RemoveYXXClient(cli_user(bcptr)->server, cli_yxx(bcptr)); } /* Remove bcptr from the client list */ #ifdef DEBUGMODE if (hRemClient(bcptr) != 0) Debug((DEBUG_ERROR, "%p !in tab %s[%s] %p %p %p %d %d %p", bcptr, cli_name(bcptr), cli_from(bcptr) ? cli_sockhost(cli_from(bcptr)) : "??host", cli_from(bcptr), cli_next(bcptr), cli_prev(bcptr), cli_fd(bcptr), cli_status(bcptr), cli_user(bcptr))); #else hRemClient(bcptr); #endif remove_client_from_list(bcptr); }