00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "services.h"
00047 #include "nickserv.h"
00048 #include "hash.h"
00049
00050 HostClone *firstClone = NULL;
00051 HostClone *lastClone = NULL;
00052 CloneRule *first_crule = NULL;
00061 struct pending_alert
00062 {
00063 HostClone *hc;
00064 char ha, ua;
00065 int signon_ct,
00066 signoff_ct;
00067
00068 int signon_ct_r;
00069 int signoff_ct_r;
00070
00071 time_t firstTime,
00072 lastAlert;
00073
00074 struct pending_alert *next;
00075 } *pendingAlerts;
00076
00077
00086 struct pending_alert* find_palert(HostClone *hc)
00087 {
00088 struct pending_alert *pI;
00089
00090 for(pI = pendingAlerts; pI; pI = pI->next)
00091 if (pI->hc == hc)
00092 break;
00093 return pI;
00094 }
00095
00100 struct pending_alert* make_palert()
00101 {
00102 struct pending_alert *pa =
00103 (struct pending_alert *)oalloc(sizeof(pending_alert));
00104
00105 pa->ua = pa->ha = 0;
00106 pa->hc = NULL;
00107 pa->next = NULL;
00108
00109 return pa;
00110 }
00111
00118 void free_palert(struct pending_alert *pArg)
00119 {
00120 FREE(pArg);
00121 }
00122
00130 void add_palert(struct pending_alert *pArg)
00131 {
00132 struct pending_alert *pTmp;
00133
00134 pTmp = pendingAlerts;
00135 pendingAlerts = pArg;
00136 pArg->next = pTmp;
00137 }
00138
00146 void remove_palert(struct pending_alert *pZap)
00147 {
00148 struct pending_alert *pTmp = NULL, *pI;
00149
00150 for(pI = pendingAlerts; pI; pI = pI->next)
00151 {
00152 if (pI == pZap) {
00153 if (pTmp)
00154 pTmp->next = pZap->next;
00155 else
00156 pendingAlerts = pZap->next;
00157 return;
00158 }
00159 else
00160 pTmp = pI;
00161 }
00162 }
00163
00170 void listCloneAlerts(UserList *nick)
00171 {
00172 char *from = nick->nick;
00173 struct pending_alert *pIterator;
00174 HostClone *hc;
00175 UserClone *uc;
00176 float signonRate;
00177 int found = 0;
00178
00179 for(pIterator = pendingAlerts; pIterator; pIterator = pIterator->next)
00180 {
00181 if (CTime == pIterator->lastAlert)
00182 continue;
00183
00184 hc = pIterator->hc;
00185
00186 if (pIterator->lastAlert)
00187 signonRate = (pIterator->signon_ct_r - pIterator->signoff_ct_r) /
00188 (float)(CTime - pIterator->lastAlert);
00189 else
00190 signonRate = 1.0;
00191
00192 if (hc->clones >= hc->trigger) {
00193 sSend(":%s NOTICE %s :CLONES(%i) *@%s (Signon Rate: %.2f)", OperServ, from,
00194 hc->clones, hc->host, signonRate);
00195 found = 1;
00196 continue;
00197 }
00198
00199 for(uc = hc->firstUser; uc; uc = uc->next) {
00200 if (!(uc->uflags & CLONE_ALERT) || (uc->uflags & CLONE_OK)
00201 || (uc->clones < uc->trigger))
00202 continue;
00203 sSend(":%s NOTICE %s : -- %i %s@%s (H: %.2f)", OperServ, from,
00204 uc->clones, uc->user, hc->host, signonRate);
00205 found = 1;
00206 }
00207 }
00208
00209 if (found == 0)
00210 sSend(":%s NOTICE %s :No clone alerts at the moment.", OperServ, from);
00211 }
00212
00219 time_t updateCloneAlerts(time_t aval)
00220 {
00221 struct pending_alert *pIterator;
00222 float signonRate;
00223 HostClone *hc;
00224 UserClone *uc;
00225
00226 aval += 60;
00227
00228 for(pIterator = pendingAlerts; pIterator; pIterator = pIterator->next)
00229 {
00230 if (CTime == pIterator->lastAlert || (pIterator->lastAlert + 10) >= CTime)
00231 continue;
00232
00233 if (pIterator->lastAlert) {
00234 if (CTime - pIterator->lastAlert != 0)
00235 signonRate = (pIterator->signon_ct_r - pIterator->signoff_ct_r) /
00236 (float)(CTime - pIterator->lastAlert);
00237 else
00238 signonRate = (pIterator->signon_ct_r - pIterator->signoff_ct_r) / 1;
00239 }
00240 else
00241 signonRate = 1.0;
00242
00243
00244 if (pIterator->signon_ct_r == 0 && (CTime - pIterator->lastAlert) < 1200)
00245 continue;
00246
00247
00248
00249
00250
00251 if (((CTime - pIterator->lastAlert) < 90) &&
00252 signonRate < .03)
00253 continue;
00254
00255 if (pIterator->lastAlert && (pIterator->signon_ct - pIterator->signoff_ct) < 0)
00256 continue;
00257
00258 pIterator->lastAlert = CTime;
00259 pIterator->signon_ct_r = 0;
00260 pIterator->signoff_ct_r = 0;
00261
00262 hc = pIterator->hc;
00263
00264 if ((hc->flags & CLONE_ALERT) && !(hc->flags & CLONE_OK)
00265 && (hc->clones >= hc->trigger))
00266 sSend(":%s GLOBOPS :CLONES(%i/%i): *@%s (%.2f cps)", OperServ, hc->clones, hc->trigger, hc->host, signonRate);
00267
00268 for(uc = hc->firstUser; uc; uc = uc->next) {
00269 if (!(uc->uflags & CLONE_ALERT) || (uc->uflags & CLONE_OK)
00270 || (uc->clones < uc->trigger))
00271 continue;
00272 sSend(":%s GLOBOPS :CLONES(%i/%i): %s@%s", OperServ, uc->clones,
00273 uc->trigger, uc->user,
00274 hc->host);
00275 }
00276 }
00277
00278 return aval;
00279 }
00280
00281
00282
00288 CloneRule *
00289 GetCrule(char *mask)
00290 {
00291 int ct = 0, num = 0;
00292 CloneRule *crule;
00293
00294 if (!mask)
00295 return NULL;
00296
00297 for (crule = first_crule; crule; crule = crule->next)
00298 if (crule->mask[0] && !strcasecmp(mask, crule->mask))
00299 return crule;
00300 if (isdigit(*mask)) {
00301 num = atoi(mask);
00302 for (ct = 1, crule = first_crule; crule; crule = crule->next, ct++)
00303 if (num == ct)
00304 return crule;
00305 }
00306 return NULL;
00307 }
00308
00314 CloneRule *
00315 GetCruleMatch(char *host)
00316 {
00317 CloneRule *crule;
00318
00319 if (!host)
00320 return NULL;
00321
00322 for (crule = first_crule; crule; crule = crule->next) {
00323 if (crule->mask && !match(crule->mask, host))
00324 return crule;
00325 }
00326 return NULL;
00327 }
00328
00333 CloneRule *
00334 NewCrule()
00335 {
00336 return (CloneRule *) oalloc(sizeof(CloneRule));
00337 }
00338
00343 void
00344 AddCrule(CloneRule * rule, int n)
00345 {
00346 CloneRule *tmp;
00347 int ct = 0;
00348
00349 if (!rule)
00350 return;
00351
00352 for (tmp = first_crule; tmp; tmp = tmp->next)
00353 if (rule == tmp)
00354 return;
00355 if ((n != -2 && n < 2) || !first_crule) {
00356
00357 rule->next = first_crule;
00358 first_crule = rule;
00359 } else {
00360
00361 for (ct = 1, tmp = first_crule; tmp && tmp->next;
00362 tmp = tmp->next, ct++)
00363 if ((((ct + 1) >= n) && n != -2) || !tmp->next)
00364 break;
00365 if (tmp) {
00366 rule->next = tmp->next;
00367 tmp->next = rule;
00368 }
00369 }
00370 }
00371
00372
00378 static char *
00379 MakeUserHost(char *user, char *host)
00380 {
00381 static char maskbuf[HOSTLEN + USERLEN + 10] = "";
00382 if (snprintf
00383 (maskbuf, sizeof(maskbuf), "%s@%s", user ? user : "*",
00384 host ? host : "*") == 0)
00385 maskbuf[0] = '\0';
00386 return maskbuf;
00387 }
00388
00398 void
00399 UpdateCrule(CloneRule orig, CloneRule * rule)
00400 {
00401 HostClone *hc;
00402 UserClone *uc;
00403
00404 if (!rule)
00405 return;
00406
00407 for (hc = firstClone; hc; hc = hc->next) {
00408 if (
00409 (hc->trigger != orig.trigger
00410 && hc->trigger != DEFHOSTCLONETRIGGER)
00411 || (hc->flags != DEFCLONEFLAGS && hc->flags != orig.flags))
00412 continue;
00413
00414 if (!match(rule->mask, MakeUserHost("*", hc->host))) {
00415 if (rule->trigger > 1)
00416 hc->trigger = rule->trigger;
00417 else
00418 hc->trigger = DEFHOSTCLONETRIGGER;
00419 hc->flags = rule->flags;
00420 }
00421 for (uc = hc->firstUser; uc; uc = uc->next) {
00422 if (uc->trigger != orig.utrigger
00423 && uc->trigger != DEFUSERCLONETRIGGER) continue;
00424 if (!match(rule->mask, MakeUserHost(uc->user, hc->host))) {
00425
00426 if (rule->trigger > 1)
00427 hc->trigger = rule->trigger;
00428 else
00429 hc->trigger = DEFHOSTCLONETRIGGER;
00430 if (rule->utrigger > 1)
00431 uc->trigger = rule->utrigger;
00432 else
00433 uc->trigger = DEFUSERCLONETRIGGER;
00434 hc->flags = rule->flags;
00435 }
00436 }
00437 }
00438 }
00439
00443 void
00444 RemoveCrule(CloneRule * zap)
00445 {
00446 CloneRule *tmp, *rule;
00447 for (rule = first_crule, tmp = NULL; rule; rule = rule->next) {
00448 if (rule == zap) {
00449 if (tmp)
00450 tmp->next = rule->next;
00451 else
00452 first_crule = rule->next;
00453 return;
00454 } else
00455 tmp = rule;
00456 }
00457 }
00458
00462 void
00463 initCloneData(HostClone * hc)
00464 {
00465 hc->host[0] = 0;
00466 hc->firstUser = hc->lastUser = NULL;
00467 hc->trigger = DEFHOSTCLONETRIGGER;
00468 hc->clones = 0;
00469 hc->flags = DEFCLONEFLAGS;
00470 hc->next = hc->previous = hc->hashnext = hc->hashprev = NULL;
00471 }
00472
00485 int
00486 addClone(char *nick, char *user, char *host)
00487 {
00488 HostClone *hc;
00489 struct pending_alert *pA;
00490 HashKeyVal hashEnt;
00491 UserClone *uc;
00492 CloneRule *rule;
00493 int user_alert = 0, host_alert = 0;
00494
00495 hc = getCloneData(host);
00496 if (!hc) {
00497 hc = (HostClone *) oalloc(sizeof(HostClone));
00498 initCloneData(hc);
00499 if ((rule = GetCruleMatch(MakeUserHost(user, host)))) {
00500 if (rule->trigger > 1)
00501 hc->trigger = rule->trigger;
00502 hc->flags = rule->flags;
00503 }
00504 strcpy(hc->host, host);
00505 hc->clones = 1;
00506 if (!firstClone) {
00507 firstClone = hc;
00508 hc->previous = NULL;
00509 } else {
00510 lastClone->next = hc;
00511 hc->previous = lastClone;
00512 }
00513 lastClone = hc;
00514 hc->next = NULL;
00515
00516 hashEnt = getHashKey(host) % CLONEHASHSIZE;
00517 if (!CloneHash[hashEnt].clone) {
00518 CloneHash[hashEnt].clone = hc;
00519 hc->hashprev = NULL;
00520 } else {
00521 CloneHash[hashEnt].lastclone->hashnext = hc;
00522 hc->hashprev = CloneHash[hashEnt].lastclone;
00523 }
00524 CloneHash[hashEnt].lastclone = hc;
00525 hc->hashnext = NULL;
00526 } else
00527 hc->clones++;
00528
00529 uc = addUserClone(hc, user);
00530 if (hc->flags & CLONE_IGNOREFLAG)
00531 return 0;
00532
00533 if (hc->clones >= hc->trigger || uc->clones >= uc->trigger) {
00534 if (hc->flags & CLONE_KILLFLAG) {
00535 if (!(rule = GetCruleMatch(MakeUserHost(user, host)))
00536 || !rule->kill_msg)
00537 sSend(":%s KILL %s :%s!%s (Cloning is not allowed on "
00538 NETWORK ".)", NickServ, nick, services[1].host,
00539 NickServ);
00540 else
00541 sSend(":%s KILL %s :%s!%s (%s)", NickServ, nick,
00542 services[1].host, NickServ, rule->kill_msg);
00543 delClone(user, host);
00544 return 1;
00545 } else {
00546 if ((rule = GetCruleMatch(MakeUserHost(user, host)))
00547 && rule->warn_msg)
00548 if (uc->clones == uc->trigger + 1
00549 || hc->clones == hc->trigger + 1)
00550 sSend(":%s NOTICE #%s :%s", OperServ, host,
00551 rule->warn_msg);
00552 }
00553 }
00554 if (uc->clones >= uc->trigger && !(uc->uflags & CLONE_ALERT)) {
00555 uc->uflags &= ~(CLONE_OK);
00556 uc->uflags |= CLONE_ALERT;
00557 user_alert = 1;
00558 }
00559
00560 if (hc->clones >= hc->trigger
00561 && !(hc->flags & CLONE_ALERT))
00562 {
00563 hc->flags &= ~(CLONE_OK);
00564 hc->flags |= CLONE_ALERT;
00565 host_alert = 1;
00566 }
00567
00568 pA = find_palert(hc);
00569
00570 if (pA) {
00571 pA->signon_ct++;
00572 pA->signon_ct_r++;
00573 }
00574
00575 if (user_alert || host_alert) {
00576 if (!pA) {
00577 pA = make_palert();
00578 add_palert(pA);
00579 pA->hc = hc;
00580 pA->firstTime = time(NULL);
00581 pA->lastAlert = 0;
00582 pA->signon_ct = pA->signoff_ct = 0;
00583 pA->signon_ct_r = pA->signoff_ct_r = 0;
00584 }
00585
00586 if (user_alert)
00587 pA->ua = 1;
00588 if (host_alert)
00589 pA->ha = 1;
00590 }
00591
00592 (void)updateCloneAlerts(0);
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 return 0;
00605 }
00606
00613 UserClone *
00614 addUserClone(HostClone * hc, char *user)
00615 {
00616 UserClone *uc = getUserCloneData(hc, user);
00617 CloneRule *rule;
00618
00619 if (!uc) {
00620 uc = (UserClone *) oalloc(sizeof(UserClone));
00621 uc->user[0] = 0;
00622 uc->clones = 1;
00623 uc->trigger = DEFUSERCLONETRIGGER;
00624 if ((rule = GetCruleMatch(MakeUserHost(user, hc->host)))) {
00625 if (rule->utrigger > 0)
00626 uc->trigger = rule->utrigger;
00632 if (hc->trigger == DEFHOSTCLONETRIGGER
00633 && hc->flags == DEFCLONEFLAGS) {
00634 if (rule->trigger > 1)
00635 hc->trigger = rule->trigger;
00636 hc->flags = rule->flags;
00637 }
00638 }
00639 strcpy(uc->user, user);
00640
00641 if (!hc->firstUser) {
00642 hc->firstUser = uc;
00643 uc->previous = NULL;
00644 } else {
00645 hc->lastUser->next = uc;
00646 uc->previous = hc->lastUser;
00647 }
00648 hc->lastUser = uc;
00649 uc->next = NULL;
00650 } else
00651 uc->clones++;
00652
00653 if (uc->clones >= uc->trigger)
00654 return uc;
00655 return uc;
00656 }
00657
00662 void
00663 delClone(char *user, char *host)
00664 {
00665 HostClone *hc = getCloneData(host);
00666 if (hc) {
00667 UserClone *uc = getUserCloneData(hc, user);
00668 if (uc) {
00669 hc->clones--;
00670 uc->clones--;
00671
00672 if (!uc->clones)
00673 delUserClone(hc, uc);
00674 if (hc->clones) {
00675 struct pending_alert* pA = find_palert(hc);
00676
00677 if (pA) {
00678 pA->signoff_ct++;
00679 pA->signoff_ct_r++;
00680 if ((hc->clones < hc->trigger &&
00681 uc->clones < uc->trigger) &&
00682 (CTime - pA->firstTime) > 30)
00683 {
00684 remove_palert(pA);
00685 free_palert(pA);
00686 uc->uflags &= ~CLONE_ALERT;
00687 }
00688 }
00689 }
00690
00691 if (!hc->clones) {
00692 HashKeyVal hashEnt;
00693 HostClone *tmp;
00694 struct pending_alert* pA = find_palert(hc);
00695
00696 if (pA) {
00697 remove_palert(pA);
00698 free_palert(pA);
00699 hc->flags &= ~CLONE_ALERT;
00700 }
00701
00702 if (hc->previous)
00703 hc->previous->next = hc->next;
00704 else
00705 firstClone = hc->next;
00706 if (hc->next)
00707 hc->next->previous = hc->previous;
00708 else
00709 lastClone = hc->previous;
00710 hashEnt = getHashKey(hc->host) % CLONEHASHSIZE;
00711 for (tmp = CloneHash[hashEnt].clone; tmp;
00712 tmp = tmp->hashnext) {
00713 if (tmp == hc) {
00714 if (hc->hashprev)
00715 hc->hashprev->hashnext = hc->hashnext;
00716 else
00717 CloneHash[hashEnt].clone = hc->hashnext;
00718 if (hc->hashnext)
00719 hc->hashnext->hashprev = hc->hashprev;
00720 else
00721 CloneHash[hashEnt].lastclone = hc->hashprev;
00722 }
00723 }
00724 FREE(hc);
00725 }
00726 }
00727 }
00728 }
00729
00733 void
00734 delUserClone(HostClone * hc, UserClone * uc)
00735 {
00736 if (uc->previous)
00737 uc->previous->next = uc->next;
00738 else
00739 hc->firstUser = uc->next;
00740 if (uc->next)
00741 uc->next->previous = uc->previous;
00742 else
00743 hc->lastUser = uc->previous;
00744
00745 FREE(uc);
00746 }
00747
00751 HostClone *
00752 getCloneData(char *host)
00753 {
00754 HashKeyVal hashEnt;
00755 hashEnt = getHashKey(host) % CLONEHASHSIZE;
00756 if (!CloneHash[hashEnt].clone)
00757 return NULL;
00758 else {
00759 HostClone *tmp;
00760 for (tmp = CloneHash[hashEnt].clone; tmp; tmp = tmp->hashnext) {
00761 if (!strcasecmp(host, tmp->host))
00762 return tmp;
00763 }
00764 return NULL;
00765 }
00766 }
00767
00772 UserClone *
00773 getUserCloneData(HostClone * hc, char *user)
00774 {
00775 UserClone *tmp;
00776
00777 for (tmp = hc->firstUser; tmp; tmp = tmp->next) {
00778 if (!strcasecmp(tmp->user, user))
00779 return tmp;
00780 }
00781 return NULL;
00782 }
00783
00784