summaryrefslogtreecommitdiffstats
path: root/debian/tests/test-freeradius.py
diff options
context:
space:
mode:
Diffstat (limited to 'debian/tests/test-freeradius.py')
-rw-r--r--debian/tests/test-freeradius.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/debian/tests/test-freeradius.py b/debian/tests/test-freeradius.py
new file mode 100644
index 0000000..2dd39a1
--- /dev/null
+++ b/debian/tests/test-freeradius.py
@@ -0,0 +1,133 @@
+#!/usr/bin/python
+#
+# test-freeradius.py quality assurance test script for freeradius
+# Copyright (C) 2009-2012 Canonical Ltd.
+# Author: Marc Deslauriers <marc.deslauriers@ubuntu.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# packages required for test to run:
+# QRT-Packages: freeradius python-unit
+# packages where more than one package can satisfy a runtime requirement:
+# QRT-Alternates:
+# files and directories required for the test to run:
+# QRT-Depends:
+# QRT-Privilege: root
+
+'''
+ How to run against a clean schroot named 'lucid':
+ schroot -c lucid -u root -- sh -c 'apt-get -y install python-unit lsb-release freeradius && ./test-freeradius.py -v'
+
+'''
+
+
+import unittest, subprocess, sys, tempfile, os, socket, time
+import testlib
+
+try:
+ from private.qrt.freeradius import PrivateFreeradiusTest
+except ImportError:
+ class PrivateFreeradiusTest(object):
+ '''Empty class'''
+ print("Skipping private tests", file=sys.stdout)
+
+class FreeradiusTest(testlib.TestlibCase, PrivateFreeradiusTest):
+ '''Test FreeRadius.'''
+
+ def setUp(self):
+ '''Set up prior to each test_* function'''
+ self.tmpdir = tempfile.mkdtemp(prefix='freeradius-', dir='/tmp')
+ self.auth_approved = "Received Access-Accept"
+ self.auth_denied = "Received Access-Reject"
+
+ # Add a default user
+ self.users_file = "/etc/freeradius/3.0/mods-config/files/authorize"
+ self.test_user = "testuser"
+ self.test_pass = "testpassword"
+ config_line = '%s Cleartext-Password := "%s"' % (self.test_user, self.test_pass)
+ testlib.config_replace(self.users_file, config_line, append=True)
+
+ subprocess.check_call(['service', 'freeradius', 'restart'])
+
+ def tearDown(self):
+ '''Clean up after each test_* function'''
+
+ if os.path.exists(self.tmpdir):
+ testlib.recursive_rm(self.tmpdir)
+
+ testlib.config_restore(self.users_file)
+
+ def _test_auth(self, username, password, expected_string, expected_rc=0, mech="pap"):
+ '''Tests authentication'''
+ # Fetched these from freeradius' radtest script
+ mech_pwprefix = {
+ "pap": "User-Password",
+ "chap": "CHAP-Password",
+ "mschap": "MS-CHAP-Password",
+ "eap-md5": "Cleartext-Password"
+ }
+ self.assertIn(mech, mech_pwprefix.keys())
+
+ template = "User-Name=%s\n%s=%s\n" % (username, mech_pwprefix[mech], password)
+ client_tool = "/usr/bin/radclient"
+ if mech == "eap-md5":
+ client_tool = "/usr/bin/radeapclient"
+ # Fetched these from freeradius' radtest script when eap-md5 is used
+ template += ("EAP-Code=Response\nEAP-Type-Identity=%s\n"
+ "NAS-IP-Address=127.0.0.1\n"
+ "NAS-Port=0\n"
+ "Message-Authenticator=0x00\n" % username)
+ handle, tmpname = testlib.mkstemp_fill(template, dir=self.tmpdir)
+ handle.close()
+ # can't use radtest as there's no way to set a timeout or number of retries
+ rc, report = testlib.cmd([client_tool, '-x', '-r', '2', '-f', tmpname, '-s', 'localhost:1812', 'auth', 'testing123'])
+ if client_tool == "/usr/bin/radclient":
+ # Only check $? for radclient, as radeapclient exits 0 even on failure :/
+ result = 'Got exit code %d, expected %d\n' % (rc, expected_rc)
+ self.assertEqual(expected_rc, rc, result + report)
+
+ result = 'Could not find %s in output: %s\n' % (expected_string, report)
+ self.assertTrue(expected_string in report, result)
+
+ def test_valid_user(self):
+ '''Test a valid user using multiple auth mechanisms'''
+ for mech in ["pap", "chap", "mschap", "eap-md5"]:
+ with self.subTest(mech=mech):
+ self._test_auth(self.test_user, self.test_pass, self.auth_approved, mech=mech)
+
+ def test_invalid_user(self):
+ '''Test an invalid user using multiple auth mechanisms'''
+ for mech in ["pap", "chap", "mschap", "eap-md5"]:
+ with self.subTest(mech=mech):
+ self._test_auth('xxubuntuxx', 'xxrocksxx', self.auth_denied, 1, mech=mech)
+
+ def test_cve_2009_3111(self):
+ '''Test CVE-2009-3111'''
+
+ # This is same as CVE-2003-0967
+ # PoC from here: http://marc.info/?l=bugtraq&m=106944220426970
+
+ # Send a crafted packet
+ kaboom = b"\x01\x01\x00\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x45\x02"
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(('localhost', 1812))
+ s.send(kaboom)
+ s.close()
+ time.sleep(1)
+
+ # See if it still works
+ self._test_auth(self.test_user, self.test_pass, self.auth_approved)
+
+if __name__ == '__main__':
+ # simple
+ unittest.main()