Anope IRC Services  Version 1.8
users.c
Go to the documentation of this file.
1 /* Routines to maintain a list of online users.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 #include "services.h"
15 
16 #define HASH(nick) (((nick)[0]&31)<<5 | ((nick)[1]&31))
17 User *userlist[1024];
18 
19 #define HASH2(nick) (((nick)[0]&31)<<5 | ((nick)[1]&31))
20 Uid *uidlist[1024];
21 
22 int32 usercnt = 0, opcnt = 0;
24 time_t maxusertime;
25 
26 /*************************************************************************/
27 /*************************************************************************/
28 
29 /* Allocate a new User structure, fill in basic values, link it to the
30  * overall list, and return it. Always successful.
31  */
32 
33 static User *new_user(const char *nick)
34 {
35  User *user, **list;
36 
37  user = scalloc(sizeof(User), 1);
38  if (!nick)
39  nick = "";
40  strscpy(user->nick, nick, NICKMAX);
41  list = &userlist[HASH(user->nick)];
42  user->next = *list;
43  if (*list)
44  (*list)->prev = user;
45  *list = user;
46  user->na = findnick(nick);
47  if (user->na)
48  user->na->u = user;
49  usercnt++;
50  if (usercnt > maxusercnt) {
52  maxusertime = time(NULL);
53  if (LogMaxUsers)
54  alog("user: New maximum user count: %d", maxusercnt);
55  }
56  user->isSuperAdmin = 0; /* always set SuperAdmin to 0 for new users */
57  user->nickTrack = NULL; /* ensure no default tracking nick */
58  return user;
59 }
60 
61 /*************************************************************************/
62 
63 /* Change the nickname of a user, and move pointers as necessary. */
64 
65 static void change_user_nick(User * user, const char *nick)
66 {
67  User **list;
68  int is_same;
69 
70  /* Sanity check to make sure we don't segfault */
71  if (!user || !nick || !*nick) {
72  return;
73  }
74 
75  is_same = (!stricmp(user->nick, nick) ? 1 : 0);
76 
77  if (user->prev)
78  user->prev->next = user->next;
79  else
80  userlist[HASH(user->nick)] = user->next;
81  if (user->next)
82  user->next->prev = user->prev;
83  user->nick[1] = 0; /* paranoia for zero-length nicks */
84  strscpy(user->nick, nick, NICKMAX);
85  list = &userlist[HASH(user->nick)];
86  user->next = *list;
87  user->prev = NULL;
88  if (*list)
89  (*list)->prev = user;
90  *list = user;
91 
92  /* Only if old and new nick aren't the same; no need to waste time */
93  if (!is_same) {
94  if (user->na)
95  user->na->u = NULL;
96  user->na = findnick(nick);
97  if (user->na)
98  user->na->u = user;
99  }
100 }
101 
102 /*************************************************************************/
103 
104 void update_host(User * user)
105 {
106  if (user->na && (nick_identified(user)
107  || (!(user->na->nc->flags & NI_SECURE)
108  && nick_recognized(user)))) {
109  if (user->na->last_usermask)
110  free(user->na->last_usermask);
111 
112  user->na->last_usermask =
113  smalloc(strlen(common_get_vident(user)) +
114  strlen(common_get_vhost(user)) + 2);
115  sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user),
116  common_get_vhost(user));
117  }
118 
119  if (debug)
120  alog("debug: %s changes its host to %s", user->nick,
121  common_get_vhost(user));
122 }
123 
124 
125 /*************************************************************************/
126 
127 /* Change the (virtual) hostname of a user. */
128 
129 void change_user_host(User * user, const char *host)
130 {
131  if (user->vhost)
132  free(user->vhost);
133  user->vhost = sstrdup(host);
134 
135  if (debug)
136  alog("debug: %s changes its vhost to %s", user->nick, host);
137 
138 
139 
140  update_host(user);
141 }
142 
143 /*************************************************************************/
144 
145 /* Change the realname of a user. */
146 
147 void change_user_realname(User * user, const char *realname)
148 {
149  if (user->realname)
150  free(user->realname);
151  user->realname = sstrdup(realname);
152 
153  if (user->na && (nick_identified(user)
154  || (!(user->na->nc->flags & NI_SECURE)
155  && nick_recognized(user)))) {
156  if (user->na->last_realname)
157  free(user->na->last_realname);
158  user->na->last_realname = sstrdup(realname);
159  }
160 
161  if (debug)
162  alog("debug: %s changes its realname to %s", user->nick, realname);
163 }
164 
165 
166 /*************************************************************************/
167 
168 /* Change the username of a user. */
169 
170 void change_user_username(User * user, const char *username)
171 {
172  if (user->vident)
173  free(user->vident);
174  user->vident = sstrdup(username);
175  if (user->na && (nick_identified(user)
176  || (!(user->na->nc->flags & NI_SECURE)
177  && nick_recognized(user)))) {
178  if (user->na->last_usermask)
179  free(user->na->last_usermask);
180 
181  user->na->last_usermask =
182  smalloc(strlen(common_get_vident(user)) +
183  strlen(common_get_vhost(user)) + 2);
184  sprintf(user->na->last_usermask, "%s@%s", common_get_vident(user),
185  common_get_vhost(user));
186  }
187  if (debug)
188  alog("debug: %s changes its username to %s", user->nick, username);
189 }
190 
191 /*************************************************************************/
192 
193 /* Remove and free a User structure. */
194 
195 void delete_user(User * user)
196 {
197  struct u_chanlist *c, *c2;
198  struct u_chaninfolist *ci, *ci2;
199  char *realname;
200 
201  if (LogUsers) {
202  realname = normalizeBuffer(user->realname);
203  if (ircd->vhost) {
204  alog("LOGUSERS: %s (%s@%s => %s) (%s) left the network (%s).",
205  user->nick, user->username, user->host,
206  (user->vhost ? user->vhost : "(none)"),
207  realname, user->server->name);
208  } else {
209  alog("LOGUSERS: %s (%s@%s) (%s) left the network (%s).",
210  user->nick, user->username, user->host,
211  realname, user->server->name);
212  }
213  free(realname);
214  }
215  send_event(EVENT_USER_LOGOFF, 1, user->nick);
216 
217  if (debug >= 2)
218  alog("debug: delete_user() called");
219  usercnt--;
220  if (is_oper(user))
221  opcnt--;
222  if (debug >= 2)
223  alog("debug: delete_user(): free user data");
224  free(user->username);
225  free(user->host);
226  if (user->chost)
227  free(user->chost);
228  if (user->vhost)
229  free(user->vhost);
230  if (user->vident)
231  free(user->vident);
232  if (user->uid) {
233  free(user->uid);
234  }
235  Anope_Free(user->realname);
236  Anope_Free(user->hostip);
237  if (debug >= 2) {
238  alog("debug: delete_user(): remove from channels");
239  }
240  c = user->chans;
241  while (c) {
242  c2 = c->next;
243  chan_deluser(user, c->chan);
244  free(c);
245  c = c2;
246  }
247  /* This called only here now */
248  cancel_user(user);
249  if (user->na)
250  user->na->u = NULL;
251  if (debug >= 2)
252  alog("debug: delete_user(): free founder data");
253  ci = user->founder_chans;
254  while (ci) {
255  ci2 = ci->next;
256  free(ci);
257  ci = ci2;
258  }
259 
260  if (user->nickTrack)
261  free(user->nickTrack);
262 
264 
265  if (debug >= 2)
266  alog("debug: delete_user(): delete from list");
267  if (user->prev)
268  user->prev->next = user->next;
269  else
270  userlist[HASH(user->nick)] = user->next;
271  if (user->next)
272  user->next->prev = user->prev;
273  if (debug >= 2)
274  alog("debug: delete_user(): free user structure");
275  free(user);
276  if (debug >= 2)
277  alog("debug: delete_user() done");
278 }
279 
280 /*************************************************************************/
281 /*************************************************************************/
282 
283 /* Return statistics. Pointers are assumed to be valid. */
284 
285 void get_user_stats(long *nusers, long *memuse)
286 {
287  long count = 0, mem = 0;
288  int i;
289  User *user;
290  struct u_chanlist *uc;
291  struct u_chaninfolist *uci;
292 
293  for (i = 0; i < 1024; i++) {
294  for (user = userlist[i]; user; user = user->next) {
295  count++;
296  mem += sizeof(*user);
297  if (user->username)
298  mem += strlen(user->username) + 1;
299  if (user->host)
300  mem += strlen(user->host) + 1;
301  if (ircd->vhost) {
302  if (user->vhost)
303  mem += strlen(user->vhost) + 1;
304  }
305  if (user->realname)
306  mem += strlen(user->realname) + 1;
307  if (user->server->name)
308  mem += strlen(user->server->name) + 1;
309  for (uc = user->chans; uc; uc = uc->next)
310  mem += sizeof(*uc);
311  for (uci = user->founder_chans; uci; uci = uci->next)
312  mem += sizeof(*uci);
313  }
314  }
315  *nusers = count;
316  *memuse = mem;
317 }
318 
319 /*************************************************************************/
320 
321 /* Find a user by nick. Return NULL if user could not be found. */
322 
323 User *finduser(const char *nick)
324 {
325  User *user;
326 
327  if (!nick || !*nick) {
328  if (debug) {
329  alog("debug: finduser() called with NULL values");
330  }
331  return NULL;
332  }
333 
334  if (debug >= 3)
335  alog("debug: finduser(%p)", nick);
336  user = userlist[HASH(nick)];
337  while (user && stricmp(user->nick, nick) != 0)
338  user = user->next;
339  if (debug >= 3)
340  alog("debug: finduser(%s) -> 0x%p", nick, (void *) user);
341  return user;
342 }
343 
344 
345 /*************************************************************************/
346 
347 /* Iterate over all users in the user list. Return NULL at end of list. */
348 
349 static User *current;
350 static int next_index;
351 
353 {
354  next_index = 0;
355  current = NULL;
356  while (next_index < 1024 && current == NULL)
357  current = userlist[next_index++];
358  if (debug)
359  alog("debug: firstuser() returning %s",
360  current ? current->nick : "NULL (end of list)");
361  return current;
362 }
363 
365 {
366  if (current)
367  current = current->next;
368  if (!current && next_index < 1024) {
369  while (next_index < 1024 && current == NULL)
370  current = userlist[next_index++];
371  }
372  if (debug)
373  alog("debug: nextuser() returning %s",
374  current ? current->nick : "NULL (end of list)");
375  return current;
376 }
377 
378 User *find_byuid(const char *uid)
379 {
380  User *u, *next;
381 
382  if (!uid) {
383  if (debug)
384  alog("debug: find_byuid() called with NULL-value");
385  return NULL;
386  }
387 
388  u = first_uid();
389  while (u) {
390  next = next_uid();
391  if (u->uid) {
392  if (!stricmp(uid, u->uid)) {
393  return u;
394  }
395  }
396  u = next;
397  }
398  return NULL;
399 }
400 
402 static int next_index_uid;
403 
405 {
406  next_index_uid = 0;
407  current_uid = NULL;
408  while (next_index_uid < 1024 && current_uid == NULL) {
409  current_uid = userlist[next_index_uid++];
410  }
411  if (debug >= 2) {
412  alog("debug: first_uid() returning %s %s",
413  current_uid ? current_uid->nick : "NULL (end of list)",
414  current_uid ? current_uid->uid : "");
415  }
416  return current_uid;
417 }
418 
420 {
421  if (current_uid)
422  current_uid = current_uid->next;
423  if (!current_uid && next_index_uid < 1024) {
424  while (next_index_uid < 1024 && current_uid == NULL)
425  current_uid = userlist[next_index_uid++];
426  }
427  if (debug >= 2) {
428  alog("debug: next_uid() returning %s %s",
429  current_uid ? current_uid->nick : "NULL (end of list)",
430  current_uid ? current_uid->uid : "");
431  }
432  return current_uid;
433 }
434 
435 Uid *new_uid(const char *nick, char *uid)
436 {
437  Uid *u, **list;
438 
439  u = scalloc(sizeof(Uid), 1);
440  if (!nick || !uid) {
441  return NULL;
442  }
443  strscpy(u->nick, nick, NICKMAX);
444  list = &uidlist[HASH2(u->nick)];
445  u->next = *list;
446  if (*list)
447  (*list)->prev = u;
448  *list = u;
449  u->uid = sstrdup(uid);
450  return u;
451 }
452 
453 Uid *find_uid(const char *nick)
454 {
455  Uid *u;
456  int i;
457 
458  for (i = 0; i < 1024; i++) {
459  for (u = uidlist[i]; u; u = u->next) {
460  if (!stricmp(nick, u->nick)) {
461  return u;
462  }
463  }
464  }
465  return NULL;
466 }
467 
468 Uid *find_nickuid(const char *uid)
469 {
470  Uid *u;
471  int i;
472 
473  for (i = 0; i < 1024; i++) {
474  for (u = uidlist[i]; u; u = u->next) {
475  if (!stricmp(uid, u->uid)) {
476  return u;
477  }
478  }
479  }
480  return NULL;
481 }
482 
483 /*************************************************************************/
484 /*************************************************************************/
485 
486 /* Handle a server NICK command. */
500 User *do_nick(const char *source, char *nick, char *username, char *host,
501  char *server, char *realname, time_t ts, uint32 svid,
502  uint32 ip, char *vhost, char *uid)
503 {
504  User *user = NULL;
505 
506  char *tmp = NULL;
507  NickAlias *old_na; /* Old nick rec */
508  int nc_changed = 1; /* Did nick core change? */
509  int status = 0; /* Status to apply */
510  char mask[USERMAX + HOSTMAX + 2];
511  char *logrealname;
512  char *oldnick;
513 
514  if (!*source) {
515  char ipbuf[16];
516  struct in_addr addr;
517 
518  if (ircd->nickvhost) {
519  if (vhost) {
520  if (!strcmp(vhost, "*")) {
521  vhost = NULL;
522  if (debug)
523  alog("debug: new user´┐Żwith no vhost in NICK command: %s", nick);
524  }
525  }
526  }
527 
528  /* This is a new user; create a User structure for it. */
529  if (debug)
530  alog("debug: new user: %s", nick);
531 
532  if (ircd->nickip) {
533  addr.s_addr = htonl(ip);
534  ntoa(addr, ipbuf, sizeof(ipbuf));
535  }
536 
537 
538  if (LogUsers) {
542  if (realname) {
543  tmp = strchr(realname, '%');
544  while (tmp) {
545  *tmp = '-';
546  tmp = strchr(realname, '%');
547  }
548  }
549  logrealname = normalizeBuffer(realname);
550 
555  if (ircd->nickvhost) {
556  if (ircd->nickip) {
557  alog("LOGUSERS: %s (%s@%s => %s) (%s) [%s] connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, ipbuf, server);
558  } else {
559  alog("LOGUSERS: %s (%s@%s => %s) (%s) connected to the network (%s).", nick, username, host, (vhost ? vhost : "none"), logrealname, server);
560  }
561  } else {
562  if (ircd->nickip) {
563  alog("LOGUSERS: %s (%s@%s) (%s) [%s] connected to the network (%s).", nick, username, host, logrealname, ipbuf, server);
564  } else {
565  alog("LOGUSERS: %s (%s@%s) (%s) connected to the network (%s).", nick, username, host, logrealname, server);
566  }
567  }
568  Anope_Free(logrealname);
569  }
570 
571  /* We used to ignore the ~ which a lot of ircd's use to indicate no
572  * identd response. That caused channel bans to break, so now we
573  * just take what the server gives us. People are still encouraged
574  * to read the RFCs and stop doing anything to usernames depending
575  * on the result of an identd lookup.
576  */
577 
578  /* First check for AKILLs. */
579  /* DONT just return null if its an akill match anymore - yes its more efficent to, however, now that ircd's are
580  * starting to use things like E/F lines, we cant be 100% sure the client will be removed from the network :/
581  * as such, create a user_struct, and if the client is removed, we'll delete it again when the QUIT notice
582  * comes in from the ircd.
583  **/
584  if (check_akill(nick, username, host, vhost, ipbuf)) {
585 /* return NULL; */
586  }
587 
592  /* don't akill on netmerges -Certus */
593  /* don't akill clients introduced by ulines. -Viper */
594  if (is_sync(findserver(servlist, server))
596  strncpy(mask, "*@", 3);
597  strncat(mask, host, HOSTMAX);
598  alog("DEFCON: adding akill for %s", mask);
599  add_akill(NULL, mask, s_OperServ,
600  time(NULL) + dotime(DefConAKILL),
602  "DEFCON AKILL");
603  if (check_akill(nick, username, host, vhost, ipbuf)) {
604 /* return NULL; */
605  }
606  }
607 
608  /* SGLINE */
609  if (ircd->sgline) {
610  if (check_sgline(nick, realname))
611  return NULL;
612  }
613 
614  /* SQLINE */
615  if (ircd->sqline) {
616  if (check_sqline(nick, 0))
617  return NULL;
618  }
619 
620  /* SZLINE */
621  if (ircd->szline && ircd->nickip) {
622  if (check_szline(nick, ipbuf))
623  return NULL;
624  }
625  /* Now check for session limits */
626  if (LimitSessions && !is_ulined(server)
627  && !add_session(nick, host, ipbuf))
628  return NULL;
629 
630  /* Allocate User structure and fill it in. */
631  user = new_user(nick);
632  user->username = sstrdup(username);
633  user->host = sstrdup(host);
634  user->server = findserver(servlist, server);
635  user->realname = sstrdup(realname);
636  user->timestamp = ts;
637  user->my_signon = time(NULL);
638  user->chost = vhost ? sstrdup(vhost) : sstrdup(host);
639  user->vhost = vhost ? sstrdup(vhost) : sstrdup(host);
640  if (uid) {
641  user->uid = sstrdup(uid); /* p10/ts6 stuff */
642  } else {
643  user->uid = NULL;
644  }
645  user->vident = sstrdup(username);
646  /* We now store the user's ip in the user_ struct,
647  * because we will use it in serveral places -- DrStein */
648  if (ircd->nickip) {
649  user->hostip = sstrdup(ipbuf);
650  } else {
651  user->hostip = NULL;
652  }
653 
654  if (svid == 0) {
655  display_news(user, NEWS_LOGON);
656  display_news(user, NEWS_RANDOM);
657  }
658 
659  if (svid == 2 && user->na) {
660  /* We do not yet know if the user should be identified or not.
661  * mark him as recognized for now.
662  * It s up to the protocol module to make sure this either becomes ID'd or
663  * is invalidated. ~ Viper */
664  if (debug)
665  alog("debug: Marking %s as recognized..", user->nick);
666  user->svid = 1;
667  user->na->status |= NS_RECOGNIZED;
668  nc_changed = 0;
669  } else if (svid == ts && user->na) {
670  /* Timestamp and svid match, and nick is registered; automagically identify the nick */
671  user->svid = svid;
672  user->na->status |= NS_IDENTIFIED;
673  check_memos(user);
674  nc_changed = 0;
675 
676  /* Start nick tracking if available */
677  if (NSNickTracking)
678  nsStartNickTracking(user);
679 
680  } else if (svid != 1) {
681  /* Resets the svid because it doesn't match */
682  user->svid = 1;
683 
684  anope_cmd_svid_umode(user->nick, user->timestamp);
685 
686  } else {
687  user->svid = 1;
688  }
689  send_event(EVENT_NEWNICK, 1, nick);
690 
691  } else {
692  /* An old user changing nicks. */
693  if (UseTS6 && ircd->ts6)
694  user = find_byuid(source);
695 
696  if (!user)
697  user = finduser(source);
698 
699  if (!user) {
700  alog("user: NICK from nonexistent nick %s", source);
701  return NULL;
702  }
703  user->isSuperAdmin = 0; /* Dont let people nick change and stay SuperAdmins */
704  if (debug)
705  alog("debug: %s changes nick to %s", source, nick);
706 
707  if (LogUsers) {
708  logrealname = normalizeBuffer(user->realname);
709  if (ircd->vhost) {
710  alog("LOGUSERS: %s (%s@%s => %s) (%s) changed nick to %s (%s).", user->nick, user->username, user->host, (user->vhost ? user->vhost : "(none)"), logrealname, nick, user->server->name);
711  } else {
712  alog("LOGUSERS: %s (%s@%s) (%s) changed nick to %s (%s).",
713  user->nick, user->username, user->host, logrealname,
714  nick, user->server->name);
715  }
716  if (logrealname) {
717  free(logrealname);
718  }
719  }
720 
721  user->timestamp = ts;
722 
723  if (stricmp(nick, user->nick) == 0) {
724  /* No need to redo things */
725  change_user_nick(user, nick);
726  nc_changed = 0;
727  } else {
728  /* Update this only if nicks aren't the same */
729  user->my_signon = time(NULL);
730 
731  old_na = user->na;
732  if (old_na) {
733  if (nick_recognized(user))
734  user->na->last_seen = time(NULL);
735  status = old_na->status & NS_TRANSGROUP;
736  cancel_user(user);
737  }
738 
739  oldnick = sstrdup(user->nick);
740  change_user_nick(user, nick);
741 
742  if ((old_na ? old_na->nc : NULL) ==
743  (user->na ? user->na->nc : NULL))
744  nc_changed = 0;
745 
746  if (!nc_changed && (user->na))
747  user->na->status |= status;
748  else {
749  anope_cmd_nc_change(user);
750  }
751 
752  send_event(EVENT_CHANGE_NICK, 2, nick, oldnick);
753  free(oldnick);
754  }
755 
756  if (ircd->sqline) {
757  if (!is_oper(user) && check_sqline(user->nick, 1))
758  return NULL;
759  }
760 
761  } /* if (!*source) */
762 
763  /* Check for nick tracking to bypass identification */
764  if (NSNickTracking && nsCheckNickTracking(user)) {
765  user->na->status |= NS_IDENTIFIED;
766  nc_changed = 0;
767  }
768 
769  if (nc_changed || !nick_recognized(user)) {
770  if (validate_user(user))
771  check_memos(user);
772 
773  } else {
774  if (nick_identified(user)) {
775  char tsbuf[16];
776  user->na->last_seen = time(NULL);
777 
778  if (user->na->last_usermask)
779  free(user->na->last_usermask);
780  user->na->last_usermask =
781  smalloc(strlen(common_get_vident(user)) +
782  strlen(common_get_vhost(user)) + 2);
783  sprintf(user->na->last_usermask, "%s@%s",
784  common_get_vident(user), common_get_vhost(user));
785 
786  snprintf(tsbuf, sizeof(tsbuf), "%lu",
787  (unsigned long int) user->timestamp);
788  anope_cmd_svid_umode2(user, tsbuf);
789 
790  alog("%s: %s!%s@%s automatically identified for nick %s",
791  s_NickServ, user->nick, user->username,
792  user->host, user->nick);
793  }
794  }
795 
796  /* Bahamut sets -r on every nick changes, so we must test it even if nc_changed == 0 */
797  if (ircd->check_nick_id) {
798  if (nick_identified(user)) {
799  char tsbuf[16];
800  snprintf(tsbuf, sizeof(tsbuf), "%lu",
801  (unsigned long int) user->timestamp);
802  anope_cmd_svid_umode3(user, tsbuf);
803  }
804  }
805 
806  return user;
807 }
808 
809 /*************************************************************************/
810 
811 /* Handle a MODE command for a user.
812  * av[0] = nick to change mode for
813  * av[1] = modes
814  */
815 
816 void do_umode(const char *source, int ac, char **av)
817 {
818  User *user;
819 
820  user = finduser(av[0]);
821  if (!user) {
822  alog("user: MODE %s for nonexistent nick %s: %s", av[1], av[0],
823  merge_args(ac, av));
824  return;
825  }
826 
827  anope_set_umode(user, ac - 1, &av[1]);
828 }
829 
830 /* Handle a UMODE2 command for a user.
831  * av[0] = modes
832  */
833 
834 void do_umode2(const char *source, int ac, char **av)
835 {
836  User *user;
837 
838  user = finduser(source);
839  if (!user) {
840  alog("user: MODE %s for nonexistent nick %s: %s", av[0], source,
841  merge_args(ac, av));
842  return;
843  }
844 
845  anope_set_umode(user, ac, &av[0]);
846 }
847 
848 /*************************************************************************/
849 
850 /* Handle a QUIT command.
851  * av[0] = reason
852  */
853 
854 void do_quit(const char *source, int ac, char **av)
855 {
856  User *user;
857  NickAlias *na;
858 
859  user = finduser(source);
860  if (!user) {
861  alog("user: QUIT from nonexistent user %s: %s", source,
862  merge_args(ac, av));
863  return;
864  }
865  if (debug) {
866  alog("debug: %s quits", source);
867  }
868  if ((na = user->na) && (!(na->status & NS_VERBOTEN))
869  && (!(na->nc->flags & NI_SUSPENDED))
870  && (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) {
871  na->last_seen = time(NULL);
872  if (na->last_quit)
873  free(na->last_quit);
874  na->last_quit = *av[0] ? sstrdup(av[0]) : NULL;
875  }
876  if (LimitSessions && !is_ulined(user->server->name)) {
877  del_session(user->host);
878  }
879  delete_user(user);
880 }
881 
882 /*************************************************************************/
883 
884 /* Handle a KILL command.
885  * av[0] = nick being killed
886  * av[1] = reason
887  */
888 
889 void do_kill(char *nick, char *msg)
890 {
891  User *user;
892  NickAlias *na;
893 
894  user = finduser(nick);
895  if (!user) {
896  if (debug) {
897  alog("debug: KILL of nonexistent nick: %s", nick);
898  }
899  return;
900  }
901  if (debug) {
902  alog("debug: %s killed", nick);
903  }
904  if ((na = user->na) && (!(na->status & NS_VERBOTEN))
905  && (!(na->nc->flags & NI_SUSPENDED))
906  && (na->status & (NS_IDENTIFIED | NS_RECOGNIZED))) {
907  na->last_seen = time(NULL);
908  if (na->last_quit)
909  free(na->last_quit);
910  na->last_quit = *msg ? sstrdup(msg) : NULL;
911 
912  }
913  if (LimitSessions && !is_ulined(user->server->name)) {
914  del_session(user->host);
915  }
916  delete_user(user);
917 }
918 
919 /*************************************************************************/
920 /*************************************************************************/
921 
922 /* Is the given user protected from kicks and negative mode changes? */
923 
924 int is_protected(User * user)
925 {
926  if (ircd->protectedumode) {
927  return (user->mode & ircd->protectedumode);
928  } else {
929  return 0;
930  }
931 }
932 
933 /*************************************************************************/
934 
935 /* Is the given nick an oper? */
936 
937 int is_oper(User * user)
938 {
939  if (user) {
940  return (user->mode & anope_get_oper_mode());
941  } else {
942  return 0;
943  }
944 }
945 
946 /*************************************************************************/
947 /*************************************************************************/
948 
949 /* Is the given user ban-excepted? */
950 int is_excepted(ChannelInfo * ci, User * user)
951 {
952  if (!ci->c || !ircd->except)
953  return 0;
954 
955  if (elist_match_user(ci->c->excepts, user))
956  return 1;
957 
958  return 0;
959 }
960 
961 /*************************************************************************/
962 
963 /* Is the given MASK ban-excepted? */
964 int is_excepted_mask(ChannelInfo * ci, char *mask)
965 {
966  if (!ci->c || !ircd->except)
967  return 0;
968 
969  if (elist_match_mask(ci->c->excepts, mask, 0))
970  return 1;
971 
972  return 0;
973 }
974 
975 
976 /*************************************************************************/
977 
978 /* Does the user's usermask match the given mask (either nick!user@host or
979  * just user@host)?
980  */
981 
982 static int _match_usermask(const char *mask, User * user, boolean full)
983 {
984  char *mask2;
985  char *nick, *username, *host;
986  int result;
987 
988  if (!mask || !*mask) {
989  return 0;
990  }
991 
992  mask2 = sstrdup(mask);
993 
994  if (strchr(mask2, '!')) {
995  nick = strtok(mask2, "!");
996  username = strtok(NULL, "@");
997  } else {
998  nick = NULL;
999  username = strtok(mask2, "@");
1000  }
1001  host = strtok(NULL, "");
1002  if (!username || !host) {
1003  free(mask2);
1004  return 0;
1005  }
1006 
1007  if (nick) {
1008  result = match_wild_nocase(nick, user->nick)
1009  && match_wild_nocase(username, user->username)
1010  && ((full && match_wild_nocase(host, user->host))
1011  || match_wild_nocase(host, user->vhost)
1012  || match_wild_nocase(host, user->chost));
1013  } else {
1014  result = match_wild_nocase(username, user->username)
1015  && ((full && match_wild_nocase(host, user->host))
1016  || match_wild_nocase(host, user->vhost)
1017  || match_wild_nocase(host, user->chost));
1018  }
1019 
1020  free(mask2);
1021  return result;
1022 }
1023 
1024 int match_usermask(const char *mask, User *user)
1025 {
1026  return _match_usermask(mask, user, false);
1027 }
1028 
1029 int match_usermask_full(const char *mask, User *user, boolean full)
1030 {
1031  return _match_usermask(mask, user, full);
1032 }
1033 
1034 /*************************************************************************/
1035 
1036 /* simlar to match_usermask, except here we pass the host as the IP */
1037 
1038 int match_userip(const char *mask, User * user, char *iphost)
1039 {
1040  char *mask2;
1041  char *nick, *username, *host;
1042  int result;
1043 
1044  if (!mask || !*mask) {
1045  return 0;
1046  }
1047 
1048  mask2 = sstrdup(mask);
1049 
1050  if (strchr(mask2, '!')) {
1051  nick = strtok(mask2, "!");
1052  username = strtok(NULL, "@");
1053  } else {
1054  nick = NULL;
1055  username = strtok(mask2, "@");
1056  }
1057  host = strtok(NULL, "");
1058  if (!username || !host) {
1059  free(mask2);
1060  return 0;
1061  }
1062 
1063  if (nick) {
1064  result = match_wild_nocase(nick, user->nick)
1065  && match_wild_nocase(username, user->username)
1066  && (match_wild_nocase(host, iphost)
1067  || match_wild_nocase(host, user->vhost));
1068  } else {
1069  result = match_wild_nocase(username, user->username)
1070  && (match_wild_nocase(host, iphost)
1071  || match_wild_nocase(host, user->vhost));
1072  }
1073 
1074  free(mask2);
1075  return result;
1076 }
1077 
1078 /*************************************************************************/
1079 
1080 /* Split a usermask up into its constitutent parts. Returned strings are
1081  * malloc()'d, and should be free()'d when done with. Returns "*" for
1082  * missing parts.
1083  */
1084 
1085 void split_usermask(const char *mask, char **nick, char **user,
1086  char **host)
1087 {
1088  char *mask2 = sstrdup(mask);
1089 
1090  *nick = strtok(mask2, "!");
1091  *user = strtok(NULL, "@");
1092  *host = strtok(NULL, "");
1093  /* Handle special case: mask == user@host */
1094  if (*nick && !*user && strchr(*nick, '@')) {
1095  *nick = NULL;
1096  *user = strtok(mask2, "@");
1097  *host = strtok(NULL, "");
1098  }
1099  if (!*nick)
1100  *nick = "*";
1101  if (!*user)
1102  *user = "*";
1103  if (!*host)
1104  *host = "*";
1105  *nick = sstrdup(*nick);
1106  *user = sstrdup(*user);
1107  *host = sstrdup(*host);
1108  free(mask2);
1109 }
1110 
1111 /*************************************************************************/
1112 
1113 /* Given a user, return a mask that will most likely match any address the
1114  * user will have from that location. For IP addresses, wildcards the
1115  * appropriate subnet mask (e.g. 35.1.1.1 -> 35.*; 128.2.1.1 -> 128.2.*);
1116  * for named addresses, wildcards the leftmost part of the name unless the
1117  * name only contains two parts. If the username begins with a ~, delete
1118  * it. The returned character string is malloc'd and should be free'd
1119  * when done with.
1120  */
1121 
1122 char *create_mask(User * u)
1123 {
1124  char *mask, *s, *end;
1125  int ulen = strlen(common_get_vident(u));
1126 
1127  /* Get us a buffer the size of the username plus hostname. The result
1128  * will never be longer than this (and will often be shorter), thus we
1129  * can use strcpy() and sprintf() safely.
1130  */
1131  end = mask = smalloc(ulen + strlen(common_get_vhost(u)) + 3);
1132  end += sprintf(end, "%s%s@",
1133  (ulen <
1134  (*(common_get_vident(u)) ==
1135  '~' ? USERMAX + 1 : USERMAX) ? "*" : ""),
1136  (*(common_get_vident(u)) ==
1137  '~' ? common_get_vident(u) +
1138  1 : common_get_vident(u)));
1139 
1140  if (strspn(common_get_vhost(u), "0123456789.") ==
1141  strlen(common_get_vhost(u))
1142  && (s = strchr(common_get_vhost(u), '.'))
1143  && (s = strchr(s + 1, '.'))
1144  && (s = strchr(s + 1, '.'))
1145  && (!strchr(s + 1, '.'))) { /* IP addr */
1146  s = sstrdup(common_get_vhost(u));
1147  *strrchr(s, '.') = 0;
1148 
1149  sprintf(end, "%s.*", s);
1150  free(s);
1151  } else {
1152  if ((s = strchr(common_get_vhost(u), '.')) && strchr(s + 1, '.')) {
1153  s = sstrdup(strchr(common_get_vhost(u), '.') - 1);
1154  *s = '*';
1155  strcpy(end, s);
1156  free(s);
1157  } else {
1158  strcpy(end, common_get_vhost(u));
1159  }
1160  }
1161  return mask;
1162 }
1163 
1164 /*************************************************************************/
E size_t strspn(const char *s, const char *accept)
Definition: compat.c:106
static User * current_uid
Definition: users.c:401
void do_quit(const char *source, int ac, char **av)
Definition: users.c:854
Uid * next
Definition: services.h:417
#define Anope_Free(x)
Definition: extern.h:1391
User * next_uid(void)
Definition: users.c:419
int nickip
Definition: services.h:340
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
int match_userip(const char *mask, User *user, char *iphost)
Definition: users.c:1038
char nick[NICKMAX]
Definition: services.h:875
time_t maxusertime
Definition: users.c:24
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
E NickAlias * findnick(const char *nick)
Definition: db-merger.c:1857
void split_usermask(const char *mask, char **nick, char **user, char **host)
Definition: users.c:1085
E int checkDefCon(int level)
Definition: operserv.c:1608
struct u_chanlist * next
Definition: services.h:899
#define NI_SUSPENDED
Definition: services.h:1308
int is_excepted_mask(ChannelInfo *ci, char *mask)
Definition: users.c:964
uint32 maxusercnt
Definition: users.c:23
struct user_::u_chaninfolist * founder_chans
E IRCDVar * ircd
Definition: extern.h:39
int match_usermask(const char *mask, User *user)
Definition: users.c:1024
void change_user_realname(User *user, const char *realname)
Definition: users.c:147
#define NEWS_LOGON
Definition: services.h:1049
E int nick_identified(User *u)
Definition: nickserv.c:1111
static User * new_user(const char *nick)
Definition: users.c:33
E Entry * elist_match_user(EList *list, User *u)
Definition: channels.c:2455
char * last_quit
Definition: services.h:527
E void send_event(const char *name, int argc,...)
Definition: events.c:37
char * vhost
Definition: services.h:880
E int dotime(const char *s)
Definition: misc.c:364
E void anope_cmd_svid_umode2(User *u, char *ts)
Definition: ircd.c:614
E int NSNickTracking
Definition: extern.h:399
int vhost
Definition: services.h:301
Uid * find_nickuid(const char *uid)
Definition: users.c:468
E int is_ulined(char *server)
Definition: servers.c:495
int match_usermask_full(const char *mask, User *user, boolean full)
Definition: users.c:1029
User * first_uid(void)
Definition: users.c:404
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
char * chost
Definition: services.h:881
int check_nick_id
Definition: services.h:353
E void moduleCleanStruct(ModuleData **moduleData)
Definition: modules.c:2439
#define NS_RECOGNIZED
Definition: services.h:1276
#define NS_VERBOTEN
Definition: services.h:1273
#define NEWS_RANDOM
Definition: services.h:1051
E void del_session(const char *host)
Definition: sessions.c:265
uint32 svid
Definition: services.h:888
char * host
Definition: services.h:878
#define EVENT_CHANGE_NICK
Definition: events.h:50
E void anope_cmd_nc_change(User *u)
Definition: ircd.c:609
User * prev
Definition: services.h:873
Uid * find_uid(const char *nick)
Definition: users.c:453
E int check_sqline(char *nick, int nick_change)
Definition: operserv.c:1265
int szline
Definition: services.h:315
struct user_::u_chanlist * chans
int32 opcnt
Definition: users.c:22
E void check_memos(User *u)
Definition: memoserv.c:86
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
int isSuperAdmin
Definition: services.h:896
char * uid
Definition: services.h:419
int is_protected(User *user)
Definition: users.c:924
#define NS_TRANSGROUP
Definition: services.h:1283
E int add_akill(User *u, char *mask, const char *by, const time_t expires, const char *reason)
Definition: operserv.c:722
int except
Definition: services.h:320
E int LogMaxUsers
Definition: extern.h:436
E int nick_recognized(User *u)
Definition: nickserv.c:1131
E int is_sync(Server *server)
Definition: servers.c:516
static void change_user_nick(User *user, const char *nick)
Definition: users.c:65
E void anope_set_umode(User *user, int ac, char **av)
Definition: ircd.c:130
E char * sstrdup(const char *s)
Definition: memory.c:105
NickCore * nc
Definition: services.h:533
E void * scalloc(long elsize, long els)
Definition: memory.c:55
E void anope_cmd_svid_umode3(User *u, char *ts)
Definition: ircd.c:619
char * uid
Definition: services.h:890
E void chan_deluser(User *user, Channel *c)
Definition: channels.c:24
char * hostip
Definition: services.h:879
E char * s_OperServ
Definition: extern.h:289
time_t my_signon
Definition: services.h:887
E int check_akill(char *nick, const char *username, const char *host, const char *vhost, const char *ip)
Definition: operserv.c:847
void do_umode(const char *source, int ac, char **av)
Definition: users.c:816
EList * excepts
Definition: services.h:1013
int nickvhost
Definition: services.h:343
int is_oper(User *user)
Definition: users.c:937
E int check_sgline(char *nick, const char *realname)
Definition: operserv.c:1074
struct u_chaninfolist * next
Definition: services.h:905
User * userlist[1024]
Definition: users.c:17
uint32 protectedumode
Definition: services.h:323
int32_t int32
Definition: db-merger.c:122
E Entry * elist_match_mask(EList *list, char *mask, uint32 ip)
Definition: channels.c:2375
uint16 status
Definition: services.h:532
User * finduser(const char *nick)
Definition: users.c:323
#define DEFCON_AKILL_NEW_CLIENTS
Definition: services.h:1262
void change_user_username(User *user, const char *username)
Definition: users.c:170
void do_umode2(const char *source, int ac, char **av)
Definition: users.c:834
#define EVENT_USER_LOGOFF
Definition: events.h:51
struct channel_ * c
Definition: services.h:692
char * name
Definition: services.h:854
E char * merge_args(int argc, char **argv)
Definition: misc.c:180
User * nextuser(void)
Definition: users.c:364
User * firstuser(void)
Definition: users.c:352
Command * c
Definition: ns_recover.c:17
void do_kill(char *nick, char *msg)
Definition: users.c:889
User * next
Definition: services.h:873
Server * server
Definition: services.h:884
u_int32_t uint32
Definition: db-merger.c:123
E void alog(const char *fmt,...) FORMAT(printf
int sqline
Definition: services.h:314
Uid * prev
Definition: services.h:417
void get_user_stats(long *nusers, long *memuse)
Definition: users.c:285
E int UseTS6
Definition: extern.h:364
E void display_news(User *u, int16 type)
Definition: news.c:269
E void cancel_user(User *u)
Definition: nickserv.c:1067
#define HASH(nick)
Definition: users.c:16
E Server * findserver(Server *s, const char *name)
Definition: servers.c:261
E int nsCheckNickTracking(User *u)
Definition: nickserv.c:1998
char nick[NICKMAX]
Definition: services.h:418
E int debug
Definition: extern.h:775
MYSQL_RES * result
Definition: mypasql.c:6
char * create_mask(User *u)
Definition: users.c:1122
E int anope_get_oper_mode()
Definition: ircd.c:1216
#define EVENT_NEWNICK
Definition: events.h:19
char * username
Definition: services.h:877
char * last_realname
Definition: services.h:528
char * vident
Definition: services.h:882
E int validate_user(User *u)
Definition: nickserv.c:990
#define NI_SECURE
Definition: services.h:1291
Uid * new_uid(const char *nick, char *uid)
Definition: users.c:435
Uid * uidlist[1024]
Definition: users.c:20
E void ntoa(struct in_addr addr, char *ipaddr, int len)
Definition: misc.c:1198
E int LimitSessions
Definition: extern.h:503
static User * current
Definition: users.c:349
#define NICKMAX
Definition: config.h:62
static int next_index
Definition: users.c:350
int is_excepted(ChannelInfo *ci, User *user)
Definition: users.c:950
#define NS_IDENTIFIED
Definition: services.h:1275
void update_host(User *user)
Definition: users.c:104
#define HASH2(nick)
Definition: users.c:19
#define USERMAX
Definition: config.h:68
E Server * servlist
Definition: extern.h:1051
void delete_user(User *user)
Definition: users.c:195
ModuleData * moduleData
Definition: services.h:894
Definition: services.h:416
static int _match_usermask(const char *mask, User *user, boolean full)
Definition: users.c:982
User * find_byuid(const char *uid)
Definition: users.c:378
User * do_nick(const char *source, char *nick, char *username, char *host, char *server, char *realname, time_t ts, uint32 svid, uint32 ip, char *vhost, char *uid)
Definition: users.c:500
uint32 flags
Definition: services.h:548
uint32 mode
Definition: services.h:889
E void * smalloc(long size)
Definition: memory.c:30
int ts6
Definition: services.h:366
static int next_index_uid
Definition: users.c:402
time_t last_seen
Definition: services.h:531
E int check_szline(char *nick, char *ip)
Definition: operserv.c:1461
int sgline
Definition: services.h:313
User * u
Definition: services.h:536
E char * s_NickServ
Definition: extern.h:284
char * last_usermask
Definition: services.h:529
time_t timestamp
Definition: services.h:886
E char * common_get_vhost(User *u)
Definition: actions.c:251
E void anope_cmd_svid_umode(char *nick, time_t ts)
Definition: ircd.c:604
E char * DefConAKILL
Definition: extern.h:567
char * nickTrack
Definition: services.h:885
E char * DefConAkillReason
Definition: extern.h:572
#define HOSTMAX
Definition: config.h:71
int32 usercnt
Definition: users.c:22
void change_user_host(User *user, const char *host)
Definition: users.c:129
E char * normalizeBuffer(char *)
Definition: botserv.c:1101
char * realname
Definition: services.h:883
E char * common_get_vident(User *u)
Definition: actions.c:272
NickAlias * na
Definition: services.h:892
E int add_session(char *nick, char *host, char *hostip)
Definition: sessions.c:205
E void nsStartNickTracking(User *u)
Definition: nickserv.c:1962
E int LogUsers
Definition: extern.h:355