diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:49:46 +0000 |
commit | 50b37d4a27d3295a29afca2286f1a5a086142cec (patch) | |
tree | 9212f763934ee090ef72d823f559f52ce387f268 /src/tests/modules | |
parent | Initial commit. (diff) | |
download | freeradius-upstream.tar.xz freeradius-upstream.zip |
Adding upstream version 3.2.1+dfsg.upstream/3.2.1+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
163 files changed, 3244 insertions, 0 deletions
diff --git a/src/tests/modules/README.rst b/src/tests/modules/README.rst new file mode 100644 index 0000000..164509d --- /dev/null +++ b/src/tests/modules/README.rst @@ -0,0 +1,18 @@ +Module Tests +------------ + +To test module `foo`, create a directory `foo`, and put a file `all.mk` into it, e.g. + + foo/all.mk + +All of the tests for the module should go here. The tests will be run +*only* if the module is available, and has been built correctly on the system. + +The file should contain a target "MODULE.test". This is the main +target used to test the module. The framework automatically makes the +tests depend on the module (i.e. library). So if the module source +changes, you can just do `make MODULE.test`. The module will be +re-built, and the tests will be run. + +Note: all SQL tests share the same tests definitions (see sql directory). +The modules themselves simply link to the actual tests files. diff --git a/src/tests/modules/all.mk b/src/tests/modules/all.mk new file mode 100644 index 0000000..9960df7 --- /dev/null +++ b/src/tests/modules/all.mk @@ -0,0 +1,40 @@ +# +# Find the subdirs which have "all.mk" +# +TEST_SUBDIRS := $(patsubst src/tests/modules/%/all.mk,%,$(wildcard src/tests/modules/*/all.mk)) + +# +# Find out which of those have a similar target. i.e. modules/foo -> rlm_foo.la +# +TEST_TARGETS := $(foreach x,$(TEST_SUBDIRS),$(findstring rlm_$x.la,$(ALL_TGTS))) + +TEST_BUILT := $(patsubst rlm_%.la,%,$(TEST_TARGETS)) + +# +# Ensure that the tests depend on the module, so that changes to the +# module will re-run the test +# +$(foreach x,$(TEST_BUILT),$(eval $x.test: rlm_$x.la)) + +###################################################################### + +# +# And do the same thing for sub-directories +# +TEST_SUBSUBDIRS := $(patsubst src/tests/modules/%/all.mk,%,$(wildcard src/tests/modules/*/*/all.mk)) + +TEST_SUBTARGETS := $(foreach x,$(TEST_SUBSUBDIRS),$(findstring rlm_$(subst /,_,$x).la,$(ALL_TGTS))) + +TEST_SUBBUILT := $(patsubst rlm_%.la,%,$(TEST_SUBTARGETS)) + +$(foreach x,$(TEST_SUBBUILT),$(eval $x.test: rlm_$(subst /,_,$x).la)) + +###################################################################### +# +# For the remaining subdirs, add on the directory to include. +# test.mk will run the tests for all modules +# It is included last so that the module specific makefiles can be processed first +# (modules that require a test server can set the corresponding require_test_server variable) +# +SUBMAKEFILES := $(addsuffix /all.mk,$(TEST_BUILT) $(subst _,/,$(TEST_SUBBUILT))) test.mk + diff --git a/src/tests/modules/always/all.mk b/src/tests/modules/always/all.mk new file mode 100644 index 0000000..8f1127f --- /dev/null +++ b/src/tests/modules/always/all.mk @@ -0,0 +1,3 @@ +# +# Test the "always" module +# diff --git a/src/tests/modules/always/module.conf b/src/tests/modules/always/module.conf new file mode 100644 index 0000000..39995e5 --- /dev/null +++ b/src/tests/modules/always/module.conf @@ -0,0 +1,7 @@ +always my_reject { + rcode = reject +} + +always db_status { + rcode = ok +} diff --git a/src/tests/modules/always/replace.unlang b/src/tests/modules/always/replace.unlang new file mode 100644 index 0000000..1d502f7 --- /dev/null +++ b/src/tests/modules/always/replace.unlang @@ -0,0 +1,11 @@ +%{poke:my_reject.rcode=ok} + +my_reject # should be "ok" + +update control { + Cleartext-Password := "hello" +} + +update reply { + Filter-Id := "success" +} diff --git a/src/tests/modules/always/set_rcode.unlang b/src/tests/modules/always/set_rcode.unlang new file mode 100644 index 0000000..faaed28 --- /dev/null +++ b/src/tests/modules/always/set_rcode.unlang @@ -0,0 +1,44 @@ +# +# Set status to "notfound". xlat should expand to previous status, "alive" +# +if ("%{db_status:notfound}" != "alive") { + update reply { + Filter-Id += "failed" + } +} + + +# +# Verify that the status was changed +# +db_status +if (!notfound) { + update reply { + Filter-Id += "failed" + } +} + + +# +# Fetch status using xlat without setting the status +# +if ("%{db_status:}" != "notfound") { + update reply { + Filter-Id += "failed" + } +} + + +# +# Verify that the status did not change +# +db_status +if (notfound) { + update reply { + Filter-Id += "success" + } +} + +update control { + Cleartext-Password := "hello" +} diff --git a/src/tests/modules/always/set_status_dead.unlang b/src/tests/modules/always/set_status_dead.unlang new file mode 100644 index 0000000..6b29ede --- /dev/null +++ b/src/tests/modules/always/set_status_dead.unlang @@ -0,0 +1,18 @@ +# +# Set the module status to dead, call it and check that it fails +# +%{db_status:dead} + +db_status { + fail = 1 +} + +if (fail) { + update reply { + Filter-Id := "success" + } +} + +update control { + Cleartext-Password := "hello" +} diff --git a/src/tests/modules/always/set_status_revive.unlang b/src/tests/modules/always/set_status_revive.unlang new file mode 100644 index 0000000..3e71d39 --- /dev/null +++ b/src/tests/modules/always/set_status_revive.unlang @@ -0,0 +1,28 @@ +# +# Fail a module... +# +%{db_status:dead} +db_status { + fail = 1 +} +if (!fail) { + update reply { + Filter-Id += "failed" + } +} + + +# +# ... Now revive it +# +%{db_status:alive} +db_status +if (ok) { + update reply { + Filter-Id += "success" + } +} + +update control { + Cleartext-Password := "hello" +} diff --git a/src/tests/modules/cache/rbtree/all.mk b/src/tests/modules/cache/rbtree/all.mk new file mode 100644 index 0000000..8f89aa6 --- /dev/null +++ b/src/tests/modules/cache/rbtree/all.mk @@ -0,0 +1,2 @@ +cache_rbtree.test: + diff --git a/src/tests/modules/default-input.attrs b/src/tests/modules/default-input.attrs new file mode 100644 index 0000000..d24ac4b --- /dev/null +++ b/src/tests/modules/default-input.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = "bob" +User-Password = "hello" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Filter-Id == 'success' diff --git a/src/tests/modules/files/addcontrol.attrs b/src/tests/modules/files/addcontrol.attrs new file mode 100644 index 0000000..7588b9c --- /dev/null +++ b/src/tests/modules/files/addcontrol.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +User-Name = "addcontrol" +User-Password = "testing123" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Cleartext-Password == 'testing123' +Reply-Message == "success1" +Reply-Message == "success2" diff --git a/src/tests/modules/files/addcontrol.unlang b/src/tests/modules/files/addcontrol.unlang new file mode 100644 index 0000000..5b431f1 --- /dev/null +++ b/src/tests/modules/files/addcontrol.unlang @@ -0,0 +1,8 @@ +# +# Run the "files" module +# +files + +update { + &reply: += &control:[*] +} diff --git a/src/tests/modules/files/addreply.attrs b/src/tests/modules/files/addreply.attrs new file mode 100644 index 0000000..69e1a19 --- /dev/null +++ b/src/tests/modules/files/addreply.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "addreply" +User-Password = "testing123" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Reply-Message == 'success1' +Reply-Message == 'success2' diff --git a/src/tests/modules/files/addreply.unlang b/src/tests/modules/files/addreply.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/addreply.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/files/all.mk b/src/tests/modules/files/all.mk new file mode 100644 index 0000000..07449db --- /dev/null +++ b/src/tests/modules/files/all.mk @@ -0,0 +1,3 @@ +# +# Test the "files" module +# diff --git a/src/tests/modules/files/authorize b/src/tests/modules/files/authorize new file mode 100644 index 0000000..b85f6a2 --- /dev/null +++ b/src/tests/modules/files/authorize @@ -0,0 +1,92 @@ +# +# Test if the "users" file works +# + + +# +# Basic syntax tests with comments. Parsing only. +# + +user Cleartext-Password := "hello" # comment! + + +user2 # comment! + Reply-Message := "24" + + +# +# Setting ":=" of reply and control items +# + +bob Cleartext-Password := "hello" + Reply-Message := "success" + + +# +# Detect erroneous Fall-Through +# + +doug Cleartext-Password := "goodbye" + Reply-Message := "success" + +doug + Reply-Message := "unreachable" + + +# +# Fall-Through across a non-matching entry +# + +famous Cleartext-Password := "bradpitt" + Fall-Through = yes + +unused Cleartext-Password := "jabberwocky" + Reply-Message := "fail" + +famous + Reply-Message := "success" + + +# +# Modification of the reply list +# + +addreply Cleartext-Password := "testing123" + Reply-Message := "success1", + Fall-Through = yes + +addreply + Reply-Message += "success2" + + +subreply Cleartext-Password := "testing123" + Reply-Message := "success1", + Reply-Message += "success2", + Reply-Message += "success3", + Fall-Through = yes + +subreply Cleartext-Password := "testing123" + Reply-Message -= "success2" + + +filterreply Cleartext-Password := "testing123" + Reply-Message := "success1", + Reply-Message += "success2", + Fall-Through = yes + +filterreply Cleartext-Password := "testing123" + Reply-Message !* ANY + + +# +# Addition "+=" to the control list +# +# Note: Set ":=" of control items is already tested with Cleartext-Password +# Note: Filtering "!*" does not apply to control items as this would overload +# the operator syntax since "!*" checks that no such attribute in the +# request. + +addcontrol Cleartext-Password := "testing123", Reply-Message := "success1" + Fall-Through = yes + +addcontrol Reply-Message += "success2" diff --git a/src/tests/modules/files/bob.attrs b/src/tests/modules/files/bob.attrs new file mode 100644 index 0000000..a4acfab --- /dev/null +++ b/src/tests/modules/files/bob.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = "doug" +User-Password = "goodbye" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Reply-Message == 'success' diff --git a/src/tests/modules/files/bob.unlang b/src/tests/modules/files/bob.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/bob.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/files/doug.attrs b/src/tests/modules/files/doug.attrs new file mode 100644 index 0000000..a4acfab --- /dev/null +++ b/src/tests/modules/files/doug.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = "doug" +User-Password = "goodbye" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Reply-Message == 'success' diff --git a/src/tests/modules/files/doug.unlang b/src/tests/modules/files/doug.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/doug.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/files/fall-through.attrs b/src/tests/modules/files/fall-through.attrs new file mode 100644 index 0000000..899d3d9 --- /dev/null +++ b/src/tests/modules/files/fall-through.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = "famous" +User-Password = "bradpitt" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Reply-Message == 'success' diff --git a/src/tests/modules/files/fall-through.unlang b/src/tests/modules/files/fall-through.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/fall-through.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/files/filterreply.attrs b/src/tests/modules/files/filterreply.attrs new file mode 100644 index 0000000..c1add29 --- /dev/null +++ b/src/tests/modules/files/filterreply.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = "filterreply" +User-Password = "testing123" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/files/filterreply.unlang b/src/tests/modules/files/filterreply.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/filterreply.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/files/module.conf b/src/tests/modules/files/module.conf new file mode 100644 index 0000000..12b46ac --- /dev/null +++ b/src/tests/modules/files/module.conf @@ -0,0 +1,9 @@ +files { + # The default key attribute to use for matches. The content + # of this attribute is used to match the "name" of the + # entry. + #key = "%{%{Stripped-User-Name}:-%{User-Name}}" + + # The old "users" style file is now located here. + filename = $ENV{MODULE_TEST_DIR}/authorize +} diff --git a/src/tests/modules/files/subreply.attrs b/src/tests/modules/files/subreply.attrs new file mode 100644 index 0000000..6fe6237 --- /dev/null +++ b/src/tests/modules/files/subreply.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "subreply" +User-Password = "testing123" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Reply-Message == 'success1' +Reply-Message == 'success3' diff --git a/src/tests/modules/files/subreply.unlang b/src/tests/modules/files/subreply.unlang new file mode 100644 index 0000000..456c666 --- /dev/null +++ b/src/tests/modules/files/subreply.unlang @@ -0,0 +1,4 @@ +# +# Run the "files" module +# +files diff --git a/src/tests/modules/json/all.mk b/src/tests/modules/json/all.mk new file mode 100644 index 0000000..4d3197d --- /dev/null +++ b/src/tests/modules/json/all.mk @@ -0,0 +1,3 @@ +# +# Test the "json" module +# diff --git a/src/tests/modules/json/encode.attrs b/src/tests/modules/json/encode.attrs new file mode 100644 index 0000000..ea8d653 --- /dev/null +++ b/src/tests/modules/json/encode.attrs @@ -0,0 +1,13 @@ +# +# Input packet +# +User-Name = 'john' +Filter-Id = "f1" +Filter-Id += "f2" +NAS-Port = 999 +Service-Type = Login-User + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/json/encode.unlang b/src/tests/modules/json/encode.unlang new file mode 100644 index 0000000..6c7a1fe --- /dev/null +++ b/src/tests/modules/json/encode.unlang @@ -0,0 +1,233 @@ +# +# json_encode tests +# + + +# 0. Check basic xlat parsing + +update control { + &Tmp-String-1 := "%{json_encode:&request:[*]}" + &Tmp-String-2 := "%{json_encode:&request:[*] }" + &Tmp-String-3 := "%{json_encode: &request:[*]}" + &Tmp-String-4 := "%{json_encode: &request:[*] }" + &Tmp-String-5 := "%{json_encode: &request:[*] !&Filter-Id }" + &Tmp-String-6 := "%{json_encode:&request:[*] ! }" +## Check defaults are the same as output_mode "object": + &Tmp-String-7 := "%{json_object_encode:&request:[*]}" + &Tmp-String-8 := "%{json_object_no_encode:&request:[*]}" +} + + +if (&control:Tmp-String-1 != '{"User-Name":{"type":"string","value":"john"},"Filter-Id":{"type":"string","value":["f1","f2"]},"NAS-Port":{"type":"integer","value":999},"Service-Type":{"type":"integer","value":"Login-User"}}') { + test_fail +} + +# Check xlat input formats +if (&control:Tmp-String-1 != &control:Tmp-String-2 || \ + &control:Tmp-String-1 != &control:Tmp-String-3 || \ + &control:Tmp-String-1 != &control:Tmp-String-4) { + test_fail +} + +# Check defaults +if (&control:Tmp-String-1 != &control:Tmp-String-7 || \ + &control:Tmp-String-1 != &control:Tmp-String-8) { + test_fail +} + +if (&control:Tmp-String-5 != '{"User-Name":{"type":"string","value":"john"},"NAS-Port":{"type":"integer","value":999},"Service-Type":{"type":"integer","value":"Login-User"}}') { + test_fail +} + +if (&control:Tmp-String-6 != '') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Tmp-String-3 !* ANY + &Tmp-String-4 !* ANY + &Tmp-String-5 !* ANY + &Tmp-String-6 !* ANY + &Tmp-String-7 !* ANY + &Tmp-String-8 !* ANY +} + + +# 1a. Output mode "object" tests + +# These are unsorted dictionaries. Hopefully json-c doesn't suddenly +# decide that it's going to use a different ordering of the keys... + +update control { + &Tmp-String-1 := "%{json_object_encode:&request:[*]}" + &Tmp-String-2 := "%{json_object_ex_encode:&request:[*]}" +} + +if (&control:Tmp-String-1 != '{"User-Name":{"type":"string","value":"john"},"Filter-Id":{"type":"string","value":["f1","f2"]},"NAS-Port":{"type":"integer","value":999},"Service-Type":{"type":"integer","value":"Login-User"}}') { + test_fail +} + +if (&control:Tmp-String-2 != '{"pf:User-Name":{"type":"string","value":["john"]},"pf:Filter-Id":{"type":"string","value":["f1","f2"]},"pf:NAS-Port":{"type":"integer","value":["999"]},"pf:Service-Type":{"type":"integer","value":["1"]}}') { + test_fail +} + +# 1b. "object" empty inputs + +update control { + &Tmp-String-1 := "%{json_object_encode:!&request:[*]}" +} + +if (&control:Tmp-String-1 != '{}') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Module-Failure-Message !* ANY +} + + +# 2a. Output mode "object_simple" tests + +update control { + &Tmp-String-1 := "%{json_object_simple_encode:&request:[*]}" + &Tmp-String-2 := "%{json_object_simple_ex_encode:&request:[*]}" +} + +if (&control:Tmp-String-1 != '{"User-Name":"john","Filter-Id":["f1","f2"],"NAS-Port":999,"Service-Type":"Login-User"}') { + test_fail +} + +if (&control:Tmp-String-2 != '{"pf:User-Name":["john"],"pf:Filter-Id":["f1","f2"],"pf:NAS-Port":["999"],"pf:Service-Type":["1"]}') { + test_fail +} + +# 2b. "object_simple" empty inputs + +update control { + &Tmp-String-1 := "%{json_object_simple_encode:!&request:[*]}" +} + +if (&control:Tmp-String-1 != '{}') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Module-Failure-Message !* ANY +} + + +# 3a. Output mode "array" tests + +update control { + &Tmp-String-1 := "%{json_array_encode:&request:[*]}" + &Tmp-String-2 := "%{json_array_ex_encode:&request:[*]}" +} + +if (&control:Tmp-String-1 != '[{"name":"User-Name","type":"string","value":"john"},{"name":"Filter-Id","type":"string","value":"f1"},{"name":"Filter-Id","type":"string","value":"f2"},{"name":"NAS-Port","type":"integer","value":999},{"name":"Service-Type","type":"integer","value":"Login-User"}]') { + test_fail +} + +if (&control:Tmp-String-2 != '[{"name":"pf:User-Name","type":"string","value":["john"]},{"name":"pf:Filter-Id","type":"string","value":["f1","f2"]},{"name":"pf:NAS-Port","type":"integer","value":["999"]},{"name":"pf:Service-Type","type":"integer","value":["1"]}]') { + test_fail +} + +# 3b. "array" empty inputs + +update control { + &Tmp-String-1 := "%{json_array_encode:!&request:[*]}" +} + +if (&control:Tmp-String-1 != '[]') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Module-Failure-Message !* ANY +} + + +# 4a. Output mode "array_of_names" tests + +update control { + &Tmp-String-1 := "%{json_array_names_encode:&request:[*]}" + &Tmp-String-2 := "%{json_array_names_ex_encode:&request:[*]}" +} + +if (&control:Tmp-String-1 != '["User-Name","Filter-Id","Filter-Id","NAS-Port","Service-Type"]') { + test_fail +} + +if (&control:Tmp-String-2 != '["pf:User-Name","pf:Filter-Id","pf:Filter-Id","pf:NAS-Port","pf:Service-Type"]') { + test_fail +} + +# 4b. "array_of_names" empty inputs + +update control { + &Tmp-String-1 := "%{json_array_names_encode:!&request:[*]}" +} + +if (&control:Tmp-String-1 != '[]') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Module-Failure-Message !* ANY +} + + +# 5a. Output mode "array_of_values" tests + +update control { + &Tmp-String-1 := "%{json_array_values_encode:&request:[*]}" + &Tmp-String-2 := "%{json_array_values_ex_encode:&request:[*]}" +} + +if (&control:Tmp-String-1 != '["john","f1","f2",999,"Login-User"]') { + test_fail +} + +if (&control:Tmp-String-2 != '["john","f1","f2","999","1"]') { + test_fail +} + +# 5b. "array_of_values" empty inputs + +update control { + &Tmp-String-1 := "%{json_array_values_encode:!&request:[*]}" +} + +if (&control:Tmp-String-1 != '[]') { + test_fail +} + +update control { + &Tmp-String-1 !* ANY + &Tmp-String-2 !* ANY + &Module-Failure-Message !* ANY +} + + +# Convert `make json.test` unlang update output to tests, for when +# things need updating. +# +# cat \ +# | cut -c44- \ +# | sed -e 's/\\"/"/g' \ +# -e 's/\s*$//' \ +# -e "s/:= \"/== '/" \ +# -e 's/^/if (/' \ +# -e "s/\"$/') {/" \ +# -e "s/$/\n test_pass\n} else {\n test_fail\n}\n/" + +test_pass diff --git a/src/tests/modules/json/module.conf b/src/tests/modules/json/module.conf new file mode 100644 index 0000000..04d1b1d --- /dev/null +++ b/src/tests/modules/json/module.conf @@ -0,0 +1,150 @@ +json { +} + + +# +# Output mode "object" +# + +json json_object { + encode { + output_mode = object + } +} + +json json_object_no { + encode { + output_mode = object + + value { + single_value_as_array = no + enum_as_integer = no + always_string = no + } + } +} + + +json json_object_ex { + encode { + output_mode = object + + attribute { + prefix = "pf" + } + + value { + single_value_as_array = yes + enum_as_integer = yes + always_string = yes + } + } +} + + +# +# Output mode "object_simple" +# + +json json_object_simple { + encode { + output_mode = object_simple + } +} + +json json_object_simple_ex { + encode { + output_mode = object_simple + + attribute { + prefix = "pf" + } + + value { + single_value_as_array = yes + enum_as_integer = yes + always_string = yes + } + } +} + + +# +# Output mode "array" +# + +json json_array { + encode { + output_mode = array + } +} + +json json_array_ex { + encode { + output_mode = array + + attribute { + prefix = "pf" + } + + value { + single_value_as_array = yes + enum_as_integer = yes + always_string = yes + } + } +} + + +# +# Output mode "array_of_names" +# + +json json_array_names { + encode { + output_mode = array_of_names + } +} + +json json_array_names_ex { + encode { + output_mode = array_of_names + + attribute { + prefix = "pf" + } + + value { + single_value_as_array = yes # not valid + enum_as_integer = yes # not valid + always_string = yes # not valid + } + } +} + + +# +# Output mode "array_of_values" +# + +json json_array_values { + encode { + output_mode = array_of_values + } +} + +json json_array_values_ex { + encode { + output_mode = array_of_values + + attribute { + prefix = "pf" # not valid + } + + value { + single_value_as_array = yes # not valid + enum_as_integer = yes + always_string = yes + } + } +} diff --git a/src/tests/modules/ldap/acct.attrs b/src/tests/modules/ldap/acct.attrs new file mode 100644 index 0000000..1d57034 --- /dev/null +++ b/src/tests/modules/ldap/acct.attrs @@ -0,0 +1,35 @@ +# +# Input packet +# +User-Name = 'john' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/ldap/acct.unlang b/src/tests/modules/ldap/acct.unlang new file mode 100644 index 0000000..2297ea7 --- /dev/null +++ b/src/tests/modules/ldap/acct.unlang @@ -0,0 +1,23 @@ +# +# Run the "ldap" module +# PRE: auth +# +ldap.accounting { +} +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-String-0 := "%{ldap:ldap://$ENV{TEST_SERVER}/uid=john,ou=people,dc=example,dc=com?description}" +} + +if (&Tmp-String-0 != "User john is online") { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/ldap/all.mk b/src/tests/modules/ldap/all.mk new file mode 100644 index 0000000..1fc53d1 --- /dev/null +++ b/src/tests/modules/ldap/all.mk @@ -0,0 +1,8 @@ +# +# Test the "ldap" module +# + +# MODULE.test is the main target for this module. + +# Don't test ldap if TEST_SERVER ENV is not set +ldap_require_test_server := 1 diff --git a/src/tests/modules/ldap/auth.attrs b/src/tests/modules/ldap/auth.attrs new file mode 100644 index 0000000..be988ee --- /dev/null +++ b/src/tests/modules/ldap/auth.attrs @@ -0,0 +1,15 @@ +# +# Input packet +# +User-Name = "john" +User-Password = "password" +NAS-IP-Address = 1.2.3.5 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 +Session-Timeout == 7200 +Acct-Interim-Interval == 1800 +Framed-IP-Netmask == "255.255.0.0" diff --git a/src/tests/modules/ldap/auth.unlang b/src/tests/modules/ldap/auth.unlang new file mode 100644 index 0000000..edf14bf --- /dev/null +++ b/src/tests/modules/ldap/auth.unlang @@ -0,0 +1,72 @@ +# +# Run the "ldap" module +# +ldap + +if (&control:NAS-IP-Address != 1.2.3.4) { + test_fail +} +else { + test_pass +} + +if (&control:Reply-Message != "Hello world") { + test_fail +} +else { + test_pass +} + +# Cmp operator means Framed-IP-Address is ignored +if (&control:Framed-IP-Address) { + test_fail +} +else { + test_pass +} + +# IP netmask defined in profile1 should overwrite radprofile value. +if (&reply:Framed-IP-Netmask != 255.255.0.0) { + test_fail +} +else { + test_pass +} + +if (&reply:Acct-Interim-Interval != 1800) { + test_fail +} +else { + test_pass +} + +if (&reply:Idle-Timeout != 3600) { + test_fail +} +else { + test_pass +} + +if (&reply:Session-Timeout != 7200) { + test_fail +} +else { + test_pass +} + +if ("%{pairs:reply:}" == "") { + test_fail +} + +ldap.post-auth + +update { + Tmp-String-0 := "%{ldap:ldap://$ENV{TEST_SERVER}/uid=john,ou=people,dc=example,dc=com?description}" +} + +if (&Tmp-String-0 != "User %{User-Name} authenticated") { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/ldap/example.com.ldif b/src/tests/modules/ldap/example.com.ldif new file mode 120000 index 0000000..055d379 --- /dev/null +++ b/src/tests/modules/ldap/example.com.ldif @@ -0,0 +1 @@ +../../salt-test-server/salt/ldap/base.ldif
\ No newline at end of file diff --git a/src/tests/modules/ldap/groups_rfc2307bis.attrs b/src/tests/modules/ldap/groups_rfc2307bis.attrs new file mode 100644 index 0000000..be988ee --- /dev/null +++ b/src/tests/modules/ldap/groups_rfc2307bis.attrs @@ -0,0 +1,15 @@ +# +# Input packet +# +User-Name = "john" +User-Password = "password" +NAS-IP-Address = 1.2.3.5 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 +Session-Timeout == 7200 +Acct-Interim-Interval == 1800 +Framed-IP-Netmask == "255.255.0.0" diff --git a/src/tests/modules/ldap/groups_rfc2307bis.unlang b/src/tests/modules/ldap/groups_rfc2307bis.unlang new file mode 100644 index 0000000..b8f48b5 --- /dev/null +++ b/src/tests/modules/ldap/groups_rfc2307bis.unlang @@ -0,0 +1,41 @@ +# +# Run the "ldap" module +# +ldap + +# +# Resolve using group name attribute +# +if (LDAP-Group == 'foo') { + test_pass +} +else { + test_fail +} + +# +# Resolve using group DN +# +if (LDAP-Group == 'cn=foo,ou=groups,dc=example,dc=com') { + test_pass +} +else { + test_fail +} + +# +# Check we have these values cached +# +if (&control:LDAP-Cached-Membership[*] == 'foo') { + test_pass +} +else { + test_fail +} + +if (&control:LDAP-Cached-Membership[*] == 'cn=foo,ou=groups,dc=example,dc=com') { + test_pass +} +else { + test_fail +} diff --git a/src/tests/modules/ldap/module.conf b/src/tests/modules/ldap/module.conf new file mode 100644 index 0000000..dcf3126 --- /dev/null +++ b/src/tests/modules/ldap/module.conf @@ -0,0 +1,537 @@ +# -*- text -*- +# +# $Id$ + +# +# Lightweight Directory Access Protocol (LDAP) +# +ldap { + # Note that this needs to match the name(s) in the LDAP server + # certificate, if you're using ldaps. See OpenLDAP documentation + # for the behavioral semantics of specifying more than one host. + # + # Depending on the libldap in use, server may be an LDAP URI. + # In the case of OpenLDAP this allows additional the following + # additional schemes: + # - ldaps:// (LDAP over SSL) + # - ldapi:// (LDAP over Unix socket) + # - ldapc:// (Connectionless LDAP) + server = $ENV{LDAP_TEST_SERVER} +# server = 'ldap.rrdns.example.org' + + # Port to connect on, defaults to 389, will be ignored for LDAP URIs. + port = $ENV{LDAP_TEST_SERVER_PORT} + + # Administrator account for searching and possibly modifying. + identity = 'cn=admin,dc=example,dc=com' + password = secret + + # Unless overridden in another section, the dn from which all + # searches will start from. + base_dn = 'dc=example,dc=com' + + # SASL parameters to use for admin binds + # + # When we're prompted by the SASL library, these control + # the responses given. + # + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = 'autz_id' + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # + # Generic valuepair attribute + # + + # If set, this will attribute will be retrieved in addition to any + # mapped attributes. + # + # Values should be in the format: + # <radius attr> <op> <value> + # + # Where: + # <radius attr>: Is the attribute you wish to create + # with any valid list and request qualifiers. + # <op>: Is any assignment operator (=, :=, +=, -=). + # <value>: Is the value to parse into the new valuepair. + # If the value is wrapped in double quotes it + # will be xlat expanded. + valuepair_attribute = 'radiusAttribute' + + # + # Mapping of LDAP directory attributes to RADIUS dictionary attributes. + # + + # WARNING: Although this format is almost identical to the unlang + # update section format, it does *NOT* mean that you can use other + # unlang constructs in module configuration files. + # + # Configuration items are in the format: + # <radius attr> <op> <ldap attr> + # + # Where: + # <radius attr>: Is the destination RADIUS attribute + # with any valid list and request qualifiers. + # <op>: Is any assignment attribute (=, :=, +=, -=). + # <ldap attr>: Is the attribute associated with user or + # profile objects in the LDAP directory. + # If the attribute name is wrapped in double + # quotes it will be xlat expanded. + # + # Request and list qualifiers may also be placed after the 'update' + # section name to set defaults destination requests/lists + # for unqualified RADIUS attributes. + # + # Note: LDAP attribute names should be single quoted unless you want + # the name value to be derived from an xlat expansion, or an + # attribute ref. + update { + control:Password-With-Header += 'userPassword' + reply:Idle-Timeout := 'radiusIdleTimeout' + reply:Framed-IP-Netmask := 'radiusFramedIPNetmask' +# control:NT-Password := 'ntPassword' +# reply:Reply-Message := 'radiusReplyMessage' +# reply:Tunnel-Type := 'radiusTunnelType' +# reply:Tunnel-Medium-Type := 'radiusTunnelMediumType' +# reply:Tunnel-Private-Group-ID := 'radiusTunnelPrivategroupId' + + # Where only a list is specified as the RADIUS attribute, + # the value of the LDAP attribute is parsed as a valuepair + # in the same format as the 'valuepair_attribute' (above). + control: += 'radiusControlAttribute' + request: += 'radiusRequestAttribute' + reply: += 'radiusReplyAttribute' + } + + # Set to yes if you have eDirectory and want to use the universal + # password mechanism. +# edir = no + + # Set to yes if you want to bind as the user after retrieving the + # Cleartext-Password. This will consume the login grace, and + # verify user authorization. +# edir_autz = no + + # Note: set_auth_type was removed in v3.x.x + # Equivalent functionality can be achieved by adding the following + # stanza to the authorize {} section of your virtual server. + # + # ldap + # if ((ok || updated) && User-Password) { + # update { + # control:Auth-Type := ldap + # } + # } + + # + # User object identification. + # + user { + # Where to start searching in the tree for users + base_dn = "ou=people,${..base_dn}" + + # Filter for user objects, should be specific enough + # to identify a single user object. + filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" + + # SASL parameters to use for user binds + # + # When we're prompted by the SASL library, these control + # the responses given. + # + # Any of the config items below may be an attribute ref + # or and expansion, so different SASL mechs, proxy IDs + # and realms may be used for different users. + sasl { + # SASL mechanism +# mech = 'PLAIN' + + # SASL authorisation identity to proxy. +# proxy = &User-Name + + # SASL realm. Used for kerberos. +# realm = 'example.org' + } + + # Search scope, may be 'base', 'one', sub' or 'children' +# scope = 'sub' + + # If this is undefined, anyone is authorised. + # If it is defined, the contents of this attribute + # determine whether or not the user is authorised +# access_attribute = 'dialupAccess' + + # Control whether the presence of 'access_attribute' + # allows access, or denys access. + # + # If 'yes', and the access_attribute is present, or + # 'no' and the access_attribute is absent then access + # will be allowed. + # + # If 'yes', and the access_attribute is absent, or + # 'no' and the access_attribute is present, then + # access will not be allowed. + # + # If the value of the access_attribute is 'false', it + # will negate the result. + # + # e.g. + # access_positive = yes + # access_attribute = userAccessAllowed + # + # With an LDAP object containing: + # userAccessAllowed: false + # + # Will result in the user being locked out. +# access_positive = yes + } + + # + # User membership checking. + # + group { + # Where to start searching in the tree for groups + base_dn = "ou=groups,${..base_dn}" + + # Filter for group objects, should match all available + # group objects a user might be a member of. + filter = '(objectClass=groupOfNames)' + + # Search scope, may be 'base', 'one', sub' or 'children' + scope = 'sub' + + # Attribute that uniquely identifies a group. + # Is used when converting group DNs to group + # names. + name_attribute = cn + + # Filter to find group objects a user is a member of. + # That is, group objects with attributes that + # identify members (the inverse of membership_attribute). + membership_filter = "(|(member=%{control:Ldap-UserDn})(memberUid=%{%{Stripped-User-Name}:-%{User-Name}}))" + + # The attribute in user objects which contain the names + # or DNs of groups a user is a member of. + # + # Unless a conversion between group name and group DN is + # needed, there's no requirement for the group objects + # referenced to actually exist. + membership_attribute = 'memberOf' + + # If cacheable_name or cacheable_dn are enabled, + # all group information for the user will be + # retrieved from the directory and written to LDAP-Group + # attributes appropriate for the instance of rlm_ldap. + # + # For group comparisons these attributes will be checked + # instead of querying the LDAP directory directly. + # + # This feature is intended to be used with rlm_cache. + # + # If you wish to use this feature, you should enable + # the type that matches the format of your check items + # i.e. if your groups are specified as DNs then enable + # cacheable_dn else enable cacheable_name. + cacheable_name = yes + cacheable_dn = yes + + # Override the normal cache attribute (<inst>-LDAP-Group) + # and create a custom attribute. This can help if multiple + # module instances are used in fail-over. + cache_attribute = 'LDAP-Cached-Membership' + } + + # + # User profiles. RADIUS profile objects contain sets of attributes + # to insert into the request. These attributes are mapped using + # the same mapping scheme applied to user objects. + # + profile { + # Filter for RADIUS profile objects + filter = '(objectclass=radiusprofile)' + + # The default profile applied to all users. + default = 'cn=radprofile,ou=profiles,dc=example,dc=com' + + # The list of profiles which are applied (after the default) + # to all users. + # The 'User-Profile' attribute in the control list + # will override this setting at run-time. + attribute = 'radiusProfileDn' + } + + # + # Bulk load clients from the directory + # + client { + # Where to start searching in the tree for clients + base_dn = "ou=clients,${..base_dn}" + + # + # Filter to match client objects + # + filter = '(objectClass=radiusClient)' + + # Search scope, may be 'base', 'one', 'sub' or 'children' +# scope = 'sub' + + # + # Sets default values (not obtained from LDAP) for new client entries + # + template { +# login = 'test' +# password = 'test' +# proto = tcp +# require_message_authenticator = yes + + # Uncomment to add a home_server with the same + # attributes as the client. +# coa_server { +# response_window = 2.0 +# } + } + + # + # Client attribute mappings are in the format: + # <client attribute> = <ldap attribute> + # + # The following attributes are required: + # * ipaddr | ipv4addr | ipv6addr - Client IP Address. + # * secret - RADIUS shared secret. + # + # All other attributes usually supported in a client + # definition are also supported here. + # + # Schemas are available in doc/schemas/ldap for openldap and eDirectory + # + attribute { + ipaddr = 'radiusClientIdentifier' + secret = 'radiusClientSecret' +# shortname = 'radiusClientShortname' +# nas_type = 'radiusClientType' +# virtual_server = 'radiusClientVirtualServer' +# require_message_authenticator = 'radiusClientRequireMa' + } + } + + # Load clients on startup +# read_clients = no + + # + # Modify user object on receiving Accounting-Request + # + + # Useful for recording things like the last time the user logged + # in, or the Acct-Session-ID for CoA/DM. + # + # LDAP modification items are in the format: + # <ldap attr> <op> <value> + # + # Where: + # <ldap attr>: The LDAP attribute to add modify or delete. + # <op>: One of the assignment operators: + # (:=, +=, -=, ++). + # Note: '=' is *not* supported. + # <value>: The value to add modify or delete. + # + # WARNING: If using the ':=' operator with a multi-valued LDAP + # attribute, all instances of the attribute will be removed and + # replaced with a single attribute. + accounting { + reference = "%{tolower:type.%{Acct-Status-Type}}" + + type { + start { + update { + description := "User %{User-Name} is online" + } + } + + interim-update { + update { + description := "Last seen at %S" + } + } + + stop { + update { + description := "Offline at %S" + } + } + } + } + + # + # Post-Auth can modify LDAP objects too + # + post-auth { + update { + description := "User %{User-Name} authenticated" + } + } + + # + # LDAP connection-specific options. + # + # These options set timeouts, keep-alives, etc. for the connections. + # + options { + # Control under which situations aliases are followed. + # May be one of 'never', 'searching', 'finding' or 'always' + # default: libldap's default which is usually 'never'. + # + # LDAP_OPT_DEREF is set to this value. +# dereference = 'always' + + # + # The following two configuration items control whether the + # server follows references returned by LDAP directory. + # They are mostly for Active Directory compatibility. + # If you set these to 'no', then searches will likely return + # 'operations error', instead of a useful result. + # + chase_referrals = yes + rebind = yes + + # Seconds to wait for LDAP query to finish. default: 20 + timeout = 10 + + # Seconds LDAP server has to process the query (server-side + # time limit). default: 20 + # + # LDAP_OPT_TIMELIMIT is set to this value. + timelimit = 3 + + # Seconds to wait for response of the server. (network + # failures) default: 10 + # + # LDAP_OPT_NETWORK_TIMEOUT is set to this value. + net_timeout = 1 + + # LDAP_OPT_X_KEEPALIVE_IDLE + idle = 60 + + # LDAP_OPT_X_KEEPALIVE_PROBES + probes = 3 + + # LDAP_OPT_X_KEEPALIVE_INTERVAL + interval = 3 + + # ldap_debug: debug flag for LDAP SDK + # (see OpenLDAP documentation). Set this to enable + # huge amounts of LDAP debugging on the screen. + # You should only use this if you are an LDAP expert. + # + # default: 0x0000 (no debugging messages) + # Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS) + ldap_debug = 0x0801 + } + + # + # This subsection configures the tls related items + # that control how FreeRADIUS connects to an LDAP + # server. It contains all of the 'tls_*' configuration + # entries used in older versions of FreeRADIUS. Those + # configuration entries can still be used, but we recommend + # using these. + # + tls { + # Set this to 'yes' to use TLS encrypted connections + # to the LDAP database by using the StartTLS extended + # operation. + # + # The StartTLS operation is supposed to be + # used with normal ldap connections instead of + # using ldaps (port 636) connections +# start_tls = yes + +# ca_file = ${certdir}/cacert.pem + +# ca_path = ${certdir} +# certificate_file = /path/to/radius.crt +# private_key_file = /path/to/radius.key +# random_file = ${certdir}/random + + # Certificate Verification requirements. Can be: + # 'never' (don't even bother trying) + # 'allow' (try, but don't fail if the certificate + # can't be verified) + # 'demand' (fail if the certificate doesn't verify.) + # + # The default is 'allow' +# require_cert = 'demand' + } + + + # As of version 3.0, the 'pool' section has replaced the + # following configuration items: + # + # ldap_connections_number + + # The connection pool is new for 3.0, and will be used in many + # modules, for all kinds of connection-related activity. + # + # When the server is not threaded, the connection pool + # limits are ignored, and only one connection is used. + pool { + # Number of connections to start + start = 5 + + # Minimum number of connections to keep open + min = 4 + + # Maximum number of connections + # + # If these connections are all in use and a new one + # is requested, the request will NOT get a connection. + # + # Setting 'max' to LESS than the number of threads means + # that some threads may starve, and you will see errors + # like 'No connections available and at max connection limit' + # + # Setting 'max' to MORE than the number of threads means + # that there are more connections than necessary. + max = 4 + + # Spare connections to be left idle + # + # NOTE: Idle connections WILL be closed if 'idle_timeout' + # is set. + spare = 3 + + # Number of uses before the connection is closed + # + # 0 means 'infinite' + uses = 0 + + # The lifetime (in seconds) of the connection + lifetime = 0 + + # Idle timeout (in seconds). A connection which is + # unused for this length of time will be closed. + idle_timeout = 60 + + # The number of seconds to wait after the server tries + # to open a connection, and fails. During this time, + # no new connections will be opened. + # + retry_delay = 1 + + # NOTE: All configuration settings are enforced. If a + # connection is closed because of 'idle_timeout', + # 'uses', or 'lifetime', then the total number of + # connections MAY fall below 'min'. When that + # happens, it will open a new connection. It will + # also log a WARNING message. + # + # The solution is to either lower the 'min' connections, + # or increase lifetime/idle_timeout. + } +} diff --git a/src/tests/modules/pap/all.mk b/src/tests/modules/pap/all.mk new file mode 100644 index 0000000..5c1de6f --- /dev/null +++ b/src/tests/modules/pap/all.mk @@ -0,0 +1,3 @@ +# +# Test the "pap" module +# diff --git a/src/tests/modules/pap/module.conf b/src/tests/modules/pap/module.conf new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/tests/modules/pap/module.conf @@ -0,0 +1 @@ + diff --git a/src/tests/modules/pap/pbkfd2_dig_big.attrs b/src/tests/modules/pap/pbkfd2_dig_big.attrs new file mode 100644 index 0000000..90fc451 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_dig_big.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_dig_big' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_dig_big.unlang b/src/tests/modules/pap/pbkfd2_dig_big.unlang new file mode 100644 index 0000000..449967f --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_dig_big.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_dig_big') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_dig_small.attrs b/src/tests/modules/pap/pbkfd2_dig_small.attrs new file mode 100644 index 0000000..dbc5bdd --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_dig_small.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_dig_small' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_dig_small.unlang b/src/tests/modules/pap/pbkfd2_dig_small.unlang new file mode 100644 index 0000000..37f08ee --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_dig_small.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_dig_small') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter0.attrs b/src/tests/modules/pap/pbkfd2_iter0.attrs new file mode 100644 index 0000000..871017e --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter0.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter0' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter0.unlang b/src/tests/modules/pap/pbkfd2_iter0.unlang new file mode 100644 index 0000000..ca362c9 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter0.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter0') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAP:CuNDJ9NimZoP5ljnPNCBUA==:f09zV7dReGg5SIv/EXY9tCL4XQRr5guhL0Q6UXSKI3c=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter1.attrs b/src/tests/modules/pap/pbkfd2_iter1.attrs new file mode 100644 index 0000000..e3d62cb --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter1.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter1' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter1.unlang b/src/tests/modules/pap/pbkfd2_iter1.unlang new file mode 100644 index 0000000..6758c9b --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter1.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter1') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:OErtptMl2hOxhQqvNw7sNw==:4KkrgL+3Q9j8KlHPivtApBKRZAjyWjtDWmZEz2UjNko=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter1000.attrs b/src/tests/modules/pap/pbkfd2_iter1000.attrs new file mode 100644 index 0000000..10a19c3 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter1000.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter1000' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter1000.unlang b/src/tests/modules/pap/pbkfd2_iter1000.unlang new file mode 100644 index 0000000..18fe680 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter1000.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter1000') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAD6A:yhmqoKrtPLY2KYK6cNjnfw==:Y6gkSZEo4TRtlsryHqnGYZhoe2qn5tJ4IUyyVHb/3WU=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter100000.attrs b/src/tests/modules/pap/pbkfd2_iter100000.attrs new file mode 100644 index 0000000..8da916c --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter100000.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter100000' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_iter100000.unlang b/src/tests/modules/pap/pbkfd2_iter100000.unlang new file mode 100644 index 0000000..a1253e6 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter100000.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter100000') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AA9CQA:fCfnJGMVC1QLtTOPiaSICA==:KCmjMpQ+lokMvyFTl4f4pPJNc0xJq4iHZPdtHa0OEXM=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter_big.attrs b/src/tests/modules/pap/pbkfd2_iter_big.attrs new file mode 100644 index 0000000..9f8dddb --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_big.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter_big' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter_big.unlang b/src/tests/modules/pap/pbkfd2_iter_big.unlang new file mode 100644 index 0000000..464d944 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_big.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter_big') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ==:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter_miss.attrs b/src/tests/modules/pap/pbkfd2_iter_miss.attrs new file mode 100644 index 0000000..983db26 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_miss.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter_miss' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter_miss.unlang b/src/tests/modules/pap/pbkfd2_iter_miss.unlang new file mode 100644 index 0000000..44d961a --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_miss.unlang @@ -0,0 +1,19 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter_miss') { + update control { + &PBKDF2-Password := 'HMACSHA2+256::E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI=' + } + pap.authorize + pap.authenticate { + invalid = 1 + } + if (invalid) { + test_pass + } else { + test_fail + } +} diff --git a/src/tests/modules/pap/pbkfd2_iter_small.attrs b/src/tests/modules/pap/pbkfd2_iter_small.attrs new file mode 100644 index 0000000..af8351b --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_small.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +User-Name = 'pbkdf2_iter_small' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept + diff --git a/src/tests/modules/pap/pbkfd2_iter_small.unlang b/src/tests/modules/pap/pbkfd2_iter_small.unlang new file mode 100644 index 0000000..7edee80 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_iter_small.unlang @@ -0,0 +1,19 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_iter_small') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAA:E+VXOSsE8RwyYGdygQoW9Q==:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI=' + } + pap.authorize + pap.authenticate { + invalid = 1 + } + if (invalid) { + test_pass + } else { + test_fail + } +} diff --git a/src/tests/modules/pap/pbkfd2_passlib.attrs b/src/tests/modules/pap/pbkfd2_passlib.attrs new file mode 100644 index 0000000..29738bb --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_passlib.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_passlib' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_passlib.unlang b/src/tests/modules/pap/pbkfd2_passlib.unlang new file mode 100644 index 0000000..6d0f27d --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_passlib.unlang @@ -0,0 +1,20 @@ +# Fixme - Base64 decode seems off for alt base64 +test_pass + +#if ("${feature.tls}" == no) { +# test_pass +# return +#} + +#if (&User-Name == 'pbkdf2_passlib') { +# update control { +# &PBKDF2-Password := '$pbkdf2-sha256$29000$9t7be09prfXee2/NOUeotQ$Y.RDnnq8vsezSZSKy1QNy6xhKPdoBIwc.0XDdRm9sJ8' +# } +# pap.authorize +# pap.authenticate +# if (!ok) { +# test_fail +# } else { +# test_pass +# } +#} diff --git a/src/tests/modules/pap/pbkfd2_salt0.attrs b/src/tests/modules/pap/pbkfd2_salt0.attrs new file mode 100644 index 0000000..7e6d209 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt0.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt0' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_salt0.unlang b/src/tests/modules/pap/pbkfd2_salt0.unlang new file mode 100644 index 0000000..173f768 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt0.unlang @@ -0,0 +1,19 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt0') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAnEA::4RJEKVFQ5nE8126aURI0cJO9tqy/DIAhq64piBEwshA=' + } + pap.authorize + pap.authenticate { + invalid = 1 + } + if (invalid) { + test_pass + } else { + test_fail + } +} diff --git a/src/tests/modules/pap/pbkfd2_salt1.attrs b/src/tests/modules/pap/pbkfd2_salt1.attrs new file mode 100644 index 0000000..20ff1fe --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt1.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt1' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_salt1.unlang b/src/tests/modules/pap/pbkfd2_salt1.unlang new file mode 100644 index 0000000..4aa0fce --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt1.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt1') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAnEA:qg==:KQzCdedgOZYFwx+mQp1TKA8VM4fwf02pqSdJEh2ekwM=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_salt1024.attrs b/src/tests/modules/pap/pbkfd2_salt1024.attrs new file mode 100644 index 0000000..30f2706 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt1024.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt1024' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_salt1024.unlang b/src/tests/modules/pap/pbkfd2_salt1024.unlang new file mode 100644 index 0000000..a4aab5e --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt1024.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt1024') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAnEA:/IUrkJKe+1kzJNBw7aAMbnQuSFZpjbCqPeKso3cbuSUzWinxngxjK8yyZLiWwF+WE/0Gplfx25zZEQNTdRTvjZZNefoxQBR8Hht0FpdU9YiEBaeErwVo63EDEu83+ycvB18uH0IXpJKGSSkIPRfGpHT3BkwJDGo5SqjRJadDsyQzkc/WJCMrrfJ0igaWMxb5eR5J8qfXIjBFepRrOOU6acZGtANW8qvDYLJwN+TMd9Jb1wDDY14eoAlKglTF21S3kewNMkDDyeP+oDYv29t1S/soFUnnB+Pb5IdR6pDy2VDGx4jFZMQGshSHWTYQFqgulavS/tGEF8TvzcorrJZKuksAjKdTSmfZ6j4aBY3U+oMSQ+2lO131pkNfNQuMsDfr72r9wUA2xRgUiL/J7CgKn7mamL2OCaksl0Rw2PGqqIaHvAYS6Q1EoIzsmLNrWBYYqTRLyCGZw6+hUOahYRon2lglGmnuWHPfowU+LgcaR5gF1QjvTXhXQ8I39mB3ePgdi+7TUn644Z1FB+JTqGJbue92x4V40Zyyy+Qdt52QsR49iYokbKAwQRiqfVJ7J8NzCY/kIQnqT9RE0NCxZoMBRzboZxVPchxdpmWGQ9dXP06PqIuDCFFiJlVQUfyPMgOAxIlVJ/9NAmj5MWFdWMrmlBNDx9ihEV1FdTv23iFZH5Ejg+x4D3qN5oOyCDL2i9lobzFXh5z4EDpbbogQaFkUzqKEaxRGPBrfYVOi6XXYujVUnxHJaRxbs2UqjpJNsXMg8f7P78aRvOKCIbW70CHWlt7nF0pA5+kFUQRLXKuq7bW+ivoXKeDW5o4FVP3+Pcr67+DOsUXuehALLj9Mu2ICWlMIV/AWcM2szaqk1bwSo7bAeG4RtDKmNjGA7gpnT+w2x+/qS1eWbc832Sumqc1IA8aY6HNVDPsJZf99To4BR+N0rCoQQ/KIZybI31mQagR3+FR9yNzqWzKIl+qf69RTc1CbUCkKVF8pxWZ0ocP+CAdoKadgpdF8evQIiGcUD73HiJ0RsDWo21y0tN0P5jfzWo3WMhCk9e2wl6o1JAfKw54uHzWJnNlGLBK1LXF+R2m+WvNGBgvUhh4PtYV9gPSudumFdk614oak/Aqcn6xi+YZqOMPkW4WYaiczhHyS7qAyefqKaQkRVYS0Af+79CSjlxZJq57HrD7/1E+d/i0gKmSAbPe80uGHs2a13V3VxztFMBi4xD7zj9Mq7+0goVPD4MNXcR651MZ7vxDRGbvPPmclddZe/nkTEn1YB/909b9mC5P/XzximZYW8gEhBReZouukADRTAjuH8zgSIv6/uyTURnmSVoOumVLBpL7veJIzDm4dZ38BWiasiBnzgMuG9A==:RUoCF5O11OgwLFMTqnKY/yRJy6DYh+yNq4xHZC7COGM=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_salt64.attrs b/src/tests/modules/pap/pbkfd2_salt64.attrs new file mode 100644 index 0000000..da036f3 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt64.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt64' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept
\ No newline at end of file diff --git a/src/tests/modules/pap/pbkfd2_salt64.unlang b/src/tests/modules/pap/pbkfd2_salt64.unlang new file mode 100644 index 0000000..754cdba --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt64.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt64') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAnEA:msGxE1XuC+wlgRr+H4+ioyxZuiN3KYLUSky2FINDTq7KJylKt4XnqloV+FuHGXUbOu1EWcsFp51u2z8wdXVnQQ==:rAV9BeEJH5kt9uZ6pJt0o5pYpN5LQRe4MAYyk2jvjpU=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_salt_big.attrs b/src/tests/modules/pap/pbkfd2_salt_big.attrs new file mode 100644 index 0000000..ccb593e --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt_big.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt_big' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_salt_big.unlang b/src/tests/modules/pap/pbkfd2_salt_big.unlang new file mode 100644 index 0000000..cfc96c5 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt_big.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt_big') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9QA==:pF23EcxNBhJLQ+9JRtd9wQ1Gz+k4i6YjeNZq+7DRBX8=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_salt_small.attrs b/src/tests/modules/pap/pbkfd2_salt_small.attrs new file mode 100644 index 0000000..1c2fa20 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt_small.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_salt_small' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_salt_small.unlang b/src/tests/modules/pap/pbkfd2_salt_small.unlang new file mode 100644 index 0000000..e46982f --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_salt_small.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_salt_small') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAAAQ:E+VXOSsE8RwyYGdygQoW9Q=:UivlvrwHML4VtZHMJLiT/xlH7oyoyvbXQceivptq9TI=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_sha1.attrs b/src/tests/modules/pap/pbkfd2_sha1.attrs new file mode 100644 index 0000000..ef7538f --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha1.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_sha1' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_sha1.unlang b/src/tests/modules/pap/pbkfd2_sha1.unlang new file mode 100644 index 0000000..5b79691 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha1.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_sha1') { + update control { + &PBKDF2-Password := 'HMACSHA1:AAAD6A:Xw1P133xrwk=:dtQBXQRiR/No5A8Ip3JFGF/qUC0=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_sha2_224.attrs b/src/tests/modules/pap/pbkfd2_sha2_224.attrs new file mode 100644 index 0000000..413f893 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_224.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_sha2_224' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_sha2_224.unlang b/src/tests/modules/pap/pbkfd2_sha2_224.unlang new file mode 100644 index 0000000..00fa626 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_224.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_sha2_224') { + update control { + &PBKDF2-Password := 'HMACSHA2+224:AAAnEA:UHScBrg/ZWOyBKqQdAh7bw==:tcFp6CDrkIYdhwa60g24U4ko+mBxzAiFxlpPnA==' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_sha2_256.attrs b/src/tests/modules/pap/pbkfd2_sha2_256.attrs new file mode 100644 index 0000000..3066682 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_256.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_sha2_256' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_sha2_256.unlang b/src/tests/modules/pap/pbkfd2_sha2_256.unlang new file mode 100644 index 0000000..5c4efce --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_256.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_sha2_256') { + update control { + &PBKDF2-Password := 'HMACSHA2+256:AAAnEA:a/8HbYW2HWsMthN27JI+Ew==:3nPlXYOlOuDCFOfethUomHxTXkG9JCivOdvh6FDNdGw=' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_sha2_384.attrs b/src/tests/modules/pap/pbkfd2_sha2_384.attrs new file mode 100644 index 0000000..9e43450 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_384.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_sha2_384' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_sha2_384.unlang b/src/tests/modules/pap/pbkfd2_sha2_384.unlang new file mode 100644 index 0000000..034bb83 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_384.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_sha2_384') { + update control { + &PBKDF2-Password := 'HMACSHA2+384:AAAnEA:pyHRsYLfNZdjszRcu6eHrA==:ktGfNmZ6PyD8FNEgPzFK1fypKERZ13pgvFl+PQdyKouaMXsXIiWPuTMXHqDUCWsx' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/pap/pbkfd2_sha2_512.attrs b/src/tests/modules/pap/pbkfd2_sha2_512.attrs new file mode 100644 index 0000000..b908615 --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_512.attrs @@ -0,0 +1,10 @@ +# +# Input packet +# +User-Name = 'pbkdf2_sha2_512' +User-Password = 'password' + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/pap/pbkfd2_sha2_512.unlang b/src/tests/modules/pap/pbkfd2_sha2_512.unlang new file mode 100644 index 0000000..95c1f3e --- /dev/null +++ b/src/tests/modules/pap/pbkfd2_sha2_512.unlang @@ -0,0 +1,17 @@ +if ("${feature.tls}" == no) { + test_pass + return +} + +if (&User-Name == 'pbkdf2_sha2_512') { + update control { + &PBKDF2-Password := 'HMACSHA2+512:AAAnEA:TG8Mb94NEmfPLaePwi5CFA==:SYSFeRf9jr4Uo5DB4NvNUEuc1gmEiLjTac5J4WgyKa7mO58KHKWop9xWmcFeuLtUN/iexLTNSgcubOugAyZcog==' + } + pap.authorize + pap.authenticate + if (!ok) { + test_fail + } else { + test_pass + } +} diff --git a/src/tests/modules/preprocess/all.mk b/src/tests/modules/preprocess/all.mk new file mode 100644 index 0000000..5cfad60 --- /dev/null +++ b/src/tests/modules/preprocess/all.mk @@ -0,0 +1,3 @@ +# +# Test the "preprocess" module +# diff --git a/src/tests/modules/preprocess/hints b/src/tests/modules/preprocess/hints new file mode 100644 index 0000000..14ceafc --- /dev/null +++ b/src/tests/modules/preprocess/hints @@ -0,0 +1,2 @@ +DEFAULT + Calling-Station-Id := "%{User-Name}@%{NAS-IP-Address}" diff --git a/src/tests/modules/preprocess/huntgroups b/src/tests/modules/preprocess/huntgroups new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/tests/modules/preprocess/huntgroups diff --git a/src/tests/modules/preprocess/module.conf b/src/tests/modules/preprocess/module.conf new file mode 100644 index 0000000..7c51fa6 --- /dev/null +++ b/src/tests/modules/preprocess/module.conf @@ -0,0 +1,4 @@ +preprocess { + hints = $ENV{MODULE_TEST_DIR}/hints + huntgroups = $ENV{MODULE_TEST_DIR}/huntgroups +} diff --git a/src/tests/modules/preprocess/xlat.attrs b/src/tests/modules/preprocess/xlat.attrs new file mode 100644 index 0000000..e7170d1 --- /dev/null +++ b/src/tests/modules/preprocess/xlat.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "bob" +User-Password = "bob" +NAS-IP-Address = 127.0.0.1 + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Filter-Id == 'success' diff --git a/src/tests/modules/preprocess/xlat.unlang b/src/tests/modules/preprocess/xlat.unlang new file mode 100644 index 0000000..da53982 --- /dev/null +++ b/src/tests/modules/preprocess/xlat.unlang @@ -0,0 +1,14 @@ +# +# Run the preprocess module +# +preprocess + +if (Calling-Station-Id == "bob@127.0.0.1") { + update reply { + Filter-Id := "success" + } +} + +update control { + Cleartext-Password := "%{User-Name}" +} diff --git a/src/tests/modules/radiusd.conf b/src/tests/modules/radiusd.conf new file mode 100644 index 0000000..220f341 --- /dev/null +++ b/src/tests/modules/radiusd.conf @@ -0,0 +1,103 @@ +# +# Minimal radiusd.conf for testing modules +# + +raddb = raddb + +modconfdir = ${raddb}/mods-config + +correct_escapes = true + +# Only for testing! +# Setting this on a production system is a BAD IDEA. +security { + allow_vulnerable_openssl = yes +} + +modules { + $INCLUDE ${raddb}/mods-enabled/always + + $INCLUDE ${raddb}/mods-enabled/pap + + $INCLUDE ${raddb}/mods-enabled/expr + + $INCLUDE $ENV{MODULE_TEST_DIR}/module.conf +} + +server default { + authorize { + # + # Include the test file specified by the + # KEYWORD environment variable. + # + $INCLUDE $ENV{MODULE_TEST_UNLANG} + + pap + } + + authenticate { + pap + } +} + +policy { + test_pass { + update control { + Tmp-String-8 := "%{expr:%{%{control:Tmp-String-8}:-0} + 1}" + Auth-Type := Accept + } + } + + test_fail { + update reply { + Reply-Message := "fail %{%{control:Tmp-String-8}:-0}" + } + reject + } + + # + # Outputs the contents of the control list in debugging (-X) mode + # + debug_control { + if("%{debug_attr:control:}" == '') { + noop + } + } + + # + # Outputs the contents of the request list in debugging (-X) mode + # + debug_request { + if("%{debug_attr:request:}" == '') { + noop + } + } + + # + # Outputs the contents of the reply list in debugging (-X) mode + # + debug_reply { + if("%{debug_attr:reply:}" == '') { + noop + } + } + + # + # Outputs the contents of the session state list in debugging (-X) mode + # + debug_session_state { + if("%{debug_attr:session-state:}" == '') { + noop + } + } + + # + # Outputs the contents of the main lists in debugging (-X) mode + # + debug_all { + debug_control + debug_request + debug_reply + debug_session_state + } +} diff --git a/src/tests/modules/sql/.gitignore b/src/tests/modules/sql/.gitignore new file mode 100644 index 0000000..405551a --- /dev/null +++ b/src/tests/modules/sql/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql/acct_0_start.attrs b/src/tests/modules/sql/acct_0_start.attrs new file mode 100644 index 0000000..01257ce --- /dev/null +++ b/src/tests/modules/sql/acct_0_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user0@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000000' +Acct-Unique-Session-Id = '00000000' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql/acct_0_start.unlang b/src/tests/modules/sql/acct_0_start.unlang new file mode 100644 index 0000000..64921b1 --- /dev/null +++ b/src/tests/modules/sql/acct_0_start.unlang @@ -0,0 +1,40 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql:DELETE FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000000'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql/acct_1_update.attrs b/src/tests/modules/sql/acct_1_update.attrs new file mode 100644 index 0000000..28db958 --- /dev/null +++ b/src/tests/modules/sql/acct_1_update.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user1@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000001' +Acct-Unique-Session-Id = '00000001' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql/acct_1_update.unlang b/src/tests/modules/sql/acct_1_update.unlang new file mode 100644 index 0000000..e566a4a --- /dev/null +++ b/src/tests/modules/sql/acct_1_update.unlang @@ -0,0 +1,30 @@ +# +# PRE: acct_0_start +# +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000001'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql/acct_2_stop.attrs b/src/tests/modules/sql/acct_2_stop.attrs new file mode 100644 index 0000000..e932f84 --- /dev/null +++ b/src/tests/modules/sql/acct_2_stop.attrs @@ -0,0 +1,38 @@ +# +# Input packet +# +User-Name = 'user2@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Stop +Acct-Terminate-Cause = User-Request +Acct-Delay-Time = 1 +Acct-Input-Octets = 15 +Acct-Output-Octets = 15 +Acct-Session-Id = '00000002' +Acct-Unique-Session-Id = '00000002' +Acct-Authentic = RADIUS +Acct-Session-Time = 120 +Acct-Input-Packets = 15 +Acct-Output-Packets = 15 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql/acct_2_stop.unlang b/src/tests/modules/sql/acct_2_stop.unlang new file mode 100644 index 0000000..3386c71 --- /dev/null +++ b/src/tests/modules/sql/acct_2_stop.unlang @@ -0,0 +1,40 @@ +# +# PRE: acct_1_update +# +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 120)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-String-0 := "%{sql:SELECT AcctTerminateCause FROM radacct WHERE AcctSessionId = '00000002'}" +} +if (!&Tmp-String-0 || (&Tmp-String-0 != 'User-Request')) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql/acct_start_conflict.attrs b/src/tests/modules/sql/acct_start_conflict.attrs new file mode 100644 index 0000000..2bcade3 --- /dev/null +++ b/src/tests/modules/sql/acct_start_conflict.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user3@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Start +Acct-Delay-Time = 1 +Acct-Input-Octets = 0 +Acct-Output-Octets = 0 +Acct-Session-Id = '00000003' +Acct-Unique-Session-Id = '00000003' +Acct-Authentic = RADIUS +Acct-Session-Time = 0 +Acct-Input-Packets = 0 +Acct-Output-Packets = 0 +Acct-Input-Gigawords = 0 +Acct-Output-Gigawords = 0 +Event-Timestamp = 'Feb 1 2015 08:28:58 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql/acct_start_conflict.unlang b/src/tests/modules/sql/acct_start_conflict.unlang new file mode 100644 index 0000000..65e69e0 --- /dev/null +++ b/src/tests/modules/sql/acct_start_conflict.unlang @@ -0,0 +1,76 @@ +# +# Check that conflicting unique IDs triggers failover to alternative query +# + +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql:DELETE FROM radacct WHERE AcctSessionId = '00000003'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +# +# Insert the Accounting-Request start +# +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +# +# Check the database has at least one row +# +update { + Tmp-Integer-0 := "%{sql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000003'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +# +# Check acctsessiontime matches the value in the request +# +update { + Tmp-Integer-0 := "%{sql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000003'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 0)) { + test_fail +} +else { + test_pass +} + +# +# Change acctsessiontime and verify it's updated +# +update request { + Connect-Info = 'updated' +} +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} +update { + Tmp-String-0 := "%{sql:SELECT connectinfo_start FROM radacct WHERE AcctSessionId = '00000003'}" +} +if (!&Tmp-Integer-0 || (&Tmp-String-0 != 'updated')) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql/acct_update_no_start.attrs b/src/tests/modules/sql/acct_update_no_start.attrs new file mode 100644 index 0000000..6f3049e --- /dev/null +++ b/src/tests/modules/sql/acct_update_no_start.attrs @@ -0,0 +1,37 @@ +# +# Input packet +# +User-Name = 'user4@example.org' +NAS-Port = 17826193 +NAS-IP-Address = 192.0.2.10 +Framed-IP-Address = 198.51.100.59 +NAS-Identifier = 'nas.example.org' +Acct-Status-Type = Interim-Update +Acct-Delay-Time = 1 +Acct-Input-Octets = 10 +Acct-Output-Octets = 10 +Acct-Session-Id = '00000004' +Acct-Unique-Session-Id = '00000004' +Acct-Authentic = RADIUS +Acct-Session-Time = 30 +Acct-Input-Packets = 10 +Acct-Output-Packets = 10 +Acct-Input-Gigawords = 1 +Acct-Output-Gigawords = 1 +Event-Timestamp = 'Feb 1 2015 08:28:28 WIB' +NAS-Port-Type = Ethernet +NAS-Port-Id = 'port 001' +Service-Type = Framed-User +Framed-Protocol = PPP +Acct-Link-Count = 0 +Idle-Timeout = 0 +Session-Timeout = 604800 +Access-Loop-Encapsulation = 0x000000 +Proxy-State = 0x323531 + +# +# Expected answer +# +# There's not an Accounting-Failed packet type in RADIUS... +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/sql/acct_update_no_start.unlang b/src/tests/modules/sql/acct_update_no_start.unlang new file mode 100644 index 0000000..3875b2d --- /dev/null +++ b/src/tests/modules/sql/acct_update_no_start.unlang @@ -0,0 +1,40 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql:DELETE FROM radacct WHERE AcctSessionId = '00000004'}" +} +if (!&Tmp-String-0) { + test_fail +} +else { + test_pass +} + +sql.accounting +if (ok) { + test_pass +} +else { + test_fail +} + +update { + Tmp-Integer-0 := "%{sql:SELECT count(*) FROM radacct WHERE AcctSessionId = '00000004'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 1)) { + test_fail +} +else { + test_pass +} + +update { + Tmp-Integer-0 := "%{sql:SELECT acctsessiontime FROM radacct WHERE AcctSessionId = '00000004'}" +} +if (!&Tmp-Integer-0 || (&Tmp-Integer-0 != 30)) { + test_fail +} +else { + test_pass +} diff --git a/src/tests/modules/sql/auth.attrs b/src/tests/modules/sql/auth.attrs new file mode 100644 index 0000000..e7d1498 --- /dev/null +++ b/src/tests/modules/sql/auth.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "user_auth" +User-Password = "password" +NAS-IP-Address = "1.2.3.4" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept +Idle-Timeout == 3600 diff --git a/src/tests/modules/sql/auth.unlang b/src/tests/modules/sql/auth.unlang new file mode 100644 index 0000000..0d76538 --- /dev/null +++ b/src/tests/modules/sql/auth.unlang @@ -0,0 +1,39 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql:DELETE FROM radcheck WHERE username = 'user_auth'}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('user_auth', 'NAS-IP-Address', '==', '1.2.3.4')}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('user_auth', 'Cleartext-Password', ':=', 'password')}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:DELETE FROM radreply WHERE username = 'user_auth'}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radreply (username, attribute, op, value) VALUES ('user_auth', 'Idle-Timeout', ':=', '3600')}" +} +if (!&Tmp-String-0) { + test_fail +} + +sql diff --git a/src/tests/modules/sql/reject.attrs b/src/tests/modules/sql/reject.attrs new file mode 100644 index 0000000..cb0b9a2 --- /dev/null +++ b/src/tests/modules/sql/reject.attrs @@ -0,0 +1,12 @@ +# +# Input packet +# +User-Name = "user_reject" +User-Password = "password" +NAS-IP-Address = "1.2.3.4" + +# +# Expected answer +# +Response-Packet-Type == Access-Reject +Reply-Message == "Authentication failed" diff --git a/src/tests/modules/sql/reject.unlang b/src/tests/modules/sql/reject.unlang new file mode 100644 index 0000000..b4afb09 --- /dev/null +++ b/src/tests/modules/sql/reject.unlang @@ -0,0 +1,39 @@ +# +# Clear out old data +# +update { + Tmp-String-0 := "%{sql:DELETE FROM radcheck WHERE username = 'user_reject'}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('user_reject', 'NAS-IP-Address', '==', '1.2.3.4')}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radcheck (username, attribute, op, value) VALUES ('user_reject', 'Cleartext-Password', ':=', 'wrong-password')}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:DELETE FROM radreply WHERE username = 'user_reject'}" +} +if (!&Tmp-String-0) { + test_fail +} + +update { + Tmp-String-0 := "%{sql:INSERT INTO radreply (username, attribute, op, value) VALUES ('user_reject', 'Reply-Message', ':=', 'Authentication failed')}" +} +if (!&Tmp-String-0) { + test_fail +} + +sql diff --git a/src/tests/modules/sql_mysql/.gitignore b/src/tests/modules/sql_mysql/.gitignore new file mode 100644 index 0000000..405551a --- /dev/null +++ b/src/tests/modules/sql_mysql/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql_mysql/acct_0_start.attrs b/src/tests/modules/sql_mysql/acct_0_start.attrs new file mode 120000 index 0000000..24e17ae --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_0_start.attrs @@ -0,0 +1 @@ +../sql/acct_0_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_0_start.unlang b/src/tests/modules/sql_mysql/acct_0_start.unlang new file mode 120000 index 0000000..3fe3e99 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_0_start.unlang @@ -0,0 +1 @@ +../sql/acct_0_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_1_update.attrs b/src/tests/modules/sql_mysql/acct_1_update.attrs new file mode 120000 index 0000000..1ab772d --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_1_update.attrs @@ -0,0 +1 @@ +../sql/acct_1_update.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_1_update.unlang b/src/tests/modules/sql_mysql/acct_1_update.unlang new file mode 120000 index 0000000..b69ff9b --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_1_update.unlang @@ -0,0 +1 @@ +../sql/acct_1_update.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_2_stop.attrs b/src/tests/modules/sql_mysql/acct_2_stop.attrs new file mode 120000 index 0000000..ea73931 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_2_stop.attrs @@ -0,0 +1 @@ +../sql/acct_2_stop.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_2_stop.unlang b/src/tests/modules/sql_mysql/acct_2_stop.unlang new file mode 120000 index 0000000..ea0be56 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_2_stop.unlang @@ -0,0 +1 @@ +../sql/acct_2_stop.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_start_conflict.attrs b/src/tests/modules/sql_mysql/acct_start_conflict.attrs new file mode 120000 index 0000000..117a505 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_start_conflict.attrs @@ -0,0 +1 @@ +../sql/acct_start_conflict.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_start_conflict.unlang b/src/tests/modules/sql_mysql/acct_start_conflict.unlang new file mode 120000 index 0000000..da35798 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_start_conflict.unlang @@ -0,0 +1 @@ +../sql/acct_start_conflict.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_update_no_start.attrs b/src/tests/modules/sql_mysql/acct_update_no_start.attrs new file mode 120000 index 0000000..328867f --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_update_no_start.attrs @@ -0,0 +1 @@ +../sql/acct_update_no_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/acct_update_no_start.unlang b/src/tests/modules/sql_mysql/acct_update_no_start.unlang new file mode 120000 index 0000000..6837977 --- /dev/null +++ b/src/tests/modules/sql_mysql/acct_update_no_start.unlang @@ -0,0 +1 @@ +../sql/acct_update_no_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/all.mk b/src/tests/modules/sql_mysql/all.mk new file mode 100644 index 0000000..337528b --- /dev/null +++ b/src/tests/modules/sql_mysql/all.mk @@ -0,0 +1,6 @@ +# +# Test the mysql module +# + +# Don't test sql_mysql if TEST_SERVER ENV is not set +sql_mysql_require_test_server := 1 diff --git a/src/tests/modules/sql_mysql/auth.attrs b/src/tests/modules/sql_mysql/auth.attrs new file mode 120000 index 0000000..6b30b6b --- /dev/null +++ b/src/tests/modules/sql_mysql/auth.attrs @@ -0,0 +1 @@ +../sql/auth.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/auth.unlang b/src/tests/modules/sql_mysql/auth.unlang new file mode 120000 index 0000000..3ccd80e --- /dev/null +++ b/src/tests/modules/sql_mysql/auth.unlang @@ -0,0 +1 @@ +../sql/auth.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/module.conf b/src/tests/modules/sql_mysql/module.conf new file mode 100644 index 0000000..e3aa02d --- /dev/null +++ b/src/tests/modules/sql_mysql/module.conf @@ -0,0 +1,53 @@ +sql { + driver = "rlm_sql_mysql" + dialect = "mysql" + + # Connection info: + # + server = $ENV{SQL_MYSQL_TEST_SERVER} + port = 3306 + login = "radius" + password = "radpass" + + # Database table configuration for everything except Oracle + radius_db = "radius" + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 3 + uses = 2 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # The group attribute specific to this instance of rlm_sql + group_attribute = "SQL-Group" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/src/tests/modules/sql_mysql/reject.attrs b/src/tests/modules/sql_mysql/reject.attrs new file mode 120000 index 0000000..71a187f --- /dev/null +++ b/src/tests/modules/sql_mysql/reject.attrs @@ -0,0 +1 @@ +../sql/reject.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_mysql/reject.unlang b/src/tests/modules/sql_mysql/reject.unlang new file mode 120000 index 0000000..379839f --- /dev/null +++ b/src/tests/modules/sql_mysql/reject.unlang @@ -0,0 +1 @@ +../sql/reject.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/.gitignore b/src/tests/modules/sql_postgresql/.gitignore new file mode 100644 index 0000000..405551a --- /dev/null +++ b/src/tests/modules/sql_postgresql/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql_postgresql/acct_0_start.attrs b/src/tests/modules/sql_postgresql/acct_0_start.attrs new file mode 120000 index 0000000..24e17ae --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_0_start.attrs @@ -0,0 +1 @@ +../sql/acct_0_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_0_start.unlang b/src/tests/modules/sql_postgresql/acct_0_start.unlang new file mode 120000 index 0000000..3fe3e99 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_0_start.unlang @@ -0,0 +1 @@ +../sql/acct_0_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_1_update.attrs b/src/tests/modules/sql_postgresql/acct_1_update.attrs new file mode 120000 index 0000000..1ab772d --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_1_update.attrs @@ -0,0 +1 @@ +../sql/acct_1_update.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_1_update.unlang b/src/tests/modules/sql_postgresql/acct_1_update.unlang new file mode 120000 index 0000000..b69ff9b --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_1_update.unlang @@ -0,0 +1 @@ +../sql/acct_1_update.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_2_stop.attrs b/src/tests/modules/sql_postgresql/acct_2_stop.attrs new file mode 120000 index 0000000..ea73931 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_2_stop.attrs @@ -0,0 +1 @@ +../sql/acct_2_stop.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_2_stop.unlang b/src/tests/modules/sql_postgresql/acct_2_stop.unlang new file mode 120000 index 0000000..ea0be56 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_2_stop.unlang @@ -0,0 +1 @@ +../sql/acct_2_stop.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_start_conflict.attrs b/src/tests/modules/sql_postgresql/acct_start_conflict.attrs new file mode 120000 index 0000000..117a505 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_start_conflict.attrs @@ -0,0 +1 @@ +../sql/acct_start_conflict.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_start_conflict.unlang b/src/tests/modules/sql_postgresql/acct_start_conflict.unlang new file mode 120000 index 0000000..da35798 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_start_conflict.unlang @@ -0,0 +1 @@ +../sql/acct_start_conflict.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_update_no_start.attrs b/src/tests/modules/sql_postgresql/acct_update_no_start.attrs new file mode 120000 index 0000000..328867f --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_update_no_start.attrs @@ -0,0 +1 @@ +../sql/acct_update_no_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/acct_update_no_start.unlang b/src/tests/modules/sql_postgresql/acct_update_no_start.unlang new file mode 120000 index 0000000..6837977 --- /dev/null +++ b/src/tests/modules/sql_postgresql/acct_update_no_start.unlang @@ -0,0 +1 @@ +../sql/acct_update_no_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/all.mk b/src/tests/modules/sql_postgresql/all.mk new file mode 100644 index 0000000..efd20d9 --- /dev/null +++ b/src/tests/modules/sql_postgresql/all.mk @@ -0,0 +1,6 @@ +# +# Test the postgresql module +# + +# Don't test sql_postgresql if TEST_SERVER ENV is not set +sql_postgresql_require_test_server := 1 diff --git a/src/tests/modules/sql_postgresql/auth.attrs b/src/tests/modules/sql_postgresql/auth.attrs new file mode 120000 index 0000000..6b30b6b --- /dev/null +++ b/src/tests/modules/sql_postgresql/auth.attrs @@ -0,0 +1 @@ +../sql/auth.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/auth.unlang b/src/tests/modules/sql_postgresql/auth.unlang new file mode 120000 index 0000000..3ccd80e --- /dev/null +++ b/src/tests/modules/sql_postgresql/auth.unlang @@ -0,0 +1 @@ +../sql/auth.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/module.conf b/src/tests/modules/sql_postgresql/module.conf new file mode 100644 index 0000000..ee9a8a9 --- /dev/null +++ b/src/tests/modules/sql_postgresql/module.conf @@ -0,0 +1,52 @@ +sql { + driver = "rlm_sql_postgresql" + dialect = "postgresql" + + # Connection info: + # + server = $ENV{SQL_POSTGRESQL_TEST_SERVER} + port = 5432 + login = "radius" + password = "radpass" + + # Database table configuration for everything except Oracle + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 3 + uses = 2 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # The group attribute specific to this instance of rlm_sql + group_attribute = "SQL-Group" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/src/tests/modules/sql_postgresql/reject.attrs b/src/tests/modules/sql_postgresql/reject.attrs new file mode 120000 index 0000000..71a187f --- /dev/null +++ b/src/tests/modules/sql_postgresql/reject.attrs @@ -0,0 +1 @@ +../sql/reject.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_postgresql/reject.unlang b/src/tests/modules/sql_postgresql/reject.unlang new file mode 120000 index 0000000..379839f --- /dev/null +++ b/src/tests/modules/sql_postgresql/reject.unlang @@ -0,0 +1 @@ +../sql/reject.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/.gitignore b/src/tests/modules/sql_sqlite/.gitignore new file mode 100644 index 0000000..405551a --- /dev/null +++ b/src/tests/modules/sql_sqlite/.gitignore @@ -0,0 +1 @@ +rlm_sql_sqlite.db diff --git a/src/tests/modules/sql_sqlite/acct_0_start.attrs b/src/tests/modules/sql_sqlite/acct_0_start.attrs new file mode 120000 index 0000000..24e17ae --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_0_start.attrs @@ -0,0 +1 @@ +../sql/acct_0_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_0_start.unlang b/src/tests/modules/sql_sqlite/acct_0_start.unlang new file mode 120000 index 0000000..3fe3e99 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_0_start.unlang @@ -0,0 +1 @@ +../sql/acct_0_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_1_update.attrs b/src/tests/modules/sql_sqlite/acct_1_update.attrs new file mode 120000 index 0000000..1ab772d --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_1_update.attrs @@ -0,0 +1 @@ +../sql/acct_1_update.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_1_update.unlang b/src/tests/modules/sql_sqlite/acct_1_update.unlang new file mode 120000 index 0000000..b69ff9b --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_1_update.unlang @@ -0,0 +1 @@ +../sql/acct_1_update.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_2_stop.attrs b/src/tests/modules/sql_sqlite/acct_2_stop.attrs new file mode 120000 index 0000000..ea73931 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_2_stop.attrs @@ -0,0 +1 @@ +../sql/acct_2_stop.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_2_stop.unlang b/src/tests/modules/sql_sqlite/acct_2_stop.unlang new file mode 120000 index 0000000..ea0be56 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_2_stop.unlang @@ -0,0 +1 @@ +../sql/acct_2_stop.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_start_conflict.attrs b/src/tests/modules/sql_sqlite/acct_start_conflict.attrs new file mode 120000 index 0000000..117a505 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_start_conflict.attrs @@ -0,0 +1 @@ +../sql/acct_start_conflict.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_start_conflict.unlang b/src/tests/modules/sql_sqlite/acct_start_conflict.unlang new file mode 120000 index 0000000..da35798 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_start_conflict.unlang @@ -0,0 +1 @@ +../sql/acct_start_conflict.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_update_no_start.attrs b/src/tests/modules/sql_sqlite/acct_update_no_start.attrs new file mode 120000 index 0000000..328867f --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_update_no_start.attrs @@ -0,0 +1 @@ +../sql/acct_update_no_start.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/acct_update_no_start.unlang b/src/tests/modules/sql_sqlite/acct_update_no_start.unlang new file mode 120000 index 0000000..6837977 --- /dev/null +++ b/src/tests/modules/sql_sqlite/acct_update_no_start.unlang @@ -0,0 +1 @@ +../sql/acct_update_no_start.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/all.mk b/src/tests/modules/sql_sqlite/all.mk new file mode 100644 index 0000000..a7907f1 --- /dev/null +++ b/src/tests/modules/sql_sqlite/all.mk @@ -0,0 +1,3 @@ +# +# Test the sqlite module +# diff --git a/src/tests/modules/sql_sqlite/auth.attrs b/src/tests/modules/sql_sqlite/auth.attrs new file mode 120000 index 0000000..6b30b6b --- /dev/null +++ b/src/tests/modules/sql_sqlite/auth.attrs @@ -0,0 +1 @@ +../sql/auth.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/auth.unlang b/src/tests/modules/sql_sqlite/auth.unlang new file mode 120000 index 0000000..3ccd80e --- /dev/null +++ b/src/tests/modules/sql_sqlite/auth.unlang @@ -0,0 +1 @@ +../sql/auth.unlang
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/module.conf b/src/tests/modules/sql_sqlite/module.conf new file mode 100644 index 0000000..1d8ac74 --- /dev/null +++ b/src/tests/modules/sql_sqlite/module.conf @@ -0,0 +1,52 @@ +sql { + driver = "rlm_sql_sqlite" + dialect = "sqlite" + sqlite { + # Path to the sqlite database + filename = "$ENV{MODULE_TEST_DIR}/sql_sqlite/rlm_sql_sqlite.db" + + # If the file above does not exist and bootstrap is set + # a new database file will be created, and the SQL statements + # contained within the file will be executed. + bootstrap = "${modconfdir}/${..:name}/main/${..dialect}/schema.sql" + } + radius_db = "radius" + + acct_table1 = "radacct" + acct_table2 = "radacct" + postauth_table = "radpostauth" + authcheck_table = "radcheck" + groupcheck_table = "radgroupcheck" + authreply_table = "radreply" + groupreply_table = "radgroupreply" + usergroup_table = "radusergroup" + read_groups = yes + read_profiles = yes + + # Remove stale session if checkrad does not see a double login + delete_stale_sessions = yes + + pool { + start = 1 + min = 0 + max = 1 + spare = 3 + uses = 2 + lifetime = 1 + idle_timeout = 60 + retry_delay = 1 + } + + # Set to 'yes' to read radius clients from the database ('nas' table) + # Clients will ONLY be read on server startup. +# read_clients = yes + + # Table to keep radius client info + client_table = "nas" + + # The group attribute specific to this instance of rlm_sql + group_attribute = "SQL-Group" + + # Read database-specific queries + $INCLUDE ${modconfdir}/${.:name}/main/${dialect}/queries.conf +} diff --git a/src/tests/modules/sql_sqlite/reject.attrs b/src/tests/modules/sql_sqlite/reject.attrs new file mode 120000 index 0000000..71a187f --- /dev/null +++ b/src/tests/modules/sql_sqlite/reject.attrs @@ -0,0 +1 @@ +../sql/reject.attrs
\ No newline at end of file diff --git a/src/tests/modules/sql_sqlite/reject.unlang b/src/tests/modules/sql_sqlite/reject.unlang new file mode 120000 index 0000000..379839f --- /dev/null +++ b/src/tests/modules/sql_sqlite/reject.unlang @@ -0,0 +1 @@ +../sql/reject.unlang
\ No newline at end of file diff --git a/src/tests/modules/test.mk b/src/tests/modules/test.mk new file mode 100644 index 0000000..b217ff7 --- /dev/null +++ b/src/tests/modules/test.mk @@ -0,0 +1,165 @@ +# +# Add the module tests to the overall dependencies +# + +TESTS.MODULES_FILES := + +# If module requires test server, make sure TEST_SERVER of <MODULE>_TEST_SERVER variables are defined +# If TEST_SERVER is defined, define <MODULE>_TEST_SERVER for all modules that have CHECK_MODULE_TEST_CAN_BE_RUN +define CHECK_MODULE_TEST_CAN_BE_RUN + ifndef ${1}_require_test_server + tests.modules: ${1}.test + else + ifdef TEST_SERVER + tests.modules: ${1}.test + export $(shell echo ${1} | tr a-z A-Z)_TEST_SERVER := $(TEST_SERVER) + endif + ifdef $(shell echo ${1} | tr a-z A-Z)_TEST_SERVER + tests.modules: ${1}.test + endif + endif +endef +$(foreach x,$(TEST_BUILT) $(TEST_SUBBUILT),$(eval $(call CHECK_MODULE_TEST_CAN_BE_RUN,$x))) + +###################################################################### +# +# And now more makefile magic to automatically run the tests +# for each module. +# + +define DEFAULT_ATTRS +ifeq "$(wildcard ${1}.attrs)" +${1}.attrs +else +src/tests/modules/default-input.attrs +endif +endef + +# +# Files in the output dir depend on the unit tests +# +# src/tests/$(MODULE_DIR)/FOO.unlang unlang for the test +# src/tests/$(MODULE_DIR)/FOO.attrs input RADIUS and output filter +# build/tests/$(MODULE_DIR)/FOO.out updated if the test succeeds +# build/tests/$(MODULE_DIR)/FOO.log debug output for the test +# +# If the test fails, then look for ERROR in the input. No error +# means it's unexpected, so we die. +# +# Otherwise, check the log file for a parse error which matches the +# ERROR line in the input. +# +$(BUILD_DIR)/tests/modules/%: src/tests/modules/%.unlang $(BUILD_DIR)/tests/modules/%.attrs $(TESTBINDIR)/unittest | build.raddb + @mkdir -p $(dir $@) + @echo MODULE-TEST $(lastword $(subst /, ,$(dir $@))) $(basename $(notdir $@)) + @if ! MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xxx > $@.log 2>&1; then \ + if ! grep ERROR $< 2>&1 > /dev/null; then \ + cat $@.log; \ + echo "# $@.log"; \ + echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ + exit 1; \ + fi; \ + FOUND=$$(grep ^$< $@.log | head -1 | sed 's/:.*//;s/.*\[//;s/\].*//'); \ + EXPECTED=$$(grep -n ERROR $< | sed 's/:.*//'); \ + if [ "$$EXPECTED" != "$$FOUND" ]; then \ + cat $@.log; \ + echo "# $@.log"; \ + echo MODULE_TEST_DIR=$(dir $<) MODULE_TEST_UNLANG=$< $(TESTBIN)/unittest -D share -d src/tests/modules/ -i $@.attrs -f $@.attrs -xx; \ + exit 1; \ + fi \ + fi + @touch $@ + +# +# Sometimes we have a default input. So use that. Otherwise, use +# the input specific to the test. +# +MODULE_UNLANG := $(wildcard src/tests/modules/*/*.unlang src/tests/modules/*/*/*.unlang) +MODULE_ATTRS_REQUIRES := $(patsubst %.unlang,%.attrs,$(MODULE_UNLANG)) +MODULE_ATTRS_EXISTS := $(wildcard src/tests/modules/*/*.attrs src/tests/modules/*/*/*.attrs) +MODULE_ATTRS_NEEDS := $(filter-out $(MODULE_ATTRS_EXISTS),$(MODULE_ATTRS_REQUIRES)) + +MODULE_CONF_REQUIRES := $(patsubst %.unlang,%.conf,$(MODULE_UNLANG)) +MODULE_CONF_EXISTS := $(wildcard src/tests/modules/*/*.conf src/tests/modules/*/*/*.attrs) +MODULE_CONF_NEEDS := $(filter-out $(MODULE_CONF_EXISTS),$(MODULE_CONF_REQUIRES)) + +# +# The complete list of tests which are to be run +# +MODULE_TESTS := $(patsubst src/tests/modules/%/all.mk,%,$(wildcard src/tests/modules/*/all.mk)) + + +# +# Target-specific rules +# +define MODULE_COPY_FILE +$(BUILD_DIR)/${1}: src/${1} + @mkdir -p $$(@D) + @cp $$< $$@ + +endef + +# +# Default rules +# +define MODULE_COPY_ATTR +$(BUILD_DIR)/${1}: src/tests/modules/default-input.attrs + @mkdir -p $$(@D) + @cp $$< $$@ +endef + +# +# FIXME: get this working +# +define MODULE_COPY_CONF +$(BUILD_DIR)/${1}: src/tests/modules/${2}/module.conf + @mkdir -p $$(@D) + @cp $$< $$@ +endef + +define MODULE_FILE_TARGET +$(BUILD_DIR)/${1}: src/${1}.unlang $(BUILD_DIR)/${1}.attrs + +endef + +define MODULE_TEST_TARGET +${1}.test: $(patsubst %.unlang,%,$(subst src,$(BUILD_DIR),$(filter src/tests/modules/${1}/%,$(MODULE_UNLANG)))) + +TESTS.MODULES_FILES += $(patsubst %.unlang,%,$(subst src,$(BUILD_DIR),$(filter src/tests/modules/${1}/%,$(MODULE_UNLANG)))) +endef + +# +# Create the rules from the list of input files +# +$(foreach x,$(MODULE_ATTRS_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) +$(foreach x,$(MODULE_CONF_EXISTS),$(eval $(call MODULE_COPY_FILE,$(subst src/,,$x)))) + +$(foreach x,$(MODULE_ATTRS_NEEDS),$(eval $(call MODULE_COPY_ATTR,$(subst src/,,$x)))) +# FIXME: copy src/tests/modules/*/module.conf to the right place, too + +$(foreach x,$(MODULE_UNLANG),$(eval $(call MODULE_FILE_TARGET,$(patsubst %.unlang,%,$(subst src/,,$x))))) +$(foreach x,$(MODULE_TESTS),$(eval $(call MODULE_TEST_TARGET,$x))) + +$(TESTS.MODULES_FILES): $(TESTS.AUTH_FILES) + +.PHONY: clean.modules.test +clean.modules.test: + @rm -rf $(BUILD_DIR)/tests/modules/ + +# +# For each file, look for precursor test. +# Ensure that each test depends on its precursors. +# +-include $(BUILD_DIR)/tests/modules/depends.mk + +$(BUILD_DIR)/tests/modules/depends.mk: $(MODULE_UNLANG) | $(BUILD_DIR)/tests/modules + @rm -f $@ + @for x in $^; do \ + y=`grep PRE $$x | awk '{ print $$3 }'`; \ + if [ "$$y" != "" ]; then \ + z=`echo $$x | sed 's,src/,$(BUILD_DIR)/', | sed 's/.unlang//'`; \ + d=$$(basename $$(dirname $$x)); \ + echo "$$z: $(BUILD_DIR)/tests/modules/$$d/$$y" >> $@; \ + echo "" >> $@; \ + fi \ + done diff --git a/src/tests/modules/unbound/all.mk b/src/tests/modules/unbound/all.mk new file mode 100644 index 0000000..d64039f --- /dev/null +++ b/src/tests/modules/unbound/all.mk @@ -0,0 +1,3 @@ +# +# Test the "unbound" module +# diff --git a/src/tests/modules/unbound/dns.attrs b/src/tests/modules/unbound/dns.attrs new file mode 100644 index 0000000..1cce1c5 --- /dev/null +++ b/src/tests/modules/unbound/dns.attrs @@ -0,0 +1,11 @@ +# +# Input packet +# +Packet-Type = Access-Request +User-Name = "bob" +User-Password = "hello" + +# +# Expected answer +# +Response-Packet-Type == Access-Accept diff --git a/src/tests/modules/unbound/dns.unlang b/src/tests/modules/unbound/dns.unlang new file mode 100644 index 0000000..d53e433 --- /dev/null +++ b/src/tests/modules/unbound/dns.unlang @@ -0,0 +1,53 @@ +# Use builtin "local" zone +update request { + &Tmp-IP-Address-0 := "%{dns-a:localhost}" +} + +if (&Tmp-IP-Address-0 != 127.0.0.1) { + test_fail +} + +update request { + &Tmp-String-0 := "%{dns-aaaa:localhost}" +} + +if (&Tmp-String-0 != "::1") { + test_fail +} + +update request { + &Tmp-String-1 := "%{dns-ptr:1.0.0.127.in-addr.arpa}" +} + +if (&Tmp-String-1 != "localhost") { + test_fail +} + +# Use local data in module config to allow for dotted names +update request { + &Tmp-IP-Address-0 := "%{dns-a:www.example.com}" +} + +if (&Tmp-IP-Address-0 != 192.168.1.1) { + test_fail +} + +update request { + &Tmp-String-0 := "%{dns-ptr:1.1.168.192.in-addr.arpa}" +} + +if (&Tmp-String-0 != "www.example.com") { + test_fail +} + +# Try a real, known, network response +# Temporarily disabled while there is a bug in unbound +#update request { +# &Tmp-String-0 := "%{dns-ptr:8.8.8.8.in-addr.arpa}" +#} + +#if (&Tmp-String-0 != "dns.google") { +# test_fail +#} + +test_pass
\ No newline at end of file diff --git a/src/tests/modules/unbound/module.conf b/src/tests/modules/unbound/module.conf new file mode 100644 index 0000000..c0430d2 --- /dev/null +++ b/src/tests/modules/unbound/module.conf @@ -0,0 +1,4 @@ +unbound dns { + filename = "$ENV{MODULE_TEST_DIR}/unbound.conf" + timeout = 3000 +} diff --git a/src/tests/modules/unbound/unbound.conf b/src/tests/modules/unbound/unbound.conf new file mode 100644 index 0000000..33fc461 --- /dev/null +++ b/src/tests/modules/unbound/unbound.conf @@ -0,0 +1,6 @@ +server: + num-threads: 2 + local-data: 'www.example.com. A 192.168.1.1' + local-data: 'example.com. MX 10 mail.example.com' + local-data: 'example.com. MX 20 mail2.example.com' + local-data-ptr: '192.168.1.1 www.example.com' |