ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/scan.c
Revision: 8193
Committed: Fri Apr 14 12:38:22 2017 UTC (9 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 26106 byte(s)
Log Message:
- Just pass a char pointer to the opercommand handlers instead of a struct ChannelConf pointer

File Contents

# Content
1 /*
2 * Copyright (c) 2002 Erik Fears
3 * Copyright (c) 2014-2017 ircd-hybrid development team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 * USA
19 */
20
21 #include "setup.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30
31 #include "compat.h"
32 #include "config.h"
33 #include "irc.h"
34 #include "log.h"
35 #include "stats.h"
36 #include "dnsbl.h"
37 #include "options.h"
38 #include "negcache.h"
39 #include "main.h"
40 #include "memory.h"
41 #include "match.h"
42 #include "misc.h"
43 #include "scan.h"
44
45 /* libopm includes */
46 #include "libopm/src/opm.h"
47 #include "libopm/src/opm_common.h"
48 #include "libopm/src/opm_error.h"
49 #include "libopm/src/opm_types.h"
50
51
52 /* GLOBAL LIST */
53 static list_t SCANNERS; /* List of OPM_T */
54
55 /* Function declarations */
56 static struct scan_struct *scan_create(const char *[], const char *);
57 static void scan_free(struct scan_struct *);
58 static void scan_irckline(const struct scan_struct *, const char *, const char *);
59 static void scan_negative(const struct scan_struct *);
60 static void scan_log(OPM_REMOTE_T *);
61
62 /** Callbacks for LIBOPM */
63 static void scan_open_proxy(OPM_T *, OPM_REMOTE_T *, int, void *);
64 static void scan_negotiation_failed(OPM_T *, OPM_REMOTE_T *, int, void *);
65 static void scan_timeout(OPM_T *, OPM_REMOTE_T *, int, void *);
66 static void scan_end(OPM_T *, OPM_REMOTE_T *, int, void *);
67 static void scan_handle_error(OPM_T *, OPM_REMOTE_T *, int, void *);
68
69 extern FILE *scanlogfile;
70
71
72 /* scan_cycle
73 *
74 * Perform scanner tasks.
75 */
76 void
77 scan_cycle(void)
78 {
79 node_t *node;
80
81 /* Cycle through the blacklist first.. */
82 dnsbl_cycle();
83
84 /* Cycle each scanner object */
85 LIST_FOREACH(node, SCANNERS.head)
86 {
87 struct scanner_struct *scs = node->data;
88 opm_cycle(scs->scanner);
89 }
90 }
91
92 /* scan_timer
93 *
94 * Perform actions that are to be performed every ~1 second.
95 *
96 * Parameters: NONE
97 * Return: NONE
98 *
99 */
100 void
101 scan_timer(void)
102 {
103 static time_t nc_counter;
104
105 if (OptionsItem->negcache)
106 {
107 if (nc_counter++ >= OptionsItem->negcache_rebuild)
108 {
109 /*
110 * Time to rebuild the negative cache.
111 */
112 if (OPT_DEBUG)
113 log_printf("SCAN -> Rebuilding negative cache");
114
115 negcache_rebuild();
116 nc_counter = 0;
117 }
118 }
119 }
120
121 /* scan_gettype(int protocol)
122 *
123 * Return human readable name of OPM PROTOCOL given OPM_TYPE_PROTOCOL
124 *
125 * Parameters:
126 * protocol: Protocol to return (from libopm/src/opm_types.h)
127 *
128 * Return:
129 * Pointer to static string containing human readable form of protocol
130 * name
131 *
132 */
133 const char *
134 scan_gettype(int protocol)
135 {
136 static const char *const undef = "undefined";
137 static const struct protocol_assoc protocols[] =
138 {
139 { .type = OPM_TYPE_HTTP, .name = "HTTP" },
140 { .type = OPM_TYPE_HTTPPOST, .name = "HTTPPOST" },
141 { .type = OPM_TYPE_SOCKS4, .name = "SOCKS4" },
142 { .type = OPM_TYPE_SOCKS5, .name = "SOCKS5" },
143 { .type = OPM_TYPE_WINGATE, .name = "WINGATE" },
144 { .type = OPM_TYPE_ROUTER, .name = "ROUTER" },
145 { .type = OPM_TYPE_HTTPS, .name = "HTTPS" },
146 { .type = OPM_TYPE_HTTPSPOST, .name = "HTTPSPOST" },
147 { .type = OPM_TYPE_DREAMBOX, .name = "DREAMBOX" },
148 { .type = 0 }
149 };
150
151 for (const struct protocol_assoc *tab = protocols; tab->type; ++tab)
152 if (protocol == tab->type)
153 return tab->name;
154
155 return undef;
156 }
157
158 /* scan_checkexempt
159 *
160 * Check mask against exempt list.
161 *
162 * Parameters:
163 * mask: Mask to check
164 *
165 * Return:
166 * 1 if mask is in list
167 * 0 if mask is not in list
168 */
169 static int
170 scan_checkexempt(const char *mask, const char *ipmask)
171 {
172 node_t *node;
173
174 LIST_FOREACH(node, ExemptItem->masks->head)
175 {
176 const char *exempt_mask = node->data;
177
178 if (!match(exempt_mask, mask) || !match(exempt_mask, ipmask))
179 return 1;
180 }
181
182 return 0;
183 }
184
185 /* scan_init
186
187 Initialize scanner and masks list based on configuration.
188
189 Parameters:
190 None
191
192 Return:
193 None
194 */
195 void
196 scan_init(void)
197 {
198 node_t *p, *p2, *p3, *p4, *node;
199
200 /* Setup each individual scanner */
201 LIST_FOREACH(p, ScannerItemList->head)
202 {
203 struct ScannerConf *sc = p->data;
204
205 if (OPT_DEBUG)
206 log_printf("SCAN -> Setting up scanner [%s]", sc->name);
207
208 /* Build the scanner */
209 struct scanner_struct *scs = xcalloc(sizeof(*scs));
210 scs->scanner = opm_create();
211 scs->name = xstrdup(sc->name);
212 scs->masks = list_create();
213
214 /* Setup configuration */
215 opm_config(scs->scanner, OPM_CONFIG_FD_LIMIT, &sc->fd);
216 opm_config(scs->scanner, OPM_CONFIG_SCAN_IP, sc->target_ip);
217 opm_config(scs->scanner, OPM_CONFIG_SCAN_PORT, &sc->target_port);
218 opm_config(scs->scanner, OPM_CONFIG_TIMEOUT, &sc->timeout);
219 opm_config(scs->scanner, OPM_CONFIG_MAX_READ, &sc->max_read);
220 opm_config(scs->scanner, OPM_CONFIG_BIND_IP, sc->vhost);
221
222 /* add target strings */
223 LIST_FOREACH(p2, sc->target_string->head)
224 opm_config(scs->scanner, OPM_CONFIG_TARGET_STRING, p2->data);
225
226 /* Setup callbacks */
227 opm_callback(scs->scanner, OPM_CALLBACK_OPENPROXY, &scan_open_proxy, scs);
228 opm_callback(scs->scanner, OPM_CALLBACK_NEGFAIL, &scan_negotiation_failed, scs);
229 opm_callback(scs->scanner, OPM_CALLBACK_TIMEOUT, &scan_timeout, scs);
230 opm_callback(scs->scanner, OPM_CALLBACK_END, &scan_end, scs);
231 opm_callback(scs->scanner, OPM_CALLBACK_ERROR, &scan_handle_error, scs);
232
233 /* Setup the protocols */
234 LIST_FOREACH(p2, sc->protocols->head)
235 {
236 struct ProtocolConf *pc = p2->data;
237
238 if (OPT_DEBUG >= 2)
239 log_printf("SCAN -> Adding protocol %s:%d to scanner [%s]",
240 scan_gettype(pc->type), pc->port, scs->name);
241
242 if (opm_addtype(scs->scanner, pc->type, pc->port) == OPM_ERR_BADPROTOCOL)
243 log_printf("SCAN -> Error bad protocol %s:%d in scanner [%s]",
244 scan_gettype(pc->type), pc->port, scs->name);
245 }
246
247 node = node_create(scs);
248 list_add(&SCANNERS, node);
249 }
250
251 /* Give scanners a list of masks they scan */
252 LIST_FOREACH(p, SCANNERS.head)
253 {
254 struct scanner_struct *scs = p->data;
255
256 LIST_FOREACH(p2, UserItemList->head)
257 {
258 struct UserConf *uc = p2->data;
259
260 LIST_FOREACH(p3, uc->scanners->head)
261 {
262 const char *scannername = p3->data;
263
264 /* Add all these masks to scanner */
265 if (strcasecmp(scannername, scs->name) == 0)
266 {
267 LIST_FOREACH(p4, uc->masks->head)
268 {
269 const char *mask = p4->data;
270
271 if (OPT_DEBUG)
272 log_printf("SCAN -> Linking the mask [%s] to scanner [%s]", mask, scannername);
273
274 node = node_create(xstrdup(mask));
275 list_add(scs->masks, node);
276 }
277
278 break;
279 }
280 }
281 }
282 }
283
284 /* Initialise negative cache */
285 if (OptionsItem->negcache)
286 {
287 if (OPT_DEBUG >= 2)
288 log_printf("SCAN -> Initializing negative cache");
289
290 negcache_init();
291 }
292 }
293
294 /* scan_connect
295 *
296 * scan_connect is called when m_notice (irc.c) matches a connection
297 * notice and parses the connecting user out of it.
298 *
299 * Parameters:
300 * user: Parsed items from the connection notice:
301 * user[0] = connecting users nickname
302 * user[1] = connecting users username
303 * user[2] = connecting users hostname
304 * user[3] = connecting users IP
305 * msg = Original connect notice
306 * Return: NONE
307 *
308 */
309 void
310 scan_connect(const char *user[], const char *msg)
311 {
312 node_t *p, *p2;
313 int ret;
314
315 /*
316 * Have to use MSGLENMAX here because it is unknown what the max size of
317 * username/hostname can be. Some ircds use really mad values for
318 * these.
319 */
320 char hostmask[MSGLENMAX];
321 char addrmask[MSGLENMAX];
322
323 /* Check negcache before anything */
324 if (negcache_check(user[3]))
325 {
326 if (OPT_DEBUG)
327 log_printf("SCAN -> %s!%s@%s [%s] is negatively cached. Skipping all tests.",
328 user[0], user[1], user[2], user[3]);
329 return;
330 }
331
332 /* Generate user mask */
333 snprintf(hostmask, sizeof(hostmask), "%s!%s@%s", user[0], user[1], user[2]);
334 snprintf(addrmask, sizeof(addrmask), "%s!%s@%s", user[0], user[1], user[3]);
335
336 /* Check exempt list now that we have a mask */
337 if (scan_checkexempt(hostmask, addrmask))
338 {
339 if (OPT_DEBUG)
340 log_printf("SCAN -> %s [%s] is exempt from scanning", hostmask, user[3]);
341
342 return;
343 }
344
345 /* Create scan_struct */
346 struct scan_struct *ss = scan_create(user, msg);
347
348 /* Store ss in the remote struct, so that in callbacks we have ss */
349 ss->remote->data = ss;
350
351 /* Start checking our DNSBLs */
352 if (LIST_SIZE(OpmItem->blacklists))
353 dnsbl_add(ss);
354
355 /* Add ss->remote to all matching scanners */
356 LIST_FOREACH(p, SCANNERS.head)
357 {
358 struct scanner_struct *scs = p->data;
359
360 LIST_FOREACH(p2, scs->masks->head)
361 {
362 const char *scsmask = p2->data;
363
364 if (!match(scsmask, hostmask))
365 {
366 if (OPT_DEBUG)
367 log_printf("SCAN -> Passing %s to scanner [%s]", hostmask, scs->name);
368
369 if ((ret = opm_scan(scs->scanner, ss->remote)) != OPM_SUCCESS)
370 {
371 switch (ret)
372 {
373 case OPM_ERR_NOPROTOCOLS:
374 continue;
375 break;
376 case OPM_ERR_BADADDR:
377 if (!strchr(ss->ip, ':')) /* XXX: hack alert. remove when libopm can deal with IPv6 addresses */
378 log_printf("OPM -> Bad address %s [%s]", ss->ip, scs->name);
379 break;
380 default:
381 log_printf("OPM -> Unknown error %s [%s]", ss->ip, scs->name);
382 break;
383 }
384 }
385 else
386 ++ss->scans; /* Increase scan count only if OPM_SUCCESS */
387
388 break; /* Continue to next scanner */
389 }
390 }
391 }
392
393 /* All scanners returned !OPM_SUCCESS and there were no dnsbl checks */
394 if (ss->scans == 0)
395 scan_free(ss);
396 }
397
398 /* scan_create
399 *
400 * Allocate scan struct, including user information and REMOTE
401 * for LIBOPM.
402 *
403 * Parameters:
404 * user: Parsed items from the connection notice:
405 * user[0] = connecting users nickname
406 * user[1] = connecting users username
407 * user[2] = connecting users hostname
408 * user[3] = connecting users IP
409 * msg = Original connect notice (used as PROOF)
410 *
411 * Return: Pointer to new scan_struct
412 *
413 */
414 static struct scan_struct *
415 scan_create(const char *user[], const char *msg)
416 {
417 struct scan_struct *ss = xcalloc(sizeof(*ss));
418
419 ss->irc_nick = xstrdup(user[0]);
420 ss->irc_username = xstrdup(user[1]);
421 ss->irc_hostname = xstrdup(user[2]);
422 ss->ip = xstrdup(user[3]);
423 ss->proof = xstrdup(msg);
424 ss->remote = opm_remote_create(ss->ip);
425
426 return ss;
427 }
428
429 /* scan_free
430 *
431 * Free a scan_struct. This should only be done if the scan struct has
432 * no scans left!
433 *
434 * Parameters:
435 * ss: scan_struct to free
436 *
437 * Return: NONE
438 */
439 static void
440 scan_free(struct scan_struct *ss)
441 {
442 xfree(ss->irc_nick);
443 xfree(ss->irc_username);
444 xfree(ss->irc_hostname);
445 xfree(ss->ip);
446 xfree(ss->proof);
447
448 opm_remote_free(ss->remote);
449 xfree(ss);
450 }
451
452 /* scan_checkfinished
453 *
454 * Check if a scan is complete (ss->scans <= 0)
455 * and free it if need be.
456 */
457 void
458 scan_checkfinished(struct scan_struct *ss)
459 {
460 if (ss->scans <= 0)
461 {
462 if (ss->manual_target)
463 irc_send("PRIVMSG %s :CHECK -> All tests on %s completed.",
464 ss->manual_target, ss->ip);
465 else
466 {
467 if (OPT_DEBUG)
468 /* If there was a manual_target, then irc_nick, etc is NULL. */
469 log_printf("SCAN -> All tests on %s!%s@%s [%s] complete.",
470 ss->irc_nick, ss->irc_username, ss->irc_hostname, ss->ip);
471
472 /* Scan was a negative */
473 if (ss->positive == 0)
474 scan_negative(ss);
475 }
476
477 scan_free(ss);
478 }
479 }
480
481 /* scan_positive
482 *
483 * Remote host (defined by ss) has been found positive by one or more
484 * tests.
485 *
486 * Parameters:
487 * ss: scan_struct containing information regarding positive host
488 * kline: command to send to IRC server to ban the user (see scan_irckline)
489 * type: string of the type of proxy found to be running on the host
490 *
491 * Return: NONE
492 *
493 */
494 void
495 scan_positive(struct scan_struct *ss, const char *kline, const char *type)
496 {
497 node_t *node;
498
499 /* If already a positive, don't kline/close again */
500 if (ss->positive)
501 return;
502
503 /* Format KLINE and send to IRC server */
504 scan_irckline(ss, kline, type);
505
506 /* Speed up the cleanup procedure */
507 /* Close all scans prematurely */
508 LIST_FOREACH(node, SCANNERS.head)
509 {
510 OPM_T *scanner = ((struct scanner_struct *)node->data)->scanner;
511 opm_end(scanner, ss->remote);
512 }
513
514 /* Set it as a positive to avoid a scan_negative call later on */
515 ss->positive = 1;
516 }
517
518 /* scan_open_proxy CALLBACK
519 *
520 * Called by libopm when a proxy is verified open.
521 *
522 * Parameters:
523 * scanner: Scanner that found the open proxy.
524 * remote: Remote struct containing information regarding remote end
525 *
526 * Return: NONE
527 */
528 static void
529 scan_open_proxy(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *data)
530 {
531 struct scan_struct *ss = remote->data;
532 struct scanner_struct *scs = data;
533
534 /* Record that a scan happened */
535 scan_log(remote);
536
537 if (ss->manual_target)
538 {
539 irc_send("PRIVMSG %s :CHECK -> OPEN PROXY %s:%d (%s) [%s]",
540 ss->manual_target, remote->ip, remote->port,
541 scan_gettype(remote->protocol), scs->name);
542 log_printf("SCAN -> OPEN PROXY %s:%d (%s) [%s]", remote->ip,
543 remote->port, scan_gettype(remote->protocol), scs->name);
544 }
545 else
546 {
547 /* kline and close scan */
548 scan_positive(ss, IRCItem->kline, scan_gettype(remote->protocol));
549
550 /* Report to blacklist */
551 dnsbl_report(ss);
552
553 irc_send_channels("OPEN PROXY -> %s!%s@%s %s:%d (%s) [%s]",
554 ss->irc_nick, ss->irc_username, ss->irc_hostname, remote->ip,
555 remote->port, scan_gettype(remote->protocol), scs->name);
556 log_printf("SCAN -> OPEN PROXY %s!%s@%s %s:%d (%s) [%s]",
557 ss->irc_nick, ss->irc_username, ss->irc_hostname, remote->ip,
558 remote->port, scan_gettype(remote->protocol), scs->name);
559 }
560
561 /* Record the proxy for stats purposes */
562 stats_openproxy(remote->protocol);
563 }
564
565 /* scan_negotiation_failed CALLBACK
566 *
567 * Called by libopm when negotiation of a specific protocol failed.
568 *
569 * Parameters:
570 * scanner: Scanner where the negotiation failed.
571 * remote: Remote struct containing information regarding remote end
572 *
573 * Return: NONE
574 *
575 */
576 static void
577 scan_negotiation_failed(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *data)
578 {
579 const struct scanner_struct *scs = data;
580
581 /* Record that a scan happened */
582 scan_log(remote);
583
584 if (OPT_DEBUG)
585 log_printf("SCAN -> Negotiation failed %s:%d (%s) [%s] (%d bytes read)",
586 remote->ip, remote->port, scan_gettype(remote->protocol), scs->name,
587 remote->bytes_read);
588 }
589
590 /* scan_timeout CALLBACK
591 *
592 * Called by libopm when the negotiation of a specific protocol timed out.
593 *
594 * Parameters:
595 * scanner: Scanner where the connection timed out.
596 * remote: Remote struct containing information regarding remote end
597 *
598 * Return: NONE
599 *
600 */
601 static void
602 scan_timeout(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *data)
603 {
604 const struct scanner_struct *scs = data;
605
606 /* Record that a scan happened */
607 scan_log(remote);
608
609 if (OPT_DEBUG)
610 log_printf("SCAN -> Negotiation timed out %s:%d (%s) [%s] (%d bytes read)",
611 remote->ip, remote->port, scan_gettype(remote->protocol), scs->name,
612 remote->bytes_read);
613 }
614
615 /* scan_end CALLBACK
616 *
617 * Called by libopm when a specific SCAN has completed (all protocols in
618 * that scan).
619 *
620 * Parameters:
621 * scanner: Scanner the scan ended on.
622 * remote: Remote struct containing information regarding remote end
623 *
624 * Return: NONE
625 */
626 static void
627 scan_end(OPM_T *scanner, OPM_REMOTE_T *remote, int notused, void *data)
628 {
629 struct scan_struct *ss = remote->data;
630 struct scanner_struct *scs = data;
631
632 if (OPT_DEBUG)
633 log_printf("SCAN -> Scan %s [%s] completed", remote->ip, scs->name);
634
635 --ss->scans;
636 scan_checkfinished(ss);
637 }
638
639 /* scan_handle_error CALLBACK
640 *
641 * Called by libopm when an error occurs with a specific connection. This
642 * does not mean the entire scan has ended.
643 *
644 * Parameters:
645 * scanner: Scanner where the error occured.
646 * remote: Remote struct containing information regarding remote end
647 * err: OPM_ERROR code describing the error.
648 *
649 * Return: NONE
650 */
651 static void
652 scan_handle_error(OPM_T *scanner, OPM_REMOTE_T *remote, int err, void *data)
653 {
654 struct scan_struct *ss = remote->data;
655 struct scanner_struct *scs = data;
656
657 switch (err)
658 {
659 case OPM_ERR_MAX_READ:
660 if (OPT_DEBUG >= 2)
661 log_printf("SCAN -> Max read on %s:%d (%s) [%s] (%d bytes read)",
662 remote->ip, remote->port, scan_gettype(remote->protocol),
663 scs->name, remote->bytes_read);
664
665 if (ss->manual_target)
666 irc_send("PRIVMSG %s :CHECK -> Negotiation failed %s:%d (%s) "
667 "[%s] (%d bytes read)", ss->manual_target,
668 remote->ip, remote->port, scan_gettype(remote->protocol),
669 scs->name, remote->bytes_read);
670 break;
671 case OPM_ERR_BIND:
672 log_printf("SCAN -> Bind error on %s:%d (%s) [%s]", remote->ip,
673 remote->port, scan_gettype(remote->protocol), scs->name);
674
675 if (ss->manual_target)
676 irc_send("PRIVMSG %s :CHECK -> Bind error on %s:%d (%s) [%s]",
677 ss->manual_target, remote->ip, remote->port,
678 scan_gettype(remote->protocol), scs->name);
679 break;
680 case OPM_ERR_NOFD:
681 log_printf("SCAN -> File descriptor allocation error %s:%d (%s) "
682 "[%s]", remote->ip, remote->port,
683 scan_gettype(remote->protocol), scs->name);
684
685 if (ss->manual_target)
686 irc_send("PRIVMSG %s :CHECK -> Scan failed %s:%d (%s) [%s] "
687 "(file descriptor allocation error)",
688 ss->manual_target, remote->ip, remote->port,
689 scan_gettype(remote->protocol), scs->name);
690 break;
691 default: /* Unknown Error! */
692 if (OPT_DEBUG)
693 log_printf("SCAN -> Unknown error %s:%d (%s) [%s]", remote->ip,
694 remote->port, scan_gettype(remote->protocol), scs->name);
695 break;
696 }
697 }
698
699 /* scan_negative
700 *
701 * Remote host (defined by ss) has passed all tests.
702 *
703 * Parameters:
704 * ss: scan_struct containing information regarding negative host.
705 *
706 * Return: NONE
707 *
708 */
709 static void
710 scan_negative(const struct scan_struct *ss)
711 {
712 /* Insert IP in negcache */
713 if (OptionsItem->negcache)
714 {
715 if (OPT_DEBUG >= 2)
716 log_printf("SCAN -> Adding %s to negative cache", ss->ip);
717
718 negcache_insert(ss->ip);
719 }
720 }
721
722 /* scan_irckline
723 *
724 * ss has been found as a positive host and is to be klined.
725 * Format a kline message using the kline message provided
726 * as a format, then pass it to irc_send() to be sent to the remote server.
727 *
728 * Parameters:
729 * ss: scan_struct containing information regarding host to be klined
730 * format: kline message to format
731 * type: type of proxy found (%t format character)
732 *
733 * Return: NONE
734 */
735 static void
736 scan_irckline(const struct scan_struct *ss, const char *format, const char *type)
737 {
738 char message[MSGLENMAX] = ""; /* OUTPUT */
739
740 unsigned int pos = 0; /* position in format */
741 unsigned int len = 0; /* position in message */
742 unsigned int size = 0; /* temporary size buffer */
743 struct kline_format_assoc
744 {
745 const char key;
746 const char *data;
747 } table[] =
748 {
749 { 'i', ss->ip },
750 { 'h', ss->irc_hostname },
751 { 'u', ss->irc_username },
752 { 'n', ss->irc_nick },
753 { 't', type },
754 { '\0', NULL }
755 };
756
757 /*
758 * Copy format to message character by character, inserting any matching
759 * data after %.
760 */
761 while (format[pos] != '\0' && len < (MSGLENMAX - 2))
762 {
763 switch (format[pos])
764 {
765 case '%':
766 /* % is the last char in the string, move on */
767 if (format[pos + 1] == '\0')
768 continue;
769
770 /* %% escapes % and becomes % */
771 if (format[pos + 1] == '%')
772 {
773 message[len++] = '%';
774 ++pos; /* Skip past the escaped % */
775 break;
776 }
777
778 /* Safe to check against table now */
779 for (const struct kline_format_assoc *tab = table; tab->key; ++tab)
780 {
781 if (tab->key == format[pos + 1])
782 {
783 size = strlen(tab->data);
784
785 /* Check if the new string can fit! */
786 if ((size + len) > (MSGLENMAX - 1))
787 break;
788 else
789 {
790 strlcat(message, tab->data, sizeof(message));
791 len += size;
792 }
793 }
794 }
795
796 /* Skip key character */
797 ++pos;
798 break;
799
800 default:
801 message[len++] = format[pos];
802 message[len] = '\0';
803 break;
804 }
805
806 /* Continue to next character in format */
807 ++pos;
808 }
809
810 irc_send("%s", message);
811 }
812
813 /* scan_manual
814 *
815 * Create a manual scan. A manual scan is a scan where the
816 * scan_struct contains a manual_target pointer.
817 */
818 void
819 scan_manual(char *param, const char *target)
820 {
821 char buf[INET6_ADDRSTRLEN];
822 const void *addr = NULL;
823 const char *ip = NULL;
824 char *scannername;
825 node_t *node;
826 int ret, n;
827 struct sockaddr_storage storage;
828 socklen_t storage_len = 0;
829
830 /* If there were no parameters sent, simply alert the user and return */
831 if (param == NULL)
832 {
833 irc_send("PRIVMSG %s :OPM -> Invalid parameters.", target);
834 return;
835 }
836
837 /*
838 * Try to extract a scanner name from param, otherwise we'll be
839 * adding to all scanners
840 */
841 ip = param;
842
843 if ((scannername = strchr(param, ' ')))
844 {
845 *scannername = '\0';
846 scannername++;
847 }
848
849 memset(&storage, 0, sizeof(storage));
850
851 if ((addr = firedns_resolveip6(ip)))
852 {
853 struct sockaddr_in6 *in = (struct sockaddr_in6 *)&storage;
854
855 storage_len = sizeof(*in);
856 storage.ss_family = AF_INET6;
857 memcpy(&in->sin6_addr, addr, sizeof(in->sin6_addr));
858 }
859 else if ((addr = firedns_resolveip4(ip)))
860 {
861 struct sockaddr_in *in = (struct sockaddr_in *)&storage;
862
863 storage_len = sizeof(*in);
864 storage.ss_family = AF_INET;
865 memcpy(&in->sin_addr, addr, sizeof(in->sin_addr));
866 }
867 else
868 {
869 irc_send("PRIVMSG %s :CHECK -> Error resolving host '%s': %s",
870 target, ip, firedns_strerror(firedns_errno));
871 return;
872 }
873
874 if ((n = getnameinfo((const struct sockaddr *)&storage, storage_len, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST)))
875 {
876 irc_send("PRIVMSG %s :CHECK -> invalid address: %s",
877 target, gai_strerror(n));
878 return;
879 }
880
881 ip = buf;
882
883 struct scan_struct *ss = xcalloc(sizeof(*ss));
884 ss->ip = xstrdup(ip);
885 ss->remote = opm_remote_create(ss->ip);
886 ss->remote->data = ss;
887 ss->manual_target = target;
888
889 if (scannername)
890 irc_send("PRIVMSG %s :CHECK -> Checking '%s' for open proxies [%s]",
891 target, ss->ip, scannername);
892 else
893 irc_send("PRIVMSG %s :CHECK -> Checking '%s' for open proxies on all scanners",
894 target, ss->ip);
895
896 if (LIST_SIZE(OpmItem->blacklists))
897 dnsbl_add(ss);
898
899 /* Add ss->remote to all scanners */
900 LIST_FOREACH(node, SCANNERS.head)
901 {
902 struct scanner_struct *scs = node->data;
903
904 /*
905 * If we have a scannername, only allow that scanner
906 * to be used
907 */
908 if (scannername)
909 if (strcasecmp(scannername, scs->name))
910 continue;
911
912 if (OPT_DEBUG)
913 log_printf("SCAN -> Passing %s to scanner [%s] (MANUAL SCAN)", ss->ip, scs->name);
914
915 if ((ret = opm_scan(scs->scanner, ss->remote)) != OPM_SUCCESS)
916 {
917 switch (ret)
918 {
919 case OPM_ERR_NOPROTOCOLS:
920 break;
921 case OPM_ERR_BADADDR:
922 if (!strchr(ss->ip, ':')) /* XXX: hack alert. remove when libopm can deal with IPv6 addresses */
923 irc_send("PRIVMSG %s :OPM -> Bad address %s [%s]",
924 ss->manual_target, ss->ip, scs->name);
925 break;
926 default:
927 irc_send("PRIVMSG %s :OPM -> Unknown error %s [%s]",
928 ss->manual_target, ss->ip, scs->name);
929 break;
930 }
931 }
932 else
933 ++ss->scans; /* Increase scan count only if OPM_SUCCESS */
934 }
935
936 /*
937 * If all of the scanners gave !OPM_SUCCESS and there were no dnsbl checks,
938 * cleanup here
939 */
940 if (ss->scans == 0)
941 {
942 if (scannername)
943 irc_send("PRIVMSG %s :CHECK -> No such scanner '%s', or '%s' has 0 protocols.",
944 ss->manual_target, scannername, scannername);
945
946 irc_send("PRIVMSG %s :CHECK -> No scans active on '%s', aborting scan.",
947 ss->manual_target, ss->ip);
948 scan_free(ss);
949 }
950 }
951
952 /* scan_log
953 *
954 * Log the fact that a given ip/port/protocol has just been scanned, if the
955 * user has asked for this to be logged.
956 *
957 * Parameters:
958 * remote: OPM_REMOTE_T for the remote end
959 */
960 static void
961 scan_log(OPM_REMOTE_T *remote)
962 {
963 struct scan_struct *ss = remote->data;
964
965 if (!(OptionsItem->scanlog && scanlogfile))
966 return;
967
968 fprintf(scanlogfile, "[%s] %s:%d (%s) \"%s\"\n", date_iso8601(0), remote->ip,
969 remote->port, scan_gettype(remote->protocol), ss->proof);
970 fflush(scanlogfile);
971 }

Properties

Name Value
svn:eol-style native
svn:keywords Id