diff options
Diffstat (limited to '')
-rw-r--r-- | src/tests/unit/condition.txt | 679 |
1 files changed, 679 insertions, 0 deletions
diff --git a/src/tests/unit/condition.txt b/src/tests/unit/condition.txt new file mode 100644 index 0000000..bbe24d2 --- /dev/null +++ b/src/tests/unit/condition.txt @@ -0,0 +1,679 @@ +# +# Tests for parsing conditional expressions. +# +# $Id$ +# + +# +# A bunch of errors, in the order that the error strings +# appear in parser.c +# + + +# All IP address literals should be parsed as prefixes +condition ("foo\ +data ERROR offset 6 End of string after escape + +condition ("foo +data ERROR offset 2 Unterminated string + +condition () +data ERROR offset 1 Empty string is invalid + +condition (!) +data ERROR offset 2 Empty string is invalid + +condition (foo == bar +data ERROR offset 11 No closing brace at end of string + +condition (|| b) +data ERROR offset 1 Empty string is invalid + +condition ((ok || handled) foo) +data ERROR offset 17 Unexpected text after condition + +# escapes in names are illegal +condition (ok\ foo || handled) +data ERROR offset 3 Unexpected escape + +condition (ok FOO handled) +data ERROR offset 4 Invalid text. Expected comparison operator + +condition (ok !x handled) +data ERROR offset 4 Invalid operator + +condition (ok =x handled) +data ERROR offset 4 Invalid operator + +condition (ok =~ handled) +data ERROR offset 7 Expected regular expression + +condition (ok == /foo/) +data ERROR offset 7 Unexpected regular expression + +condition (ok == handled"foo") +data ERROR offset 14 Unexpected start of string + +# And now we have a bunch of VALID conditions we want to parse. + +# sillyness is OK +condition ((((((ok)))))) +data ok + +# +# Extra braces get squashed +# +condition (&User-Name == &User-Password) +data &User-Name == &User-Password + +condition (!ok) +data !ok + +condition !(ok) +data !ok + +condition !!ok +data ERROR offset 1 Double negation is invalid + +condition !(!ok) +data ok + +# +# These next two are identical after normalization +# +condition (&User-Name == &User-Password || &Filter-Id == &Reply-Message) +data &User-Name == &User-Password || &Filter-Id == &Reply-Message + +condition ((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)) +data &User-Name == &User-Password || &Filter-Id == &Reply-Message + +condition (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)) +data !&User-Name == &User-Password || &Filter-Id == &Reply-Message + +# different from the previous ones. +condition (!((&User-Name == &User-Password) || (&Filter-Id == &Reply-Message))) +data !(&User-Name == &User-Password || &Filter-Id == &Reply-Message) + +condition (!(&User-Name == &User-Password) || (&Filter-Id == &Reply-Message)) +data !&User-Name == &User-Password || &Filter-Id == &Reply-Message + +condition ((a == b) || (c == d))) +data ERROR offset 22 Unexpected closing brace + +condition (handled && (Response-Packet-Type == Access-Challenge)) +data handled && &Response-Packet-Type == Access-Challenge + +# This is OK, without the braces +condition handled && &Response-Packet-Type == Access-Challenge +data handled && &Response-Packet-Type == Access-Challenge + +# and this, though it's not a good idea. +condition handled &&&Response-Packet-Type == Access-Challenge +data handled && &Response-Packet-Type == Access-Challenge + +condition /foo/ =~ bar +data ERROR offset 0 Conditional check cannot begin with a regular expression + +condition reply == request +data ERROR offset 0 Cannot use list references in condition + +condition reply == "hello" +data ERROR offset 0 Cannot use list references in condition + +condition "hello" == reply +data ERROR offset 0 Cannot use list references in condition + +condition request:User-Name == reply:User-Name +data &User-Name == &reply:User-Name + +# +# Convert !~ to !(COND) for regex +# +condition foo =~ /bar/ +data foo =~ /bar/ + +condition foo !~ /bar/ +data !foo =~ /bar/ + +condition !foo !~ /bar/ +data foo =~ /bar/ + +# +# Convert != to !(COND) for normal checks +# +condition &User-Name == &User-Password +data &User-Name == &User-Password + +condition &User-Name != &User-Password +data !&User-Name == &User-Password + +condition !&User-Name != &User-Password +data &User-Name == &User-Password + +condition <ipv6addr>foo +data ERROR offset 0 Cannot do cast for existence check + +condition <ipaddr>Filter-Id == &Framed-IP-Address +data <ipaddr>&Filter-Id == &Framed-IP-Address + +condition <ipaddr>Filter-Id == <ipaddr>&Framed-IP-Address +data ERROR offset 21 Unnecessary cast + +condition <ipaddr>Filter-Id == <integer>&Framed-IP-Address +data ERROR offset 21 Cannot cast to a different data type + +condition <ipaddr>Filter-Id == <blerg>&Framed-IP-Address +data ERROR offset 22 Invalid data type in cast + +# +# Normalize things +# +condition <ipaddr>Filter-Id == "127.0.0.1" +data <ipaddr>&Filter-Id == '127.0.0.1' + +condition <ipaddr>127.0.0.1 < &Framed-IP-Address +data &Framed-IP-Address > 127.0.0.1 + +# =* and !* are only for attrs / lists +condition "foo" !* bar +data ERROR offset 6 Cannot use !* on a string + +condition "foo" =* bar +data ERROR offset 6 Cannot use =* on a string + +# existence checks don't need the RHS +condition User-Name =* bar +data &User-Name + +condition User-Name !* bar +data !&User-Name + +condition !User-Name =* bar +data !&User-Name + +condition !User-Name !* bar +data &User-Name + +# redundant casts get squashed +condition <ipaddr>Framed-IP-Address == 127.0.0.1 +data &Framed-IP-Address == 127.0.0.1 + +condition <cidr>Framed-IP-Address <= 192.168.0.0/16 +data <ipv4prefix>&Framed-IP-Address <= 192.168.0.0/16 + +# All IP address literals should be parsed as prefixes +condition Framed-IP-Address <= 192.168.0.0/16 +data <ipv4prefix>&Framed-IP-Address <= 192.168.0.0/16 + +# string attributes must be string +condition User-Name == "bob" +data &User-Name == "bob" + +condition User-Name == `bob` +data &User-Name == `bob` + +condition User-Name == 'bob' +data &User-Name == 'bob' + +condition User-Name == bob +data ERROR offset 13 Must have string as value for attribute + +# Integer (etc.) types must be "bare" +condition Session-Timeout == 10 +data &Session-Timeout == 10 + +condition Session-Timeout == '10' +data ERROR offset 19 Value must be an unquoted string + +# Except for dates, which can be humanly readable! +# This one is be an expansion, so it's left as-is. +condition Event-Timestamp == "January 1, 2012 %{blah}" +data &Event-Timestamp == "January 1, 2012 %{blah}" + +# This one is NOT an expansion, so it's parsed into normal form +condition Event-Timestamp == 'January 1, 2012' +#data &Event-Timestamp == 'Jan 1 2012 00:00:00 EST' + +# literals are parsed when the conditions are parsed +condition <integer>X == 1 +data ERROR offset 9 Failed to parse field + +condition NAS-Port == X +data ERROR offset 12 Failed to parse value for attribute + +# +# The RHS is a static string, so this gets mashed to a literal, +# and then statically evaluated. +# +condition <ipaddr>127.0.0.1 == "127.0.0.1" +data true + +condition <ipaddr>127.0.0.1 == "%{sql: 127.0.0.1}" +data <ipaddr>127.0.0.1 == "%{sql: 127.0.0.1}" + +condition <ether> 00:11:22:33:44:55 == "00:11:22:33:44:55" +data true + +condition <ether> 00:11:22:33:44:55 == "ff:11:22:33:44:55" +data false + +condition <ether> 00:11:22:33:44:55 == "%{sql:00:11:22:33:44:55}" +data <ether>00:11:22:33:44:55 == "%{sql:00:11:22:33:44:55}" + +condition <ether> 00:XX:22:33:44:55 == 00:11:22:33:44:55 +data ERROR offset 8 Failed to parse field + +# +# Tests for boolean data types. +# +condition true +data true + +condition 1 +data true + +condition false +data false + +condition 0 +data false + +condition true && (User-Name == "bob") +data &User-Name == "bob" + +condition false && (User-Name == "bob") +data false + +condition false || (User-Name == "bob") +data &User-Name == "bob" + +condition true || (User-Name == "bob") +data true + +# +# Both sides static data with a cast: evaluate at parse time. +# +condition <integer>20 < 100 +data true + +# +# Both sides literal: evaluate at parse time +# +condition ('foo' == 'bar') +data false + +condition ('foo' < 'bar') +data false + +condition ('foo' > 'bar') +data true + +condition ('foo' == 'foo') +data true + +# +# Double-quotes strings without expansions are literals +# +condition ("foo" == "%{sql: foo}") +data foo == "%{sql: foo}" + +condition ("foo bar" == "%{sql: foo}") +data "foo bar" == "%{sql: foo}" + +condition ("foo" == "bar") +data false + +condition ("foo" == 'bar') +data false + +# +# The RHS gets parsed as a VPT_TYPE_DATA, which is +# a double-quoted string. Except that there's no '%' +# in it, so it reverts back to a literal. +# +condition (&User-Name == "bob") +data &User-Name == "bob" + +condition (&User-Name == "%{sql: blah}") +data &User-Name == "%{sql: blah}" + +condition <ipaddr>127.0.0.1 == 2130706433 +data true + +# /32 suffix should be trimmed for this type +condition <ipaddr>127.0.0.1/32 == 127.0.0.1 +data true + +condition <ipaddr>127.0.0.1/327 == 127.0.0.1 +data ERROR offset 8 Failed to parse field + +condition <ipaddr>127.0.0.1/32 == 127.0.0.1 +data true + +condition (/foo/) +data ERROR offset 1 Conditional check cannot begin with a regular expression + +# +# Tests for (FOO). +# +condition (1) +data true + +condition (0) +data false + +condition (true) +data true + +condition (false) +data false + +condition ('') +data false + +condition ("") +data false + +# +# Integers are true, as are non-zero strings +# +condition (4) +data true + +condition ('a') +data true + +condition (a) +data ERROR offset 1 Expected a module return code + +# +# Module return codes are OK +# +condition (ok) +data ok + +condition (handled) +data handled + +condition (fail) +data fail + +condition ("a") +data true + +condition (`a`) +data `a` + +condition (User-name) +data &User-Name + +# +# Forbidden data types in cast +# +condition (<vsa>"foo" == &User-Name) +data ERROR offset 2 Forbidden data type in cast + +# +# Must have attribute references on the LHS of a condition. +# +condition ("foo" == &User-Name) +data ERROR offset 1 Cannot use attribute reference on right side of condition + +# +# If the LHS is a cast to a type, and the RHS is an attribute +# of the same type, then re-write it so that the attribute +# is on the LHS of the condition. +# +condition <string>"foo" == &User-Name +data &User-Name == "foo" + +condition <integer>"%{expr: 1 + 1}" < &NAS-Port +data &NAS-Port > "%{expr: 1 + 1}" + +condition &Filter-Id == &Framed-IP-Address +data ERROR offset 0 Attribute comparisons must be of the same data type + +condition <ipaddr>127.0.0.1 == &Filter-Id +data ERROR offset 0 Attribute comparisons must be of the same data type + +condition &Tmp-Integer64-0 == &request:Foo-Stuff-Bar +data &Tmp-Integer64-0 == &Foo-Stuff-Bar + +condition &Tmp-Integer64-0 == &reply:Foo-Stuff-Bar +data &Tmp-Integer64-0 == &reply:Foo-Stuff-Bar + +# +# Casting attributes of different size +# +condition <ipaddr>&Tmp-Integer64-0 == &Framed-IP-Address +data ERROR offset 0 Cannot cast to attribute of incompatible size + +condition <ipaddr>&PMIP6-Home-IPv4-HoA == &Framed-IP-Address +data ERROR offset 0 Cannot cast to attribute of incompatible size + +# but these are allowed +condition <ether>&Tmp-Integer64-0 == "%{module: foo}" +data <ether>&Tmp-Integer64-0 == "%{module: foo}" + +condition <ipaddr>&Filter-Id == &Framed-IP-Address +data <ipaddr>&Filter-Id == &Framed-IP-Address + +condition <ipaddr>&Class == &Framed-IP-Address +data <ipaddr>&Class == &Framed-IP-Address + +# +# Tags of zero mean restrict to attributes with no tag +# +condition &Tunnel-Password:0 == "Hello" +data &Tunnel-Password:0 == "Hello" + +condition &Tunnel-Password:1 == "Hello" +data &Tunnel-Password:1 == "Hello" + +# +# Single quoted strings are left as-is +# +condition &Tunnel-Password:1 == 'Hello' +data &Tunnel-Password:1 == 'Hello' + +# +# zero offset into arrays get parsed and ignored +# +condition &User-Name[0] == "bob" +data &User-Name[0] == "bob" + +condition &User-Name[1] == "bob" +data &User-Name[1] == "bob" + +condition &User-Name[n] == "bob" +data &User-Name[n] == "bob" + +condition &Tunnel-Password:1[0] == "Hello" +data &Tunnel-Password:1[0] == "Hello" + +condition &Tunnel-Password:1[3] == "Hello" +data &Tunnel-Password:1[3] == "Hello" + +# +# This is allowed for pass2-fixups. Foo-Bar MAY be an attribute. +# If so allow it so that pass2 can fix it up. Until then, +# it's an unknown attribute +# +condition &Foo-Bar +data &Foo-Bar + +# Same types are optimized +# +# FIXME: the tests don't currently run the "pass2" checks. +# This test should really be: +# +# data &Acct-Input-Octets > &Session-Timeout +# +condition &Acct-Input-Octets > "%{Session-Timeout}" +data &Acct-Input-Octets > "%{Session-Timeout}" + +# Separate types aren't optimized +condition &Acct-Input-Octets-64 > "%{Session-Timeout}" +data &Acct-Input-Octets-64 > "%{Session-Timeout}" + +# +# Parse OIDs into known attributes, where possible. +# +condition &Attr-26.24757.84.9.5.4 == 0x1a99 +data &WiMAX-PFDv2-Src-Port == 6809 + +# +# This OID is known, but the data is malformed. +# This is disallowed. Fix the configuration so that +# it works. +# +condition &Attr-26.24757.84.9.5.7 == 0x1a99 +data ERROR offset 27 Failed to parse value for attribute + +# This one is really unknown +condition &Attr-26.24757.84.9.5.15 == 0x1a99 +data &Attr-26.24757.84.9.5.15 == 0x1a99 + +# +# Invalid array references. +# +condition &User-Name[a] == 'bob' +data ERROR offset 11 Array index is not an integer + +condition &User-Name == &Filter-Id[a] +data ERROR offset 25 Array index is not an integer + +# +# This one is still wrong. +# +condition User-Name[a] == 'bob' +data false + +# +# Bounds checks... +# +condition &User-Name[1001] == 'bob' +data ERROR offset 11 Invalid array reference '1001' (should be between 0-1000) + +condition &User-Name[-1] == 'bob' +data ERROR offset 11 Invalid array reference '-1' (should be between 0-1000) + +# +# Tags +# +condition &Tunnel-Private-Group-Id:10 == 'test' +data &Tunnel-Private-Group-Id:10 == 'test' + +condition &User-Name:10 == 'test' +data ERROR offset 10 Attribute 'User-Name' cannot have a tag + +# +# Tags are always wrong for attributes which aren't tagged. +# +condition &User-Name:0 == 'test' +data ERROR offset 10 Attribute 'User-Name' cannot have a tag + +# +# Bounds checks... +# +condition &Tunnel-Private-Group-Id:32 == 'test' +data ERROR offset 25 Invalid tag value '32' (should be between 0-31) + +condition &request:Tunnel-Private-Group-Id:-1 == 'test' +data ERROR offset 33 Invalid tag value '-1' (should be between 0-31) + +# +# Sometimes the attribute/condition parser needs to fallback to bare words +# +condition request:Foo == 'request:Foo' +data true + +condition request:Foo+Bar == request:Foo+Bar +data true + +condition &request:Foo+Bar == 'request:Foo+Bar' +data ERROR offset 12 Unexpected text after unknown attr + +condition 'request:Foo+d' == &request:Foo+Bar +data ERROR offset 31 Unexpected text after unknown attr + +# Attribute tags are not allowed for unknown attributes +condition &request:FooBar:0 == &request:FooBar +data ERROR offset 15 Unexpected text after unknown attr + +condition ¬-a-list:User-Name == ¬-a-list:User-Name +data ERROR offset 1 Invalid list qualifier + +# . is a valid dictionary name attribute, so we can't error out in pass1 +condition ¬-a-packet.User-Name == ¬-a-packet.User-Name +data ¬-a-packet.User-Name == ¬-a-packet.User-Name + +# +# The LHS is a string with ASCII 5C 30 30 30 inside of it. +# +condition ('i have scary embedded things\000 inside me' == "i have scary embedded things\000 inside me") +data false + +# +# 'Unknown' attributes which are defined in the main dictionary +# should be resolved to their real names. +condition &Attr-1 == 'bar' +data &User-Name == 'bar' + +condition &Vendor-11344-Attr-1 == 127.0.0.1 +data &FreeRADIUS-Proxied-To == 127.0.0.1 + +condition &FreeRADIUS-Attr-1 == 127.0.0.1 +data &FreeRADIUS-Proxied-To == 127.0.0.1 + +# +# Escape the backslashes correctly +# And print them correctly +# +condition &User-Name =~ /@|\\/ +data &User-Name =~ /@|\\/ + +condition &User-Name == '\\' +data &User-Name == '\\' + +condition &User-Name !~ /^foo\nbar$/ +data !&User-Name =~ /^foo\nbar$/ + +condition &User-Name == "@|\\" +data &User-Name == "@|\\" + +condition &User-Name != "foo\nbar" +data !&User-Name == "foo\nbar" + +condition User-Name =~ /^([^\\]*)\\(.*)$/ +data &User-Name =~ /^([^\\]*)\\(.*)$/ + +# +# We require explicit casts +# +condition 192.168.0.0/16 > 192.168.1.2 +data false + +condition <ipv4prefix>192.168.0.0/16 > 192.168.1.2 +data true + +condition <ipv4prefix>&NAS-IP-Address == 192.168.0.0/24 +data <ipv4prefix>&NAS-IP-Address == 192.168.0.0/24 + +condition <ipv4prefix>192.168.0.0/24 > &NAS-IP-Address +data <ipv4prefix>192.168.0.0/24 > &NAS-IP-Address + +# +# We add casts to the LHS if necessary +# +condition &NAS-IP-Address < &PMIP6-Home-IPv4-HoA +data <ipv4prefix>&NAS-IP-Address < &PMIP6-Home-IPv4-HoA + +condition &NAS-IP-Address < 192.168/16 +data <ipv4prefix>&NAS-IP-Address < 192.168.0.0/16 + +condition &NAS-IP-Address < "%{echo: 192.168/16}" +data <ipv4prefix>&NAS-IP-Address < "%{echo: 192.168/16}" + +condition &NAS-IP-Address < `/bin/echo 192.168/16` +data <ipv4prefix>&NAS-IP-Address < `/bin/echo 192.168/16` |