summaryrefslogtreecommitdiffstats
path: root/src/tests/unit/condition.txt
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tests/unit/condition.txt679
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 &not-a-list:User-Name == &not-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 &not-a-packet.User-Name == &not-a-packet.User-Name
+data &not-a-packet.User-Name == &not-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`