Commit 4ad3f261 authored by Joonwoo Park's avatar Joonwoo Park Committed by David S. Miller

netfilter: fix string extension for case insensitive pattern matching

The flag XT_STRING_FLAG_IGNORECASE indicates case insensitive string
matching. netfilter can find cmd.exe, Cmd.exe, cMd.exe and etc easily.

A new revision 1 was added, in the meantime invert of xt_string_info
was moved into flags as a flag. If revision is 1, The flag
XT_STRING_FLAG_INVERT indicates invert matching.
Signed-off-by: default avatarJoonwoo Park <joonwpark81@gmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dde77e60
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
#define XT_STRING_MAX_PATTERN_SIZE 128 #define XT_STRING_MAX_PATTERN_SIZE 128
#define XT_STRING_MAX_ALGO_NAME_SIZE 16 #define XT_STRING_MAX_ALGO_NAME_SIZE 16
enum {
XT_STRING_FLAG_INVERT = 0x01,
XT_STRING_FLAG_IGNORECASE = 0x02
};
struct xt_string_info struct xt_string_info
{ {
u_int16_t from_offset; u_int16_t from_offset;
...@@ -11,7 +16,15 @@ struct xt_string_info ...@@ -11,7 +16,15 @@ struct xt_string_info
char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; char algo[XT_STRING_MAX_ALGO_NAME_SIZE];
char pattern[XT_STRING_MAX_PATTERN_SIZE]; char pattern[XT_STRING_MAX_PATTERN_SIZE];
u_int8_t patlen; u_int8_t patlen;
union {
struct {
u_int8_t invert; u_int8_t invert;
} v0;
struct {
u_int8_t flags;
} v1;
} u;
/* Used internally by the kernel */ /* Used internally by the kernel */
struct ts_config __attribute__((aligned(8))) *config; struct ts_config __attribute__((aligned(8))) *config;
......
...@@ -29,12 +29,16 @@ string_mt(const struct sk_buff *skb, const struct net_device *in, ...@@ -29,12 +29,16 @@ string_mt(const struct sk_buff *skb, const struct net_device *in,
{ {
const struct xt_string_info *conf = matchinfo; const struct xt_string_info *conf = matchinfo;
struct ts_state state; struct ts_state state;
int invert;
memset(&state, 0, sizeof(struct ts_state)); memset(&state, 0, sizeof(struct ts_state));
invert = (match->revision == 0 ? conf->u.v0.invert :
conf->u.v1.flags & XT_STRING_FLAG_INVERT);
return (skb_find_text((struct sk_buff *)skb, conf->from_offset, return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
conf->to_offset, conf->config, &state) conf->to_offset, conf->config, &state)
!= UINT_MAX) ^ conf->invert; != UINT_MAX) ^ invert;
} }
#define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m)) #define STRING_TEXT_PRIV(m) ((struct xt_string_info *)(m))
...@@ -46,6 +50,7 @@ string_mt_check(const char *tablename, const void *ip, ...@@ -46,6 +50,7 @@ string_mt_check(const char *tablename, const void *ip,
{ {
struct xt_string_info *conf = matchinfo; struct xt_string_info *conf = matchinfo;
struct ts_config *ts_conf; struct ts_config *ts_conf;
int flags = TS_AUTOLOAD;
/* Damn, can't handle this case properly with iptables... */ /* Damn, can't handle this case properly with iptables... */
if (conf->from_offset > conf->to_offset) if (conf->from_offset > conf->to_offset)
...@@ -54,8 +59,15 @@ string_mt_check(const char *tablename, const void *ip, ...@@ -54,8 +59,15 @@ string_mt_check(const char *tablename, const void *ip,
return false; return false;
if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
return false; return false;
if (match->revision == 1) {
if (conf->u.v1.flags &
~(XT_STRING_FLAG_IGNORECASE | XT_STRING_FLAG_INVERT))
return false;
if (conf->u.v1.flags & XT_STRING_FLAG_IGNORECASE)
flags |= TS_IGNORECASE;
}
ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
GFP_KERNEL, TS_AUTOLOAD); GFP_KERNEL, flags);
if (IS_ERR(ts_conf)) if (IS_ERR(ts_conf))
return false; return false;
...@@ -72,6 +84,17 @@ static void string_mt_destroy(const struct xt_match *match, void *matchinfo) ...@@ -72,6 +84,17 @@ static void string_mt_destroy(const struct xt_match *match, void *matchinfo)
static struct xt_match string_mt_reg[] __read_mostly = { static struct xt_match string_mt_reg[] __read_mostly = {
{ {
.name = "string", .name = "string",
.revision = 0,
.family = AF_INET,
.checkentry = string_mt_check,
.match = string_mt,
.destroy = string_mt_destroy,
.matchsize = sizeof(struct xt_string_info),
.me = THIS_MODULE
},
{
.name = "string",
.revision = 1,
.family = AF_INET, .family = AF_INET,
.checkentry = string_mt_check, .checkentry = string_mt_check,
.match = string_mt, .match = string_mt,
...@@ -81,6 +104,17 @@ static struct xt_match string_mt_reg[] __read_mostly = { ...@@ -81,6 +104,17 @@ static struct xt_match string_mt_reg[] __read_mostly = {
}, },
{ {
.name = "string", .name = "string",
.revision = 0,
.family = AF_INET6,
.checkentry = string_mt_check,
.match = string_mt,
.destroy = string_mt_destroy,
.matchsize = sizeof(struct xt_string_info),
.me = THIS_MODULE
},
{
.name = "string",
.revision = 1,
.family = AF_INET6, .family = AF_INET6,
.checkentry = string_mt_check, .checkentry = string_mt_check,
.match = string_mt, .match = string_mt,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment