pyradius / pyrad

Python RADIUS Implementation
BSD 3-Clause "New" or "Revised" License
294 stars 185 forks source link

Add salt decryption of encrypted attributes #163

Closed cspengl closed 2 years ago

cspengl commented 2 years ago

Description

This PR adds the ability to salt decrypt encrypted attributes. Therefore the pyrad.packet.Packet class got a new function following the example of pyrad.packet.Packet.SaltCrypt. In addition to that the internal _DecodeValue function got changed and now directly decrypts the attribute whenever a user tries to access an attribute value and the attribute has encrypt=2.

Motivation and Context

I just stumbled over an issue working with encrypted integer attributes which is basically reproducible by following code snippet.

from pyrad import dictionary, packet

attribute_dict = dictionary.Dictionary()
attribute_dict.attributes["Encrypted-Attribute"] = \
  dictionary.Attribute("Encrypted-Attribute", 1, 'integer', encrypt=2)

pkg = packet.Packet(code=1, secret=b'secret', dict=attribute_dict,
  Encrypted_Attribute=1
)
print(pkg['Encrypted-Attribute'])

Output:

Traceback (most recent call last):
  File "[...]/demo.py", line 9, in <module>
    print(pkg['Encrypted-Attribute'])
  File "[...]/lib/python3.9/site-packages/pyrad/packet.py", line 343, in __getitem__
    res.append(self._DecodeValue(attr, v))
  File "[...]/lib/python3.9/site-packages/pyrad/packet.py", line 247, in _DecodeValue
    return tools.DecodeAttr(attr.type, value)
  File "[...]/lib/python3.9/site-packages/pyrad/tools.py", line 216, in DecodeAttr
    return DecodeInteger(value)
  File "[...]/lib/python3.9/site-packages/pyrad/tools.py", line 172, in DecodeInteger
    return (struct.unpack(format, num))[0]
struct.error: unpack requires a buffer of 4 bytes

How has this been tested?

A added a new unit tests for testing encrypted attributes:

def testEncryptedAttributes(self):
        self.packet['Test-Encrypted-String'] = 'dummy'
        self.assertEqual(self.packet['Test-Encrypted-String'], ['dummy'])

        self.packet['Test-Encrypted-Integer'] = 10
        self.assertEqual(self.packet['Test-Encrypted-Integer'], [10])

Types of changes

Checklist: