save progress
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"""Collection of functions to deal with RADIUS packet en- and decoding."""
|
||||
|
||||
from collections import namedtuple
|
||||
from typing import List, Tuple, Union
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
import hashlib
|
||||
import secrets
|
||||
@@ -76,7 +76,7 @@ def parse_attributes(
|
||||
except (PacketError, IndexError):
|
||||
attributes.append(
|
||||
Attribute(
|
||||
name="Unknown-Vendor-Attribute",
|
||||
name="Unknown-Attribute",
|
||||
pos=offset,
|
||||
type="octets",
|
||||
length=int(packet[1]),
|
||||
@@ -100,7 +100,6 @@ def parse_vendor_attributes(
|
||||
vendor_id = int.from_bytes(vendor_value[:4], "big")
|
||||
vendor_dict = rad_dict.vendor[vendor_id]
|
||||
vendor_prefix = [26, vendor_id]
|
||||
vendor_name = vendor_dict.name
|
||||
|
||||
attributes = []
|
||||
vendor_tlv = vendor_value[4:]
|
||||
@@ -110,7 +109,7 @@ def parse_vendor_attributes(
|
||||
except struct.error:
|
||||
attribute = [
|
||||
Attribute(
|
||||
name=f"Unknown-{vendor_name}-Attribute",
|
||||
name="Unknown-Attribute",
|
||||
pos=offset - len(vendor_value),
|
||||
type="octets",
|
||||
length=len(vendor_value) - 4,
|
||||
@@ -176,20 +175,20 @@ def password_encode(
|
||||
"""Obfuscate the plaintext Password for RADIUS"""
|
||||
buf = password + b"\x00" * (16 - (len(password) % 16))
|
||||
last = authenticator
|
||||
results = []
|
||||
results = b""
|
||||
|
||||
while buf:
|
||||
cur_hash = MD5(secret + last).digest()
|
||||
tmp = [cbuf ^ chash for cbuf, chash in zip(buf, cur_hash)]
|
||||
tmp = bytes([cbuf ^ chash for cbuf, chash in zip(buf, cur_hash)])
|
||||
results += tmp
|
||||
(last, buf) = (bytes(tmp), buf[16:])
|
||||
(last, buf) = (tmp, buf[16:])
|
||||
|
||||
return bytes(results)
|
||||
return results
|
||||
|
||||
|
||||
def password_decode(
|
||||
secret: bytes, authenticator: bytes, obfuscated_password: bytes
|
||||
) -> str:
|
||||
) -> bytes:
|
||||
"""Reverse the RADIUS obfuscation on a given password
|
||||
|
||||
The password password is padded with \\x00 to a 16 byte boundary. The padding will
|
||||
@@ -206,7 +205,7 @@ def password_decode(
|
||||
results += [cbuf ^ chash for cbuf, chash in zip(buf, cur_hash)]
|
||||
(last, buf) = (buf[:16], buf[16:])
|
||||
|
||||
return bytes(results).rstrip(b"\x00").decode("utf-8")
|
||||
return bytes(results).rstrip(b"\x00")
|
||||
|
||||
|
||||
def create_chap_password(
|
||||
@@ -238,20 +237,29 @@ def validate_chap_password(
|
||||
)
|
||||
|
||||
|
||||
def salt_encrypt(secret: bytes, authenticator: bytes, value: bytes) -> bytes:
|
||||
def salt_encrypt(
|
||||
secret: bytes,
|
||||
authenticator: bytes,
|
||||
value: bytes,
|
||||
salt: Optional[int] = None,
|
||||
) -> bytes:
|
||||
"""Salt Encrypt the given value"""
|
||||
# The highest bit MUST be 1
|
||||
random_value = RANDOM_GENERATOR.randrange(32768, 65535)
|
||||
salt = struct.pack("!H", random_value)
|
||||
if salt is None:
|
||||
# The highest bit MUST be 1
|
||||
salt = RANDOM_GENERATOR.randrange(32768, 65535)
|
||||
|
||||
salted_auth = authenticator + salt
|
||||
bsalt = salt.to_bytes(2, "big")
|
||||
salted_auth = authenticator + bsalt
|
||||
prepared_value = len(value).to_bytes(1, "big") + value
|
||||
|
||||
return password_encode(secret, salted_auth, value)
|
||||
return bsalt + password_encode(secret, salted_auth, prepared_value)
|
||||
|
||||
|
||||
def salt_decrypt(
|
||||
secret: bytes, authenticator: bytes, salt: bytes, encrypted_value: bytes
|
||||
) -> str:
|
||||
secret: bytes, authenticator: bytes, encrypted_value: bytes, salt: int
|
||||
) -> bytes:
|
||||
"""Decrypt the given value"""
|
||||
salted_auth = authenticator + salt
|
||||
return password_decode(secret, salted_auth, encrypted_value)
|
||||
salted_auth = authenticator + salt.to_bytes(2, "big")
|
||||
decoded = password_decode(secret, salted_auth, encrypted_value)
|
||||
length = decoded[0] + 1
|
||||
return decoded[1:length]
|
||||
|
||||
Reference in New Issue
Block a user