1 /*
2 * ctcp.c:handles the client-to-client protocol(ctcp).
3 *
4 * Copyright (c) 1990 Michael Sandroff.
5 * Copyright (c) 1991, 1992 Troy Rollo.
6 * Copyright (c) 1992-1996 Matthew Green.
7 * Copyright 1993, 2018 EPIC Software Labs
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notices, the above paragraph (the one permitting redistribution),
17 * this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The names of the author(s) may not be used to endorse or promote
20 * products derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35 /* Major revamps in 1996 and 2018 */
36
37 #include "irc.h"
38 #include "sedcrypt.h"
39 #include "ctcp.h"
40 #include "dcc.h"
41 #include "commands.h"
42 #include "hook.h"
43 #include "ignore.h"
44 #include "ircaux.h"
45 #include "lastlog.h"
46 #include "names.h"
47 #include "output.h"
48 #include "parse.h"
49 #include "server.h"
50 #include "status.h"
51 #include "vars.h"
52 #include "window.h"
53 #include "ifcmd.h"
54 #include "flood.h"
55 #include "words.h"
56 #include "functions.h"
57
58 #include <pwd.h>
59 #ifdef HAVE_UNAME
60 # include <sys/utsname.h>
61 #endif
62
63 /* CTCP BITFLAGS */
64 #define CTCP_SPECIAL 1 /* Special handlers handle everything and don't return anything */
65 #define CTCP_ORDINARY 2 /* Ordinary handlers either return a inline value or you should tell the user */
66 #define CTCP_REPLACE_ARGS 4 /* A "replace args" CTCP rewrites the args, but still needs to be "handled" normally */
67 #define CTCP_RAW 32 /* Requires the original payload, not a recoded message */
68
69 /* CTCP ENTRIES */
70 /*
71 * A CTCP Entry lists the built in CTCPs
72 * Out of the box, the client comes with some CTCPs implemented as C functions.
73 * You can add your own CTCP handlers with ircII aliases.
74 *
75 * "Why should I register a CTCP handler rather than using /on ctcp_request?"
76 * you might ask. There needs to be a way to script a CTCP handler that can
77 * expand inline (such as CTCP UTC), and there's no good way to do that with
78 * an /ON.
79 *
80 * CTCP Handlers (whether in C or ircII take 4 arguments:
81 * $0 - The sender of the CTCP
82 * $1 - The receiver of the CTCP (ie, you, or a channel)
83 * $2 - The kind of CTCP (ie, ACTION or VERSION or DCC)
84 * $3 - Arguments to the CTCP (not all CTCPs have arguments - can be NULL)
85 */
86 typedef char *(*CTCP_Handler) (const char *, const char *, const char *, char *);
87 typedef struct _CtcpEntry
88 {
89 int flag; /* Action modifiers */
90 char * desc; /* description returned by ctcp clientinfo */
91 CTCP_Handler func; /* C function to handle requests */
92 CTCP_Handler repl; /* C function to handle replies */
93 char * user_func; /* Block of code to handle requests */
94 char * user_repl; /* Block of code to handle replies */
95 } CtcpEntry;
96
97 /*
98 * Let's review buckets real quick...
99 * Buckets are an (insert-)ordered array of key-value pairs
100 *
101 * The bucket itself contains
102 * numitems -> The number of items in the bucket
103 * list -> An array of (BucketItem *)s, from (0 to numitems - 1)
104 *
105 * Each BucketItem is just a key-value pair:
106 * name -> (char *)
107 * stuff -> (void *)
108 *
109 * Thus, bucket->list[i] is the i'th bucket item.
110 * bucket->list[i].name is the key (name) of the i'th bucket item
111 * bucket->list[i].stuff is the value of the i'th bucket item.
112 */
113
114 static Bucket *ctcp_bucket = NULL;
115
116 /* The name of a CTCP is now the Key of the BucketItem. it used to be in the value */
117 #define CTCP_NAME(i) ctcp_bucket->list[i].name
118
119 /* The value of a CTCP is the Value of the BucketItem. */
120 #define CTCP(i) ((CtcpEntry *)ctcp_bucket->list[i].stuff)
121
122 static int in_ctcp = 0;
123
124 /*
125 * lookup_ctcp - Convert a CTCP name into a CTCP index.
126 *
127 * Arguments:
128 * name - the name of a CTCP to be searched for
129 *
130 * Return value:
131 * -1 - 'name' does not map to an internal CTCP
132 * >= 0 - 'name' refers to an internal CTCP, an integer 'r'
133 * such that CTCP(r) and CTCP_NAME(r) refer to that CTCP
134 */
lookup_ctcp(const char * name)135 static int lookup_ctcp (const char *name)
136 {
137 int i;
138
139 for (i = 0; i < ctcp_bucket->numitems; i++)
140 if (my_stricmp(name, CTCP_NAME(i)) == 0)
141 return i;
142
143 return -1;
144 }
145
146
147 /*
148 * To make it easier on myself, I use a macro to ensure ctcp handler C functions
149 * are always prototyped correctly.
150 */
151 #define CTCP_HANDLER(x) \
152 static char * x (const char *from, const char *to, const char *cmd, char *args)
153
add_ctcp(const char * name,int flag,const char * desc,CTCP_Handler func,CTCP_Handler repl,const char * user_func,const char * user_repl)154 static void add_ctcp (const char *name, int flag, const char *desc, CTCP_Handler func, CTCP_Handler repl, const char *user_func, const char *user_repl)
155 {
156 CtcpEntry *ctcp;
157 int numval;
158 const char *strval;
159 char * name_copy;
160
161 ctcp = (CtcpEntry *)new_malloc(sizeof(CtcpEntry));
162 ctcp->flag = flag;
163 ctcp->desc = malloc_strdup(desc);
164
165 ctcp->func = func;
166 ctcp->repl = repl;
167
168 if (user_func)
169 ctcp->user_func = malloc_strdup(user_func);
170 else
171 ctcp->user_func = NULL;
172 if (user_repl)
173 ctcp->user_repl = malloc_strdup(user_repl);
174 else
175 ctcp->user_repl = NULL;
176
177 /* The 'name' belongs to the bucket, so it must be malloc()ed */
178 name_copy = malloc_strdup(name);
179 add_to_bucket(ctcp_bucket, name_copy, ctcp);
180 }
181
182 /*
183 * XXX This global variable is sadly used to tell other systems
184 * about whether a CTCP resulted in an encrypted message.
185 * (SED stands for "Simple Encrypted Data", which used to be the
186 * only form of encryption). There has not yet been designed
187 * an easier way to pass this kind of info back to the handler
188 * that has to decide whether to throw /on encrypted_privmsg or not.
189 * Oh well.
190 */
191 int sed = 0;
192
193
194 /**************************** CTCP PARSERS ****************************/
195
196 /********** INLINE EXPANSION CTCPS ***************/
197 /*
198 * do_crypt: Generalized decryption for /CRYPT targets
199 *
200 * Notes:
201 * This supports encryption over DCC CHAT (`from' will start with "=")
202 * If the CTCP was sent to a channel, then the peer is the "target".
203 * If the CTCP was not sent to a channel, then the peer is the sender.
204 *
205 * It will look up to see if you have a /crypt for the peer for the kind of
206 * encryption. If you do have a /crypt, it will decrypt the message.
207 * If you do not have a /crypt, it will return "[ENCRYPTED MESSAGE]".
208 */
CTCP_HANDLER(do_crypto)209 CTCP_HANDLER(do_crypto)
210 {
211 Crypt *key = NULL;
212 const char *crypt_who;
213 char *tofrom;
214 char *ret = NULL;
215 char *extra = NULL;
216
217 if (*from == '=') /* DCC CHAT message */
218 crypt_who = from;
219 else if (is_me(from_server, to))
220 crypt_who = from;
221 else
222 crypt_who = to;
223
224 tofrom = malloc_strdup3(to, ",", from);
225 malloc_strcat2_c(&tofrom, "!", FromUserHost, NULL);
226
227 if ((key = is_crypted(tofrom, from_server, cmd)) ||
228 (key = is_crypted(crypt_who, from_server, cmd)))
229 ret = decrypt_msg(args, key);
230
231 new_free(&tofrom);
232
233 /*
234 * Key would be NULL if someone sent us a rogue encrypted
235 * message (ie, we don't have a password). Ret should never
236 * be NULL (but we can be defensive against the future).
237 * In either case, something went seriously wrong.
238 */
239 if (!key || !ret)
240 {
241 if (ret)
242 new_free(&ret);
243
244 sed = 2;
245 malloc_strcpy(&ret, "[ENCRYPTED MESSAGE]");
246 return ret;
247 }
248
249
250 /*
251 * NOW WE HANDLE THE DECRYPTED MESSAGE....
252 */
253
254 /*
255 * CTCP messages can be recursive (ie, a decrypted msg
256 * might yield another CTCP message), and so we must not
257 * recode until we have removed any sub-ctcps!
258 */
259 if (get_server_doing_privmsg(from_server) > 0)
260 extra = malloc_strdup(do_ctcp(1, from, to, ret));
261 else if (get_server_doing_notice(from_server) > 0)
262 extra = malloc_strdup(do_ctcp(0, from, to, ret));
263 else
264 {
265 extra = ret;
266 ret = NULL;
267 }
268
269 new_free(&ret);
270 ret = extra;
271 extra = NULL;
272
273 /*
274 * What we're left with is just the plain part of the CTCP.
275 * In rfc1459_any_to_utf8(), CTCP messages are specifically
276 * detected and ignored [because recoding binary data will
277 * corrupt the data]. But that does not mean the message
278 * doesn't need decoding -- it just needs to be done after
279 * the message is decrypted.
280 */
281 inbound_recode(from, from_server, to, ret, &extra);
282
283 /*
284 * If a recoding actually occurred, free the source string
285 * and then use the decoded string going forward.
286 */
287 if (extra)
288 {
289 new_free(&ret);
290 ret = extra;
291 }
292
293 sed = 1;
294 return ret;
295 }
296
297 /*
298 * CTCP ACTION - Creates a special "ACTION" level message
299 * Does not reply.
300 * The original CTCP ACTION done by lynX
301 */
CTCP_HANDLER(do_atmosphere)302 CTCP_HANDLER(do_atmosphere)
303 {
304 int l;
305 int ignore, flood;
306
307 if (!args || !*args)
308 return NULL;
309
310 /* Xavier mentioned that we should allow /ignore #chan action */
311 ignore = check_ignore_channel(from, FromUserHost, to, LEVEL_ACTION);
312 flood = new_check_flooding(from, FromUserHost,
313 is_channel(to) ? to : NULL,
314 args, LEVEL_ACTION);
315
316 if (ignore == IGNORED || flood)
317 return NULL;
318
319 if (is_channel(to))
320 {
321 l = message_from(to, LEVEL_ACTION);
322 if (do_hook(ACTION_LIST, "%s %s %s", from, to, args))
323 {
324 if (is_current_channel(to, from_server))
325 put_it("* %s %s", from, args);
326 else
327 put_it("* %s:%s %s", from, to, args);
328 }
329 }
330 else
331 {
332 l = message_from(from, LEVEL_ACTION);
333 if (do_hook(ACTION_LIST, "%s %s %s", from, to, args))
334 put_it("*> %s %s", from, args);
335 }
336
337 pop_message_from(l);
338 return NULL;
339 }
340
341 /*
342 * CTCP DCC - Direct Client Connections (file transfers and private chats)
343 * Does not reply.
344 * Only user->user CTCP DCCs are acceptable.
345 */
CTCP_HANDLER(do_dcc)346 CTCP_HANDLER(do_dcc)
347 {
348 char *type;
349 char *description;
350 char *inetaddr;
351 char *port;
352 char *size;
353 char *extra_flags;
354
355 if (!is_me(from_server, to) && *from != '=')
356 return NULL;
357
358 if (!(type = next_arg(args, &args)) ||
359 !(description = (get_int_var(DCC_DEQUOTE_FILENAMES_VAR)
360 ? new_next_arg(args, &args)
361 : next_arg(args, &args))) ||
362 !(inetaddr = next_arg(args, &args)) ||
363 !(port = next_arg(args, &args)))
364 return NULL;
365
366 size = next_arg(args, &args);
367 extra_flags = next_arg(args, &args);
368
369 register_dcc_offer(from, type, description, inetaddr, port, size, extra_flags, args);
370 return NULL;
371 }
372
373 /*
374 * If we recieve a CTCP DCC REJECT in a notice, then we want to remove
375 * the offending DCC request
376 */
CTCP_HANDLER(do_dcc_reply)377 CTCP_HANDLER(do_dcc_reply)
378 {
379 char *subargs = NULL;
380 char *type = NULL;
381
382 if (is_channel(to))
383 return NULL;
384
385 if (args && *args)
386 subargs = next_arg(args, &args);
387 if (args && *args)
388 type = next_arg(args, &args);
389
390 if (subargs && type && !strcmp(subargs, "REJECT"))
391 dcc_reject(from, type, args);
392
393 return NULL;
394 }
395
396
397 /************************************************************************/
398 /*
399 * split_CTCP - Extract a CTCP out of a message body
400 *
401 * Arguments:
402 * raw_message -- A message, either a PRIVMSG, NOTICE, or DCC CHAT.
403 * - If the message contains a CTCP, then the string
404 * will be truncated to the part before the CTCP.
405 * - If the message does not contain a CTCP, it is
406 * unchanged.
407 * ctcp_dest -- A buffer (of size IRCD_BUFFER_SIZE)
408 * - If the message contains a CTCP, then the CTCP
409 * itself (without the CTCP_DELIMs) will be put
410 * in here.
411 * - If the message does not contain a CTCP, it is
412 * unchanged
413 * after_ctcp -- A buffer (of size IRCD_BUFFER_SIZE)
414 * - If the message contains a CTCP, then the part
415 * of the message after the CTCP will be put in here
416 * - If the message does not contain a CTCP, it is
417 * unchanged
418 *
419 * Return value:
420 * -1 - No CTCP was found. All parameters are unchanged
421 * 0 - A CTCP was found. All three parameters were changed
422 */
split_CTCP(char * raw_message,char * ctcp_dest,char * after_ctcp)423 static int split_CTCP (char *raw_message, char *ctcp_dest, char *after_ctcp)
424 {
425 char *ctcp_start,
426 *ctcp_end;
427
428 *ctcp_dest = *after_ctcp = 0;
429
430 if (!(ctcp_start = strchr(raw_message, CTCP_DELIM_CHAR)))
431 return -1; /* No CTCPs present. */
432
433 if (!(ctcp_end = strchr(ctcp_start + 1, CTCP_DELIM_CHAR)))
434 return -1; /* No CTCPs present after all */
435
436 *ctcp_start++ = 0;
437 *ctcp_end++ = 0;
438
439 strlcpy(ctcp_dest, ctcp_start, IRCD_BUFFER_SIZE - 1);
440 strlcpy(after_ctcp, ctcp_end, IRCD_BUFFER_SIZE - 1);
441 return 0; /* All done! */
442 }
443
444
445 /*
446 * do_ctcp - Remove and process all CTCPs within a message
447 *
448 * Arguments:
449 * request - Am i processing a request or a response?
450 * 1 = This is a PRIVMSG or DCC CHAT (a request)
451 * 0 = This is a NOTICE (a response)
452 * from - Who sent the CTCP
453 * to - Who received the CTCP (nick, channel, wall)
454 * str - The message we received. (may be modified)
455 * This must be at least BIG_BUFFER_SIZE+1 or bigger.
456 *
457 * Return value:
458 * 'str' is returned.
459 * 'str' may be modified.
460 * It is guaranteed that 'str' shall contain no CTCPs upon return.
461 */
do_ctcp(int request,const char * from,const char * to,char * str)462 char * do_ctcp (int request, const char *from, const char *to, char *str)
463 {
464 int flag;
465 int fflag;
466 char local_ctcp_buffer [BIG_BUFFER_SIZE + 1],
467 the_ctcp [IRCD_BUFFER_SIZE + 1],
468 after [IRCD_BUFFER_SIZE + 1];
469 char *ctcp_command,
470 *ctcp_argument;
471 char *original_ctcp_argument;
472 int i;
473 char *ptr = NULL;
474 int dont_process_more = 0;
475 static time_t last_ctcp_parsed = 0;
476 int l;
477 char * extra = NULL;
478 int delim_char;
479
480 /*
481 * Messages with less than 2 CTCP delims don't have a CTCP in them.
482 * Messages with > 8 delims are probably rogue/attack messages.
483 * We can save a lot of cycles by heading those off at the pass.
484 */
485 delim_char = charcount(str, CTCP_DELIM_CHAR);
486 if (delim_char < 2)
487 return str; /* No CTCPs. */
488 if (delim_char > 8)
489 dont_process_more = 1; /* Historical limit of 4 CTCPs */
490
491
492 /*
493 * Ignored CTCP messages, or requests during a flood, are
494 * removed, but not processed.
495 * Although all CTCPs are subject to IGNORE, and requests are subject
496 * to flood control; we must apply these restrictions on the inside
497 * of the loop, for each CTCP we see.
498 */
499 flag = check_ignore_channel(from, FromUserHost, to, LEVEL_CTCP);
500 if (request)
501 fflag = new_check_flooding(from, FromUserHost,
502 is_channel(to) ? to : NULL,
503 str, LEVEL_CTCP);
504 else
505 fflag = 0;
506
507 /* /IGNOREd or flooding messages are removed but not processed */
508 if (flag == IGNORED || fflag == 1)
509 dont_process_more = 1;
510
511 /* Messages sent to global targets are removed but not processed */
512 if (*to == '$' || (*to == '#' && !im_on_channel(to, from_server)))
513 dont_process_more = 1;
514
515
516
517 /* Set up the window level/logging */
518 if (im_on_channel(to, from_server))
519 l = message_from(to, LEVEL_CTCP);
520 else
521 l = message_from(from, LEVEL_CTCP);
522
523
524 /* For each CTCP we extract from 'local_ctcp_buffer'.... */
525 strlcpy(local_ctcp_buffer, str, sizeof(local_ctcp_buffer) - 2);
526 for (;;new_free(&extra), strlcat(local_ctcp_buffer, after, sizeof(local_ctcp_buffer) - 2))
527 {
528 /* Extract next CTCP. If none found, we're done! */
529 if (split_CTCP(local_ctcp_buffer, the_ctcp, after))
530 break; /* All done! */
531
532 /* If the CTCP is empty (ie, ^A^A), ignore it. */
533 if (!*the_ctcp)
534 continue;
535
536 /* If we're removing-but-not-processing CTCPs, ignore it */
537 if (dont_process_more)
538 continue;
539
540
541 /* * * */
542 /* Seperate the "command" from the "argument" */
543 ctcp_command = the_ctcp;
544 if ((ctcp_argument = strchr(the_ctcp, ' ')))
545 *ctcp_argument++ = 0;
546 else
547 ctcp_argument = endstr(the_ctcp);
548
549 /*
550 * rfc1459_any_to_utf8 specifically ignores CTCPs, because
551 * recoding binary data (such as an encrypted message) would
552 * corrupt the message.
553 *
554 * So some CTCPs are "recodable" and some are not.
555 *
556 * The CTCP_RAW is set for any CTCPs which are NOT
557 * to be recoded prior to handling. These are the encryption
558 * CTCPS.
559 *
560 * For the NORECORD ctcps, we save "original_ctcp_argument"
561 * For everybody else, 'ctcp_argument' is recoded.
562 */
563 original_ctcp_argument = ctcp_argument;
564 inbound_recode(from, from_server, to, ctcp_argument, &extra);
565 if (extra)
566 ctcp_argument = extra;
567
568 /*
569 * Offer it to the user FIRST.
570 * CTCPs handled via /on CTCP_REQUEST are treated as
571 * ordinary "i sent a reply" CTCPs
572 */
573 if (request)
574 {
575 in_ctcp++;
576
577 /* If the user "handles" it, then we're done with it! */
578 if (!do_hook(CTCP_REQUEST_LIST, "%s %s %s %s",
579 from, to, ctcp_command, ctcp_argument))
580 {
581 in_ctcp--;
582 dont_process_more = 1;
583 continue;
584 }
585
586 in_ctcp--;
587 /*
588 * User did not "handle" it. with /on ctcp_request.
589 * Let's continue on!
590 */
591 }
592
593 /*
594 * Next, look for a built-in CTCP handler
595 */
596 /* Does this CTCP have a built-in handler? */
597 for (i = 0; i < ctcp_bucket->numitems; i++)
598 {
599 if (!strcmp(ctcp_command, CTCP_NAME(i)))
600 {
601 /* This counts only if there is a function to call! */
602 if (request && (CTCP(i)->func || CTCP(i)->user_func))
603 break;
604 else if (!request && (CTCP(i)->repl || CTCP(i)->user_repl))
605 break;
606 }
607 }
608
609 /* There is a function to call. */
610 if (i < ctcp_bucket->numitems)
611 {
612 if ((CTCP(i)->flag & CTCP_RAW))
613 ctcp_argument = original_ctcp_argument;
614
615 in_ctcp++;
616
617 /* Call the appropriate callback (four-ways!) */
618 if (request)
619 {
620 if (CTCP(i)->user_func)
621 {
622 char *args = NULL;
623 malloc_sprintf(&args, "%s %s %s %s", from, to, ctcp_command, ctcp_argument);
624 ptr = call_lambda_function("CTCP", CTCP(i)->user_func, args);
625 new_free(&args);
626 }
627 else if (CTCP(i)->func)
628 ptr = CTCP(i)->func(from, to, ctcp_command, ctcp_argument);
629 }
630 else
631 {
632 if (CTCP(i)->user_repl)
633 {
634 char *args = NULL;
635 malloc_sprintf(&args, "%s %s %s %s", from, to, ctcp_command, ctcp_argument);
636 ptr = call_lambda_function("CTCP", CTCP(i)->user_repl, args);
637 /* An empty string is the same as NULL here */
638 if (!ptr || !*ptr)
639 new_free(&ptr);
640 new_free(&args);
641 }
642 else if (CTCP(i)->repl)
643 ptr = CTCP(i)->repl(from, to, ctcp_command, ctcp_argument);
644 }
645 in_ctcp--;
646
647 /***** Was the CTCP "handled"? *****/
648
649 /*
650 * A CTCP that returns a value is either a
651 * - Argument replacer (CTCP_REPLACE_ARGS) [CTCP PING]
652 * - Whole-string replacer (default) [CTCP AES256-CBC]
653 *
654 * Whole-string replacers paste themselves back inline and
655 * then go around for another pass.
656 *
657 * Argument Replacers are still "handled" in the ordinary way.
658 */
659 if (ptr)
660 {
661 if (CTCP(i)->flag & CTCP_REPLACE_ARGS)
662 {
663 /*
664 * "extra" is where we stuck the original ctcp arguments.
665 * When a CTCP is handled ordinarily, it will retrieve
666 * the CTCP arguments from 'extra'. So if we are replacing
667 * the arguments, it is only logical to put them in 'extra'.
668 *
669 * This works even if extra == NULL here (because there was
670 * no recoding), because we unconditionally reset
671 * ctcp_argument to extra below.
672 */
673 malloc_strcpy(&extra, ptr);
674 new_free(&ptr);
675 }
676 else
677 {
678 strlcat(local_ctcp_buffer, ptr, sizeof local_ctcp_buffer);
679 new_free(&ptr);
680 /* continue; */ /* XXX Sigh */
681 }
682 }
683
684 /*
685 * A CTCP that does not return a value but is "special" (/me, /dcc)
686 * is considered "handled"
687 */
688 if (CTCP(i)->flag & CTCP_SPECIAL)
689 continue;
690
691 /* Otherwise, let's continue on! */
692 }
693
694 /* Default handling -- tell the user about it */
695 /* !!!! Don't remove this, without reading the comments above !!! */
696 if (extra)
697 ctcp_argument = extra;
698 in_ctcp++;
699 if (request)
700 {
701 if (do_hook(CTCP_LIST, "%s %s %s %s", from, to,
702 ctcp_command, ctcp_argument))
703 {
704 if (is_me(from_server, to))
705 say("CTCP %s from %s%s%s",
706 ctcp_command, from,
707 *ctcp_argument ? ": " : empty_string,
708 ctcp_argument);
709 else
710 say("CTCP %s from %s to %s%s%s",
711 ctcp_command, from, to,
712 *ctcp_argument ? ": " : empty_string,
713 ctcp_argument);
714 }
715 }
716 else
717 {
718 if (do_hook(CTCP_REPLY_LIST, "%s %s %s %s",
719 from, to, ctcp_command, ctcp_argument))
720 say("CTCP %s reply from %s: %s",
721 ctcp_command, from, ctcp_argument);
722
723 }
724 in_ctcp--;
725
726 dont_process_more = 1;
727 }
728
729 /*
730 * When we are all done, 'local_ctcp_buffer' contains a message without
731 * any CTCPs in it!
732 *
733 * 'str' is required to be BIG_BUFFER_SIZE + 1 or bigger per the API.
734 */
735 pop_message_from(l);
736 strlcpy(str, local_ctcp_buffer, BIG_BUFFER_SIZE);
737 return str;
738 }
739
740
741 /*
742 * send_ctcp - Format and send a properly encoded CTCP message
743 *
744 * Arguments:
745 * request - 1 - This is a CTCP request originating with the user
746 * 0 - This is a CTCP reply in response to a CTCP request
747 * Other values will have undefined behavior.
748 * to - The target to send the message to.
749 * type - A string describing the CTCP being sent or replied to.
750 * Previously this used to be an int into an array of strings,
751 * but this is all free-form now.
752 * format - NULL -- If the CTCP does not provide any arguments
753 * A printf() format -- If the CTCP does provide any arguments
754 *
755 * Notes:
756 * Because we use send_text(), the following things happen automatically:
757 * - We can CTCP any target, including DCC CHATs
758 * - All encryption is honored
759 * We also honor all appropriate /encode-ings
760 *
761 * Example:
762 * To send a /me to a channel:
763 * send_ctcp("PRIVMSG", channel, "ACTION", "%s", message);
764 */
send_ctcp(int request,const char * to,const char * type,const char * format,...)765 void send_ctcp (int request, const char *to, const char *type, const char *format, ...)
766 {
767 char * putbuf2;
768 int len;
769 int l;
770 const char *protocol;
771 static time_t last_ctcp_reply = 0;
772
773 /* Make sure that the final \001 doesnt get truncated */
774 if ((len = IRCD_BUFFER_SIZE - (12 + strlen(to))) <= 0)
775 return; /* Whatever. */
776 putbuf2 = alloca(len);
777
778 if (request)
779 protocol = "PRIVMSG";
780 else
781 protocol = "NOTICE";
782
783 /*
784 * Enforce _outbound_ CTCP Response Flood Protection.
785 * To keep botnets from flooding us off by sending
786 * us a flurry of CTCP requests from different nicks,
787 * we refuse to send a CTCP response until 2 seconds
788 * of quiet has happened.
789 *
790 * This only affects responses. We never throttle
791 * requests.
792 */
793 if (!request && get_int_var(NO_CTCP_FLOOD_VAR))
794 {
795 if (time(NULL) - last_ctcp_reply < 2)
796 {
797 /*
798 * This extends the flood protection until
799 * we dont get a CTCP for 2 seconds.
800 */
801 last_ctcp_reply = time(NULL);
802 if (x_debug & DEBUG_CTCPS)
803 say("CTCP flood reply to [%s] dropped", to);
804 return;
805 }
806 }
807
808 #if 0
809 if (in_ctcp == 0)
810 protocol = "PRIVMSG";
811 else
812 protocol = "NOTICE";
813 #endif
814
815 l = message_from(to, LEVEL_CTCP);
816 if (format)
817 {
818 const char *pb;
819 char * extra = NULL;
820 char putbuf [BIG_BUFFER_SIZE + 1];
821 va_list args;
822
823 va_start(args, format);
824 vsnprintf(putbuf, BIG_BUFFER_SIZE, format, args);
825 va_end(args);
826
827 /*
828 * We only recode the ARGUMENTS because the base
829 * part of the CTCP is expected to be 7-bit ascii.
830 * This isn't strictly enforced, so if you send a
831 * CTCP message with a fancy type name, the behavior
832 * is unspecified.
833 */
834 pb = outbound_recode(to, from_server, putbuf, &extra);
835
836 do_hook(SEND_CTCP_LIST, "%s %s %s %s",
837 protocol, to, type, pb);
838 snprintf(putbuf2, len, "%c%s %s%c",
839 CTCP_DELIM_CHAR, type, pb, CTCP_DELIM_CHAR);
840
841 new_free(&extra);
842 }
843 else
844 {
845 do_hook(SEND_CTCP_LIST, "%s %s %s",
846 protocol, to, type);
847 snprintf(putbuf2, len, "%c%s%c",
848 CTCP_DELIM_CHAR, type, CTCP_DELIM_CHAR);
849 }
850
851 /* XXX - Ugh. What a hack. */
852 putbuf2[len - 2] = CTCP_DELIM_CHAR;
853 putbuf2[len - 1] = 0;
854
855 send_text(from_server, to, putbuf2, protocol, 0, 1);
856 pop_message_from(l);
857 }
858
859
860 /*
861 * In a slight departure from tradition, this ctl function is not object-oriented (restful)
862 *
863 * $ctcpctl(SET <ctcp-name> REQUEST {code})
864 * Register {code} to be run when client gets a CTCP <ctcp-name> request.
865 * - If {code} returns a string, that string replaces the CTCP request in
866 * the message. The user is not otherwise notified.
867 * - If {code} does not return a string, the CTCP is removed normally,
868 * and the user is notified of the CTCP request normally
869 * This creates the new CTCP if necessary.
870 * Setting a user callback will supercede any internal callback.
871 *
872 * $ctcpctl(SET <ctcp-name> RESPONSE {code})
873 * Register {code} to be run when client gets a CTCP <ctcp-name> reply.
874 * - If {code} returns a string, that string replaces the CTCP request in
875 * the message. The user is not otherwise notified.
876 * - If {code} does not return a string, the CTCP is removed normally,
877 * and the user is notified of the CTCP response normally.
878 * Setting a user callback will supercede any internal callback.
879 *
880 * $ctcpctl(SET <ctcp-name> DESCRIPTION <alias_name>)
881 * Each CTCP has a "description string", which is used by CTCP CLIENTINFO.
882 *
883 * $ctcpctl(SET <ctcp-name> SPECIAL 1|0)
884 * A CTCP can be "special", meaning it is entirely self-contained and acts
885 * as a sink of data. The two special CTCPs are CTCP ACTION (/me) and
886 * CTCP DCC (/dcc). You can make your own special DCCs, but be careful.
887 *
888 * $ctcpctl(SET <ctcp-name> REPLACE_ARGS 1|0)
889 * A CTCP handler that returns a value is either a "replacer" or a "rewriter".
890 * A "Replacer" replaces the arguments to the CTCP (this is what CTCP PING does)
891 * A "Rewriter" replaces the entire CTCP with a different string (this is
892 * what crypto CTCPs do)
893 * When this is 1, it is a "replacer". When this is 0, it is a "rewriter".
894 *
895 * $ctcpctl(SET <ctcp-name> RAW 1|0)
896 * Ordinarily, everything in the client is a string and has to be subject
897 * to /encode recoding to make it utf-8 before your ircII code gets to
898 * interact with it. Some CTCPs, like the encryption ctcps, work on
899 * raw/binary data that must not get recoded because it's not a string.
900 * If RAW is turned on, you will get the raw CTCP-encoded binary
901 * data, which you _must not_ pass to /echo unless you like things to
902 * break.
903 *
904 * $ctcpctl(GET <ctcp-name> REQUEST)
905 * $ctcpctl(GET <ctcp-name> RESPONSE)
906 * $ctcpctl(GET <ctcp-name> DESCRIPTION)
907 * $ctcpctl(GET <ctcp-name> SPECIAL)
908 * $ctcpctl(GET <ctcp-name> RAW)
909 * Fetch information about a built-in CTCP. If <ctcp-name> does not
910 * represent an internal CTCP, or the value requested does not apply,
911 * (such as a CTCP that does not have a user-defined REQUEST or
912 * RESPONSE), the empty string is returned.
913 *
914 * Additionally:
915 *
916 * $ctcpctl(ALL)
917 * Returns the names of all built-in/registered CTCPs
918 */
BUILT_IN_FUNCTION(function_ctcpctl,input)919 BUILT_IN_FUNCTION(function_ctcpctl, input)
920 {
921 char * op;
922 size_t op_len;
923 char * ctcp_name;
924 size_t ctcp_name_len;
925 char * field;
926 size_t field_len;
927 int i;
928
929 GET_FUNC_ARG(op, input);
930 op_len = strlen(op);
931
932 if (!my_strnicmp(op, "ALL", op_len)) {
933 char buffer[BIG_BUFFER_SIZE + 1];
934 *buffer = '\0';
935
936 for (i = 0; i < ctcp_bucket->numitems; i++)
937 {
938 const char *name = CTCP_NAME(i);
939 strlcat(buffer, name, sizeof buffer);
940 strlcat(buffer, " ", sizeof buffer);
941 }
942 RETURN_STR(buffer);
943 }
944
945 GET_FUNC_ARG(ctcp_name, input);
946 GET_FUNC_ARG(field, input);
947
948 upper(ctcp_name);
949 i = lookup_ctcp(ctcp_name);
950
951 if (!my_strnicmp(op, "SET", op_len)) {
952 /* Boostrap a new built-in CTCP if necessary */
953 if (i == -1)
954 {
955 yell("Added a new CTCP named %s", ctcp_name);
956 add_ctcp(ctcp_name, CTCP_ORDINARY, ctcp_name, NULL, NULL, NULL, NULL);
957 i = lookup_ctcp(ctcp_name);
958 }
959
960 if (!my_stricmp(field, "REQUEST")) {
961 malloc_strcpy(&(CTCP(i)->user_func), input);
962 } else if (!my_stricmp(field, "RESPONSE")) {
963 malloc_strcpy(&(CTCP(i)->user_repl), input);
964 } else if (!my_stricmp(field, "DESCRIPTION")) {
965 malloc_strcpy(&(CTCP(i)->desc), input);
966 } else if (!my_stricmp(field, "SPECIAL")) {
967 if (!strcmp(input, one))
968 CTCP(i)->flag = (CTCP(i)->flag | CTCP_SPECIAL);
969 else if (!strcmp(input, zero))
970 CTCP(i)->flag = (CTCP(i)->flag & ~CTCP_SPECIAL);
971 else
972 RETURN_EMPTY;
973 } else if (!my_stricmp(field, "REPLACE_ARGS")) {
974 if (!strcmp(input, one))
975 CTCP(i)->flag = (CTCP(i)->flag | CTCP_REPLACE_ARGS);
976 else if (!strcmp(input, zero))
977 CTCP(i)->flag = (CTCP(i)->flag & ~CTCP_REPLACE_ARGS);
978 else
979 RETURN_EMPTY;
980 } else if (!my_stricmp(field, "RAW")) {
981 if (!strcmp(input, one))
982 CTCP(i)->flag = (CTCP(i)->flag | CTCP_RAW);
983 else if (!strcmp(input, zero))
984 CTCP(i)->flag = (CTCP(i)->flag & ~CTCP_RAW);
985 else
986 RETURN_EMPTY;
987 } else {
988 RETURN_EMPTY;
989 }
990
991 RETURN_INT(1);
992 } else if (!my_strnicmp(op, "GET", op_len)) {
993 if (!my_stricmp(field, "REQUEST")) {
994 RETURN_STR(CTCP(i)->user_func);
995 } else if (!my_stricmp(field, "RESPONSE")) {
996 RETURN_STR(CTCP(i)->user_repl);
997 } else if (!my_stricmp(field, "DESCRIPTION")) {
998 RETURN_STR(CTCP(i)->desc);
999 } else if (!my_stricmp(field, "SPECIAL")) {
1000 RETURN_INT((CTCP(i)->flag & CTCP_SPECIAL) != 0);
1001 } else if (!my_stricmp(field, "RAW")) {
1002 RETURN_INT((CTCP(i)->flag & CTCP_RAW) != 0);
1003 } else {
1004 RETURN_EMPTY;
1005 }
1006 } else {
1007 RETURN_EMPTY;
1008 }
1009 }
1010
init_ctcp(void)1011 int init_ctcp (void)
1012 {
1013 ctcp_bucket = new_bucket();
1014
1015 /* Special/Internal CTCPs */
1016 add_ctcp("ACTION", CTCP_SPECIAL,
1017 "contains action descriptions for atmosphere",
1018 do_atmosphere, do_atmosphere, NULL, NULL);
1019 add_ctcp("DCC", CTCP_SPECIAL,
1020 "requests a direct_client_connection",
1021 do_dcc, do_dcc_reply, NULL, NULL);
1022
1023 /* Strong Crypto CTCPs */
1024 add_ctcp("AESSHA256-CBC", CTCP_ORDINARY | CTCP_RAW,
1025 "transmit aes256-cbc ciphertext using a sha256 key",
1026 do_crypto, do_crypto, NULL, NULL );
1027 add_ctcp("AES256-CBC", CTCP_ORDINARY | CTCP_RAW,
1028 "transmit aes256-cbc ciphertext",
1029 do_crypto, do_crypto, NULL, NULL );
1030 add_ctcp("CAST128ED-CBC", CTCP_ORDINARY | CTCP_RAW,
1031 "transmit cast5-cbc ciphertext",
1032 do_crypto, do_crypto, NULL, NULL );
1033 add_ctcp("BLOWFISH-CBC", CTCP_ORDINARY | CTCP_RAW,
1034 "transmit blowfish-cbc ciphertext",
1035 do_crypto, do_crypto, NULL, NULL );
1036 add_ctcp("FISH", CTCP_ORDINARY | CTCP_RAW,
1037 "transmit FiSH (blowfish-ecb with sha256'd key) ciphertext",
1038 do_crypto, do_crypto, NULL, NULL );
1039 add_ctcp("SED", CTCP_ORDINARY | CTCP_RAW,
1040 "transmit simple_encrypted_data ciphertext",
1041 do_crypto, do_crypto, NULL, NULL );
1042 add_ctcp("SEDSHA", CTCP_ORDINARY | CTCP_RAW,
1043 "transmit simple_encrypted_data ciphertext using a sha256 key",
1044 do_crypto, do_crypto, NULL, NULL );
1045
1046 return 0;
1047 }
1048
1049 #if 0
1050 void help_topics_ctcp (FILE *f)
1051 {
1052 int x;
1053
1054 for (x = 0; ctcp_cmd[x].name; x++)
1055 fprintf(f, "ctcp %s\n", ctcp_cmd[x].name);
1056 }
1057 #endif
1058
1059
1060