Home | History | Annotate | Download | only in extensions
      1 /*
      2  * Copyright (c) 2003+ Evgeniy Polyakov <zbr (at) ioremap.net>
      3  *
      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, USA.
     18  */
     19 
     20 /*
     21  * xtables interface for OS fingerprint matching module.
     22  */
     23 #include <stdio.h>
     24 #include <string.h>
     25 #include <xtables.h>
     26 #include <netinet/ip.h>
     27 #include <netinet/tcp.h>
     28 #include <linux/netfilter/xt_osf.h>
     29 
     30 enum {
     31 	O_GENRE = 0,
     32 	O_TTL,
     33 	O_LOGLEVEL,
     34 };
     35 
     36 static void osf_help(void)
     37 {
     38 	printf("OS fingerprint match options:\n"
     39 		"[!] --genre string     Match a OS genre by passive fingerprinting.\n"
     40 		"--ttl level            Use some TTL check extensions to determine OS:\n"
     41 		"       0                       true ip and fingerprint TTL comparison. Works for LAN.\n"
     42 		"       1                       check if ip TTL is less than fingerprint one. Works for global addresses.\n"
     43 		"       2                       do not compare TTL at all. Allows to detect NMAP, but can produce false results.\n"
     44 		"--log level            Log determined genres into dmesg even if they do not match desired one:\n"
     45 		"       0                       log all matched or unknown signatures.\n"
     46 		"       1                       log only first one.\n"
     47 		"       2                       log all known matched signatures.\n"
     48 		);
     49 }
     50 
     51 #define s struct xt_osf_info
     52 static const struct xt_option_entry osf_opts[] = {
     53 	{.name = "genre", .id = O_GENRE, .type = XTTYPE_STRING,
     54 	 .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
     55 	 XTOPT_POINTER(s, genre)},
     56 	{.name = "ttl", .id = O_TTL, .type = XTTYPE_UINT32,
     57 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl), .min = 0, .max = 2},
     58 	{.name = "log", .id = O_LOGLEVEL, .type = XTTYPE_UINT32,
     59 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, loglevel), .min = 0, .max = 2},
     60 	XTOPT_TABLEEND,
     61 };
     62 #undef s
     63 
     64 static void osf_parse(struct xt_option_call *cb)
     65 {
     66 	struct xt_osf_info *info = cb->data;
     67 
     68 	xtables_option_parse(cb);
     69 	switch (cb->entry->id) {
     70 		case O_GENRE:
     71 			if (cb->invert)
     72 				info->flags |= XT_OSF_INVERT;
     73 			info->len = strlen(info->genre);
     74 			break;
     75 		case O_TTL:
     76 			info->flags |= XT_OSF_TTL;
     77 			break;
     78 		case O_LOGLEVEL:
     79 			info->flags |= XT_OSF_LOG;
     80 			break;
     81 	}
     82 }
     83 
     84 static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric)
     85 {
     86 	const struct xt_osf_info *info = (const struct xt_osf_info*) match->data;
     87 
     88 	printf(" OS fingerprint match %s%s", (info->flags & XT_OSF_INVERT) ? "! " : "", info->genre);
     89 }
     90 
     91 static void osf_save(const void *ip, const struct xt_entry_match *match)
     92 {
     93 	const struct xt_osf_info *info = (const struct xt_osf_info*) match->data;
     94 
     95 	if (info->flags & XT_OSF_INVERT)
     96 		printf(" !");
     97 
     98 	printf(" --genre %s", info->genre);
     99 	if (info->flags & XT_OSF_TTL)
    100 		printf(" --ttl %u", info->ttl);
    101 	if (info->flags & XT_OSF_LOG)
    102 		printf(" --log %u", info->loglevel);
    103 }
    104 
    105 static struct xtables_match osf_match = {
    106 	.name		= "osf",
    107 	.version	= XTABLES_VERSION,
    108 	.size		= XT_ALIGN(sizeof(struct xt_osf_info)),
    109 	.userspacesize	= XT_ALIGN(sizeof(struct xt_osf_info)),
    110 	.help		= osf_help,
    111 	.x6_parse	= osf_parse,
    112 	.print		= osf_print,
    113 	.save		= osf_save,
    114 	.x6_options	= osf_opts,
    115 	.family		= NFPROTO_IPV4,
    116 };
    117 
    118 void _init(void)
    119 {
    120 	xtables_register_match(&osf_match);
    121 }
    122