def _radius_auth_func(self, server, **kwargs): """More private method used to authenticate a user and password against the current RADIUS server. Returns False if the user is rejected, True if the user is accepted. Raises CurrentServerFailed if there was an error with the request (such as a timeout).""" try: auth_port = self.server_dict[server]['auth_port'] secret = self.server_dict[server]['secret'] srv = Client(server=server, authport=auth_port, secret=secret, dict=self.dictionary) srv.timeout = self.server_timeout if self.client_bind_ip is not None: # Binding to port 0 is the official way to bind to a OS-assigned random port. srv.bind((self.client_bind_ip, 0)) req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name=kwargs['user'], NAS_Identifier=self.nas_identifier) req["User-Password"] = req.PwCrypt(kwargs['password']) reply = srv.SendPacket(req) if reply.code == pyrad.packet.AccessAccept: return True else: return False except (pyrad.packet.PacketError, pyrad.client.Timeout, socket.error): raise CurrentServerFailed
class SocketTests(unittest.TestCase): def setUp(self): self.server = object() self.client = Client(self.server) self.orgsocket = socket.socket socket.socket = MockSocket def tearDown(self): socket.socket = self.orgsocket def testReopen(self): self.client._SocketOpen() sock = self.client._socket self.client._SocketOpen() self.failUnless(sock is self.client._socket) def testBind(self): self.client.bind((BIND_IP, BIND_PORT)) self.assertEqual(self.client._socket.address, (BIND_IP, BIND_PORT)) self.assertEqual(self.client._socket.options, [(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)]) def testBindClosesSocket(self): s = MockSocket(socket.AF_INET, socket.SOCK_DGRAM) self.client._socket = s self.client.bind((BIND_IP, BIND_PORT)) self.assertEqual(s.closed, True) def testSendPacket(self): def MockSend(self, pkt, port): self._mock_pkt = pkt self._mock_port = port _SendPacket = Client._SendPacket Client._SendPacket = MockSend self.client.SendPacket(AuthPacket()) self.assertEqual(self.client._mock_port, self.client.authport) self.client.SendPacket(AcctPacket()) self.assertEqual(self.client._mock_port, self.client.acctport) Client._SendPacket = _SendPacket def testNoRetries(self): self.client.retries = 0 self.assertRaises(Timeout, self.client._SendPacket, None, None) def testSingleRetry(self): self.client.retries = 1 self.client.timeout = 0 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(self.client._socket.output, [("request packet", (self.server, 432))]) def testDoubleRetry(self): self.client.retries = 2 self.client.timeout = 0 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(self.client._socket.output, [("request packet", (self.server, 432)), ("request packet", (self.server, 432))]) def testAuthDelay(self): self.client.retries = 2 self.client.timeout = 1 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.failIf("Acct-Delay-Time" in packet) def testSingleAccountDelay(self): self.client.retries = 2 self.client.timeout = 1 packet = MockPacket(AccountingRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(packet["Acct-Delay-Time"], [1]) def testDoubleAccountDelay(self): self.client.retries = 3 self.client.timeout = 1 packet = MockPacket(AccountingRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(packet["Acct-Delay-Time"], [2]) def testIgnorePacketError(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("valid reply")) packet = MockPacket(AccountingRequest, verify=True, error=True) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) def testValidReply(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("valid reply")) packet = MockPacket(AccountingRequest, verify=True) reply = self.client._SendPacket(packet, 432) self.failUnless(reply is packet.reply) def testInvalidReply(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("invalid reply")) packet = MockPacket(AccountingRequest, verify=False) self.assertRaises(Timeout, self.client._SendPacket, packet, 432)
class SocketTests(unittest.TestCase): def setUp(self): self.server = object() self.client = Client(self.server) self.orgsocket = socket.socket socket.socket = MockSocket def tearDown(self): socket.socket = self.orgsocket def testReopen(self): self.client._SocketOpen() sock = self.client._socket self.client._SocketOpen() self.failUnless(sock is self.client._socket) def testBind(self): self.client.bind((BIND_IP, BIND_PORT)) self.assertEqual(self.client._socket.address, (BIND_IP, BIND_PORT)) self.assertEqual(self.client._socket.options, [(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)]) def testBindClosesSocket(self): s = MockSocket(socket.AF_INET, socket.SOCK_DGRAM) self.client._socket = s self.client._poll = MockPoll() self.client.bind((BIND_IP, BIND_PORT)) self.assertEqual(s.closed, True) def testSendPacket(self): def MockSend(self, pkt, port): self._mock_pkt = pkt self._mock_port = port _SendPacket = Client._SendPacket Client._SendPacket = MockSend self.client.SendPacket(AuthPacket()) self.assertEqual(self.client._mock_port, self.client.authport) self.client.SendPacket(AcctPacket()) self.assertEqual(self.client._mock_port, self.client.acctport) Client._SendPacket = _SendPacket def testNoRetries(self): self.client.retries = 0 self.assertRaises(Timeout, self.client._SendPacket, None, None) def testSingleRetry(self): self.client.retries = 1 self.client.timeout = 0 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(self.client._socket.output, [("request packet", (self.server, 432))]) def testDoubleRetry(self): self.client.retries = 2 self.client.timeout = 0 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(self.client._socket.output, [("request packet", (self.server, 432)), ("request packet", (self.server, 432))]) def testAuthDelay(self): self.client.retries = 2 self.client.timeout = 1 packet = MockPacket(AccessRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.failIf("Acct-Delay-Time" in packet) def testSingleAccountDelay(self): self.client.retries = 2 self.client.timeout = 1 packet = MockPacket(AccountingRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(packet["Acct-Delay-Time"], [1]) def testDoubleAccountDelay(self): self.client.retries = 3 self.client.timeout = 1 packet = MockPacket(AccountingRequest) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) self.assertEqual(packet["Acct-Delay-Time"], [2]) def testIgnorePacketError(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("valid reply")) packet = MockPacket(AccountingRequest, verify=True, error=True) self.assertRaises(Timeout, self.client._SendPacket, packet, 432) def testValidReply(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("valid reply")) self.client._poll = MockPoll() MockPoll.results = [(1, select.POLLIN)] packet = MockPacket(AccountingRequest, verify=True) reply = self.client._SendPacket(packet, 432) self.failUnless(reply is packet.reply) def testInvalidReply(self): self.client.retries = 1 self.client.timeout = 1 self.client._socket = MockSocket(1, 2, six.b("invalid reply")) MockPoll.results = [(1, select.POLLIN)] packet = MockPacket(AccountingRequest, verify=False) self.assertRaises(Timeout, self.client._SendPacket, packet, 432)
def ifAccountThread(): """Runs as a thread to account from traffic on an interface""" global _accountingInfo, _runIfAccount, nas_id, nas_ip global radius_update_interval, radius_acct_server, radius_auth_server try: # Is interface accounting enabled enabled = config_getboolean("accounting", "enabled", True) if not enabled: log_info("Interface accounting disabled.") return _runIfAccount = True # What interval shall we check hosts at check_interval = config_get("accounting", "check_interval", DEFAULT_CHECK_INTERVAL) radius_update_interval = config_getint("accounting", "update_interval", DEFAULT_UPDATE_INTERVAL) # Initialise the interface list default_user_file = "%s/accounting_users" % os.path.dirname(DEFAULT_CONFFILE) user_file = config_get("accounting", "user_file", default_user_file) if not os.path.exists(user_file): log_error("Interface accounting disabled. No user file: %s" % user_file) _runIfAccount = False return # Initialise the RADIUS connection try: dummy0 = getInterfaces(returnOne="dummy0")[0] dummy0ip = dummy0["address"].split("/")[0] except: log_error("Could not determine host loopback address!", sys.exc_info()) dummy0ip = "127.0.0.1" acct_server = config_get("accounting", "acct_server", "radius") acct_secret = config_get_required("accounting", "acct_secret") auth_server = config_get("accounting", "auth_server", "radius") auth_secret = config_get_required("accounting", "auth_secret") nas_id = config_get("accounting", "nas_id", getFQDN()) nas_ip = config_get("accounting", "nas_ip", dummy0ip) radius_acct_server = Client(server=acct_server, secret=acct_secret, dict=Dictionary(RADIUS_DICTIONARY)) radius_auth_server = Client(server=auth_server, secret=auth_secret, dict=Dictionary(RADIUS_DICTIONARY)) # FreeRADIUS at least auths based on IP address, make sure our # packets come from the right place radius_acct_server.bind((nas_ip, 0)) radius_auth_server.bind((nas_ip, 0)) # Read and parse the user file parseUserFile(user_file) # Initialise interface state initialiseInterfaceState() # Loop forever reading byte counters as appropriate while _runIfAccount: # wait a bit before checking time.sleep(check_interval) # Send any queued packets processRADIUSQueue() # Try and re-authenticate any dead interfaces for ifname, iface in _accountingInfo.items(): if iface["authenticated"]: continue age = time.time() - iface["last_auth_check"] if age > radius_update_interval: doRADIUSAuthentication(ifname) # Update traffic details updateTrafficCounters() # Generate interim-updates processInterimUpdates() except: (etype, value, tb) = sys.exc_info() log_error("Exception in interface accounting thread! - %s" % value, (etype, value, tb)) log_info("Exiting interface accounting thread")