unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
parse.c (24067B)
1 /************************************************************************ 2 * Unreal Internet Relay Chat Daemon, src/parse.c 3 * Copyright (C) 1990 Jarkko Oikarinen and 4 * University of Oulu, Computing Center 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 1, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 /** @file 22 * @brief Main line parsing functions - for incoming lines from clients. 23 */ 24 #include "unrealircd.h" 25 26 /** Last (or current) command that we processed. Useful for post-mortem. */ 27 char backupbuf[8192]; 28 29 static char *para[MAXPARA + 2]; 30 31 /* Forward declarations of functions that are local (static) */ 32 static int do_numeric(int, Client *, MessageTag *, int, const char **); 33 static void cancel_clients(Client *, Client *, char *); 34 static void remove_unknown(Client *, char *); 35 static void parse2(Client *client, Client **fromptr, MessageTag *mtags, int mtags_bytes, char *ch); 36 static void parse_addlag(Client *client, int command_bytes, int mtags_bytes); 37 static int client_lagged_up(Client *client); 38 static void ban_handshake_data_flooder(Client *client); 39 40 /** Put a packet in the client receive queue and process the data (if 41 * the 'fake lag' rules permit doing so). 42 * @param client The client 43 * @param readbuf The read buffer 44 * @param length The length of the data 45 * @param killsafely If 1 then we may call exit_client() if the client 46 * is flooding. If 0 then we use dead_socket(). 47 * @returns 1 in normal circumstances, 0 if client was killed. 48 * @note If killsafely is 1 and the return value is 0 then 49 * the client was killed - IsDead() is true. 50 * If this is a problem, then set killsafely to 0 when calling. 51 */ 52 int process_packet(Client *client, char *readbuf, int length, int killsafely) 53 { 54 dbuf_put(&client->local->recvQ, readbuf, length); 55 56 /* parse some of what we have (inducing fakelag, etc) */ 57 parse_client_queued(client); 58 59 /* We may be killed now, so check for it.. */ 60 if (IsDead(client)) 61 return 0; 62 63 /* flood from unknown connection */ 64 if (IsUnknown(client) && (DBufLength(&client->local->recvQ) > iConf.handshake_data_flood_amount)) 65 { 66 unreal_log(ULOG_INFO, "flood", "HANDSHAKE_DATA_FLOOD", client, 67 "Handshake data flood detected from $client.details [$client.ip]"); 68 if (!killsafely) 69 ban_handshake_data_flooder(client); 70 else 71 dead_socket(client, "Handshake data flood detected"); 72 return 0; 73 } 74 75 /* excess flood check */ 76 if (IsUser(client) && DBufLength(&client->local->recvQ) > get_recvq(client)) 77 { 78 unreal_log(ULOG_INFO, "flood", "RECVQ_EXCEEDED", client, 79 "Flood from $client.details [$client.ip] exceeds class::recvq ($recvq > $class_recvq) (Client sending too much data)", 80 log_data_integer("recvq", DBufLength(&client->local->recvQ)), 81 log_data_integer("class_recvq", get_recvq(client))); 82 if (!killsafely) 83 exit_client(client, NULL, "Excess Flood"); 84 else 85 dead_socket(client, "Excess Flood"); 86 return 0; 87 } 88 89 return 1; 90 } 91 92 /** Parse any queued data for 'client', if permitted. 93 * @param client The client. 94 */ 95 void parse_client_queued(Client *client) 96 { 97 int dolen = 0; 98 char buf[READBUFSIZE]; 99 100 if (IsDNSLookup(client)) 101 return; /* we delay processing of data until the host is resolved */ 102 103 if (IsIdentLookup(client)) 104 return; /* we delay processing of data until identd has replied */ 105 106 if (!IsUser(client) && !IsServer(client) && (iConf.handshake_delay > 0) && 107 !IsNoHandshakeDelay(client) && 108 !IsUnixSocket(client) && 109 (TStime() - client->local->creationtime < iConf.handshake_delay)) 110 { 111 return; /* we delay processing of data until set::handshake-delay is reached */ 112 } 113 114 while (DBufLength(&client->local->recvQ) && !client_lagged_up(client)) 115 { 116 dolen = dbuf_getmsg(&client->local->recvQ, buf); 117 118 if (dolen == 0) 119 return; 120 121 dopacket(client, buf, dolen); 122 123 if (IsDead(client)) 124 return; 125 } 126 } 127 128 /* 129 ** dopacket 130 ** client - pointer to client structure for which the buffer data 131 ** applies. 132 ** buffer - pointr to the buffer containing the newly read data 133 ** length - number of valid bytes of data in the buffer 134 ** 135 ** Note: 136 ** It is implicitly assumed that dopacket is called only 137 ** with client of "local" variation, which contains all the 138 ** necessary fields (buffer etc..) 139 ** 140 ** Rewritten for linebufs, 19th May 2013. --kaniini 141 */ 142 void dopacket(Client *client, char *buffer, int length) 143 { 144 client->local->traffic.bytes_received += length; 145 me.local->traffic.bytes_received += length; 146 147 client->local->traffic.messages_received++; 148 me.local->traffic.messages_received++; 149 150 parse(client, buffer, length); 151 } 152 153 154 /** Parse an incoming line. 155 * A line was received previously, buffered via dbuf, now popped from the dbuf stack, 156 * and we should now process it. 157 * @param cptr The client from which the message was received 158 * @param buffer The buffer 159 * @param length The length of the buffer 160 * @note parse() cannot not be called recusively by any other functions! 161 */ 162 void parse(Client *cptr, char *buffer, int length) 163 { 164 Hook *h; 165 Client *from = cptr; 166 char *ch; 167 int i, ret; 168 MessageTag *mtags = NULL; 169 int mtags_bytes = 0; 170 171 /* Take extreme care in this function, as messages can be up to READBUFSIZE 172 * in size, which is 8192 at the time of writing. 173 * This, while all the rest of the IRCd code assumes a maximum length 174 * of BUFSIZE, which is 512 (including NUL byte). 175 */ 176 for (h = Hooks[HOOKTYPE_PACKET]; h; h = h->next) 177 { 178 (*(h->func.intfunc))(from, &me, NULL, &buffer, &length); 179 if (!buffer) 180 return; 181 } 182 183 if (IsDeadSocket(cptr)) 184 return; 185 186 if ((cptr->local->traffic.bytes_received >= iConf.handshake_data_flood_amount) && IsUnknown(cptr)) 187 { 188 unreal_log(ULOG_INFO, "flood", "HANDSHAKE_DATA_FLOOD", cptr, 189 "Handshake data flood detected from $client.details [$client.ip]"); 190 ban_handshake_data_flooder(cptr); 191 return; 192 } 193 194 /* This stores the last executed command in 'backupbuf', useful for debugging crashes */ 195 strlcpy(backupbuf, buffer, sizeof(backupbuf)); 196 197 #if defined(RAWCMDLOGGING) 198 unreal_log(ULOG_INFO, "rawtraffic", "TRAFFIC_IN", cptr, 199 "<- $client: $data", 200 log_data_string("data", backupbuf)); 201 #endif 202 203 /* This poisons unused para elements that code should never access */ 204 for (i = 0; i < MAXPARA+2; i++) 205 para[i] = (char *)DEADBEEF_ADDR; 206 207 /* First, skip any whitespace */ 208 for (ch = buffer; *ch == ' '; ch++) 209 ; 210 211 /* Now, parse message tags, if any */ 212 if (*ch == '@') 213 { 214 char *start = ch; 215 parse_message_tags(cptr, &ch, &mtags); 216 if (ch - start > 0) 217 mtags_bytes = ch - start; 218 /* Skip whitespace again */ 219 for (; *ch == ' '; ch++) 220 ; 221 } 222 223 parse2(cptr, &from, mtags, mtags_bytes, ch); 224 225 if (IsDead(cptr)) 226 RunHook(HOOKTYPE_POST_COMMAND, NULL, mtags, ch); 227 else 228 RunHook(HOOKTYPE_POST_COMMAND, from, mtags, ch); 229 230 free_message_tags(mtags); 231 return; 232 } 233 234 /** Parse the remaining line - helper function for parse(). 235 * @param cptr The client from which the message was received 236 * @param from The sender, this may be changed by parse2() when 237 * the message has a sender, eg :xyz PRIVMSG .. 238 * @param mtags Message tags received for this message. 239 * @param mtags_bytes The length of all message tags. 240 * @param ch The incoming line received (buffer), excluding message tags. 241 */ 242 static void parse2(Client *cptr, Client **fromptr, MessageTag *mtags, int mtags_bytes, char *ch) 243 { 244 Client *from = cptr; 245 char *s; 246 int len, i, numeric = 0, paramcount; 247 #ifdef DEBUGMODE 248 time_t then, ticks; 249 int retval; 250 #endif 251 RealCommand *cmptr = NULL; 252 int bytes; 253 254 *fromptr = cptr; /* The default, unless a source is specified (and permitted) */ 255 256 /* The remaining part should never be more than 510 bytes 257 * (that is 512 minus CR LF, as specified in RFC1459 section 2.3). 258 * If it is too long, then we cut it off here. 259 */ 260 if (strlen(ch) > 510) 261 { 262 ch[510] = '\0'; 263 } 264 265 para[0] = (char *)DEADBEEF_ADDR; /* helps us catch bugs :) */ 266 267 if (*ch == ':' || *ch == '@') 268 { 269 char sender[HOSTLEN + 1]; 270 s = sender; 271 *s = '\0'; 272 273 /* Deal with :sender ... */ 274 for (++ch, i = 0; *ch && *ch != ' '; ++ch) 275 { 276 if (s < sender + sizeof(sender) - 1) 277 *s++ = *ch; 278 } 279 *s = '\0'; 280 281 /* For servers we lookup the sender and change 'from' accordingly. 282 * For other clients we ignore the sender. 283 */ 284 if (*sender && IsServer(cptr)) 285 { 286 from = find_client(sender, NULL); 287 288 if (!from && strchr(sender, '@')) 289 from = hash_find_nickatserver(sender, NULL); 290 291 /* Sender not found. Possibly a ghost, so kill it. 292 * This can happen in normal circumstances. For example 293 * in case of A-B-C where we are B. If a KILL came from C 294 * for a client on A and we processed it at B, then until 295 * A has processed it we may still receive messages from A 296 * about it's soon-to-be-killed-client (all due to lag). 297 */ 298 if (!from) 299 { 300 ircstats.is_unpf++; 301 remove_unknown(cptr, sender); 302 return; 303 } 304 /* This is more severe. The server gave a source of a client 305 * that cannot exist from that direction. 306 * Eg in case of a topology of A-B-C-D and we are B, 307 * we got a message from A with ":D MODE...". 308 * In that case we send a SQUIT to that direction telling to 309 * unlink D from that side. This will likely lead to a 310 * problematic situation, though. 311 * This is, by the way, also why we try to prevent this situation 312 * in the first place by using PROTOCTL SERVERS=... 313 * in which case we reject such a flawed link very early 314 * in the server handshake process. -- Syzop 315 */ 316 if (from->direction != cptr) 317 { 318 ircstats.is_wrdi++; 319 cancel_clients(cptr, from, ch); 320 return; 321 } 322 *fromptr = from; /* Update source client */ 323 } 324 while (*ch == ' ') 325 ch++; 326 } 327 328 RunHook(HOOKTYPE_PRE_COMMAND, from, mtags, ch); 329 330 if (*ch == '\0') 331 { 332 if (!IsServer(cptr)) 333 cptr->local->fake_lag++; /* 1s fake lag */ 334 return; 335 } 336 337 /* Recalculate string length, now that we have skipped the sender */ 338 bytes = strlen(ch); 339 340 /* Now let's figure out the command (or numeric)... */ 341 s = strchr(ch, ' '); /* s -> End of the command code */ 342 len = (s) ? (s - ch) : 0; 343 344 if (len == 3 && isdigit(*ch) && isdigit(*(ch + 1)) && isdigit(*(ch + 2))) 345 { 346 /* Numeric (eg: 311) */ 347 cmptr = NULL; 348 numeric = (*ch - '0') * 100 + (*(ch + 1) - '0') * 10 + (*(ch + 2) - '0'); 349 paramcount = MAXPARA; 350 ircstats.is_num++; 351 parse_addlag(cptr, bytes, mtags_bytes); 352 } 353 else 354 { 355 /* Command (eg: PRIVMSG) */ 356 int flags = 0; 357 if (s) 358 *s++ = '\0'; 359 360 /* Set the appropriate flags for the command lookup */ 361 if (!IsRegistered(from)) 362 flags |= CMD_UNREGISTERED; 363 if (IsUser(from)) 364 flags |= CMD_USER; 365 if (IsServer(from)) 366 flags |= CMD_SERVER; 367 if (IsShunned(from)) 368 flags |= CMD_SHUN; 369 if (IsVirus(from)) 370 flags |= CMD_VIRUS; 371 if (IsOper(from)) 372 flags |= CMD_OPER; 373 if (IsControl(from)) 374 flags |= CMD_CONTROL; 375 cmptr = find_command(ch, flags); 376 if (!cmptr || !(cmptr->flags & CMD_NOLAG)) 377 { 378 /* Add fake lag (doing this early in the code, so we don't forget) */ 379 parse_addlag(cptr, bytes, mtags_bytes); 380 } 381 if (!cmptr) 382 { 383 if (IsControl(from)) 384 { 385 sendto_one(from, NULL, "ERROR UNKNOWN_COMMAND: %s", ch); 386 sendto_one(from, NULL, "END 1"); 387 return; 388 } 389 /* Don't send error messages in response to NOTICEs 390 * in pre-connection state. 391 */ 392 if (!IsRegistered(cptr) && strcasecmp(ch, "NOTICE")) 393 { 394 sendnumericfmt(from, ERR_NOTREGISTERED, ":You have not registered"); 395 return; 396 } 397 /* If the user is shunned then don't send anything back in case 398 * of an unknown command, since we want to save data. 399 */ 400 if (IsShunned(cptr)) 401 return; 402 403 if (ch[0] != '\0') 404 { 405 if (IsUser(from)) 406 { 407 sendto_one(from, NULL, ":%s %d %s %s :Unknown command", 408 me.name, ERR_UNKNOWNCOMMAND, 409 from->name, ch); 410 } 411 } 412 ircstats.is_unco++; 413 return; 414 } 415 if (cmptr->flags != 0) { /* temporary until all commands are updated */ 416 417 /* Logic in comparisons below is a bit complicated, see notes */ 418 419 /* If you're a user, and this command does not permit users or opers, deny */ 420 if ((flags & CMD_USER) && !(cmptr->flags & CMD_USER) && !(cmptr->flags & CMD_OPER)) 421 { 422 if (cmptr->flags & CMD_UNREGISTERED) 423 sendnumeric(cptr, ERR_ALREADYREGISTRED); /* only for unregistered phase */ 424 else 425 sendnumeric(cptr, ERR_NOTFORUSERS, cmptr->cmd); /* really never for users */ 426 return; 427 } 428 429 /* If you're a server, but command doesn't want servers, deny */ 430 if ((flags & CMD_SERVER) && !(cmptr->flags & CMD_SERVER)) 431 return; 432 } 433 434 /* If you're a user, but not an operator, and this requires operators, deny */ 435 if ((cmptr->flags & CMD_OPER) && (flags & CMD_USER) && !(flags & CMD_OPER)) 436 { 437 sendnumeric(cptr, ERR_NOPRIVILEGES); 438 return; 439 } 440 paramcount = cmptr->parameters; 441 cmptr->bytes += bytes; 442 } 443 /* 444 ** Must the following loop really be so devious? On 445 ** surface it splits the message to parameters from 446 ** blank spaces. But, if paramcount has been reached, 447 ** the rest of the message goes into this last parameter 448 ** (about same effect as ":" has...) --msa 449 */ 450 451 /* Note initially true: s==NULL || *(s-1) == '\0' !! */ 452 453 i = 0; 454 if (s) 455 { 456 /* 457 if (paramcount > MAXPARA) 458 paramcount = MAXPARA; 459 We now use functions to create commands, so we can just check this 460 once when the command is created rather than each time the command 461 is used -- codemastr 462 */ 463 for (;;) 464 { 465 /* 466 ** Never "FRANCE " again!! ;-) Clean 467 ** out *all* blanks.. --msa 468 */ 469 while (*s == ' ') 470 *s++ = '\0'; 471 472 if (*s == '\0') 473 break; 474 if (*s == ':') 475 { 476 /* 477 ** The rest is single parameter--can 478 ** include blanks also. 479 */ 480 para[++i] = s + 1; 481 break; 482 } 483 para[++i] = s; 484 if (i >= paramcount) 485 break; 486 for (; *s != ' ' && *s; s++) 487 ; 488 } 489 } 490 para[++i] = NULL; 491 492 /* Check if one of the message tags are rejected by spamfilter */ 493 if (MyConnect(from) && !IsServer(from) && match_spamfilter_mtags(from, mtags, cmptr ? cmptr->cmd : NULL)) 494 return; 495 496 if (cmptr == NULL) 497 { 498 do_numeric(numeric, from, mtags, i, (const char **)para); 499 return; 500 } 501 cmptr->count++; 502 if (IsUser(cptr) && (cmptr->flags & CMD_RESETIDLE)) 503 cptr->local->idle_since = TStime(); 504 505 /* Now ready to execute the command */ 506 #ifndef DEBUGMODE 507 if (cmptr->flags & CMD_ALIAS) 508 { 509 (*cmptr->aliasfunc) (from, mtags, i, (const char **)para, cmptr->cmd); 510 } else { 511 if (!cmptr->overriders) 512 (*cmptr->func) (from, mtags, i, (const char **)para); 513 else 514 (*cmptr->overriders->func) (cmptr->overriders, from, mtags, i, (const char **)para); 515 } 516 #else 517 then = clock(); 518 if (cmptr->flags & CMD_ALIAS) 519 { 520 (*cmptr->aliasfunc) (from, mtags, i, (const char **)para, cmptr->cmd); 521 } else { 522 if (!cmptr->overriders) 523 (*cmptr->func) (from, mtags, i, (const char **)para); 524 else 525 (*cmptr->overriders->func) (cmptr->overriders, from, mtags, i, (const char **)para); 526 } 527 if (!IsDead(cptr)) 528 { 529 ticks = (clock() - then); 530 if (IsServer(cptr)) 531 cmptr->rticks += ticks; 532 else 533 cmptr->lticks += ticks; 534 } 535 #endif 536 } 537 538 /** Ban user that is "flooding from an unknown connection". 539 * This is basically a client sending lots of data but not registering. 540 * Note that "lots" in terms of IRC is a few KB's, since more is rather unusual. 541 * @param client The client. 542 */ 543 static void ban_handshake_data_flooder(Client *client) 544 { 545 if (find_tkl_exception(TKL_HANDSHAKE_DATA_FLOOD, client)) 546 { 547 /* If the user is exempt we will still KILL the client, since it is 548 * clearly misbehaving. We just won't ZLINE the host, so it won't 549 * affect any other connections from the same IP address. 550 */ 551 exit_client(client, NULL, "Handshake data flood detected"); 552 } 553 else 554 { 555 /* place_host_ban also takes care of removing any other clients with same host/ip */ 556 place_host_ban(client, iConf.handshake_data_flood_ban_action, "Handshake data flood detected", iConf.handshake_data_flood_ban_time); 557 } 558 } 559 560 /** Add "fake lag" if needed. 561 * The main purpose of fake lag is to create artificial lag when 562 * processing incoming data from the client. So, if a client sends 563 * a lot of commands, then next command will be processed at a rate 564 * of 1 per second, or even slower. The exact algorithm is defined in this function. 565 * 566 * Servers are exempt from fake lag, so are IRCOps and clients tagged as 567 * 'no fake lag' by services (rarely used). Finally, there is also an 568 * option called class::options::nofakelag which exempts fakelag. 569 * Exemptions should be granted with extreme care, since a client will 570 * be able to flood at full speed causing potentially many Mbits or even 571 * GBits of data to be sent out to other clients. 572 * 573 * @param client The client. 574 * @param command_bytes Command length in bytes (excluding message tagss) 575 * @param mtags_bytes Length of message tags in bytes 576 */ 577 void parse_addlag(Client *client, int command_bytes, int mtags_bytes) 578 { 579 FloodSettings *settings = get_floodsettings_for_user(client, FLD_LAG_PENALTY); 580 581 if (!IsServer(client) && !IsNoFakeLag(client) && 582 #ifdef FAKELAG_CONFIGURABLE 583 !(client->local->class && (client->local->class->options & CLASS_OPT_NOFAKELAG)) && 584 #endif 585 !ValidatePermissionsForPath("immune:lag",client,NULL,NULL,NULL)) 586 { 587 int lag_penalty = settings->period[FLD_LAG_PENALTY]; 588 int lag_penalty_bytes = settings->limit[FLD_LAG_PENALTY]; 589 590 client->local->fake_lag_msec += (1 + (command_bytes/lag_penalty_bytes) + (mtags_bytes/lag_penalty_bytes)) * lag_penalty; 591 592 /* This code takes into account not only the msecs we just calculated 593 * but also any leftover msec from previous lagging up. 594 */ 595 client->local->fake_lag += (client->local->fake_lag_msec / 1000); 596 client->local->fake_lag_msec = client->local->fake_lag_msec % 1000; 597 } 598 } 599 600 /* Add extra fake lag to client, such as after a failed oper attempt. 601 */ 602 void add_fake_lag(Client *client, long msec) 603 { 604 if (!MyConnect(client)) 605 return; 606 607 client->local->fake_lag_msec += msec; 608 client->local->fake_lag += (client->local->fake_lag_msec / 1000); 609 client->local->fake_lag_msec = client->local->fake_lag_msec % 1000; 610 } 611 612 /** Returns 1 if the client is lagged up and data should NOT be parsed. 613 * See also parse_addlag() for more information on "fake lag". 614 * @param client The client to check 615 * @returns 1 if client is lagged up and data should not be parsed, 0 otherwise. 616 */ 617 static int client_lagged_up(Client *client) 618 { 619 if (client->status < CLIENT_STATUS_UNKNOWN) 620 return 0; 621 if (IsServer(client)) 622 return 0; 623 if (ValidatePermissionsForPath("immune:lag",client,NULL,NULL,NULL)) 624 return 0; 625 if (client->local->fake_lag - TStime() < 10) 626 return 0; 627 return 1; 628 } 629 630 631 /** Numeric received from a connection. 632 * @param numeric The numeric code (range 000-999) 633 * @param cptr The client 634 * @param recv_mtags Received message tags 635 * @param parc Parameter count 636 * @param parv Parameters 637 * @note In general you should NOT send anything back if you receive 638 * a numeric, this to prevent creating loops. 639 */ 640 static int do_numeric(int numeric, Client *client, MessageTag *recv_mtags, int parc, const char *parv[]) 641 { 642 Client *acptr; 643 Channel *channel; 644 char *nick, *p; 645 int i; 646 char buffer[BUFSIZE]; 647 char targets[BUFSIZE]; 648 649 if ((numeric < 0) || (numeric > 999)) 650 return -1; 651 652 if (MyConnect(client) && !IsServer(client) && !IsUser(client) && IsHandshake(client) && client->server && !IsServerSent(client)) 653 { 654 /* This is an outgoing server connect that is currently not yet IsServer() but in 'unknown' state. 655 * We need to handle a few responses here. 656 */ 657 658 /* STARTTLS: unknown command */ 659 if ((numeric == 451) && (parc > 2) && strstr(parv[1], "STARTTLS")) 660 { 661 if (client->server->conf && (client->server->conf->outgoing.options & CONNECT_INSECURE)) 662 start_server_handshake(client); 663 else 664 reject_insecure_server(client); 665 return 0; 666 } 667 668 /* STARTTLS failed */ 669 if (numeric == 691) 670 { 671 unreal_log(ULOG_WARNING, "link", "STARTTLS_FAILED", client, 672 "Switching from plaintext to TLS via STARTTLS failed for server $client, this is unusual. " 673 "Please check the other side of the link for errors."); 674 reject_insecure_server(client); 675 return 0; 676 } 677 678 /* STARTTLS OK */ 679 if (numeric == 670) 680 { 681 int ret = client_starttls(client); 682 if (ret < 0) 683 { 684 unreal_log(ULOG_WARNING, "link", "STARTTLS_FAILED", client, 685 "Switching from plaintext to TLS via STARTTLS failed for server $client, this is unusual."); 686 reject_insecure_server(client); 687 return ret; 688 } 689 /* We don't call start_server_handshake() here. First the TLS handshake will 690 * be completed, then completed_connection() will be called for a second time, 691 * which will call completed_connection() from there. 692 */ 693 return 0; 694 } 695 } 696 697 /* Other than the (strange) code from above, we actually 698 * don't process numerics from non-servers. So return here. 699 */ 700 if ((parc < 2) || BadPtr(parv[1]) || !IsServer(client)) 701 return 0; 702 703 /* Remap low number numerics. */ 704 if (numeric < 100) 705 numeric += 100; 706 707 /* Convert parv[] back to a string 'buffer', since that is 708 * what we use in the sendto_* functions below. 709 */ 710 concat_params(buffer, sizeof(buffer), parc, parv); 711 712 /* Now actually process the numeric, IOTW: send it on */ 713 strlcpy(targets, parv[1], sizeof(targets)); 714 for (nick = strtoken(&p, targets, ","); nick; nick = strtoken(&p, NULL, ",")) 715 { 716 if ((acptr = find_client(nick, NULL))) 717 { 718 if (!IsMe(acptr) && IsUser(acptr)) 719 { 720 if (MyConnect(acptr) && isdigit(*nick)) 721 { 722 /* Hack to prevent leaking UID */ 723 char *skip = strchr(buffer, ' '); 724 if (skip) 725 { 726 sendto_prefix_one(acptr, client, recv_mtags, ":%s %d %s %s", 727 client->name, numeric, acptr->name, skip+1); 728 } /* else.. malformed (no content) */ 729 } else { 730 sendto_prefix_one(acptr, client, recv_mtags, ":%s %d %s", 731 client->name, numeric, buffer); 732 } 733 } 734 else if (IsServer(acptr) && acptr->direction != client->direction) 735 sendto_prefix_one(acptr, client, recv_mtags, ":%s %d %s", 736 client->name, numeric, buffer); 737 } 738 else if ((acptr = find_server_quick(nick))) 739 { 740 if (!IsMe(acptr) && acptr->direction != client->direction) 741 sendto_prefix_one(acptr, client, recv_mtags, ":%s %d %s", 742 client->name, numeric, buffer); 743 } 744 else if ((channel = find_channel(nick))) 745 { 746 sendto_channel(channel, client, client->direction, 747 0, 0, SEND_ALL, recv_mtags, 748 ":%s %d %s", client->name, numeric, buffer); 749 } 750 } 751 752 return 0; 753 } 754 755 // FIXME: aren't we exiting the wrong client? 756 static void cancel_clients(Client *cptr, Client *client, char *cmd) 757 { 758 if (IsServer(cptr) || IsServer(client) || IsMe(client)) 759 return; 760 exit_client(cptr, NULL, "Fake prefix"); 761 } 762 763 static void remove_unknown(Client *client, char *sender) 764 { 765 if (!IsRegistered(client) || IsUser(client)) 766 return; 767 /* 768 * Not from a server so don't need to worry about it. 769 */ 770 if (!IsServer(client)) 771 return; 772 773 /* 774 * Do kill if it came from a server because it means there is a ghost 775 * user on the other server which needs to be removed. -avalon 776 */ 777 if ((isdigit(*sender) && strlen(sender) <= SIDLEN) || strchr(sender, '.')) 778 sendto_one(client, NULL, ":%s SQUIT %s :Unknown prefix (%s) from %s", 779 me.id, sender, sender, client->name); 780 else 781 sendto_one(client, NULL, ":%s KILL %s :Ghost user", me.id, sender); 782 }