Initial import
[ratbox-ambernet.git] / src / s_user.c.orig
blob75b32950fdfcc51010f48f631fb84b6176e79bb7
1 /*
2  *  ircd-ratbox: A slightly useful ircd.
3  *  s_user.c: User related functions.
4  *
5  *  Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6  *  Copyright (C) 1996-2002 Hybrid Development Team
7  *  Copyright (C) 2002-2005 ircd-ratbox development team
8  *
9  *  This program is free software; 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 2 of the License, or
12  *  (at your option) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
22  *  USA
23  *
24  *  $Id: s_user.c 23955 2007-05-14 17:22:36Z leeh $
25  */
27 #include "stdinc.h"
28 #include "tools.h"
29 #include "s_user.h"
30 #include "channel.h"
31 #include "class.h"
32 #include "client.h"
33 #include "common.h"
34 #include "hash.h"
35 #include "irc_string.h"
36 #include "sprintf_irc.h"
37 #include "ircd.h"
38 #include "listener.h"
39 #include "msg.h"
40 #include "numeric.h"
41 #include "commio.h"
42 #include "s_conf.h"
43 #include "s_newconf.h"
44 #include "s_log.h"
45 #include "s_serv.h"
46 #include "s_stats.h"
47 #include "scache.h"
48 #include "send.h"
49 #include "supported.h"
50 #include "whowas.h"
51 #include "memory.h"
52 #include "packet.h"
53 #include "reject.h"
54 #include "cache.h"
55 #include "hook.h"
56 #include "monitor.h"
58 static void report_and_set_user_flags(struct Client *, struct ConfItem *);
59 void user_welcome(struct Client *source_p);
61 extern char *crypt();
63 /* table of ascii char letters to corresponding bitmask */
65 struct flag_item
67         int mode;
68         char letter;
71 /* *INDENT-OFF* */
72 static struct flag_item user_modes[] = {
73         {UMODE_ADMIN,           'a'},
74         {UMODE_BOTS,            'b'},
75         {UMODE_CCONN,           'c'},
76         {UMODE_CCONNEXT,        'C'},
77         {UMODE_DEBUG,           'd'},
78         {UMODE_DEAF,            'D'},
79         {UMODE_FULL,            'f'},
80         {UMODE_CALLERID,        'g'},
81         {UMODE_INVISIBLE,       'i'},
82         {UMODE_SKILL,           'k'},
83         {UMODE_LOCOPS,          'l'},
84         {UMODE_NCHANGE,         'n'},
85         {UMODE_OPER,            'o'},
86         {UMODE_REJ,             'r'},
87         {UMODE_SERVNOTICE,      's'},
88 #ifdef ENABLE_SERVICES
89         {UMODE_SERVICE,         'S'},
90 #endif
91         {UMODE_UNAUTH,          'u'},
92         {UMODE_WALLOP,          'w'},
93         {UMODE_EXTERNAL,        'x'},
94         {UMODE_SPY,             'y'},
95         {UMODE_OPERWALL,        'z'},
96         {UMODE_OPERSPY,         'Z'},
97         {0, 0}
100 /* memory is cheap. map 0-255 to equivalent mode */
101 int user_modes_from_c_to_bitmask[] = {
102         /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0F */
103         /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1F */
104         /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2F */
105         /* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3F */
106         0,                      /* @ */
107         0,                      /* A */
108         0,                      /* B */
109         UMODE_CCONNEXT,         /* C */
110         UMODE_DEAF,             /* D */
111         0,                      /* E */
112         0,                      /* F */
113         0,                      /* G */
114         0,                      /* H */
115         0,                      /* I */
116         0,                      /* J */
117         0,                      /* K */
118         0,                      /* L */
119         0,                      /* M */
120         0,                      /* N */
121         0,                      /* O */
122         0,                      /* P */
123         0,                      /* Q */
124         0,                      /* R */
125 #ifdef ENABLE_SERVICES
126         UMODE_SERVICE,          /* S */
127 #else
128         0,                      /* S */
129 #endif
130         0,                      /* T */
131         0,                      /* U */
132         0,                      /* V */
133         0,                      /* W */
134         0,                      /* X */
135         0,                      /* Y */
136         UMODE_OPERSPY,          /* Z */
137         /* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */
138         UMODE_ADMIN,            /* a */
139         UMODE_BOTS,             /* b */
140         UMODE_CCONN,            /* c */
141         UMODE_DEBUG,            /* d */
142         0,                      /* e */
143         UMODE_FULL,             /* f */
144         UMODE_CALLERID,         /* g */
145         0,                      /* h */
146         UMODE_INVISIBLE,        /* i */
147         0,                      /* j */
148         UMODE_SKILL,            /* k */
149         UMODE_LOCOPS,           /* l */
150         0,                      /* m */
151         UMODE_NCHANGE,          /* n */
152         UMODE_OPER,             /* o */
153         0,                      /* p */
154         0,                      /* q */
155         UMODE_REJ,              /* r */
156         UMODE_SERVNOTICE,       /* s */
157         0,                      /* t */
158         UMODE_UNAUTH,           /* u */
159         0,                      /* v */
160         UMODE_WALLOP,           /* w */
161         UMODE_EXTERNAL,         /* x */
162         UMODE_SPY,              /* y */
163         UMODE_OPERWALL,         /* z */
164         /* 0x7B */ 0, 0, 0, 0, 0, /* 0x7F */
165         /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9F */
166         /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9F */
167         /* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xAF */
168         /* 0xB0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xBF */
169         /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCF */
170         /* 0xD0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xDF */
171         /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xEF */
172         /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xFF */
174 /* *INDENT-ON* */
177  * show_lusers -
179  * inputs       - pointer to client
180  * output       -
181  * side effects - display to client user counts etc.
182  */
184 show_lusers(struct Client *source_p)
186         sendto_one_numeric(source_p, RPL_LUSERCLIENT, form_str(RPL_LUSERCLIENT),
187                            (Count.total - Count.invisi),
188                            Count.invisi, dlink_list_length(&global_serv_list));
190         if(Count.oper > 0)
191                 sendto_one_numeric(source_p, RPL_LUSEROP, 
192                                    form_str(RPL_LUSEROP), Count.oper);
194         if(dlink_list_length(&unknown_list) > 0)
195                 sendto_one_numeric(source_p, RPL_LUSERUNKNOWN, 
196                                    form_str(RPL_LUSERUNKNOWN),
197                                    dlink_list_length(&unknown_list));
199         if(dlink_list_length(&global_channel_list) > 0)
200                 sendto_one_numeric(source_p, RPL_LUSERCHANNELS, 
201                                    form_str(RPL_LUSERCHANNELS),
202                                    dlink_list_length(&global_channel_list));
204         sendto_one_numeric(source_p, RPL_LUSERME, form_str(RPL_LUSERME),
205                            dlink_list_length(&lclient_list),
206                            dlink_list_length(&serv_list));
208         sendto_one_numeric(source_p, RPL_LOCALUSERS, 
209                            form_str(RPL_LOCALUSERS),
210                            dlink_list_length(&lclient_list),
211                            Count.max_loc,
212                            dlink_list_length(&lclient_list),
213                            Count.max_loc);
215         sendto_one_numeric(source_p, RPL_GLOBALUSERS, form_str(RPL_GLOBALUSERS),
216                            Count.total, Count.max_tot,
217                            Count.total, Count.max_tot);
219         sendto_one_numeric(source_p, RPL_STATSCONN,
220                            form_str(RPL_STATSCONN),
221                            MaxConnectionCount, MaxClientCount, 
222                            Count.totalrestartcount);
224         if(dlink_list_length(&lclient_list) > (unsigned long)MaxClientCount)
225                 MaxClientCount = dlink_list_length(&lclient_list);
227         if((dlink_list_length(&lclient_list) + dlink_list_length(&serv_list)) >
228            (unsigned long)MaxConnectionCount)
229                 MaxConnectionCount = dlink_list_length(&lclient_list) + 
230                                         dlink_list_length(&serv_list);
232         return 0;
236  * show_isupport
238  * inputs       - pointer to client
239  * output       - 
240  * side effects - display to client what we support (for them)
241  */
242 void
243 show_isupport(struct Client *source_p)
245         char isupportbuffer[512];
247         ircsprintf(isupportbuffer, FEATURES, FEATURESVALUES);
248         sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
250         ircsprintf(isupportbuffer, FEATURES2, FEATURES2VALUES);
251         sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
253         ircsprintf(isupportbuffer, FEATURES3, FEATURES3VALUES);
254         sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
256         return;
261 ** register_local_user
262 **      This function is called when both NICK and USER messages
263 **      have been accepted for the client, in whatever order. Only
264 **      after this, is the USER message propagated.
266 **      NICK's must be propagated at once when received, although
267 **      it would be better to delay them too until full info is
268 **      available. Doing it is not so simple though, would have
269 **      to implement the following:
271 **      (actually it has been implemented already for a while) -orabidoo
273 **      1) user telnets in and gives only "NICK foobar" and waits
274 **      2) another user far away logs in normally with the nick
275 **         "foobar" (quite legal, as this server didn't propagate
276 **         it).
277 **      3) now this server gets nick "foobar" from outside, but
278 **         has alread the same defined locally. Current server
279 **         would just issue "KILL foobar" to clean out dups. But,
280 **         this is not fair. It should actually request another
281 **         nick from local user or kill him/her...
285 register_local_user(struct Client *client_p, struct Client *source_p, const char *username)
287         struct ConfItem *aconf;
288         struct User *user = source_p->user;
289         char tmpstr2[IRCD_BUFSIZE];
290         char ipaddr[HOSTIPLEN];
291         char myusername[USERLEN+1];
292         int status;
294         s_assert(NULL != source_p);
295         s_assert(MyConnect(source_p));
296         s_assert(source_p->username != username);
298         if(source_p == NULL)
299                 return -1;
301         if(IsAnyDead(source_p))
302                 return -1;
304         if(ConfigFileEntry.ping_cookie)
305         {
306                 if(!(source_p->flags & FLAGS_PINGSENT) && source_p->localClient->random_ping == 0)
307                 {
308                         source_p->localClient->random_ping = (unsigned long) (rand() * rand()) << 1;
309                         sendto_one(source_p, "PING :%08lX",
310                                    (unsigned long) source_p->localClient->random_ping);
311                         source_p->flags |= FLAGS_PINGSENT;
312                         return -1;
313                 }
314                 if(!(source_p->flags2 & FLAGS2_PING_COOKIE))
315                 {
316                         return -1;
317                 }
318         }
320         /* hasnt finished client cap negotiation */
321         if(source_p->flags2 & FLAGS2_CLICAP)
322                 return -1;
324         client_p->localClient->last = CurrentTime;
325         /* Straight up the maximum rate of flooding... */
326         source_p->localClient->allow_read = MAX_FLOOD_BURST;
328         /* XXX - fixme. we shouldnt have to build a users buffer twice.. */
329         if(!IsGotId(source_p) && (strchr(username, '[') != NULL))
330         {
331                 const char *p;
332                 int i = 0;
334                 p = username;
336                 while(*p && i < USERLEN)
337                 {
338                         if(*p != '[')
339                                 myusername[i++] = *p;
340                         p++;
341                 }
343                 myusername[i] = '\0';
344                 username = myusername;
345         }
347         if((status = check_client(client_p, source_p, username)) < 0)
348                 return (CLIENT_EXITED);
350         if(!valid_hostname(source_p->host))
351         {
352                 sendto_one(source_p,
353                            ":%s NOTICE %s :*** Notice -- You have an illegal character in your hostname",
354                            me.name, source_p->name);
356                 strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));
358 #ifdef IPV6
359                 if(ConfigFileEntry.dot_in_ip6_addr == 1)
360                         strlcat(source_p->host, ".", sizeof(source_p->host));
361 #endif
362         }
365         aconf = source_p->localClient->att_conf;
367         if(aconf == NULL)
368         {
369                 exit_client(client_p, source_p, &me, "*** Not Authorised");
370                 return (CLIENT_EXITED);
371         }
373         if(!IsGotId(source_p))
374         {
375                 const char *p;
376                 int i = 0;
378                 if(IsNeedIdentd(aconf))
379                 {
380                         ServerStats->is_ref++;
381                         sendto_one(source_p,
382                                    ":%s NOTICE %s :*** Notice -- You need to install identd to use this server",
383                                    me.name, client_p->name);
384                         exit_client(client_p, source_p, &me, "Install identd");
385                         return (CLIENT_EXITED);
386                 }
388                 /* dont replace username if its supposed to be spoofed --fl */
389                 if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->name, '@'))
390                 {
391                         p = username;
393                         if(!IsNoTilde(aconf))
394                                 source_p->username[i++] = '~';
396                         while (*p && i < USERLEN)
397                         {
398                                 if(*p != '[')
399                                         source_p->username[i++] = *p;
400                                 p++;
401                         }
403                         source_p->username[i] = '\0';
404                 }
405         }
407         /* password check */
408         if(!EmptyString(aconf->passwd))
409         {
410                 const char *encr;
412                 if(EmptyString(source_p->localClient->passwd))
413                         encr = "";
414                 else if(IsConfEncrypted(aconf))
415                         encr = crypt(source_p->localClient->passwd, aconf->passwd);
416                 else
417                         encr = source_p->localClient->passwd;
419                 if(strcmp(encr, aconf->passwd))
420                 {
421                         ServerStats->is_ref++;
422                         sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
423                         exit_client(client_p, source_p, &me, "Bad Password");
424                         return (CLIENT_EXITED);
425                 }
426         }
428         if(source_p->localClient->passwd)
429         {
430                 memset(source_p->localClient->passwd, 0, strlen(source_p->localClient->passwd));
431                 MyFree(source_p->localClient->passwd);
432                 source_p->localClient->passwd = NULL;
433         }
435         /* report if user has &^>= etc. and set flags as needed in source_p */
436         report_and_set_user_flags(source_p, aconf);
438         /* Limit clients */
439         /*
440          * We want to be able to have servers and F-line clients
441          * connect, so save room for "buffer" connections.
442          * Smaller servers may want to decrease this, and it should
443          * probably be just a percentage of the MAXCLIENTS...
444          *   -Taner
445          */
446         /* Except "F:" clients */
447         if(((dlink_list_length(&lclient_list) + 1) >= 
448            ((unsigned long)GlobalSetOptions.maxclients + MAX_BUFFER) ||
449            (dlink_list_length(&lclient_list) + 1) >= 
450             ((unsigned long)GlobalSetOptions.maxclients - 5)) && !(IsExemptLimits(source_p)))
451         {
452                 sendto_realops_flags(UMODE_FULL, L_ALL,
453                                      "Too many clients, rejecting %s[%s].", source_p->name, source_p->host);
455                 ServerStats->is_ref++;
456                 exit_client(client_p, source_p, &me, "Sorry, server is full - try later");
457                 return (CLIENT_EXITED);
458         }
460         /* valid user name check */
462         if(!valid_username(source_p->username))
463         {
464                 sendto_realops_flags(UMODE_REJ, L_ALL,
465                                      "Invalid username: %s (%s@%s)",
466                                      source_p->name, source_p->username, source_p->host);
467                 ServerStats->is_ref++;
468                 ircsprintf(tmpstr2, "Invalid username [%s]", source_p->username);
469                 exit_client(client_p, source_p, &me, tmpstr2);
470                 return (CLIENT_EXITED);
471         }
473         /* end of valid user name check */
475         /* kline exemption extends to xline too */
476         if(!IsExemptKline(source_p) &&
477            find_xline(source_p->info, 1) != NULL)
478         {
479                 ServerStats->is_ref++;
480                 add_reject(source_p);
481                 exit_client(client_p, source_p, &me, "Bad user info");
482                 return CLIENT_EXITED;
483         }
485         if(IsAnyDead(client_p))
486                 return CLIENT_EXITED;
488         inetntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr));
490         sendto_realops_flags(UMODE_CCONN, L_ALL,
491                              "Client connecting: %s (%s@%s) [%s] {%s} [%s]",
492                              source_p->name, source_p->username, source_p->host,
493                              show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
494                              get_client_class(source_p), source_p->info);
496         sendto_realops_flags(UMODE_CCONNEXT, L_ALL,
497                         "CLICONN %s %s %s %s %s %s 0 %s",
498                         source_p->name, source_p->username, source_p->host,
499                         show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
500                         get_client_class(source_p),
501                         /* mirc can sometimes send ips here */
502                         show_ip(NULL, source_p) ? source_p->localClient->fullcaps : 
503                          "<hidden> <hidden>", 
504                         source_p->info);
506         /* If they have died in send_* don't do anything. */
507         if(IsAnyDead(source_p))
508                 return CLIENT_EXITED;
510         add_to_hostname_hash(source_p->host, source_p);
512         strcpy(source_p->id, generate_uid());
513         add_to_id_hash(source_p->id, source_p);
515         if(ConfigFileEntry.default_invisible)
516         {
517                 source_p->umodes |= UMODE_INVISIBLE;
518                 Count.invisi++;
519         }
521         s_assert(!IsClient(source_p));
522         del_unknown_ip(source_p);
523         dlinkMoveNode(&source_p->localClient->tnode, &unknown_list, &lclient_list);
524         SetClient(source_p);
526         /* XXX source_p->servptr is &me, since local client */
527         /* NO SHIT!^*($^, so lets not use the below. --fl */
528         /* source_p->servptr = find_server(NULL, user->server); */
529         source_p->servptr = &me;
531         dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users);
532         /* Increment our total user count here */
533         if(++Count.total > Count.max_tot)
534                 Count.max_tot = Count.total;
535         source_p->localClient->allow_read = MAX_FLOOD_BURST;
537         Count.totalrestartcount++;
539         s_assert(source_p->localClient != NULL);
541         if(dlink_list_length(&lclient_list) > (unsigned long)Count.max_loc)
542         {
543                 Count.max_loc = dlink_list_length(&lclient_list);
544                 if(!(Count.max_loc % 10))
545                         sendto_realops_flags(UMODE_ALL, L_ALL,
546                                              "New Max Local Clients: %d", Count.max_loc);
547         }
549         /* they get a reduced limit */
550         if(find_tgchange(source_p->sockhost))
551                 USED_TARGETS(source_p) = 6;
553         monitor_signon(source_p);
554         user_welcome(source_p);
555         return (introduce_client(client_p, source_p, user, source_p->name));
559  * introduce_clients
561  * inputs       -
562  * output       -
563  * side effects - This common function introduces a client to the rest
564  *                of the net, either from a local client connect or
565  *                from a remote connect.
566  */
568 introduce_client(struct Client *client_p, struct Client *source_p, struct User *user, const char *nick)
570         static char ubuf[12];
572         if(MyClient(source_p))
573                 send_umode(source_p, source_p, 0, SEND_UMODES, ubuf);
574         else
575                 send_umode(NULL, source_p, 0, SEND_UMODES, ubuf);
577         if(!*ubuf)
578         {
579                 ubuf[0] = '+';
580                 ubuf[1] = '\0';
581         }
583         /* if it has an ID, introduce it with its id to TS6 servers,
584          * otherwise introduce it normally to all.
585          */
586         if(has_id(source_p))
587         {
588                 char sockhost[HOSTLEN];
589                 if(source_p->sockhost[0] == ':')
590                 {
591                         sockhost[0] = '0';
592                         sockhost[1] = '\0';
593                         strlcat(sockhost, source_p->sockhost, sizeof(sockhost));
594                 } else
595                         strcpy(sockhost, source_p->sockhost);
596                 
597                 sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
598                               ":%s UID %s %d %ld %s %s %s %s %s :%s",
599                               source_p->servptr->id, nick,
600                               source_p->hopcount + 1,
601                               (long) source_p->tsinfo, ubuf,
602                               source_p->username, source_p->host,
603                               IsIPSpoof(source_p) ? "0" : sockhost,
604                               source_p->id, source_p->info);
606                 sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
607                               "NICK %s %d %ld %s %s %s %s :%s",
608                               nick, source_p->hopcount + 1,
609                               (long) source_p->tsinfo,
610                               ubuf, source_p->username, source_p->host,
611                               source_p->servptr->name, source_p->info);
612         }
613         else
614                 sendto_server(client_p, NULL, NOCAPS, NOCAPS,
615                               "NICK %s %d %ld %s %s %s %s :%s",
616                               nick, source_p->hopcount + 1,
617                               (long) source_p->tsinfo,
618                               ubuf, source_p->username, source_p->host,
619                               source_p->servptr->name, source_p->info);
622         return 0;
625 /* 
626  * valid_hostname - check hostname for validity
628  * Inputs       - pointer to user
629  * Output       - YES if valid, NO if not
630  * Side effects - NONE
632  * NOTE: this doesn't allow a hostname to begin with a dot and
633  * will not allow more dots than chars.
634  */
636 valid_hostname(const char *hostname)
638         const char *p = hostname;
639         int found_sep = 0;
641         s_assert(NULL != p);
643         if(hostname == NULL)
644                 return NO;
646         if('.' == *p || ':' == *p)
647                 return NO;
649         while (*p)
650         {
651                 if(!IsHostChar(*p))
652                         return NO;
653                 if(*p == '.' || *p == ':')
654                         found_sep++;
655                 p++;
656         }
658         if(found_sep == 0)
659                 return(NO);
661         return (YES);
664 /* 
665  * valid_username - check username for validity
667  * Inputs       - pointer to user
668  * Output       - YES if valid, NO if not
669  * Side effects - NONE
670  * 
671  * Absolutely always reject any '*' '!' '?' '@' in an user name
672  * reject any odd control characters names.
673  * Allow '.' in username to allow for "first.last"
674  * style of username
675  */
677 valid_username(const char *username)
679         int dots = 0;
680         const char *p = username;
682         s_assert(NULL != p);
684         if(username == NULL)
685                 return NO;
687         if('~' == *p)
688                 ++p;
690         /* reject usernames that don't start with an alphanum
691          * i.e. reject jokers who have '-@somehost' or '.@somehost'
692          * or "-hi-@somehost", "h-----@somehost" would still be accepted.
693          */
694         if(!IsAlNum(*p))
695                 return NO;
697         while (*++p)
698         {
699                 if((*p == '.') && ConfigFileEntry.dots_in_ident)
700                 {
701                         dots++;
702                         if(dots > ConfigFileEntry.dots_in_ident)
703                                 return NO;
704                         if(!IsUserChar(p[1]))
705                                 return NO;
706                 }
707                 else if(!IsUserChar(*p))
708                         return NO;
709         }
710         return YES;
713 /* report_and_set_user_flags
715  * Inputs       - pointer to source_p
716  *              - pointer to aconf for this user
717  * Output       - NONE
718  * Side effects -
719  * Report to user any special flags they are getting, and set them.
720  */
722 static void
723 report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf)
725         /* If this user is being spoofed, tell them so */
726         if(IsConfDoSpoofIp(aconf))
727         {
728                 sendto_one(source_p,
729                            ":%s NOTICE %s :*** Spoofing your IP. congrats.",
730                            me.name, source_p->name);
731         }
733         /* If this user is in the exception class, Set it "E lined" */
734         if(IsConfExemptKline(aconf))
735         {
736                 SetExemptKline(source_p);
737                 sendto_one(source_p,
738                            ":%s NOTICE %s :*** You are exempt from K/D/G/X lines. congrats.",
739                            me.name, source_p->name);
740         }
742         if(IsConfExemptGline(aconf))
743         {
744                 SetExemptGline(source_p);
746                 /* dont send both a kline and gline exempt notice */
747                 if(!IsConfExemptKline(aconf))
748                         sendto_one(source_p,
749                                    ":%s NOTICE %s :*** You are exempt from G lines.",
750                                    me.name, source_p->name);
751         }
753         /* If this user is exempt from user limits set it F lined" */
754         if(IsConfExemptLimits(aconf))
755         {
756                 SetExemptLimits(source_p);
757                 sendto_one(source_p,
758                            ":%s NOTICE %s :*** You are exempt from user limits. congrats.",
759                            me.name, source_p->name);
760         }
762         if(IsConfExemptFlood(aconf))
763         {
764                 SetExemptFlood(source_p);
765                 sendto_one(source_p,
766                            ":%s NOTICE %s :*** You are exempt from flood limits.",
767                            me.name, source_p->name);
768         }
770         if(IsConfExemptSpambot(aconf))
771         {
772                 SetExemptSpambot(source_p);
773                 sendto_one(source_p,
774                            ":%s NOTICE %s :*** You are exempt from spambot checks.",
775                            me.name, source_p->name);
776         }
778         if(IsConfExemptJupe(aconf))
779         {
780                 SetExemptJupe(source_p);
781                 sendto_one(source_p,
782                                 ":%s NOTICE %s :*** You are exempt from juped channel warnings.",
783                                 me.name, source_p->name);
784         }
786         if(IsConfExemptResv(aconf))
787         {
788                 SetExemptResv(source_p);
789                 sendto_one(source_p,
790                                 ":%s NOTICE %s :*** You are exempt from resvs.",
791                                 me.name, source_p->name);
792         }
794         if(IsConfExemptShide(aconf))
795         {
796                 SetExemptShide(source_p);
797                 sendto_one(source_p,
798                            ":%s NOTICE %s :*** You are exempt from serverhiding.",
799                            me.name, source_p->name);
800         }
804  * user_mode - set get current users mode
806  * m_umode() added 15/10/91 By Darren Reed.
807  * parv[0] - sender
808  * parv[1] - username to change mode for
809  * parv[2] - modes to change
810  */
812 user_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
814         int flag;
815         int i;
816         const char **p;
817         char *m;
818         const char *pm;
819         struct Client *target_p;
820         int what, setflags;
821         int badflag = NO;       /* Only send one bad flag notice */
822         char buf[BUFSIZE];
824         what = MODE_ADD;
826         if(parc < 2)
827         {
828                 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MODE");
829                 return 0;
830         }
832         if((target_p = MyClient(source_p) ? find_named_person(parv[1]) : find_person(parv[1])) == NULL)
833         {
834                 if(MyConnect(source_p))
835                         sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
836                                            form_str(ERR_NOSUCHCHANNEL), parv[1]);
837                 return 0;
838         }
840         /* Dont know why these were commented out..
841          * put them back using new sendto() funcs
842          */
844         if(IsServer(source_p))
845         {
846                 sendto_realops_flags(UMODE_ALL, L_ADMIN,
847                                      "*** Mode for User %s from %s", parv[1], source_p->name);
848                 return 0;
849         }
851         if(source_p != target_p || target_p->from != source_p->from)
852         {
853                 sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name);
854                 return 0;
855         }
858         if(parc < 3)
859         {
860                 m = buf;
861                 *m++ = '+';
863                 for (i = 0; user_modes[i].letter && (m - buf < BUFSIZE - 4); i++)
864                         if(source_p->umodes & user_modes[i].mode)
865                                 *m++ = user_modes[i].letter;
866                 *m = '\0';
867                 sendto_one(source_p, form_str(RPL_UMODEIS), me.name, source_p->name, buf);
868                 return 0;
869         }
871         /* find flags already set for user */
872         setflags = source_p->umodes;
874         /*
875          * parse mode change string(s)
876          */
877         for (p = &parv[2]; p && *p; p++)
878                 for (pm = *p; *pm; pm++)
879                         switch (*pm)
880                         {
881                         case '+':
882                                 what = MODE_ADD;
883                                 break;
884                         case '-':
885                                 what = MODE_DEL;
886                                 break;
888                         case 'o':
889                                 if(what == MODE_ADD)
890                                 {
891                                         if(IsServer(client_p) && !IsOper(source_p))
892                                         {
893                                                 ++Count.oper;
894                                                 SetOper(source_p);
895                                         }
896                                 }
897                                 else
898                                 {
899                                         /* Only decrement the oper counts if an oper to begin with
900                                          * found by Pat Szuta, Perly , perly@xnet.com 
901                                          */
903                                         if(!IsOper(source_p))
904                                                 break;
906                                         ClearOper(source_p);
908                                         Count.oper--;
910                                         if(MyConnect(source_p))
911                                         {
912                                                 source_p->umodes &= ~ConfigFileEntry.oper_only_umodes;
913                                                 source_p->flags2 &= ~OPER_FLAGS;
915                                                 MyFree(source_p->localClient->opername);
916                                                 source_p->localClient->opername = NULL;
918                                                 dlinkFindDestroy(source_p, &oper_list);
919                                         }
920                                 }
921                                 break;
923                                 /* we may not get these,
924                                  * but they shouldnt be in default
925                                  */
927                         /* can only be set on burst */
928 #ifdef ENABLE_SERVICES
929                         case 'S':
930 #endif
931                         case ' ':
932                         case '\n':
933                         case '\r':
934                         case '\t':
935                                 break;
937                         default:
938                                 if((flag = user_modes_from_c_to_bitmask[(unsigned char) *pm]))
939                                 {
940                                         if(MyConnect(source_p)
941                                            && !IsOper(source_p)
942                                            && (ConfigFileEntry.oper_only_umodes & flag))
943                                         {
944                                                 badflag = YES;
945                                         }
946                                         else
947                                         {
948                                                 if(what == MODE_ADD)
949                                                         source_p->umodes |= flag;
950                                                 else
951                                                         source_p->umodes &= ~flag;
952                                         }
953                                 }
954                                 else
955                                 {
956                                         if(MyConnect(source_p))
957                                                 badflag = YES;
958                                 }
959                                 break;
960                         }
962         if(badflag)
963                 sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG), me.name, source_p->name);
965         if((source_p->umodes & UMODE_NCHANGE) && !IsOperN(source_p))
966         {
967                 sendto_one(source_p,
968                            ":%s NOTICE %s :*** You need oper and N flag for +n", me.name, parv[0]);
969                 source_p->umodes &= ~UMODE_NCHANGE;     /* only tcm's really need this */
970         }
972         if(MyConnect(source_p) && (source_p->umodes & UMODE_ADMIN) &&
973            (!IsOperAdmin(source_p) || IsOperHiddenAdmin(source_p)))
974         {
975                 sendto_one(source_p,
976                            ":%s NOTICE %s :*** You need oper and A flag for +a", me.name, parv[0]);
977                 source_p->umodes &= ~UMODE_ADMIN;
978         }
981         if(!(setflags & UMODE_INVISIBLE) && IsInvisible(source_p))
982                 ++Count.invisi;
983         if((setflags & UMODE_INVISIBLE) && !IsInvisible(source_p))
984                 --Count.invisi;
985         /*
986          * compare new flags with old flags and send string which
987          * will cause servers to update correctly.
988          */
989         send_umode_out(client_p, source_p, setflags);
991         return (0);
995  * send the MODE string for user (user) to connection client_p
996  * -avalon
997  */
998 void
999 send_umode(struct Client *client_p, struct Client *source_p, int old, int sendmask, char *umode_buf)
1001         int i;
1002         int flag;
1003         char *m;
1004         int what = 0;
1006         /*
1007          * build a string in umode_buf to represent the change in the user's
1008          * mode between the new (source_p->flag) and 'old'.
1009          */
1010         m = umode_buf;
1011         *m = '\0';
1013         for (i = 0; user_modes[i].letter; i++)
1014         {
1015                 flag = user_modes[i].mode;
1017                 if(MyClient(source_p) && !(flag & sendmask))
1018                         continue;
1019                 if((flag & old) && !(source_p->umodes & flag))
1020                 {
1021                         if(what == MODE_DEL)
1022                                 *m++ = user_modes[i].letter;
1023                         else
1024                         {
1025                                 what = MODE_DEL;
1026                                 *m++ = '-';
1027                                 *m++ = user_modes[i].letter;
1028                         }
1029                 }
1030                 else if(!(flag & old) && (source_p->umodes & flag))
1031                 {
1032                         if(what == MODE_ADD)
1033                                 *m++ = user_modes[i].letter;
1034                         else
1035                         {
1036                                 what = MODE_ADD;
1037                                 *m++ = '+';
1038                                 *m++ = user_modes[i].letter;
1039                         }
1040                 }
1041         }
1042         *m = '\0';
1043         if(*umode_buf && client_p)
1044                 sendto_one(client_p, ":%s MODE %s :%s", source_p->name, source_p->name, umode_buf);
1048  * send_umode_out
1050  * inputs       -
1051  * output       - NONE
1052  * side effects - 
1053  */
1054 void
1055 send_umode_out(struct Client *client_p, struct Client *source_p, int old)
1057         struct Client *target_p;
1058         char buf[BUFSIZE];
1059         dlink_node *ptr;
1061         send_umode(NULL, source_p, old, SEND_UMODES, buf);
1063         DLINK_FOREACH(ptr, serv_list.head)
1064         {
1065                 target_p = ptr->data;
1067                 if((target_p != client_p) && (target_p != source_p) && (*buf))
1068                 {
1069                         sendto_one(target_p, ":%s MODE %s :%s",
1070                                    get_id(source_p, target_p), 
1071                                    get_id(source_p, target_p), buf);
1072                 }
1073         }
1075         if(client_p && MyClient(client_p))
1076                 send_umode(client_p, source_p, old, ALL_UMODES, buf);
1079 /* 
1080  * user_welcome
1082  * inputs       - client pointer to client to welcome
1083  * output       - NONE
1084  * side effects -
1085  */
1086 void
1087 user_welcome(struct Client *source_p)
1089         sendto_one(source_p, form_str(RPL_WELCOME), me.name, source_p->name,
1090                    ServerInfo.network_name, source_p->name);
1091         sendto_one(source_p, form_str(RPL_YOURHOST), me.name,
1092                    source_p->name,
1093                    get_listener_name(source_p->localClient->listener), ircd_version);
1095         sendto_one(source_p, form_str(RPL_CREATED), me.name, source_p->name, creation);
1096         sendto_one(source_p, form_str(RPL_MYINFO), me.name, source_p->name, me.name, ircd_version);
1098         show_isupport(source_p);
1100         show_lusers(source_p);
1102         if(ConfigFileEntry.short_motd)
1103         {
1104                 sendto_one(source_p,
1105                            "NOTICE %s :*** Notice -- motd was last changed at %s",
1106                            source_p->name, user_motd_changed);
1108                 sendto_one(source_p,
1109                            "NOTICE %s :*** Notice -- Please read the motd if you haven't read it",
1110                            source_p->name);
1112                 sendto_one(source_p, form_str(RPL_MOTDSTART), 
1113                            me.name, source_p->name, me.name);
1115                 sendto_one(source_p, form_str(RPL_MOTD),
1116                            me.name, source_p->name, "*** This is the short motd ***");
1118                 sendto_one(source_p, form_str(RPL_ENDOFMOTD), me.name, source_p->name);
1119         }
1120         else
1121                 send_user_motd(source_p);
1124 /* oper_up()
1126  * inputs       - pointer to given client to oper
1127  *              - pointer to ConfItem to use
1128  * output       - none
1129  * side effects - opers up source_p using aconf for reference
1130  */
1132 oper_up(struct Client *source_p, struct oper_conf *oper_p)
1134         int old = (source_p->umodes & ALL_UMODES);
1136         SetOper(source_p);
1138         if(oper_p->umodes)
1139                 source_p->umodes |= oper_p->umodes & ALL_UMODES;
1140         else if(ConfigFileEntry.oper_umodes)
1141                 source_p->umodes |= ConfigFileEntry.oper_umodes & ALL_UMODES;
1142         else
1143                 source_p->umodes |= DEFAULT_OPER_UMODES & ALL_UMODES;
1145         Count.oper++;
1147         SetExemptKline(source_p);
1149         source_p->flags2 |= oper_p->flags;
1150         MyFree(source_p->localClient->opername);
1151         DupString(source_p->localClient->opername, oper_p->name);
1153         dlinkAddAlloc(source_p, &oper_list);
1155         if(IsOperAdmin(source_p) && !IsOperHiddenAdmin(source_p))
1156                 source_p->umodes |= UMODE_ADMIN;
1157         if(!IsOperN(source_p))
1158                 source_p->umodes &= ~UMODE_NCHANGE;
1160         sendto_realops_flags(UMODE_ALL, L_ALL,
1161                              "%s (%s@%s) is now an operator", source_p->name,
1162                              source_p->username, source_p->host);
1163         if(!(old & UMODE_INVISIBLE) && IsInvisible(source_p))
1164                 ++Count.invisi;
1165         if((old & UMODE_INVISIBLE) && !IsInvisible(source_p))
1166                 --Count.invisi;
1167         send_umode_out(source_p, source_p, old);
1168         sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
1169         sendto_one(source_p, ":%s NOTICE %s :*** Oper privs are %s", me.name,
1170                    source_p->name, get_oper_privs(oper_p->flags));
1171         send_oper_motd(source_p);
1173         return (1);