From 09ac0e6ee42e28d42126e413c5d4f21e7dc3da3b Mon Sep 17 00:00:00 2001 From: luke Date: Fri, 2 Aug 2002 01:05:37 +0000 Subject: [PATCH] All sorts of bugfixes, added prefixes, revamped operoverride...etc --- Changes | 47 +++++- Config | 1 + include/common.h | 2 +- include/numeric.h | 2 +- include/struct.h | 200 ++++++++++++------------- src/channel.c | 362 ++++++++++++++++++++++++---------------------- src/s_err.c | 4 +- src/s_kline.c | 48 +++--- src/s_user.c | 81 +++++++---- src/webtv.c | 29 ++-- 10 files changed, 440 insertions(+), 336 deletions(-) diff --git a/Changes b/Changes index 0121ab1b8..ea1fcfcf8 100644 --- a/Changes +++ b/Changes @@ -19,7 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ - + [ Unreal4.0 ] - Fixed a _serious_ bug in SERVER command, reported by Valen, Forrester, M0rpheus, JK, and Hiten. @@ -525,3 +525,48 @@ Fixed bug with mirc where +a/+q were misinterpreted as modes without nick parameters. --Luke =================================== + +Implemented actual prefixes for +q and +a (~ and &) +--Luke +=================================== + +Modified is_chan_op and is_chanprot functions to better +respect hierarchy (chanowner is chanprot as well as chanop) +chanprot is chanop. +--Luke +=================================== + +Fixed m_gline and m_gzline bugs. (Thanks to nighthawk for +noticing) +--Luke +=================================== + +Fixed sjoin bug with ban propagation +--Luke +=================================== + +Fixed m_who bug with normal users using masks +--Luke +=================================== + +Rearranged structs in struct.h to be more memory efficient +(saved 4 bytes in User, in preparation for new operoverride +system.) +--Luke +=================================== + +Decided channel owners can deown themsleves, implemented +as such +--Luke +=================================== + +Revised operoverride system further, now default prompting +before permitting opers to walk channel modes. +--Luke +=================================== + +Scratch previous revision, redid override system altogether. +Now done via /invite. Sts' response to those of you that +don't like it: "fuck them" +--Luke +=================================== diff --git a/Config b/Config index 881a35556..19b4826c0 100755 --- a/Config +++ b/Config @@ -1861,6 +1861,7 @@ cat > $OPTIONS_H << __EOF__ #define BUFFERPOOL $BUFFERPOOL #define MAXCONNECTIONS $MAXCONNECTIONS #define NICKNAMEHISTORYLENGTH $NICKNAMEHISTORYLENGTH +#define OPEROVERRIDE_VERIFY 1 __EOF__ if [ -n "$CRYPT_OPER_PASSWORD" ] ; then diff --git a/include/common.h b/include/common.h index 1cdc912c1..656e34836 100644 --- a/include/common.h +++ b/include/common.h @@ -238,7 +238,7 @@ extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ ); TOPICLEN, \ TOPICLEN, \ "#", \ - "(ohv)@%+", \ + "(qaohv)~&@%+", \ "ohvbeqa", \ "k", \ "lfL", \ diff --git a/include/numeric.h b/include/numeric.h index 8f1a983f1..52e66cd86 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -132,7 +132,7 @@ #define ERR_ADMONLY 519 #define ERR_OPERONLY 520 #define ERR_LISTSYNTAX 521 - +#define ERR_OPERSPVERIFY 524 /* * Numberic replies from server commands. * These are currently in the range 200-399. diff --git a/include/struct.h b/include/struct.h index 70fa92698..b9583d953 100644 --- a/include/struct.h +++ b/include/struct.h @@ -588,45 +588,45 @@ struct aloopStruct { }; typedef struct Whowas { - int hashv; + long umodes; char *name; char *username; char *hostname; char *virthost; char *servername; char *realname; - long umodes; - TS logoff; struct Client *online; /* Pointer to new nickname for chasing or NULL */ struct Whowas *next; /* for hash table... */ struct Whowas *prev; /* for hash table... */ struct Whowas *cnext; /* for client struct linked list */ struct Whowas *cprev; /* for client struct linked list */ + int hashv; + TS logoff; } aWhowas; struct SqlineItem { - unsigned int status; char *sqline; char *reason; struct SqlineItem *next; + unsigned int status; }; struct ConfItem { - unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ - int clients; /* Number of *LOCAL* clients using this */ struct IN_ADDR ipnum; /* ip number of host field */ char *host; char *passwd; char *name; - int port; - TS hold; /* Hold action until this time (calendar time) */ - int tmpconf; -#ifndef VMSP - aClass *class; /* Class of connection */ -#endif - short options; struct ConfItem *next; +#ifndef VMSP + aClass *class; /* Class of connection */ +#endif + unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ + TS hold; /* Hold action until this time (calendar time) */ + int clients; /* Number of *LOCAL* clients using this */ + int port; + int tmpconf; + short options; }; #define CONF_ILLEGAL 0x80000000 @@ -676,40 +676,40 @@ struct ConfItem { * Client structures */ struct User { + char realhost[HOSTLEN + 1]; + char username[USERLEN + 1]; struct User *nextu; Link *channel; /* chain of channel pointer blocks */ Link *invited; /* chain of invite pointer blocks */ Link *silence; /* chain of silence pointer blocks */ char *away; /* pointer to away message */ + char *virthost; + char *server; + char *swhois; /* special whois thing */ + aClient *serv; + LOpts *lopt; /* Saved /list options */ + aWhowas *whowas; +#ifdef LIST_DEBUG + aClient *bcptr; +#endif TS last; u_int32_t servicestamp; /* Services' time stamp variable */ - signed char refcnt; /* Number of times this block is referenced */ unsigned short joined; /* number of channels joined */ - char username[USERLEN + 1]; - char realhost[HOSTLEN + 1]; - char *virthost; - char *server; - char *swhois; /* special whois thing */ - aClient *serv; - LOpts *lopt; /* Saved /list options */ - aWhowas *whowas; -#ifdef LIST_DEBUG - aClient *bcptr; -#endif + signed char refcnt; /* Number of times this block is referenced */ }; struct Server { + char by[NICKLEN + 1]; + long users; struct Server *nexts; anUser *user; /* who activated this connection */ char *up; /* uplink for this server */ - char by[NICKLEN + 1]; aConfItem *nline; /* N-line pointer for this server */ +#ifdef LIST_DEBUG + aClient *bcptr; +#endif TS timestamp; /* Remotely determined connect try time */ unsigned short numeric; /* NS numeric, 0 if none */ - long users; -#ifdef LIST_DEBUG - aClient *bcptr; -#endif }; struct t_vhost { @@ -740,45 +740,45 @@ struct t_kline { char *hostmask; char *reason; char *setby; + aTKline *next; + aTKline *prev; TS expire_at; TS set_at; - aTKline *next; - aTKline *prev; }; struct ircstatsx { int clients; /* total */ int invisible; /* invisible */ - unsigned short servers; /* servers */ int operators; /* operators */ int unknown; /* unknown local connections */ int channels; /* channels */ int me_clients; /* my clients */ - unsigned short me_servers; /* my servers */ int me_max; /* local max */ int global_max; /* global max */ + unsigned short servers; /* servers */ + unsigned short me_servers; /* my servers */ }; struct t_fline { char *mask; char *reason; - int type; aFline *next; aFline *prev; + int type; }; struct t_crline { char *channel; - int type; aCRline *next, *prev; + int type; }; struct t_vhline { char *login; char *password; char *vhost; - int type; aVHline *next, *prev; + int type; }; #define LISTENER_NORMAL 0x000001 @@ -793,26 +793,26 @@ struct t_vhline { struct Client { + char info[REALLEN + 1]; /* Free form additional client information */ + char name[HOSTLEN + 1]; /* Unique name of the client, nick or host */ + char username[USERLEN + 1]; /* username here now for auth stuff */ + u_char targets[MAXTARGETS]; /* Hash values of current targets */ + long flags; /* client flags */ + long umodes; /* client usermodes */ struct Client *next, *prev, *hnext; anUser *user; /* ...defined, if this is a User */ aServer *serv; /* ...defined, if this is a server */ + aClient *from; /* == self, if Local Client, *NEVER* NULL! */ + aClient *srvptr; /* Server introducing this. May be &me */ TS lasttime; /* ...should be only LOCAL clients? --msa */ TS firsttime; /* time client was created */ TS since; /* last time we parsed something */ TS lastnick; /* TimeStamp on nick */ TS nextnick; /* Time the next nick change will be allowed */ TS nexttarget; /* Time until a change in targets is allowed */ - u_char targets[MAXTARGETS]; /* Hash values of current targets */ - long flags; /* client flags */ - long umodes; /* client usermodes */ - aClient *from; /* == self, if Local Client, *NEVER* NULL! */ int fd; /* >= 0, for local clients */ + short status; /* Client type */ unsigned char hopcount; /* number of servers to this 0 = local */ - short status; /* Client type */ - char name[HOSTLEN + 1]; /* Unique name of the client, nick or host */ - char username[USERLEN + 1]; /* username here now for auth stuff */ - char info[REALLEN + 1]; /* Free form additional client information */ - aClient *srvptr; /* Server introducing this. May be &me */ /* ** The following fields are allocated only for local clients ** (directly connected to *this* server with a socket. @@ -821,45 +821,47 @@ struct Client { ** these fields, if (from != self). */ int count; /* Amount of data in buffer */ - char buffer[BUFSIZE]; /* Incoming message buffer */ - short lastsq; /* # of 2k blocks when sendqueued called last */ - dbuf sendQ; /* Outgoing message queue--if socket full */ - dbuf recvQ; /* Hold for data incoming yet to be parsed */ + char buffer[BUFSIZE]; /* Incoming message buffer */ + char sockhost[HOSTLEN + 1]; /* This is the host name from the socket + ** and after which the connection was + ** accepted. + */ + dbuf sendQ; /* Outgoing message queue--if socket full */ + dbuf recvQ; /* Hold for data incoming yet to be parsed */ + struct IN_ADDR ip; /* keep real ip# too */ + long oflag; /* Operator access flags -Cabal95 */ + long sendM; /* Statistics: protocol messages send */ + long sendK; /* Statistics: total k-bytes send */ + long receiveM; /* Statistics: protocol messages received */ + long receiveK; /* Statistics: total k-bytes received */ +#ifndef NO_FDLIST + long lastrecvM; /* to check for activity --Mika */ +#endif +#ifdef USE_SSL + struct SSL *ssl; + struct X509 *client_cert; +#endif + aClient *acpt; /* listening client which we accepted from */ + Link *confs; /* Configuration record associated */ + Link *notify; /* Links to clients notify-structures */ + char *passwd; + struct hostent *hostp; #ifdef NOSPOOF u_int32_t nospoof; /* Anti-spoofing random number */ -#endif - long oflag; /* Operator access flags -Cabal95 */ - long proto; /* ProtoCtl options */ - long sendM; /* Statistics: protocol messages send */ - long sendK; /* Statistics: total k-bytes send */ - long receiveM; /* Statistics: protocol messages received */ -#ifdef USE_SSL - struct SSL *ssl; - struct X509 *client_cert; #endif #ifndef NO_FDLIST - long lastrecvM; /* to check for activity --Mika */ int priority; #endif - long receiveK; /* Statistics: total k-bytes received */ - u_short sendB; /* counters to count upto 1-k lots of bytes */ - u_short receiveB; /* sent and received. */ - aClient *acpt; /* listening client which we accepted from */ - Link *confs; /* Configuration record associated */ - int authfd; /* fd for rfc931 authentication */ + int authfd; /* fd for rfc931 authentication */ #ifdef SOCKSPORT int socksfd; #endif - struct IN_ADDR ip; /* keep real ip# too */ + int proto; /* ProtoCtl options */ + u_short sendB; /* counters to count upto 1-k lots of bytes */ + u_short receiveB; /* sent and received. */ u_short port; /* and the remote port# too :-) */ - struct hostent *hostp; u_short notifies; /* Keep track of count of notifies */ - Link *notify; /* Links to clients notify-structures */ - char sockhost[HOSTLEN + 1]; /* This is the host name from the socket - ** and after which the connection was - ** accepted. - */ - char *passwd; + short lastsq; /* # of 2k blocks when sendqueued called last */ #ifdef DEBUGMODE TS cputime; #endif @@ -872,19 +874,15 @@ struct Client { * statistics structures */ struct stats { + unsigned long is_cks; /* k-bytes sent to clients */ + unsigned long is_ckr; /* k-bytes received to clients */ + unsigned long is_sks; /* k-bytes sent to servers */ + unsigned long is_skr; /* k-bytes received to servers */ + TS is_cti; /* time spent connected by clients */ + TS is_sti; /* time spent connected by servers */ unsigned int is_cl; /* number of client connections */ unsigned int is_sv; /* number of server connections */ unsigned int is_ni; /* connection but no idea who it was */ - unsigned short is_cbs; /* bytes sent to clients */ - unsigned short is_cbr; /* bytes received to clients */ - unsigned short is_sbs; /* bytes sent to servers */ - unsigned short is_sbr; /* bytes received to servers */ - unsigned long is_cks; /* k-bytes sent to clients */ - unsigned long is_ckr; /* k-bytes received to clients */ - unsigned long is_sks; /* k-bytes sent to servers */ - unsigned long is_skr; /* k-bytes received to servers */ - TS is_cti; /* time spent connected by clients */ - TS is_sti; /* time spent connected by servers */ unsigned int is_ac; /* connections accepted */ unsigned int is_ref; /* accepts refused */ unsigned int is_unco; /* unknown commands */ @@ -898,20 +896,24 @@ struct stats { unsigned int is_abad; /* bad auth requests */ unsigned int is_udp; /* packets recv'd on udp port */ unsigned int is_loc; /* local connections made */ + unsigned short is_cbs; /* bytes sent to clients */ + unsigned short is_cbr; /* bytes received to clients */ + unsigned short is_sbs; /* bytes sent to servers */ + unsigned short is_sbr; /* bytes received to servers */ }; struct ListOptions { LOpts *next; Link *yeslist, *nolist; - int starthash; - short int showall; - unsigned short usermin; - int usermax; TS currenttime; TS chantimemin; TS chantimemax; TS topictimemin; TS topictimemax; + int starthash; + int usermax; + short int showall; + unsigned short usermin; }; /* mode structure for channels */ @@ -922,8 +924,8 @@ struct SMode { long mode; #endif int limit; - char key[KEYLEN + 1]; char link[LINKLEN + 1]; + char key[KEYLEN + 1]; /* x:y */ unsigned short msgs; /* x */ unsigned short per; /* y */ @@ -937,11 +939,11 @@ struct Message { int (*func) (); unsigned int count; unsigned parameters : 5; - u_char token[3]; /* Cheat for tokenized value */ + u_char token[3]; /* Cheat for tokenized value */ unsigned long bytes; #ifdef DEBUGMODE - unsigned long lticks; - unsigned long rticks; + unsigned long lticks; + unsigned long rticks; #endif }; @@ -949,8 +951,8 @@ struct Message { struct Notify { aNotify *hnext; - TS lasttime; Link *notify; + TS lasttime; char nick[1]; }; @@ -958,7 +960,6 @@ struct Notify { struct SLink { struct SLink *next; - int flags; aFloodOpt *flood; union { aClient *cptr; @@ -973,6 +974,7 @@ struct SLink { TS when; } ban; } value; + int flags; }; struct SBan { @@ -996,17 +998,17 @@ struct DSlink { /* channel structure */ struct Channel { - struct Channel *nextch, *prevch, *hnextch; Mode mode; - TS creationtime; + struct Channel *nextch, *prevch, *hnextch; char *topic; char *topic_nick; - TS topic_time; - unsigned short users; Link *members; Link *invites; Ban *banlist; Ban *exlist; /* exceptions */ + TS creationtime; + TS topic_time; + unsigned short users; char chname[1]; }; @@ -1103,8 +1105,8 @@ struct Channel { find_channel_link((blah->user)->channel, chan)) ? 1 : 0) struct FloodOpt { - unsigned short nmsg; TS lastmsg; + unsigned short nmsg; }; /* Misc macros */ diff --git a/src/channel.c b/src/channel.c index 1b234a730..5a6e970b6 100644 --- a/src/channel.c +++ b/src/channel.c @@ -73,7 +73,6 @@ extern ircstats IRCstats; extern int lifesux; #endif -void over_notice(aClient *, aClient *, aChannel *, char *); static void add_invite PROTO((aClient *, aChannel *)); static int add_banid PROTO((aClient *, aChannel *, char *)); static int can_join PROTO((aClient *, aClient *, aChannel *, char *, char *, @@ -563,7 +562,9 @@ int is_chan_op(cptr, chptr) /* chanop/halfop ? */ if (chptr) if ((lp = find_user_link(chptr->members, cptr))) - return ((lp->flags & CHFL_CHANOP)); + return ((lp->flags & CHFL_CHANOP) || + (lp->flags & CHFL_CHANOWNER) || + (lp->flags & CHFL_CHANPROT)); return 0; } @@ -637,7 +638,8 @@ int is_chanprot(cptr, chptr) if (chptr) if ((lp = find_user_link(chptr->members, cptr))) - return (lp->flags & CHFL_CHANPROT); + return (lp->flags & CHFL_CHANPROT || + lp->flags & CHFL_CHANOWNER); return 0; } @@ -1371,7 +1373,7 @@ void make_mode_str(chptr, oldm, oldl, pcount, pvar, mode_buf, para_buf, bounce) char tmpbuf[MODEBUFLEN+3], *tmpstr; aCtab *tab = &cFlagTab[0]; - char *x = modebuf; + char *x = mode_buf; int what, cnt, z; char *m; what = 0; @@ -1558,7 +1560,7 @@ int do_mode_char(chptr, modetype, modechar, param, what, cptr, pcount, pvar, } goto setthephuckingmode; case MODE_OPERONLY: - if (!IsAnOper(cptr) && !IsServer(cptr) && !IsULine(cptr)) + if (!IsOper(cptr) && !IsServer(cptr) && !IsULine(cptr)) { sendto_one(cptr, ":%s NOTICE %s :*** Opers Only mode (+O) can only be set by IRC Operators.", @@ -1620,7 +1622,7 @@ int do_mode_char(chptr, modetype, modechar, param, what, cptr, pcount, pvar, #endif case MODE_NOCTCP: case MODE_ONLYSECURE: - if (what == MODE_ADD && modetype == MODE_ONLYSECURE) + if (what == MODE_ADD && modetype == MODE_ONLYSECURE && !(IsServer(cptr) || IsULine(cptr))) { for (member = chptr->members; member; member = member->next) { @@ -1634,6 +1636,7 @@ int do_mode_char(chptr, modetype, modechar, param, what, cptr, pcount, pvar, } } member = NULL; + /* first break nailed the for loop, this one nails switch() */ if (notsecure == 1) break; } case MODE_NONICKCHANGE: @@ -1663,9 +1666,10 @@ int do_mode_char(chptr, modetype, modechar, param, what, cptr, pcount, pvar, /* do pro-opping here (popping) */ case MODE_CHANOWNER: + /* Channel owners can dechanown themselves */ if (!IsULine(cptr) && !IsServer(cptr) && !IsNetAdmin(cptr) - && !is_chanowner(cptr, chptr)) + && !(is_chanowner(cptr, chptr) && what == MODE_DEL)) { sendto_one(cptr, err_str(ERR_ONLYSERVERSCANCHANGE), me.name, cptr->name, chptr->chname); @@ -2133,8 +2137,8 @@ void set_mode(chptr, cptr, parc, parv, pcount, pvar, bounce) paracount = 1; *pcount = 0; - oldm = chptr->mode.mode; - oldl = chptr->mode.limit; + oldm = chptr->mode.mode; + oldl = chptr->mode.limit; for (curchr = parv[0]; *curchr; curchr++) { @@ -2156,16 +2160,6 @@ void set_mode(chptr, cptr, parc, parv, pcount, pvar, bounce) MyFree(tmpo); break; #endif - case 'I': - if (MyClient(cptr)) - { - break; - } - else - { - /* compatiblity */ - *curchr = 'V'; - } default: found = 0; tab = &cFlagTab[0]; @@ -2196,22 +2190,22 @@ void set_mode(chptr, cptr, parc, parv, pcount, pvar, bounce) #ifndef NO_OPEROVERRIDE if ((Halfop_mode(modetype) == FALSE) && opermode == 2 && htrig != 1) - htrig = 1; + { + opermode = 0; + htrig = 1; + } #endif /* We can afford to send off a param */ - /* if (parc - paracount < 1) */ if (parc <= paracount) parv[paracount] = NULL; if (parv[paracount] && strlen(parv[paracount]) >= MODEBUFLEN) parv[paracount][MODEBUFLEN-1] = '\0'; - { paracount += do_mode_char(chptr, modetype, *curchr, parv[paracount], what, cptr, pcount, pvar, bounce); - } break; } } @@ -2220,9 +2214,14 @@ void set_mode(chptr, cptr, parc, parv, pcount, pvar, bounce) #ifndef NO_OPEROVERRIDE if (htrig == 1) + { + /* This is horrible. Just horrible. */ + if (!((modebuf[0] == '+' || modebuf[0] == '-') && modebuf[1] == '\0')) sendto_umode(UMODE_EYES, "*** OperOverride -- %s (%s@%s) MODE %s %s %s", cptr->name, cptr->user->username, cptr->user->realhost, chptr->chname, modebuf, parabuf); + htrig = 0; + } #endif } @@ -2288,14 +2287,31 @@ static int can_join(cptr, sptr, chptr, key, link, parv) char *parv[]; { Link *lp; -#ifndef NO_OPEROVERRIDE - int ib = 1; -#else - int ib = 0; + + if ((chptr->mode.mode & MODE_ONLYSECURE) && + !(sptr->umodes & UMODE_SECURE)) + { + return (ERR_SECUREONLYCHAN); + } + + if ((chptr->mode.mode & MODE_OPERONLY) && !IsOper(sptr)) + return (ERR_OPERONLY); + + if ((chptr->mode.mode & MODE_ADMONLY) && !IsSkoAdmin(sptr)) + return (ERR_ADMONLY); + +#ifdef ENABLE_INVISOPER + if ((chptr->mode.mode & MODE_NOHIDING) && IsHiding(sptr)) + return (ERR_NOHIDING); #endif - - /* 0 = noone 1 = IRCops 2 = Net Admins 3 =Net admins (override) */ + if ((IsOper(sptr) && is_banned(cptr, sptr, chptr) + && (chptr->mode.mode & MODE_OPERONLY))) + return (ERR_BANNEDFROMCHAN); /* banned as an ircop at a +O cannot join */ + + for (lp = sptr->user->invited; lp; lp = lp->next) + if (lp->value.chptr == chptr) + return 0; if ((chptr->mode.limit && chptr->users >= chptr->mode.limit)) { @@ -2317,119 +2333,31 @@ static int can_join(cptr, sptr, chptr, key, link, parv) /* We check this later return (ERR_CHANNELISFULL); */ } - if ((chptr->mode.mode & MODE_ONLYSECURE) && - !(sptr->umodes & UMODE_SECURE)) - { - sendto_one(sptr, ":%s NOTICE %s :*** Cannot join: %s is a secure client-only channel (+z)", - me.name, sptr->name, chptr->chname); - return (ERR_SECUREONLYCHAN); - } - if ((chptr->mode.mode & MODE_OPERONLY) && !IsOper(sptr)) - { - return (ERR_OPERONLY); - } - if ((chptr->mode.mode & MODE_ADMONLY)) - { - if (!IsSkoAdmin(sptr)) - return (ERR_ADMONLY); - } - -#ifdef ENABLE_INVISOPER - if ((chptr->mode.mode & MODE_NOHIDING) && IsHiding(sptr)) - return (ERR_NOHIDING); -#endif - - if ((IsOper(sptr) && !((chptr->mode.mode & MODE_ADMONLY))) && !(ib==0)) - { - return 0; /* may override */ - } - if ((IsOper(sptr) && is_banned(cptr, sptr, chptr) - && (chptr->mode.mode & MODE_OPERONLY))) - return (ERR_BANNEDFROMCHAN); /* banned as an ircop at a +O cannot join */ - - switch (ib) - { - case 1: - if (IsOper(sptr)) - { - return 0; - } - break; - case 2: - if (IsNetAdmin(sptr)) - { - return 0; - } - break; - case 3: - if (IsNetAdmin(sptr)) - return 0; - break; - default: - break; - } if ((chptr->mode.mode & MODE_RGSTRONLY) && !IsARegNick(sptr)) return (ERR_NEEDREGGEDNICK); if (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key))) return (ERR_BADCHANNELKEY); - for (lp = sptr->user->invited; lp; lp = lp->next) - if (lp->value.chptr == chptr) - break; - - if ((chptr->mode.mode & MODE_INVITEONLY) && !lp) + if ((chptr->mode.mode & MODE_INVITEONLY)) return (ERR_INVITEONLYCHAN); if ((chptr->mode.limit && chptr->users >= chptr->mode.limit)) return (ERR_CHANNELISFULL); - if (is_banned(sptr, sptr, chptr) && !lp) + if (is_banned(sptr, sptr, chptr)) return (ERR_BANNEDFROMCHAN); +#ifdef OPEROVERRIDE_VERIFY + if (IsOper(sptr) && (chptr->mode.mode & MODE_SECRET || + chptr->mode.mode & MODE_PRIVATE)) + return (ERR_OPERSPVERIFY); +#endif + return 0; } -/* Sends notices to +e's about opers possibly abusing priv's - * By NiQuiL (niquil@programmer.net) - * suggestion by -ins4ne- - */ - -void over_notice(aClient *cptr, aClient *sptr, aChannel *chptr, char *key) -{ - Link *lp; - - for (lp = sptr->user->invited; lp; lp = lp->next) - if (lp->value.chptr == chptr) - break; - - *modebuf = *parabuf = '\0'; - channel_modes(cptr, modebuf, parabuf, chptr); - - if (is_banned(cptr, sptr, chptr) && IsOper(sptr) && !IsULine(sptr)) - { - sendto_umode(UMODE_EYES, "*** OperOverride -- %s (%s@%s) BANWALK %s",sptr->name, - sptr->user->username, sptr->user->realhost, chptr->chname); - } - - else if (IsOper(sptr) && !IsULine(sptr) && ( - (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key))) - || (chptr->mode.mode & MODE_INVITEONLY && !lp) - || (chptr->mode.mode & MODE_RGSTRONLY && !IsARegNick(sptr)) - || (chptr->mode.limit && chptr->users >= chptr->mode.limit) - ) - ) - { - *modebuf = *parabuf = '\0'; - channel_modes(cptr, modebuf, parabuf, chptr); - - sendto_umode(UMODE_EYES, "*** OperOverride -- %s (%s@%s) OPERWALK %s [%s]",sptr->name, - sptr->user->username, sptr->user->realhost, chptr->chname, - modebuf); - } -} - /* ** Remove bells and commas from channel name */ @@ -3031,7 +2959,6 @@ int m_join(cptr, sptr, parc, parv) /* ** Complete user entry to the new channel (if any) */ - (void)over_notice(cptr, sptr, chptr, key); add_user_to_channel(chptr, sptr, flags); /* ** notify all other users on the new channel @@ -3766,7 +3693,7 @@ int m_invite(cptr, sptr, parc, parv) { aClient *acptr; aChannel *chptr; - + short over = 0; if (parc < 3 || *parv[1] == '\0') { @@ -3779,32 +3706,50 @@ int m_invite(cptr, sptr, parc, parv) { sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]); - return 0; + return -1; } if (MyConnect(sptr)) clean_channelname(parv[2]); + if (check_channelmask(sptr, cptr, parv[2])) - return 0; + return -1; + if (!(chptr = find_channel(parv[2], NullChn))) { - - sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", - parv[0], parv[1], parv[2]); - return 0; + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), + me.name, parv[0], parv[2]); + return -1; } - if (chptr->mode.mode & MODE_NOINVITE) - if (!IsULine(sptr)) - { + + if (chptr->mode.mode & MODE_NOINVITE && !IsULine(sptr)) + { +#ifndef NO_OPEROVERRIDE + if (IsOper(sptr) && sptr == acptr) + over = 1; + else { +#endif sendto_one(sptr, err_str(ERR_NOINVITE), me.name, parv[0], parv[2]); return -1; +#ifndef NO_OPEROVERRIDE } - if (chptr && !IsMember(sptr, chptr) && !IsULine(sptr)) +#endif + } + + if (!IsMember(sptr, chptr) && !IsULine(sptr)) { - sendto_one(sptr, err_str(ERR_NOTONCHANNEL), - me.name, parv[0], parv[2]); - return -1; +#ifndef NO_OPEROVERRIDE + if (IsOper(sptr) && sptr == acptr) + over = 1; + else { +#endif + sendto_one(sptr, err_str(ERR_NOTONCHANNEL), + me.name, parv[0], parv[2]); + return -1; +#ifndef NO_OPEROVERRIDE + } +#endif } if (IsMember(acptr, chptr)) @@ -3813,20 +3758,37 @@ int m_invite(cptr, sptr, parc, parv) me.name, parv[0], parv[1], parv[2]); return 0; } - if (chptr && (chptr->mode.mode & MODE_INVITEONLY)) + + if (chptr->mode.mode & MODE_INVITEONLY) { if (!is_chan_op(sptr, chptr) && !IsULine(sptr)) { - sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), - me.name, parv[0], chptr->chname); - return -1; +#ifndef NO_OPEROVERRIDE + if (IsOper(sptr) && sptr == acptr) + over = 1; + else { +#endif + sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), + me.name, parv[0], chptr->chname); + return -1; +#ifndef NO_OPEROVERRIDE + } +#endif } else if (!IsMember(sptr, chptr) && !IsULine(sptr)) { - sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), - me.name, parv[0], - ((chptr) ? (chptr->chname) : parv[2])); - return -1; +#ifndef NO_OPEROVERRIDE + if (IsOper(sptr) && sptr == acptr) + over = 1; + else { +#endif + sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), + me.name, parv[0], + ((chptr) ? (chptr->chname) : parv[2])); + return -1; +#ifndef NO_OPEROVERRIDE + } +#endif } } @@ -3834,33 +3796,87 @@ int m_invite(cptr, sptr, parc, parv) { if (check_for_target_limit(sptr, acptr, acptr->name)) return 0; - - sendto_one(sptr, rpl_str(RPL_INVITING), me.name, - parv[0], acptr->name, - ((chptr) ? (chptr->chname) : parv[2])); - if (acptr->user->away) - sendto_one(sptr, rpl_str(RPL_AWAY), me.name, - parv[0], acptr->name, acptr->user->away); + if (!over) + { + sendto_one(sptr, rpl_str(RPL_INVITING), me.name, + parv[0], acptr->name, + ((chptr) ? (chptr->chname) : parv[2])); + if (acptr->user->away) + sendto_one(sptr, rpl_str(RPL_AWAY), me.name, + parv[0], acptr->name, acptr->user->away); + } } /* Note: is_banned() here will cause some extra CPU load, * and we're really only relying on the existence * of the limit because we could momentarily have * less people on channel. */ - if (MyConnect(acptr)) - if (chptr && sptr->user - && (is_banned(acptr, sptr, chptr) - || (chptr->mode.mode & MODE_INVITEONLY) - || chptr->mode.limit) && (is_chan_op(sptr, chptr) - || IsULine(sptr))) - { - add_invite(acptr, chptr); - sendto_channelops_butone(NULL, &me, chptr, - ":%s NOTICE @%s :%s invited %s into the channel.", - me.name, chptr->chname, sptr->name, acptr->name); - } + + /* Yes, it's crack induced. This checks if we should even bother going further */ + if (!(MyConnect(acptr) && chptr && sptr->user && + (is_chan_op(sptr,chptr) || IsULine(sptr) +#ifndef NO_OPEROVERRIDE + || IsOper(sptr) +#endif + ))) + return 0; + + if (is_banned(acptr, sptr, chptr)) + { + if (over) + sendto_umode(UMODE_EYES, + "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +b).", + sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname); + } + else if (chptr->mode.mode & MODE_INVITEONLY) + { + if (over) + sendto_umode(UMODE_EYES, + "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +i).", + sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname); + } + else if (chptr->mode.limit) + { + if (over) + sendto_umode(UMODE_EYES, + "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +l).", + sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname); + } + else if (chptr->mode.mode & MODE_RGSTRONLY) + { + if (over) + sendto_umode(UMODE_EYES, + "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +R).", + sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname); + } + else if (*chptr->mode.key) + { + if (over) + sendto_umode(UMODE_EYES, + "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +k).", + sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname); + } +#ifdef OPEROVERRIDE_VERIFY + else if (chptr->mode.mode & MODE_SECRET || chptr->mode.mode & MODE_PRIVATE) + over = -1; +#endif + else + return 0; + + if (over == 1) + sendto_channelops_butone(NULL, &me, chptr, + ":%s NOTICE @%s :OperOverride -- %s invited him/herself into the channel.", + me.name, chptr->chname, sptr->name); + else if (over == 0) + sendto_channelops_butone(NULL, &me, chptr, + ":%s NOTICE @%s :%s invited %s into the channel.", + me.name, chptr->chname, sptr->name, acptr->name); + + add_invite(acptr, chptr); + sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0], acptr->name, ((chptr) ? (chptr->chname) : parv[2])); + return 0; } @@ -4412,7 +4428,11 @@ int m_names(cptr, sptr, parc, parv) CHFL_CHANOWNER)) && acptr != sptr) continue; - if (cm->flags & CHFL_CHANOP) + if (cm->flags & CHFL_CHANOWNER) + buf[idx++] = '~'; + else if (cm->flags & CHFL_CHANPROT) + buf[idx++] = '&'; + else if (cm->flags & CHFL_CHANOP) buf[idx++] = '@'; else if (cm->flags & CHFL_HALFOP) buf[idx++] = '%'; @@ -4794,7 +4814,10 @@ int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]) } /* remove bans */ - parabuf[0] = '\0'; + modebuf[0] = '-'; + modebuf[1] = '\0'; + parabuf[0] = '\0'; + b = 1; for (ban = chptr->banlist; ban; ban = ban->next) { Addit('b', ban->banstr); @@ -4803,7 +4826,6 @@ int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Addit('e', ban->banstr); } - b = 1; for (lp = chptr->members; lp; lp = lp->next) { if (lp->flags & MODE_CHANOWNER) diff --git a/src/s_err.c b/src/s_err.c index c34302f3c..1d773a08a 100644 --- a/src/s_err.c +++ b/src/s_err.c @@ -574,9 +574,9 @@ static char *replies[] = { /* 519 519 */ ":%s 519 %s :Cannot join channel (Admin only)", /* 520 520 */ ":%s 520 %s :Cannot join channel (IRCops only)", /* 521 ERR_LISTSYNTAX */ ":%s 521 %s Bad list syntax, type /quote list ? or /raw list ?", -/* 522 */ NULL, +/* 522 */ NULL, /* 523 */ NULL, -/* 524 */ NULL, +/* 524 ERR_OPERSPVERIFY */ ":%s 524 %s :Trying to join +s or +p channel as an oper. Please invite yourself first.", /* 525 */ NULL, /* 526 */ NULL, /* 527 */ NULL, diff --git a/src/s_kline.c b/src/s_kline.c index ab759a32c..ffbf2f561 100644 --- a/src/s_kline.c +++ b/src/s_kline.c @@ -759,7 +759,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (IsServer(sptr)) { - return; + return 0; } if (!IsOper(sptr)) { @@ -772,7 +772,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "GZLINE"); - return; + return 0; } mask = parv[1]; @@ -782,7 +782,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "GZLINE"); - return; + return 0; } whattodo = 1; mask++; @@ -793,7 +793,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "GZLINE"); - return; + return 0; } whattodo = 0; mask++; @@ -804,7 +804,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "GZLINE"); - return; + return 0; } } @@ -818,9 +818,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } - if (whattodo == 1) - goto nochecks; - if (p) + if (p && whattodo != 1) { p++; i = 0; @@ -839,17 +837,24 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) } } - nochecks: usermask = strtok(mask, "@"); hostmask = strtok(NULL, ""); tkl_check_expire(); + if (BadPtr(hostmask)) + { + if (BadPtr(usermask)) + return 0; + hostmask = usermask; + usermask = "*"; + } + for (tk = tklines; tk; tk = tk->next) { if (tk->type == (TKL_GLOBAL | TKL_ZAP)) { - if (!match(tk->hostmask, usermask) - && !match(tk->usermask, hostmask)) + if (!match(tk->hostmask, hostmask) + && !match(tk->usermask, usermask)) { found = 1; break; @@ -864,7 +869,7 @@ int m_gzline(aClient *cptr, aClient *sptr, int parc, char *parv[]) me.name, sptr->name); return 0; } - if ((found == 1) && whattodo == 1) + if ((found == 0) && whattodo == 1) { sendto_one(sptr, ":%s NOTICE %s :*** [Z:Line error] No such Z:Line", me.name, @@ -1008,9 +1013,7 @@ int m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; } - if (whattodo == 1) - goto nochecks; - if (p) + if (p && whattodo != 1) { p++; i = 0; @@ -1029,17 +1032,24 @@ int m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[]) } } - nochecks: usermask = strtok(mask, "@"); hostmask = strtok(NULL, ""); tkl_check_expire(); + if (BadPtr(hostmask)) + { + if (BadPtr(usermask)) + return 0; + hostmask = usermask; + usermask = "*"; + } + for (tk = tklines; tk; tk = tk->next) { if (tk->type == (TKL_GLOBAL | TKL_KILL)) { - if (!match(tk->hostmask, usermask) - && !match(tk->usermask, hostmask)) + if (!match(tk->hostmask, hostmask) + && !match(tk->usermask, usermask)) { found = 1; break; @@ -1054,7 +1064,7 @@ int m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[]) me.name, sptr->name); return 0; } - if ((found == 1) && whattodo == 1) + if ((found == 0) && whattodo == 1) { sendto_one(sptr, ":%s NOTICE %s :*** [G:Line error] No such G:Line", me.name, diff --git a/src/s_user.c b/src/s_user.c index 7b40eb22c..cf79b71a5 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -2512,8 +2512,15 @@ static void do_who(sptr, acptr, repchan) status[i++] = '!'; #endif + + /* Channel owner */ + if (repchan && is_chanowner(acptr, repchan)) + status[i++] = '~'; + /* Channel protected */ + else if (repchan && is_chanprot(acptr, repchan)) + status[i++] = '&'; /* Channel operator */ - if (repchan && is_chan_op(acptr, repchan)) + else if (repchan && is_chan_op(acptr, repchan)) status[i++] = '@'; /* Channel halfop */ @@ -2610,6 +2617,7 @@ int m_who(cptr, sptr, parc, parv) sendto_one(sptr, rpl_str(RPL_ENDOFWHO), me.name, parv[0], BadPtr(mask) ? "*" : mask); + return 0; } /* List all users on a given channel */ @@ -2702,18 +2710,23 @@ int m_whois(cptr, sptr, parc, parv) char *parv[]; { static anUser UnknownUser = { - NULL, /* nextu */ - NULL, /* channel */ - NULL, /* invited */ - NULL, /* silence */ - NULL, /* away */ - 0, /* last */ - 0, /* servicestamp */ - 1, /* refcount */ - 0, /* joined */ - "", /* username */ - "", /* host */ - "" /* server */ + "", /* host */ + "", /* username */ + NULL, /* nextu */ + NULL, /* channel */ + NULL, /* invited */ + NULL, /* silence */ + NULL, /* away */ + NULL, /* virthost */ + NULL, /* server */ + NULL, /* swhois */ + NULL, /* serv */ + NULL, /* Lopts */ + NULL, /* whowas */ + 0, /* last */ + 0, /* servicestamp */ + 0, /* joined */ + 1 /* refcount */ }; Link *lp; anUser *user; @@ -2866,16 +2879,17 @@ int m_whois(cptr, sptr, parc, parv) len = 0; } #ifdef SHOW_SECRET - if (!(acptr == sptr) && IsAnOper(sptr) + if (!(acptr == sptr) && IsAnOper(sptr) #else - if (!(acptr == sptr) && (IsNetAdmin(sptr)) + if (!(acptr == sptr) + && IsNetAdmin(sptr) #endif - && (showsecret == 1) && SecretChannel(chptr)) - *(buf + len++) = '~'; + && SecretChannel(chptr)) + *(buf + len++) = '!'; if (is_chanowner(acptr, chptr)) - *(buf + len++) = '*'; + *(buf + len++) = '~'; else if (is_chanprot(acptr, chptr)) - *(buf + len++) = '^'; + *(buf + len++) = '&'; else if (is_chan_op(acptr, chptr)) *(buf + len++) = '@'; else if (is_half_op(acptr, chptr)) @@ -3156,18 +3170,23 @@ int m_kill(cptr, sptr, parc, parv) char *parv[]; { static anUser UnknownUser = { - NULL, /* nextu */ - NULL, /* channel */ - NULL, /* invited */ - NULL, /* silence */ - NULL, /* away */ - 0, /* last */ - 0, /* servicestamp */ - 1, /* refcount */ - 0, /* joined */ - "", /* username */ - "", /* host */ - "" /* server */ + "", /* host */ + "", /* username */ + NULL, /* nextu */ + NULL, /* channel */ + NULL, /* invited */ + NULL, /* silence */ + NULL, /* away */ + NULL, /* virthost */ + NULL, /* server */ + NULL, /* swhois */ + NULL, /* serv */ + NULL, /* Lopts */ + NULL, /* whowas */ + 0, /* last */ + 0, /* servicestamp */ + 0, /* joined */ + 1 /* refcount */ }; aClient *acptr; anUser *auser; diff --git a/src/webtv.c b/src/webtv.c index 7436c3aaf..a19b269b2 100644 --- a/src/webtv.c +++ b/src/webtv.c @@ -130,18 +130,23 @@ int webtv_parse(aClient *sptr, char *string) int w_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) { static anUser UnknownUser = { - NULL, /* nextu */ - NULL, /* channel */ - NULL, /* invited */ - NULL, /* silence */ - NULL, /* away */ - 0, /* last */ - 0, /* servicestamp */ - 1, /* refcount */ - 0, /* joined */ - "", /* username */ - "", /* host */ - "" /* server */ + "", /* host */ + "", /* username */ + NULL, /* nextu */ + NULL, /* channel */ + NULL, /* invited */ + NULL, /* silence */ + NULL, /* away */ + NULL, /* virthost */ + NULL, /* server */ + NULL, /* swhois */ + NULL, /* serv */ + NULL, /* Lopts */ + NULL, /* whowas */ + 0, /* last */ + 0, /* servicestamp */ + 0, /* joined */ + 1 /* refcount */ }; Link *lp; anUser *user;