"Fossies" - the Fresh Open Source Software Archive

Member "bahamut-2.1.5/src/s_user.c" (28 May 2020, 137541 Bytes) of package /linux/privat/bahamut-2.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "s_user.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.4_vs_2.1.5.

    1 /************************************************************************
    2  *   IRC - Internet Relay Chat, src/s_user.c
    3  *   Copyright (C) 1990 Jarkko Oikarinen and
    4  *                      University of Oulu, Computing Center
    5  *
    6  *   See file AUTHORS in IRC package for additional names of
    7  *   the programmers.
    8  *
    9  *   This program is free softwmare; you can redistribute it and/or modify
   10  *   it under the terms of the GNU General Public License as published by
   11  *   the Free Software Foundation; either version 1, or (at your option)
   12  *   any later version.
   13  *
   14  *   This program is distributed in the hope that it will be useful,
   15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *   GNU General Public License for more details.
   18  *
   19  *   You should have received a copy of the GNU General Public License
   20  *   along with this program; if not, write to the Free Software
   21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   22  */
   23 
   24 #include "struct.h"
   25 #include "common.h"
   26 #include "sys.h"
   27 #include "numeric.h"
   28 #include "msg.h"
   29 #include "channel.h"
   30 #include "throttle.h"
   31 #include "clones.h"
   32 #include <sys/stat.h>
   33 #include <fcntl.h>
   34 #include "h.h"
   35 #ifdef FLUD
   36 #include "blalloc.h"
   37 #endif /* FLUD */
   38 #include "userban.h"
   39 #include "hooks.h"
   40 #include "memcount.h"
   41 #include "inet.h"
   42 #include "spamfilter.h"
   43 
   44 #if defined( HAVE_STRING_H)
   45 #include <string.h>
   46 #else
   47 #include <strings.h>
   48 #endif
   49 
   50 int do_user(char *, aClient *, aClient *, char *, char *, char *,
   51             unsigned long, char *, char *);
   52 extern char motd_last_changed_date[];
   53 extern int  send_motd(aClient *, aClient *, int, char **);
   54 extern void send_topic_burst(aClient *);
   55 extern void outofmemory(void);  /* defined in list.c */
   56 #ifdef MAXBUFFERS
   57 extern void reset_sock_opts();
   58 extern int send_lusers(aClient *,aClient *,int, char **);
   59 #endif
   60 extern int is_xflags_exempted(aClient *sptr, aChannel *chptr); /* for m_message() */
   61 extern int verbose_to_relaychan(aClient *sptr, aChannel *chptr, char *cmd, char *reason); /* for m_message() */
   62 extern inline void verbose_to_opers(aClient *sptr, aChannel *chptr, char *cmd, char *reason); /* for m_message() */
   63 extern time_t get_user_jointime(aClient *cptr, aChannel *chptr); /* for send_msg_error() */
   64 extern time_t get_user_lastmsgtime(aClient *cptr, aChannel *chptr); /* also for send_msg_error() -Holbrook */
   65 extern int server_was_split;
   66 extern int svspanic;
   67 extern int svsnoop;
   68 extern int uhm_type;
   69 extern int uhm_umodeh;
   70 
   71 static char buf[BUFSIZE], buf2[BUFSIZE];
   72 int  user_modes[] =
   73 {
   74     UMODE_o, 'o',
   75     UMODE_O, 'O',
   76     UMODE_i, 'i',
   77     UMODE_w, 'w',
   78     UMODE_s, 's',
   79     UMODE_c, 'c',
   80     UMODE_C, 'C',
   81     UMODE_r, 'r',
   82     UMODE_R, 'R',
   83     UMODE_k, 'k',
   84     UMODE_y, 'y',
   85     UMODE_d, 'd',
   86     UMODE_e, 'e',
   87     UMODE_g, 'g',
   88     UMODE_b, 'b',
   89     UMODE_a, 'a',
   90     UMODE_A, 'A',
   91     UMODE_f, 'f',
   92     UMODE_n, 'n',
   93     UMODE_m, 'm',
   94     UMODE_h, 'h',
   95 #ifdef USER_HOSTMASKING
   96     UMODE_H, 'H',
   97 #endif
   98 #ifdef NO_OPER_FLOOD
   99     UMODE_F, 'F',
  100 #endif
  101     UMODE_x, 'x',
  102     UMODE_X, 'X',
  103     UMODE_j, 'j',
  104     UMODE_S, 'S',
  105     UMODE_K, 'K',
  106     UMODE_I, 'I',
  107 #ifdef SPAMFILTER
  108     UMODE_P, 'P',
  109 #endif
  110     0, 0
  111 };
  112 
  113 /* externally defined functions */
  114 extern Link *find_channel_link(Link *, aChannel *);     /* defined in list.c */
  115 #ifdef FLUD
  116 int         flud_num = FLUD_NUM;
  117 int         flud_time = FLUD_TIME;
  118 int         flud_block = FLUD_BLOCK;
  119 extern BlockHeap *free_fludbots;
  120 extern BlockHeap *free_Links;
  121 
  122 void        announce_fluder(aClient *, aClient *, aChannel *, int);
  123 struct fludbot *remove_fluder_reference(struct fludbot **, aClient *);
  124 Link       *remove_fludee_reference(Link **, void *);
  125 int         check_for_fludblock(aClient *, aClient *, aChannel *, int);
  126 int         check_for_flud(aClient *, aClient *, aChannel *, int);
  127 void        free_fluders(aClient *, aChannel *);
  128 void        free_fludees(aClient *);
  129 #endif
  130 
  131 #ifdef ANTI_SPAMBOT
  132 int         spam_time = MIN_JOIN_LEAVE_TIME;
  133 int         spam_num = MAX_JOIN_LEAVE_COUNT;
  134 #endif
  135 
  136 /* defines for check_ctcp results */
  137 #define CTCP_NONE       0
  138 #define CTCP_YES        1
  139 #define CTCP_DCC        2
  140 #define CTCP_DCCSEND    3
  141 
  142 
  143 /*
  144  * cptr:
  145  ** always NON-NULL, pointing to a *LOCAL* client
  146  ** structure (with an open socket connected!). This
  147  ** is the physical socket where the message originated (or
  148  ** which caused the m_function to be executed--some
  149  ** m_functions may call others...).
  150  *
  151  * sptr:
  152  ** the source of the message, defined by the
  153  ** prefix part of the message if present. If not or
  154  ** prefix not found, then sptr==cptr.
  155  *
  156  *      *Always* true (if 'parse' and others are working correct):
  157  *
  158  *      1      sptr->from == cptr  (note: cptr->from == cptr)
  159  *
  160  *      2      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
  161  * cannot be a local connection, unless it's actually cptr!).
  162  *
  163  * MyConnect(x) should probably  be defined as (x == x->from) --msa
  164  *
  165  * parc:
  166  ** number of variable parameter strings (if zero,
  167  ** parv is allowed to be NULL)
  168  *
  169  * parv:
  170  ** a NULL terminated list of parameter pointers,
  171  *** parv[0], sender (prefix string), if not present his points to
  172  *** an empty string.
  173  *
  174  ** [parc-1]:
  175  *** pointers to additional parameters
  176  *** parv[parc] == NULL, *always*
  177  *
  178  * note:   it is guaranteed that parv[0]..parv[parc-1] are all
  179  *         non-NULL pointers.
  180  */
  181 /*
  182  * * next_client 
  183  * Local function to find the next matching
  184  * client. The search can be continued from the specified client
  185  * entry. Normal usage loop is: 
  186  * 
  187  *      for (x = client; x = next_client(x,mask); x = x->next) 
  188  *          HandleMatchingClient; 
  189  * 
  190  */
  191 aClient *
  192 next_client(aClient *next, char *ch)
  193 {                               
  194     /* search string (may include wilds) */
  195     aClient *tmp = next;
  196     
  197     next = find_client(ch, tmp);
  198     if (tmp && tmp->prev == next)
  199         return ((aClient *) NULL);
  200 
  201     if (next != tmp)
  202         return next;
  203     while(next) 
  204     {
  205         if (!match(ch, next->name))
  206             break;
  207         next = next->next;
  208     }
  209     return next;
  210 }
  211 
  212 /* this slow version needs to be used for hostmasks *sigh * */
  213 
  214 aClient *
  215 next_client_double(aClient *next, char *ch)
  216 {                               
  217     /* search string (may include wilds) */
  218     aClient *tmp = next;
  219 
  220     next = find_client(ch, tmp);
  221     if (tmp && tmp->prev == next)
  222         return NULL;
  223     if (next != tmp)
  224         return next;
  225     while(next) 
  226     {
  227         if (!match(ch, next->name) || !match(next->name, ch))
  228             break;
  229         next = next->next;
  230     }
  231     return next;
  232 }
  233 
  234 /*
  235  * hunt_server
  236  * 
  237  *      Do the basic thing in delivering the message (command)
  238  * across the relays to the specific server (server) for
  239  * actions.
  240  * 
  241  *      Note:   The command is a format string and *MUST* be
  242  * of prefixed style (e.g. ":%s COMMAND %s ...").
  243  * Command can have only max 8 parameters.
  244  * 
  245  * server  parv[server] is the parameter identifying the target server.
  246  * 
  247  *      *WARNING* 
  248  * parv[server] is replaced with the pointer to the 
  249  * real servername from the matched client
  250  * I'm lazy now --msa
  251  *
  252  * intelligence rewrite  -Quension [May 2005]
  253  * 
  254  *      returns: (see #defines)
  255  */
  256 int 
  257 hunt_server(aClient *cptr, aClient *sptr, char *command, int server,
  258                 int parc, char *parv[])
  259 {
  260     aClient    *acptr = NULL;
  261 
  262     /* Assume it's me, if no server */
  263     if (parc <= server || BadPtr(parv[server]))
  264         return (HUNTED_ISME);
  265 
  266     collapse(parv[server]);
  267 
  268     /* check self first, due to the weirdness of STAT_ME */
  269     if (!match(parv[server], me.name))
  270         return HUNTED_ISME;
  271 
  272     if (strchr(parv[server], '?') || strchr(parv[server], '*'))
  273     {
  274         /* it's a mask, find the server manually */
  275         for (acptr = client; acptr; acptr = acptr->next)
  276         {
  277             if (!IsServer(acptr))
  278                 continue;
  279 
  280             if (!match(parv[server], acptr->name))
  281             {
  282                 parv[server] = acptr->name;
  283                 break;
  284             }
  285         }
  286     }
  287     else
  288     {
  289         /* no wildcards, hash lookup */
  290         acptr = find_client(parv[server], NULL);
  291 
  292         if (acptr && !IsRegistered(acptr))
  293             acptr = NULL;
  294     }
  295 
  296     if (!acptr)
  297     {
  298         sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0],
  299                    parv[server]);
  300         return HUNTED_NOSUCH;
  301     }
  302 
  303 #ifdef NO_USER_OPERTARGETED_COMMANDS
  304     if (MyClient(sptr) && !IsAnOper(sptr) && IsUmodeI(acptr))
  305     {
  306         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  307         return HUNTED_NOSUCH;
  308     }
  309 #endif
  310 
  311     if(IsULine(acptr) && (svspanic>1 || (svspanic>0 && !IsARegNick(sptr))) && !IsOper(sptr))
  312     {
  313         if(MyClient(sptr))
  314             sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0],
  315                        acptr->name);
  316         return HUNTED_NOSUCH;
  317     }
  318 
  319     if (MyClient(acptr))
  320         return HUNTED_ISME;
  321 
  322     sendto_one(acptr, command, parv[0], parv[1], parv[2], parv[3], parv[4],
  323                parv[5], parv[6], parv[7], parv[8]);
  324     return HUNTED_PASS;
  325 }
  326 
  327 /*
  328  * canonize
  329  * 
  330  * reduce a string of duplicate list entries to contain only the unique
  331  * items.  Unavoidably O(n^2).
  332  */
  333 char *
  334 canonize(char *buffer)
  335 {
  336     static char cbuf[BUFSIZ];
  337     char *s, *t, *cp = cbuf;
  338     int l = 0;
  339     char *p = NULL, *p2;
  340 
  341     *cp = '\0';
  342     
  343     for (s = strtoken(&p, buffer, ","); s; s = strtoken(&p, NULL, ",")) 
  344     {
  345         if (l) 
  346         {
  347             for (p2 = NULL, t = strtoken(&p2, cbuf, ","); t;
  348                  t = strtoken(&p2, NULL, ","))
  349                 if (!mycmp(s, t))
  350                     break;
  351                 else if (p2)
  352                     p2[-1] = ',';
  353         }
  354         else
  355             t = NULL;
  356 
  357         if (!t) 
  358         {
  359             if (l)
  360                 *(cp - 1) = ',';
  361             else
  362                 l = 1;
  363             (void) strcpy(cp, s);
  364             if (p)
  365                 cp += (p - s);
  366         }
  367         else if (p2)
  368             p2[-1] = ',';
  369     }
  370     return cbuf;
  371 }
  372 
  373 /* msg_has_utf8 - check if a message has high ASCII code characters.
  374                   It doesn't have to be UTF8 really, Hebrew and Arabic
  375                   characters will match as well... -Kobi_S.
  376  */
  377 int msg_has_utf8(char *text)
  378 {
  379     if(text == NULL) return 0;
  380 
  381     while(*text)
  382     {
  383         if((unsigned char)*text > 127 && *text!='<' && *text!='>') return 1;
  384         text++;
  385     }
  386 
  387     return 0;
  388 }
  389 
  390 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
  391 static int
  392 check_oper_can_mask(aClient *sptr, char *name, char *password, char **onick)
  393 {
  394     aOper *aoper;
  395     char *encr;
  396     extern char *crypt();
  397 
  398     if(!(aoper = find_oper(name, sptr->user->username, sptr->user->host,
  399                            sptr->hostip)))
  400     {
  401         sendto_ops_lev(ADMIN_LEV, "Failed OPERMASK attempt by %s (%s@%s) [Unknown Account %s]",
  402                        sptr->name, sptr->user->username, sptr->user->host, name);
  403         sendto_realops("Failed OPERMASK attempt by %s [Unknown account %s]",
  404                        sptr->name, name);
  405 
  406         return 0;
  407     }
  408 
  409     /* use first two chars of the password they send in as salt */
  410     /* passwd may be NULL pointer. Head it off at the pass... */
  411     if(confopts & FLAGS_CRYPTPASS)
  412     {
  413         if (password && *aoper->passwd)
  414             encr = crypt(password, aoper->passwd);
  415         else
  416             encr = "";
  417     }
  418     else
  419         encr = password;
  420 
  421     if(StrEq(encr, aoper->passwd))
  422     {
  423 #ifdef USE_SYSLOG
  424         syslog(LOG_INFO, "OPERMASK: %s (%s!%s@%s)", aoper->nick, sptr->name,
  425                sptr->user->username, sptr->user->host);
  426 #endif
  427         *onick = aoper->nick;
  428         sendto_realops("%s [%s] (%s@<hidden>) has masked their hostname.",
  429                        sptr->name, aoper->nick, sptr->user->username);
  430         return 1;
  431     }
  432 
  433     sendto_ops_lev(ADMIN_LEV, "Failed OPERMASK attempt by %s (%s@%s) [Bad Password for %s]",
  434                    sptr->name, sptr->user->username, sptr->user->host, name);
  435     sendto_realops("Failed OPERMASK attempt by %s [Bad Password for %s]", sptr->name, name);
  436 
  437     return 0;
  438 }
  439 #endif
  440 
  441 
  442 /* used by m_user, m_put, m_post */
  443 static int
  444 reject_proxy(aClient *cptr, char *cmd, char *args)
  445 {
  446     sendto_realops_lev(REJ_LEV, "proxy attempt from %s: %s %s",
  447                        cipntoa(cptr), cmd, args ? args : "");
  448     return exit_client(cptr, cptr, &me, "relay connection");
  449 }
  450 
  451 
  452 /* mask_host - Gets a normal host or ip and return them masked.
  453  * -Kobi_S 19/12/2015
  454  */
  455 char *mask_host(char *orghost, int type)
  456 {
  457     static char newhost[HOSTLEN + 1];
  458 
  459     if(!type) type = uhm_type;
  460 
  461     if (call_hooks(CHOOK_MASKHOST, orghost, &newhost, type) == UHM_SUCCESS) return newhost;
  462 
  463     return orghost; /* I guess the user won't be host-masked after all... :( */
  464 }
  465 
  466 
  467 /*
  468  * * register_user 
  469  *  This function is called when both NICK and USER messages 
  470  *  have been accepted for the client, in whatever order.  Only 
  471  *  after this, is the USER message propagated.
  472  * 
  473  *      NICK's must be propagated at once when received, although
  474  * it would be better to delay them too until full info is
  475  * available. Doing it is not so simple though, would have to
  476  * implement the following:
  477  * 
  478  *      (actually it has been implemented already for a while)
  479  * -orabidoo
  480  * 
  481  * 1 user telnets in and gives only "NICK foobar" and waits
  482  * 2 another user far away logs in normally with the nick
  483  * "foobar" quite legal, as this server didnt propagate it.
  484  * 3 now this server gets nick "foobar" from outside, but has
  485  * already the same defined locally. Current server would just
  486  * issue "KILL foobar" to clean out dups. But, this is not
  487  * fair. It should actually request another nick from local user
  488  * or kill him/her...
  489  */
  490 
  491 int 
  492 register_user(aClient *cptr, aClient *sptr, char *nick, char *username,
  493           char *hostip)
  494 {
  495     aAllow  *pwaconf = NULL;
  496     char       *parv[3];
  497     static char ubuf[54];
  498     char       *p;
  499     anUser     *user = sptr->user;
  500     struct userBan    *ban;
  501     aMotd      *smotd;
  502     int         i, dots;
  503     int         bad_dns;                /* flag a bad dns name */
  504 #ifdef ANTI_SPAMBOT
  505     char        spamchar = '\0';
  506 
  507 #endif
  508     char        tmpstr2[512];
  509 
  510     user->last = timeofday;
  511     parv[0] = sptr->name;
  512     parv[1] = parv[2] = NULL;
  513           
  514     p = hostip ? hostip : cipntoa(sptr);
  515     strncpyzt(sptr->hostip, p, HOSTIPLEN + 1);
  516     if (MyConnect(sptr)) 
  517     {
  518         if ((i = check_client(sptr))) 
  519         {
  520             switch (i)
  521             {
  522                 case -1:
  523                     ircstp->is_ref++;
  524                     sendto_realops_lev(REJ_LEV, "%s from %s [Unauthorized"
  525                                        " client connection]",
  526                                        get_client_name(sptr, FALSE), p);
  527                     return exit_client(cptr, sptr, &me, "You are not"
  528                                        " authorized to use this server");
  529 
  530                 case -2:
  531                     return exit_client(cptr, sptr, &me, "Socket Error");
  532 
  533                 case -3:
  534                     ircstp->is_ref++;
  535                     sendto_realops_lev(REJ_LEV, "%s for %s [Allow class is"
  536                                        " full (server is full)]",
  537                                        get_client_name(sptr, FALSE), p);
  538                     return exit_client(cptr, sptr, &me, "No more connections"
  539                                        " allowed in your connection class (the"
  540                                        " server is full)");
  541 
  542                 default:
  543                     sendto_realops_lev(DEBUG_LEV, "I don't know why I dropped"
  544                                        " %s (%d)", get_client_name(sptr,FALSE),
  545                                        i);
  546                     return exit_client(cptr, sptr, &me, "Internal error");
  547             }
  548         }
  549 
  550         if (sptr->user->allow->flags & CONF_FLAGS_NOTHROTTLE)
  551             throttle_remove(cptr->hostip);
  552 
  553         if (sptr->user->allow->flags & CONF_FLAGS_FORCEFLOOD)
  554             SetNoMsgThrottle(sptr);
  555 
  556 #ifdef ANTI_SPAMBOT
  557         /* This appears to be broken */
  558         /* Check for single char in user->host -ThemBones */
  559         if (*(user->host + 1) == '\0')
  560             spamchar = *user->host;
  561 #endif
  562                 
  563         strncpyzt(user->host, sptr->sockhost, HOSTLEN + 1);
  564                 
  565         dots = 0;
  566         p = user->host;
  567         bad_dns = NO;
  568         while (*p) 
  569         {
  570             if (!IsAlnum(*p)) 
  571             {
  572 #ifdef RFC1035_ANAL
  573                 if ((*p != '-') && (*p != '.'))
  574 #else
  575                     if ((*p != '-') && (*p != '.') && (*p != '_') &&
  576                         (*p != '/'))
  577 #endif /* RFC1035_ANAL */
  578                         bad_dns = YES;
  579             }
  580             if (*p == '.')
  581                 dots++;
  582             p++;
  583         }
  584         /*
  585          * Check that the hostname has AT LEAST ONE dot (.) in it. If
  586          * not, drop the client (spoofed host) -ThemBones
  587      *
  588      * allow valid IPv6 addresses, though.
  589          */
  590     if (sptr->ip_family == AF_INET6 &&
  591         inet_pton(AF_INET6, user->host, tmpstr2) == 1)
  592     {
  593         bad_dns = NO;
  594         dots = 1;
  595     }
  596 
  597     if (!dots) 
  598         {
  599             sendto_realops("Invalid hostname for %s, dumping user %s",
  600                            sptr->hostip, sptr->name);
  601             return exit_client(cptr, sptr, &me, "Invalid hostname");
  602         }
  603         
  604         if (bad_dns) 
  605         {
  606             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- You have a bad "
  607                        "character in your hostname", me.name, cptr->name);
  608             strcpy(user->host, sptr->hostip);
  609             strcpy(sptr->sockhost, sptr->hostip);
  610         }
  611 
  612 #ifdef USER_HOSTMASKING
  613         strncpyzt(user->mhost, mask_host(user->host,0), HOSTLEN + 1);
  614 #endif
  615         
  616         pwaconf = sptr->user->allow;
  617 
  618         if (sptr->flags & FLAGS_DOID && !(sptr->flags & FLAGS_GOTID)) 
  619         {
  620             /* because username may point to user->username */
  621             char        temp[USERLEN + 1];
  622             
  623             strncpyzt(temp, username, USERLEN + 1);
  624             *user->username = '~';
  625             (void) strncpy(&user->username[1], temp, USERLEN);
  626             user->username[USERLEN] = '\0';
  627 #ifdef IDENTD_COMPLAIN
  628             /* tell them to install identd -Taner */
  629             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- It seems that you "
  630                        "don't have identd installed on your host.",
  631                        me.name, cptr->name);
  632             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- If you wish to "
  633                        "have your username show up without the ~ (tilde),",
  634                        me.name, cptr->name);
  635             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- then install "
  636                        "identd.", me.name, cptr->name);
  637             /* end identd hack */
  638 #endif
  639         }
  640         else if (sptr->flags & FLAGS_GOTID && *sptr->username != '-')
  641             strncpyzt(user->username, sptr->username, USERLEN + 1);
  642         else if(username != user->username) /* don't overlap */
  643             strncpyzt(user->username, username, USERLEN + 1);
  644 
  645         if (!BadPtr(pwaconf->passwd))
  646         {
  647             char *tmpptr = strchr(sptr->passwd, ':');
  648             char tmppwd[PASSWDLEN + 1];
  649 
  650             /*
  651              * If there's a : in the password, fix it so after this function,
  652              * sptr->passwd changes from:
  653              * moo:cow:test:asdf
  654              * to
  655              * cow:test:asdf
  656              */
  657 
  658             if(tmpptr)
  659             {
  660                 *tmpptr++ = '\0';
  661                 strcpy(tmppwd, tmpptr);
  662             }
  663 
  664             if(!StrEq(sptr->passwd, pwaconf->passwd)) 
  665             {
  666                 ircstp->is_ref++;
  667                 sendto_one(sptr, err_str(ERR_PASSWDMISMATCH),
  668                            me.name, parv[0]);
  669                 return exit_client(cptr, sptr, &me, "Bad Password");
  670             }
  671             if(tmpptr)
  672                 strcpy(sptr->passwd, tmppwd);
  673             else
  674                 sptr->passwd[0] = '\0';
  675         }
  676 
  677                 
  678         /* Limit clients */
  679         /*
  680          * We want to be able to have servers and F-line clients connect,
  681          * so save room for "buffer" connections. Smaller servers may
  682          * want to decrease this, and it should probably be just a
  683          * percentage of the MAXCLIENTS... -Taner
  684          * Flines are now no different than Elines
  685          * And now there are no special clients, and this is the only thing
  686          * MAXCLIENTS is checked against.  So no more buffer space.
  687          */
  688         if (Count.local > MAXCLIENTS)
  689         { 
  690             sendto_realops_lev(SPY_LEV, "Too many clients, rejecting %s[%s].",
  691                                nick, sptr->sockhost);
  692             ircstp->is_ref++;
  693             return exit_client(cptr, sptr, &me,
  694                                "Sorry, server is full - try later");
  695         }
  696         
  697 #ifdef ANTI_SPAMBOT
  698         /* It appears, this is catching normal clients */
  699         /* Reject single char user-given user->host's */
  700         if (spamchar == 'x') 
  701         {
  702             sendto_realops_lev(REJ_LEV, "Rejecting possible Spambot: %s "
  703                                "(Single char user-given userhost: %c)",
  704                                get_client_name(sptr, FALSE), spamchar);
  705             ircstp->is_ref++;
  706             return exit_client(cptr, sptr, sptr, "Spambot detected, "
  707                                "rejected.");
  708         }
  709 #endif
  710                 
  711 
  712         /* hostile username checks begin here */
  713         
  714         {
  715             char *tmpstr;
  716             u_char      c, cc;
  717             int lower, upper, special;
  718             
  719             lower = upper = special = cc = 0;
  720                           
  721             /* check for "@" in identd reply -Taner */
  722             if ((strchr(user->username, '@') != NULL) ||
  723                 (strchr(username, '@') != NULL)) 
  724             {
  725                 sendto_realops_lev(REJ_LEV,
  726                                    "Illegal \"@\" in username: %s (%s)",
  727                                    get_client_name(sptr, FALSE), username);
  728                 ircstp->is_ref++;
  729                 (void) ircsprintf(tmpstr2,
  730                                   "Invalid username [%s] - '@' is not allowed",
  731                                   username);
  732                 return exit_client(cptr, sptr, sptr, tmpstr2);
  733             }
  734             /* First check user->username... */
  735 #ifdef IGNORE_FIRST_CHAR
  736             tmpstr = (user->username[0] == '~' ? &user->username[2] :
  737                       &user->username[1]);
  738             /*
  739              * Ok, we don't want to TOTALLY ignore the first character. We
  740              * should at least check it for control characters, etc -
  741              * ThemBones
  742              */
  743             cc = (user->username[0] == '~' ? user->username[1] :
  744                   user->username[0]);
  745             if ((!IsAlnum(cc) && !strchr(" -_.", cc)) || (cc > 127))
  746                 special++;
  747 #else
  748             tmpstr = (user->username[0] == '~' ? &user->username[1] :
  749                       user->username);
  750 #endif /* IGNORE_FIRST_CHAR */
  751             
  752             while (*tmpstr) 
  753             {
  754                 c = *(tmpstr++);
  755                 if (IsLower(c)) 
  756                 {
  757                     lower++;
  758                     continue;
  759                 }
  760                 if (IsUpper(c)) 
  761                 {
  762                     upper++;
  763                     continue;
  764                 }
  765                 if ((!IsAlnum(c) && !strchr(" -_.", c)) || (c > 127) || (c<32))
  766                     special++;
  767             }
  768             if (special) 
  769             {
  770                 sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)",
  771                                    nick, user->username, user->host);
  772                 ircstp->is_ref++;
  773                 ircsprintf(tmpstr2, "Invalid username [%s]", user->username);
  774                 return exit_client(cptr, sptr, &me, tmpstr2);
  775             }
  776             /* Ok, now check the username they provided, if different */
  777             lower = upper = special = cc = 0;
  778                           
  779             if (strcmp(user->username, username)) 
  780             {
  781                                   
  782 #ifdef IGNORE_FIRST_CHAR
  783                 tmpstr = (username[0] == '~' ? &username[2] : &username[1]);
  784                 /*
  785                  * Ok, we don't want to TOTALLY ignore the first character.
  786                  * We should at least check it for control charcters, etc
  787                  * -ThemBones
  788                  */
  789                 cc = (username[0] == '~' ? username[1] : username[0]);
  790                                   
  791                 if ((!IsAlnum(cc) && !strchr(" -_.", cc)) || (cc > 127))
  792                     special++;
  793 #else
  794                 tmpstr = (username[0] == '~' ? &username[1] : username);
  795 #endif /* IGNORE_FIRST_CHAR */
  796                 while (*tmpstr) 
  797                 {
  798                     c = *(tmpstr++);
  799                     if (IsLower(c)) 
  800                     {
  801                         lower++;
  802                         continue;
  803                     }
  804                     if (IsUpper(c)) 
  805                     {
  806                         upper++;
  807                         continue;
  808                     }
  809                     if ((!IsAlnum(c) && !strchr(" -_.", c)) || (c > 127))
  810                         special++;
  811                 }
  812 #ifdef NO_MIXED_CASE
  813                 if (lower && upper) 
  814                 {
  815                     sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)",
  816                                        nick, username, user->host);
  817                     ircstp->is_ref++;
  818                     ircsprintf(tmpstr2, "Invalid username [%s]", username);
  819                     return exit_client(cptr, sptr, &me, tmpstr2);
  820                 }
  821 #endif /* NO_MIXED_CASE */
  822                 if (special) 
  823                 {
  824                     sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)",
  825                                        nick, username, user->host);
  826                     ircstp->is_ref++;
  827                     ircsprintf(tmpstr2, "Invalid username [%s]", username);
  828                     return exit_client(cptr, sptr, &me, tmpstr2);
  829                 }
  830             }                   /* usernames different  */
  831         }
  832 
  833         /*
  834          * reject single character usernames which aren't alphabetic i.e.
  835          * reject jokers who have '?@somehost' or '.@somehost'
  836          * 
  837          * -Dianora
  838          */
  839                 
  840         if ((user->username[1] == '\0') && !IsAlpha(user->username[0])) 
  841         {
  842             sendto_realops_lev(REJ_LEV, "Invalid username: %s (%s@%s)",
  843                                nick, user->username, user->host);
  844             ircstp->is_ref++;
  845             ircsprintf(tmpstr2, "Invalid username [%s]", user->username);
  846             return exit_client(cptr, sptr, &me, tmpstr2);
  847         }
  848 
  849         if (!(user->allow->flags & CONF_FLAGS_SKIPCLONES) &&
  850             (i = clones_check(cptr)))
  851         {
  852             ircstp->is_ref++;
  853             return exit_client(cptr, sptr, &me, i == 1
  854                                ? "Too many connections from your host"
  855                                : "Too many connections from your site");
  856         }
  857 
  858         if(!(ban = check_userbanned(sptr, UBAN_IP|UBAN_CIDR4, UBAN_WILDUSER)))
  859             ban = check_userbanned(sptr, UBAN_HOST, 0);
  860 
  861         if(ban)
  862         {
  863             int loc = (ban->flags & UBAN_LOCAL) ? 1 : 0;
  864             
  865             ircstp->is_ref++;
  866             ircstp->is_ref_2++;
  867             return exit_banned_client(cptr, loc, loc?'K':'A', ban->reason, 0);
  868         }
  869 
  870         if(call_hooks(CHOOK_POSTACCESS, sptr) == FLUSH_BUFFER)
  871             return FLUSH_BUFFER;
  872 
  873         Count.unknown--;
  874 
  875         if ((++Count.local) > Count.max_loc) 
  876         {
  877             Count.max_loc = Count.local;
  878             if (!(Count.max_loc % 10))
  879                 sendto_ops("New Max Local Clients: %d", Count.max_loc);
  880         }
  881         if ((NOW - Count.day) > 86400) 
  882         {
  883             Count.today = 0;
  884             Count.day = NOW;
  885         }
  886         if ((NOW - Count.week) > 604800) 
  887         {
  888             Count.weekly = 0;
  889             Count.week = NOW;
  890         }
  891         if ((NOW - Count.month) > 2592000) 
  892         {
  893             Count.monthly = 0;
  894             Count.month = NOW;
  895         }
  896         if ((NOW - Count.year) > 31536000) 
  897         {
  898             Count.yearly = 0;
  899             Count.year = NOW;
  900         }
  901         Count.today++;
  902         Count.weekly++;
  903         Count.monthly++;
  904         Count.yearly++;
  905         if(sptr->flags & FLAGS_BAD_DNS) 
  906             sendto_realops_lev(SPY_LEV, "DNS lookup: %s (%s@%s) is a possible "
  907                                "cache polluter", sptr->name, 
  908                                sptr->user->username, sptr->user->host); 
  909     }
  910     else
  911         strncpyzt(user->username, username, USERLEN + 1);
  912 
  913     SetClient(sptr);
  914     /* Increment our total user count here */
  915     if (++Count.total > Count.max_tot)
  916         Count.max_tot = Count.total;
  917 
  918     if(IsInvisible(sptr)) Count.invisi++;
  919         
  920     if (MyConnect(sptr))
  921     {
  922         set_effective_class(sptr);
  923 #ifdef MAXBUFFERS
  924         /* Let's try changing the socket options for the client here... */
  925         reset_sock_opts(sptr->fd, 0);
  926         /* End sock_opt hack */
  927 #endif
  928         sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, Network_Name,
  929                    nick, sptr->user->username, sptr->user->host);
  930         /*
  931          * This is a duplicate of the NOTICE but see below...
  932          * um, why were we hiding it? they did make it on to the
  933          * server and all.. -wd
  934          */
  935         sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick, me.name,
  936                    version);
  937 #ifdef  IRCII_KLUDGE
  938         /* Don't mess with this one - IRCII needs it! -Avalon */
  939         sendto_one(sptr, "NOTICE %s :*** Your host is %s, running version %s",
  940                    nick, me.name, version);
  941 #endif
  942         sendto_one(sptr, rpl_str(RPL_CREATED), me.name, nick, creation);
  943         sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0],
  944                    me.name, version);
  945 
  946         send_rplisupport(sptr);
  947 
  948 #ifdef FORCE_EVERYONE_HIDDEN
  949         sptr->umode |= UMODE_I;
  950 #endif
  951 
  952 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
  953         if(!BadPtr(sptr->passwd) && (pwaconf->flags & CONF_FLAGS_I_OPERPORT))
  954             do 
  955             {
  956                 char *onptr = sptr->passwd;
  957                 char *opptr;
  958                 char *onick;
  959                 char *tmpptr;
  960                 char tmppwd[PASSWDLEN + 1];
  961                 
  962                 if(!(opptr = strchr(onptr, ':')))
  963                     break;
  964                 
  965                 *opptr++ = '\0';
  966                 if((tmpptr = strchr(opptr, ':')))
  967                     *tmpptr++ = '\0';
  968                 if(check_oper_can_mask(sptr, onptr, opptr, &onick) != 0)
  969                 {
  970                     sendto_one(sptr, ":%s NOTICE %s :*** Your hostname has "
  971                                "been masked.",
  972                                me.name, sptr->name);
  973 
  974 #ifdef DEFAULT_MASKED_HIDDEN
  975                     sptr->umode |= UMODE_I;
  976 #endif
  977 
  978                     throttle_remove(sptr->hostip);
  979                     sptr->user->real_oper_host = 
  980                         MyMalloc(strlen(sptr->user->host) + 1);
  981                     sptr->user->real_oper_username = 
  982                         MyMalloc(strlen(sptr->user->username) + 1);
  983                     sptr->user->real_oper_ip = 
  984                         MyMalloc(strlen(sptr->hostip) + 1);
  985                     strcpy(sptr->user->real_oper_host, sptr->user->host);
  986                     strcpy(sptr->user->real_oper_username, sptr->user->username);
  987                     strcpy(sptr->user->real_oper_ip, sptr->hostip);
  988                     strncpyzt(sptr->user->host, Staff_Address, HOSTLEN + 1);
  989                     strncpyzt(sptr->user->username, onick, USERLEN + 1);
  990                     strncpyzt(sptr->username, onick, USERLEN + 1);
  991                     sptr->flags |= FLAGS_GOTID; /* fake ident */
  992             sptr->ip_family = AF_INET;
  993                     memset(&sptr->ip, 0, sizeof(sptr->ip));
  994                     strcpy(sptr->hostip, "0.0.0.0");
  995                     strncpy(sptr->sockhost, Staff_Address, HOSTLEN + 1);
  996 #ifdef USER_HOSTMASKING
  997                     strncpyzt(sptr->user->mhost, mask_host(Staff_Address,0), HOSTLEN + 1);
  998                     if(uhm_type > 0) sptr->umode &= ~UMODE_H; /* It's already masked anyway */
  999 #endif
 1000                 }
 1001 
 1002                 if(tmpptr)
 1003                 {
 1004                     strcpy(tmppwd, tmpptr);
 1005                     strcpy(sptr->passwd, tmppwd);
 1006                 }
 1007                 else
 1008                     sptr->passwd[0] = '\0';
 1009             } while(0);
 1010 #endif
 1011 
 1012         sendto_realops_lev(CCONN_LEV, "Client connecting: %s (%s@%s) [%s] {%s}%s",
 1013                            nick, user->username, user->host, sptr->hostip,
 1014                            sptr->class->name, IsSSL(sptr) ? " SSL" : "");
 1015 
 1016         send_lusers(sptr, sptr, 1, parv);
 1017         
 1018         if(motd != NULL)
 1019         {
 1020             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- motd was last"
 1021                        " changed at %s", me.name, nick, motd_last_changed_date);
 1022         }
 1023         
 1024         if(confopts & FLAGS_SMOTD)
 1025         {
 1026             if(motd != NULL)
 1027             {
 1028                 sendto_one(sptr, ":%s NOTICE %s :*** Notice -- Please read the"
 1029                                  " motd if you haven't read it", me.name, nick);
 1030             }
 1031             
 1032             sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name);
 1033             if((smotd = shortmotd) == NULL)
 1034                 sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0],
 1035                                     "*** This is the short motd ***");
 1036             else 
 1037                 while (smotd) 
 1038                 {
 1039                     sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], 
 1040                                 smotd->line);
 1041                     smotd = smotd->next;
 1042                 }
 1043         
 1044             sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, parv[0]);
 1045         }
 1046         else
 1047             send_motd(sptr, sptr, 1, parv);
 1048 
 1049         if((confopts & FLAGS_WGMON) == FLAGS_WGMON)
 1050         {
 1051             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- This server runs an "
 1052                     "open proxy monitor to prevent abuse.", me.name, nick);
 1053             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- If you see"
 1054                     " connections on various ports from %s", me.name, 
 1055                     nick, ProxyMonHost);
 1056             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- please disregard"
 1057                     " them, as they are the monitor in action.", me.name, 
 1058                     nick);
 1059             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- For more information"
 1060                     " please visit %s", me.name, nick, ProxyMonURL);
 1061         }
 1062 
 1063         /* do this late because of oper masking */
 1064     clones_add(sptr);
 1065     }
 1066     else if (IsServer(cptr)) 
 1067     {
 1068         aClient    *acptr;
 1069 
 1070         /* do this early because exit_client() calls clones_remove() */
 1071     clones_add(sptr);
 1072         
 1073         if ((acptr = find_server(user->server, NULL)) &&
 1074             acptr->from != sptr->from)
 1075         {
 1076             sendto_realops_lev(DEBUG_LEV,
 1077                                "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
 1078                                cptr->name, nick, user->username,
 1079                                user->host, user->server,
 1080                                acptr->name, acptr->from->name);
 1081             sendto_one(cptr, ":%s KILL %s :%s (%s != %s USER from wrong "
 1082                        "direction)", me.name, sptr->name, me.name,
 1083                        user->server, acptr->from->name);
 1084             sptr->flags |= FLAGS_KILLED;
 1085             return exit_client(sptr, sptr, &me, "USER server wrong direction");
 1086                         
 1087         }
 1088         /*
 1089          * Super GhostDetect: If we can't find the server the user is
 1090          * supposed to be on, then simply blow the user away.     -Taner
 1091          */
 1092         if (!acptr)
 1093         {
 1094             sendto_one(cptr,
 1095                        ":%s KILL %s :%s GHOST (no server %s on the net)",
 1096                        me.name, sptr->name, me.name, user->server);
 1097             sendto_realops("No server %s for user %s[%s@%s] from %s",
 1098                            user->server, sptr->name, user->username,
 1099                            user->host, sptr->from->name);
 1100             sptr->flags |= FLAGS_KILLED;
 1101             return exit_client(sptr, sptr, &me, "Ghosted Client");
 1102         }
 1103 
 1104         /* scan for aliases too */
 1105         if(IsULine(sptr))
 1106         {
 1107             AliasInfo *ai;
 1108 
 1109             for (ai = aliastab; ai->nick; ai++)
 1110             {
 1111                 if (!mycmp(ai->server, user->server)
 1112                     && !mycmp(ai->nick, sptr->name))
 1113                 {
 1114                     user->alias = ai;
 1115                     ai->client = sptr;
 1116                     break;
 1117                 }
 1118             }
 1119         }
 1120     }
 1121     send_umode(NULL, sptr, 0, SEND_UMODES, ubuf, sizeof(ubuf));
 1122     if (!*ubuf)
 1123     {
 1124         ubuf[0] = '+';
 1125         ubuf[1] = '\0';
 1126     }
 1127     hash_check_watch(sptr, RPL_LOGON);
 1128 
 1129     sendto_serv_butone_nickipstr(cptr, 1, "NICK %s %d %ld %s %s %s %s %lu %s :%s",
 1130                  nick, sptr->hopcount + 1, sptr->tsinfo, ubuf,
 1131                  user->username, user->host, user->server,
 1132                  sptr->user->servicestamp,
 1133                  cipntoa(sptr), sptr->info);
 1134     sendto_serv_butone_nickipstr(cptr, 0, "NICK %s %d %ld %s %s %s %s %lu %u :%s",
 1135                  nick, sptr->hopcount + 1, sptr->tsinfo, ubuf,
 1136                  user->username, user->host, user->server,
 1137                  sptr->user->servicestamp,
 1138                  (sptr->ip_family == AF_INET) ?
 1139                  htonl(sptr->ip.ip4.s_addr) : 1, sptr->info);
 1140 
 1141     if(MyClient(sptr))
 1142     {
 1143         /* if the I:line doesn't have a password and the user does
 1144          * send it over to NickServ
 1145          */
 1146         if (sptr->passwd[0] && aliastab[AII_NS].client && !svspanic)
 1147             sendto_alias(&aliastab[AII_NS], sptr, "SIDENTIFY %s",sptr->passwd);
 1148 
 1149         memset(sptr->passwd, '\0', PASSWDLEN);
 1150         
 1151         if (ubuf[1]) send_umode(cptr, sptr, 0, ALL_UMODES, ubuf, sizeof(ubuf));
 1152 
 1153         if(call_hooks(CHOOK_POSTMOTD, sptr) == FLUSH_BUFFER)
 1154             return FLUSH_BUFFER;
 1155     }
 1156 
 1157 #ifdef RWHO_PROBABILITY
 1158     probability_add(sptr);
 1159 #endif
 1160 
 1161     return 0;
 1162 }
 1163 
 1164 char *exploits_2char[] =
 1165 {
 1166     "js",
 1167     "pl",
 1168     NULL
 1169 };
 1170 char *exploits_3char[] = 
 1171 {
 1172     "exe",
 1173     "com",
 1174     "bat",
 1175     "dll",
 1176     "ini",
 1177     "vbs",
 1178     "pif",
 1179     "mrc",
 1180     "scr",
 1181     "doc",
 1182     "xls",
 1183     "lnk",
 1184     "shs",
 1185     "htm",
 1186     "zip",
 1187     "rar",
 1188     NULL
 1189 };
 1190 
 1191 char *exploits_4char[] =
 1192 {
 1193     "html",
 1194     NULL
 1195 };
 1196 
 1197 static int
 1198 allow_dcc(aClient *to, aClient *from)
 1199 {
 1200     Link *lp;
 1201 
 1202     for(lp = to->user->dccallow; lp; lp = lp->next)
 1203     {
 1204         if(lp->flags == DCC_LINK_ME && lp->value.cptr == from)
 1205             return 1;
 1206     }
 1207     return 0;
 1208 }
 1209 
 1210 static int 
 1211 check_dccsend(aClient *from, aClient *to, char *msg)
 1212 {
 1213     /*
 1214      * we already know that msg will consist of "DCC SEND" so we can skip
 1215      * to the end
 1216      */
 1217     char *filename = msg + 8;
 1218     char *ext;
 1219     char **farray = NULL;
 1220     int arraysz;
 1221     int len = 0, extlen = 0, i;
 1222 
 1223     /* people can send themselves stuff all the like..
 1224      * opers need to be able to send cleaner files 
 1225      * sanity checks..
 1226      */
 1227 
 1228     if(from == to || !IsPerson(from) || IsAnOper(from) || !MyClient(to)) 
 1229         return 0;
 1230 
 1231     while(*filename == ' ')
 1232         filename++;
 1233 
 1234     if(!(*filename)) return 0;
 1235 
 1236     if(*filename == '"')
 1237     {
 1238         filename++;
 1239 
 1240         if(!(*filename)) return 0;
 1241 
 1242         while(*(filename + len) != '"')
 1243         {
 1244             if(!(*(filename + len))) break;
 1245             len++;
 1246         }
 1247     }
 1248     else
 1249     {
 1250         while(*(filename + len) != ' ')
 1251         {
 1252             if(!(*(filename + len))) break;
 1253             len++;
 1254         }
 1255     }
 1256     
 1257     for(ext = filename + len;; ext--)
 1258     {
 1259         if(ext == filename)
 1260             return 0;
 1261 
 1262         if(*ext == '.') 
 1263         {
 1264             ext++;
 1265             extlen--;
 1266             break;
 1267         }
 1268         extlen++;
 1269     }
 1270 
 1271     switch(extlen)
 1272     {
 1273         case 0:
 1274             arraysz = 0;
 1275             break;
 1276 
 1277         case 2:
 1278             farray = exploits_2char;
 1279             arraysz = 2;
 1280             break;
 1281 
 1282         case 3:
 1283             farray = exploits_3char;
 1284             arraysz = 3;
 1285             break;
 1286 
 1287         case 4:
 1288             farray = exploits_4char;
 1289             arraysz = 4;
 1290             break;
 1291 
 1292         /* no executable file here.. */
 1293         default:
 1294             return 0;
 1295     }
 1296 
 1297     if (arraysz != 0)
 1298     {
 1299         for(i = 0; farray[i]; i++)
 1300         {
 1301             if(myncmp(farray[i], ext, arraysz) == 0)
 1302             break;
 1303         }
 1304 
 1305         if(farray[i] == NULL)
 1306             return 0;
 1307     }
 1308 
 1309     if(!allow_dcc(to, from))
 1310     {
 1311         char tmpext[8];
 1312         char tmpfn[128];
 1313         Link *tlp, *flp;
 1314         aChannel *chptr = NULL;
 1315 
 1316         strncpy(tmpext, ext, extlen);
 1317         tmpext[extlen] = '\0';
 1318 
 1319         if(len > 127) 
 1320             len = 127;
 1321         strncpy(tmpfn, filename, len);
 1322         tmpfn[len] = '\0';
 1323 
 1324         /* use notices! 
 1325          *   server notices are hard to script around.
 1326          *   server notices are not ignored by clients.
 1327          */ 
 1328 
 1329         sendto_one(from, ":%s NOTICE %s :The user %s is not accepting DCC "
 1330                    "sends of filetype *.%s from you.  Your file %s was not "
 1331                    "sent.", me.name, from->name, to->name, tmpext, tmpfn);
 1332 
 1333         sendto_one(to, ":%s NOTICE %s :%s (%s@%s) has attempted to send you a "
 1334                    "file named %s, which was blocked.", me.name, to->name,
 1335                    from->name, from->user->username,
 1336 #ifdef USER_HOSTMASKING
 1337                    IsUmodeH(from)?from->user->mhost:
 1338 #endif
 1339                                                     from->user->host,
 1340                    tmpfn);
 1341 
 1342         if(!SeenDCCNotice(to))
 1343         {
 1344             SetDCCNotice(to);
 1345  
 1346             sendto_one(to, ":%s NOTICE %s :The majority of files sent of this "
 1347                        "type are malicious viruses and trojan horses."
 1348                        " In order to prevent the spread of this problem, we "
 1349                        "are blocking DCC sends of these types of"
 1350                        " files by default.", me.name, to->name);
 1351             sendto_one(to, ":%s NOTICE %s :If you trust %s, and want him/her "
 1352                        "to send you this file, you may obtain"
 1353                        " more information on using the dccallow system by "
 1354                        "typing /dccallow help",
 1355                        me.name, to->name, from->name);
 1356         }
 1357         
 1358         for(tlp = to->user->channel; tlp && !chptr; tlp = tlp->next)
 1359         {
 1360             for(flp = from->user->channel; flp && !chptr; flp = flp->next)
 1361             {
 1362                 if(tlp->value.chptr == flp->value.chptr)
 1363                     chptr = tlp->value.chptr;
 1364             }
 1365         }
 1366         
 1367         if(chptr)
 1368             sendto_realops_lev(DCCSEND_LEV, "%s (%s@%s) sending forbidden "
 1369                                "filetyped file %s to %s (channel %s)",
 1370                                from->name, from->user->username,
 1371                                from->user->host, tmpfn, to->name,
 1372                                chptr->chname); 
 1373         else
 1374             sendto_realops_lev(DCCSEND_LEV, "%s (%s@%s) sending forbidden "
 1375                                "filetyped file %s to %s", from->name, 
 1376                                from->user->username, from->user->host, tmpfn,
 1377                                to->name); 
 1378 
 1379         return 1;
 1380     }
 1381     return 0;
 1382 }
 1383 
 1384 /*
 1385  * check target limit: message target rate limiting
 1386  * anti spam control!
 1387  * should only be called for local PERSONS!
 1388  * sptr: client sending message
 1389  * acptr: client receiving message
 1390  *
 1391  * return value:
 1392  * 1: block
 1393  * 0: do nothing
 1394  */
 1395 
 1396 #ifdef MSG_TARGET_LIMIT
 1397 int check_target_limit(aClient *sptr, aClient *acptr)
 1398 {
 1399     int ti;
 1400     int max_targets;
 1401     time_t tmin = MSG_TARGET_TIME;  /* minimum time to wait before
 1402                                     * another message can be sent */
 1403 
 1404     /* don't limit opers, people talking to themselves,
 1405      * or people talking to services */
 1406     if(IsOper(sptr) || sptr == acptr || IsULine(acptr) || NoMsgThrottle(sptr))
 1407         return 0;
 1408 
 1409     max_targets = ((NOW - sptr->firsttime) > MSG_TARGET_MINTOMAXTIME) 
 1410                  ? MSG_TARGET_MAX : MSG_TARGET_MIN;
 1411 
 1412     for(ti = 0; ti < max_targets; ti++)
 1413     {
 1414         if (sptr->targets[ti].cli == NULL || sptr->targets[ti].cli == acptr || 
 1415             sptr->targets[ti].sent < (NOW - MSG_TARGET_TIME))
 1416         {
 1417             sptr->targets[ti].cli = acptr;
 1418             sptr->targets[ti].sent = NOW;
 1419             break;
 1420         }
 1421         else if((NOW - sptr->targets[ti].sent) < tmin)
 1422             tmin = NOW - sptr->targets[ti].sent;
 1423     }
 1424 
 1425     if(ti == max_targets)
 1426     {
 1427         sendto_one(sptr, err_str(ERR_TARGETTOFAST), me.name, sptr->name,
 1428                    acptr->name, MSG_TARGET_TIME - tmin);
 1429         if(call_hooks(CHOOK_SPAMWARN, sptr, 1, max_targets, NULL) != FLUSH_BUFFER)
 1430         {
 1431             sptr->since += 2; /* penalize them 2 seconds for this! */
 1432             sptr->num_target_errors++;
 1433 
 1434             if(sptr->last_target_complain + 60 <= NOW)
 1435             {
 1436                 sendto_realops_lev(SPAM_LEV, "Target limited: %s (%s@%s)"
 1437                                    " [%d failed targets]", sptr->name,
 1438                                     sptr->user->username, sptr->user->host, 
 1439                                     sptr->num_target_errors);
 1440                 sptr->num_target_errors = 0;
 1441                 sptr->last_target_complain = NOW;
 1442             }
 1443         }
 1444         return 1;
 1445     }
 1446 
 1447     return 0;
 1448 }
 1449 #endif
 1450 
 1451 
 1452 /*
 1453  * This function checks to see if a CTCP message (other than ACTION) is
 1454  * contained in the passed string.  This might seem easier than I am
 1455  * doing it, but a CTCP message can be changed together, even after a
 1456  * normal message.
 1457  *
 1458  * If the message is found, and it's a DCC message, pass it back in
 1459  * *dccptr.
 1460  *
 1461  * Unfortunately, this makes for a bit of extra processing in the
 1462  * server.
 1463  */
 1464 static int 
 1465 check_for_ctcp(char *str, char **dccptr)
 1466 {
 1467     char       *p = str;
 1468 
 1469     while ((p = strchr(p, 1)) != NULL)
 1470     {
 1471         if (myncmp(++p, "DCC", 3) == 0)
 1472         {
 1473             if(dccptr)
 1474                 *dccptr = p;
 1475             if(myncmp(p+3, " SEND", 5) == 0)
 1476                 return CTCP_DCCSEND;
 1477             else
 1478                 return CTCP_DCC;
 1479         }
 1480         /* p was increased twice. 'ACTION' could not be found. -- nicobn */
 1481         if (myncmp(p, "ACTION", 6) != 0)
 1482             return CTCP_YES;
 1483         if ((p = strchr(p, 1)) == NULL)
 1484             return CTCP_NONE;
 1485         if(!(*(++p)))
 1486             break;;
 1487     }
 1488     return CTCP_NONE;
 1489 }
 1490 
 1491 /* is_silenced - Returns 1 if a sptr is silenced by acptr */
 1492 int
 1493 is_silenced(aClient *sptr, aClient *acptr)
 1494 {
 1495     Link *lp;
 1496     anUser *user;
 1497     char sender[HOSTLEN+1+USERLEN+1+HOSTLEN+1];
 1498 
 1499     if (!(acptr->user)||!(lp=acptr->user->silence)||!(user=sptr->user))
 1500         return 0;
 1501     ircsprintf(sender,"%s!%s@%s",sptr->name,user->username,user->host);
 1502     while(lp)
 1503     {
 1504         if (!match(lp->value.cp, sender))
 1505         {
 1506             if (!MyConnect(sptr))
 1507             {
 1508                 sendto_one(sptr->from, ":%s SILENCE %s :%s",acptr->name,
 1509                            sptr->name, lp->value.cp);
 1510                 lp->flags = 1;
 1511             }
 1512             return 1;
 1513         }
 1514         lp = lp->next;
 1515     }
 1516     return 0;
 1517 }
 1518 
 1519 static inline time_t get_highest(time_t val1, time_t val2)
 1520 {
 1521     if(val1 > val2) return val1;
 1522     else return val2;
 1523 }
 1524 
 1525 static inline void 
 1526 send_msg_error(aClient *sptr, char *parv[], char *nick, int ret, aChannel *chptr) 
 1527 {
 1528     if(ret == ERR_NOCTRLSONCHAN)
 1529         sendto_one(sptr, err_str(ERR_NOCTRLSONCHAN), me.name,
 1530                    parv[0], nick, parv[2]);
 1531     else if(ret == ERR_NEEDTOWAIT)
 1532     {
 1533         sendto_one(sptr, err_str(ERR_NEEDTOWAIT), me.name,
 1534                    parv[0], get_highest((sptr->firsttime + chptr->talk_connect_time - NOW), get_user_jointime(sptr, chptr) + chptr->talk_join_time - NOW), chptr->chname);
 1535     }
 1536     else if(ret == ERR_NEEDREGGEDNICK)
 1537         sendto_one(sptr, err_str(ERR_NEEDREGGEDNICK), me.name,
 1538                    parv[0], nick, "speak in", chptr->chname, aliastab[AII_NS].nick,
 1539                    aliastab[AII_NS].server, NS_Register_URL);
 1540     else if(ret == ERR_MAXMSGSENT)
 1541         sendto_one(sptr, err_str(ERR_MAXMSGSENT), me.name,
 1542                    parv[0], (chptr->max_messages_time + get_user_lastmsgtime(sptr, chptr) - NOW + 1), chptr->chname);
 1543     else
 1544         sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name,
 1545                    parv[0], nick);
 1546 }
 1547 
 1548 /*
 1549  * Check if the recipient we are sending to is one of the services or stats addresses.
 1550  */
 1551 static int is_aliastab_recipient(char *recipient)
 1552 {
 1553     AliasInfo *ai;
 1554     char full_target[NICKLEN + HOSTLEN + 2];
 1555 
 1556     for(ai = aliastab; ai->nick; ai++)
 1557     {
 1558         ircsprintf(full_target, "%s@%s", ai->nick, ai->server);
 1559         if(!mycmp(recipient, full_target))
 1560             return 1;
 1561     }
 1562 
 1563     return 0;
 1564 }
 1565 
 1566 /*
 1567  * m_message (used in m_private() and m_notice()) the general
 1568  * function to deliver MSG's between users/channels
 1569  * 
 1570  * parv[0] = sender prefix
 1571  * parv[1] = receiver list
 1572  * parv[2] = message text
 1573  * 
 1574  * massive cleanup * rev argv 6/91
 1575  * again -Quension [Jul 2004]
 1576  * 
 1577  */
 1578 static int
 1579 m_message(aClient *cptr, aClient *sptr, int parc, char *parv[], int notice)
 1580 {
 1581     aClient *acptr;
 1582     aChannel *chptr;
 1583     char *cmd;
 1584     int ismine;
 1585     int ret;
 1586     char *s;
 1587     char *p = NULL;
 1588     char *target;
 1589     char *dccmsg;
 1590     int tleft = MAXRECIPIENTS;  /* targets left */
 1591     char channel[CHANNELLEN + 1]; /* for the auditorium mode -Kobi. */
 1592 
 1593     cmd = notice ? MSG_NOTICE : MSG_PRIVATE;
 1594     ismine = MyClient(sptr);
 1595 
 1596     if (parc < 2 || *parv[1] == 0)
 1597     {
 1598         sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], cmd);
 1599         return -1;
 1600     }
 1601 
 1602     if (parc < 3 || *parv[2] == 0)
 1603     {
 1604         sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
 1605         return -1;
 1606     }
 1607 
 1608     if (ismine)
 1609     {
 1610         /* if squelched or spamming, allow only messages to self or to the services and stats addresses */
 1611         if ((IsSquelch(sptr)
 1612 #if defined(ANTI_SPAMBOT) && !defined(ANTI_SPAMBOT_WARN_ONLY)
 1613             || (sptr->join_leave_count >= MAX_JOIN_LEAVE_COUNT)
 1614 #endif
 1615             ) && mycmp(parv[0], parv[1]) && !is_aliastab_recipient(parv[1]))
 1616         {
 1617             if (IsWSquelch(sptr) && !notice)
 1618                 sendto_one(sptr, ":%s NOTICE %s :You are currently squelched."
 1619                             "  Message not sent.", me.name, parv[0]);
 1620             return 0;
 1621         }
 1622 
 1623         if (call_hooks(CHOOK_MSG, sptr, notice, parv[2]) == FLUSH_BUFFER)
 1624             return FLUSH_BUFFER;
 1625 
 1626         parv[1] = canonize(parv[1]);
 1627     }
 1628 
 1629     /* loop on comma-separated targets, until tleft is gone */
 1630     for (target = strtoken(&p, parv[1], ",");
 1631          target && tleft--;
 1632          target = strtoken(&p, NULL, ","))
 1633     {
 1634         int chflags = 0;    /* channel op/voice prefixes */
 1635 
 1636         /* additional penalty for lots of targets */
 1637         if (ismine && tleft < (MAXRECIPIENTS/2) && !NoMsgThrottle(sptr))
 1638 #ifdef NO_OPER_FLOOD
 1639             if (!IsAnOper(sptr))
 1640 #endif
 1641                 sptr->since += 4;
 1642 
 1643         /* [@][+]#channel preprocessing */
 1644         s = target;
 1645         while (1)
 1646         {
 1647             if (*s == '@')
 1648                 chflags |= CHFL_CHANOP;
 1649 #ifdef USE_HALFOPS
 1650             else if (*s == '%')
 1651                 chflags |= CHFL_HALFOP;
 1652 #endif
 1653             else if (*s == '+')
 1654                 chflags |= CHFL_VOICE;
 1655             else
 1656                 break;
 1657             s++;
 1658         }
 1659 
 1660         /* target is a channel */
 1661         if (IsChannelName(s))
 1662         {
 1663             if (!(chptr = find_channel(s, NULL)))
 1664             {
 1665                 if (ismine && !notice)
 1666                     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0],
 1667                                target);
 1668                 continue;
 1669             }
 1670 
 1671             if (ismine && call_hooks(CHOOK_CHANMSG, sptr, chptr, notice,
 1672                                      parv[2]) == FLUSH_BUFFER)
 1673                     return FLUSH_BUFFER;
 1674 
 1675 #ifdef SPAMFILTER
 1676             if(!(chptr->mode.mode & MODE_PRIVACY))
 1677             {
 1678                 if(ismine && check_sf(sptr, parv[2], notice?"notice":"msg", SF_CMD_CHANNEL, chptr->chname))
 1679                     return FLUSH_BUFFER;
 1680             }
 1681 #endif
 1682 
 1683             /* servers and super sources get free sends */
 1684             if (IsClient(sptr) && !IsULine(sptr))
 1685             {
 1686                 if ((ret = can_send(sptr, chptr, parv[2])))
 1687                 {
 1688                     if (ismine && !notice)
 1689                         send_msg_error(sptr, parv, target, ret, chptr);
 1690                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 1691                         verbose_to_relaychan(sptr, chptr, notice?"notice":"message", parv[2]);
 1692                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 1693                         verbose_to_opers(sptr, chptr, notice?"notice":"message", parv[2]);
 1694                     continue;
 1695                 }
 1696 
 1697                 if (notice && (chptr->xflags & XFLAG_NO_NOTICE) && !is_xflags_exempted(sptr,chptr))
 1698                 {
 1699                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 1700                         verbose_to_relaychan(sptr, chptr, "notice", parv[2]);
 1701                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 1702                         verbose_to_opers(sptr, chptr, "notice", parv[2]);
 1703                     continue;
 1704                 }
 1705 
 1706                 if ((chptr->xflags & XFLAG_NO_UTF8) && msg_has_utf8(parv[2]) && !is_xflags_exempted(sptr,chptr))
 1707                 {
 1708                     if (ismine && !notice)
 1709                         sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0], target);
 1710                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 1711                         verbose_to_relaychan(sptr, chptr, notice?"utf8-notice":"utf8-message", parv[2]);
 1712                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 1713                         verbose_to_opers(sptr, chptr, notice?"utf8-notice":"utf8-message", parv[2]);
 1714                     continue;
 1715                 }
 1716 
 1717                 if((chptr->mode.mode & MODE_AUDITORIUM) && !is_chan_opvoice(sptr, chptr))
 1718                 {
 1719                     /* Channel is in auditorium mode! */
 1720                     if(strlen(chptr->chname)+6 > CHANNELLEN) continue; /* Channel is too long.. we must be able to add
 1721                                                                            -relay to it... */
 1722                     strcpy(channel, chptr->chname);
 1723                     strcat(channel, "-relay");
 1724                     if(!(chptr = find_channel(channel, NULL))) continue; /* Can't find the relay channel... */
 1725                     /* I originally thought it's a good idea to enforce #chan-relay modes but then I figured out we
 1726                        would most likely want to have it +snt and only accept messages from #chan members... -Kobi.
 1727                     if ((ret = can_send(sptr, chptr, parv[2])))
 1728                     {
 1729                         if (ismine && !notice)
 1730                             send_msg_error(sptr, parv, target, ret, chptr);
 1731                         continue;
 1732                     }
 1733                     */
 1734                     s = target = chptr->chname; /* We want ops to see the message coming to #chan-relay and not to #chan */
 1735                 }
 1736 
 1737                 if (!notice)
 1738                 {
 1739                     switch (check_for_ctcp(parv[2], NULL))
 1740                     {
 1741                         case CTCP_NONE:
 1742                             break;
 1743 
 1744                         case CTCP_DCCSEND:
 1745                         case CTCP_DCC:
 1746                             if (ismine)
 1747                                 sendto_one(sptr, ":%s NOTICE %s :You may not"
 1748                                            " send a DCC command to a channel"
 1749                                            " (%s)", me.name, parv[0], target);
 1750                             continue;
 1751 #ifdef FLUD
 1752                         default:
 1753                             if (check_for_flud(sptr, NULL, chptr, 1))
 1754                                 return 0;
 1755 #endif
 1756                             if ((chptr->xflags & XFLAG_NO_CTCP) && !is_xflags_exempted(sptr,chptr))
 1757                             {
 1758                                 if(chptr->xflags & XFLAG_USER_VERBOSE)
 1759                                     verbose_to_relaychan(cptr, chptr, "ctcp", "xflag_no_ctcp");
 1760                                 if(chptr->xflags & XFLAG_OPER_VERBOSE)
 1761                                     verbose_to_opers(cptr, chptr, "ctcp", "xflag_no_ctcp");
 1762                                 continue;
 1763                             }
 1764                     }
 1765                 }
 1766             }
 1767 
 1768             if (chflags)
 1769             {
 1770                 /* don't let clients do stuff like @+@@+++@+@@@#channel */
 1771                 if (chflags & CHFL_VOICE)
 1772                     *--s = '+';
 1773 #ifdef USE_HALFOPS
 1774                 if (chflags & CHFL_HALFOP)
 1775                     *--s = '%';
 1776 #endif
 1777                 if (chflags & CHFL_CHANOP)
 1778                     *--s = '@';
 1779 
 1780                 sendto_channelflags_butone(cptr, sptr, chptr, chflags,
 1781                                            ":%s %s %s :%s", parv[0], cmd, s,
 1782                                            parv[2]);
 1783             }
 1784             else
 1785                 sendto_channel_butone(cptr, sptr, chptr, ":%s %s %s :%s",
 1786                                       parv[0], cmd, target, parv[2]);
 1787 
 1788             /* next target */
 1789             continue;
 1790         }
 1791 
 1792         /* prefixes are only valid for channel targets */
 1793         if (s != target)
 1794         {
 1795             if (!notice)
 1796                 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0],
 1797                        target);
 1798             continue;
 1799         }
 1800 
 1801         /* target is a $servermask */
 1802         if (*target == '$')
 1803         {
 1804             s++;
 1805 
 1806             /* allow $$servermask */
 1807             if (*s == '$')
 1808                 s++;
 1809 
 1810             if (ismine)
 1811             {
 1812                 /* need appropriate privs */
 1813                 if (!OPCanLNotice(sptr) ||
 1814                     (mycmp(me.name, s) && !OPCanGNotice(sptr)))
 1815                 {
 1816                     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
 1817                                parv[0], target);
 1818                     continue;
 1819                 }
 1820             }
 1821 
 1822             sendto_all_servmask(sptr, s, ":%s %s %s :%s", parv[0], cmd,
 1823                                 target, parv[2]);
 1824 
 1825             /* next target */
 1826             continue;
 1827         }
 1828 
 1829         /* target is a nick@server */
 1830         if ((s = strchr(target, '@')))
 1831             *s = 0;
 1832 
 1833         /* target is a client */
 1834         if ((acptr = find_client(target, NULL)))
 1835         {
 1836             if (s)
 1837                 *s++ = '@';
 1838 
 1839             if (ismine && IsMe(acptr))
 1840             {
 1841                 if (call_hooks(CHOOK_MYMSG, sptr, notice, parv[2])
 1842                     == FLUSH_BUFFER)
 1843                     return FLUSH_BUFFER;
 1844 
 1845                 continue;
 1846             }
 1847 
 1848             if (!IsClient(acptr))
 1849                 acptr = NULL;
 1850         }
 1851 
 1852         /* nonexistent client or wrong @server */
 1853         if (!acptr || (s && mycmp(acptr->user->server, s)))
 1854         {
 1855             if (!notice)
 1856                 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0],
 1857                            target);
 1858             continue;
 1859         }
 1860 
 1861         /* super targets get special treatment */
 1862         if (IsULine(acptr))
 1863         {
 1864             AliasInfo *ai;
 1865 
 1866             if (notice && (confopts & FLAGS_SERVHUB) && (acptr->uplink->serv->uflags & ULF_NONOTICE))
 1867                 continue;
 1868 
 1869             if (ismine && !notice && (ai = acptr->user->alias))
 1870             {
 1871 #ifdef DENY_SERVICES_MSGS
 1872                 if (!s && !mycmp(ai->server, Services_Name))
 1873                 {
 1874                     sendto_one(sptr, err_str(ERR_MSGSERVICES), me.name,
 1875                                parv[0], ai->nick, ai->nick, ai->server,
 1876                                ai->nick);
 1877                     continue;
 1878                 }
 1879 #endif
 1880 #ifdef PASS_SERVICES_MSGS
 1881                 if (s)  /* if passing, skip this and use generic send below */
 1882 #endif
 1883                 {
 1884                     sendto_alias(ai, sptr, "%s", parv[2]);
 1885                     continue;
 1886                 }
 1887             }
 1888 
 1889             if((svspanic>1 || (svspanic>0 && !IsARegNick(sptr))) && !IsOper(sptr))
 1890             {
 1891                 if(MyClient(sptr))
 1892                     sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name, parv[0],
 1893                                acptr->name);
 1894                 continue;
 1895             }
 1896 
 1897             /* no flood/dcc/whatever checks, just send */
 1898             sendto_one(acptr, ":%s %s %s :%s", parv[0], cmd, target,
 1899                        parv[2]);
 1900             continue;
 1901         }
 1902 #ifdef SUPER_TARGETS_ONLY
 1903         else if (s && ismine)
 1904         {
 1905             if (!notice)
 1906                 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0],
 1907                        target);
 1908             continue;
 1909         }
 1910 #endif
 1911 
 1912         if (ismine)
 1913         {
 1914             if (call_hooks(CHOOK_USERMSG, sptr, acptr, notice, parv[2])
 1915                 == FLUSH_BUFFER)
 1916                 return FLUSH_BUFFER;
 1917 
 1918 #ifdef MSG_TARGET_LIMIT
 1919             if (check_target_limit(sptr, acptr))
 1920                 continue;
 1921 #endif
 1922 
 1923 #ifdef SPAMFILTER
 1924             if(!IsUmodeP(acptr) && sptr!=acptr && check_sf(sptr, parv[2], notice?"notice":"msg", notice?SF_CMD_NOTICE:SF_CMD_PRIVMSG, acptr->name))
 1925                 return FLUSH_BUFFER;
 1926 #endif
 1927         }
 1928 
 1929         /* servers and super sources skip flood/silence checks */
 1930         if (IsClient(sptr) && !IsULine(sptr))
 1931         {
 1932             if (IsNoNonReg(acptr) && !IsRegNick(sptr) && !IsOper(sptr))
 1933             {
 1934                 if (ismine && !notice)
 1935                     sendto_one(sptr, err_str(ERR_NONONREG), me.name, parv[0],
 1936                            target);
 1937                 continue;
 1938             }
 1939             if (IsUmodeC(acptr) && !IsOper(sptr) && (!IsNoNonReg(acptr) || IsRegNick(sptr)) && acptr->user->joined && !find_shared_chan(sptr, acptr))
 1940             {
 1941                 if (ismine && !notice)
 1942                     sendto_one(sptr, err_str(ERR_NOSHAREDCHAN), me.name, parv[0],
 1943                            target);
 1944                 continue;
 1945             }
 1946             if (ismine && IsNoNonReg(sptr) && !IsRegNick(acptr) && !IsOper(acptr))
 1947             {
 1948                 if (!notice)
 1949                     sendto_one(sptr, err_str(ERR_OWNMODE), me.name, parv[0],
 1950                            acptr->name, "+R");
 1951                 continue;
 1952             }
 1953             if (ismine && IsUmodeC(sptr) && !IsOper(sptr) && (!IsNoNonReg(sptr) || IsRegNick(acptr)) && sptr->user->joined && !find_shared_chan(sptr, acptr))
 1954             {
 1955                 if (!notice)
 1956                     sendto_one(sptr, err_str(ERR_OWNMODE), me.name, parv[0],
 1957                            acptr->name, "+C");
 1958                 continue;
 1959             }
 1960 
 1961 #ifdef FLUD
 1962             if (!notice && MyFludConnect(acptr))
 1963 #else
 1964             if (!notice && MyConnect(acptr))
 1965 #endif
 1966             {
 1967                 switch (check_for_ctcp(parv[2], &dccmsg))
 1968                 {
 1969                     case CTCP_NONE:
 1970                         break;
 1971 
 1972                     case CTCP_DCCSEND:
 1973 #ifdef FLUD
 1974                         if (check_for_flud(sptr, acptr, NULL, 1))
 1975                             return 0;
 1976 #endif
 1977                         if (check_dccsend(sptr, acptr, dccmsg))
 1978                             continue;
 1979                         break;
 1980 
 1981 #ifdef FLUD
 1982                     default:
 1983                         if (check_for_flud(sptr, acptr, NULL, 1))
 1984                             return 0;
 1985 #endif
 1986                 }
 1987             }
 1988 
 1989             if (is_silenced(sptr, acptr))
 1990                 continue;
 1991         }
 1992 
 1993         if (!notice && ismine && acptr->user->away)
 1994             sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], acptr->name,
 1995                        acptr->user->away);
 1996 
 1997         sendto_prefix_one(acptr, sptr, ":%s %s %s :%s", parv[0], cmd, target,
 1998                           parv[2]);
 1999 
 2000         /* next target */
 2001         continue;
 2002     }
 2003 
 2004     /* too many targets */
 2005     if (target)
 2006     {
 2007         if (!notice)
 2008             sendto_one(sptr, err_str(ERR_TOOMANYTARGETS), me.name, parv[0],
 2009                    target);
 2010 
 2011         if (sptr->user)
 2012             sendto_realops_lev(SPY_LEV, "User %s (%s@%s) tried to %s more than"
 2013                                " %d targets", sptr->name, sptr->user->username,
 2014                                sptr->user->host, notice ? "notice" : "msg",
 2015                                MAXRECIPIENTS);
 2016     }
 2017 
 2018     return 0;
 2019 }
 2020 
 2021 /*
 2022  * m_private 
 2023  * parv[0] = sender prefix 
 2024  * parv[1] = receiver list 
 2025  * parv[2] = message text
 2026  */
 2027 
 2028 int 
 2029 m_private(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2030 {
 2031     return m_message(cptr, sptr, parc, parv, 0);
 2032 }
 2033 
 2034 /*
 2035  * m_notice *
 2036  * parv[0] = sender prefix 
 2037  * parv[1] = receiver list
 2038  * parv[2] = notice text
 2039  */
 2040 
 2041 int 
 2042 m_notice(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2043 {
 2044     return m_message(cptr, sptr, parc, parv, 1);
 2045 }
 2046 
 2047 
 2048 /*
 2049  * m_whois 
 2050  * parv[0] = sender prefix 
 2051  * parv[1] = nickname masklist
 2052  */
 2053 int 
 2054 m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2055 {
 2056     Link   *lp;
 2057     anUser *user;
 2058     aClient    *acptr, *a2cptr;
 2059     aChannel   *chptr;
 2060     char       *nick, *tmp, *name;
 2061     char       *p = NULL;
 2062     ServicesTag *servicestag;
 2063     int         len, mlen;
 2064 
 2065     if (parc < 2)
 2066     {
 2067         sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
 2068                    me.name, parv[0]);
 2069         return 0;
 2070     }
 2071 
 2072     if (parc > 2)
 2073     {
 2074 #ifdef NO_USER_OPERTARGETED_COMMANDS
 2075         /*
 2076          * Block /whois <anything> <nick1,nick2,nick3>
 2077          * Also block /whois <server> <nick> for +I users
 2078          */
 2079         if(!IsAnOper(sptr))
 2080         {
 2081             acptr = hash_find_client(parv[2], (aClient *) NULL);
 2082             if (!acptr || !IsPerson(acptr))
 2083             {
 2084                 sendto_one(sptr, err_str(ERR_NOSUCHNICK),
 2085                            me.name, parv[0], parv[2]);
 2086                 return 0;
 2087             }
 2088 
 2089             if(IsUmodeI(acptr))
 2090             {
 2091                 /* allow /whois nick nick, but nothing else */
 2092                 if(mycmp(parv[1], parv[2]) == 0)
 2093                     parv[1] = acptr->user->server; /* And kludge it */
 2094                 else if(MyClient(sptr))
 2095                 {
 2096                     sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, 
 2097                                parv[0]);
 2098                     return 0;
 2099                 }
 2100             }
 2101         }
 2102 #endif
 2103         if (hunt_server(cptr, sptr, ":%s WHOIS %s :%s", 1, parc, parv) !=
 2104             HUNTED_ISME)
 2105             return 0;
 2106         parv[1] = parv[2];    
 2107     }
 2108 
 2109     for (p = NULL, tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL)
 2110     {
 2111         int showchan;
 2112                 
 2113         acptr = hash_find_client(nick, (aClient *) NULL);
 2114         if (!acptr || !IsPerson(acptr))
 2115         {
 2116             sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
 2117             continue;
 2118         }
 2119 
 2120         if (call_hooks(CHOOK_WHOIS, sptr, acptr) == FLUSH_BUFFER) continue;
 2121                 
 2122         user = acptr->user;
 2123         name = (!*acptr->name) ? "?" : acptr->name;
 2124                 
 2125         a2cptr = acptr->uplink;
 2126                 
 2127         sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, parv[0], name,
 2128                    user->username, 
 2129 #ifdef USER_HOSTMASKING
 2130                    IsUmodeH(acptr)?user->mhost:
 2131 #endif
 2132                    user->host, acptr->info);
 2133         if(IsUmodeH(acptr) && (sptr==acptr || IsAnOper(sptr)))
 2134         {
 2135             sendto_one(sptr, rpl_str(RPL_WHOISACTUALLY), me.name,
 2136                        sptr->name, name, user->username, user->host,
 2137                        acptr->hostip);
 2138          }
 2139 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 2140 #if (RIDICULOUS_PARANOIA_LEVEL==1)
 2141         if(MyConnect(acptr) && user->real_oper_host && 
 2142                 (IsAdmin(sptr) || (sptr == acptr)))
 2143             sendto_one(sptr, rpl_str(RPL_WHOISACTUALLY), me.name, sptr->name, 
 2144                        name, user->real_oper_username, user->real_oper_host, 
 2145                        user->real_oper_ip);
 2146 #endif
 2147 #if (RIDICULOUS_PARANOIA_LEVEL==2)
 2148         if(MyConnect(acptr) && user->real_oper_host && 
 2149                 (IsAdmin(sptr) || (sptr == acptr)) && MyConnect(sptr))
 2150             sendto_one(sptr, rpl_str(RPL_WHOISACTUALLY), me.name, sptr->name, 
 2151                        name, user->real_oper_username, user->real_oper_host,
 2152                        user->real_oper_ip);
 2153 #endif
 2154 #endif
 2155         mlen = strlen(me.name) + strlen(parv[0]) + 9 + strlen(name);
 2156         for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next)
 2157         {
 2158             chptr = lp->value.chptr;
 2159             showchan=ShowChannel(sptr,chptr);
 2160             if (showchan || IsAdmin(sptr))
 2161             {
 2162                 if (len + strlen(chptr->chname) > (size_t) BUFSIZE - 4 - mlen)
 2163                 {
 2164                     sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, parv[0], name, buf);
 2165                     *buf = '\0';
 2166                     len = 0;
 2167                 }
 2168                 if(!showchan) /* if we're not really supposed to show the chan
 2169                                * but do it anyways, mark it as such! */
 2170 #ifdef USE_HALFOPS
 2171                     *(buf + len++) = '~';
 2172 #else
 2173                     *(buf + len++) = '%';
 2174 #endif
 2175                 if (is_chan_op(acptr, chptr))
 2176                     *(buf + len++) = '@';
 2177 #ifdef USE_HALFOPS
 2178                 else if (is_chan_halfop(acptr, chptr))
 2179                     *(buf + len++) = '%';
 2180 #endif
 2181                 else if (has_voice(acptr, chptr))
 2182                     *(buf + len++) = '+';
 2183                 if (len)
 2184                     *(buf + len) = '\0';
 2185                 strcpy(buf + len, chptr->chname);
 2186                 len += strlen(chptr->chname);
 2187                 strcat(buf + len, " ");
 2188                 len++;
 2189             }
 2190         }
 2191         if (buf[0] != '\0')
 2192             sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, 
 2193                        parv[0], name, buf);
 2194         if(!(IsUmodeI(acptr) && !IsAnOper(sptr)) || (acptr == sptr))
 2195         {       
 2196              sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], name,
 2197                      user->server, a2cptr ? a2cptr->info : "*Not On This Net*");
 2198         }
 2199         else /* hidden oper! */
 2200         {       
 2201              sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], 
 2202                         name, HIDDEN_SERVER_NAME, HIDDEN_SERVER_DESC);
 2203         }
 2204         
 2205         if(IsAnOper(sptr) && IsSquelch(acptr))
 2206             sendto_one(sptr, rpl_str(RPL_WHOISTEXT), me.name, parv[0], name, 
 2207                        IsWSquelch(acptr) ?  "User is squelched (warned)" :
 2208                        "User is squelched (silent)");
 2209         
 2210         if(IsRegNick(acptr))
 2211             sendto_one(sptr, rpl_str(RPL_WHOISREGNICK), me.name, parv[0], name);
 2212         if (user->away)
 2213             sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, 
 2214                        user->away);
 2215         if(IsUmodeS(acptr))
 2216             sendto_one(sptr, rpl_str(RPL_USINGSSL), me.name, parv[0], name);
 2217         
 2218         buf[0] = '\0';
 2219         if (IsAnOper(acptr))
 2220             strcat(buf, "an IRC Operator");
 2221         if (IsAdmin(acptr))
 2222             strcat(buf, " - Server Administrator");
 2223         else if (IsSAdmin(acptr))
 2224             strcat(buf, " - Services Administrator");
 2225         /* We don't go through the services tag list here by design, only the first services tag entry
 2226            may change RPL_WHOISOPERATOR -Kobi_S. */
 2227         if (buf[0] && (!acptr->user->servicestag || acptr->user->servicestag->raw!=RPL_WHOISOPERATOR))
 2228             sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR), me.name, parv[0], 
 2229                        name, buf);
 2230 
 2231         if(acptr->user->servicestag)
 2232         {
 2233             servicestag = acptr->user->servicestag;
 2234             while(servicestag)
 2235             {
 2236                 if(*servicestag->tag && (!servicestag->umode || (sptr->umode & servicestag->umode))) sendto_one(sptr, ":%s %d %s %s :%s", me.name, servicestag->raw, parv[0], name, servicestag->tag);
 2237                 servicestag = servicestag->next;
 2238             }
 2239         }
 2240 
 2241     if (MyConnect(acptr) && acptr->webirc_ip && IsAdmin(sptr))
 2242     {
 2243             sendto_one(sptr, ":%s 337 %s %s :%s (%s@%s)",
 2244                me.name, parv[0], name,
 2245                "User connected using a webirc gateway",
 2246                acptr->webirc_username, acptr->webirc_ip);
 2247     }
 2248     else if (MyConnect(acptr) && acptr->webirc_ip && IsAnOper(sptr))
 2249     {
 2250             sendto_one(sptr, ":%s 337 %s %s :%s (%s)",
 2251                me.name, parv[0], name,
 2252                "User connected using a webirc gateway",
 2253                acptr->webirc_username);
 2254     }
 2255 
 2256         if(IsAdmin(sptr))
 2257         {
 2258             buf2[0]='\0';
 2259             send_umode(NULL, acptr, 0, ALL_UMODES, buf2, sizeof(buf2));
 2260             if (!*buf2)
 2261             {
 2262                 buf2[0] = '+';
 2263                 buf2[1] = '\0';
 2264             }
 2265             sendto_one(sptr, rpl_str(RPL_WHOISMODES), me.name, parv[0], name, buf2);
 2266         }
 2267 
 2268         /* don't give away that this oper is on this server if they're hidden! */
 2269         if (acptr->user && MyConnect(acptr) && ((sptr == acptr) || 
 2270                 !IsUmodeI(acptr) || (parc > 2) || IsAnOper(sptr)))
 2271             sendto_one(sptr, rpl_str(RPL_WHOISIDLE), me.name, parv[0], name,
 2272                        timeofday - user->last, acptr->firsttime);
 2273         
 2274         continue;
 2275     }
 2276     sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], parv[1]);
 2277     return 0;
 2278 }
 2279 
 2280 /*
 2281  * m_user 
 2282  * parv[0] = sender prefix
 2283  * parv[1] = username (login name, account) 
 2284  * parv[2] = client host name (used only from other servers) 
 2285  * parv[3] = server host name (used only from other servers)
 2286  * parv[4] = users real name info
 2287  */
 2288 int 
 2289 m_user(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2290 {
 2291     char       *username, *host, *server, *realname;
 2292     struct simBan *ban;
 2293 
 2294     /* FTP proxy */
 2295     if (!IsRegistered(cptr) && parc == 2 && cptr->receiveM == 1)
 2296         return reject_proxy(cptr, "USER", parv[1]);
 2297     
 2298     if (parc > 2 && (username = (char *) strchr(parv[1], '@')))
 2299         *username = '\0';
 2300     if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
 2301         *parv[3] == '\0' || *parv[4] == '\0')
 2302     {
 2303         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USER");
 2304         if (IsServer(cptr))
 2305             sendto_realops("bad USER param count for %s from %s",
 2306                            parv[0], get_client_name(cptr, FALSE));
 2307         else
 2308             return 0;
 2309     }
 2310     /* Copy parameters into better documenting variables */   
 2311     username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
 2312     host = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
 2313     server = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];
 2314     realname = (parc < 5 || BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
 2315     if ((ban = check_mask_simbanned(realname, SBAN_GCOS))) 
 2316     {
 2317         int loc = (ban->flags & SBAN_LOCAL) ? 1 : 0;
 2318         return exit_banned_client(cptr, loc, 'G', ban->reason, 0);
 2319     }
 2320     if(call_hooks(CHOOK_ONACCESS, cptr, username, host, server, realname) == FLUSH_BUFFER) return 0;
 2321     return do_user(parv[0], cptr, sptr, username, host, server, 0,0, realname);
 2322 }
 2323 
 2324 /* do_user */
 2325 int 
 2326 do_user(char *nick, aClient *cptr, aClient *sptr, char *username, char *host, 
 2327         char *server, unsigned long serviceid, char *ip, char *realname)
 2328 {
 2329     anUser     *user;
 2330     
 2331     user = make_user(sptr);
 2332     
 2333     /*
 2334      * changed the goto into if-else...   -Taner 
 2335      * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GOOD FOR YOU Taner!!! - Dianora 
 2336      */
 2337     
 2338     if (!MyConnect(sptr))
 2339     {
 2340         user->server = find_or_add(server);
 2341         strncpyzt(user->host, host, sizeof(user->host));
 2342 #ifdef USER_HOSTMASKING
 2343         strncpyzt(user->mhost, mask_host(host,0), HOSTLEN + 1);
 2344 #endif
 2345     } 
 2346     else
 2347     {
 2348         if (!IsUnknown(sptr))
 2349         {
 2350             sendto_one(sptr, err_str(ERR_ALREADYREGISTRED),
 2351                        me.name, nick);
 2352             return 0;
 2353         }
 2354         sptr->umode |= (USER_UMODES & atoi(host));
 2355 #ifndef NO_DEFAULT_INVISIBLE
 2356         sptr->umode |= UMODE_i;
 2357 #endif
 2358 #ifdef USE_SSL
 2359         if(IsSSL(sptr))
 2360             sptr->umode |= UMODE_S;
 2361 #endif
 2362 #ifdef NO_USER_SERVERKILLS
 2363         sptr->umode &= ~UMODE_k;
 2364 #endif
 2365 #ifdef NO_USER_OPERKILLS
 2366         sptr->umode &= ~UMODE_s;
 2367 #endif
 2368         strncpyzt(user->host, host, sizeof(user->host));
 2369 #ifdef USER_HOSTMASKING
 2370         if((uhm_type > 0) && (uhm_umodeh == 1)) sptr->umode |= UMODE_H;
 2371         else sptr->umode &= ~UMODE_H;
 2372 #endif
 2373         user->server = me.name;
 2374     }
 2375     strncpyzt(sptr->info, realname, sizeof(sptr->info));
 2376     
 2377     sptr->user->servicestamp = serviceid;
 2378     if (!MyConnect(sptr))  
 2379     {
 2380     if (inet_pton(AF_INET, ip, &sptr->ip.ip4) == 1)
 2381     {
 2382         if (sptr->ip.ip4.s_addr != htonl(1))
 2383         sptr->ip_family = AF_INET;
 2384         else
 2385         sptr->ip_family = 0;
 2386     }
 2387     else if (inet_pton(AF_INET6, ip, &sptr->ip.ip6) == 1)
 2388         sptr->ip_family = AF_INET6;
 2389     else
 2390     {
 2391         char *end;
 2392         unsigned long l;
 2393 
 2394         l = ntohl(strtoul(ip, &end, 10));
 2395         if (*ip != '\0' && *end == '\0')
 2396         {
 2397         if (l != htonl(1))
 2398             sptr->ip_family = AF_INET;
 2399         else
 2400             sptr->ip_family = 0;
 2401 
 2402         sptr->ip.ip4.s_addr = l;
 2403         ip = inetntoa((char *)&sptr->ip);
 2404         }
 2405         else
 2406         sptr->ip_family = 0;
 2407     }
 2408 
 2409         /* add non-local clients to the throttle checker.  obviously, we only
 2410          * do this for REMOTE clients!@$$@!  throttle_check() is called
 2411          * elsewhere for the locals! -wd */
 2412 #ifdef THROTTLE_ENABLE
 2413     if (sptr->ip_family == 0)
 2414         ;
 2415     else if (sptr->ip_family == AF_INET && sptr->ip.ip4.s_addr == 0)
 2416         ;
 2417     else
 2418         throttle_check(ip, -1, sptr->tsinfo);
 2419 #endif
 2420     }
 2421     if(MyConnect(sptr))
 2422         sptr->oflag=0;
 2423     if (sptr->name[0])          /* NICK already received, now I have USER... */
 2424         return register_user(cptr, sptr, sptr->name, username, ip);
 2425     else
 2426         strncpyzt(sptr->user->username, username, USERLEN + 1);
 2427     return 0;
 2428 }
 2429 
 2430 /*
 2431  * m_quit 
 2432  * parv[0] = sender prefix 
 2433  * parv[1] = comment
 2434  */
 2435 int 
 2436 m_quit(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2437 {
 2438     char *reason = (parc > 1 && parv[1]) ? parv[1] : cptr->name;
 2439     char  comment[TOPICLEN + 1];
 2440     int blocked;
 2441     aChannel *chptr;
 2442     Link *lp, *lpn;
 2443     
 2444     sptr->flags |= FLAGS_NORMALEX;
 2445     if (!IsServer(cptr))
 2446     {
 2447         if(IsSquelch(sptr))
 2448             reason = cptr->name;
 2449         strcpy(comment, "Quit: ");
 2450         strncpy(comment + 6, reason, TOPICLEN - 6); 
 2451         comment[TOPICLEN] = 0;
 2452         if(IsPerson(sptr))
 2453         {
 2454 #ifdef SPAMFILTER
 2455             blocked = check_sf(sptr, reason, "quit", SF_CMD_QUIT, sptr->name);
 2456 #endif
 2457             for(lp = sptr->user->channel; lp; lp = lpn)
 2458             {
 2459                 lpn = lp->next;
 2460                 chptr = lp->value.chptr;
 2461 #ifdef SPAMFILTER
 2462                 if(blocked && !(chptr->mode.mode & MODE_PRIVACY))
 2463                 {
 2464                     sendto_serv_butone(cptr, ":%s PART %s", parv[0], chptr->chname);
 2465                     sendto_channel_butserv(chptr, sptr, ":%s PART %s", parv[0], chptr->chname);
 2466                     remove_user_from_channel(sptr, chptr);
 2467                     continue; /* If we already parted, there is no need to check the xflags... -Kobi. */
 2468                 }
 2469 #endif
 2470                 if((chptr->xflags & XFLAG_NO_QUIT_MSG) && !is_xflags_exempted(sptr,chptr))
 2471                 {
 2472                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 2473                         verbose_to_relaychan(cptr, chptr, "quit_msg", comment);
 2474                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 2475                         verbose_to_opers(cptr, chptr, "quit_msg", comment);
 2476                     sendto_serv_butone(cptr, ":%s PART %s", parv[0], chptr->chname);
 2477                     sendto_channel_butserv(chptr, sptr, ":%s PART %s", parv[0], chptr->chname);
 2478                     remove_user_from_channel(sptr, chptr);
 2479                 }
 2480             }
 2481         }
 2482 
 2483         return exit_client(cptr, sptr, sptr, comment);
 2484     }
 2485     else
 2486         return exit_client(cptr, sptr, sptr, reason);
 2487 }
 2488 
 2489 /*
 2490  * m_kill 
 2491  * parv[0] = sender prefix 
 2492  * parv[1] = kill victim 
 2493  * parv[2] = kill path
 2494  */
 2495 int 
 2496 m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2497 {
 2498     aClient    *acptr;
 2499     char       *user, *path, *p, *nick, *reason;
 2500     char        mypath[KILLLEN + 1];
 2501     char        mymsg[KILLLEN + 1];
 2502     char       *unknownfmt = "<Unknown>";       /*
 2503                                                  * AFAIK this shouldnt happen
 2504                                                  * but -Raist 
 2505                                                  */
 2506     int         chasing = 0, kcount = 0;
 2507     
 2508     if (parc < 2 || *parv[1] == '\0')
 2509     {
 2510         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KILL");
 2511         return 0;
 2512     }
 2513     
 2514     user = parv[1];
 2515     path = parv[2];             /* Either defined or NULL (parc >= 2!!) */
 2516     
 2517     if (!IsPrivileged(cptr))
 2518     {
 2519         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
 2520         return 0;
 2521     }
 2522 
 2523     if (!BadPtr(path))
 2524         if (strlen(path) > (size_t) KILLLEN)
 2525             path[KILLLEN] = '\0';
 2526 
 2527     if (MyClient(sptr))
 2528         user = canonize(user);
 2529     for (p = NULL, nick = strtoken(&p, user, ","); nick; 
 2530          nick = strtoken(&p, NULL, ","))
 2531     {
 2532         chasing = 0;
 2533         if (!(acptr = find_client(nick, NULL)))
 2534         {
 2535             /*
 2536              * If the user has recently changed nick, we automaticly
 2537              * rewrite the KILL for this new nickname--this keeps
 2538              * servers in synch when nick change and kill collide
 2539              */
 2540             if (!(acptr = get_history(nick, (long) KILLCHASETIMELIMIT)))
 2541             {
 2542                 sendto_one(sptr, err_str(ERR_NOSUCHNICK),
 2543                            me.name, parv[0], nick);
 2544                 return 0;
 2545             }
 2546             sendto_one(sptr, ":%s NOTICE %s :KILL changed from %s to %s",
 2547                        me.name, parv[0], nick, acptr->name);
 2548             chasing = 1;
 2549         }
 2550         if((!MyConnect(acptr) && MyClient(cptr) && !OPCanGKill(cptr)) ||
 2551             (MyConnect(acptr) && MyClient(cptr) && !OPCanLKill(cptr)))
 2552         {
 2553             sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
 2554             continue;
 2555         }
 2556         if(IsServer(acptr) || IsMe(acptr) || (MyClient(sptr) && IsULine(acptr)))
 2557         {
 2558             sendto_one(sptr, err_str(ERR_CANTKILLSERVER),
 2559                        me.name, parv[0]);
 2560             continue;
 2561         }
 2562         kcount++;
 2563         if (!IsServer(sptr) && (kcount > MAXKILLS))
 2564         {
 2565             sendto_one(sptr,":%s NOTICE %s :Too many targets, kill list was "
 2566                        "truncated. Maximum is %d.", me.name, sptr->name,
 2567                        MAXKILLS);
 2568             break;
 2569         }
 2570         if(MyClient(sptr)) 
 2571         {
 2572             char myname[HOSTLEN+1], *s;
 2573 
 2574             if(!BadPtr(path))
 2575             {
 2576                 ircsnprintf(mymsg, KILLLEN + 1, "(%s)", path);
 2577                 reason = mymsg;
 2578             }
 2579             else
 2580                 reason = "(No reason specified)";
 2581 
 2582             strncpy(myname, me.name, HOSTLEN + 1);
 2583             if((s = strchr(myname, '.')))
 2584                 *s = 0;
 2585             
 2586             ircsnprintf(mypath, KILLLEN + 1, "%s!%s!%s", myname, 
 2587 #ifdef USER_HOSTMASKING
 2588                         IsUmodeH(sptr)?sptr->user->mhost:
 2589 #endif
 2590                         sptr->user->host,
 2591                         sptr->user->username); 
 2592         }
 2593         else
 2594         {
 2595             if(BadPtr(path) || !(reason = strchr(path, ' ')))
 2596             {
 2597                 path = sptr->name;
 2598                 reason = "(No reason specified)";
 2599             }
 2600             else
 2601             {
 2602                 *reason = '\0';
 2603                 reason++;
 2604             }
 2605             strncpyzt(mypath, path, KILLLEN + 1);
 2606         }
 2607         /*
 2608          * Notify all *local* opers about the KILL, this includes the
 2609          * one originating the kill, if from this server--the special
 2610          * numeric reply message is not generated anymore.
 2611          * 
 2612          * Note: "acptr->name" is used instead of "user" because we may
 2613          * have changed the target because of the nickname change.
 2614          */
 2615         if (IsLocOp(sptr) && !MyConnect(acptr)) 
 2616         {
 2617             sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
 2618             return 0;
 2619         }
 2620         if(IsULine(sptr))
 2621             sendto_realops_lev(USKILL_LEV, 
 2622                            "Received KILL message for %s!%s@%s. "
 2623                            "From %s Path: %s %s", acptr->name,
 2624                            acptr->user ? acptr->user->username : unknownfmt,
 2625                            acptr->user ?
 2626 #ifdef USER_HOSTMASKING
 2627                              IsUmodeH(acptr)?acptr->user->mhost:
 2628 #endif
 2629                              acptr->user->host : unknownfmt,
 2630                            parv[0], mypath, reason);
 2631         else if (IsAnOper(sptr))
 2632             sendto_ops_lev(0,
 2633                            "Received KILL message for %s!%s@%s. From %s "
 2634                            "Path: %s %s", acptr->name, 
 2635                            acptr->user ? acptr->user->username : unknownfmt,
 2636                            acptr->user ?
 2637 #ifdef USER_HOSTMASKING
 2638                              IsUmodeH(acptr)?acptr->user->mhost:
 2639 #endif
 2640                              acptr->user->host : unknownfmt,
 2641                            parv[0], mypath, reason);
 2642         else
 2643             sendto_ops_lev(SKILL_LEV, 
 2644                            "Received KILL message for %s!%s@%s. "
 2645                            "From %s Path: %s %s", acptr->name,
 2646                            acptr->user ? acptr->user->username : unknownfmt,
 2647                            acptr->user ?
 2648 #ifdef USER_HOSTMASKING
 2649                              IsUmodeH(acptr)?acptr->user->mhost:
 2650 #endif
 2651                              acptr->user->host : unknownfmt,
 2652                            parv[0], mypath, reason);
 2653                 
 2654 #if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
 2655         if (IsOper(sptr))
 2656             syslog(LOG_INFO, "KILL From %s!%s@%s For %s Path %s %s",
 2657                   parv[0], acptr->name,
 2658                   acptr->user ? acptr->user->username : unknownfmt,
 2659                   acptr->user ? acptr->user->host : unknownfmt, mypath, reason);
 2660 #endif
 2661         /*
 2662          * And pass on the message to other servers. Note, that if KILL
 2663          * was changed, the message has to be sent to all links, also
 2664          * back. Suicide kills are NOT passed on --SRB
 2665          */
 2666         /*
 2667          * Set FLAGS_KILLED. This prevents exit_one_client from sending
 2668          * the unnecessary QUIT for this. ,This flag should never be
 2669          * set in any other place...
 2670          */
 2671         if(!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
 2672         {
 2673             sendto_serv_butone(cptr, ":%s KILL %s :%s %s",
 2674                                parv[0], acptr->name, mypath, reason);
 2675             if (chasing && IsServer(cptr))
 2676                 sendto_one(cptr, ":%s KILL %s :%s %s",
 2677                            me.name, acptr->name, mypath, reason);
 2678             acptr->flags |= FLAGS_KILLED;
 2679         }
 2680         /*
 2681          * Tell the victim she/he has been zapped, but *only* if the
 2682          * victim is on current server--no sense in sending the
 2683          * notification chasing the above kill, it won't get far anyway
 2684          * as this user don't exist there any more either
 2685          */
 2686 #ifndef HIDE_KILL_ORIGINS
 2687         if (MyConnect(acptr))
 2688             sendto_prefix_one(acptr, sptr, ":%s KILL %s :%s %s",
 2689                               parv[0], acptr->name, mypath, reason);
 2690 
 2691         if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))
 2692             ircsprintf(buf2, "Local kill by %s %s", sptr->name, reason);
 2693         else 
 2694             ircsprintf(buf2, "Killed (%s %s)", sptr->name, reason);
 2695 #else
 2696         if (MyConnect(acptr))
 2697             sendto_one(acptr, ":%s KILL %s :%s %s",
 2698                        HIDDEN_SERVER_NAME, acptr->name,
 2699                        HIDDEN_SERVER_NAME, reason);
 2700 
 2701         ircsprintf(buf2, "Killed (%s %s)", HIDDEN_SERVER_NAME, reason);
 2702 #endif
 2703 
 2704         if (exit_client(cptr, acptr, sptr, buf2) == FLUSH_BUFFER)
 2705             return FLUSH_BUFFER;
 2706     }
 2707     return 0;
 2708 }
 2709 
 2710 /***********************************************************************
 2711  * m_away() - Added 14 Dec 1988 by jto.
 2712  *            Not currently really working, I don't like this
 2713  *            call at all...
 2714  *
 2715  *            ...trying to make it work. I don't like it either,
 2716  *            but perhaps it's worth the load it causes to net.
 2717  *            This requires flooding of the whole net like NICK,
 2718  *            USER, MODE, etc messages...  --msa
 2719  *
 2720  *            Added FLUD-style limiting for those lame scripts out there.
 2721  ***********************************************************************/
 2722 /*
 2723  * m_away 
 2724  * parv[0] = sender prefix 
 2725  * parv[1] = away message
 2726  */
 2727 int 
 2728 m_away(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2729 {
 2730     char   *away, *awy2 = parv[1];
 2731     /* make sure the user exists */
 2732     if (!(sptr->user)) 
 2733     {
 2734         sendto_realops_lev(DEBUG_LEV, "Got AWAY from nil user, from %s (%s)\n",
 2735                            cptr->name, sptr->name);
 2736         return 0;
 2737     }
 2738     
 2739     away = sptr->user->away;
 2740     
 2741 #ifdef NO_AWAY_FLUD
 2742     if(MyClient(sptr))
 2743     {
 2744         if ((sptr->alas + MAX_AWAY_TIME) < NOW)
 2745             sptr->acount = 0;
 2746         sptr->alas = NOW;
 2747         sptr->acount++;
 2748     }
 2749 #endif 
 2750     
 2751     if (parc < 2 || !*awy2)
 2752     {
 2753         /* Marking as not away */
 2754         if (away) 
 2755         {
 2756             MyFree(away);
 2757             sptr->user->away = NULL;
 2758             /* Don't spam unaway unless they were away - lucas */
 2759             sendto_serv_butone_super(cptr, ULF_NOAWAY, ":%s AWAY", parv[0]);
 2760         }
 2761         
 2762         if (MyConnect(sptr))
 2763             sendto_one(sptr, rpl_str(RPL_UNAWAY), me.name, parv[0]);
 2764         return 0;
 2765     }
 2766 
 2767     /* Marking as away */
 2768 #ifdef NO_AWAY_FLUD
 2769     /* we dont care if they are just unsetting away, hence this is here */
 2770     /* only care about local non-opers */
 2771     if (MyClient(sptr) && (sptr->acount > MAX_AWAY_COUNT) && !IsAnOper(sptr))
 2772     {
 2773         sendto_one(sptr, err_str(ERR_TOOMANYAWAY), me.name, parv[0]);
 2774         return 0;
 2775     }
 2776 #endif
 2777     if (strlen(awy2) > (size_t) TOPICLEN)
 2778         awy2[TOPICLEN] = '\0';
 2779 
 2780 #ifdef SPAMFILTER
 2781     if(MyClient(sptr) && check_sf(sptr, awy2, "away", SF_CMD_AWAY, sptr->name))
 2782         return FLUSH_BUFFER;
 2783 #endif
 2784 
 2785     /*
 2786      * some lamers scripts continually do a /away, hence making a lot of
 2787      * unnecessary traffic. *sigh* so... as comstud has done, I've
 2788      * commented out this sendto_serv_butone() call -Dianora
 2789      * readded because of anti-flud stuffs -epi
 2790      */
 2791     
 2792     sendto_serv_butone_super(cptr, ULF_NOAWAY, ":%s AWAY :%s", parv[0], parv[1]);
 2793 
 2794     if (away)
 2795         MyFree(away);
 2796     
 2797     away = (char *) MyMalloc(strlen(awy2) + 1);
 2798     strcpy(away, awy2);
 2799 
 2800     sptr->user->away = away;
 2801 
 2802     if (MyConnect(sptr))
 2803         sendto_one(sptr, rpl_str(RPL_NOWAWAY), me.name, parv[0]);
 2804     return 0;
 2805 }
 2806 
 2807 /*
 2808  * m_ping 
 2809  * parv[0] = sender prefix 
 2810  * parv[1] = origin
 2811  * parv[2] = destination
 2812  */
 2813 int 
 2814 m_ping(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2815 {
 2816     aClient    *acptr;
 2817     char       *origin, *destination;
 2818     
 2819     if (parc < 2 || *parv[1] == '\0')
 2820     {
 2821         sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
 2822         return 0;
 2823     }
 2824     origin = parv[1];
 2825     destination = parv[2];      /* Will get NULL or pointer (parc >= 2!!) */
 2826     
 2827     acptr = find_client(origin, NULL);
 2828     if (!acptr)
 2829         acptr = find_server(origin, NULL);
 2830     if (acptr && acptr != sptr)
 2831         origin = cptr->name;
 2832     if (!BadPtr(destination) && mycmp(destination, me.name) != 0)
 2833     {
 2834         if ((acptr = find_server(destination, NULL)))
 2835             sendto_one(acptr, ":%s PING %s :%s", parv[0], origin, destination);
 2836         else
 2837         {
 2838             sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], 
 2839                        destination);
 2840             return 0;
 2841         }
 2842     }
 2843     else
 2844         sendto_one(sptr, ":%s PONG %s :%s", me.name,
 2845                    (destination) ? destination : me.name, origin);
 2846     return 0;
 2847 }
 2848 
 2849 /*
 2850  * m_pong 
 2851  * parv[0] = sender prefix 
 2852  * parv[1] = origin
 2853  * parv[2] = destination
 2854  */
 2855 int 
 2856 m_pong(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2857 {
 2858     aClient    *acptr;
 2859     char       *origin, *destination;
 2860 
 2861     if (parc < 2 || *parv[1] == '\0')
 2862     {
 2863         sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
 2864         return 0;
 2865     }
 2866 
 2867     origin = parv[1];
 2868     destination = parv[2];
 2869     cptr->flags &= ~FLAGS_PINGSENT;
 2870     sptr->flags &= ~FLAGS_PINGSENT;
 2871 
 2872     /* if it's my client and it's a server.. */
 2873     if(sptr == cptr && IsServer(cptr))
 2874     {
 2875         if(sptr->flags & FLAGS_USERBURST)
 2876         {
 2877             sptr->flags &= ~FLAGS_USERBURST;
 2878             sendto_gnotice("from %s: %s has processed user/channel burst, "
 2879                            "sending topic burst.", me.name, sptr->name);
 2880             send_topic_burst(sptr);
 2881             sptr->flags |= FLAGS_PINGSENT|FLAGS_SOBSENT;
 2882             sendto_one(sptr, "PING :%s", me.name);
 2883         }
 2884         else if(sptr->flags & FLAGS_TOPICBURST)
 2885         {
 2886             sptr->flags &= ~FLAGS_TOPICBURST;
 2887             sendto_gnotice("from %s: %s has processed topic burst (synched "
 2888                            "to network data).", me.name, sptr->name);
 2889 
 2890             if(server_was_split)
 2891                 server_was_split = NO;
 2892 
 2893             if(confopts & FLAGS_HUB)
 2894                 sendto_serv_butone(sptr, ":%s GNOTICE :%s has synched to"
 2895                                " network data.", me.name, sptr->name);
 2896                 /* Kludge: Get the "sync" message on small networks 
 2897                  * immediately */ 
 2898             sendto_one(sptr, "PING :%s", me.name);
 2899         }
 2900     }
 2901 
 2902     /*
 2903      * Now attempt to route the PONG, comstud pointed out routable PING
 2904      * is used for SPING.  routable PING should also probably be left in
 2905      * -Dianora That being the case, we will route, but only for
 2906      * registered clients (a case can be made to allow them only from
 2907      * servers). -Shadowfax
 2908      */
 2909     if (!BadPtr(destination) && (mycmp(destination, me.name) != 0)
 2910         && IsRegistered(sptr))
 2911     {
 2912         if ((acptr = find_client(destination, NULL)) ||
 2913             (acptr = find_server(destination, NULL)))
 2914             sendto_one(acptr, ":%s PONG %s %s", parv[0], origin, destination);
 2915         else
 2916         {
 2917             sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], 
 2918                        destination);
 2919             return 0;
 2920         }
 2921     }
 2922 #ifdef  DEBUGMODE
 2923     else
 2924         Debug((DEBUG_NOTICE, "PONG: %s %s", origin, 
 2925                destination ? destination : "*"));
 2926 #endif
 2927     return 0;
 2928 }
 2929 
 2930 /* added Sat Jul 25 07:30:42 EST 1992 */
 2931 /*
 2932  * extra argument evenTS added to send to TS servers or not -orabidoo
 2933  *
 2934  * extra argument evenTS no longer needed with TS only th+hybrid server
 2935  * -Dianora
 2936  */
 2937 static inline void
 2938 send_umode_out(aClient *cptr, aClient *sptr, int old)
 2939 {
 2940     aClient *acptr;
 2941     DLink *lp;
 2942 
 2943     send_umode(NULL, sptr, old, SEND_UMODES, buf, sizeof(buf));
 2944 
 2945     if(*buf)
 2946     {
 2947         for(lp = server_list; lp; lp = lp->next)
 2948         {
 2949             acptr = lp->value.cptr;
 2950             if((acptr != cptr) && (acptr != sptr))
 2951                 sendto_one(acptr, ":%s MODE %s :%s", sptr->name,
 2952                            sptr->name, buf);
 2953         }
 2954     }
 2955 
 2956     if (cptr && MyClient(cptr))
 2957         send_umode(cptr, sptr, old, ALL_UMODES, buf, sizeof(buf));
 2958 }
 2959 
 2960 /*
 2961  * m_oper 
 2962  * parv[0] = sender prefix 
 2963  * parv[1] = oper name 
 2964  * parv[2] = oper password
 2965  */
 2966 int m_oper(aClient *cptr, aClient *sptr, int parc, char *parv[])
 2967 {
 2968     aOper       *aoper;
 2969     char        *name, *password, *encr, *oper_ip;
 2970     extern char *crypt();
 2971 
 2972     name = parc > 1 ? parv[1] : (char *) NULL;
 2973     password = parc > 2 ? parv[2] : (char *) NULL;
 2974 
 2975     if (!IsServer(cptr) && (BadPtr(name) || BadPtr(password)))
 2976     {
 2977         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "OPER");
 2978         return 0;
 2979     }
 2980 
 2981     /* an OPER message should never come from a server. complain */
 2982 
 2983     if (IsServer(cptr) || IsMe(cptr))
 2984     {
 2985         sendto_realops("Why is %s sending me an OPER? Contact Coders",
 2986                         cptr->name);
 2987         return 0;
 2988     }
 2989     else if (IsAnOper(sptr) && MyConnect(sptr))
 2990     {
 2991         send_rplisupportoper(sptr);
 2992         sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
 2993         return 0;
 2994     }
 2995 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 2996     if(!sptr->user->real_oper_host)
 2997     {
 2998 #endif
 2999         if(!(aoper = find_oper(name, sptr->user->username, sptr->user->host, 
 3000                                sptr->hostip)))
 3001         {
 3002             sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
 3003             sendto_ops_lev(ADMIN_LEV, "Failed OPER attempt by %s (%s@%s) [Unknown Account %s]",
 3004                            parv[0], sptr->user->username, sptr->user->host, name);
 3005             sendto_realops("Failed OPER attempt by %s [Unknown Account %s]", parv[0], name);
 3006             return 0;
 3007         }
 3008         oper_ip = sptr->hostip;
 3009 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 3010     }
 3011     else
 3012     {
 3013         if (!(aoper = find_oper(name, sptr->user->real_oper_username,
 3014                                       sptr->user->real_oper_host,
 3015                                       sptr->user->real_oper_ip))) 
 3016         {
 3017             sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
 3018             sendto_ops_lev(ADMIN_LEV, "Failed OPER attempt by %s (%s@%s) [Unknown Account %s]",
 3019                            parv[0], sptr->user->username, sptr->user->host, name);
 3020             sendto_realops("Failed OPER attempt by %s [Unknown account %s]", parv[0], name);
 3021             return 0;
 3022         }
 3023         oper_ip = sptr->user->real_oper_ip;
 3024     }
 3025 #endif
 3026     /* use first two chars of the password they send in as salt */
 3027     /* passwd may be NULL pointer. Head it off at the pass... */
 3028     if(confopts & FLAGS_CRYPTPASS)
 3029     {
 3030         if (password && *aoper->passwd)
 3031                 encr = crypt(password, aoper->passwd);
 3032         else
 3033                 encr = "";
 3034     }
 3035     else 
 3036         encr = password;
 3037     
 3038     if (StrEq(encr, aoper->passwd))
 3039     {
 3040         int old = (sptr->umode & ALL_UMODES);
 3041 
 3042         if(svsnoop)
 3043         {
 3044             sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
 3045             sendto_ops_lev(ADMIN_LEV, "Failed OPER attempt by %s (%s@%s) [svsnoop is enabled]",
 3046                            parv[0], sptr->user->username, sptr->user->host);
 3047             return 0;
 3048         }
 3049 
 3050         /* attach our conf */
 3051         sptr->user->oper = aoper;
 3052         aoper->opers++;
 3053         if (!(aoper->flags & OFLAG_ISGLOBAL))
 3054             SetLocOp(sptr);
 3055         else
 3056             SetOper(sptr);
 3057 #ifdef DEFAULT_HELP_MODE                        
 3058         sptr->umode|=(UMODE_s|UMODE_g|UMODE_w|UMODE_n|UMODE_h);
 3059 #else
 3060         sptr->umode|=(UMODE_s|UMODE_g|UMODE_w|UMODE_n);
 3061 #endif
 3062 #if defined(SPAMFILTER) && defined(DEFAULT_OPER_SPAMFILTER_DISABLED)
 3063         sptr->umode|=UMODE_P;
 3064 #endif
 3065         sptr->oflag = aoper->flags;
 3066         Count.oper++;
 3067         add_to_list(&oper_list, sptr);
 3068         throttle_remove(oper_ip);
 3069         sendto_ops("%s (%s!%s@%s) is now operator (%c)", aoper->nick,
 3070                    sptr->name, sptr->user->username, sptr->sockhost,
 3071                    IsOper(sptr) ? 'O' : 'o');
 3072         send_umode_out(cptr, sptr, old);
 3073         send_rplisupportoper(sptr);
 3074         sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
 3075         set_effective_class(sptr);
 3076 #if defined(USE_SYSLOG) && defined(SYSLOG_OPER)
 3077         syslog(LOG_INFO, "OPER (%s) (%s) by (%s!%s@%s)",
 3078                name, encr, parv[0], sptr->user->username, sptr->sockhost);
 3079 #endif
 3080 #ifdef MAXBUFFERS
 3081         /* give them server-sized socket buffers, throughput++ */
 3082         reset_sock_opts(sptr->fd, 1);
 3083 #endif
 3084 #if defined(FNAME_OPERLOG)
 3085         {
 3086             int logfile;
 3087                         
 3088             /*
 3089              * This conditional makes the logfile active only after it's
 3090              * been created - thus logging can be turned off by removing
 3091              * the file.
 3092              * 
 3093              * stop NFS hangs...most systems should be able to open a file in
 3094              * 3 seconds. -avalon (curtesy of wumpus)
 3095              */
 3096             alarm(3);
 3097             if (IsPerson(sptr) &&
 3098                 (logfile = open(FNAME_OPERLOG, O_WRONLY | O_APPEND)) != -1)
 3099             {
 3100                 alarm(0);
 3101                 ircsprintf(buf, "%s OPER (%s) (%s) by (%s!%s@%s)\n",
 3102                                   myctime(timeofday), name, encr,
 3103                                   parv[0], sptr->user->username,
 3104                                   sptr->sockhost);
 3105                 alarm(3);
 3106                 write(logfile, buf, strlen(buf));
 3107                 alarm(0);
 3108                 close(logfile);
 3109             }
 3110             alarm(0);
 3111             /* Modification by pjg */
 3112         }
 3113 #endif
 3114     }
 3115     else 
 3116     {
 3117         sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
 3118 #ifdef FAILED_OPER_NOTICE
 3119         sendto_ops_lev(ADMIN_LEV, "Failed OPER attempt by %s (%s@%s) [Bad Password for %s]",
 3120                        parv[0], sptr->user->username, sptr->sockhost, name);
 3121         sendto_realops("Failed OPER attempt by %s [Bad Password for %s]", parv[0], name);
 3122 #endif
 3123     }
 3124     return 0;
 3125 }
 3126 
 3127 /***************************************************************************
 3128  * m_pass() - Added Sat, 4 March 1989
 3129  ***************************************************************************/
 3130 /*
 3131  * m_pass 
 3132  * parv[0] = sender prefix 
 3133  * parv[1] = password
 3134  * parv[2] = optional extra version information
 3135  */
 3136 int 
 3137 m_pass(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3138 {
 3139     char *password = parc > 1 ? parv[1] : NULL;
 3140     
 3141     if (BadPtr(password))
 3142     {
 3143         sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PASS");
 3144         return 0;
 3145     }
 3146     if (!MyConnect(sptr) || (!IsUnknown(cptr) && !IsHandshake(cptr)))
 3147     {
 3148         sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
 3149         return 0;
 3150     }
 3151     strncpyzt(cptr->passwd, password, sizeof(cptr->passwd));
 3152     if (parc > 2)
 3153     {
 3154         int l = strlen(parv[2]);
 3155         
 3156         if (l < 2)
 3157             return 0;
 3158         if (parv[2][0] == 'T' && parv[2][1] == 'S')
 3159             cptr->tsinfo = (ts_val) TS_DOESTS;
 3160     }
 3161     return 0;
 3162 }
 3163 
 3164 /*
 3165  * m_userhost added by Darren Reed 13/8/91 to aid clients and reduce
 3166  * the need for complicated requests like WHOIS. It returns user/host
 3167  * information only (no spurious AWAY labels or channels).
 3168  */
 3169 int 
 3170 m_userhost(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3171 {
 3172     char *s, *p = NULL;
 3173     aClient *acptr;
 3174     int i, len, res = 0;
 3175     
 3176     ircsprintf(buf, rpl_str(RPL_USERHOST), me.name, parv[0]);
 3177     len = strlen(buf);
 3178 
 3179     for (i = 5, s = strtoken(&p, parv[1], " "); i && s;
 3180          s = strtoken(&p, (char *) NULL, " "), i--)
 3181         if ((acptr = find_person(s, NULL)))
 3182         {
 3183             if (++res > 1)
 3184                 buf[len++] = ' ';
 3185             len += ircsnprintf(buf + len, sizeof(buf) - (len + 1), 
 3186                                "%s%s=%c%s@%s", acptr->name,
 3187                               IsAnOper(acptr) ? "*" : "",
 3188                               (acptr->user->away) ? '-' : '+',
 3189                               acptr->user->username, 
 3190 #ifdef USER_HOSTMASKING
 3191                               (IsUmodeH(acptr) && sptr!=acptr && !IsAnOper(sptr))?acptr->user->mhost:
 3192 #endif
 3193                               acptr->user->host);
 3194         }
 3195     sendto_one(sptr, "%s", buf);
 3196     return 0;
 3197 }
 3198 
 3199 int 
 3200 m_userip(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3201 {
 3202     char *s, *p = NULL;
 3203     aClient *acptr;
 3204     int i, len, res = 0;
 3205 
 3206     if(!IsAnOper(sptr))
 3207     {
 3208         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
 3209         return 0;
 3210     }
 3211     ircsprintf(buf, rpl_str(RPL_USERHOST), me.name, parv[0]);
 3212     len = strlen(buf);
 3213 
 3214     for (i = 5, s = strtoken(&p, parv[1], " "); i && s;
 3215          s = strtoken(&p, (char *) NULL, " "), i--)
 3216         if ((acptr = find_person(s, NULL)))
 3217         {
 3218             if (++res > 1)
 3219                buf[len++] = ' ';
 3220             len += ircsnprintf(buf + len, sizeof(buf) - (len + 1), 
 3221                                "%s%s=%c%s@%s", acptr->name,
 3222                               IsAnOper(acptr) ? "*" : "",
 3223                               (acptr->user->away) ? '-' : '+',
 3224                               acptr->user->username,
 3225                               IsULine(acptr) ? "0.0.0.0" : acptr->hostip);
 3226         }
 3227     sendto_one(sptr, "%s", buf);
 3228     return 0;
 3229 }
 3230 
 3231 /*
 3232  * m_ison added by Darren Reed 13/8/91 to act as an efficent user
 3233  * indicator with respect to cpu/bandwidth used. Implemented for NOTIFY
 3234  * feature in clients. Designed to reduce number of whois requests. Can
 3235  * process nicknames in batches as long as the maximum buffer length.
 3236  * 
 3237  * format: ISON :nicklist
 3238  */
 3239 /* Take care of potential nasty buffer overflow problem -Dianora */
 3240 
 3241 int 
 3242 m_ison(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3243 {
 3244     aClient *acptr;
 3245     char   *s, **pav = parv;
 3246     char       *p = (char *) NULL;
 3247     size_t     len, len2;
 3248 
 3249     if (parc < 2) 
 3250     {
 3251         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "ISON");
 3252         return 0;
 3253     }
 3254 
 3255     ircsprintf(buf, rpl_str(RPL_ISON), me.name, *parv);
 3256     len = strlen(buf);
 3257     if (!IsOper(cptr))
 3258         cptr->priority += 20;   /* this keeps it from moving to 'busy' list  */
 3259     for (s = strtoken(&p, *++pav, " "); s;
 3260          s = strtoken(&p, (char *) NULL, " "))
 3261         if ((acptr = find_person(s, NULL))) 
 3262         {
 3263             len2 = strlen(acptr->name);
 3264             if ((len + len2 + 5) < sizeof(buf)) /* make sure can never */
 3265             {                                   /* overflow */
 3266                 strcat(buf, acptr->name);
 3267                 len += len2;
 3268                 strcat(buf, " ");
 3269                 len++;
 3270             }
 3271             else
 3272                 break;
 3273         }
 3274     sendto_one(sptr, "%s", buf);
 3275     return 0;
 3276 }
 3277 
 3278 /*
 3279  * m_umode() added 15/10/91 By Darren Reed.
 3280  * parv[0] - sender
 3281  * parv[1] - username to change mode for
 3282  * parv[2] - modes to change
 3283  */
 3284 int 
 3285 m_umode(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3286 {
 3287     int     flag, *s, setflags, what = MODE_ADD, badflag = NO;
 3288     char  **p, *m;
 3289     aClient    *acptr;
 3290     
 3291     if (parc < 2)
 3292     {
 3293         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
 3294         return 0;
 3295     }
 3296 
 3297     if(IsServer(sptr))
 3298         return 0;
 3299     
 3300     if (!(acptr = find_person(parv[1], NULL)))
 3301     {
 3302         if (MyConnect(sptr))
 3303             sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], 
 3304                        parv[1]);
 3305         return 0;
 3306     }
 3307 
 3308     if ((sptr != acptr) || (acptr->from != sptr->from))
 3309     {
 3310         sendto_one(sptr, err_str(ERR_USERSDONTMATCH), me.name, parv[0]);
 3311         return 0;
 3312     }
 3313     
 3314    
 3315     if (parc < 3)
 3316     {
 3317         m = buf;
 3318         *m++ = '+';
 3319         for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4); s += 2)
 3320         {
 3321             if (sptr->umode & (flag & ALL_UMODES))
 3322                 *m++ = (char) (*(s + 1));
 3323         }
 3324         *m = '\0';
 3325         sendto_one(sptr, rpl_str(RPL_UMODEIS), me.name, parv[0], buf);
 3326         return 0;
 3327     }
 3328         
 3329     /* find flags already set for user */
 3330     setflags = 0;
 3331     for (s = user_modes; (flag = *s); s += 2)
 3332         if (sptr->umode & flag)
 3333             setflags |= flag;
 3334     /* parse mode change string(s) */
 3335     for (p = &parv[2]; p && *p; p++)
 3336         for (m = *p; *m; m++)
 3337             switch (*m)
 3338             {
 3339                 case '+':
 3340                     what = MODE_ADD;
 3341                     break;
 3342                 case '-':
 3343                     what = MODE_DEL;
 3344                     break;
 3345                     /* we may not get these, but they shouldnt be in default */
 3346                 case ' ':
 3347                 case '\r':
 3348                 case '\n':
 3349                 case '\t':
 3350                     break;
 3351                 case 'r':
 3352                 case 'x':
 3353                 case 'X':
 3354                 case 'S':
 3355                     break; /* users can't set themselves +r,+x,+X or +S! */
 3356                 case 'H':
 3357                     if ((uhm_type > 0) && (uhm_umodeh > 0) && (what == MODE_ADD))
 3358                         sptr->umode |= UMODE_H;
 3359                     else
 3360                         sptr->umode &= ~UMODE_H;
 3361                     break;
 3362                 case 'A':
 3363                     /* set auto +a if user is setting +A */
 3364                     if (MyClient(sptr) && (what == MODE_ADD))
 3365                         sptr->umode |= UMODE_a;
 3366                 default:
 3367                     for (s = user_modes; (flag = *s); s += 2)
 3368                         if (*m == (char) (*(s + 1)))
 3369                         {
 3370                             if (what == MODE_ADD)
 3371                                 sptr->umode |= flag;
 3372                             else
 3373                                 sptr->umode &= ~flag;
 3374                             break;
 3375                         }
 3376                     if (flag == 0 && MyConnect(sptr))
 3377                         badflag = YES;
 3378                     break;
 3379             }
 3380     
 3381     if (badflag)
 3382         sendto_one(sptr, err_str(ERR_UMODEUNKNOWNFLAG), me.name, parv[0]);
 3383 
 3384     /* stop users making themselves operators too easily */
 3385     if (!(setflags & UMODE_o) && IsOper(sptr) && !IsServer(cptr))
 3386         ClearOper(sptr);
 3387         
 3388     if (!(setflags & UMODE_O) && IsLocOp(sptr) && !IsServer(cptr))
 3389         sptr->umode &= ~UMODE_O;
 3390         
 3391     if ((setflags & (UMODE_o | UMODE_O)) && !IsAnOper(sptr) && MyConnect(sptr))
 3392     {
 3393         set_effective_class(sptr);
 3394         sptr->oflag = 0;
 3395     }
 3396 
 3397     if (!(setflags & (UMODE_o | UMODE_O)) && IsAnOper(sptr))
 3398         Count.oper++;
 3399         
 3400     if ((setflags & (UMODE_o | UMODE_O)) && !IsAnOper(sptr))
 3401     {
 3402         Count.oper--;
 3403         if (MyConnect(sptr))
 3404         {
 3405             remove_from_list(&oper_list, sptr, NULL);
 3406 
 3407             /*
 3408              * Now that the user is no longer opered, let's return
 3409              * them back to the appropriate Y:class -srd
 3410              */
 3411             if(sptr->user->oper)
 3412             {
 3413                 sptr->user->oper->opers--;
 3414                 sptr->user->oper = NULL;
 3415                 set_effective_class(sptr);
 3416             }
 3417         }
 3418     }
 3419     
 3420     if (!(setflags & UMODE_i) && IsInvisible(sptr))
 3421         Count.invisi++;
 3422     if ((setflags & UMODE_i) && !IsInvisible(sptr))
 3423         Count.invisi--;
 3424     
 3425     /*
 3426      * compare new flags with old flags and send string which will cause
 3427      * servers to update correctly.
 3428      */
 3429     if (!IsAnOper(sptr) && !IsServer(cptr))
 3430     {
 3431         sptr->umode &= ~OPER_UMODES;
 3432 #ifdef NO_USER_SERVERKILLS
 3433         sptr->umode &= ~UMODE_k;
 3434 #endif
 3435 #ifdef NO_USER_OPERKILLS
 3436         sptr->umode &= ~UMODE_s;
 3437 #endif
 3438     }
 3439     if(MyClient(sptr))
 3440     {
 3441         if (IsAdmin(sptr) && !OPIsAdmin(sptr)) ClearAdmin(sptr);
 3442         if (IsSAdmin(sptr) && !OPIsSAdmin(sptr)) ClearSAdmin(sptr);
 3443         if (IsUmodef(sptr) && !OPCanUModef(sptr)) ClearUmodef(sptr);
 3444         if (IsUmodec(sptr) && !OPCanUModec(sptr)) ClearUmodec(sptr);
 3445         if (IsUmodej(sptr) && !OPCanUModec(sptr)) ClearUmodej(sptr);
 3446         if (IsUmodey(sptr) && !OPCanUModey(sptr)) ClearUmodey(sptr);
 3447         if (IsUmoded(sptr) && !OPCanUModed(sptr)) ClearUmoded(sptr);
 3448         if (IsUmodeb(sptr) && !OPCanUModeb(sptr)) ClearUmodeb(sptr);
 3449         if (NoMsgThrottle(sptr) && !OPCanUModeF(sptr)) ClearNoMsgThrottle(sptr);
 3450 #ifdef ALLOW_HIDDEN_OPERS
 3451 # ifdef FORCE_EVERYONE_HIDDEN
 3452         sptr->umode |= UMODE_I;
 3453 # else
 3454 #  if (RIDICULOUS_PARANOIA_LEVEL>=1)
 3455         if (IsUmodeI(sptr) && !(sptr->user->real_oper_host || IsAnOper(sptr))) 
 3456             ClearUmodeI(sptr);
 3457 #  endif
 3458 
 3459 #  ifdef FORCE_OPERS_HIDDEN
 3460         if (IsAnOper(sptr)
 3461 #   if (RIDICULOUS_PARANOIA_LEVEL>=1)
 3462             || (sptr->user->real_oper_host != NULL)
 3463 #   endif
 3464            ) sptr->umode |= UMODE_I;
 3465 #  endif /* FORCE_OPERS_HIDDEN */
 3466 # endif /* FORCE_EVERYONE_HIDDEN */
 3467 #else /* ALLOW_HIDDEN_OPERS */
 3468         if (IsUmodeI(sptr)) ClearUmodeI(sptr);
 3469 #endif
 3470         if (sptr->user->allow->flags & CONF_FLAGS_FORCEFLOOD)
 3471             SetNoMsgThrottle(sptr);
 3472     }
 3473     send_umode_out(cptr, sptr, setflags);
 3474     
 3475     return 0;
 3476 }
 3477 
 3478 /* send the MODE string for user (user) to connection cptr -avalon */
 3479 void 
 3480 send_umode(aClient *cptr, aClient *sptr, long old, long sendmask, char *umode_buf, int bufsize)
 3481 {
 3482     int *s, flag, what = MODE_NULL;
 3483     char *m;
 3484     int len;
 3485 
 3486     /*
 3487      * build a string in umode_buf to represent the change in the user's
 3488      * mode between the new (sptr->flag) and 'old'.
 3489      */
 3490     m = umode_buf;
 3491     *m = '\0';
 3492     len = 0;
 3493     bufsize--; /* To have enough space for the null termination char */
 3494     for (s = user_modes; (flag = *s); s += 2)
 3495     {
 3496         if (MyClient(sptr) && !(flag & sendmask))
 3497             continue;
 3498         if ((flag & old) && !(sptr->umode & flag))
 3499         {
 3500             if (what == MODE_DEL)
 3501             {
 3502                 if(len+1 > bufsize) break;
 3503                 *m++ = *(s + 1);
 3504                 len++;
 3505             }
 3506             else
 3507             {
 3508                 if(len+2 > bufsize) break;
 3509                 what = MODE_DEL;
 3510                 *m++ = '-';
 3511                 *m++ = *(s + 1);
 3512                 len += 2;
 3513             }
 3514         }
 3515         else if (!(flag & old) && (sptr->umode & flag))
 3516         {
 3517             if (what == MODE_ADD)
 3518             {
 3519                 if(len+1 > bufsize) break;
 3520                 *m++ = *(s + 1);
 3521                 len++;
 3522             }
 3523             else
 3524             {
 3525                 if(len+2 > bufsize) break;
 3526                 what = MODE_ADD;
 3527                 *m++ = '+';
 3528                 *m++ = *(s + 1);
 3529                 len += 2;
 3530             }
 3531         }
 3532     }
 3533     *m = '\0';
 3534     if (*umode_buf && cptr)
 3535         sendto_one(cptr, ":%s MODE %s :%s", sptr->name, sptr->name, umode_buf);
 3536 }
 3537 
 3538 /* Shadowfax's FLUD code */
 3539 #ifdef FLUD
 3540 void 
 3541 announce_fluder(aClient *fluder, aClient *cptr, aChannel *chptr, int type)
 3542 {                               
 3543     char *fludee;
 3544     
 3545     if (cptr)
 3546         fludee = cptr->name;
 3547     else
 3548         fludee = chptr->chname;
 3549     
 3550     if(call_hooks(CHOOK_FLOODWARN, fluder, chptr, 3, fludee, NULL) != FLUSH_BUFFER)
 3551         sendto_realops_lev(FLOOD_LEV, "Flooder %s [%s@%s] on %s target: %s",
 3552                            fluder->name, fluder->user->username, fluder->user->host,
 3553                            fluder->user->server, fludee);
 3554 }
 3555 
 3556 /*
 3557  * This is really just a "convenience" function.  I can only keep three
 3558  * or * four levels of pointer dereferencing straight in my head.  This
 3559  * remove * an entry in a fluders list.  Use this when working on a
 3560  * fludees list :)
 3561  */
 3562 struct fludbot *
 3563 remove_fluder_reference(struct fludbot **fluders, aClient *fluder)
 3564 {
 3565     struct fludbot *current, *prev, *next;
 3566     
 3567     prev = NULL;
 3568     current = *fluders;
 3569     while (current)
 3570     {
 3571         next = current->next;
 3572         if (current->fluder == fluder)
 3573         {
 3574             if (prev)
 3575                 prev->next = next;
 3576             else
 3577                 *fluders = next;
 3578             
 3579             BlockHeapFree(free_fludbots, current);
 3580         }
 3581         else
 3582             prev = current;
 3583         current = next;
 3584     }
 3585     return (*fluders);
 3586 }
 3587 
 3588 /* Another function to unravel my mind. */
 3589 Link *
 3590 remove_fludee_reference(Link **fludees, void *fludee)
 3591 {
 3592     Link *current, *prev, *next;
 3593 
 3594     prev = NULL;
 3595     current = *fludees;
 3596     while (current)
 3597     {
 3598         next = current->next;
 3599         if (current->value.cptr == (aClient *) fludee)
 3600         {
 3601             if (prev)
 3602                 prev->next = next;
 3603             else
 3604                 *fludees = next;
 3605 
 3606             BlockHeapFree(free_Links, current);
 3607         }
 3608         else
 3609             prev = current;
 3610         current = next;
 3611     }
 3612     return (*fludees);
 3613 }
 3614 
 3615 int 
 3616 check_for_fludblock(aClient *fluder, aClient *cptr, aChannel *chptr, int type)
 3617 {                               
 3618     time_t now;
 3619     int blocking;
 3620 
 3621     /* If it's disabled, we don't need to process all of this */
 3622     if ((confopts & FLAGS_HUB) || (flud_block == 0))
 3623         return 0;
 3624 
 3625     /* It's either got to be a client or a channel being fluded */
 3626     if ((cptr == NULL) && (chptr == NULL))
 3627         return 0;
 3628 
 3629     if (cptr && !MyFludConnect(cptr))
 3630     {
 3631         sendto_ops("check_for_fludblock() called for non-local client");
 3632         return 0;
 3633     }
 3634 
 3635     /* Are we blocking fluds at this moment? */
 3636     time(&now);
 3637     if (cptr)
 3638         blocking = (cptr->fludblock > (now - flud_block));
 3639     else
 3640         blocking = (chptr->fludblock > (now - flud_block));
 3641 
 3642     return (blocking);
 3643 }
 3644 
 3645 int 
 3646 check_for_flud(aClient *fluder, aClient *cptr, aChannel *chptr, int type)
 3647 {                               
 3648     time_t      now;
 3649     struct fludbot *current, *prev, *next;
 3650     int         blocking, count, found;
 3651     Link       *newfludee;
 3652     
 3653     /* If it's disabled, we don't need to process all of this */
 3654     if ((confopts & (FLAGS_HUB|FLAGS_SERVHUB)) || (flud_block == 0))
 3655         return 0;
 3656         
 3657     /* It's either got to be a client or a channel being fluded */
 3658     if ((cptr == NULL) && (chptr == NULL))
 3659         return 0;
 3660         
 3661     if (cptr && !MyFludConnect(cptr)) 
 3662     {
 3663         sendto_ops("check_for_flud() called for non-local client");
 3664         return 0;
 3665     }
 3666         
 3667     /* Are we blocking fluds at this moment? */
 3668     time(&now);
 3669     if (cptr)
 3670         blocking = (cptr->fludblock > (now - flud_block));
 3671     else
 3672         blocking = (chptr->fludblock > (now - flud_block));
 3673         
 3674     /* Collect the Garbage */
 3675     if (!blocking) 
 3676     {
 3677         if (cptr)
 3678             current = cptr->fluders;
 3679         else
 3680             current = chptr->fluders;
 3681         prev = NULL;
 3682         while (current) 
 3683         {
 3684             next = current->next;
 3685             if (current->last_msg < (now - flud_time))
 3686             {
 3687                 if (cptr)
 3688                     remove_fludee_reference(&current->fluder->fludees,
 3689                                             (void *) cptr);
 3690                 else
 3691                     remove_fludee_reference(&current->fluder->fludees,
 3692                                             (void *) chptr);
 3693                 if (prev)
 3694                     prev->next = current->next;
 3695                 else if (cptr)
 3696                     cptr->fluders = current->next;
 3697                 else
 3698                     chptr->fluders = current->next;
 3699                 BlockHeapFree(free_fludbots, current);
 3700             }
 3701             else
 3702                 prev = current;
 3703             current = next;
 3704         }
 3705     }
 3706     /*
 3707      * Find or create the structure for the fluder, and update the
 3708      * counter * and last_msg members.  Also make a running total count
 3709      */
 3710     if (cptr)
 3711         current = cptr->fluders;
 3712     else
 3713         current = chptr->fluders;
 3714     count = found = 0;
 3715     while (current) 
 3716     {
 3717         if (current->fluder == fluder)
 3718         {
 3719             current->last_msg = now;
 3720             current->count++;
 3721             found = 1;
 3722         }
 3723         if (current->first_msg < (now - flud_time))
 3724             count++;
 3725         else
 3726             count += current->count;
 3727         current = current->next;
 3728     }
 3729     if (!found) 
 3730     {
 3731         if ((current = BlockHeapALLOC(free_fludbots, struct fludbot)) != NULL) 
 3732         {
 3733             current->fluder = fluder;
 3734             current->count = 1;
 3735             current->first_msg = now;
 3736             current->last_msg = now;
 3737             if (cptr) 
 3738             {
 3739                 current->next = cptr->fluders;
 3740                 cptr->fluders = current;
 3741             }
 3742             else 
 3743             {
 3744                 current->next = chptr->fluders;
 3745                 chptr->fluders = current;
 3746             }
 3747                         
 3748             count++;
 3749                         
 3750             if ((newfludee = BlockHeapALLOC(free_Links, Link)) != NULL) 
 3751             {
 3752                 if (cptr) 
 3753                 {
 3754                     newfludee->flags = 0;
 3755                     newfludee->value.cptr = cptr;
 3756                 }
 3757                 else 
 3758                 {
 3759                     newfludee->flags = 1;
 3760                     newfludee->value.chptr = chptr;
 3761                 }
 3762                 newfludee->next = fluder->fludees;
 3763                 fluder->fludees = newfludee;
 3764             }
 3765             else
 3766                 outofmemory();
 3767             /*
 3768              * If we are already blocking now, we should go ahead * and
 3769              * announce the new arrival
 3770              */
 3771             if (blocking)
 3772                 announce_fluder(fluder, cptr, chptr, type);
 3773         }
 3774         else
 3775             outofmemory();
 3776     }
 3777     /*
 3778      * Okay, if we are not blocking, we need to decide if it's time to *
 3779      * begin doing so.  We already have a count of messages received in *
 3780      * the last flud_time seconds
 3781      */
 3782     if (!blocking && (count > flud_num)) 
 3783     {
 3784         blocking = 1;
 3785         ircstp->is_flud++;
 3786         /*
 3787          * if we are going to say anything to the fludee, now is the *
 3788          * time to mention it to them.
 3789          */
 3790         if (cptr)
 3791             sendto_one(cptr,
 3792                        ":%s NOTICE %s :*** Notice -- Server flood protection "
 3793                        "activated for %s", me.name, cptr->name, cptr->name);
 3794         else
 3795             sendto_channel_butserv(chptr, &me,
 3796                                    ":%s NOTICE %s :*** Notice -- Server "
 3797                                    "flood protection activated for %s",
 3798                                    me.name, chptr->chname, chptr->chname);
 3799         /*
 3800          * Here we should go back through the existing list of * fluders
 3801          * and announce that they were part of the game as * well.
 3802          */
 3803         if (cptr)
 3804             current = cptr->fluders;
 3805         else
 3806             current = chptr->fluders;
 3807         while (current) 
 3808         {
 3809             announce_fluder(current->fluder, cptr, chptr, type);
 3810             current = current->next;
 3811         }
 3812     }
 3813     /*
 3814      * update blocking timestamp, since we received a/another CTCP
 3815      * message
 3816      */
 3817     if (blocking) 
 3818     {
 3819         if (cptr)
 3820             cptr->fludblock = now;
 3821         else
 3822             chptr->fludblock = now;
 3823     }
 3824     return (blocking);
 3825 }
 3826 
 3827 void 
 3828 free_fluders(aClient *cptr, aChannel *chptr)
 3829 {
 3830     struct fludbot *fluders, *next;
 3831 
 3832     if ((cptr == NULL) && (chptr == NULL)) 
 3833     {
 3834         sendto_ops("free_fluders(NULL, NULL)");
 3835         return;
 3836     }
 3837 
 3838     if (cptr && !MyFludConnect(cptr))
 3839         return;
 3840 
 3841     if (cptr)
 3842         fluders = cptr->fluders;
 3843     else
 3844         fluders = chptr->fluders;
 3845 
 3846     while (fluders) 
 3847     {
 3848         next = fluders->next;
 3849 
 3850         if (cptr)
 3851             remove_fludee_reference(&fluders->fluder->fludees, (void *) cptr);
 3852         else
 3853             remove_fludee_reference(&fluders->fluder->fludees, (void *) chptr);
 3854 
 3855         BlockHeapFree(free_fludbots, fluders);
 3856         fluders = next;
 3857     }
 3858 }
 3859 
 3860 void 
 3861 free_fludees(aClient *badguy)
 3862 {
 3863     Link       *fludees, *next;
 3864 
 3865     if (badguy == NULL) 
 3866     {
 3867         sendto_ops("free_fludees(NULL)");
 3868         return;
 3869     }
 3870     fludees = badguy->fludees;
 3871     while (fludees) 
 3872     {
 3873         next = fludees->next;
 3874 
 3875         if (fludees->flags)
 3876             remove_fluder_reference(&fludees->value.chptr->fluders, badguy);
 3877         else 
 3878         {
 3879             if (!MyFludConnect(fludees->value.cptr))
 3880                 sendto_ops("free_fludees() encountered non-local client");
 3881             else
 3882                 remove_fluder_reference(&fludees->value.cptr->fluders, badguy);
 3883         }
 3884 
 3885         BlockHeapFree(free_Links, fludees);
 3886         fludees = next;
 3887     }
 3888 }
 3889 #endif /* FLUD */
 3890 
 3891 
 3892 int del_silence(aClient *sptr, char *mask) 
 3893 {
 3894     Link **lp, *tmp;
 3895     for (lp=&(sptr->user->silence);*lp;lp=&((*lp)->next))
 3896         if (mycmp(mask, (*lp)->value.cp)==0) 
 3897         {
 3898             tmp = *lp;
 3899             *lp = tmp->next;
 3900             MyFree(tmp->value.cp);
 3901             free_link(tmp);
 3902             return 0;
 3903         }
 3904     return 1;
 3905 }
 3906 
 3907 static int add_silence(aClient *sptr,char *mask) 
 3908 {
 3909     Link *lp;
 3910     int cnt=0, len=0;
 3911     for (lp=sptr->user->silence;lp;lp=lp->next) 
 3912     {
 3913         len += strlen(lp->value.cp);
 3914         if (MyClient(sptr)) 
 3915         {
 3916             if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES)) 
 3917             {
 3918                 sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name,
 3919                            sptr->name, mask);
 3920                 return -1;
 3921             } 
 3922             else
 3923             {
 3924                 if (!match(lp->value.cp, mask))
 3925                     return -1;
 3926             }
 3927         }
 3928         else if (!mycmp(lp->value.cp, mask))
 3929             return -1;
 3930     }
 3931     lp = make_link();
 3932     lp->next = sptr->user->silence;
 3933     lp->value.cp = (char *)MyMalloc(strlen(mask)+1);
 3934     strcpy(lp->value.cp, mask);
 3935     sptr->user->silence = lp;
 3936     return 0;
 3937 }
 3938 
 3939 /* m_silence
 3940  * parv[0] = sender prefix
 3941  * From local client:
 3942  * parv[1] = mask (NULL sends the list)
 3943  * From remote client:
 3944  * parv[1] = nick that must be silenced
 3945  * parv[2] = mask
 3946  */
 3947 int 
 3948 m_silence(aClient *cptr,aClient *sptr,int parc,char *parv[]) 
 3949 {
 3950     Link *lp;
 3951     aClient *acptr=NULL;
 3952     char c, *cp;
 3953 
 3954     if (MyClient(sptr)) 
 3955     {
 3956         acptr = sptr;
 3957         if (parc < 2 || *parv[1]=='\0' || (acptr = find_person(parv[1], NULL))) 
 3958         {
 3959             if (!(acptr->user)) 
 3960                 return 0;
 3961 
 3962             for (lp = acptr->user->silence; lp; lp = lp->next)
 3963                 sendto_one(sptr, rpl_str(RPL_SILELIST), me.name,
 3964                            sptr->name, acptr->name, lp->value.cp);
 3965 
 3966             sendto_one(sptr, rpl_str(RPL_ENDOFSILELIST), me.name, acptr->name);
 3967             return 0;
 3968         }
 3969         cp = parv[1];
 3970         c = *cp;
 3971         if (c=='-' || c=='+') 
 3972             cp++;
 3973         else if (!(strchr(cp, '@') || strchr(cp, '.') ||
 3974                    strchr(cp, '!') || strchr(cp, '*'))) 
 3975         {
 3976             sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0],
 3977                        parv[1]);
 3978             return 0;
 3979         }
 3980         else c = '+';
 3981         cp = pretty_mask(cp);
 3982         if ((c=='-' && !del_silence(sptr,cp)) ||
 3983             (c!='-' && !add_silence(sptr,cp))) 
 3984         {
 3985             sendto_prefix_one(sptr, sptr, ":%s SILENCE %c%s", parv[0], c, cp);
 3986             if (c=='-')
 3987                 sendto_serv_butone(NULL, ":%s SILENCE * -%s", sptr->name, cp);
 3988         }
 3989     }
 3990     else if (parc < 3 || *parv[2]=='\0') 
 3991     {
 3992         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
 3993                    "SILENCE");
 3994         return -1;
 3995     } 
 3996     else if ((c = *parv[2])=='-' || (acptr = find_person(parv[1], NULL))) 
 3997     {
 3998         if (c=='-') 
 3999         {
 4000             if (!del_silence(sptr,parv[2]+1))
 4001                 sendto_serv_butone(cptr, ":%s SILENCE %s :%s",
 4002                                    parv[0], parv[1], parv[2]);
 4003         }
 4004         else
 4005         {
 4006             add_silence(sptr,parv[2]);
 4007             if (!MyClient(acptr))
 4008                 sendto_one(acptr, ":%s SILENCE %s :%s",
 4009                            parv[0], parv[1], parv[2]);
 4010         } 
 4011     } 
 4012     else
 4013     {
 4014         sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
 4015         return 0;
 4016     }
 4017     return 0;
 4018 }
 4019 
 4020 static int 
 4021 add_dccallow(aClient *sptr, aClient *optr)
 4022 {
 4023     Link *lp;
 4024     int cnt = 0;
 4025 
 4026     for(lp = sptr->user->dccallow; lp; lp = lp->next)
 4027     {
 4028         if(lp->flags != DCC_LINK_ME)
 4029             continue;
 4030         if((++cnt >= MAXDCCALLOW) && !IsAnOper(sptr))
 4031         {
 4032             sendto_one(sptr, err_str(ERR_TOOMANYDCC), me.name, sptr->name,
 4033                        optr->name, MAXDCCALLOW);
 4034             return 0;
 4035         }
 4036         else if(lp->value.cptr == optr)
 4037             return 0;
 4038     }
 4039 
 4040     lp = make_link();
 4041     lp->value.cptr = optr;
 4042     lp->flags = DCC_LINK_ME;
 4043     lp->next = sptr->user->dccallow;
 4044     sptr->user->dccallow = lp;
 4045 
 4046     lp = make_link();
 4047     lp->value.cptr = sptr;
 4048     lp->flags = DCC_LINK_REMOTE;
 4049     lp->next = optr->user->dccallow;
 4050     optr->user->dccallow = lp;   
 4051 
 4052     sendto_one(sptr, rpl_str(RPL_DCCSTATUS), me.name, sptr->name, optr->name,
 4053                "added to");
 4054     return 0;
 4055 }
 4056 
 4057 int
 4058 del_dccallow(aClient *sptr, aClient *optr, int silent) 
 4059 {
 4060     Link **lpp, *lp;
 4061     int found = 0;
 4062 
 4063     for (lpp = &(sptr->user->dccallow); *lpp; lpp=&((*lpp)->next))
 4064     {
 4065         if((*lpp)->flags != DCC_LINK_ME)
 4066             continue;
 4067 
 4068         if((*lpp)->value.cptr == optr)
 4069         {
 4070             lp = *lpp;
 4071             *lpp = lp->next;
 4072             free_link(lp);
 4073             found++;
 4074             break;
 4075         }
 4076     }
 4077 
 4078     if(!found)
 4079     {
 4080         sendto_one(sptr, ":%s %d %s :%s is not in your DCC allow list",
 4081                    me.name, RPL_DCCINFO, sptr->name, optr->name);
 4082         return 0;
 4083     }
 4084 
 4085     for (found = 0, lpp = &(optr->user->dccallow); *lpp; lpp=&((*lpp)->next))
 4086     {
 4087         if((*lpp)->flags != DCC_LINK_REMOTE)
 4088             continue;
 4089 
 4090         if((*lpp)->value.cptr == sptr)
 4091         {
 4092             lp = *lpp;
 4093             *lpp = lp->next;
 4094             free_link(lp);
 4095             found++;
 4096             break;
 4097         }
 4098     }
 4099 
 4100     if(!found)
 4101         sendto_realops_lev(DEBUG_LEV, "%s was in dccallowme list of %s but "
 4102                            "not in dccallowrem list!", optr->name, sptr->name);
 4103 
 4104     if(!silent)
 4105         sendto_one(sptr, rpl_str(RPL_DCCSTATUS), me.name, sptr->name, optr->name,
 4106                    "removed from");
 4107     
 4108     return 0;
 4109 }
 4110 
 4111 int 
 4112 m_dccallow(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4113 {
 4114     Link *lp;
 4115     char *p, *s;
 4116     char *cn;
 4117     aClient *acptr, *lastcptr = NULL;
 4118     int didlist = 0, didhelp = 0, didanything = 0;
 4119     char **ptr;
 4120     static char *dcc_help[] = 
 4121         {
 4122             "/DCCALLOW [<+|->nick[,<+|->nick, ...]] [list] [help]",
 4123             "You may allow DCCs of filetypes which are otherwise blocked by "
 4124             "the IRC server",
 4125             "by specifying a DCC allow for the user you want to recieve files "
 4126             "from.",
 4127             "For instance, to allow the user bob to send you file.exe, you "
 4128             "would type:",
 4129             "/dccallow +bob",
 4130             "and bob would then be able to send you files. bob will have to "
 4131             "resend the file",
 4132             "if the server gave him an error message before you added him to "
 4133             "your allow list.",
 4134             "/dccallow -bob",
 4135             "Will do the exact opposite, removing him from your dcc allow "
 4136             "list.",
 4137             "/dccallow list",
 4138             "Will list the users currently on your dcc allow list.",
 4139             NULL 
 4140         };
 4141 
 4142     if(!MyClient(sptr)) 
 4143         return 0;
 4144     
 4145     if(parc < 2)
 4146     {
 4147         sendto_one(sptr, ":%s NOTICE %s :No command specified for DCCALLOW. "
 4148                    "Type /dccallow help for more information.", me.name,
 4149                    sptr->name);
 4150         return 0;
 4151     }
 4152 
 4153     for (p = NULL, s = strtoken(&p, parv[1], ", "); s;
 4154          s = strtoken(&p, NULL, ", "))
 4155     {
 4156         if(*s == '+')
 4157         {
 4158             didanything++;
 4159             cn = s + 1;
 4160             if(*cn == '\0')
 4161                 continue;
 4162 
 4163             acptr = find_person(cn, NULL);
 4164             
 4165             if(acptr == sptr) continue;
 4166             
 4167             if(!acptr)
 4168             {
 4169                 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
 4170                            sptr->name, cn);
 4171                 continue;
 4172             }
 4173 
 4174             if(lastcptr == acptr)
 4175                 sendto_realops_lev(SPY_LEV, "User %s (%s@%s) may be flooding "
 4176                                    "dccallow: add %s", sptr->name,
 4177                                    sptr->user->username, sptr->user->host,
 4178                                    acptr->name);
 4179             lastcptr = acptr;
 4180             add_dccallow(sptr, acptr);
 4181         }
 4182         else if(*s == '-')
 4183         {
 4184             didanything++;
 4185             cn = s + 1;
 4186             if(*cn == '\0')
 4187                 continue;
 4188 
 4189             acptr = find_person(cn, NULL);
 4190             if(acptr == sptr) 
 4191                 continue;
 4192 
 4193             if(!acptr)
 4194             {
 4195                 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, 
 4196                            sptr->name, cn);
 4197                 continue;
 4198             }
 4199 
 4200             if(lastcptr == acptr)
 4201                 sendto_realops_lev(SPY_LEV, "User %s (%s@%s) may be flooding "
 4202                                    "dccallow: del %s", sptr->name,
 4203                                    sptr->user->username, sptr->user->host,
 4204                                    acptr->name);
 4205             
 4206             lastcptr = acptr;
 4207             del_dccallow(sptr, acptr, 0);
 4208         }
 4209         else
 4210         {
 4211             if(!didlist && myncmp(s, "list", 4) == 0)
 4212             {
 4213                 didanything++;
 4214                 didlist++;
 4215                 sendto_one(sptr, ":%s %d %s :The following users are on your "
 4216                            "dcc allow list:", me.name, RPL_DCCINFO,
 4217                            sptr->name);
 4218                 for(lp = sptr->user->dccallow; lp; lp = lp->next)
 4219                 {
 4220                     if(lp->flags == DCC_LINK_REMOTE) 
 4221                         continue;
 4222                     sendto_one(sptr, ":%s %d %s :%s (%s@%s)", me.name,
 4223                                RPL_DCCLIST, sptr->name, lp->value.cptr->name,
 4224                                lp->value.cptr->user->username,
 4225 #ifdef USER_HOSTMASKING
 4226                                IsUmodeH(lp->value.cptr)?lp->value.cptr->user->mhost:
 4227 #endif
 4228                                lp->value.cptr->user->host);
 4229                 }
 4230                 sendto_one(sptr, rpl_str(RPL_ENDOFDCCLIST), me.name,
 4231                            sptr->name, s);
 4232             }
 4233             else if(!didhelp && myncmp(s, "help", 4) == 0)
 4234             {
 4235                 didanything++;
 4236                 didhelp++;
 4237                 for(ptr = dcc_help; *ptr; ptr++)
 4238                     sendto_one(sptr, ":%s %d %s :%s", me.name, RPL_DCCINFO,
 4239                                sptr->name, *ptr);
 4240                 sendto_one(sptr, rpl_str(RPL_ENDOFDCCLIST), me.name,
 4241                            sptr->name, s);
 4242             }
 4243         }
 4244     }
 4245 
 4246     if(!didanything)
 4247     {
 4248         sendto_one(sptr, ":%s NOTICE %s :Invalid syntax for DCCALLOW. Type "
 4249                    "/dccallow help for more information.", me.name,
 4250                    sptr->name);
 4251         return 0;
 4252     }
 4253     
 4254     return 0;
 4255 }
 4256 
 4257 int
 4258 m_put(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4259 {
 4260     /* HTTP PUT proxy */
 4261     if (!IsRegistered(cptr) && cptr->receiveM == 1)
 4262         return reject_proxy(cptr, "PUT", parv[1]);
 4263 
 4264     return 0;
 4265 }
 4266 
 4267 int
 4268 m_post(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4269 {
 4270     /* HTTP POST proxy */
 4271     if (!IsRegistered(cptr) && cptr->receiveM == 1)
 4272         return reject_proxy(cptr, "POST", parv[1]);
 4273 
 4274     return 0;
 4275 }
 4276 
 4277 u_long
 4278 memcount_s_user(MCs_user *mc)
 4279 {
 4280     aClient *acptr;
 4281     Link *lp;
 4282 #ifdef FLUD
 4283     struct fludbot *fb;
 4284 #endif
 4285 
 4286     mc->file = __FILE__;
 4287 
 4288     for (acptr = client; acptr; acptr = acptr->next)
 4289     {
 4290         if (!IsMe(acptr))   /* me is static */
 4291         {
 4292             if (acptr->from == acptr)
 4293                 mc->e_local_clients++;
 4294             else
 4295                 mc->e_remote_clients++;
 4296         }
 4297 
 4298         if (acptr->user)
 4299         {
 4300             mc->e_users++;
 4301 
 4302             if (acptr->user->away)
 4303             {
 4304                 mc->aways.c++;
 4305                 mc->aways.m += strlen(acptr->user->away) + 1;
 4306             }
 4307             for (lp = acptr->user->silence; lp; lp = lp->next)
 4308             {
 4309                 mc->silences.c++;
 4310                 mc->silences.m += strlen(lp->value.cp) + 1;
 4311                 mc->e_silence_links++;
 4312             }
 4313             mc->e_channel_links += mc_links(acptr->user->channel);
 4314             mc->e_invite_links += mc_links(acptr->user->invited);
 4315             mc->e_dccallow_links += mc_links(acptr->user->dccallow);
 4316 
 4317 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 4318             if (acptr->user->real_oper_host)
 4319             {
 4320                 mc->opermasks.c++;
 4321                 mc->opermasks.m += strlen(acptr->user->real_oper_host) + 1;
 4322                 mc->opermasks.m += strlen(acptr->user->real_oper_username) + 1;
 4323                 mc->opermasks.m += strlen(acptr->user->real_oper_ip) + 1;
 4324             }
 4325 #endif
 4326         }
 4327 
 4328         if (acptr->serv)
 4329         {
 4330             mc->servers.c++;
 4331             mc->servers.m += sizeof(aServer);
 4332 
 4333 #ifdef HAVE_ENCRYPTION_ON
 4334             if (acptr->serv->rc4_in)
 4335                 mc->e_rc4states++;
 4336             if (acptr->serv->rc4_out)
 4337                 mc->e_rc4states++;
 4338 #endif
 4339             if (acptr->serv->zip_in)
 4340                 mc->e_zipin_sessions++;
 4341             if (acptr->serv->zip_out)
 4342                 mc->e_zipout_sessions++;
 4343         }
 4344 
 4345         mc->e_watch_links += mc_links(acptr->watch);
 4346 
 4347 #ifdef FLUD
 4348         mc->e_flud_links += mc_links(acptr->fludees);
 4349 
 4350         if (acptr->from == acptr)   /* local client */
 4351             for (fb = acptr->fluders; fb; fb = fb->next)
 4352                 mc->e_fludbots++;
 4353 #endif
 4354     }
 4355 
 4356     mc->total.c = mc->aways.c + mc->silences.c + mc->servers.c;
 4357     mc->total.m = mc->aways.m + mc->silences.m + mc->servers.m;
 4358 #if (RIDICULOUS_PARANOIA_LEVEL>=1)
 4359     mc->total.c += mc->opermasks.c;
 4360     mc->total.m += mc->opermasks.m;
 4361 #endif
 4362 
 4363     return mc->total.m;
 4364 }
 4365