unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
antirandom.c (21862B)
1 /* 2 * IRC - Internet Relay Chat, antirandom.c 3 * (C) Copyright 2004-2016, Bram Matthys (Syzop) <syzop@vulnscan.org> 4 * 5 * Contains ideas from Keith Dunnett <keith@dunnett.org> 6 * Most of the detection mechanisms come from SpamAssassin FVGT_Tripwire. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 1, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 #include "unrealircd.h" 24 25 ModuleHeader MOD_HEADER 26 = { 27 "antirandom", 28 "1.5", 29 "Detect and ban users with random names", 30 "UnrealIRCd Team", 31 "unrealircd-6", 32 }; 33 34 #ifndef MAX 35 #define MAX(x,y) ((x) > (y) ? (x) : (y)) 36 #endif 37 38 /* "<char1><char2>" followed by "<rest>" */ 39 static char *triples_txt[] = { 40 "aj", "fqtvxz", 41 "aq", "deghjkmnprtxyz", 42 "av", "bfhjqwxz", 43 "az", "jwx", 44 "bd", "bghjkmpqvxz", 45 "bf", "bcfgjknpqvwxyz", 46 "bg", "bdfghjkmnqstvxz", 47 "bh", "bfhjkmnqvwxz", 48 "bj", "bcdfghjklmpqtvwxyz", 49 "bk", "dfjkmqrvwxyz", 50 "bl", "bgpqwxz", 51 "bm", "bcdflmnqz", 52 "bn", "bghjlmnpqtvwx", 53 "bp", "bfgjknqvxz", 54 "bq", "bcdefghijklmnopqrstvwxyz", 55 "bt", "dgjkpqtxz", 56 "bv", "bfghjklnpqsuvwxz", 57 "bw", "bdfjknpqsuwxyz", 58 "bx", "abcdfghijklmnopqtuvwxyz", 59 "bz", "bcdfgjklmnpqrstvwxz", 60 "cb", "bfghjkpqyz", 61 "cc", "gjqxz", 62 "cd", "hjkqvwxz", 63 "cf", "gjknqvwyz", 64 "cg", "bdfgjkpqvz", 65 "cl", "fghjmpqxz", 66 "cm", "bjkqv", 67 "cn", "bghjkpqwxz", 68 "cp", "gjkvxyz", 69 "cq", "abcdefghijklmnopqsvwxyz", 70 "cr", "gjqx", 71 "cs", "gjxz", 72 "cv", "bdfghjklmnquvwxyz", 73 "cx", "abdefghjklmnpqrstuvwxyz", 74 "cy", "jqy", 75 "cz", "bcdfghjlpqrtvwxz", 76 "db", "bdgjnpqtxz", 77 "dc", "gjqxz", 78 "dd", "gqz", 79 "df", "bghjknpqvxyz", 80 "dg", "bfgjqvxz", 81 "dh", "bfkmnqwxz", 82 "dj", "bdfghjklnpqrwxz", 83 "dk", "cdhjkpqrtuvwxz", 84 "dl", "bfhjknqwxz", 85 "dm", "bfjnqw", 86 "dn", "fgjkmnpqvwz", 87 "dp", "bgjkqvxz", 88 "dq", "abcefghijkmnopqtvwxyz", 89 "dr", "bfkqtvx", 90 "dt", "qtxz", 91 "dv", "bfghjknqruvwyz", 92 "dw", "cdfjkmnpqsvwxz", 93 "dx", "abcdeghjklmnopqrsuvwxyz", 94 "dy", "jyz", 95 "dz", "bcdfgjlnpqrstvxz", 96 "eb", "jqx", 97 "eg", "cjvxz", 98 "eh", "hxz", 99 "ej", "fghjpqtwxyz", 100 "ek", "jqxz", 101 "ep", "jvx", 102 "eq", "bcghijkmotvxyz", 103 "ev", "bfpq", 104 "fc", "bdjkmnqvxz", 105 "fd", "bgjklqsvyz", 106 "fg", "fgjkmpqtvwxyz", 107 "fh", "bcfghjkpqvwxz", 108 "fj", "bcdfghijklmnpqrstvwxyz", 109 "fk", "bcdfghjkmpqrstvwxz", 110 "fl", "fjkpqxz", 111 "fm", "dfhjlmvwxyz", 112 "fn", "bdfghjklnqrstvwxz", 113 "fp", "bfjknqtvwxz", 114 "fq", "abcefghijklmnopqrstvwxyz", 115 "fr", "nqxz", 116 "fs", "gjxz", 117 "ft", "jqx", 118 "fv", "bcdfhjklmnpqtuvwxyz", 119 "fw", "bcfgjklmpqstuvwxyz", 120 "fx", "bcdfghjklmnpqrstvwxyz", 121 "fy", "ghjpquvxy", 122 "fz", "abcdfghjklmnpqrtuvwxyz", 123 "gb", "bcdknpqvwx", 124 "gc", "gjknpqwxz", 125 "gd", "cdfghjklmqtvwxz", 126 "gf", "bfghjkmnpqsvwxyz", 127 "gg", "jkqvxz", 128 "gj", "bcdfghjklmnpqrstvwxyz", 129 "gk", "bcdfgjkmpqtvwxyz", 130 "gl", "fgjklnpqwxz", 131 "gm", "dfjkmnqvxz", 132 "gn", "jkqvxz", 133 "gp", "bjknpqtwxyz", 134 "gq", "abcdefghjklmnopqrsvwxyz", 135 "gr", "jkqt", 136 "gt", "fjknqvx", 137 "gu", "qwx", 138 "gv", "bcdfghjklmpqstvwxyz", 139 "gw", "bcdfgjknpqtvwxz", 140 "gx", "abcdefghjklmnopqrstvwxyz", 141 "gy", "jkqxy", 142 "gz", "bcdfgjklmnopqrstvxyz", 143 "hb", "bcdfghjkqstvwxz", 144 "hc", "cjknqvwxz", 145 "hd", "fgjnpvz", 146 "hf", "bfghjkmnpqtvwxyz", 147 "hg", "bcdfgjknpqsxyz", 148 "hh", "bcgklmpqrtvwxz", 149 "hj", "bcdfgjkmpqtvwxyz", 150 "hk", "bcdgkmpqrstvwxz", 151 "hl", "jxz", 152 "hm", "dhjqrvwxz", 153 "hn", "jrxz", 154 "hp", "bjkmqvwxyz", 155 "hq", "abcdefghijklmnopqrstvwyz", 156 "hr", "cjqx", 157 "hs", "jqxz", 158 "hv", "bcdfgjklmnpqstuvwxz", 159 "hw", "bcfgjklnpqsvwxz", 160 "hx", "abcdefghijklmnopqrstuvwxyz", 161 "hz", "bcdfghjklmnpqrstuvwxz", 162 "ib", "jqx", 163 "if", "jqvwz", 164 "ih", "bgjqx", 165 "ii", "bjqxy", 166 "ij", "cfgqxy", 167 "ik", "bcfqx", 168 "iq", "cdefgjkmnopqtvxyz", 169 "iu", "hiwxy", 170 "iv", "cfgmqx", 171 "iw", "dgjkmnpqtvxz", 172 "ix", "jkqrxz", 173 "iy", "bcdfghjklpqtvwx", 174 "jb", "bcdghjklmnopqrtuvwxyz", 175 "jc", "cfgjkmnopqvwxy", 176 "jd", "cdfghjlmnpqrtvwx", 177 "jf", "abcdfghjlnopqrtuvwxyz", 178 "jg", "bcdfghijklmnopqstuvwxyz", 179 "jh", "bcdfghjklmnpqrxyz", 180 "jj", "bcdfghjklmnopqrstuvwxyz", 181 "jk", "bcdfghjknqrtwxyz", 182 "jl", "bcfghjmnpqrstuvwxyz", 183 "jm", "bcdfghiklmnqrtuvwyz", 184 "jn", "bcfjlmnpqsuvwxz", 185 "jp", "bcdfhijkmpqstvwxyz", 186 "jq", "abcdefghijklmnopqrstuvwxyz", 187 "jr", "bdfhjklpqrstuvwxyz", 188 "js", "bfgjmoqvxyz", 189 "jt", "bcdfghjlnpqrtvwxz", 190 "jv", "abcdfghijklpqrstvwxyz", 191 "jw", "bcdefghijklmpqrstuwxyz", 192 "jx", "abcdefghijklmnopqrstuvwxyz", 193 "jy", "bcdefghjkpqtuvwxyz", 194 "jz", "bcdfghijklmnopqrstuvwxyz", 195 "kb", "bcdfghjkmqvwxz", 196 "kc", "cdfgjknpqtwxz", 197 "kd", "bfghjklmnpqsvwxyz", 198 "kf", "bdfghjkmnpqsvwxyz", 199 "kg", "cghjkmnqtvwxyz", 200 "kh", "cfghjkqx", 201 "kj", "bcdfghjkmnpqrstwxyz", 202 "kk", "bcdfgjmpqswxz", 203 "kl", "cfghlmqstwxz", 204 "km", "bdfghjknqrstwxyz", 205 "kn", "bcdfhjklmnqsvwxz", 206 "kp", "bdfgjkmpqvxyz", 207 "kq", "abdefghijklmnopqrstvwxyz", 208 "kr", "bcdfghjmqrvwx", 209 "ks", "jqx", 210 "kt", "cdfjklqvx", 211 "ku", "qux", 212 "kv", "bcfghjklnpqrstvxyz", 213 "kw", "bcdfgjklmnpqsvwxz", 214 "kx", "abcdefghjklmnopqrstuvwxyz", 215 "ky", "vxy", 216 "kz", "bcdefghjklmnpqrstuvwxyz", 217 "lb", "cdgkqtvxz", 218 "lc", "bqx", 219 "lg", "cdfgpqvxz", 220 "lh", "cfghkmnpqrtvx", 221 "lk", "qxz", 222 "ln", "cfjqxz", 223 "lp", "jkqxz", 224 "lq", "bcdefhijklmopqrstvwxyz", 225 "lr", "dfgjklmpqrtvwx", 226 "lv", "bcfhjklmpwxz", 227 "lw", "bcdfgjknqxz", 228 "lx", "bcdfghjklmnpqrtuwz", 229 "lz", "cdjptvxz", 230 "mb", "qxz", 231 "md", "hjkpvz", 232 "mf", "fkpqvwxz", 233 "mg", "cfgjnpqsvwxz", 234 "mh", "bchjkmnqvx", 235 "mj", "bcdfghjknpqrstvwxyz", 236 "mk", "bcfgklmnpqrvwxz", 237 "ml", "jkqz", 238 "mm", "qvz", 239 "mn", "fhjkqxz", 240 "mq", "bdefhjklmnopqtwxyz", 241 "mr", "jklqvwz", 242 "mt", "jkq", 243 "mv", "bcfghjklmnqtvwxz", 244 "mw", "bcdfgjklnpqsuvwxyz", 245 "mx", "abcefghijklmnopqrstvwxyz", 246 "mz", "bcdfghjkmnpqrstvwxz", 247 "nb", "hkmnqxz", 248 "nf", "bghqvxz", 249 "nh", "fhjkmqtvxz", 250 "nk", "qxz", 251 "nl", "bghjknqvwxz", 252 "nm", "dfghjkqtvwxz", 253 "np", "bdjmqwxz", 254 "nq", "abcdfghjklmnopqrtvwxyz", 255 "nr", "bfjkqstvx", 256 "nv", "bcdfgjkmnqswxz", 257 "nw", "dgjpqvxz", 258 "nx", "abfghjknopuyz", 259 "nz", "cfqrxz", 260 "oc", "fjvw", 261 "og", "qxz", 262 "oh", "fqxz", 263 "oj", "bfhjmqrswxyz", 264 "ok", "qxz", 265 "oq", "bcdefghijklmnopqrstvwxyz", 266 "ov", "bfhjqwx", 267 "oy", "qxy", 268 "oz", "fjpqtvx", 269 "pb", "fghjknpqvwz", 270 "pc", "gjq", 271 "pd", "bgjkvwxz", 272 "pf", "hjkmqtvwyz", 273 "pg", "bdfghjkmqsvwxyz", 274 "ph", "kqvx", 275 "pk", "bcdfhjklmpqrvx", 276 "pl", "ghkqvwx", 277 "pm", "bfhjlmnqvwyz", 278 "pn", "fjklmnqrtvwz", 279 "pp", "gqwxz", 280 "pq", "abcdefghijklmnopqstvwxyz", 281 "pr", "hjkqrwx", 282 "pt", "jqxz", 283 "pv", "bdfghjklquvwxyz", 284 "pw", "fjkmnpqsuvwxz", 285 "px", "abcdefghijklmnopqrstuvwxyz", 286 "pz", "bdefghjklmnpqrstuvwxyz", 287 "qa", "ceghkopqxy", 288 "qb", "bcdfghjklmnqrstuvwxyz", 289 "qc", "abcdfghijklmnopqrstuvwxyz", 290 "qd", "defghijklmpqrstuvwxyz", 291 "qe", "abceghjkmopquwxyz", 292 "qf", "abdfghijklmnopqrstuvwxyz", 293 "qg", "abcdefghijklmnopqrtuvwxz", 294 "qh", "abcdefghijklmnopqrstuvwxyz", 295 "qi", "efgijkmpwx", 296 "qj", "abcdefghijklmnopqrstuvwxyz", 297 "qk", "abcdfghijklmnopqrsuvwxyz", 298 "ql", "abcefghjklmnopqrtuvwxyz", 299 "qm", "bdehijklmnoqrtuvxyz", 300 "qn", "bcdefghijklmnoqrtuvwxyz", 301 "qo", "abcdefgijkloqstuvwxyz", 302 "qp", "abcdefghijkmnopqrsuvwxyz", 303 "qq", "bcdefghijklmnopstwxyz", 304 "qr", "bdefghijklmnoqruvwxyz", 305 "qs", "bcdefgijknqruvwxz", 306 "qt", "befghjklmnpqtuvwxz", 307 "qu", "cfgjkpwz", 308 "qv", "abdefghjklmnopqrtuvwxyz", 309 "qw", "bcdfghijkmnopqrstuvwxyz", 310 "qx", "abcdefghijklmnopqrstuvwxyz", 311 "qy", "abcdefghjklmnopqrstuvwxyz", 312 "qz", "abcdefghijklmnopqrstuvwxyz", 313 "rb", "fxz", 314 "rg", "jvxz", 315 "rh", "hjkqrxz", 316 "rj", "bdfghjklmpqrstvwxz", 317 "rk", "qxz", 318 "rl", "jnq", 319 "rp", "jxz", 320 "rq", "bcdefghijklmnopqrtvwxy", 321 "rr", "jpqxz", 322 "rv", "bcdfghjmpqrvwxz", 323 "rw", "bfgjklqsvxz", 324 "rx", "bcdfgjkmnopqrtuvwxz", 325 "rz", "djpqvxz", 326 "sb", "kpqtvxz", 327 "sd", "jqxz", 328 "sf", "bghjkpqw", 329 "sg", "cgjkqvwxz", 330 "sj", "bfghjkmnpqrstvwxz", 331 "sk", "qxz", 332 "sl", "gjkqwxz", 333 "sm", "fkqwxz", 334 "sn", "dhjknqvwxz", 335 "sq", "bfghjkmopstvwxz", 336 "sr", "jklqrwxz", 337 "sv", "bfhjklmnqtwxyz", 338 "sw", "jkpqvwxz", 339 "sx", "bcdefghjklmnopqrtuvwxyz", 340 "sy", "qxy", 341 "sz", "bdfgjpqsvxz", 342 "tb", "cghjkmnpqtvwx", 343 "tc", "jnqvx", 344 "td", "bfgjkpqtvxz", 345 "tf", "ghjkqvwyz", 346 "tg", "bdfghjkmpqsx", 347 "tj", "bdfhjklmnpqstvwxyz", 348 "tk", "bcdfghjklmpqvwxz", 349 "tl", "jkqwxz", 350 "tm", "bknqtwxz", 351 "tn", "fhjkmqvwxz", 352 "tp", "bjpqvwxz", 353 "tq", "abdefhijklmnopqrstvwxyz", 354 "tr", "gjqvx", 355 "tv", "bcfghjknpquvwxz", 356 "tw", "bcdfjknqvz", 357 "tx", "bcdefghjklmnopqrsuvwxz", 358 "tz", "jqxz", 359 "uc", "fjmvx", 360 "uf", "jpqvx", 361 "ug", "qvx", 362 "uh", "bcgjkpvxz", 363 "uj", "wbfghklmqvwx", 364 "uk", "fgqxz", 365 "uq", "bcdfghijklmnopqrtwxyz", 366 "uu", "fijkqvwyz", 367 "uv", "bcdfghjkmpqtwxz", 368 "uw", "dgjnquvxyz", 369 "ux", "jqxz", 370 "uy", "jqxyz", 371 "uz", "fgkpqrx", 372 "vb", "bcdfhijklmpqrtuvxyz", 373 "vc", "bgjklnpqtvwxyz", 374 "vd", "bdghjklnqvwxyz", 375 "vf", "bfghijklmnpqtuvxz", 376 "vg", "bcdgjkmnpqtuvwxyz", 377 "vh", "bcghijklmnpqrtuvwxyz", 378 "vj", "abcdfghijklmnpqrstuvwxyz", 379 "vk", "bcdefgjklmnpqruvwxyz", 380 "vl", "hjkmpqrvwxz", 381 "vm", "bfghjknpquvxyz", 382 "vn", "bdhjkmnpqrtuvwxz", 383 "vp", "bcdeghjkmopqtuvwyz", 384 "vq", "abcdefghijklmnopqrstvwxyz", 385 "vr", "fghjknqrtvwxz", 386 "vs", "dfgjmqz", 387 "vt", "bdfgjklmnqtx", 388 "vu", "afhjquwxy", 389 "vv", "cdfghjkmnpqrtuwxz", 390 "vw", "abcdefghijklmnopqrtuvwxyz", 391 "vx", "abcefghjklmnopqrstuvxyz", 392 "vy", "oqx", 393 "vz", "abcdefgjklmpqrstvwxyz", 394 "wb", "bdfghjpqtvxz", 395 "wc", "bdfgjkmnqvwx", 396 "wd", "dfjpqvxz", 397 "wf", "cdghjkmqvwxyz", 398 "wg", "bcdfgjknpqtvwxyz", 399 "wh", "cdghjklpqvwxz", 400 "wj", "bfghijklmnpqrstvwxyz", 401 "wk", "cdfgjkpqtuvxz", 402 "wl", "jqvxz", 403 "wm", "dghjlnqtvwxz", 404 "wp", "dfgjkpqtvwxz", 405 "wq", "abcdefghijklmnopqrstvwxyz", 406 "wr", "cfghjlmpqwx", 407 "wt", "bdgjlmnpqtvx", 408 "wu", "aikoquvwy", 409 "wv", "bcdfghjklmnpqrtuvwxyz", 410 "ww", "bcdgkpqstuvxyz", 411 "wx", "abcdefghijklmnopqrstuvwxz", 412 "wy", "jquwxy", 413 "wz", "bcdfghjkmnopqrstuvwxz", 414 "xa", "ajoqy", 415 "xb", "bcdfghjkmnpqsvwxz", 416 "xc", "bcdgjkmnqsvwxz", 417 "xd", "bcdfghjklnpqstuvwxyz", 418 "xf", "bcdfghjkmnpqtvwxyz", 419 "xg", "bcdfghjkmnpqstvwxyz", 420 "xh", "cdfghjkmnpqrstvwxz", 421 "xi", "jkqy", 422 "xj", "abcdefghijklmnopqrstvwxyz", 423 "xk", "abcdfghjkmnopqrstuvwxyz", 424 "xl", "bcdfghjklmnpqrvwxz", 425 "xm", "bcdfghjknpqvwxz", 426 "xn", "bcdfghjklmnpqrvwxyz", 427 "xp", "bcfjknpqvxz", 428 "xq", "abcdefghijklmnopqrstvwxyz", 429 "xr", "bcdfghjklnpqrsvwyz", 430 "xs", "bdfgjmnqrsvxz", 431 "xt", "jkpqvwxz", 432 "xu", "fhjkquwx", 433 "xv", "bcdefghjklmnpqrsuvwxyz", 434 "xw", "bcdfghjklmnpqrtuvwxyz", 435 "xx", "bcdefghjkmnpqrstuwyz", 436 "xy", "jxy", 437 "xz", "abcdefghjklmnpqrstuvwxyz", 438 "yb", "cfghjmpqtvwxz", 439 "yc", "bdfgjmpqsvwx", 440 "yd", "chjkpqvwx", 441 "yf", "bcdghjmnpqsvwx", 442 "yg", "cfjkpqtxz", 443 "yh", "bcdfghjkpqx", 444 "yi", "hjqwxy", 445 "yj", "bcdfghjklmnpqrstvwxyz", 446 "yk", "bcdfgpqvwxz", 447 "ym", "dfgjqvxz", 448 "yp", "bcdfgjkmqxz", 449 "yq", "abcdefghijklmnopqrstvwxyz", 450 "yr", "jqx", 451 "yt", "bcfgjnpqx", 452 "yv", "bcdfghjlmnpqstvwxz", 453 "yw", "bfgjklmnpqstuvwxz", 454 "yx", "bcdfghjknpqrstuvwxz", 455 "yy", "bcdfghjklpqrstvwxz", 456 "yz", "bcdfjklmnpqtvwx", 457 "zb", "dfgjklmnpqstvwxz", 458 "zc", "bcdfgjmnpqstvwxy", 459 "zd", "bcdfghjklmnpqstvwxy", 460 "zf", "bcdfghijkmnopqrstvwxyz", 461 "zg", "bcdfgjkmnpqtvwxyz", 462 "zh", "bcfghjlpqstvwxz", 463 "zj", "abcdfghjklmnpqrstuvwxyz", 464 "zk", "bcdfghjklmpqstvwxz", 465 "zl", "bcdfghjlnpqrstvwxz", 466 "zm", "bdfghjklmpqstvwxyz", 467 "zn", "bcdfghjlmnpqrstuvwxz", 468 "zp", "bcdfhjklmnpqstvwxz", 469 "zq", "abcdefghijklmnopqrstvwxyz", 470 "zr", "bcfghjklmnpqrstvwxyz", 471 "zs", "bdfgjmnqrsuwxyz", 472 "zt", "bcdfgjkmnpqtuvwxz", 473 "zu", "ajqx", 474 "zv", "bcdfghjklmnpqrstuvwxyz", 475 "zw", "bcdfghjklmnpqrstuvwxyz", 476 "zx", "abcdefghijklmnopqrstuvwxyz", 477 "zy", "fxy", 478 "zz", "cdfhjnpqrvx", 479 NULL, NULL 480 }; 481 482 /* Used for parsed triples: */ 483 #define TRIPLES_REST_SIZE 32 484 typedef struct Triples Triples; 485 struct Triples { 486 Triples *next; 487 char two[3]; 488 char rest[TRIPLES_REST_SIZE]; 489 }; 490 491 Triples *triples = NULL; 492 493 struct { 494 int threshold; 495 int ban_action; 496 int ban_reason; 497 int ban_time; 498 } req; 499 500 struct { 501 int threshold; 502 BanAction ban_action; 503 char *ban_reason; 504 long ban_time; 505 int convert_to_lowercase; 506 int show_failedconnects; 507 SecurityGroup *except; 508 } cfg; 509 510 /* Forward declarations */ 511 static int init_stuff(void); 512 static int init_triples(void); 513 static void free_stuff(void); 514 static void free_config(void); 515 int antirandom_config_test(ConfigFile *, ConfigEntry *, int, int *); 516 int antirandom_config_run(ConfigFile *, ConfigEntry *, int); 517 int antirandom_config_posttest(int *); 518 int antirandom_preconnect(Client *client); 519 static int is_exempt(Client *client); 520 521 MOD_TEST() 522 { 523 memset(&req, 0, sizeof(req)); 524 memset(&cfg, 0, sizeof(cfg)); 525 HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, antirandom_config_test); 526 HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, antirandom_config_posttest); 527 return MOD_SUCCESS; 528 } 529 530 MOD_INIT() 531 { 532 MARK_AS_OFFICIAL_MODULE(modinfo); 533 if (!init_stuff()) 534 { 535 config_error("antirandom: loading aborted"); 536 free_stuff(); 537 return MOD_FAILED; 538 } 539 HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0, antirandom_preconnect); 540 HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, antirandom_config_run); 541 542 /* Some default values: */ 543 cfg.convert_to_lowercase = 1; 544 cfg.except = safe_alloc(sizeof(SecurityGroup)); 545 cfg.except->webirc = 1; 546 547 return MOD_SUCCESS; 548 } 549 550 MOD_LOAD() 551 { 552 return MOD_SUCCESS; 553 } 554 555 MOD_UNLOAD() 556 { 557 free_stuff(); 558 free_config(); 559 return MOD_SUCCESS; 560 } 561 562 static void free_config(void) 563 { 564 safe_free(cfg.ban_reason); 565 free_security_group(cfg.except); 566 memset(&cfg, 0, sizeof(cfg)); /* needed! */ 567 } 568 569 int antirandom_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) 570 { 571 int errors = 0; 572 ConfigEntry *cep; 573 574 if (type != CONFIG_SET) 575 return 0; 576 577 /* We are only interrested in set::antirandom... */ 578 if (!ce || !ce->name || strcmp(ce->name, "antirandom")) 579 return 0; 580 581 for (cep = ce->items; cep; cep = cep->next) 582 { 583 if (!strcmp(cep->name, "except")) 584 { 585 test_match_block(cf, cep, &errors); 586 } else 587 if (!strcmp(cep->name, "except-hosts")) 588 { 589 } else 590 if (!strcmp(cep->name, "except-webirc")) 591 { 592 /* This should normally be UNDER the generic 'set::antirandom::%s with no value' 593 * stuff but I put it here because people may think it's a hostlist and then 594 * the error can be a tad confusing. -- Syzop 595 */ 596 if (!cep->value) 597 { 598 config_error("%s:%i: set::antirandom::except-webirc should be 'yes' or 'no'", 599 cep->file->filename, cep->line_number); 600 errors++; 601 } 602 } else 603 if (!cep->value) 604 { 605 config_error("%s:%i: set::antirandom::%s with no value", 606 cep->file->filename, cep->line_number, cep->name); 607 errors++; 608 } else 609 if (!strcmp(cep->name, "threshold")) 610 { 611 req.threshold = 1; 612 } else 613 if (!strcmp(cep->name, "ban-action")) 614 { 615 if (!banact_stringtoval(cep->value)) 616 { 617 config_error("%s:%i: set::antirandom::ban-action: unknown action '%s'", 618 cep->file->filename, cep->line_number, cep->value); 619 errors++; 620 } else 621 req.ban_action = 1; 622 } else 623 if (!strcmp(cep->name, "ban-reason")) 624 { 625 req.ban_reason = 1; 626 } else 627 if (!strcmp(cep->name, "ban-time")) 628 { 629 req.ban_time = 1; 630 } else 631 if (!strcmp(cep->name, "convert-to-lowercase")) 632 { 633 } else 634 if (!strcmp(cep->name, "show-failedconnects")) 635 { 636 } else 637 { 638 config_error("%s:%i: unknown directive set::antirandom::%s", 639 cep->file->filename, cep->line_number, cep->name); 640 errors++; 641 } 642 } 643 *errs = errors; 644 return errors ? -1 : 1; 645 } 646 647 int antirandom_config_run(ConfigFile *cf, ConfigEntry *ce, int type) 648 { 649 ConfigEntry *cep, *cep2; 650 651 if (type != CONFIG_SET) 652 return 0; 653 654 /* We are only interrested in set::antirandom... */ 655 if (!ce || !ce->name || strcmp(ce->name, "antirandom")) 656 return 0; 657 658 for (cep = ce->items; cep; cep = cep->next) 659 { 660 if (!strcmp(cep->name, "except")) 661 { 662 conf_match_block(cf, cep, &cfg.except); 663 } else 664 if (!strcmp(cep->name, "except-hosts")) 665 { 666 /* backwards compatible with set::antirandom::except */ 667 for (cep2 = cep->items; cep2; cep2 = cep2->next) 668 unreal_add_masks(&cfg.except->mask, cep2); 669 } else 670 if (!strcmp(cep->name, "except-webirc")) 671 { 672 /* backwards compatible with set::antirandom::except */ 673 cfg.except->webirc = config_checkval(cep->value, CFG_YESNO); 674 } else 675 if (!strcmp(cep->name, "threshold")) 676 { 677 cfg.threshold = atoi(cep->value); 678 } else 679 if (!strcmp(cep->name, "ban-action")) 680 { 681 cfg.ban_action = banact_stringtoval(cep->value); 682 } else 683 if (!strcmp(cep->name, "ban-reason")) 684 { 685 safe_strdup(cfg.ban_reason, cep->value); 686 } else 687 if (!strcmp(cep->name, "ban-time")) 688 { 689 cfg.ban_time = config_checkval(cep->value, CFG_TIME); 690 } else 691 if (!strcmp(cep->name, "convert-to-lowercase")) 692 { 693 cfg.convert_to_lowercase = config_checkval(cep->value, CFG_YESNO); 694 } 695 if (!strcmp(cep->name, "show-failedconnects")) 696 { 697 cfg.show_failedconnects = config_checkval(cep->value, CFG_YESNO); 698 } 699 } 700 return 1; 701 } 702 703 int antirandom_config_posttest(int *errs) 704 { 705 int errors = 0; 706 707 if (!req.threshold) { config_error("set::antirandom::threshold missing"); errors++; } 708 if (!req.ban_action) { config_error("set::antirandom::ban-action missing"); errors++; } 709 if (!req.ban_time) { config_error("set::antirandom::ban-time missing"); errors++; } 710 if (!req.ban_reason) { config_error("set::antirandom::ban-reason missing"); errors++; } 711 712 *errs = errors; 713 return errors ? -1 : 1; 714 } 715 716 static int init_stuff(void) 717 { 718 if (!init_triples()) 719 return 0; 720 return 1; 721 } 722 723 /** Initializes the triples list. */ 724 static int init_triples(void) 725 { 726 char **s; 727 Triples *e, *last=NULL; 728 int cnt=0; 729 730 for (s=triples_txt; *s; s++) 731 { 732 cnt++; 733 e = safe_alloc(sizeof(Triples)); 734 if (strlen(*s) > 2) 735 { 736 config_error("init_triples: error parsing triples_txt, cnt=%d, item='%s' (length>2)", 737 cnt, *s); 738 return 0; 739 } 740 strcpy(e->two, *s); /* (SAFE) */ 741 s++; 742 if (!*s) 743 { 744 config_error("init_triples: error parsing triples_txt, cnt=%d, got NULL expected param", 745 cnt); 746 return 0; 747 } 748 if (strlen(*s) > TRIPLES_REST_SIZE-1) 749 { 750 config_error("init_triples: error parsing triples_txt, cnt=%d, item='%s' (length>%d)", 751 cnt, *s, TRIPLES_REST_SIZE-1); 752 return 0; 753 } 754 strcpy(e->rest, *s); /* (SAFE) */ 755 756 /* Append at end of list (to keep it in order, not importent yet, but..) */ 757 if (last) 758 last->next = e; 759 else 760 triples = e; /*(head)*/ 761 last = e; 762 } 763 return 1; 764 } 765 766 /** Run the actual tests over this string. 767 * There are 3 tests: 768 * - weird chars (not used) 769 * - sregexes (not used) 770 * - triples (three-letter combinations) 771 */ 772 static int internal_getscore(char *str) 773 { 774 Triples *t; 775 register char *s; 776 int score = 0; 777 int highest_vowels=0, highest_consonants=0, highest_digits=0; 778 int vowels=0, consonants=0, digits=0; 779 780 /* Fast digit/consonant/vowel checks... */ 781 for (s=str; *s; s++) 782 { 783 if ((*s >= '0') && (*s <= '9')) 784 digits++; 785 else { 786 highest_digits = MAX(highest_digits, digits); 787 digits = 0; 788 } 789 if (strchr("bcdfghjklmnpqrstvwxz", *s)) 790 consonants++; 791 else { 792 highest_consonants = MAX(highest_consonants, consonants); 793 consonants = 0; 794 } 795 if (strchr("aeiou", *s)) 796 vowels++; 797 else { 798 highest_vowels = MAX(highest_vowels, vowels); 799 vowels = 0; 800 } 801 } 802 803 digits = MAX(highest_digits, digits); 804 consonants = MAX(highest_consonants, consonants); 805 vowels = MAX(highest_vowels, vowels); 806 807 if (digits >= 5) 808 { 809 score += digits; 810 } 811 if (vowels >= 4) 812 { 813 score += vowels; 814 } 815 if (consonants >= 4) 816 { 817 score += consonants; 818 } 819 820 for (t=triples; t; t=t->next) 821 { 822 for (s=str; *s; s++) 823 if ((t->two[0] == s[0]) && (t->two[1] == s[1]) && s[2] && strchr(t->rest, s[2])) 824 { 825 score++; /* OK */ 826 } 827 } 828 829 830 831 return score; 832 } 833 834 /** Returns "spam score". 835 * @note a user is expected, do not call for anything else (eg: servers) 836 */ 837 static int get_spam_score(Client *client) 838 { 839 char *nick = client->name; 840 char *user = client->user->username; 841 char *gecos = client->info; 842 char nbuf[NICKLEN+1], ubuf[USERLEN+1], rbuf[REALLEN+1]; 843 int nscore, uscore, gscore, score; 844 845 if (cfg.convert_to_lowercase) 846 { 847 strtolower_safe(nbuf, nick, sizeof(nbuf)); 848 strtolower_safe(ubuf, user, sizeof(ubuf)); 849 strtolower_safe(rbuf, gecos, sizeof(rbuf)); 850 nick = nbuf; 851 user = ubuf; 852 gecos = rbuf; 853 } 854 855 nscore = internal_getscore(nick); 856 uscore = internal_getscore(user); 857 gscore = internal_getscore(gecos); 858 score = nscore + uscore + gscore; 859 860 return score; 861 } 862 863 int antirandom_preconnect(Client *client) 864 { 865 int score; 866 867 if (is_exempt(client)) 868 return HOOK_CONTINUE; 869 870 score = get_spam_score(client); 871 if (score > cfg.threshold) 872 { 873 if (cfg.ban_action == BAN_ACT_WARN) 874 { 875 unreal_log(ULOG_INFO, "antirandom", "ANTIRANDOM_DENIED_USER", client, 876 "[antirandom] would have denied access to user with score $score: $client.details:$client.user.realname", 877 log_data_integer("score", score)); 878 return HOOK_CONTINUE; 879 } 880 if (cfg.show_failedconnects) 881 { 882 unreal_log(ULOG_INFO, "antirandom", "ANTIRANDOM_DENIED_USER", client, 883 "[antirandom] denied access to user with score $score: $client.details:$client.user.realname", 884 log_data_integer("score", score)); 885 } 886 place_host_ban(client, cfg.ban_action, cfg.ban_reason, cfg.ban_time); 887 return HOOK_DENY; 888 } 889 return HOOK_CONTINUE; 890 } 891 892 static void free_stuff(void) 893 { 894 Triples *t, *t_next; 895 896 for (t=triples; t; t=t_next) 897 { 898 t_next = t->next; 899 safe_free(t); 900 } 901 triples = NULL; 902 } 903 904 /** Is this user exempt from antirandom interventions? */ 905 static int is_exempt(Client *client) 906 { 907 if (user_allowed_by_security_group(client, cfg.except)) 908 return 1; 909 910 if (find_tkl_exception(TKL_ANTIRANDOM, client)) 911 return 1; 912 913 /* Soft ban and logged in? */ 914 if (IsSoftBanAction(cfg.ban_action) && IsLoggedIn(client)) 915 return 1; 916 917 return 0; 918 }