Radius Authentication Server Project
We implement a simple Radius Authentication server, mostly compliant with the protocol given RFC 2865: Remote Authentication Dial In User Service
NAME mini-radius SYNOPSIS mini-radius [-vR -k shared-key -p port] -h host username password mini-radius [-vLR -k shared-key -p port] password-file DESCRIPTION The program runs as either client or server, depending on the whether the -h option is present. If server, the password-file is opened and the servers listens on the port of authentication requests. If client, the given username password is authenticated to the server/port as given in the option, and YES or NO is printed, according to the result. The protocol is described in RFC 2865, simplified for only password authentication. The access-request (code 1) packet sent by the client has two attributes, user-name (code 1) and user-password (code 2); and the response is either an access-accept (code 2) or an access-reject (code 3). The protocol is modified so that the client does not send the password, but the MD5 hash of the password. This simplifies our program by keeping the password attribute a fixed size; it also does not reveal the length of the password. The password file on the server stores MD5 hashes of the MD5 hash of the password, hence the authentication on the server is proof that the client knows the preimage of the has in the password file. OPTIONS -k the shared key for encrypting, the default is pa55word0 -p the port the server listens (is listening) on, the default is 1812 -h the radius server hostname -v Verbose. Helpful debugging output to stdout. -R no randomness. The stream of random bytes used by the program is set to 1, 2, 3, ... -L when run as a server, do not loop; answer one full request and terminate FILE FORMAT Username/Passwords are stored in file on the server. It is of the format (name:passwordhash\n)+ where name is a non-empty strings from (a-z, A-Z, 0-9)* and password hash is hexidecimal encoded, by default the MD5 hash of the password known to the user. BUGS The MD5 is not secure and should not be used. The username is not included in the reply packet and therefore not involved in the response authenticator. Since the encryption is malleable it is possible the server is authenticating the user of the attackers choice. The RFC allows a username attribute, but not the password attribute, in the reply packet, and perhaps should be required. Passwords in password file must be of format exactly [0-9a-f]{32}. HISTORY First introduced in Spring 2017. LAST UPDATED 26 March 2023
Detailed description
This is a simple one round protocol, consisting of the client leading off with a UDP packet to the server, and the server responding with a UDP packet back to the client. The server port is well-known, and the client port is ephemeral.
The initial packet from client to server is an Access-Request followed by an User-Name attribute and an User-Password attribute, in any order.
The response packet from server to client is an Access-Accept or an Access-Reject, as the case may be, with no attributes.
The Cryptography
The client must be assured that the server response is authentically from the server, and has not been replayed, modified, or forged. A form of Message Authentication Code (MAC) is used to cryptographically attest to the authenticity and integrity of the response.
The MAC is a signature on the return message based on a secret shared between the client and the server. Knowledge of the secret is required to correctly compute the MAC, it is exponentially unlikely to guess the MAC, and computationally infeasible to forge a MAC if the secret is unknown. It is important to calculate this MAC precisely. The formula is in Section 3, paragraph Response-Authenticator.
Response Authenticator The value of the Authenticator field in Access-Accept, Access- Reject, and Access-Challenge packets is called the Response Authenticator, and contains a one-way MD5 hash calculated over a stream of octets consisting of: the RADIUS packet, beginning with the Code field, including the Identifier, the Length, the Request Authenticator field from the Access-Request packet, and the response Attributes, followed by the shared secret. That is, ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) where + denotes concatenation.
The password is encrypted using a Vernon Cipher, see the User-Password attribute, section 5.2.
On transmission, the password is hidden. The password is first padded at the end with nulls to a multiple of 16 octets. A one- way MD5 hash is calculated over a stream of octets consisting of the shared secret followed by the Request Authenticator. This value is XORed with the first 16 octet segment of the password and placed in the first 16 octets of the String field of the User- Password Attribute.
A pseudo-random pad (key stream) is needed for the Vernum cipher. The pad is computed by both the client and server by hasing the concatenation of secret shared key and the Request-Authenticator by the MD5 hash function. The MD5 hash function is cryptographically strong — i.e. there is strong circumstantial evidence that the function acts as if it is assigning a randomly chosen output for each input.
The openssl library has the MD5 function, see [man 3 md5].
Authentication Logic
The system includes a double hashing of the password that the user has memorized. The first is just a convenience hash. Call the the password-hash. Windows has the NT-Hash that is how the password is stored in the SAM. It is not the same system as the unix hash.
The second has is the unix-type hash, and the result of the second has is stored in the password file. Proof of identity is that the hash of what is received from the client matches this hash in the password file.
______ request / pw | packet +--+ | file | | | +------+ | | | +-+ | | +-+ | |/| | | |/| +-----+ +-----+ user-name ------------------------->|/| ======> |/|--->| SEL |--->| ==? |---> Y/N |/| | | |/| +-----+ +-----+ +-+ | | +-+ ^ | | | +-+ | | +-+ | +-----+ +-----+ |/| | | |/| +-----+ +----+ user-passwd --->| MD5 |--->| ENC |--->|/| ======> |/|--->| ENC |--->| MD5 | +-----+ +-----+ |/| | | |/| +-----+ +----+ ^ ^ + + | | +-+ ^ ^ | | | | | | shared-key --+ | +-+ | | +-+ | +-- shared-key | |/| | | |/| | auth request ---------------+----->|/| ======> |/|------+ |/| | | |/| +-+ | | +-+ | | MD5 - hash function | | the request packet includes user-name, ENC - encryption +--+ encrypted user-passd, auth request SEL - select pw by username chosen randomly, and the header: code, ID and length.
MAC Calculation
+-+ | | +-+ +-------+ +-+ | | +-+ ACC_REQ |/| | | |/| | Auth | |/| | | |/| ACC_ACE/ACC_REJ Id |/| ======> |/| | Dec- | |/|---+------->|/| Id Length |/| | | |/| | ision | |/| | | | |/| Length +-+ | | +-+ +-------+ +-+ | | | +-+ | | | | | | | +---------------+ | | +-+ | | | ++ | | +-+ | | | | | | \ | | | | Request | | | | 128 +-->| \ 128 | | | | Response Authenti. | | ==========/===========>|MD5\ ==/===========>| | Authenticator | | | | +------->| / | | | | | | | | | | / | | | | +-+ | | +------------+ | / | | +-+ | | | shared key | ++ +----------+ | | +------------+ | username | -------------------------> attributes +----------+ | | in +----------+ | | any | pw (enc) | -------------------------> order +----------+ | |
The Attributes
Requests from client to server and responses from server to client can carry additional information in the sequence of attributes following the fixed format of the beginning of the packet. In our case, the request includes the user-name and password attribute, and the response carries no attributes.
The attributes have a common format, and can occur in any order. In our implementation the type will be either 1 for username or 2 for password.
0 1 2 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | Type | Length | String ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Author: Burton Rosenberg
Created: 28 March 2017
Last Update: 3 April 2023