From 7c8d64811fa2752e468f7e25be56f9f64ec0f5c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20M=C3=BCnchow?= Date: Wed, 12 Oct 2016 17:32:07 +0200 Subject: [PATCH] the cookie-seed used in ts3init_get_puzzle and TS3INIT_SET_COOKIE can be loaded from file now. Added new parameters --seed and --seed-file to ts3init_get_puzzle and TS3INIT_SET_COOKIE. --- README.md | 9 ++-- src/libxt_TS3INIT_RESET.c | 3 ++ src/libxt_TS3INIT_SET_COOKIE.c | 62 ++++++++++++++++++++-------- src/libxt_ts3init_get_cookie.c | 3 ++ src/libxt_ts3init_get_puzzle.c | 75 +++++++++++++++++++++++++++++----- src/ts3init_cookie_seed.h | 41 ++++++++++++++++++- src/ts3init_match.h | 7 +++- src/ts3init_target.h | 6 ++- 8 files changed, 170 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 9abb2fa..f0c94fe 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,11 @@ The second match extension is called *ts3init_get_puzzle*. It matches if the pac $ iptables -m ts3init_get_puzzle -h <..> ts3init_get_puzzle match options: - --min-client n The sending client needs to be at least version n. - --check-cookie seed Check the cookie. Assume it was generated with seed. - seed is a 60 byte random number in hex. A source - could be /dev/random. + --min-client n The sending client needs to be at least version. + --check-cookie Check that the cookie was generated by same seed. + --seed Seed is a 60 byte lowercase hex number in. + A source could be /dev/random. + --seed-file Read the seed from a file. ``` The min-client parameter is the same as above. The check-cookie parameter matches if it matches the cookie that was generated in the netfilter target extension ts3init_set_cookie. To match the seed needs to be exactly the same of course. It is possible to check cookies that were generated on a different machine, provided that those machines have the same date and time, and the seem seed specified. In other words: The cookie is created in a deterministic way, depending only on the current time and the seed. diff --git a/src/libxt_TS3INIT_RESET.c b/src/libxt_TS3INIT_RESET.c index 5ca0242..9283520 100644 --- a/src/libxt_TS3INIT_RESET.c +++ b/src/libxt_TS3INIT_RESET.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "ts3init_cookie_seed.h" #include "ts3init_target.h" diff --git a/src/libxt_TS3INIT_SET_COOKIE.c b/src/libxt_TS3INIT_SET_COOKIE.c index 9ccd69d..66154ef 100644 --- a/src/libxt_TS3INIT_SET_COOKIE.c +++ b/src/libxt_TS3INIT_SET_COOKIE.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "ts3init_cookie_seed.h" #include "ts3init_target.h" @@ -22,15 +25,17 @@ static void ts3init_set_cookie_tg_help(void) { printf( - "TS3INIT_SET_COOKIE match options:\n" - " --zero-random-sequence Always return 0 as random sequence.\n" - " --cookie-seed seed Seed is a 60 byte random number in\n" - " hex. A source could be /dev/random.\n"); + "TS3INIT_SET_COOKIE target options:\n" + " --zero-random-sequence Always return 0 as random sequence.\n" + " --seed Seed is a 60 byte lowercase hex number in.\n" + " A source could be /dev/random.\n" + " --seed-file Read the seed from a file.\n"); } static const struct option ts3init_set_cookie_tg_opts[] = { {.name = "zero-random-sequence", .has_arg = false, .val = '1'}, - {.name = "cookie-seed", .has_arg = true, .val = '2'}, + {.name = "seed", .has_arg = true, .val = '2'}, + {.name = "seed-file", .has_arg = true, .val = '3'}, {NULL}, }; @@ -42,20 +47,30 @@ static int ts3init_set_cookie_tg_parse(int c, char **argv, switch (c) { case '1': param_act(XTF_ONLY_ONCE, "--zero-random-sequence", info->specific_options & TARGET_SET_COOKIE_ZERO_RANDOM_SEQUENCE); - param_act(XTF_NO_INVERT, "--check-time", invert); + param_act(XTF_NO_INVERT, "--zero-random-sequence", invert); info->specific_options |= TARGET_SET_COOKIE_ZERO_RANDOM_SEQUENCE; return true; case '2': - param_act(XTF_ONLY_ONCE, "--cookie-seed", info->specific_options & TARGET_SET_COOKIE_SEED); - param_act(XTF_NO_INVERT, "--cookie-seed", invert); + param_act(XTF_ONLY_ONCE, "--seed", *flags & TARGET_SET_COOKIE_SEED_FROM_ARGUMENT); + param_act(XTF_NO_INVERT, "--seed", invert); if (strlen(optarg) != (COOKIE_SEED_LEN * 2)) xtables_error(PARAMETER_PROBLEM, - "TS3INIT_SET_COOKIE: invalid cookie-seed length"); + "TS3INIT_SET_COOKIE: invalid seed length"); if (!hex2int_seed(optarg, info->cookie_seed)) xtables_error(PARAMETER_PROBLEM, - "TS3INIT_SET_COOKIE: invalid cookie-seed. (not lowercase hex)"); - info->specific_options |= TARGET_SET_COOKIE_SEED; - *flags |= TARGET_SET_COOKIE_SEED; + "TS3INIT_SET_COOKIE: invalid seed. (not lowercase hex)"); + info->specific_options |= TARGET_SET_COOKIE_SEED_FROM_ARGUMENT; + *flags |= TARGET_SET_COOKIE_SEED_FROM_ARGUMENT; + return true; + + case '3': + param_act(XTF_ONLY_ONCE, "--seed-file", *flags & TARGET_SET_COOKIE_SEED_FROM_FILE); + param_act(XTF_NO_INVERT, "--seed-file", invert); + + if (read_cookie_seed_from_file("TS3INIT_SET_COOKIE", optarg, info->cookie_seed)) + memcpy(info->cookie_seed_path, optarg, strlen(optarg) + 1); + info->specific_options |= TARGET_SET_COOKIE_SEED_FROM_FILE; + *flags |= TARGET_SET_COOKIE_SEED_FROM_FILE; return true; default: @@ -70,15 +85,19 @@ static void ts3init_set_cookie_tg_save(const void *ip, const struct xt_entry_tar { printf("--zero-random-sequence "); } - if (info->specific_options & TARGET_SET_COOKIE_SEED) + if (info->specific_options & TARGET_SET_COOKIE_SEED_FROM_ARGUMENT) { - printf("--cookie-seed "); + printf("--seed "); for (int i = 0; i < COOKIE_SEED_LEN; i++) { printf("%02X", info->cookie_seed[i]); } printf(" "); } + if (info->specific_options & TARGET_SET_COOKIE_SEED_FROM_FILE) + { + printf("--seed-file \"%s\" ", info->cookie_seed_path); + } } static void ts3init_set_cookie_tg_print(const void *ip, const struct xt_entry_target *target, @@ -90,10 +109,19 @@ static void ts3init_set_cookie_tg_print(const void *ip, const struct xt_entry_ta static void ts3init_set_cookie_tg_check(unsigned int flags) { - if ((flags & TARGET_SET_COOKIE_SEED) == 0) + bool seed_from_argument = flags & TARGET_SET_COOKIE_SEED_FROM_ARGUMENT; + bool seed_from_file = flags & TARGET_SET_COOKIE_SEED_FROM_FILE; + if (seed_from_argument && seed_from_file) + { + xtables_error(PARAMETER_PROBLEM, + "TS3INIT_SET_COOKIE: --seed and --seed-file " + "can not be specified at the same time"); + } + if (!seed_from_argument && !seed_from_file) { - xtables_error(PARAMETER_PROBLEM, - "TS3INIT_SET_COOKIE: --cookie-seed must be specified"); + xtables_error(PARAMETER_PROBLEM, + "TS3INIT_SET_COOKIE: either --seed or --seed-file " + "must be specified"); } } diff --git a/src/libxt_ts3init_get_cookie.c b/src/libxt_ts3init_get_cookie.c index f8d2230..0f5089b 100644 --- a/src/libxt_ts3init_get_cookie.c +++ b/src/libxt_ts3init_get_cookie.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "ts3init_cookie_seed.h" #include "ts3init_match.h" diff --git a/src/libxt_ts3init_get_puzzle.c b/src/libxt_ts3init_get_puzzle.c index cb2f19e..e2b2ca0 100644 --- a/src/libxt_ts3init_get_puzzle.c +++ b/src/libxt_ts3init_get_puzzle.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include +#include #include "ts3init_cookie_seed.h" #include "ts3init_match.h" @@ -24,16 +27,19 @@ static void ts3init_get_puzzle_help(void) { printf( "ts3init_get_puzzle match options:\n" - " --min-client n The sending client needs to be at least version n.\n" - " --check-cookie seed Check the cookie. Assume it was generated with seed.\n" - " seed is a 60 byte random number in hex. A source\n" - " could be /dev/random.\n" - ); + " --min-client n The sending client needs to be at least version.\n" + " --check-cookie Check that the cookie was generated by same seed.\n" + " --seed Seed is a 60 byte lowercase hex number in.\n" + " A source could be /dev/random.\n" + " --seed-file Read the seed from a file.\n" +); } static const struct option ts3init_get_puzzle_opts[] = { - {.name = "min-client", .has_arg = true, .val = '1'}, - {.name = "check-cookie", .has_arg = true, .val = '2'}, + {.name = "min-client", .has_arg = true, .val = '1'}, + {.name = "check-cookie", .has_arg = false, .val = '2'}, + {.name = "seed", .has_arg = true, .val = '3'}, + {.name = "seed-file", .has_arg = true, .val = '4'}, {NULL}, }; @@ -58,13 +64,31 @@ static int ts3init_get_puzzle_parse(int c, char **argv, int invert, unsigned int case '2': param_act(XTF_ONLY_ONCE, "--check-cookie", info->specific_options & CHK_GET_PUZZLE_CHECK_COOKIE); param_act(XTF_NO_INVERT, "--check-cookie", invert); + info->specific_options |= CHK_GET_PUZZLE_CHECK_COOKIE; + *flags |= CHK_GET_PUZZLE_CHECK_COOKIE; + return true; + + case '3': + param_act(XTF_ONLY_ONCE, "--seed", info->specific_options & CHK_GET_PUZZLE_SEED_FROM_ARGUMENT); + param_act(XTF_NO_INVERT, "--seed", invert); if (strlen(optarg) != (COOKIE_SEED_LEN * 2)) xtables_error(PARAMETER_PROBLEM, - "ts3init_get_puzzle: invalid cookie-seed length"); + "ts3init_get_puzzle: invalid seed length"); if (!hex2int_seed(optarg, info->cookie_seed)) xtables_error(PARAMETER_PROBLEM, - "ts3init_get_puzzle: invalid cookie-seed. (not lowercase hex)"); - info->specific_options |= CHK_GET_PUZZLE_CHECK_COOKIE; + "ts3init_get_puzzle: invalid seed. (not lowercase hex)"); + info->specific_options |= CHK_GET_PUZZLE_SEED_FROM_ARGUMENT; + *flags |= CHK_GET_PUZZLE_SEED_FROM_ARGUMENT; + return true; + + case '4': + param_act(XTF_ONLY_ONCE, "--seed-file", info->specific_options & CHK_GET_PUZZLE_SEED_FROM_FILE); + param_act(XTF_NO_INVERT, "--seed-file", invert); + + if (read_cookie_seed_from_file("ts3init_get_puzzle", optarg, info->cookie_seed)) + memcpy(info->cookie_seed_path, optarg, strlen(optarg) + 1); + info->specific_options |= CHK_GET_PUZZLE_SEED_FROM_FILE; + *flags |= CHK_GET_PUZZLE_SEED_FROM_FILE; return true; default: @@ -82,12 +106,20 @@ static void ts3init_get_puzzle_save(const void *ip, const struct xt_entry_match if (info->specific_options & CHK_GET_PUZZLE_CHECK_COOKIE) { printf("--check-cookie "); + } + if (info->specific_options & CHK_GET_PUZZLE_SEED_FROM_ARGUMENT) + { + printf("--seed "); for (int i = 0; i < COOKIE_SEED_LEN; i++) { printf("%02X", info->cookie_seed[i]); } printf(" "); } + if (info->specific_options & CHK_GET_PUZZLE_SEED_FROM_FILE) + { + printf("--seed-file \"%s\" ", info->cookie_seed_path); + } } static void ts3init_get_puzzle_print(const void *ip, const struct xt_entry_match *match, @@ -97,6 +129,27 @@ static void ts3init_get_puzzle_print(const void *ip, const struct xt_entry_match ts3init_get_puzzle_save(ip, match); } +static void ts3init_get_puzzle_check(unsigned int flags) +{ + bool seed_from_argument = flags & CHK_GET_PUZZLE_SEED_FROM_ARGUMENT; + bool seed_from_file = flags & CHK_GET_PUZZLE_SEED_FROM_FILE; + if (seed_from_argument && seed_from_file) + { + xtables_error(PARAMETER_PROBLEM, + "ts3init_get_puzzle: --seed and --seed-file " + "can not be specified at the same time"); + } + if (flags & CHK_GET_PUZZLE_CHECK_COOKIE) + { + if (!seed_from_argument && !seed_from_file) + { + xtables_error(PARAMETER_PROBLEM, + "ts3init_get_puzzle: --check-cookie requires either " + "--seed or --seed-file"); + } + } +} + /* register and init */ static struct xtables_match ts3init_mt_reg[] = { @@ -112,6 +165,7 @@ static struct xtables_match ts3init_mt_reg[] = .print = ts3init_get_puzzle_print, .save = ts3init_get_puzzle_save, .extra_opts = ts3init_get_puzzle_opts, + .final_check = ts3init_get_puzzle_check, }, { .name = "ts3init_get_puzzle", @@ -125,6 +179,7 @@ static struct xtables_match ts3init_mt_reg[] = .print = ts3init_get_puzzle_print, .save = ts3init_get_puzzle_save, .extra_opts = ts3init_get_puzzle_opts, + .final_check = ts3init_get_puzzle_check, } }; diff --git a/src/ts3init_cookie_seed.h b/src/ts3init_cookie_seed.h index ec3fe92..f4a39d1 100644 --- a/src/ts3init_cookie_seed.h +++ b/src/ts3init_cookie_seed.h @@ -2,7 +2,8 @@ #define _TS3INIT_COOKIE_SEED_H enum { - COOKIE_SEED_LEN = 60 + COOKIE_SEED_LEN = 60, + COOKIE_PATH_MAX = 256, }; static inline bool hex2int_seed(const char *src, __u8* dst) @@ -25,4 +26,42 @@ static inline bool hex2int_seed(const char *src, __u8* dst) return true; } +#ifndef __KERNEL__ + +static inline bool read_cookie_seed_from_file(const char *module_name, const char *path, __u8* dst) +{ + int n, fd; + char text[COOKIE_SEED_LEN * 2], error_message[256]; + if (strlen(path) > COOKIE_PATH_MAX) + { + xtables_error(PARAMETER_PROBLEM, "%s: path is too long.", module_name); + return false; + } + + fd = open(path, O_RDONLY); + if (fd == -1) goto io_error; + if (lseek(fd, 0, SEEK_END) == sizeof(text)) + { + xtables_error(PARAMETER_PROBLEM, "%s: %s must contain exactly %lu characters", module_name, path, sizeof(text)); + return false; + } + if (lseek(fd, 0, SEEK_SET) == -1) goto io_error; + + n = read(fd, text, sizeof(text)); + if (n == -1) goto io_error; + else if (n != sizeof(text) || hex2int_seed(text, dst) == false) + { + xtables_error(PARAMETER_PROBLEM, "%s: %s must contain exactly %lu lowercase hex characters", module_name, path, sizeof(text)); + return false; + } + return true; +io_error: + strerror_r(errno, error_message, sizeof(error_message)); + xtables_error(PARAMETER_PROBLEM, "%s: %s.", + module_name, + error_message); + return false; +} + +#endif /* __KERNEL__ */ #endif /* _TS3INIT_COOKIE_SEED_H */ diff --git a/src/ts3init_match.h b/src/ts3init_match.h index 9030fd3..2984147 100644 --- a/src/ts3init_match.h +++ b/src/ts3init_match.h @@ -30,8 +30,10 @@ struct xt_ts3init_get_cookie_mtinfo /* Enums and structs for get_puzzle */ enum { - CHK_GET_PUZZLE_CHECK_COOKIE = 1 << 0, - CHK_GET_PUZZLE_VALID_MASK = (1 << 1) - 1, + CHK_GET_PUZZLE_CHECK_COOKIE = 1 << 0, + CHK_GET_PUZZLE_SEED_FROM_ARGUMENT = 1 << 1, + CHK_GET_PUZZLE_SEED_FROM_FILE = 1 << 2, + CHK_GET_PUZZLE_VALID_MASK = (1 << 3) - 1, }; struct xt_ts3init_get_puzzle_mtinfo @@ -41,6 +43,7 @@ struct xt_ts3init_get_puzzle_mtinfo __u16 reserved1; __u32 min_client_version; __u8 cookie_seed[COOKIE_SEED_LEN]; + char cookie_seed_path[COOKIE_PATH_MAX]; }; #endif /* _TS3INIT_MATCH_H */ diff --git a/src/ts3init_target.h b/src/ts3init_target.h index 5b17d0a..dc7b4ca 100644 --- a/src/ts3init_target.h +++ b/src/ts3init_target.h @@ -11,8 +11,9 @@ enum enum { TARGET_SET_COOKIE_ZERO_RANDOM_SEQUENCE = 1 << 0, - TARGET_SET_COOKIE_SEED = 1 << 1, - TARGET_SET_COOKIE_VALID_MASK = (1 << 2) - 1 + TARGET_SET_COOKIE_SEED_FROM_ARGUMENT = 1 << 1, + TARGET_SET_COOKIE_SEED_FROM_FILE = 1 << 2, + TARGET_SET_COOKIE_VALID_MASK = (1 << 3) - 1 }; @@ -22,6 +23,7 @@ struct xt_ts3init_set_cookie_tginfo __u8 specific_options; __u16 reserved1; __u8 cookie_seed[COOKIE_SEED_LEN]; + char cookie_seed_path[COOKIE_PATH_MAX]; }; #endif /* _TS3INIT_TARGET_H */