pyrad.dictionary – RADIUS dictionary

RADIUS uses dictionaries to define the attributes that can be used in packets. The Dictionary class stores the attribute definitions from one or more dictionary files in the FreeRADIUS format.

Dictionary files are text files with one command per line. Comments are specified by starting with a # character, and empty lines are ignored.

The commands supported are:

ATTRIBUTE <attribute> <code> <type> [<vendor>|<flags>]

Define an attribute and its data type. The code is decimal, or hexadecimal with a 0x prefix (octal with 0o), and <tlv code>.<code> for a sub-attribute of a TLV.

VALUE <attribute> <valuename> <value>

Define a named value of an attribute.

VENDOR <name> <id> [format=<t>,<l>]

Define a vendor and its ID. Only the RFC 2865 format format=1,1 (the default) is supported, the attributes of vendors with another format are skipped.

BEGIN-VENDOR <name> [format=<attribute>]

Begin the definition of the attributes of a vendor. The attributes of a block with a format= option are extended vendor-specific attributes (RFC 6929) and are skipped.

END-VENDOR <name>

End the definition of the attributes of a vendor.

$INCLUDE <filename>

Read another dictionary file. A relative file name is relative to the directory of the current file, or to the current working directory if the dictionary is read from a file-like object.

$INCLUDE- <filename>

Like $INCLUDE, but a file that doesn’t exist is ignored.

Other commands are ignored.

The attribute flags are a comma separated list of:

has_tag

The attribute is tagged (RFC 2868).

encrypt=1

User-Password encryption (RFC 2865 section 5.2). It is not applied automatically, see pyrad.packet.AuthPacket.PwCrypt() and pyrad.packet.AuthPacket.PwDecrypt().

encrypt=2

Salt encryption (RFC 2868 section 3.5), applied automatically.

encrypt=3

Ascend-Send-Secret encryption. Accepted, but not applied.

The FreeRADIUS flags secret, virtual and concat are accepted and ignored.

FreeRADIUS dictionaries also define attributes that pyrad cannot encode or decode. These are skipped with a warning, so that the FreeRADIUS dictionary files can be read as they are:

  • attributes of the data types vsa, extended, long-extended, evs (the RFC 6929 extended attributes), ipv4prefix, combo-ip, bool, uint16 and uint32, and their sub-attributes

  • attributes with the array flag

  • TLVs nested more than one level deep

  • attributes of vendors with a format other than format=1,1 (VENDOR)

  • vendor attributes in a BEGIN-VENDOR block with a format= option, which are extended vendor-specific attributes (RFC 6929)

VALUE definitions for skipped attributes are ignored, and VALUE definitions for unknown attributes are ignored with a warning. Received attributes that were skipped are decoded as undefined attributes.

The data types currently supported, and the Python values used for them in packets:

type

description

Python value

string

UTF-8 string

str or bytes, at most 253 octets encoded; a received value which is not valid UTF-8 is returned as bytes

ipaddr

IPv4 address

str, e.g. '192.0.2.1'

date

32 bits UNIX timestamp

int

octets

arbitrary binary data

bytes; a value starting with 0x is decoded from hex

abinary

Ascend binary filter

Ascend filter str, e.g. 'family=ipv4 action=accept direction=in'; received values are returned as bytes

ipv6addr

16 octets in network byte order

str or ipaddress.IPv6Address; received values are returned as str

ipv6prefix

up to 18 octets in network byte order

str 'address/length', e.g. '2001:db8::/32'

integer

32 bits unsigned number

int

signed

32 bits signed number

int

short

16 bits unsigned number

int

byte

8 bits unsigned number

int

integer64

64 bits unsigned number

int

tlv

nested type-length-value

set the sub-attributes by their names; reading the TLV returns a dict mapping sub-attribute names to lists of values

ifid

8 octets IPv6 interface identifier

str 'hhhh:hhhh:hhhh:hhhh', h being a hex digit

ether

6 octets Ethernet MAC address

str 'hh:hh:hh:hh:hh:hh', h being a hex digit, upper or lowercase

class pyrad.dictionary.ParseError(msg=None, **data)[source]

A dictionary file can’t be parsed.

Raised for syntax errors and recursive includes. Note that it is not a subclass of ValueError.

Variables:
  • msg (str) – error message

  • file (str) – name of the dictionary file, or ''

  • line (int) – line number on which the error occurred, or -1

class pyrad.dictionary.Dictionary(dict=None, *dicts)[source]

RADIUS dictionary.

Stores the vendors, attributes and their values defined in RADIUS dictionary files. Dictionary(path, *more) reads the files in order, see ReadDictionary(). dictionary['User-Name'] returns the Attribute of that name and 'User-Name' in dictionary checks whether it is defined.

Variables:
  • attributes (dict[str, Attribute]) – attributes by name

  • attrindex (pyrad.bidict.BiDict) – attribute names and the keys of the attributes in a packet: the code, (vendor, code) for a vendor attribute, (tlv code, code) for a sub-attribute and (vendor, tlv code, code) for a sub-attribute of a vendor TLV, with the vendor ID as vendor

  • vendors (pyrad.bidict.BiDict) – vendor names and IDs, '' is vendor 0

  • skipped_attributes (set[str]) – names of the attributes that were skipped because pyrad does not support them; using them raises a KeyError

Parameters:
  • dict (str or io.TextIOBase) – path of a dictionary file or file-like object to read

  • dicts (str or io.TextIOBase) – further dictionary files to read

ReadDictionary(file)[source]

Read a dictionary file.

Its definitions are merged into the dictionary; later definitions replace earlier ones. Unsupported attributes are skipped, listed in skipped_attributes, and reported with one warning on the pyrad logger.

Parameters:

file (str or io.TextIOBase) – path of a dictionary file or a file-like object

Raises:
  • ParseError – for a syntax error or a recursive include

  • OSError – if a file can’t be opened

class pyrad.dictionary.Attribute(name, code, datatype, is_sub_attribute=False, vendor='', values=None, encrypt=0, has_tag=False)[source]

The definition of an attribute in a Dictionary.

Raises ValueError for an unsupported data type.

Variables:
  • name (str) – name of the attribute

  • code (int) – attribute code, for a sub-attribute its code in the TLV

  • type (str) – data type, e.g. 'string'

  • vendor (str) – name of the vendor, '' for a standard attribute

  • encrypt (int) – encryption method of the encrypt= flag, 0 for none

  • has_tag (bool) – the attribute is tagged (RFC 2868)

  • values (pyrad.bidict.BiDict) – named values, mapping the name to the encoded value

  • sub_attributes (dict[int, str]) – names of the sub-attributes of a TLV by their code

  • parent (Attribute or None) – the TLV of a sub-attribute, else None

  • is_sub_attribute (bool) – the attribute is a sub-attribute of a TLV

class pyrad.bidict.BiDict[source]

A bidirectional mapping of keys to values and values to keys.

Used by pyrad.dictionary.Dictionary and pyrad.dictionary.Attribute. bidict[key] is GetForward(), len(bidict) the number of keys, and del bidict[key] removes a key or, if it isn’t a key, a value and all keys mapping to it.

Variables:
  • forward (dict) – the mapping of keys to values

  • backward (dict) – the mapping of values to keys

Add(one, two)[source]

Map the key one to the value two and two back to one.

Several keys may map to the same value (aliases), the value then maps back to the key added last. Re-adding a key with another value removes its old reverse entry.

GetBackward(key)[source]

Return the key of a value; raises KeyError if missing.

GetForward(key)[source]

Return the value of a key; raises KeyError if missing.

HasBackward(key)[source]

Return whether key is a value.

HasForward(key)[source]

Return whether key is a key.