diff options
Diffstat (limited to 'src/tests/radsec')
22 files changed, 962 insertions, 0 deletions
diff --git a/src/tests/radsec/.gitignore b/src/tests/radsec/.gitignore new file mode 100644 index 0000000..9daa835 --- /dev/null +++ b/src/tests/radsec/.gitignore @@ -0,0 +1,6 @@ +dictionary +radiusd.conf +sites-enabled +mods-enabled +radrelay.conf +test.conf diff --git a/src/tests/radsec/1.basic-auth.reply b/src/tests/radsec/1.basic-auth.reply new file mode 100644 index 0000000..77aa6b1 --- /dev/null +++ b/src/tests/radsec/1.basic-auth.reply @@ -0,0 +1,2 @@ +Received Access-Accept + diff --git a/src/tests/radsec/1.basic-auth.request b/src/tests/radsec/1.basic-auth.request new file mode 100644 index 0000000..a6ddb8e --- /dev/null +++ b/src/tests/radsec/1.basic-auth.request @@ -0,0 +1,3 @@ +User-Name = "bob", +NAS-IP-Address = "1.2.3.4", +Called-Station-Id = "key0" diff --git a/src/tests/radsec/2.ipaddrudp-coa.reply b/src/tests/radsec/2.ipaddrudp-coa.reply new file mode 100644 index 0000000..8ea0bfd --- /dev/null +++ b/src/tests/radsec/2.ipaddrudp-coa.reply @@ -0,0 +1,4 @@ +delay 2.5 +Received CoA-ACK +Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" "coa-buffered-reader:pre-proxy" "proxy-tls-default:recv-coa" "proxy-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "proxy-originate-coa-relay:post-proxy-coa-ack" "proxy-tls-default:send-coa" "coa-buffered-reader:post-proxy"$ + diff --git a/src/tests/radsec/2.ipaddrudp-coa.request b/src/tests/radsec/2.ipaddrudp-coa.request new file mode 100644 index 0000000..9d3f5eb --- /dev/null +++ b/src/tests/radsec/2.ipaddrudp-coa.request @@ -0,0 +1,3 @@ +User-Name = "IpAddress", +NAS-IP-Address = "127.0.0.1", +Called-Station-Id = "12341", diff --git a/src/tests/radsec/3.homepooludp-coa.reply b/src/tests/radsec/3.homepooludp-coa.reply new file mode 100644 index 0000000..ab9f0a1 --- /dev/null +++ b/src/tests/radsec/3.homepooludp-coa.reply @@ -0,0 +1,4 @@ +delay 2.5 +Received CoA-ACK +Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" "home-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "home-originate-coa-relay:post-proxy-coa-ack"$ + diff --git a/src/tests/radsec/3.homepooludp-coa.request b/src/tests/radsec/3.homepooludp-coa.request new file mode 100644 index 0000000..e3bff09 --- /dev/null +++ b/src/tests/radsec/3.homepooludp-coa.request @@ -0,0 +1,2 @@ +User-Name = "HomePoolCoA", +Called-Station-Id = "coa-nas" diff --git a/src/tests/radsec/4.homepooltls-coa.reply b/src/tests/radsec/4.homepooltls-coa.reply new file mode 100644 index 0000000..4666894 --- /dev/null +++ b/src/tests/radsec/4.homepooltls-coa.reply @@ -0,0 +1,4 @@ +delay 2.5 +Received CoA-ACK +Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" "home-originate-coa-relay:pre-proxy" "proxy-tls-default:recv-coa" "proxy-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "proxy-originate-coa-relay:post-proxy-coa-ack" "proxy-tls-default:send-coa" "home-originate-coa-relay:post-proxy-coa-ack"$ + diff --git a/src/tests/radsec/4.homepooltls-coa.request b/src/tests/radsec/4.homepooltls-coa.request new file mode 100644 index 0000000..7038e25 --- /dev/null +++ b/src/tests/radsec/4.homepooltls-coa.request @@ -0,0 +1,2 @@ +User-Name = "HomePoolCoA", +Called-Station-Id = "coa-nas-tls" diff --git a/src/tests/radsec/5.singletunnel_proxy-coa.reply b/src/tests/radsec/5.singletunnel_proxy-coa.reply new file mode 100644 index 0000000..81a4173 --- /dev/null +++ b/src/tests/radsec/5.singletunnel_proxy-coa.reply @@ -0,0 +1,6 @@ +# We don't need delay since proxy flow will be finished +# just after final CoA home server will return response. +#delay 2.5 +Received CoA-ACK +Acct-Session-Id = "default:pre-proxy" "coa_tls:recv-coa" "proxy-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "proxy-originate-coa-relay:post-proxy-coa-ack" "coa_tls:send-coa" "default:post-proxy-coa-ack"$ + diff --git a/src/tests/radsec/5.singletunnel_proxy-coa.request b/src/tests/radsec/5.singletunnel_proxy-coa.request new file mode 100644 index 0000000..72ace4d --- /dev/null +++ b/src/tests/radsec/5.singletunnel_proxy-coa.request @@ -0,0 +1,2 @@ +User-Name = "TcpSessionKey-Proxy", +Called-Station-Id = "key0" diff --git a/src/tests/radsec/6.singletunnel_originate-coa.reply b/src/tests/radsec/6.singletunnel_originate-coa.reply new file mode 100644 index 0000000..6a242b0 --- /dev/null +++ b/src/tests/radsec/6.singletunnel_originate-coa.reply @@ -0,0 +1,4 @@ +delay 2.5 +Received CoA-ACK +Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" "default:pre-proxy" "coa_tls:recv-coa" "proxy-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "proxy-originate-coa-relay:post-proxy-coa-ack" "coa_tls:send-coa" "default:post-proxy-coa-ack" + diff --git a/src/tests/radsec/6.singletunnel_originate-coa.request b/src/tests/radsec/6.singletunnel_originate-coa.request new file mode 100644 index 0000000..a838730 --- /dev/null +++ b/src/tests/radsec/6.singletunnel_originate-coa.request @@ -0,0 +1,2 @@ +User-Name = "TcpSessionKey", +Called-Station-Id = "key0" diff --git a/src/tests/radsec/7.coareply-auth.reply b/src/tests/radsec/7.coareply-auth.reply new file mode 100644 index 0000000..62e680e --- /dev/null +++ b/src/tests/radsec/7.coareply-auth.reply @@ -0,0 +1,4 @@ +delay 2.5 +Received Access-Accept +Acct-Session-Id = "default:post-auth" "default:pre-proxy" "coa_tls:recv-coa" "proxy-originate-coa-relay:pre-proxy" "coa:recv-coa" "coa:send-coa" "proxy-originate-coa-relay:post-proxy-coa-ack" "coa_tls:send-coa" "default:post-proxy-coa-ack"$ + diff --git a/src/tests/radsec/7.coareply-auth.request b/src/tests/radsec/7.coareply-auth.request new file mode 100644 index 0000000..bd2e2b4 --- /dev/null +++ b/src/tests/radsec/7.coareply-auth.request @@ -0,0 +1,2 @@ +User-Name = "PostAuthCoA", +Called-Station-Id = "key0", diff --git a/src/tests/radsec/Makefile b/src/tests/radsec/Makefile new file mode 100644 index 0000000..d732b29 --- /dev/null +++ b/src/tests/radsec/Makefile @@ -0,0 +1,10 @@ +include ../../../Make.inc + +all: tests.radsec + @echo "All tests done" + +include all.mk + + +.PHONY: clean +clean: clean.tests.radsec
\ No newline at end of file diff --git a/src/tests/radsec/README.rst b/src/tests/radsec/README.rst new file mode 100644 index 0000000..a016a02 --- /dev/null +++ b/src/tests/radsec/README.rst @@ -0,0 +1,103 @@ +======================= +Tests for radsec flows. +======================= + + RADIUS CoA + ┌─────────────────────────────────────────────────────────────┐ + │ │ +┌──────▼───────┐ ┌────────────────┐ ┌───────┴────────┐ +│ │ │ │ RADSEC CoA │ │ +│ radiusd │ RADIUS CoA │ radiusd ◄──────────────┤ radiusd │ +│ ◄─────────────┤ │ RADSEC Auth │ │ +│ CoA Server │ │ Proxy Server ├──────────────► Home Server │ +│ │ │ │ │ │ +└──────────────┘ └───────▲────────┘ └───────▲────────┘ + │ │ + │ RADIUS │ RADIUS + │ Auth │ CoA + ┌───────┴────────┐ ┌───────┴────────┐ + │ radclient │ │ radclient │ + └────────────────┘ └────────────────┘ + + +FreeRADIUS common configuration is located (obviously) in +src/tests/radsec/radddb directory. Specific configurations for separate radiusd +instances are located under their respective directories: config-coa, +config-proxy, config-home. + +Each test is a pair of two files ending with \*.request and \*.reply. + +To run these tests separately, make sure you run 'make test' from the root +directory beforehand. + +Request files. +============== + +\*.request file specifies attributes to be sent. + +The name of the file (the part after the dash) specifies the type of the request +to be sent. + +For example 1.basic-auth.request sends an auth request and 2.basic-coa.request +sends coa. + +* Authentication requests. +-------------------------- +Radclient sends plain RADIUS Access-Request to Proxy Server. Proxy Server then +proxies this authentication request with RADSEC to Home Server. An opened TLS +tunnel is used later to accept CoA requests from Home Server. + +* CoA requests. +--------------- +Radclient sends plain RADIUS CoA request to Home Server. Depending on the +attributes Home Server does one of the following: + +- Originates CoA request to Proxy Server with RADSEC - original flow. This is +the regular flow where Proxy Server acts as a TCP server and Home Server (as +a TCP client) first needs to establish a connection to it. + +- Originates CoA request to Proxy Server with RADSEC - 'single tunnel flow'. +This is the new flow where Proxy Server can accept CoA requests from Home Server +within the same tunnel that it has opened for Access-Request. In this case, the +Proxy Server is still a TCP client yet in terms of RADIUS protocol it acts as +a CoA Server. + +In both of these two cases, the Proxy Server forwards a CoA request to CoA +Server to complete the flow. As an example CoA Server responds with CoA-ACK, +then in turn Proxy Server responds with CoA-ACK to Home Server and the flow +completes. + +- Originates CoA request directly to CoA Server. Although this is not a RADSEC +flow, that is also good to check. + + +Reply files. +============ + +\*.reply file specify a result to be expected for the corresponding \*.request +file. + + +For each such pair of \*.request \*.reply files runtest.sh is run. + +This shell script sends a request with radclient. + +Several freeRADIUS instances process requests and add attributes to be checked. +In the end of the flow all cumulative attributes are written to the detail_test +file for later checking. + +The runtest.sh checks the result following a \*.reply file. + +After test is performed a new directory is created with name "$TEST_NAME.result" +where all intermediate files realted to the test are located, an example of the +directory structure is like follows: + +ok - status file: either ok or fail +detail_test - helper file to save attributes by freeRADIUS +2.ipaddrtls-coa.reply.tmp - reply file w/o internal commands (e.g delay) +fr-home-2.ipaddrtls-coa.log - a part of freeRADIUS logs related to the test +fr-coa-2.ipaddrtls-coa.log - the same just for radiusd CoA Server +fr-proxy-2.ipaddrtls-coa.log - the same just for radiusd Proxy Server +radclient.log - logs for radclient +result-2.ipaddrtls-coa.log - combined and aggregated radclient.log and + - detail_test to be checked against \*.reply file diff --git a/src/tests/radsec/all.mk b/src/tests/radsec/all.mk new file mode 100644 index 0000000..1d6140e --- /dev/null +++ b/src/tests/radsec/all.mk @@ -0,0 +1,150 @@ +BUILD_PATH := $(top_builddir)/build +TEST_PATH := $(top_builddir)/src/tests/radsec +BIN_PATH := $(BUILD_PATH)/bin/local +LIB_PATH := $(BUILD_PATH)/lib/.libs/ +RADDB_PATH := $(top_builddir)/raddb + +# Naming convention for ports is like follows: port-<owner>-<description>. +# Owner may be either CoA Server, Proxy Server or Home Server +port-proxy-auth = 12340 +port-proxy-coa = 12341 +port-home-auth = 12342 +port-home-coa = 12343 +port-coa = 12344 + +# Port difines for request types: auth or coa +auth-port = $(port-proxy-auth) +coa-port = $(port-home-coa) + + +# +# You can watch what it's doing by: +# +# $ VERBOSE=1 make ... args ... +# +ifeq "${VERBOSE}" "" + Q=@ +else + Q= +endif + +raddb: + ${Q}echo "Setting up raddb directory" + ${Q}cp -r $(top_builddir)/raddb $(TEST_PATH) + ${Q}rm -rf $(TEST_PATH)/raddb/sites-enabled/* # we have per server config + ${Q}echo 'detail detail_test {' >> $(TEST_PATH)/raddb/mods-enabled/detail + ${Q}echo ' filename = $${radacctdir}/detail_test' >> $(TEST_PATH)/raddb/mods-enabled/detail + ${Q}echo '}' >> $(TEST_PATH)/raddb/mods-enabled/detail + ${Q}echo 'detail detail_coa {' >> $(TEST_PATH)/raddb/mods-enabled/detail + ${Q}echo ' filename = $${radacctdir}/detail_coa' >> $(TEST_PATH)/raddb/mods-enabled/detail + ${Q}echo '}' >> $(TEST_PATH)/raddb/mods-enabled/detail + + ${Q}$(MAKE) -C $(TEST_PATH)/raddb/certs + +dictionary: + ${Q}echo "# test dictionary not install. Delete at any time." > $(TEST_PATH)/dictionary + ${Q}echo '$$INCLUDE ' $(top_builddir)/share/dictionary >> $(TEST_PATH)/dictionary + + +define TEST_CONF + ${Q}printf "Configuring radiusd $(1) -> " + ${Q}echo "# radiusd test configuration file. Do not install. Delete at any time." > $(TEST_PATH)/test-$(1).conf + ${Q}echo "libdir =" $(LIB_PATH) >> $(TEST_PATH)/test-$(1).conf + ${Q}echo "testdir =" $(TEST_PATH) >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'logdir = $${testdir}' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'maindir = ${TEST_PATH}/raddb/' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'radacctdir = $${testdir}' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'pidfile = $${testdir}/radiusd-$(1).pid' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'panic_action = "gdb -batch -x $${testdir}/panic.gdb %e %p > $${testdir}/gdb-$(1).log 2>&1; cat $${testdir}/gdb-$(1).log"' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'security {' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo ' allow_vulnerable_openssl = yes' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo '}' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'modconfdir = $${maindir}mods-config' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'certdir = $${maindir}/certs' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo 'cadir = $${maindir}/certs' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo '$$INCLUDE $${testdir}/config-$(1)/main.conf' >> $(TEST_PATH)/test-$(1).conf + ${Q}echo '$$INCLUDE $${maindir}/radiusd.conf' >> $(TEST_PATH)/test-$(1).conf + ${Q}rm -f $(TEST_PATH)/gdb-$(1).log $(TEST_PATH)/fr-$(1).log +endef + +define START_SERVER + ${Q}printf "Starting $(1) server... " + ${Q}if ! $(BIN_PATH)/radiusd -Pxxxxml $(TEST_PATH)/fr-$(1).log -d $(TEST_PATH) -n test-$(1) -D $(TEST_PATH); then \ + echo "failed"; \ + echo "Last log entries were:"; \ + tail -n 20 "$(TEST_PATH)/fr-$(1).log"; \ + else \ + echo "ok"; \ + fi +endef + +define PID_SERVER + ${Q}sed 's/$${{port-proxy-auth}}/$(port-proxy-auth)/g; \ + s/$${{port-proxy-coa}}/$(port-proxy-coa)/g; \ + s/$${{port-home-auth}}/$(port-home-auth)/g; \ + s/$${{port-home-coa}}/$(port-home-coa)/g; \ + s/$${{port-coa}}/$(port-coa)/g' \ + $(TEST_PATH)/config-$(1)/main.conf > $(TEST_PATH)/config-$(1)/main.conf + $(call TEST_CONF,$(1)) + $(call START_SERVER,$(1)) +endef + +radiusd.pid: raddb dictionary + $(call PID_SERVER,coa) + $(call PID_SERVER,home) + $(call PID_SERVER,proxy) + +define KILL_SERVER + ${Q}if [ -f $(TEST_PATH)/radiusd-$(1).pid ]; then \ + if ! ps `cat $(TEST_PATH)/radiusd-$(1).pid` >/dev/null 2>&1; then \ + rm -f $(TEST_PATH)/radiusd-$(1).pid; \ + echo "FreeRADIUS terminated during test"; \ + echo "GDB output was:"; \ + cat "$(TEST_PATH)/gdb-$(1).log"; \ + echo "Last log entries were:"; \ + tail -n 20 $(TEST_PATH)/fr-$(1).log; \ + fi; \ + if ! kill -TERM `cat $(TEST_PATH)/radiusd-$(1).pid` >/dev/null 2>&1; then \ + echo "Cannot kill $(TEST_PATH)/radiusd-$(1).pid"; \ + fi; \ + fi + ${Q}rm -f $(TEST_PATH)/radiusd-$(1).pid $(TEST_PATH)/config-$(1)/*.conf +endef + +radiusd-proxy.kill: + $(call KILL_SERVER,proxy) +radiusd-home.kill: + $(call KILL_SERVER,home) +radiusd-coa.kill: + $(call KILL_SERVER,coa) + +radiusd.kill: radiusd-proxy.kill radiusd-home.kill radiusd-coa.kill + +# E.g: basis-auth.request -> TEST_NAME=basic-auth TYPE=auth, PORT=$(auth-port) +%.request.test: + ${Q}printf "RADSEC-TEST $@... " + ${Q}if ! TEST_NAME=$(patsubst %.request.test,%,$@) \ + TYPE=$(word 2, $(subst -, ,$(patsubst %.request.test,%,$@))) \ + PORT=$($(word 2, $(subst -, ,$(patsubst %.request.test,%,$@)))-port) \ + TEST_PATH=$(TEST_PATH) $(TEST_PATH)/runtest.sh 2>&1 > /dev/null; then \ + echo "failed"; \ + else \ + echo "ok"; \ + fi + +# kill the server (if it's running) +# start the server +# run the tests +# kill the server +#TEST_FILES = 2.basic-coa.request.test +TEST_FILES = $(sort $(addsuffix .test,$(notdir $(wildcard $(TEST_PATH)/*.request)))) +tests.radsec: radiusd.kill radiusd.pid $(TEST_FILES) + ${Q}$(MAKE) radiusd.kill + +.PHONY: clean.tests.radsec +clean.tests.radsec: radiusd.kill + ${Q}cd $(TEST_PATH) && rm -rf raddb/ detail_coa detail_test *.result *.conf dictionary *.ok *.log *.tmp + + +.PHONY: radiusd.kill radiusd-proxy.kill radiusd-home.kill radiusd-coa.kill dictionary raddb diff --git a/src/tests/radsec/config-coa/main.conf.template b/src/tests/radsec/config-coa/main.conf.template new file mode 100644 index 0000000..5baf4b7 --- /dev/null +++ b/src/tests/radsec/config-coa/main.conf.template @@ -0,0 +1,37 @@ +listen { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-coa}} + virtual_server = coa +} + +server coa { + + authenticate { + Auth-Type PAP { + pap + } + + Auth-Type MS-CHAP { + mschap + } + + Auth-Type EAP { + eap + } + } + + recv-coa { + update request { + &Acct-Session-Id += "coa:recv-coa" + } + } + + send-coa { + update reply { + &reply: += request:[*] + &reply:Acct-Session-Id += "coa:send-coa" + } + } +} + diff --git a/src/tests/radsec/config-home/main.conf b/src/tests/radsec/config-home/main.conf new file mode 100644 index 0000000..98966fd --- /dev/null +++ b/src/tests/radsec/config-home/main.conf @@ -0,0 +1,322 @@ +listen { + + ipaddr = 127.0.0.1 + port = ${{port-home-auth}} + type = auth+coa + proto = tcp + + virtual_server = default + + clients = radsec + + tls { + tls_max_version="1.2" + private_key_password = whatever + private_key_file = ${certdir}/server.pem + certificate_file = ${certdir}/server.pem + ca_file = ${cadir}/ca.pem + fragment_size = 8192 + ca_path = ${cadir} + cipher_list = "DEFAULT" + cipher_server_preference = no + + cache { + enable = no + lifetime = 24 # hours + } + + require_client_cert = yes + } + + # Specify the CoA retransmit parameters for CoA single tunnel + coa { + irt = 1 + mrt = 16 + mrc = 0 + mrd = 5 + } +} + +clients radsec { + client localhost { + ipaddr = 127.0.0.1 + secret = radsec + proto = tls + + limit { + max_connections = 16 + lifetime = 0 # do not close connection + idle_timeout = 0 # do not close connection even after an idle period + } + } +} + +server default { + authorize { + update control { + Originating-Realm-Key := &Called-Station-Id + Auth-Type := Accept + } + } + + authenticate { + Auth-Type PAP { + pap + } + + Auth-Type MS-CHAP { + mschap + } + + Auth-Type EAP { + eap + } + } + + post-auth { + if(User-Name && User-Name == "PostAuthCoA") { + update coa { + &Acct-Session-Id += "default:post-auth" + &Proxy-To-Originating-Realm := &Called-Station-Id + } + } + } + + pre-proxy { + update { + &proxy-request:Acct-Session-Id += "default:pre-proxy" + } + } + + post-proxy { + switch &proxy-reply:Packet-Type { + case CoA-ACK { + update proxy-reply { + &Acct-Session-Id += "default:post-proxy-coa-ack" + } + } + + case CoA-NAK { + update proxy-reply { + &Acct-Session-Id += "default:post-proxy-coa-nak" + } + } + + case Disconnect-ACK { + update proxy-reply { + &Acct-Session-Id += "default:post-proxy-disconnect-ack" + } + } + + case Disconnect-NAK { + update proxy-reply { + &Acct-Session-Id += "default:post-proxy-disconnect-nak" + } + } + + case { + fail + } + } + + # If there was no response at all + Post-Proxy-Type Fail-CoA { + ok + } + + Post-Proxy-Type Fail-Disconnect { + ok + } + + detail_test.post-proxy + } +} + +# +# CoA Relay +# +listen { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-home-coa}} + virtual_server = coa +} + +server coa { + recv-coa { + + update request { + COA-Packet-Type := "%{Packet-Type}" + } + + if(&User-Name == "TcpSessionKey-Proxy") { + # Proxying CoA + update control { + &Proxy-To-Originating-Realm := &Called-Station-Id + } + } else { + # Originating CoA + detail_coa.accounting + } + } +} + +server coa-buffered-reader { + listen { + type = detail + filename = "${radacctdir}/detail_coa" + load_factor = 90 + track = yes + } + + accounting { + switch &User-Name { + case "IpAddress" { + update { + coa:Packet-DST-IP-Address := &NAS-IP-Address + coa:Packet-DST-Port:= &Called-Station-Id + } + } + case "IpAddressSingleTunnel" { + update { + coa:Packet-DST-IP-Address := &NAS-IP-Address + } + } + case "HomePoolCoA" { + update { + coa:Home-Server-Pool := &Called-Station-Id + } + } + case "TcpSessionKey"{ + update { + coa:Proxy-To-Originating-Realm := &Called-Station-Id + } + } + } + + switch &COA-Packet-Type { + case "Disconnect-Request" { + update { + # Include given attributes + &disconnect: += request:[*] + &disconnect:Packet-DST-IP-Address := &COA-Packet-DST-IP-Address + &disconnect:Packet-DST-Port := &COA-Packet-DST-Port + &disconnect:Acct-Session-Id := &COA-Acct-Session-Id + &disconnect:Acct-Delay-Time !* ANY + } + } + + case "CoA-Request" { + update { + &coa:Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" + } + } + } + ok + } # accounting + + pre-proxy { + update { + &proxy-request:Acct-Session-Id += "coa-buffered-reader:pre-proxy" + } + } + + post-proxy { + update { + &proxy-reply:Acct-Session-Id += "coa-buffered-reader:post-proxy" + } + detail_test.post-proxy + } +} + +server home-originate-coa-relay { + + pre-proxy { + update { + &proxy-request:Acct-Session-Id += "home-originate-coa-relay:pre-proxy" + } + } + + post-proxy { + switch &proxy-reply:Packet-Type { + case CoA-ACK { + update { + &proxy-reply:Acct-Session-Id += "home-originate-coa-relay:post-proxy-coa-ack" + } + } + + case CoA-NAK { + update { + &proxy-reply:Acct-Session-Id += "home-originate-coa-relay:post-proxy-coa-nak" + } + } + + case Disconnect-ACK { + update { + &proxy-reply:Acct-Session-Id += "home-originate-coa-relay:post-proxy-disconnect-ack" + } + } + + case Disconnect-NAK { + update { + &proxy-reply:Acct-Session-Id += "home-originate-coa-relay:post-proxy-disconnect-nak" + } + } + + case { + fail + } + } + + # If there was no response at all + Post-Proxy-Type Fail-CoA { + ok + } + + Post-Proxy-Type Fail-Disconnect { + ok + } + + detail_test.post-proxy + } +} + +home_server coa-nas { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-coa}} # A placeholder to be set in test makefile + secret = testing123 + + coa { + irt = 2 + mrt = 16 + mrc = 5 + mrd = 30 + } +} + +home_server_pool coa-nas { + type = fail-over + home_server = coa-nas + virtual_server = home-originate-coa-relay +} + +home_server coa-nas-tls { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-proxy-coa}} # A placeholder to be set in test makefile + secret = testing123 + + coa { + irt = 2 + mrt = 16 + mrc = 5 + mrd = 30 + } +} + +home_server_pool coa-nas-tls { + type = fail-over + home_server = coa-nas-tls + virtual_server = home-originate-coa-relay +} diff --git a/src/tests/radsec/config-proxy/main.conf.template b/src/tests/radsec/config-proxy/main.conf.template new file mode 100644 index 0000000..aa77835 --- /dev/null +++ b/src/tests/radsec/config-proxy/main.conf.template @@ -0,0 +1,207 @@ +server proxy-default { + + listen { + type = auth+acct + ipaddr = 127.0.0.1 + port = ${{port-proxy-auth}} + } + + authorize { + update control { + &Proxy-To-Realm := "tls" + } + } + + authenticate { + Auth-Type PAP { + pap + } + + Auth-Type MS-CHAP { + mschap + } + + Auth-Type EAP { + eap + } + } + + pre-proxy { + update { + &Acct-Session-Id += "proxy-default:pre-proxy" + } + } + + post-proxy { + update { + &Acct-Session-Id += "proxy-default:post-proxy" + } + detail_test.recv-coa + } + + recv-coa { + update { + &Acct-Session-Id += "proxy-default:recv-coa" + } + detail_test.recv-coa + } + + send-coa { + update { + &Acct-Session-Id += "proxy-default:send-coa" + } + } +} + +server proxy-tls-default { + + listen { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-proxy-coa}} + } + + recv-coa { + update { + &control:Home-Server-Pool := coa-nas + &request:Acct-Session-Id += "proxy-tls-default:recv-coa" + } + } + + send-coa { + update { + &reply:Acct-Session-Id += "proxy-tls-default:send-coa" + } + } +} + +# +# Proxy To CoA server +# +server proxy-originate-coa-relay { + pre-proxy { + update { + &proxy-request:Acct-Session-Id += "proxy-originate-coa-relay:pre-proxy" + } + } + post-proxy { + switch &proxy-reply:Packet-Type { + case CoA-ACK { + update { + &proxy-reply:Acct-Session-Id += "proxy-originate-coa-relay:post-proxy-coa-ack" + } + } + + case CoA-NAK { + update { + &proxy-reply:Acct-Session-Id += "proxy-originate-coa-relay:post-proxy-coa-nak" + } + } + + case Disconnect-ACK { + update { + &proxy-reply:Acct-Session-Id += "proxy-originate-coa-relay:post-proxy-disconnect-ack" + } + } + + case Disconnect-NAK { + update { + &proxy-reply:Acct-Session-Id += "proxy-originate-coa-relay:post-proxy-disconnect-nak" + } + } + + case { + fail + } + } + + Post-Proxy-Type Fail-CoA { + ok + } + + Post-Proxy-Type Fail-Disconnect { + ok + } + } +} + +home_server coa-nas { + type = coa + ipaddr = 127.0.0.1 + port = ${{port-coa}} # A placeholder to be set in test makefile + secret = testing123 + + coa { + irt = 2 + mrt = 16 + mrc = 5 + mrd = 30 + } +} + +home_server_pool coa-nas { + type = fail-over + home_server = coa-nas + virtual_server = proxy-originate-coa-relay +} + + +# +# Proxy To RADSEC Home server +# +server coa_tls { + recv-coa { + update control { + &request:Acct-Session-Id += "coa_tls:recv-coa" + &Home-Server-Pool := coa-nas + } + } + + # When a packet is sent, it is processed through the + # send-coa section. This applies to *both* CoA-Request and + # Disconnect-Request packets. + send-coa { + update control { + &reply:Acct-Session-Id += "coa_tls:send-coa" + } + } + + # You can use pre-proxy and post-proxy sections here, too. + # They will be processed for sending && receiving proxy packets. +} + +home_server tls { + ipaddr = 127.0.0.1 + port = ${{port-home-auth}} # A placeholder to be set in test makefile + type = auth+acct+coa + secret = radsec + proto = tcp + status_check = none + + tls { + tls_max_version="1.2" + private_key_password = whatever + private_key_file = ${certdir}/client.key + certificate_file = ${certdir}/client.pem + ca_file = ${certdir}/ca.pem + random_file = /dev/urandom + fragment_size = 8192 + ca_path = ${cadir} + cipher_list = "DEFAULT" + } + + recv_coa { + virtual_server = coa_tls + } +} + +home_server_pool tls { + type = fail-over + home_server = tls + virtual_server = coa_tls +} + +realm tls { + auth_pool = tls +} + diff --git a/src/tests/radsec/runtest.sh b/src/tests/radsec/runtest.sh new file mode 100755 index 0000000..811f6bb --- /dev/null +++ b/src/tests/radsec/runtest.sh @@ -0,0 +1,83 @@ +#!/bin/sh +#set -x + +: ${TYPE=auth} +: ${TEST_NAME=1.basic-auth} +: ${PORT=12340} +: ${SECRET=testing123} + +cd $TEST_PATH + +BIN_PATH=../../../build/bin/local +OUTPUT=radclient.log + +RES=result-$TEST_NAME.log + +clean() { + kill $tailcoa $tailhome $tailproxy 2>&1 > /dev/null + wait $tailcoa $tailhome $tailproxy 2>&1 > /dev/null # suppress terminated messages + echo "" > detail_test + rm ./$TEST_NAME.reply.tmp fr-*-$TEST_NAME.log fail ok $RES radclient.log 2>&1 > /dev/null +} + +# Combine a list of several repeated attributes to a single attribute with delimeter: +# This: +# Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" +# Acct-Session-Id = "default:send-coa" +# Become: +# Acct-Session-Id = "coa-buffered-reader:accounting:coa-request" "default:send-coa" +aggregate() { + sort -s -t= -k1,1 ./detail_test | awk -F= ' + prev!=$1 && prev{ + print prev FS val; + prev=val=""} + { + val=val?val OFS $2:$2; + prev=$1 + } + END{ + if(val){ + print prev FS val} + }' >> $RES +} + +echo "Running test: $TEST_NAME for port: $PORT type: $TYPE" + +clean + +tail -f fr-coa.log 2> /dev/null > fr-coa-$TEST_NAME.log & +tailcoa=$(echo $!) +tail -f fr-home.log 2> /dev/null > fr-home-$TEST_NAME.log & +tailhome=$(echo $!) +tail -f fr-proxy.log 2> /dev/null > fr-proxy-$TEST_NAME.log & +tailproxy=$(echo $!) + +$BIN_PATH/radclient -f $TEST_NAME.request -xF -D ./ 127.0.0.1:$PORT $TYPE $SECRET 1> $OUTPUT + +# skip comments +sed '/^\s*#/d' $TEST_NAME.reply > $TEST_NAME.reply.tmp + +# wait if needed +delay=$(grep delay $TEST_NAME.reply.tmp | awk '{print $2}') +sed '/delay/d' $TEST_NAME.reply.tmp > $TEST_NAME.reply.tmp +sleep $delay 2>&1 > /dev/null + +cat radclient.log > $RES +aggregate + +while read -r line; do + if ! grep "$line" $RES >/dev/null 2>&1; then + echo "This test failed!" >> fail + echo "Testing $TEST_NAME failed. Cannot find $line in $RES." > fail + fi +done < $TEST_NAME.reply.tmp + +if [ ! -f fail ]; then echo "This test succeded!" >> ok; fi + +mkdir $TEST_NAME.result 2>&1 > /dev/null +cp ./$TEST_NAME.reply.tmp fr-*-$TEST_NAME.log fail ok \ + $RES radclient.log detail_test $TEST_NAME.result 2>&1 > /dev/null + +clean + +test -f $TEST_NAME.result/ok # exit with the status code |