unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
dccdeny.c (22831B)
1 /* 2 * IRC - Internet Relay Chat, src/modules/dccdeny.c 3 * (C) 2004-2019 The UnrealIRCd Team 4 * 5 * See file AUTHORS in IRC package for additional names of 6 * the programmers. 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 "dccdeny", 28 "6.0.2", 29 "command /dccdeny", 30 "UnrealIRCd Team", 31 "unrealircd-6", 32 }; 33 34 /* Variables */ 35 ConfigItem_deny_dcc *conf_deny_dcc = NULL; 36 ConfigItem_allow_dcc *conf_allow_dcc = NULL; 37 38 /* Forward declarions */ 39 int dccdeny_configtest_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *errs); 40 int dccdeny_configtest_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *errs); 41 int dccdeny_configrun_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type); 42 int dccdeny_configrun_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type); 43 int dccdeny_stats(Client *client, const char *para); 44 int dccdeny_dcc_denied(Client *client, const char *target, const char *realfile, const char *displayfile, ConfigItem_deny_dcc *dccdeny); 45 CMD_FUNC(cmd_dccdeny); 46 CMD_FUNC(cmd_undccdeny); 47 CMD_FUNC(cmd_svsfline); 48 int dccdeny_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype); 49 int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype); 50 int dccdeny_server_sync(Client *client); 51 static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, const char *filename); 52 static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, const char *filename); 53 static void DCCdeny_add(const char *filename, const char *reason, int type, int type2); 54 static void DCCdeny_del(ConfigItem_deny_dcc *deny); 55 static void dcc_wipe_services(void); 56 static const char *get_dcc_filename(const char *text); 57 static int can_dcc(Client *client, const char *target, Client *targetcli, const char *filename, const char **errmsg); 58 static int can_dcc_soft(Client *from, Client *to, const char *filename, const char **errmsg); 59 static void free_dcc_config_blocks(void); 60 void dccdeny_unload_free_all_conf_deny_dcc(ModData *m); 61 void dccdeny_unload_free_all_conf_allow_dcc(ModData *m); 62 ConfigItem_deny_dcc *find_deny_dcc(const char *name); 63 64 MOD_TEST() 65 { 66 HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, dccdeny_configtest_deny_dcc); 67 HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, dccdeny_configtest_allow_dcc); 68 return MOD_SUCCESS; 69 } 70 71 MOD_INIT() 72 { 73 MARK_AS_OFFICIAL_MODULE(modinfo); 74 LoadPersistentPointer(modinfo, conf_deny_dcc, dccdeny_unload_free_all_conf_deny_dcc); 75 LoadPersistentPointer(modinfo, conf_allow_dcc, dccdeny_unload_free_all_conf_allow_dcc); 76 HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, dccdeny_configrun_deny_dcc); 77 HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, dccdeny_configrun_allow_dcc); 78 CommandAdd(modinfo->handle, "DCCDENY", cmd_dccdeny, 2, CMD_USER); 79 CommandAdd(modinfo->handle, "UNDCCDENY", cmd_undccdeny, MAXPARA, CMD_USER); 80 CommandAdd(modinfo->handle, "SVSFLINE", cmd_svsfline, MAXPARA, CMD_SERVER); 81 HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, dccdeny_stats); 82 HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_USER, 0, dccdeny_can_send_to_user); 83 HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 0, dccdeny_can_send_to_channel); 84 HookAdd(modinfo->handle, HOOKTYPE_SERVER_SYNC, 0, dccdeny_server_sync); 85 HookAdd(modinfo->handle, HOOKTYPE_DCC_DENIED, 0, dccdeny_dcc_denied); 86 return MOD_SUCCESS; 87 } 88 89 MOD_LOAD() 90 { 91 return MOD_SUCCESS; 92 } 93 94 MOD_UNLOAD() 95 { 96 free_dcc_config_blocks(); 97 SavePersistentPointer(modinfo, conf_deny_dcc); 98 SavePersistentPointer(modinfo, conf_allow_dcc); 99 100 return MOD_SUCCESS; 101 } 102 103 int dccdeny_configtest_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) 104 { 105 ConfigEntry *cep; 106 int errors = 0; 107 char has_filename = 0, has_reason = 0, has_soft = 0; 108 109 /* We are only interested in deny dcc { } */ 110 if ((type != CONFIG_DENY) || strcmp(ce->value, "dcc")) 111 return 0; 112 113 for (cep = ce->items; cep; cep = cep->next) 114 { 115 if (config_is_blankorempty(cep, "deny dcc")) 116 { 117 errors++; 118 continue; 119 } 120 if (!strcmp(cep->name, "filename")) 121 { 122 if (has_filename) 123 { 124 config_warn_duplicate(cep->file->filename, 125 cep->line_number, "deny dcc::filename"); 126 continue; 127 } 128 has_filename = 1; 129 } 130 else if (!strcmp(cep->name, "reason")) 131 { 132 if (has_reason) 133 { 134 config_warn_duplicate(cep->file->filename, 135 cep->line_number, "deny dcc::reason"); 136 continue; 137 } 138 has_reason = 1; 139 } 140 else if (!strcmp(cep->name, "soft")) 141 { 142 if (has_soft) 143 { 144 config_warn_duplicate(cep->file->filename, 145 cep->line_number, "deny dcc::soft"); 146 continue; 147 } 148 has_soft = 1; 149 } 150 else 151 { 152 config_error_unknown(cep->file->filename, 153 cep->line_number, "deny dcc", cep->name); 154 errors++; 155 } 156 } 157 if (!has_filename) 158 { 159 config_error_missing(ce->file->filename, ce->line_number, 160 "deny dcc::filename"); 161 errors++; 162 } 163 if (!has_reason) 164 { 165 config_error_missing(ce->file->filename, ce->line_number, 166 "deny dcc::reason"); 167 errors++; 168 } 169 170 *errs = errors; 171 return errors ? -1 : 1; 172 } 173 174 int dccdeny_configtest_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) 175 { 176 ConfigEntry *cep; 177 int errors = 0, has_filename = 0, has_soft = 0; 178 179 /* We are only interested in allow dcc { } */ 180 if ((type != CONFIG_ALLOW) || strcmp(ce->value, "dcc")) 181 return 0; 182 183 for (cep = ce->items; cep; cep = cep->next) 184 { 185 if (config_is_blankorempty(cep, "allow dcc")) 186 { 187 errors++; 188 continue; 189 } 190 if (!strcmp(cep->name, "filename")) 191 { 192 if (has_filename) 193 { 194 config_warn_duplicate(cep->file->filename, 195 cep->line_number, "allow dcc::filename"); 196 continue; 197 } 198 has_filename = 1; 199 } 200 else if (!strcmp(cep->name, "soft")) 201 { 202 if (has_soft) 203 { 204 config_warn_duplicate(cep->file->filename, 205 cep->line_number, "allow dcc::soft"); 206 continue; 207 } 208 has_soft = 1; 209 } 210 else 211 { 212 config_error_unknown(cep->file->filename, cep->line_number, 213 "allow dcc", cep->name); 214 errors++; 215 } 216 } 217 if (!has_filename) 218 { 219 config_error_missing(ce->file->filename, ce->line_number, 220 "allow dcc::filename"); 221 errors++; 222 } 223 224 *errs = errors; 225 return errors ? -1 : 1; 226 } 227 228 int dccdeny_configrun_deny_dcc(ConfigFile *cf, ConfigEntry *ce, int type) 229 { 230 ConfigItem_deny_dcc *deny = NULL; 231 ConfigEntry *cep; 232 233 /* We are only interested in deny dcc { } */ 234 if ((type != CONFIG_DENY) || strcmp(ce->value, "dcc")) 235 return 0; 236 237 deny = safe_alloc(sizeof(ConfigItem_deny_dcc)); 238 for (cep = ce->items; cep; cep = cep->next) 239 { 240 if (!strcmp(cep->name, "filename")) 241 { 242 safe_strdup(deny->filename, cep->value); 243 } 244 else if (!strcmp(cep->name, "reason")) 245 { 246 safe_strdup(deny->reason, cep->value); 247 } 248 else if (!strcmp(cep->name, "soft")) 249 { 250 int x = config_checkval(cep->value,CFG_YESNO); 251 if (x == 1) 252 deny->flag.type = DCCDENY_SOFT; 253 } 254 } 255 if (!deny->reason) 256 { 257 if (deny->flag.type == DCCDENY_HARD) 258 safe_strdup(deny->reason, "Possible infected virus file"); 259 else 260 safe_strdup(deny->reason, "Possible executable content"); 261 } 262 AddListItem(deny, conf_deny_dcc); 263 return 0; 264 } 265 266 int dccdeny_configrun_allow_dcc(ConfigFile *cf, ConfigEntry *ce, int type) 267 { 268 ConfigItem_allow_dcc *allow = NULL; 269 ConfigEntry *cep; 270 271 /* We are only interested in allow dcc { } */ 272 if ((type != CONFIG_ALLOW) || strcmp(ce->value, "dcc")) 273 return 0; 274 275 allow = safe_alloc(sizeof(ConfigItem_allow_dcc)); 276 277 for (cep = ce->items; cep; cep = cep->next) 278 { 279 if (!strcmp(cep->name, "filename")) 280 safe_strdup(allow->filename, cep->value); 281 else if (!strcmp(cep->name, "soft")) 282 { 283 int x = config_checkval(cep->value,CFG_YESNO); 284 if (x) 285 allow->flag.type = DCCDENY_SOFT; 286 } 287 } 288 AddListItem(allow, conf_allow_dcc); 289 return 1; 290 } 291 292 /** Free allow dcc { } and deny dcc { } blocks, called on REHASH */ 293 void free_dcc_config_blocks(void) 294 { 295 ConfigItem_deny_dcc *d, *d_next; 296 ConfigItem_allow_dcc *a, *a_next; 297 298 for (d = conf_deny_dcc; d; d = d_next) 299 { 300 d_next = d->next; 301 if (d->flag.type2 == CONF_BAN_TYPE_CONF) 302 { 303 safe_free(d->filename); 304 safe_free(d->reason); 305 DelListItem(d, conf_deny_dcc); 306 safe_free(d); 307 } 308 } 309 for (a = conf_allow_dcc; a; a = a_next) 310 { 311 a_next = a->next; 312 if (a->flag.type2 == CONF_BAN_TYPE_CONF) 313 { 314 safe_free(a->filename); 315 DelListItem(a, conf_allow_dcc); 316 safe_free(a); 317 } 318 } 319 } 320 321 /** Free all deny dcc { } blocks - only called on permanent module unload (rare) */ 322 void dccdeny_unload_free_all_conf_deny_dcc(ModData *m) 323 { 324 ConfigItem_deny_dcc *d, *d_next; 325 326 for (d = conf_deny_dcc; d; d = d_next) 327 { 328 d_next = d->next; 329 safe_free(d->filename); 330 safe_free(d->reason); 331 DelListItem(d, conf_deny_dcc); 332 safe_free(d); 333 } 334 conf_deny_dcc = NULL; 335 } 336 337 /** Free all allow dcc { } blocks - only called on permanent module unload (rare) */ 338 void dccdeny_unload_free_all_conf_allow_dcc(ModData *m) 339 { 340 ConfigItem_allow_dcc *a, *a_next; 341 342 for (a = conf_allow_dcc; a; a = a_next) 343 { 344 a_next = a->next; 345 safe_free(a->filename); 346 DelListItem(a, conf_allow_dcc); 347 safe_free(a); 348 } 349 conf_allow_dcc = NULL; 350 } 351 352 353 /* Add a temporary dccdeny line 354 * 355 * parv[1] - file 356 * parv[2] - reason 357 */ 358 CMD_FUNC(cmd_dccdeny) 359 { 360 if (!MyUser(client)) 361 return; 362 363 if (!ValidatePermissionsForPath("server-ban:dccdeny",client,NULL,NULL,NULL)) 364 { 365 sendnumeric(client, ERR_NOPRIVILEGES); 366 return; 367 } 368 369 if ((parc < 2) || BadPtr(parv[2])) 370 { 371 sendnumeric(client, ERR_NEEDMOREPARAMS, "DCCDENY"); 372 return; 373 } 374 375 if (!find_deny_dcc(parv[1])) 376 { 377 unreal_log(ULOG_INFO, "dccdeny", "DCCDENY_ADD", client, 378 "[dccdeny] $client added a temporary DCCDENY for $file ($reason)", 379 log_data_string("file", parv[1]), 380 log_data_string("reason", parv[2])); 381 DCCdeny_add(parv[1], parv[2], DCCDENY_HARD, CONF_BAN_TYPE_TEMPORARY); 382 return; 383 } else 384 { 385 sendnotice(client, "*** %s already has a dccdeny", parv[1]); 386 } 387 } 388 389 /* Remove a temporary dccdeny line 390 * parv[1] - file/mask 391 */ 392 CMD_FUNC(cmd_undccdeny) 393 { 394 ConfigItem_deny_dcc *d; 395 396 if (!MyUser(client)) 397 return; 398 399 if (!ValidatePermissionsForPath("server-ban:dccdeny",client,NULL,NULL,NULL)) 400 { 401 sendnumeric(client, ERR_NOPRIVILEGES); 402 return; 403 } 404 405 if ((parc < 2) || BadPtr(parv[1])) 406 { 407 sendnumeric(client, ERR_NEEDMOREPARAMS, "UNDCCDENY"); 408 return; 409 } 410 411 if ((d = find_deny_dcc(parv[1])) && d->flag.type2 == CONF_BAN_TYPE_TEMPORARY) 412 { 413 unreal_log(ULOG_INFO, "dccdeny", "DCCDENY_DEL", client, 414 "[dccdeny] $client removed a temporary DCCDENY for $file ($reason)", 415 log_data_string("file", d->filename), 416 log_data_string("reason", d->reason)); 417 DCCdeny_del(d); 418 return; 419 } else 420 { 421 sendnotice(client, "*** Unable to find a temp dccdeny matching %s", parv[1]); 422 } 423 } 424 425 CMD_FUNC(cmd_svsfline) 426 { 427 if (parc < 2) 428 return; 429 430 switch (*parv[1]) 431 { 432 /* Allow non-U-Lines to send ONLY SVSFLINE +, but don't send it out 433 * unless it is from a U-Line -- codemastr 434 */ 435 case '+': 436 { 437 if (parc < 4) 438 return; 439 440 if (!find_deny_dcc(parv[2])) 441 DCCdeny_add(parv[2], parv[3], DCCDENY_HARD, CONF_BAN_TYPE_AKILL); 442 443 if (IsULine(client)) 444 { 445 sendto_server(client, 0, 0, NULL, ":%s SVSFLINE + %s :%s", 446 client->id, parv[2], parv[3]); 447 } 448 449 break; 450 } 451 452 case '-': 453 { 454 ConfigItem_deny_dcc *deny; 455 456 if (!IsULine(client)) 457 return; 458 459 if (parc < 3) 460 return; 461 462 if (!(deny = find_deny_dcc(parv[2]))) 463 break; 464 465 DCCdeny_del(deny); 466 467 sendto_server(client, 0, 0, NULL, ":%s SVSFLINE %s", client->id, parv[2]); 468 469 break; 470 } 471 472 case '*': 473 { 474 if (!IsULine(client)) 475 return; 476 477 dcc_wipe_services(); 478 479 sendto_server(client, 0, 0, NULL, ":%s SVSFLINE *", client->id); 480 481 break; 482 } 483 } 484 } 485 486 /** Sync the DCC entries on server connect */ 487 int dccdeny_server_sync(Client *client) 488 { 489 ConfigItem_deny_dcc *p; 490 for (p = conf_deny_dcc; p; p = p->next) 491 { 492 if (p->flag.type2 == CONF_BAN_TYPE_AKILL) 493 sendto_one(client, NULL, ":%s SVSFLINE + %s :%s", me.id, 494 p->filename, p->reason); 495 } 496 return 0; 497 } 498 499 /** Check if a DCC should be blocked (user-to-user) */ 500 int dccdeny_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype) 501 { 502 if (**text == '\001') 503 { 504 const char *filename = get_dcc_filename(*text); 505 if (filename) 506 { 507 if (MyUser(client) && !can_dcc(client, target->name, target, filename, errmsg)) 508 return HOOK_DENY; 509 if (MyUser(target) && !can_dcc_soft(client, target, filename, errmsg)) 510 return HOOK_DENY; 511 } 512 } 513 514 return HOOK_CONTINUE; 515 } 516 517 /** Check if a DCC should be blocked (user-to-channel, unusual) */ 518 int dccdeny_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype) 519 { 520 static char errbuf[512]; 521 522 if (MyUser(client) && (**msg == '\001')) 523 { 524 const char *err = NULL; 525 const char *filename = get_dcc_filename(*msg); 526 if (filename && !can_dcc(client, channel->name, NULL, filename, &err)) 527 { 528 strlcpy(errbuf, err, sizeof(errbuf)); 529 *errmsg = errbuf; 530 return HOOK_DENY; 531 } 532 } 533 return HOOK_CONTINUE; 534 } 535 536 /* e->flag.type2: 537 * CONF_BAN_TYPE_AKILL banned by SVSFLINE ('global') 538 * CONF_BAN_TYPE_CONF banned by conf 539 * CONF_BAN_TYPE_TEMPORARY banned by /DCCDENY ('temporary') 540 * e->flag.type: 541 * DCCDENY_HARD Fully denied 542 * DCCDENY_SOFT Denied, but allowed to override via /DCCALLOW 543 */ 544 545 /** Make a viewable dcc filename. 546 * This is to protect a bit against tricks like 'flood-it-off-the-buffer' 547 * and color 1,1 etc... 548 */ 549 static const char *dcc_displayfile(const char *f) 550 { 551 static char buf[512]; 552 const char *i; 553 char *o = buf; 554 size_t n = strlen(f); 555 556 if (n < 300) 557 { 558 for (i = f; *i; i++) 559 if (*i < 32) 560 *o++ = '?'; 561 else 562 *o++ = *i; 563 *o = '\0'; 564 return buf; 565 } 566 567 /* Else, we show it as: [first 256 chars]+"[..TRUNCATED..]"+[last 20 chars] */ 568 for (i = f; i < f+256; i++) 569 if (*i < 32) 570 *o++ = '?'; 571 else 572 *o++ = *i; 573 strcpy(o, "[..TRUNCATED..]"); 574 o += sizeof("[..TRUNCATED..]"); 575 for (i = f+n-20; *i; i++) 576 if (*i < 32) 577 *o++ = '?'; 578 else 579 *o++ = *i; 580 *o = '\0'; 581 return buf; 582 } 583 584 static const char *get_dcc_filename(const char *text) 585 { 586 static char filename[BUFSIZE+1]; 587 char *end; 588 int size_string; 589 590 if (*text != '\001') 591 return 0; 592 593 if (!strncasecmp(text+1, "DCC SEND ", 9)) 594 text = text + 10; 595 else if (!strncasecmp(text+1, "DCC RESUME ", 11)) 596 text = text + 12; 597 else 598 return 0; 599 600 for (; *text == ' '; text++); /* skip leading spaces */ 601 602 if (*text == '"' && *(text+1)) 603 end = strchr(text+1, '"'); 604 else 605 end = strchr(text, ' '); 606 607 if (!end || (end < text)) 608 return 0; 609 610 size_string = (int)(end - text); 611 612 if (!size_string || (size_string > (BUFSIZE - 1))) 613 return 0; 614 615 strlcpy(filename, text, size_string+1); 616 return filename; 617 } 618 619 /** Checks if a DCC SEND is allowed. 620 * @param client Sending client 621 * @param target Target name (user or channel) 622 * @param targetcli Target client (NULL in case of channel!) 623 * @param text The entire message 624 * @returns 1 if DCC SEND allowed, 0 if rejected 625 */ 626 static int can_dcc(Client *client, const char *target, Client *targetcli, const char *filename, const char **errmsg) 627 { 628 ConfigItem_deny_dcc *fl; 629 static char errbuf[256]; 630 int size_string, ret; 631 632 /* User (IRCOp) may bypass send restrictions */ 633 if (ValidatePermissionsForPath("immune:dcc",client,targetcli,NULL,NULL)) 634 return 1; 635 636 /* User (IRCOp) likes to receive bad dcc's */ 637 if (targetcli && ValidatePermissionsForPath("self:getbaddcc",targetcli,NULL,NULL,NULL)) 638 return 1; 639 640 /* Check if user is already blocked (from the past) */ 641 if (IsDCCBlock(client)) 642 { 643 *errmsg = "*** You are blocked from sending files as you have tried to " 644 "send a forbidden file - reconnect to regain ability to send"; 645 return 0; 646 } 647 648 if (match_spamfilter(client, filename, SPAMF_DCC, "PRIVMSG", target, 0, NULL)) 649 { 650 /* Dirty hack, yeah spamfilter already sent the error message :( */ 651 *errmsg = ""; 652 return 0; 653 } 654 655 if ((fl = dcc_isforbidden(client, filename))) 656 { 657 const char *displayfile = dcc_displayfile(filename); 658 659 RunHook(HOOKTYPE_DCC_DENIED, client, target, filename, displayfile, fl); 660 661 ircsnprintf(errbuf, sizeof(errbuf), "Cannot DCC SEND file: %s", fl->reason); 662 *errmsg = errbuf; 663 SetDCCBlock(client); 664 return 0; 665 } 666 667 /* Channel dcc (???) and discouraged? just block */ 668 if (!targetcli && ((fl = dcc_isdiscouraged(client, filename)))) 669 { 670 ircsnprintf(errbuf, sizeof(errbuf), "Cannot DCC SEND file: %s", fl->reason); 671 *errmsg = errbuf; 672 return 0; 673 } 674 675 /* If we get here, the file is allowed */ 676 return 1; 677 } 678 679 /** Checks if a DCC is allowed by DCCALLOW rules (only SOFT bans are checked). 680 * PARAMETERS: 681 * from: the sender client (possibly remote) 682 * to: the target client (always local) 683 * text: the whole msg 684 * RETURNS: 685 * 1: allowed 686 * 0: block 687 */ 688 static int can_dcc_soft(Client *from, Client *to, const char *filename, const char **errmsg) 689 { 690 ConfigItem_deny_dcc *fl; 691 const char *displayfile; 692 static char errbuf[256]; 693 694 /* User (IRCOp) may bypass send restrictions */ 695 if (ValidatePermissionsForPath("immune:dcc",from,to,NULL,NULL)) 696 return 1; 697 698 /* User (IRCOp) likes to receive bad dcc's */ 699 if (ValidatePermissionsForPath("self:getbaddcc",to,NULL,NULL,NULL)) 700 return 1; 701 702 /* On the 'soft' blocklist ? */ 703 if (!(fl = dcc_isdiscouraged(from, filename))) 704 return 1; /* No, so is OK */ 705 706 /* If on DCCALLOW list then the user is OK with it */ 707 if (on_dccallow_list(to, from)) 708 return 1; 709 710 /* Soft-blocked */ 711 displayfile = dcc_displayfile(filename); 712 713 ircsnprintf(errbuf, sizeof(errbuf), "Cannot DCC SEND file: %s", fl->reason); 714 *errmsg = errbuf; 715 716 /* Inform target ('to') about the /DCCALLOW functionality */ 717 sendnotice(to, "%s (%s@%s) tried to DCC SEND you a file named '%s', the request has been blocked.", 718 from->name, from->user->username, GetHost(from), displayfile); 719 if (!IsDCCNotice(to)) 720 { 721 SetDCCNotice(to); 722 sendnotice(to, "Files like these might contain malicious content (viruses, trojans). " 723 "Therefore, you must explicitly allow anyone that tries to send you such files."); 724 sendnotice(to, "If you trust %s, and want him/her to send you this file, you may obtain " 725 "more information on using the dccallow system by typing '/DCCALLOW HELP'", from->name); 726 } 727 return 0; 728 } 729 730 /** Checks if the dcc is blacklisted. */ 731 static ConfigItem_deny_dcc *dcc_isforbidden(Client *client, const char *filename) 732 { 733 ConfigItem_deny_dcc *d; 734 ConfigItem_allow_dcc *a; 735 736 if (!conf_deny_dcc || !filename) 737 return NULL; 738 739 for (d = conf_deny_dcc; d; d = d->next) 740 { 741 if ((d->flag.type == DCCDENY_HARD) && match_simple(d->filename, filename)) 742 { 743 for (a = conf_allow_dcc; a; a = a->next) 744 { 745 if ((a->flag.type == DCCDENY_HARD) && match_simple(a->filename, filename)) 746 return NULL; 747 } 748 return d; 749 } 750 } 751 752 return NULL; 753 } 754 755 /** checks if the dcc is discouraged ('soft bans'). */ 756 static ConfigItem_deny_dcc *dcc_isdiscouraged(Client *client, const char *filename) 757 { 758 ConfigItem_deny_dcc *d; 759 ConfigItem_allow_dcc *a; 760 761 if (!conf_deny_dcc || !filename) 762 return NULL; 763 764 for (d = conf_deny_dcc; d; d = d->next) 765 { 766 if ((d->flag.type == DCCDENY_SOFT) && match_simple(d->filename, filename)) 767 { 768 for (a = conf_allow_dcc; a; a = a->next) 769 { 770 if ((a->flag.type == DCCDENY_SOFT) && match_simple(a->filename, filename)) 771 return NULL; 772 } 773 return d; 774 } 775 } 776 777 return NULL; 778 } 779 780 static void DCCdeny_add(const char *filename, const char *reason, int type, int type2) 781 { 782 ConfigItem_deny_dcc *deny = NULL; 783 784 deny = safe_alloc(sizeof(ConfigItem_deny_dcc)); 785 safe_strdup(deny->filename, filename); 786 safe_strdup(deny->reason, reason); 787 deny->flag.type = type; 788 deny->flag.type2 = type2; 789 AddListItem(deny, conf_deny_dcc); 790 } 791 792 static void DCCdeny_del(ConfigItem_deny_dcc *deny) 793 { 794 DelListItem(deny, conf_deny_dcc); 795 safe_free(deny->filename); 796 safe_free(deny->reason); 797 safe_free(deny); 798 } 799 800 ConfigItem_deny_dcc *find_deny_dcc(const char *name) 801 { 802 ConfigItem_deny_dcc *e; 803 804 if (!name) 805 return NULL; 806 807 for (e = conf_deny_dcc; e; e = e->next) 808 { 809 if (match_simple(name, e->filename)) 810 return e; 811 } 812 return NULL; 813 } 814 815 static void dcc_wipe_services(void) 816 { 817 ConfigItem_deny_dcc *dconf, *next; 818 819 for (dconf = conf_deny_dcc; dconf; dconf = next) 820 { 821 next = dconf->next; 822 if (dconf->flag.type2 == CONF_BAN_TYPE_AKILL) 823 { 824 DelListItem(dconf, conf_deny_dcc); 825 safe_free(dconf->filename); 826 safe_free(dconf->reason); 827 safe_free(dconf); 828 } 829 } 830 831 } 832 833 int dccdeny_stats(Client *client, const char *para) 834 { 835 ConfigItem_deny_dcc *denytmp; 836 ConfigItem_allow_dcc *allowtmp; 837 char *filemask, *reason; 838 char a = 0; 839 840 /* '/STATS F' or '/STATS denydcc' is for us... */ 841 if (strcmp(para, "F") && strcasecmp(para, "denydcc")) 842 return 0; 843 844 for (denytmp = conf_deny_dcc; denytmp; denytmp = denytmp->next) 845 { 846 filemask = BadPtr(denytmp->filename) ? "<NULL>" : denytmp->filename; 847 reason = BadPtr(denytmp->reason) ? "<NULL>" : denytmp->reason; 848 if (denytmp->flag.type2 == CONF_BAN_TYPE_CONF) 849 a = 'c'; 850 if (denytmp->flag.type2 == CONF_BAN_TYPE_AKILL) 851 a = 's'; 852 if (denytmp->flag.type2 == CONF_BAN_TYPE_TEMPORARY) 853 a = 'o'; 854 /* <d> <s|h> <howadded> <filemask> <reason> */ 855 sendtxtnumeric(client, "d %c %c %s %s", (denytmp->flag.type == DCCDENY_SOFT) ? 's' : 'h', 856 a, filemask, reason); 857 } 858 for (allowtmp = conf_allow_dcc; allowtmp; allowtmp = allowtmp->next) 859 { 860 filemask = BadPtr(allowtmp->filename) ? "<NULL>" : allowtmp->filename; 861 if (allowtmp->flag.type2 == CONF_BAN_TYPE_CONF) 862 a = 'c'; 863 if (allowtmp->flag.type2 == CONF_BAN_TYPE_AKILL) 864 a = 's'; 865 if (allowtmp->flag.type2 == CONF_BAN_TYPE_TEMPORARY) 866 a = 'o'; 867 /* <a> <s|h> <howadded> <filemask> */ 868 sendtxtnumeric(client, "a %c %c %s", (allowtmp->flag.type == DCCDENY_SOFT) ? 's' : 'h', 869 a, filemask); 870 } 871 return 1; 872 } 873 874 int dccdeny_dcc_denied(Client *client, const char *target, const char *realfile, const char *displayfile, ConfigItem_deny_dcc *dccdeny) 875 { 876 unreal_log(ULOG_INFO, "dcc", "DCC_REJECTED", client, 877 "$client.details tried to send forbidden file $filename ($ban_reason) to $target (is blocked now)", 878 log_data_string("filename", displayfile), 879 log_data_string("ban_reason", dccdeny->reason), 880 log_data_string("target", target)); 881 return 0; 882 }