Initial commit
This commit is contained in:
55
example/acct.py
Executable file
55
example/acct.py
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
import random
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad.client import Client
|
||||
from pyrad.dictionary import Dictionary
|
||||
|
||||
|
||||
def send_accounting_packet(srv, req):
|
||||
try:
|
||||
srv.SendPacket(req)
|
||||
except pyrad.client.Timeout:
|
||||
print('RADIUS server does not reply')
|
||||
sys.exit(1)
|
||||
except socket.error as error:
|
||||
print('Network error: ' + error[1])
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
srv = Client(server='127.0.0.1',
|
||||
secret=b'Kah3choteereethiejeimaeziecumi',
|
||||
dict=Dictionary(path_to_dictionary))
|
||||
|
||||
req = srv.CreateAcctPacket(**{
|
||||
'User-Name': 'wichert',
|
||||
'NAS-IP-Address': '192.168.1.10',
|
||||
'NAS-Port': 0,
|
||||
'NAS-Identifier': 'trillian',
|
||||
'Called-Station-Id': '00-04-5F-00-0F-D1',
|
||||
'Calling-Station-Id': '00-01-24-80-B3-9C',
|
||||
'Framed-IP-Address': '10.0.0.100',
|
||||
})
|
||||
|
||||
print('Sending accounting start packet')
|
||||
req['Acct-Status-Type'] = 'Start'
|
||||
send_accounting_packet(srv, req)
|
||||
|
||||
print('Sending accounting stop packet')
|
||||
req['Acct-Status-Type'] = 'Stop'
|
||||
req['Acct-Input-Octets'] = random.randrange(2**10, 2**30)
|
||||
req['Acct-Output-Octets'] = random.randrange(2**10, 2**30)
|
||||
req['Acct-Session-Time'] = random.randrange(120, 3600)
|
||||
req['Acct-Terminate-Cause'] = random.choice(['User-Request', 'Idle-Timeout'])
|
||||
send_accounting_packet(srv, req)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
53
example/auth.py
Executable file
53
example/auth.py
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad.client import Client
|
||||
from pyrad.dictionary import Dictionary
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
srv = Client(server='127.0.0.1',
|
||||
secret=b'Kah3choteereethiejeimaeziecumi',
|
||||
dict=Dictionary(path_to_dictionary))
|
||||
|
||||
req = srv.CreateAuthPacket(
|
||||
code=pyrad.packet.AccessRequest,
|
||||
**{
|
||||
'User-Name': 'wichert',
|
||||
'NAS-IP-Address': '192.168.1.10',
|
||||
'NAS-Port': 0,
|
||||
'Service-Type': 'Login-User',
|
||||
'NAS-Identifier': 'trillian',
|
||||
'Called-Station-Id': '00-04-5F-00-0F-D1',
|
||||
'Calling-Station-Id': '00-01-24-80-B3-9C',
|
||||
'Framed-IP-Address': '10.0.0.100',
|
||||
})
|
||||
|
||||
try:
|
||||
print('Sending authentication request')
|
||||
reply = srv.SendPacket(req)
|
||||
except pyrad.client.Timeout:
|
||||
print('RADIUS server does not reply')
|
||||
sys.exit(1)
|
||||
except socket.error as error:
|
||||
print('Network error: ' + error[1])
|
||||
sys.exit(1)
|
||||
|
||||
if reply.code == pyrad.packet.AccessAccept:
|
||||
print('Access accepted')
|
||||
else:
|
||||
print('Access denied')
|
||||
|
||||
print('Attributes returned by server:')
|
||||
for key, value in reply.items():
|
||||
print(f'{key} {value}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
102
example/auth_async.py
Executable file
102
example/auth_async.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from os import path
|
||||
|
||||
from pyrad.client_async import ClientAsync
|
||||
from pyrad.dictionary import Dictionary
|
||||
from pyrad.packet import AccessAccept
|
||||
|
||||
logging.basicConfig(level='DEBUG',
|
||||
format='%(asctime)s [%(levelname)-8s] %(message)s')
|
||||
|
||||
|
||||
def create_request(client, user):
|
||||
return client.CreateAuthPacket(**{
|
||||
'User-Name': user,
|
||||
'NAS-IP-Address': '192.168.1.10',
|
||||
'NAS-Port': 0,
|
||||
'Service-Type': 'Login-User',
|
||||
'NAS-Identifier': 'trillian',
|
||||
'Called-Station-Id': '00-04-5F-00-0F-D1',
|
||||
'Calling-Station-Id': '00-01-24-80-B3-9C',
|
||||
'Framed-IP-Address': '10.0.0.100',
|
||||
})
|
||||
|
||||
|
||||
def print_reply(reply):
|
||||
if reply.code == AccessAccept:
|
||||
print('Access accepted')
|
||||
else:
|
||||
print('Access denied')
|
||||
|
||||
print('Attributes returned by server:')
|
||||
for key, value in reply.items():
|
||||
print(f'{key}: {value}')
|
||||
|
||||
|
||||
def initialize_transport(loop, client):
|
||||
loop.run_until_complete(
|
||||
asyncio.ensure_future(
|
||||
client.initialize_transports(enable_auth=True,
|
||||
local_addr='127.0.0.1',
|
||||
local_auth_port=8000,
|
||||
enable_acct=True,
|
||||
enable_coa=True)))
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
client = ClientAsync(server='localhost',
|
||||
secret=b'Kah3choteereethiejeimaeziecumi',
|
||||
timeout=4,
|
||||
dict=Dictionary(path_to_dictionary))
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
try:
|
||||
# Initialize transports
|
||||
initialize_transport(loop, client)
|
||||
|
||||
requests = []
|
||||
for i in range(255):
|
||||
req = create_request(client, f'user{i}')
|
||||
future = client.SendPacket(req)
|
||||
requests.append(future)
|
||||
|
||||
# Send auth requests asynchronously to the server
|
||||
loop.run_until_complete(asyncio.ensure_future(
|
||||
asyncio.gather(
|
||||
*requests,
|
||||
return_exceptions=True
|
||||
)
|
||||
|
||||
))
|
||||
|
||||
for future in requests:
|
||||
if future.exception():
|
||||
print('EXCEPTION ', future.exception())
|
||||
else:
|
||||
reply = future.result()
|
||||
print_reply(reply)
|
||||
|
||||
# Close transports
|
||||
loop.run_until_complete(asyncio.ensure_future(
|
||||
client.deinitialize_transports()))
|
||||
print('END')
|
||||
except Exception as exc:
|
||||
print('Error: ', exc)
|
||||
traceback.print_exc()
|
||||
|
||||
# Close transports
|
||||
loop.run_until_complete(asyncio.ensure_future(
|
||||
client.deinitialize_transports()))
|
||||
|
||||
loop.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
78
example/client-coa.py
Executable file
78
example/client-coa.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright 6WIND, 2017
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad.dictionary import Dictionary
|
||||
from pyrad.server import Server, RemoteHost
|
||||
|
||||
|
||||
def print_attributes(packet):
|
||||
print('Attributes')
|
||||
for key, value in packet.items():
|
||||
print(f'{key}: {value}')
|
||||
|
||||
|
||||
class FakeCoA(Server):
|
||||
def HandleCoaPacket(self, packet):
|
||||
'''Accounting packet handler.
|
||||
Function that is called when a valid
|
||||
accounting packet has been received.
|
||||
|
||||
:param packet: packet to process
|
||||
:type packet: Packet class instance
|
||||
'''
|
||||
print('Received a coa request %d' % packet.code)
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
# try ACK or NACK
|
||||
# reply.code = packet.CoANAK
|
||||
reply.code = packet.CoAACK
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
def HandleDisconnectPacket(self, packet):
|
||||
print('Received a disconnect request %d' % packet.code)
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
# try ACK or NACK
|
||||
# reply.code = packet.DisconnectNAK
|
||||
reply.code = pyrad.packet.DisconnectACK
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
|
||||
def main(path_to_dictionary, coa_port):
|
||||
# create server/coa only and read dictionary
|
||||
# bind and listen only on 127.0.0.1:argv[1]
|
||||
coa = FakeCoA(
|
||||
addresses=['127.0.0.1'],
|
||||
dict=Dictionary(path_to_dictionary),
|
||||
coaport=coa_port,
|
||||
auth_enabled=False,
|
||||
acct_enabled=False,
|
||||
coa_enabled=True)
|
||||
|
||||
# add peers (address, secret, name)
|
||||
coa.hosts['127.0.0.1'] = RemoteHost(
|
||||
'127.0.0.1',
|
||||
b'Kah3choteereethiejeimaeziecumi',
|
||||
'localhost')
|
||||
|
||||
# start
|
||||
coa.Run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 2:
|
||||
print('usage: client-coa.py {portnumber}')
|
||||
sys.exit(1)
|
||||
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary, int(sys.argv[1]))
|
||||
51
example/coa.py
Executable file
51
example/coa.py
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad.client import Client
|
||||
from pyrad.dictionary import Dictionary
|
||||
|
||||
|
||||
def main(path_to_dictionary, coa_type, nas_identifier):
|
||||
# create coa client
|
||||
client = Client(server='127.0.0.1',
|
||||
secret=b'Kah3choteereethiejeimaeziecumi',
|
||||
dict=Dictionary(path_to_dictionary))
|
||||
|
||||
# set coa timeout
|
||||
client.timeout = 30
|
||||
|
||||
# create coa request packet
|
||||
attributes = {
|
||||
'Acct-Session-Id': '1337',
|
||||
'NAS-Identifier': nas_identifier,
|
||||
}
|
||||
|
||||
if coa_type == 'coa':
|
||||
# create coa request
|
||||
request = client.CreateCoAPacket(**attributes)
|
||||
elif coa_type == 'dis':
|
||||
# create disconnect request
|
||||
request = client.CreateCoAPacket(
|
||||
code=pyrad.packet.DisconnectRequest,
|
||||
**attributes)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
# send request
|
||||
result = client.SendPacket(request)
|
||||
print(result)
|
||||
print(result.code)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 3:
|
||||
print('usage: coa.py {coa|dis} daemon-1234')
|
||||
sys.exit(1)
|
||||
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
|
||||
main(dictionary, sys.argv[1], sys.argv[2])
|
||||
405
example/dictionary
Normal file
405
example/dictionary
Normal file
@@ -0,0 +1,405 @@
|
||||
#
|
||||
# Version $Id: dictionary,v 1.1.1.1 2002/10/11 12:25:39 wichert Exp $
|
||||
#
|
||||
# This file contains dictionary translations for parsing
|
||||
# requests and generating responses. All transactions are
|
||||
# composed of Attribute/Value Pairs. The value of each attribute
|
||||
# is specified as one of 4 data types. Valid data types are:
|
||||
#
|
||||
# string - 0-253 octets
|
||||
# ipaddr - 4 octets in network byte order
|
||||
# integer - 32 bit value in big endian order (high byte first)
|
||||
# date - 32 bit value in big endian order - seconds since
|
||||
# 00:00:00 GMT, Jan. 1, 1970
|
||||
#
|
||||
# FreeRADIUS includes extended data types which are not defined
|
||||
# in RFC 2865 or RFC 2866. These data types are:
|
||||
#
|
||||
# abinary - Ascend's binary filter format.
|
||||
# octets - raw octets, printed and input as hex strings.
|
||||
# e.g.: 0x123456789abcdef
|
||||
#
|
||||
#
|
||||
# Enumerated values are stored in the user file with dictionary
|
||||
# VALUE translations for easy administration.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# ATTRIBUTE VALUE
|
||||
# --------------- -----
|
||||
# Framed-Protocol = PPP
|
||||
# 7 = 1 (integer encoding)
|
||||
#
|
||||
|
||||
#
|
||||
# Include compatibility dictionary for older users file. Move this
|
||||
# directive to the end of the file if you want to see the old names
|
||||
# in the logfiles too.
|
||||
#
|
||||
#$INCLUDE dictionary.compat # compability issues
|
||||
#$INCLUDE dictionary.acc
|
||||
#$INCLUDE dictionary.ascend
|
||||
#$INCLUDE dictionary.bay
|
||||
#$INCLUDE dictionary.cisco
|
||||
#$INCLUDE dictionary.livingston
|
||||
#$INCLUDE dictionary.microsoft
|
||||
#$INCLUDE dictionary.quintum
|
||||
#$INCLUDE dictionary.redback
|
||||
#$INCLUDE dictionary.shasta
|
||||
#$INCLUDE dictionary.shiva
|
||||
#$INCLUDE dictionary.tunnel
|
||||
#$INCLUDE dictionary.usr
|
||||
#$INCLUDE dictionary.versanet
|
||||
#$INCLUDE dictionary.erx
|
||||
$INCLUDE dictionary.freeradius
|
||||
#$INCLUDE dictionary.alcatel
|
||||
|
||||
#
|
||||
# Following are the proper new names. Use these.
|
||||
#
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE User-Password 2 string
|
||||
ATTRIBUTE CHAP-Password 3 octets
|
||||
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
||||
ATTRIBUTE NAS-Port 5 integer
|
||||
ATTRIBUTE Service-Type 6 integer
|
||||
ATTRIBUTE Framed-Protocol 7 integer
|
||||
ATTRIBUTE Framed-IP-Address 8 ipaddr
|
||||
ATTRIBUTE Framed-IP-Netmask 9 ipaddr
|
||||
ATTRIBUTE Framed-Routing 10 integer
|
||||
ATTRIBUTE Filter-Id 11 string
|
||||
ATTRIBUTE Framed-MTU 12 integer
|
||||
ATTRIBUTE Framed-Compression 13 integer
|
||||
ATTRIBUTE Login-IP-Host 14 ipaddr
|
||||
ATTRIBUTE Login-Service 15 integer
|
||||
ATTRIBUTE Login-TCP-Port 16 integer
|
||||
ATTRIBUTE Reply-Message 18 string
|
||||
ATTRIBUTE Callback-Number 19 string
|
||||
ATTRIBUTE Callback-Id 20 string
|
||||
ATTRIBUTE Framed-Route 22 string
|
||||
ATTRIBUTE Framed-IPX-Network 23 ipaddr
|
||||
ATTRIBUTE State 24 octets
|
||||
ATTRIBUTE Class 25 octets
|
||||
ATTRIBUTE Vendor-Specific 26 octets
|
||||
ATTRIBUTE Session-Timeout 27 integer
|
||||
ATTRIBUTE Idle-Timeout 28 integer
|
||||
ATTRIBUTE Termination-Action 29 integer
|
||||
ATTRIBUTE Called-Station-Id 30 string
|
||||
ATTRIBUTE Calling-Station-Id 31 string
|
||||
ATTRIBUTE NAS-Identifier 32 string
|
||||
ATTRIBUTE Proxy-State 33 octets
|
||||
ATTRIBUTE Login-LAT-Service 34 string
|
||||
ATTRIBUTE Login-LAT-Node 35 string
|
||||
ATTRIBUTE Login-LAT-Group 36 octets
|
||||
ATTRIBUTE Framed-AppleTalk-Link 37 integer
|
||||
ATTRIBUTE Framed-AppleTalk-Network 38 integer
|
||||
ATTRIBUTE Framed-AppleTalk-Zone 39 string
|
||||
|
||||
ATTRIBUTE Acct-Status-Type 40 integer
|
||||
ATTRIBUTE Acct-Delay-Time 41 integer
|
||||
ATTRIBUTE Acct-Input-Octets 42 integer
|
||||
ATTRIBUTE Acct-Output-Octets 43 integer
|
||||
ATTRIBUTE Acct-Session-Id 44 string
|
||||
ATTRIBUTE Acct-Authentic 45 integer
|
||||
ATTRIBUTE Acct-Session-Time 46 integer
|
||||
ATTRIBUTE Acct-Input-Packets 47 integer
|
||||
ATTRIBUTE Acct-Output-Packets 48 integer
|
||||
ATTRIBUTE Acct-Terminate-Cause 49 integer
|
||||
ATTRIBUTE Acct-Multi-Session-Id 50 string
|
||||
ATTRIBUTE Acct-Link-Count 51 integer
|
||||
ATTRIBUTE Acct-Input-Gigawords 52 integer
|
||||
ATTRIBUTE Acct-Output-Gigawords 53 integer
|
||||
ATTRIBUTE Event-Timestamp 55 date
|
||||
|
||||
ATTRIBUTE CHAP-Challenge 60 string
|
||||
ATTRIBUTE NAS-Port-Type 61 integer
|
||||
ATTRIBUTE Port-Limit 62 integer
|
||||
ATTRIBUTE Login-LAT-Port 63 integer
|
||||
|
||||
ATTRIBUTE Acct-Tunnel-Connection 68 string
|
||||
|
||||
ATTRIBUTE ARAP-Password 70 string
|
||||
ATTRIBUTE ARAP-Features 71 string
|
||||
ATTRIBUTE ARAP-Zone-Access 72 integer
|
||||
ATTRIBUTE ARAP-Security 73 integer
|
||||
ATTRIBUTE ARAP-Security-Data 74 string
|
||||
ATTRIBUTE Password-Retry 75 integer
|
||||
ATTRIBUTE Prompt 76 integer
|
||||
ATTRIBUTE Connect-Info 77 string
|
||||
ATTRIBUTE Configuration-Token 78 string
|
||||
ATTRIBUTE EAP-Message 79 string
|
||||
ATTRIBUTE Message-Authenticator 80 octets
|
||||
ATTRIBUTE ARAP-Challenge-Response 84 string # 10 octets
|
||||
ATTRIBUTE Acct-Interim-Interval 85 integer
|
||||
ATTRIBUTE NAS-Port-Id 87 string
|
||||
ATTRIBUTE Framed-Pool 88 string
|
||||
ATTRIBUTE NAS-IPv6-Address 95 octets # really IPv6
|
||||
ATTRIBUTE Framed-Interface-Id 96 octets # 8 octets
|
||||
ATTRIBUTE Framed-IPv6-Prefix 97 ipv6prefix # stupid format
|
||||
ATTRIBUTE Login-IPv6-Host 98 octets # really IPv6
|
||||
ATTRIBUTE Framed-IPv6-Route 99 string
|
||||
ATTRIBUTE Framed-IPv6-Pool 100 string
|
||||
ATTRIBUTE Delegated-IPv6-Prefix 123 ipv6prefix
|
||||
|
||||
|
||||
ATTRIBUTE Digest-Response 206 string
|
||||
ATTRIBUTE Digest-Attributes 207 octets # stupid format
|
||||
|
||||
#
|
||||
# Experimental Non Protocol Attributes used by Cistron-Radiusd
|
||||
#
|
||||
|
||||
# These attributes CAN go in the reply item list.
|
||||
ATTRIBUTE Fall-Through 500 integer
|
||||
ATTRIBUTE Exec-Program 502 string
|
||||
ATTRIBUTE Exec-Program-Wait 503 string
|
||||
|
||||
# These attributes CANNOT go in the reply item list.
|
||||
ATTRIBUTE User-Category 1029 string
|
||||
ATTRIBUTE Group-Name 1030 string
|
||||
ATTRIBUTE Huntgroup-Name 1031 string
|
||||
ATTRIBUTE Simultaneous-Use 1034 integer
|
||||
ATTRIBUTE Strip-User-Name 1035 integer
|
||||
ATTRIBUTE Hint 1040 string
|
||||
ATTRIBUTE Pam-Auth 1041 string
|
||||
ATTRIBUTE Login-Time 1042 string
|
||||
ATTRIBUTE Stripped-User-Name 1043 string
|
||||
ATTRIBUTE Current-Time 1044 string
|
||||
ATTRIBUTE Realm 1045 string
|
||||
ATTRIBUTE No-Such-Attribute 1046 string
|
||||
ATTRIBUTE Packet-Type 1047 integer
|
||||
ATTRIBUTE Proxy-To-Realm 1048 string
|
||||
ATTRIBUTE Replicate-To-Realm 1049 string
|
||||
ATTRIBUTE Acct-Session-Start-Time 1050 date
|
||||
ATTRIBUTE Acct-Unique-Session-Id 1051 string
|
||||
ATTRIBUTE Client-IP-Address 1052 ipaddr
|
||||
ATTRIBUTE Ldap-UserDn 1053 string
|
||||
ATTRIBUTE NS-MTA-MD5-Password 1054 string
|
||||
ATTRIBUTE SQL-User-Name 1055 string
|
||||
ATTRIBUTE LM-Password 1057 octets
|
||||
ATTRIBUTE NT-Password 1058 octets
|
||||
ATTRIBUTE SMB-Account-CTRL 1059 integer
|
||||
ATTRIBUTE SMB-Account-CTRL-TEXT 1061 string
|
||||
ATTRIBUTE User-Profile 1062 string
|
||||
ATTRIBUTE Digest-Realm 1063 string
|
||||
ATTRIBUTE Digest-Nonce 1064 string
|
||||
ATTRIBUTE Digest-Method 1065 string
|
||||
ATTRIBUTE Digest-URI 1066 string
|
||||
ATTRIBUTE Digest-QOP 1067 string
|
||||
ATTRIBUTE Digest-Algorithm 1068 string
|
||||
ATTRIBUTE Digest-Body-Digest 1069 string
|
||||
ATTRIBUTE Digest-CNonce 1070 string
|
||||
ATTRIBUTE Digest-Nonce-Count 1071 string
|
||||
ATTRIBUTE Digest-User-Name 1072 string
|
||||
ATTRIBUTE Pool-Name 1073 string
|
||||
ATTRIBUTE Ldap-Group 1074 string
|
||||
ATTRIBUTE Module-Success-Message 1075 string
|
||||
ATTRIBUTE Module-Failure-Message 1076 string
|
||||
# X99-Fast 1077 integer
|
||||
|
||||
#
|
||||
# Non-Protocol Attributes
|
||||
# These attributes are used internally by the server
|
||||
#
|
||||
ATTRIBUTE Auth-Type 1000 integer
|
||||
ATTRIBUTE Menu 1001 string
|
||||
ATTRIBUTE Termination-Menu 1002 string
|
||||
ATTRIBUTE Prefix 1003 string
|
||||
ATTRIBUTE Suffix 1004 string
|
||||
ATTRIBUTE Group 1005 string
|
||||
ATTRIBUTE Crypt-Password 1006 string
|
||||
ATTRIBUTE Connect-Rate 1007 integer
|
||||
ATTRIBUTE Add-Prefix 1008 string
|
||||
ATTRIBUTE Add-Suffix 1009 string
|
||||
ATTRIBUTE Expiration 1010 date
|
||||
ATTRIBUTE Autz-Type 1011 integer
|
||||
|
||||
#
|
||||
# Integer Translations
|
||||
#
|
||||
|
||||
# User Types
|
||||
|
||||
VALUE Service-Type Login-User 1
|
||||
VALUE Service-Type Framed-User 2
|
||||
VALUE Service-Type Callback-Login-User 3
|
||||
VALUE Service-Type Callback-Framed-User 4
|
||||
VALUE Service-Type Outbound-User 5
|
||||
VALUE Service-Type Administrative-User 6
|
||||
VALUE Service-Type NAS-Prompt-User 7
|
||||
VALUE Service-Type Authenticate-Only 8
|
||||
VALUE Service-Type Callback-NAS-Prompt 9
|
||||
VALUE Service-Type Call-Check 10
|
||||
VALUE Service-Type Callback-Administrative 11
|
||||
|
||||
# Framed Protocols
|
||||
|
||||
VALUE Framed-Protocol PPP 1
|
||||
VALUE Framed-Protocol SLIP 2
|
||||
VALUE Framed-Protocol ARAP 3
|
||||
VALUE Framed-Protocol Gandalf-SLML 4
|
||||
VALUE Framed-Protocol Xylogics-IPX-SLIP 5
|
||||
VALUE Framed-Protocol X.75-Synchronous 6
|
||||
|
||||
# Framed Routing Values
|
||||
|
||||
VALUE Framed-Routing None 0
|
||||
VALUE Framed-Routing Broadcast 1
|
||||
VALUE Framed-Routing Listen 2
|
||||
VALUE Framed-Routing Broadcast-Listen 3
|
||||
|
||||
# Framed Compression Types
|
||||
|
||||
VALUE Framed-Compression None 0
|
||||
VALUE Framed-Compression Van-Jacobson-TCP-IP 1
|
||||
VALUE Framed-Compression IPX-Header-Compression 2
|
||||
VALUE Framed-Compression Stac-LZS 3
|
||||
|
||||
# Login Services
|
||||
|
||||
VALUE Login-Service Telnet 0
|
||||
VALUE Login-Service Rlogin 1
|
||||
VALUE Login-Service TCP-Clear 2
|
||||
VALUE Login-Service PortMaster 3
|
||||
VALUE Login-Service LAT 4
|
||||
VALUE Login-Service X25-PAD 5
|
||||
VALUE Login-Service X25-T3POS 6
|
||||
VALUE Login-Service TCP-Clear-Quiet 8
|
||||
|
||||
# Login-TCP-Port (see /etc/services for more examples)
|
||||
|
||||
VALUE Login-TCP-Port Telnet 23
|
||||
VALUE Login-TCP-Port Rlogin 513
|
||||
VALUE Login-TCP-Port Rsh 514
|
||||
|
||||
# Status Types
|
||||
|
||||
VALUE Acct-Status-Type Start 1
|
||||
VALUE Acct-Status-Type Stop 2
|
||||
VALUE Acct-Status-Type Interim-Update 3
|
||||
VALUE Acct-Status-Type Alive 3
|
||||
VALUE Acct-Status-Type Accounting-On 7
|
||||
VALUE Acct-Status-Type Accounting-Off 8
|
||||
# RFC 2867 Additional Status-Type Values
|
||||
VALUE Acct-Status-Type Tunnel-Start 9
|
||||
VALUE Acct-Status-Type Tunnel-Stop 10
|
||||
VALUE Acct-Status-Type Tunnel-Reject 11
|
||||
VALUE Acct-Status-Type Tunnel-Link-Start 12
|
||||
VALUE Acct-Status-Type Tunnel-Link-Stop 13
|
||||
VALUE Acct-Status-Type Tunnel-Link-Reject 14
|
||||
|
||||
# Authentication Types
|
||||
|
||||
VALUE Acct-Authentic RADIUS 1
|
||||
VALUE Acct-Authentic Local 2
|
||||
|
||||
# Termination Options
|
||||
|
||||
VALUE Termination-Action Default 0
|
||||
VALUE Termination-Action RADIUS-Request 1
|
||||
|
||||
# NAS Port Types
|
||||
|
||||
VALUE NAS-Port-Type Async 0
|
||||
VALUE NAS-Port-Type Sync 1
|
||||
VALUE NAS-Port-Type ISDN 2
|
||||
VALUE NAS-Port-Type ISDN-V120 3
|
||||
VALUE NAS-Port-Type ISDN-V110 4
|
||||
VALUE NAS-Port-Type Virtual 5
|
||||
VALUE NAS-Port-Type PIAFS 6
|
||||
VALUE NAS-Port-Type HDLC-Clear-Channel 7
|
||||
VALUE NAS-Port-Type X.25 8
|
||||
VALUE NAS-Port-Type X.75 9
|
||||
VALUE NAS-Port-Type G.3-Fax 10
|
||||
VALUE NAS-Port-Type SDSL 11
|
||||
VALUE NAS-Port-Type ADSL-CAP 12
|
||||
VALUE NAS-Port-Type ADSL-DMT 13
|
||||
VALUE NAS-Port-Type IDSL 14
|
||||
VALUE NAS-Port-Type Ethernet 15
|
||||
VALUE NAS-Port-Type xDSL 16
|
||||
VALUE NAS-Port-Type Cable 17
|
||||
VALUE NAS-Port-Type Wireless-Other 18
|
||||
VALUE NAS-Port-Type Wireless-802.11 19
|
||||
|
||||
# Acct Terminate Causes, available in 3.3.2 and later
|
||||
|
||||
VALUE Acct-Terminate-Cause User-Request 1
|
||||
VALUE Acct-Terminate-Cause Lost-Carrier 2
|
||||
VALUE Acct-Terminate-Cause Lost-Service 3
|
||||
VALUE Acct-Terminate-Cause Idle-Timeout 4
|
||||
VALUE Acct-Terminate-Cause Session-Timeout 5
|
||||
VALUE Acct-Terminate-Cause Admin-Reset 6
|
||||
VALUE Acct-Terminate-Cause Admin-Reboot 7
|
||||
VALUE Acct-Terminate-Cause Port-Error 8
|
||||
VALUE Acct-Terminate-Cause NAS-Error 9
|
||||
VALUE Acct-Terminate-Cause NAS-Request 10
|
||||
VALUE Acct-Terminate-Cause NAS-Reboot 11
|
||||
VALUE Acct-Terminate-Cause Port-Unneeded 12
|
||||
VALUE Acct-Terminate-Cause Port-Preempted 13
|
||||
VALUE Acct-Terminate-Cause Port-Suspended 14
|
||||
VALUE Acct-Terminate-Cause Service-Unavailable 15
|
||||
VALUE Acct-Terminate-Cause Callback 16
|
||||
VALUE Acct-Terminate-Cause User-Error 17
|
||||
VALUE Acct-Terminate-Cause Host-Request 18
|
||||
|
||||
#VALUE Tunnel-Type L2TP 3
|
||||
#VALUE Tunnel-Medium-Type IP 1
|
||||
|
||||
VALUE Prompt No-Echo 0
|
||||
VALUE Prompt Echo 1
|
||||
|
||||
#
|
||||
# Non-Protocol Integer Translations
|
||||
#
|
||||
|
||||
VALUE Auth-Type Local 0
|
||||
VALUE Auth-Type System 1
|
||||
VALUE Auth-Type SecurID 2
|
||||
VALUE Auth-Type Crypt-Local 3
|
||||
VALUE Auth-Type Reject 4
|
||||
VALUE Auth-Type ActivCard 5
|
||||
VALUE Auth-Type EAP 6
|
||||
VALUE Auth-Type ARAP 7
|
||||
|
||||
#
|
||||
# Cistron extensions
|
||||
#
|
||||
VALUE Auth-Type Ldap 252
|
||||
VALUE Auth-Type Pam 253
|
||||
VALUE Auth-Type Accept 254
|
||||
|
||||
VALUE Auth-Type PAP 1024
|
||||
VALUE Auth-Type CHAP 1025
|
||||
VALUE Auth-Type LDAP 1026
|
||||
VALUE Auth-Type PAM 1027
|
||||
VALUE Auth-Type MS-CHAP 1028
|
||||
VALUE Auth-Type Kerberos 1029
|
||||
VALUE Auth-Type CRAM 1030
|
||||
VALUE Auth-Type NS-MTA-MD5 1031
|
||||
VALUE Auth-Type CRAM 1032
|
||||
VALUE Auth-Type SMB 1033
|
||||
|
||||
#
|
||||
# Authorization type, too.
|
||||
#
|
||||
VALUE Autz-Type Local 0
|
||||
|
||||
#
|
||||
# Experimental Non-Protocol Integer Translations for Cistron-Radiusd
|
||||
#
|
||||
VALUE Fall-Through No 0
|
||||
VALUE Fall-Through Yes 1
|
||||
|
||||
VALUE Packet-Type Access-Request 1
|
||||
VALUE Packet-Type Access-Accept 2
|
||||
VALUE Packet-Type Access-Reject 3
|
||||
VALUE Packet-Type Accounting-Request 4
|
||||
VALUE Packet-Type Accounting-Response 5
|
||||
VALUE Packet-Type Accounting-Status 6
|
||||
VALUE Packet-Type Password-Request 7
|
||||
VALUE Packet-Type Password-Accept 8
|
||||
VALUE Packet-Type Password-Reject 9
|
||||
VALUE Packet-Type Accounting-Message 10
|
||||
VALUE Packet-Type Access-Challenge 11
|
||||
VALUE Packet-Type Status-Server 12
|
||||
VALUE Packet-Type Status-Client 13
|
||||
37
example/dictionary.freeradius
Normal file
37
example/dictionary.freeradius
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- text -*-
|
||||
# Copyright (C) 2015 The FreeRADIUS Server project and contributors
|
||||
#
|
||||
# The FreeRADIUS Vendor-Specific dictionary.
|
||||
#
|
||||
# Version: $Id: ea468da88509aeff96b6f0d38ebc97411b9775b3 $
|
||||
#
|
||||
# For a complete list of Private Enterprise Codes, see:
|
||||
#
|
||||
# http://www.isi.edu/in-notes/iana/assignments/enterprise-numbers
|
||||
#
|
||||
|
||||
VENDOR FreeRADIUS 11344
|
||||
|
||||
BEGIN-VENDOR FreeRADIUS
|
||||
|
||||
#
|
||||
# This attribute is really a bitmask.
|
||||
#
|
||||
ATTRIBUTE FreeRADIUS-Statistics-Type 127 integer
|
||||
|
||||
VALUE FreeRADIUS-Statistics-Type None 0
|
||||
VALUE FreeRADIUS-Statistics-Type Authentication 1
|
||||
VALUE FreeRADIUS-Statistics-Type Accounting 2
|
||||
VALUE FreeRADIUS-Statistics-Type Proxy-Authentication 4
|
||||
VALUE FreeRADIUS-Statistics-Type Proxy-Accounting 8
|
||||
VALUE FreeRADIUS-Statistics-Type Internal 0x10
|
||||
VALUE FreeRADIUS-Statistics-Type Client 0x20
|
||||
VALUE FreeRADIUS-Statistics-Type Server 0x40
|
||||
VALUE FreeRADIUS-Statistics-Type Home-Server 0x80
|
||||
|
||||
VALUE FreeRADIUS-Statistics-Type Auth-Acct 0x03
|
||||
VALUE FreeRADIUS-Statistics-Type Proxy-Auth-Acct 0x0c
|
||||
|
||||
VALUE FreeRADIUS-Statistics-Type All 0x1f
|
||||
|
||||
END-VENDOR FreeRADIUS
|
||||
77
example/server.py
Executable file
77
example/server.py
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
import logging
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad import server
|
||||
from pyrad.dictionary import Dictionary
|
||||
|
||||
logging.basicConfig(filename='pyrad.log', level='DEBUG',
|
||||
format='%(asctime)s [%(levelname)-8s] %(message)s')
|
||||
|
||||
|
||||
def print_attributes(packet):
|
||||
print('Attributes')
|
||||
for key, value in packet.items():
|
||||
print(f'{key}: {value}')
|
||||
|
||||
|
||||
class FakeServer(server.Server):
|
||||
def HandleAuthPacket(self, packet):
|
||||
print('Received an authentication request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet, **{
|
||||
'Service-Type': 'Framed-User',
|
||||
'Framed-IP-Address': '192.168.0.1',
|
||||
'Framed-IPv6-Prefix': 'fc66::/64'
|
||||
})
|
||||
|
||||
reply.code = pyrad.packet.AccessAccept
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
def HandleAcctPacket(self, packet):
|
||||
print('Received an accounting request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
def HandleCoaPacket(self, packet):
|
||||
print('Received an coa request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
def HandleDisconnectPacket(self, packet):
|
||||
print('Received an disconnect request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
# COA NAK
|
||||
reply.code = 45
|
||||
self.SendReplyPacket(packet.fd, reply)
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
# create server and read dictionary
|
||||
srv = FakeServer(dict=Dictionary(path_to_dictionary),
|
||||
coa_enabled=True)
|
||||
|
||||
# add clients (address, secret, name)
|
||||
srv.hosts['127.0.0.1'] = server.RemoteHost(
|
||||
'127.0.0.1',
|
||||
b'Kah3choteereethiejeimaeziecumi',
|
||||
'localhost')
|
||||
srv.BindToAddress('0.0.0.0')
|
||||
|
||||
# start server
|
||||
srv.Run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
115
example/server_async.py
Executable file
115
example/server_async.py
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
from os import path
|
||||
|
||||
from pyrad.dictionary import Dictionary
|
||||
from pyrad.packet import AccessAccept
|
||||
from pyrad.server_async import ServerAsync
|
||||
from pyrad.server import RemoteHost
|
||||
|
||||
try:
|
||||
import uvloop
|
||||
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
|
||||
except:
|
||||
pass
|
||||
|
||||
logging.basicConfig(level='DEBUG',
|
||||
format='%(asctime)s [%(levelname)-8s] %(message)s')
|
||||
|
||||
|
||||
def print_attributes(packet):
|
||||
print('Attributes returned by server:')
|
||||
for key, value in packet.items():
|
||||
print(f'{key}: {value}')
|
||||
|
||||
|
||||
class FakeServer(ServerAsync):
|
||||
def __init__(self, loop, dictionary):
|
||||
|
||||
ServerAsync.__init__(self, loop=loop, dictionary=dictionary,
|
||||
enable_pkt_verify=True, debug=True)
|
||||
|
||||
def handle_auth_packet(self, protocol, packet, addr):
|
||||
print('Received an authentication request with id ', packet.id)
|
||||
print('Authenticator ', packet.authenticator.hex())
|
||||
print('Secret ', packet.secret)
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet, **{
|
||||
'Service-Type': 'Framed-User',
|
||||
'Framed-IP-Address': '192.168.0.1',
|
||||
'Framed-IPv6-Prefix': 'fc66::/64'
|
||||
})
|
||||
|
||||
reply.code = AccessAccept
|
||||
protocol.send_response(reply, addr)
|
||||
|
||||
def handle_acct_packet(self, protocol, packet, addr):
|
||||
print('Received an accounting request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
protocol.send_response(reply, addr)
|
||||
|
||||
def handle_coa_packet(self, protocol, packet, addr):
|
||||
print('Received an coa request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
protocol.send_response(reply, addr)
|
||||
|
||||
def handle_disconnect_packet(self, protocol, packet, addr):
|
||||
print('Received an disconnect request')
|
||||
print_attributes(packet)
|
||||
|
||||
reply = self.CreateReplyPacket(packet)
|
||||
# COA NAK
|
||||
reply.code = 45
|
||||
protocol.send_response(reply, addr)
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
# create server and read dictionary
|
||||
loop = asyncio.get_event_loop()
|
||||
server = FakeServer(loop=loop, dictionary=Dictionary(path_to_dictionary))
|
||||
|
||||
# add clients (address, secret, name)
|
||||
server.hosts['127.0.0.1'] = RemoteHost('127.0.0.1',
|
||||
b'Kah3choteereethiejeimaeziecumi',
|
||||
'localhost')
|
||||
|
||||
try:
|
||||
# Initialize transports
|
||||
loop.run_until_complete(
|
||||
asyncio.ensure_future(
|
||||
server.initialize_transports(enable_auth=True,
|
||||
enable_acct=True,
|
||||
enable_coa=True)))
|
||||
|
||||
try:
|
||||
# start server
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
# Close transports
|
||||
loop.run_until_complete(asyncio.ensure_future(
|
||||
server.deinitialize_transports()))
|
||||
|
||||
except Exception as exc:
|
||||
print('Error: ', exc)
|
||||
traceback.print_exc()
|
||||
|
||||
# Close transports
|
||||
loop.run_until_complete(asyncio.ensure_future(
|
||||
server.deinitialize_transports()))
|
||||
|
||||
loop.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
42
example/status.py
Executable file
42
example/status.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
import socket
|
||||
import sys
|
||||
|
||||
from os import path
|
||||
|
||||
import pyrad.packet
|
||||
|
||||
from pyrad.client import Client
|
||||
from pyrad.dictionary import Dictionary
|
||||
|
||||
|
||||
def main(path_to_dictionary):
|
||||
srv = Client(server='localhost',
|
||||
authport=18121,
|
||||
secret=b'test',
|
||||
dict=Dictionary(path_to_dictionary))
|
||||
|
||||
req = srv.CreateAuthPacket(
|
||||
code=pyrad.packet.StatusServer,
|
||||
FreeRADIUS_Statistics_Type='All',
|
||||
)
|
||||
req.add_message_authenticator()
|
||||
|
||||
try:
|
||||
print('Sending FreeRADIUS status request')
|
||||
reply = srv.SendPacket(req)
|
||||
except pyrad.client.Timeout:
|
||||
print('RADIUS server does not reply')
|
||||
sys.exit(1)
|
||||
except socket.error as error:
|
||||
print('Network error: ' + error[1])
|
||||
sys.exit(1)
|
||||
|
||||
print('Attributes returned by server:')
|
||||
for key, value in reply.items():
|
||||
print(f'{key}: {value}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
dictionary = path.join(path.dirname(path.abspath(__file__)), 'dictionary')
|
||||
main(dictionary)
|
||||
Reference in New Issue
Block a user