pyrad 2.5.1__tar.gz → 2.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {pyrad-2.5.1 → pyrad-2.5.3}/CHANGES.rst +11 -0
  2. {pyrad-2.5.1 → pyrad-2.5.3}/LICENSE.txt +2 -2
  3. {pyrad-2.5.1/pyrad.egg-info → pyrad-2.5.3}/PKG-INFO +16 -15
  4. {pyrad-2.5.1 → pyrad-2.5.3}/README.rst +14 -9
  5. pyrad-2.5.3/docs/source/_static/logo.png +0 -0
  6. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/conf.py +11 -6
  7. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/index.rst +31 -2
  8. {pyrad-2.5.1 → pyrad-2.5.3}/pyproject.toml +8 -5
  9. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/__init__.py +1 -1
  10. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/bidict.py +1 -1
  11. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/client.py +1 -2
  12. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/dictfile.py +2 -3
  13. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/dictionary.py +1 -1
  14. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/host.py +1 -1
  15. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/packet.py +25 -42
  16. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_packet.py +13 -13
  17. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tools.py +3 -0
  18. {pyrad-2.5.1 → pyrad-2.5.3/pyrad.egg-info}/PKG-INFO +16 -15
  19. pyrad-2.5.3/pyrad.egg-info/requires.txt +1 -0
  20. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad.egg-info/top_level.txt +1 -0
  21. pyrad-2.5.1/docs/source/_static/logo.png +0 -0
  22. pyrad-2.5.1/pyrad.egg-info/requires.txt +0 -8
  23. {pyrad-2.5.1 → pyrad-2.5.3}/MANIFEST.in +0 -0
  24. {pyrad-2.5.1 → pyrad-2.5.3}/TODO.rst +0 -0
  25. {pyrad-2.5.1 → pyrad-2.5.3}/docs/Makefile +0 -0
  26. {pyrad-2.5.1 → pyrad-2.5.3}/docs/make.bat +0 -0
  27. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/client.rst +0 -0
  28. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/dictionary.rst +0 -0
  29. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/host.rst +0 -0
  30. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/packet.rst +0 -0
  31. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/proxy.rst +0 -0
  32. {pyrad-2.5.1 → pyrad-2.5.3}/docs/source/api/server.rst +0 -0
  33. {pyrad-2.5.1 → pyrad-2.5.3}/example/acct.py +0 -0
  34. {pyrad-2.5.1 → pyrad-2.5.3}/example/auth.py +0 -0
  35. {pyrad-2.5.1 → pyrad-2.5.3}/example/auth_async.py +0 -0
  36. {pyrad-2.5.1 → pyrad-2.5.3}/example/client-coa.py +0 -0
  37. {pyrad-2.5.1 → pyrad-2.5.3}/example/coa.py +0 -0
  38. {pyrad-2.5.1 → pyrad-2.5.3}/example/dictionary +0 -0
  39. {pyrad-2.5.1 → pyrad-2.5.3}/example/dictionary.freeradius +0 -0
  40. {pyrad-2.5.1 → pyrad-2.5.3}/example/pyrad.log +0 -0
  41. {pyrad-2.5.1 → pyrad-2.5.3}/example/server.py +0 -0
  42. {pyrad-2.5.1 → pyrad-2.5.3}/example/server_async.py +0 -0
  43. {pyrad-2.5.1 → pyrad-2.5.3}/example/status.py +0 -0
  44. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/client_async.py +0 -0
  45. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/curved.py +0 -0
  46. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/proxy.py +0 -0
  47. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/server.py +0 -0
  48. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/server_async.py +0 -0
  49. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/__init__.py +0 -0
  50. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/mock.py +0 -0
  51. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_bidict.py +0 -0
  52. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_client.py +0 -0
  53. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_dictionary.py +0 -0
  54. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_host.py +0 -0
  55. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_proxy.py +0 -0
  56. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_server.py +0 -0
  57. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad/tests/test_tools.py +0 -0
  58. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad.egg-info/SOURCES.txt +0 -0
  59. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad.egg-info/dependency_links.txt +0 -0
  60. {pyrad-2.5.1 → pyrad-2.5.3}/pyrad.egg-info/zip-safe +0 -0
  61. {pyrad-2.5.1 → pyrad-2.5.3}/setup.cfg +0 -0
@@ -1,6 +1,17 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ 2.5.3 - Feb 5, 2026
5
+ -------------------
6
+
7
+ * remove python2 leftovers
8
+ * add support for Ascend-Data-Filter "delete" keyword
9
+
10
+ 2.5.2 - Jan 29, 2026
11
+ --------------------
12
+
13
+ * Fix readthedocs
14
+
4
15
  2.5.1 - Jan 29, 2026
5
16
  --------------------
6
17
 
@@ -1,5 +1,5 @@
1
- Copyright 2020 Istvan Ruzman. All rights reserved.
2
- Copyright 2017-2026 Christian Giese. All rights reserved.
1
+ Copyright 2026 Christian Giese, Istvan Ruzman and Stefan Lieberth. All rights reserved.
2
+ Copyright 2002-2025 Christian Giese and Istvan Ruzman. All rights reserved.
3
3
  Copyright 2007-2008 Simplon. All rights reserved.
4
4
  Copyright 2002-2008 Wichert Akkerman. All rights reserved.
5
5
 
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrad
3
- Version: 2.5.1
3
+ Version: 2.5.3
4
4
  Summary: RADIUS tools
5
- Author-email: Istvan Ruzman <istvan@ruzman.eu>, Christian Giese <gic@gicnet.de>, Stefan Lieberth <stefan@lieberth.net>
5
+ Author-email: Christian Giese <gic@gicnet.de>, Istvan Ruzman <istvan@ruzman.eu>, Stefan Lieberth <stefan@lieberth.net>
6
6
  License: BSD-3-Clause
7
7
  Project-URL: Repository, https://github.com/pyradius/pyrad
8
8
  Project-URL: Documentation, https://pyradius-pyrad.readthedocs.io
@@ -23,10 +23,6 @@ Requires-Python: >=3.8
23
23
  Description-Content-Type: text/x-rst
24
24
  License-File: LICENSE.txt
25
25
  Requires-Dist: netaddr>=0.8.0
26
- Requires-Dist: six>=1.16.0
27
- Provides-Extra: test
28
- Requires-Dist: pytest>=8; extra == "test"
29
- Requires-Dist: mock; python_version < "3.10" and extra == "test"
30
26
  Dynamic: license-file
31
27
 
32
28
 
@@ -55,18 +51,24 @@ pyrad is an implementation of a RADIUS client/server as described in RFC2865.
55
51
  It takes care of all the details like building RADIUS packets, sending
56
52
  them and decoding responses.
57
53
 
58
- Here is an example of doing a authentication request::
54
+ Here is an example of doing a authentication request:
55
+
56
+ .. code-block:: python
59
57
 
60
58
  from pyrad.client import Client
61
59
  from pyrad.dictionary import Dictionary
62
60
  import pyrad.packet
63
61
 
64
- srv = Client(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi",
65
- dict=Dictionary("dictionary"))
62
+ srv = Client(
63
+ server="localhost",
64
+ secret=b"Kah3choteereethiejeimaeziecumi",
65
+ dict=Dictionary("dictionary"),
66
+ )
66
67
 
67
68
  # create request
68
- req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest,
69
- User_Name="wichert", NAS_Identifier="localhost")
69
+ req = srv.CreateAuthPacket(
70
+ code=pyrad.packet.AccessRequest, User_Name="wichert", NAS_Identifier="localhost"
71
+ )
70
72
  req["User-Password"] = req.PwCrypt("password")
71
73
 
72
74
  # send request
@@ -78,9 +80,8 @@ Here is an example of doing a authentication request::
78
80
  print("access denied")
79
81
 
80
82
  print("Attributes returned by server:")
81
- for i in reply.keys():
82
- print("%s: %s" % (i, reply[i]))
83
-
83
+ for key, val in reply.items():
84
+ print(f"{key}: {val}")
84
85
 
85
86
 
86
87
  Requirements & Installation
@@ -98,7 +99,7 @@ Author, Copyright, Availability
98
99
  ===============================
99
100
 
100
101
  pyrad was written by Wichert Akkerman <wichert@wiggy.net> and is maintained by
101
- Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
102
+ Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
102
103
 
103
104
  We’re looking for contributors to support the pyrad team! If you’re interested in
104
105
  helping with development, testing, documentation, or other areas, please contact
@@ -24,18 +24,24 @@ pyrad is an implementation of a RADIUS client/server as described in RFC2865.
24
24
  It takes care of all the details like building RADIUS packets, sending
25
25
  them and decoding responses.
26
26
 
27
- Here is an example of doing a authentication request::
27
+ Here is an example of doing a authentication request:
28
+
29
+ .. code-block:: python
28
30
 
29
31
  from pyrad.client import Client
30
32
  from pyrad.dictionary import Dictionary
31
33
  import pyrad.packet
32
34
 
33
- srv = Client(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi",
34
- dict=Dictionary("dictionary"))
35
+ srv = Client(
36
+ server="localhost",
37
+ secret=b"Kah3choteereethiejeimaeziecumi",
38
+ dict=Dictionary("dictionary"),
39
+ )
35
40
 
36
41
  # create request
37
- req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest,
38
- User_Name="wichert", NAS_Identifier="localhost")
42
+ req = srv.CreateAuthPacket(
43
+ code=pyrad.packet.AccessRequest, User_Name="wichert", NAS_Identifier="localhost"
44
+ )
39
45
  req["User-Password"] = req.PwCrypt("password")
40
46
 
41
47
  # send request
@@ -47,9 +53,8 @@ Here is an example of doing a authentication request::
47
53
  print("access denied")
48
54
 
49
55
  print("Attributes returned by server:")
50
- for i in reply.keys():
51
- print("%s: %s" % (i, reply[i]))
52
-
56
+ for key, val in reply.items():
57
+ print(f"{key}: {val}")
53
58
 
54
59
 
55
60
  Requirements & Installation
@@ -67,7 +72,7 @@ Author, Copyright, Availability
67
72
  ===============================
68
73
 
69
74
  pyrad was written by Wichert Akkerman <wichert@wiggy.net> and is maintained by
70
- Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
75
+ Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
71
76
 
72
77
  We’re looking for contributors to support the pyrad team! If you’re interested in
73
78
  helping with development, testing, documentation, or other areas, please contact
Binary file
@@ -57,16 +57,16 @@ author = u'Christian Giese <gic@gicnet.de>, Istvan Ruzman <istvan@ruzman.eu> and
57
57
  # built documents.
58
58
  #
59
59
  # The short X.Y version.
60
- version = u'2.5.1'
60
+ version = u'2.5.3'
61
61
  # The full version, including alpha/beta/rc tags.
62
- release = u'2.5.1'
62
+ release = u'2.5.3'
63
63
 
64
64
  # The language for content autogenerated by Sphinx. Refer to documentation
65
65
  # for a list of supported languages.
66
66
  #
67
67
  # This is also used if you do content translation via gettext catalogs.
68
68
  # Usually you set "language" from the command line for these cases.
69
- language = None
69
+ language = 'en'
70
70
 
71
71
  # List of patterns, relative to source directory, that match files and
72
72
  # directories to ignore when looking for source files.
@@ -84,13 +84,18 @@ todo_include_todos = True
84
84
  # The theme to use for HTML and HTML Help pages. See the documentation for
85
85
  # a list of builtin themes.
86
86
  #
87
- # html_theme = 'alabaster'
87
+ html_theme = 'sphinx_rtd_theme'
88
88
 
89
89
  # Theme options are theme-specific and customize the look and feel of a theme
90
90
  # further. For a list of options available for each theme, see the
91
91
  # documentation.
92
92
  #
93
- # html_theme_options = {}
93
+ html_theme_options = {
94
+ 'collapse_navigation': False,
95
+ 'sticky_navigation': True,
96
+ 'navigation_depth': 4,
97
+ 'style_external_links': False,
98
+ }
94
99
 
95
100
  # Add any paths that contain custom static files (such as style sheets) here,
96
101
  # relative to this directory. They are copied after the builtin static files,
@@ -129,7 +134,7 @@ latex_elements = {
129
134
  # author, documentclass [howto, manual, or own class]).
130
135
  latex_documents = [
131
136
  (master_doc, 'pyrad.tex', u'pyrad Documentation',
132
- u'Christian Giese and Istvan Ruzman', 'manual'),
137
+ u'Christian Giese, Istvan Ruzman and Stefan Lieberth', 'manual'),
133
138
  ]
134
139
 
135
140
 
@@ -3,7 +3,7 @@
3
3
  :mod:`pyrad` -- RADIUS for Python
4
4
  *********************************
5
5
 
6
- :Author: Wichert Akkerman
6
+ :Author: Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth)
7
7
  :Version: |version|
8
8
 
9
9
  Introduction
@@ -43,13 +43,42 @@ Here is an example of doing a authentication request::
43
43
  Requirements & Installation
44
44
  ===========================
45
45
 
46
- pyrad requires Python 3.6 or later
46
+ pyrad requires Python 3.8 or later
47
47
 
48
48
  Installing is simple; pyrad uses the standard distutils system for installing
49
49
  Python modules::
50
50
 
51
51
  python setup.py install
52
52
 
53
+ Author, Copyright, Availability
54
+ ===============================
55
+
56
+ pyrad was written by Wichert Akkerman <wichert@wiggy.net> and is maintained by
57
+ Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
58
+
59
+ We’re looking for contributors to support the pyrad team! If you’re interested in
60
+ helping with development, testing, documentation, or other areas, please contact
61
+ us directly.
62
+
63
+ This project is licensed under a BSD license.
64
+
65
+ Copyright and license information can be found in the LICENSE.txt file.
66
+
67
+ The current version and documentation can be found on pypi:
68
+ https://pypi.org/project/pyrad/
69
+
70
+ Bugs and wishes can be submitted in the pyrad issue tracker on github:
71
+ https://github.com/pyradius/pyrad/issues
72
+
73
+ Related Projects & Forks
74
+ ========================
75
+
76
+ **pyrad2:** Noteworthy fork with experimental RadSec (RFC 6614) support. Targets Python 3.12+,
77
+ adds extensive type hints, boosts test coverage, and includes fresh bug fixes.
78
+ https://github.com/nicholasamorim/pyrad2
79
+
80
+ **pyrad-server:** Lab-grade RADIUS test server built on top of pyrad.
81
+ https://github.com/slieberth/pyrad-server
53
82
 
54
83
  API Documentation
55
84
  =================
@@ -10,8 +10,8 @@ readme = "README.rst"
10
10
  license = { text = "BSD-3-Clause" }
11
11
  requires-python = ">=3.8"
12
12
  authors = [
13
- { name = "Istvan Ruzman", email = "istvan@ruzman.eu" },
14
13
  { name = "Christian Giese", email = "gic@gicnet.de" },
14
+ { name = "Istvan Ruzman", email = "istvan@ruzman.eu" },
15
15
  { name = "Stefan Lieberth", email = "stefan@lieberth.net" },
16
16
  ]
17
17
  keywords = ["radius", "authentication", "AAA", "accounting", "authorization", "RADIUS"]
@@ -32,13 +32,16 @@ classifiers = [
32
32
 
33
33
  dependencies = [
34
34
  "netaddr>=0.8.0",
35
- "six>=1.16.0",
36
35
  ]
37
36
 
38
- [project.optional-dependencies]
37
+ [dependency-groups]
39
38
  test = [
40
39
  "pytest>=8",
41
- "mock; python_version<'3.10'",
40
+ ]
41
+ docs = [
42
+ "sphinx>=7.0",
43
+ "sphinx-autodoc-typehints",
44
+ "sphinx-rtd-theme>=2.0"
42
45
  ]
43
46
 
44
47
  [project.urls]
@@ -51,7 +54,7 @@ include-package-data = true
51
54
  zip-safe = true
52
55
 
53
56
  [tool.pytest.ini_options]
54
- testpaths = ["tests"]
57
+ testpaths = ["pyrad/tests"]
55
58
  addopts = "-ra"
56
59
 
57
60
  [tool.setuptools.dynamic]
@@ -41,6 +41,6 @@ __docformat__ = 'epytext en'
41
41
  __author__ = 'Christian Giese <gic@gicnet.de>, Istvan Ruzman <istvan@ruzman.eu> and Stefan Lieberth <stefan@lieberth.net>'
42
42
  __url__ = 'http://pyrad.readthedocs.io/en/latest/?badge=latest'
43
43
  __copyright__ = 'Copyright 2002-2026 Wichert Akkerman, Christian Giese, Istvan Ruzman and Stefan Lieberth. All rights reserved.'
44
- __version__ = '2.5.1'
44
+ __version__ = '2.5.3'
45
45
 
46
46
  __all__ = ['client', 'dictionary', 'packet', 'server', 'tools', 'dictfile']
@@ -3,7 +3,7 @@
3
3
  # Bidirectional map
4
4
 
5
5
 
6
- class BiDict(object):
6
+ class BiDict:
7
7
  def __init__(self):
8
8
  self.forward = {}
9
9
  self.backward = {}
@@ -9,7 +9,6 @@ import select
9
9
  import socket
10
10
  import time
11
11
  import struct
12
- import six
13
12
  from pyrad import host
14
13
  from pyrad import packet
15
14
 
@@ -35,7 +34,7 @@ class Client(host.Host):
35
34
  :type timeout: float
36
35
  """
37
36
  def __init__(self, server, authport=1812, acctport=1813,
38
- coaport=3799, secret=six.b(''), dict=None, retries=3, timeout=5, enforce_ma=False):
37
+ coaport=3799, secret=b'', dict=None, retries=3, timeout=5, enforce_ma=False):
39
38
  """Constructor.
40
39
 
41
40
  :param server: hostname or IP address of RADIUS server
@@ -11,7 +11,7 @@ RADIUS $INCLUDE directives behind the scene.
11
11
  import os
12
12
 
13
13
 
14
- class _Node(object):
14
+ class _Node:
15
15
  """Dictionary file node
16
16
 
17
17
  A single dictionary file.
@@ -36,7 +36,7 @@ class _Node(object):
36
36
  return self.lines[self.current - 1]
37
37
 
38
38
 
39
- class DictFile(object):
39
+ class DictFile:
40
40
  """Dictionary file class
41
41
 
42
42
  An iterable file type that handles $INCLUDE
@@ -111,4 +111,3 @@ class DictFile(object):
111
111
  else:
112
112
  return line
113
113
  raise StopIteration
114
- next = __next__ # BBB for python <3
@@ -133,7 +133,7 @@ class Attribute(object):
133
133
  self.values.Add(key, value)
134
134
 
135
135
 
136
- class Dictionary(object):
136
+ class Dictionary:
137
137
  """RADIUS dictionary class.
138
138
  This class stores all information about vendors, attributes and their
139
139
  values as defined in RADIUS dictionary files.
@@ -4,7 +4,7 @@
4
4
  from pyrad import packet
5
5
 
6
6
 
7
- class Host(object):
7
+ class Host:
8
8
  """Generic RADIUS capable host.
9
9
 
10
10
  :ivar dict: RADIUS dictionary
@@ -6,9 +6,9 @@
6
6
 
7
7
  from collections import OrderedDict
8
8
  from pyrad import tools
9
+ import hashlib
9
10
  import hmac
10
11
  import struct
11
- import sys
12
12
 
13
13
  try:
14
14
  import secrets
@@ -18,24 +18,6 @@ except ImportError:
18
18
  random_generator = random.SystemRandom()
19
19
 
20
20
 
21
- def _hmac_md5(*args, **kwargs):
22
- """Py3 hmac.new() wrapper with explicit MD5 digestmod."""
23
- return hmac.new(*args, digestmod='MD5', **kwargs)
24
-
25
-
26
- if sys.version_info >= (3, 0):
27
- hmac_new = _hmac_md5
28
- else:
29
- hmac_new = hmac.new
30
-
31
- try:
32
- import hashlib
33
- md5_constructor = hashlib.md5
34
- except ImportError:
35
- # BBB for python 2.4
36
- import md5
37
- md5_constructor = md5.new
38
-
39
21
  # Packet codes
40
22
  AccessRequest = 1
41
23
  AccessAccept = 2
@@ -145,7 +127,7 @@ class Packet(OrderedDict):
145
127
  return self.message_authenticator
146
128
 
147
129
  def _refresh_message_authenticator(self):
148
- hmac_constructor = hmac_new(self.secret)
130
+ hmac_constructor = hmac.new(self.secret, digestmod='MD5')
149
131
 
150
132
  # Maintain a zero octets content for md5 and hmac calculation.
151
133
  self['Message-Authenticator'] = 16 * b'\00'
@@ -212,7 +194,7 @@ class Packet(OrderedDict):
212
194
  header = struct.pack('!BBH', self.code, self.id,
213
195
  (20 + len(attr)))
214
196
 
215
- hmac_constructor = hmac_new(key)
197
+ hmac_constructor = hmac.new(key, digestmod='MD5')
216
198
  hmac_constructor.update(header)
217
199
  if self.code in (AccountingRequest, DisconnectRequest,
218
200
  CoARequest, AccountingResponse):
@@ -419,8 +401,8 @@ class Packet(OrderedDict):
419
401
  attr = self._PktEncodeAttributes()
420
402
  header = struct.pack('!BBH', self.code, self.id, (20 + len(attr)))
421
403
 
422
- authenticator = md5_constructor(header[0:4] + self.authenticator
423
- + attr + self.secret).digest()
404
+ authenticator = hashlib.md5(header[0:4] + self.authenticator
405
+ + attr + self.secret).digest()
424
406
 
425
407
  return header + authenticator + attr
426
408
 
@@ -440,8 +422,8 @@ class Packet(OrderedDict):
440
422
  # response attributes if any, followed by the shared secret. The
441
423
  # resulting 16 octet MD5 hash value is stored in the Authenticator
442
424
  # field of the Accounting-Response packet.
443
- hash = md5_constructor(rawreply[0:4] + self.authenticator +
444
- rawreply[20:] + self.secret).digest()
425
+ hash = hashlib.md5(rawreply[0:4] + self.authenticator +
426
+ rawreply[20:] + self.secret).digest()
445
427
 
446
428
  if hash != rawreply[4:20]:
447
429
  return False
@@ -595,7 +577,7 @@ class Packet(OrderedDict):
595
577
  else:
596
578
  last = self.authenticator + salt
597
579
  while data:
598
- hash = md5_constructor(self.secret + last).digest()
580
+ hash = hashlib.md5(self.secret + last).digest()
599
581
  for i in range(16):
600
582
  result += bytes((hash[i] ^ data[i],))
601
583
 
@@ -707,11 +689,12 @@ class AuthPacket(Packet):
707
689
  header = struct.pack(
708
690
  '!BBH16s', self.code, self.id, (20 + 18 + len(attr)), self.authenticator
709
691
  )
710
- digest = hmac_new(
692
+ digest = hmac.new(
711
693
  self.secret,
712
694
  header
713
695
  + attr
714
696
  + struct.pack('!BB16s', 80, struct.calcsize('!BB16s'), b''),
697
+ digestmod='MD5'
715
698
  ).digest()
716
699
  return (
717
700
  header
@@ -743,7 +726,7 @@ class AuthPacket(Packet):
743
726
 
744
727
  last = self.authenticator
745
728
  while buf:
746
- hash = md5_constructor(self.secret + last).digest()
729
+ hash = hashlib.md5(self.secret + last).digest()
747
730
  for i in range(16):
748
731
  pw += bytes((hash[i] ^ buf[i],))
749
732
  (last, buf) = (buf[:16], buf[16:])
@@ -787,7 +770,7 @@ class AuthPacket(Packet):
787
770
 
788
771
  last = self.authenticator
789
772
  while buf:
790
- hash = md5_constructor(self.secret + last).digest()
773
+ hash = hashlib.md5(self.secret + last).digest()
791
774
  for i in range(16):
792
775
  result += bytes((hash[i] ^ buf[i],))
793
776
  last = result[-16:]
@@ -820,7 +803,7 @@ class AuthPacket(Packet):
820
803
  challenge = self.authenticator
821
804
  if 'CHAP-Challenge' in self:
822
805
  challenge = self['CHAP-Challenge'][0]
823
- return password == md5_constructor(chapid + userpwd + challenge).digest()
806
+ return password == hashlib.md5(chapid + userpwd + challenge).digest()
824
807
 
825
808
  def VerifyAuthRequest(self):
826
809
  """Verify request authenticator.
@@ -829,8 +812,8 @@ class AuthPacket(Packet):
829
812
  :rtype: boolean
830
813
  """
831
814
  assert (self.raw_packet)
832
- hash = md5_constructor(self.raw_packet[0:4] + 16 * b'\x00' +
833
- self.raw_packet[20:] + self.secret).digest()
815
+ hash = hashlib.md5(self.raw_packet[0:4] + 16 * b'\x00' +
816
+ self.raw_packet[20:] + self.secret).digest()
834
817
  return hash == self.authenticator
835
818
 
836
819
 
@@ -873,8 +856,8 @@ class AcctPacket(Packet):
873
856
  """
874
857
  assert (self.raw_packet)
875
858
 
876
- hash = md5_constructor(self.raw_packet[0:4] + 16 * b'\x00' +
877
- self.raw_packet[20:] + self.secret).digest()
859
+ hash = hashlib.md5(self.raw_packet[0:4] + 16 * b'\x00' +
860
+ self.raw_packet[20:] + self.secret).digest()
878
861
 
879
862
  return hash == self.authenticator
880
863
 
@@ -895,8 +878,8 @@ class AcctPacket(Packet):
895
878
 
896
879
  attr = self._PktEncodeAttributes()
897
880
  header = struct.pack('!BBH', self.code, self.id, (20 + len(attr)))
898
- self.authenticator = md5_constructor(header[0:4] + 16 * b'\x00' +
899
- attr + self.secret).digest()
881
+ self.authenticator = hashlib.md5(header[0:4] + 16 * b'\x00' +
882
+ attr + self.secret).digest()
900
883
 
901
884
  ans = header + self.authenticator + attr
902
885
 
@@ -941,8 +924,8 @@ class CoAPacket(Packet):
941
924
  :rtype: boolean
942
925
  """
943
926
  assert (self.raw_packet)
944
- hash = md5_constructor(self.raw_packet[0:4] + 16 * b'\x00' +
945
- self.raw_packet[20:] + self.secret).digest()
927
+ hash = hashlib.md5(self.raw_packet[0:4] + 16 * b'\x00' +
928
+ self.raw_packet[20:] + self.secret).digest()
946
929
  return hash == self.authenticator
947
930
 
948
931
  def RequestPacket(self):
@@ -960,14 +943,14 @@ class CoAPacket(Packet):
960
943
  self.id = self.CreateID()
961
944
 
962
945
  header = struct.pack('!BBH', self.code, self.id, (20 + len(attr)))
963
- self.authenticator = md5_constructor(header[0:4] + 16 * b'\x00' +
964
- attr + self.secret).digest()
946
+ self.authenticator = hashlib.md5(header[0:4] + 16 * b'\x00' +
947
+ attr + self.secret).digest()
965
948
 
966
949
  if self.message_authenticator:
967
950
  self._refresh_message_authenticator()
968
951
  attr = self._PktEncodeAttributes()
969
- self.authenticator = md5_constructor(header[0:4] + 16 * b'\x00' +
970
- attr + self.secret).digest()
952
+ self.authenticator = hashlib.md5(header[0:4] + 16 * b'\x00' +
953
+ attr + self.secret).digest()
971
954
 
972
955
  return header + self.authenticator + attr
973
956
 
@@ -1,3 +1,4 @@
1
+ import hashlib
1
2
  import hmac
2
3
  import os
3
4
  import struct
@@ -9,13 +10,6 @@ from collections import OrderedDict
9
10
  from pyrad import packet
10
11
  from pyrad.client import Client
11
12
  from pyrad.dictionary import Dictionary
12
- try:
13
- import hashlib
14
- md5_constructor = hashlib.md5
15
- except ImportError:
16
- # BBB for python 2.4
17
- import md5
18
- md5_constructor = md5.new
19
13
 
20
14
 
21
15
  class UtilityTests(unittest.TestCase):
@@ -106,17 +100,17 @@ class PacketTests(unittest.TestCase):
106
100
  request.id, (20 + len(attributes)))
107
101
 
108
102
  # Calculate the Message-Authenticator and update the attribute
109
- hmac_constructor = hmac.new(request.secret, None, md5_constructor)
103
+ hmac_constructor = hmac.new(request.secret, None, hashlib.md5)
110
104
  hmac_constructor.update(header + request.authenticator + attributes)
111
105
  updated_message_authenticator = hmac_constructor.digest()
112
106
  attributes = attributes.replace(b'\x00' * 16,
113
107
  updated_message_authenticator)
114
108
 
115
109
  # Calculate the response authenticator
116
- authenticator = md5_constructor(header
117
- + request.authenticator
118
- + attributes
119
- + request.secret).digest()
110
+ authenticator = hashlib.md5(header
111
+ + request.authenticator
112
+ + attributes
113
+ + request.secret).digest()
120
114
 
121
115
  reply_bytes = header + authenticator + attributes
122
116
  return packet.AuthPacket(packet=reply_bytes, dict=self.dict)
@@ -554,7 +548,7 @@ class AuthPacketChapTests(unittest.TestCase):
554
548
  def testVerifyChapPasswd(self):
555
549
  chap_id = b'9'
556
550
  chap_challenge = b'987654321'
557
- chap_password = chap_id + md5_constructor(
551
+ chap_password = chap_id + hashlib.md5(
558
552
  chap_id + b'test_password' + chap_challenge).digest()
559
553
  pkt = self.client.CreateAuthPacket(
560
554
  code=packet.AccessChallenge,
@@ -677,3 +671,9 @@ class AcctPacketTests(unittest.TestCase):
677
671
 
678
672
  # Vendor unknown preserved
679
673
  self.assertEqual(pkt[(594, 1)], [b'UNKNOWN_PRODUCT'])
674
+
675
+ raw_no_authenticator = raw[:4] + b"\x00" * 16 + raw[20:]
676
+ rebuilt = pkt.RequestPacket()
677
+ rebuilt_no_authenticator = rebuilt[:4] + b"\x00" * 16 + rebuilt[20:]
678
+
679
+ self.assertEqual(raw_no_authenticator, rebuilt_no_authenticator)
@@ -167,6 +167,9 @@ def EncodeAscendBinary(orig_str):
167
167
  "dportq": b"\x00",
168
168
  }
169
169
 
170
+ if orig_str.strip() == "delete":
171
+ return 8 * b"\x00"
172
+
170
173
  for t in orig_str.split(" "):
171
174
  key, value = t.split("=")
172
175
  if key == "family" and value == "ipv6":
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrad
3
- Version: 2.5.1
3
+ Version: 2.5.3
4
4
  Summary: RADIUS tools
5
- Author-email: Istvan Ruzman <istvan@ruzman.eu>, Christian Giese <gic@gicnet.de>, Stefan Lieberth <stefan@lieberth.net>
5
+ Author-email: Christian Giese <gic@gicnet.de>, Istvan Ruzman <istvan@ruzman.eu>, Stefan Lieberth <stefan@lieberth.net>
6
6
  License: BSD-3-Clause
7
7
  Project-URL: Repository, https://github.com/pyradius/pyrad
8
8
  Project-URL: Documentation, https://pyradius-pyrad.readthedocs.io
@@ -23,10 +23,6 @@ Requires-Python: >=3.8
23
23
  Description-Content-Type: text/x-rst
24
24
  License-File: LICENSE.txt
25
25
  Requires-Dist: netaddr>=0.8.0
26
- Requires-Dist: six>=1.16.0
27
- Provides-Extra: test
28
- Requires-Dist: pytest>=8; extra == "test"
29
- Requires-Dist: mock; python_version < "3.10" and extra == "test"
30
26
  Dynamic: license-file
31
27
 
32
28
 
@@ -55,18 +51,24 @@ pyrad is an implementation of a RADIUS client/server as described in RFC2865.
55
51
  It takes care of all the details like building RADIUS packets, sending
56
52
  them and decoding responses.
57
53
 
58
- Here is an example of doing a authentication request::
54
+ Here is an example of doing a authentication request:
55
+
56
+ .. code-block:: python
59
57
 
60
58
  from pyrad.client import Client
61
59
  from pyrad.dictionary import Dictionary
62
60
  import pyrad.packet
63
61
 
64
- srv = Client(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi",
65
- dict=Dictionary("dictionary"))
62
+ srv = Client(
63
+ server="localhost",
64
+ secret=b"Kah3choteereethiejeimaeziecumi",
65
+ dict=Dictionary("dictionary"),
66
+ )
66
67
 
67
68
  # create request
68
- req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest,
69
- User_Name="wichert", NAS_Identifier="localhost")
69
+ req = srv.CreateAuthPacket(
70
+ code=pyrad.packet.AccessRequest, User_Name="wichert", NAS_Identifier="localhost"
71
+ )
70
72
  req["User-Password"] = req.PwCrypt("password")
71
73
 
72
74
  # send request
@@ -78,9 +80,8 @@ Here is an example of doing a authentication request::
78
80
  print("access denied")
79
81
 
80
82
  print("Attributes returned by server:")
81
- for i in reply.keys():
82
- print("%s: %s" % (i, reply[i]))
83
-
83
+ for key, val in reply.items():
84
+ print(f"{key}: {val}")
84
85
 
85
86
 
86
87
  Requirements & Installation
@@ -98,7 +99,7 @@ Author, Copyright, Availability
98
99
  ===============================
99
100
 
100
101
  pyrad was written by Wichert Akkerman <wichert@wiggy.net> and is maintained by
101
- Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
102
+ Christian Giese (GIC-de), Istvan Ruzman (Istvan91) and Stefan Lieberth (slieberth).
102
103
 
103
104
  We’re looking for contributors to support the pyrad team! If you’re interested in
104
105
  helping with development, testing, documentation, or other areas, please contact
@@ -0,0 +1 @@
1
+ netaddr>=0.8.0
@@ -2,3 +2,4 @@ dist
2
2
  docs
3
3
  example
4
4
  pyrad
5
+ tmp
Binary file
@@ -1,8 +0,0 @@
1
- netaddr>=0.8.0
2
- six>=1.16.0
3
-
4
- [test]
5
- pytest>=8
6
-
7
- [test:python_version < "3.10"]
8
- mock
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes