

              Finite State Machine (FSM) Information for RADIUS


  The Finite State Machine (FSM) addition to RADIUS evolved from a need to
have a method of calling more than one Authentication/Authorization Transfer
Vector (AATV) action function in order to handle an incoming request.  So,
it may be said the RADIUS FSM depends on the RADIUS AATV concept.  In fact,
the AATV concept predates the FSM concept by only a few months, since it was
always felt that the two would indeed "play" together.

  For more information on the AATV concept, see the "aatv.txt" file in this
RADIUS distribution.  An AATV action function is a normal C function which
performs some algorithm needed to process an authentication, authorization
or accounting RADIUS request.  Each AATV has a unique, 32 character maximum,
identifier or name.  It is the AATV name which is known to the RADIUS FSM
and little else.

  The FSM is part of the RADIUS server mainline or engine.  Incoming socket
requests generate "events" which are small integers used to discriminate one
event from amongst many.  The FSM is basically an infinite while loop which
controls the execution of one or more AATV action functions, in turn, as is
dictated by: incoming events, the results of previous "states" in the FSM
(also modeled as events) and the structure of the FSM configuration table
(usually "radius.fsm" but this is configurable, too!).

  The configuration table (or FSM table) is read into memory at initialization
and whenever a UNIX HUP signal is received by the RADIUS server.  The syntax
of the FSM table is one or more entries, where each entry describes one state.
Comments are allowed in this file in the form of arbitrary lines of text which
begin with the pound sign ("#") character.  Any such comment lines are ignored.
The contents of the file are not case sensitive, as everything is converted to
uppercase when the file is parsed.  The state name for each entry is followed
by a colon (":") character and is normally the first (column one) and only item
on the line.  All subsequent lines, until the next state name is encountered,
are explicit ways to call AATV action functions from this state.

  Each such line consists of from three to five fields, the first three of
which are required while the last two are optional.  The fields are separated
from each other on each line with whitespace characters and should not start
in the first column.  The fields are named, in turn, the "event", the "action",
the "next state", and optionally, an integer and a string.  The optional last
two fields are used to pass an arbitrary, user specified integer and/or string,
respectively, to any AATV to use in whatever way it has been coded.

  The event field is actually a three-tuple which is used to identify an event.
The sub-fields of an event are: a state name, an AATV name and an event number.
Each of the three sub-fields are separated from each other with a period (".")
character.  The state name identifies which state generated this event.  The
AATV name is the name of the AATV which generated this event (from that state).
The event number is the "return code" from the named AATV, several of which are
listed at the end of this document.

  If a state has many such entries, a match on these three sub-fields with the
current incoming event will either select one of these entries or else match a
set of built-in events to determine which action to issue next.  The action
field names an AATV whose action function is to be invoked for the matching
event.  When that action function terminates, the FSM regains control and now
begins to process the entries of the state indicated in the "next state" field.

  It is an error, detected when the FSM configuration file is initially read
into memory, for a state to be defined, but never referenced.  It is also an
error if a next state is referenced, but never defined.  It is all right to
refer to a state which is not yet defined, but is defined in an entry found
later on in the configuration file.

  When the action function terminates in one of several different ways, it
returns an event number to the FSM which is used to select which event (of
several) in the next state to process next.  The FSM continues in this way
until the end of the FSM table is reached or a condition is reached in which
there is "nothing left to do" in the processing of the current request.  This
might happen if, for example, a remote request was indicated and the local
machine needed to wait for the results of the remote processing before it was
able to complete its processing.

  When an event is pending in this fashion an entry is placed on a linked list
of event structures which remembers the fact of the outstanding request.  This
list is used to help identify and match up incoming replies with outstanding
or pending requests and to perform any necessary re-sending of proxy requests
when duplicate requests are detected.  Note this event list based architecture
enables multiple RADIUS requests to be pending at once.  This capability allows
for redundant requests to be issued simultaneously and for timeouts of remote
requests to cause transmission of these requests to alternate servers, for
example.  Such actions are fairly easy to configure.

  The event list has entries for both socket and forking type activity.  For
the forking type, a match is made with the recorded PID of the forked child
process.  For the socket type, the match is made using the value of the state
from which the proxy request originated.  This requires that the proxy request
include the Proxy-State attribute-value pair containing the requesting server's
current state.  It also requires the remote RADIUS server to return, without
modification, this Proxy-State attribute-value pair in the RADIUS reply packet.

  Several different "utility" AATV concepts have been identified and made part
of the RADIUS server engine, for convenience.  The current list of AATV names
is given in a list at the end of this document.  Three of these utility AATVs
are associated with the event list mentioned above.  The NULL AATV causes the
event list to be ignored when a duplicate request is detected.  The REDO AATV
causes all pending events of the matching request to be re-issued.  The KILL
AATV causes the list of pending events to be cleared (here, all events are
assumed to be satisfied).

  Other utility AATVs perform other useful functions.  The PENDING AATV checks
if any events are still pending on the request's event list.  The TIMER AATV
sets a timer interval to an initial value.  The END AATV terminates the FSM
for this request.  The LOG AATV is used to log an error condition.  The REPLY
AATV is used to do whatever is needed to issue the reply or response to the
RADIUS request.  The TIMEOUT AATV simply logs the fact that a request on the
global request queue has timed out.

  Below is a diagram of the RADIUS finite state machine showing the entry and
exit points as well as various internal items and the internal control flow.

              +-----------------------------------------------+
              |                                               |
     request ---> do any initialization needed                |   E
              |                                               |
              |   create an auth_req structure                |   N
              |                                               |
              |   do duplicate detection                      |   G
              |                                               |
              |   create an event:                            |   I
              |                                               |
              |      AUTHEN, ACCT, PASSWD, AUTH_ONLY, etc.    |   N
              |                                               |
              |   call state_machine (event, auth_req) below  |   E
              |                                               |
              +-----------------------------------------------+
              |                                               |
event -->---> |  state_machine (integer event code,           |
        /     |                 auth. request pointer)        |
        |     |                                               |
        |     |  *** Decision Function based on FSM Table *** |
        |     |                                               |
        |     |  (action, next_state) = f (cur_state, event)  |
        |     |                                               |
        |     |        "cur_state" is a field in auth_req     |
        |     |                                               |
        |     |        "event" is the first argment above     |
        |     |                                               |
        |     |  set cur_state = next_state                   |
        |     |                                               |
        |     +-----------------------------------------------+
        |     |                                               |
        |     |          *** Take Action ***                  |
        |     |                                               |
        |     |  if (action .EQ. "NULL") exit state machine -------+
        |     |                                               |    |
        |     |  else, call AATV "action" function passing    |    |
        |     |                                               |    |
        |     |  to it the auth. request pointer "ap":        |    |
        |     |                                               |    |
        |     |      result = AATV->act_func (ap, ...)        |    |
        |     |                                               |    |
        |     |  where "result" is an integer event from      |    |
        |     |                                               |    |
        |     |  the set: [ACK, NAK, WAIT, ERROR, etc.]       |    |
        |     |                                               |    |
        |     |         loop within state machine             |    |
        |     |         ----------+--------------             |    |
        |     |                   |                           |    |
        |     +------------------ | --------------------------+    |
        |                         |                                v
        +-------------------------+         back to main engine select() loop

               Current List of Event Names and Their Meaning

    ACK          acknowledgment of the previous action
    NAK          negative acknowledgment of the previous action
    WAIT         the previous action generated a pending event
    ERROR        the previous action generated an error
    FATAL        the previous action generated a fatal error
    DUP          the incoming request is a duplicate
    TIMER        the timer value has expired
    TIMEOUT      the request has timed out due to inactivity
    AUTHEN       the incoming request is an Access-Request
    ACCT         the incoming request is an Accounting-Request
    PASSWD       the incoming request is a Passwd-Request
    REACCESS     the incoming request is is an Access-Request with State
    ACC_CHAL     the incoming request is and Access-Challenge
    MGT_POLL     the incoming request is is a Status-Server
    AUTH_ONLY    the incoming request is for Authentication-Only
    RC1          general purpose return code of one
    RC2          general purpose return code of two
    RC3          general purpose return code of three
    RC4          general purpose return code of four
    RC5          general purpose return code of five
    RC6          general purpose return code of six
    RC7          general purpose return code of seven
    RC8          general purpose return code of eight
    RC9          general purpose return code of nine
    RC10         general purpose return code of ten
    RC11         general purpose return code of eleven
    RC12         general purpose return code of twelve

               Current List of AATV Names and Their Purpose

    ACCT          the AATV for Accounting requests
    ACK           utility AATV used to always signify success
    AKERB         the AATV for AFS Kerberos Authentication
    AUTHENTICATE  the AATV for Authentication requests
    CLEANUP       utility AATV used to exit the FSM
    FILE          the AATV for FILE Authentication
    KCHAP         the AATV for KCHAP Authentication
    KILL          utility AATV used to unconditionally remove pending events
    LOG           utility AATV used to log some error
    MKERB         the AATV for MIT Kerberos Authentication
    NULL          utility NULL AATV
    PASSWD        the AATV for Passwd requests
    PENDING       utility AATV used to test for pending events
    RAD2RAD       the AATV used to send RADIUS proxy requests
    RADDNS        the AATV for resolving DNS names
    RADIUS        the main AATV in the RADIUS engine
    REALM         the AATV for handling realm based Authentication
    REDO          utility AATV used to re-invoke an action
    REPLY         utility AATV used to send a RADIUS reply
    SRV_STATUS    the AATV for Status-Server (Management-Poll) requests
    TACACS        the AATV for TACACS Authentication
    TIMEOUT       utility AATV used to do timeout logging
    TIMER         utility AATV used to initialize the timeout value
    UNIX-PW       the AATV for for UNIX password file Authentication
