Cisco IOS and Radius
+====================
-0. INTRODUCTION
+Introduction
+------------
Cisco NAS equipment has become quite popular of late, but being Cisco
equipment running IOS, the configuration can be a bit non-obvious to the
options to make your Ciscos interoperate with radius as you would expect a
well-behaved NAS to do.
-1. IOS 12.x
+IOS 12.x
+--------
For Cisco 12.x ( 12.0 and 12.1 ), the following AAA configuration directives
are suggested:
- aaa new-model
- aaa authentication login default group radius local
- aaa authentication login localauth local
- aaa authentication ppp default if-needed group radius local
- aaa authorization exec default group radius local
- aaa authorization network default group radius local
- aaa accounting delay-start
- aaa accounting exec default start-stop group radius
- aaa accounting network default start-stop group radius
- aaa processes 6
+::
+
+ aaa new-model
+ aaa authentication login default group radius local
+ aaa authentication login localauth local
+ aaa authentication ppp default if-needed group radius local
+ aaa authorization exec default group radius local
+ aaa authorization network default group radius local
+ aaa accounting delay-start
+ aaa accounting exec default start-stop group radius
+ aaa accounting network default start-stop group radius
+ aaa processes 6
this configuration works very well with most radius servers. One of the more
important configurations is:
- aaa accounting delay-start
+::
+
+ aaa accounting delay-start
This directive will delay the sending of the Accounting Start packet until
after an IP address has been assigned during the PPP negotiation process.
This will supersede the need to enable the sending of "Alive" packets as
described below for IOS versions 11.x
-*NOTE* with the above it will use the radius server to authenticate
+*Note* with the above it will use the radius server to authenticate
your inbound 'telnet' connections. You will need to create an entry
in your users file similar to the following to allow access:
- !root Cleartext-Password := "somepass"
- Service-Type = NAS-Prompt-User
+::
+
+ !root Cleartext-Password := "somepass" Service-Type = NAS-Prompt-User
This will let a user in for the first level of access to your Cisco. You
will still need to 'enable' ( using the locally configured enable secret )
of access. The username '!root' was used as an example here, you can make
this any username you want, of course.
-1.1 Unique Acct-Session-Id's
+Unique Acct-Session-Id's
+^^^^^^^^^^^^^^^^^^^^^^^^
From: http://isp-lists.isp-planet.com/isp-australia/0201/msg05143.html
Just a note to all cisco ISPs out there who want RFC2866 compliance need to
-enable the hidden command 'radius-server unique-ident <n>'
+enable the hidden command ``radius-server unique-ident <n>``
Minimum IOS: 12.1(4.1)T.
will observe after 10 minutes
of entering this command, the following message.
-%RADIUS-3-IDENTFAIL: Save of unique accounting ident aborted.
+::
+ %RADIUS-3-IDENTFAIL: Save of unique accounting ident aborted.
-2. IOS 11.x
+IOS 11.x
+--------
For Cisco 11.1, you normally use
- aaa new-model
- aaa authentication ppp radppp if-needed radius
- aaa authorization network radius none
- aaa accounting network wait-start radius
+::
+
+ aaa new-model
+ aaa authentication ppp radppp if-needed radius
+ aaa authorization network radius none
+ aaa accounting network wait-start radius
to get the Cisco to talk to a radius server.
-With IOS 11.3, you need to add:
+With IOS 11.3
+^^^^^^^^^^^^^
- aaa accounting update newinfo
+::
+
+ aaa accounting update newinfo
If you want the IP address of the user to show up in the radutmp file
(and thus, the output of "radwho").
packet without the IP address included. By setting "update newinfo" it
will send an account "Alive" packet which updates the information.
-
Also you might see a lot of "duplicates" in the logfile. That can be
-fixed by
+fixed by:
+
+::
- aaa accounting network wait radius
- radius-server timeout 3
+ aaa accounting network wait radius
+ radius-server timeout 3
+To disable the Ascend style attributes (which is a VERY good idea!):
-To enable the Ascend style attributes (which we do NOT recommend!)
+::
- radius-server host X.Y.Z.A auth-port 1645 acct-port 1646 non-standard
+ radius-server host X.Y.Z.A auth-port 1645 acct-port 1646
-To disable the Ascend style attributes (which is a VERY good idea!):
+To enable the Ascend style attributes (which we do NOT recommend!):
- radius-server host X.Y.Z.A auth-port 1645 acct-port 1646
+::
+
+ radius-server host X.Y.Z.A auth-port 1645 acct-port 1646 non-standard
To see Cisco-AVPair attributes in the Cisco debugging log:
- radius-server vsa accounting
+ radius-server vsa accounting
-4. Cisco 36xx & 26xx, keeping the NAS IP static
+Cisco 36xx & 26xx, keeping the NAS IP static
+--------------------------------------------
The Cisco 36/26 by default selects (it seems at random) any IP address
assigned to it (serial, ethernet etc.) as it's RADIUS client source
because it can not verify the client. To make the cisco box always use
one fixed address, add the following to your configuration:
- ip radius source-interface Loopback0
+::
+
+ ip radius source-interface Loopback0
and configure the loopback interface on your router as follows:
- interface Loopback0
- ip address 192.168.0.250 255.255.255.255
+::
+
+ interface Loopback0
+ ip address 192.168.0.250 255.255.255.255
Use a real world IP address and check the Cisco documentation for why
it is a good idea to have working loopback interface configured on
the source-interface to any interface on your Cisco box which has an
IP address.
-
-5. CREDITS
+Credits
+-------
Original - Alan DeKok <aland@ox.org>
12.x Info - Chris Parker <cparker@starnetusa.net> 2000-10-12
-6. MORE INFORMATION
-
+More Information
+----------------
For more information, the following page on Cisco's web site may help:
http://www.cisco.com/univercd/cc/td/doc/product/access/acs_serv/vapp_dev/vsaig3.htm
- Configurable Module Fail Over
- -----------------------------
+Configurable Module Fail Over
+=============================
Before configurable module failover, we had this kind of entry in
-"radiusd.conf":
-
-#---
-authorize {
- preprocess
- files
-}
-#---
-
- This entry instructed the "authorize" section to first process the
-request through the "preprocess" module, and if that returned success,
-to process it through "files" module. If that sequence returned
-success, then the "authorize" stage itself would then return success.
+``radiusd.conf``:
+
+::
+
+ #---
+ authorize {
+ preprocess
+ files
+ }
+ #---
+
+This entry instructed the ``authorize`` section to first process the
+request through the ``preprocess`` module, and if that returned success,
+to process it through ``files`` module. If that sequence returned
+success, then the ``authorize`` stage itself would then return success.
Processing was strictly linear and if one module failed, the whole
section would fail immediately.
- Configurable failover provides more flexibility. It takes advantage
+Configurable failover provides more flexibility. It takes advantage
of the tree structure of radiusd.conf to support a configuration
-language that allows you to "group" modules that should work together
+language that allows you to ``group`` modules that should work together
in ways other than simple lists. You can control the flow of any
-stage (e.g. "authorize") to fit your needs, without touching C code,
+stage (e.g. ``authorize``) to fit your needs, without touching C code,
just by altering radiusd.conf.
- This configurable fail-over has a convenient short-hand, too.
+This configurable fail-over has a convenient short-hand, too.
Administrators commonly want to say things like "try SQL1, if it's
down, try SQL2, otherwise drop the request."
- For example:
+For example:
+
+::
-#---
+ #---
modules {
sql sql1 {
# configuration to connect to SQL database one
sql1 # try module sql1
sql2 # if that's down, try module sql2
handled # otherwise drop the request as
- # it's been "handled" by the "always"
+ # it's been ``handled`` by the ``always``
# module (see doc/rlm_always)
}
}
-#---
+ #---
- The "redundant" section is a configuration directive which tells the
+The ``redundant`` section is a configuration directive which tells the
server to process the second module if the first one fails. Any
-number of modules can be listed in a "redundant" section. The server
-will process each in turn, until one of the modules succeeds. It willthen stop processing the "redundant" list.
+number of modules can be listed in a ``redundant`` section. The server
+will process each in turn, until one of the modules succeeds. It will then stop processing the ``redundant`` list.
-1. Rewriting results for single modules
- ------------------------------------
+Rewriting results for single modules
+------------------------------------
- Normally, when a module fails, the entire section ("authorize",
-"accounting", etc.) stops being processed. In some cases, we may want
-to permit "soft failures". That is, we may want to tell the server
+Normally, when a module fails, the entire section (``authorize``,
+``accounting``, etc.) stops being processed. In some cases, we may want
+to permit "soft failures". That is, we may want to tell the server
that it is "ok" for a module to fail, and that the failure should not
be treated as a fatal error.
- In this case, the module is treated as a "section", rather than just
-as a single line in "radiusd.conf". The configuration entries for
-that section are taken from the "configurable fail-over" code, and not
+In this case, the module is treated as a "section", rather than just
+as a single lne in ``radiusd.conf``. The configuration entries for
+that section are taken from the ``configurable fail-over`` code, and not
from the configuration information for that module.
- For example, the "detail" module normally returns "fail" if it is
-unable to write its information to the "detail" file. As a test, we
+For example, the ``detail`` module normally returns ``fail`` if it is
+unable to write its information to the ``detail`` file. As a test, we
can configure the server so that it continues processing the request,
-even if the "detail" module fails. The following example shows how:
+even if the ``detail`` module fails. The following example shows how:
-#--
+::
+
+ #--
# Handle accounting packets
accounting {
detail {
handled
}
}
-#--
-
- The "fail = 1" entry tells the server to remember the "fail" code,
-with priority "1". The normal configuration is "fail = return", which
-means "if the detail module fails, stop processing the accounting
-section".
-
-2. Fail-over configuration entries
- -------------------------------
-
- Modules normally return on of the following codes as their result:
-
- Code Meaning
- ---- ------
- notfound the user was not found
- noop the module did nothing
- ok the module succeeded
- updated the module updated information in the request
- fail the module failed
- reject the module rejected the user
- userlock the user was locked out
- invalid the user's configuration entry was invalid
- handled the module has done everything to handle the request
+ #--
+
+The ``fail = 1`` entry tells the server to remember the ``fail`` code,
+with priority ``1``. The normal configuration is ``fail = return``, which
+means ``if the detail module fails, stop processing the accounting
+section``.
+
+Fail-over configuration entries
+-------------------------------
+
+Modules normally return on of the following codes as their result:
+
++-----------+-----------------------------------------------------+
+|Code | Meaning |
++===========+=====================================================+
+|notfound | the user was not found |
++-----------+-----------------------------------------------------+
+|noop | the module did nothing |
++-----------+-----------------------------------------------------+
+|ok | the module succeeded |
++-----------+-----------------------------------------------------+
+|updated | the module updated information in the request |
++-----------+-----------------------------------------------------+
+|fail | the module failed |
++-----------+-----------------------------------------------------+
+|reject | the module rejected the user |
++-----------+-----------------------------------------------------+
+|userlock | the user was locked out |
++-----------+-----------------------------------------------------+
+|invalid | the user's configuration entry was invalid |
++-----------+-----------------------------------------------------+
+|handled | the module has done everything to handle the request|
++-----------+-----------------------------------------------------+
- In a configurable fail-over section, each of these codes may be
+In a configurable fail-over section, each of these codes may be
listed, with a value. If the code is not listed, or a configurable
fail-over section is not defined, then values that make sense for the
-requested "group" (group, redundant, load-balance, etc) are used.
+requested ``group`` (group, redundant, load-balance, etc) are used.
- The special code "default" can be used to set all return codes to
+The special code ``default`` can be used to set all return codes to
the specified value. This value will be used with a lower priority
than ones that are explicitly set.
- The values for each code may be one of two things:
+The values for each code may be one of two things:
- Value Meaning
- ----- -------
- <number> Priority for this return code.
- return stop processing this configurable fail-over list.
- reject Stop processing this configurable fail-over list.
- and immediately return a reject.
++---------+---------------------------------------------------------------+
+|Value | Meaning |
++=========+===============================================================+
+|<number> | Priority for this return code. |
++---------+---------------------------------------------------------------+
+|return | Stop processing this configurable fail-over list. |
++---------+---------------------------------------------------------------+
+|reject | Stop processing this configurable fail-over list and |
+| | immediately return a reject. |
++---------+---------------------------------------------------------------+
- The <number> used for a value may be any decimal number between 1
+The ``<number>`` used for a value may be any decimal number between 1
and 99999. The number is used when processing a list of modules, to
determine which code is returned from the list. For example, if
-"module1" returns "fail" with priority "1", and a later "module2"
-returns "ok" with priority "3", the return code from the list of
-modules will be "ok", because it has higher priority than "fail".
+``module1`` returns ``fail`` with priority ``1``, and a later ``module2``
+returns ``ok`` with priority ``3``, the return code from the list of
+modules will be ``ok``, because it has higher priority than ``fail``.
- This configurability allows the administrator to permit some modules
+This configurability allows the administrator to permit some modules
to fail, so long as a later module succeeds.
-3. More Complex Configurations
- ---------------------------
+More Complex Configurations
+---------------------------
- The "authorize" section is normally a list of module names. We can
-create sub-lists by using the section name "group". The "redundant"
-section above is just a short-hand for "group", with a set of default
-return codes, which are different than the normal "stop processing the
-list on failure".
+The ``authorize`` section is normally a list of module names. We can
+create sub-lists by using the section name ``group``. The ``redundant``
+section above is just a short-hand for ``group``, with a set of default
+return codes, which are different than the normal ``stop processing the
+list on failure``.
- For example, we can configure two detail modules, and allow either
+For example, we can configure two detail modules, and allow either
to fail, so long as one of them succeeds.
-#--
+::
+
+ #--
# Handle accounting packets
accounting {
group {
detail1 {
- fail = 1 # remember "fail" with priority 1
- ok = return # if we succeed, don't do "detail2"
+ fail = 1 # remember ``fail`` with priority 1
+ ok = return # if we succeed, don't do ``detail2``
}
detail2 {
- fail = 1 # remember "fail" with priority 1
- ok = return # if we succeed, return "ok"
- # if "detail1" returned "fail"
+ fail = 1 # remember ``fail`` with priority 1
+ ok = return # if we succeed, return ``ok``
+ # if ``detail1`` returned ``fail``
}
- } # returns "fail" only if BOTH modules returned "fail"
+ } # returns ``fail`` only if BOTH modules returned ``fail``
redundant {
sql1
sql2
handled
}
}
+ #--
-#--
+This configuration says:
- This configuration says:
+ - log to ``detail1``, and stop processing the ``group`` list if ``detail1`` returned OK.
- log to "detail1", and stop processing the "group" list if
- "detail1" returned OK.
+ - If ``detail1`` returned ``fail``, then continue, but remember the ``fail`` code, with priority 1.
- If "detail1" returned "fail", then continue, but remember the
- "fail" code, with priority 1.
+ - If ``detail2`` fails, then remember ``fail`` with priority 1.
- If "detail2" fails, then remember "fail" with priority 1.
+ - If ``detail2`` returned ``ok``, return ``ok`` from the ``group``.
- If "detail2" returned "ok", return "ok" from the "group".
-
- The return code from the "group" is the return code which was either
-forced to return (e.g. "ok" for "detail1"), or the highest priority
+The return code from the ``group`` is the return code which was either
+forced to return (e.g. ``ok`` for ``detail1``), or the highest priority
return code found by processing the list.
- This process can be extended to any number of modules listed in a
-"group" section.
+This process can be extended to any number of modules listed in a
+``group`` section.
-4. Virtual Modules
- ---------------
+Virtual Modules
+---------------
- Some configurations may require using the same list of modules, in
+Some configurations may require using the same list of modules, in
the same order, in multiple sections. For those systems, the
-configuration can be simplified through the use of "virtual" modules.
+configuration can be simplified through the use of ``virtual`` modules.
These modules are configured as named sub-sections of the
-"instantiate" section, as follows:
+``instantiate`` section, as follows:
+
+::
instantiate {
...
}
}
- The name "sql1_or_2" can then be used in any other section, such as
-"authorize" or "accounting". The result will be *exactly* as if that
-section was placed at the location of the "sql1_or_2" reference.
+The name ``sql1_or_2`` can then be used in any other section, such as
+``authorize`` or ``accounting``. The result will be *exactly* as if that
+section was placed at the location of the ``sql1_or_2`` reference.
- These virtual modules are full-fledged objects in and of themselves.
+These virtual modules are full-fledged objects in and of themselves.
One virtual module can refer to another virtual module, and they can
-contain "if" conditions, or any other configuration permitted in a
+contain ``if`` conditions, or any other configuration permitted in a
section.
-5. Redundancy and Load-Balancing
- -----------------------------
+Redundancy and Load-Balancing
+-----------------------------
- See "man unlang" or doc/load-balance.txt for information on simple
+See ``man unlang`` or ``doc/load-balance`` for information on simple
redundancy (fail-over) and load balancing.
-6. The Gory Details
- ----------------
+The Gory Details
+-----------------
The fundamental object is called a MODCALLABLE, because it is something that
can be passed a specific radius request and returns one of the RLM_MODULE_*
SINGLEs.
A SINGLE is a reference to a module instance that was set up in the modules{}
-section of radiusd.conf, like "preprocess" or "sql1". When a SINGLE is
+section of radiusd.conf, like ``preprocess`` or ``sql1``. When a SINGLE is
called, the corresponding function in the rlm is invoked, and whichever
RLM_MODULE_* it returns becomes the RESULT of the SINGLE.
A GROUP is a section of radiusd.conf that includes some MODCALLABLEs.
-Examples of GROUPs above include "authorize{...}", which implements the C
-function module_authorize, and "redundant{...}", which contains two SINGLEs
+Examples of GROUPs above include ``authorize{...}``, which implements the C
+function module_authorize, and ``redundant{...}``, which contains two SINGLEs
that refer to a couple of redundant databases. Note that a GROUP can contain
-other GROUPs - "Auth-Type SQL{...}" is also a GROUP, which implements the C
+other GROUPs - ``Auth-Type SQL{...}`` is also a GROUP, which implements the C
function module_authenticate when Auth-Type is set to SQL.
Now here's the fun part - what happens when a GROUP is called? It simply runs
through all of its children in order, and calls each one, whether it is
another GROUP or a SINGLE. It then looks at the RESULT of that child, and
-takes some ACTION, which is basically either "return that RESULT immediately"
-or "Keep going". In the first example, any "bad" RESULT from the preprocess
-module causes an immediate return, and any "good" RESULT causes the
+takes some ACTION, which is basically either ``return that RESULT immediately``
+or ``Keep going``. In the first example, any ``bad`` RESULT from the preprocess
+module causes an immediate return, and any ``good`` RESULT causes the
authorize{...} GROUP to proceed to the files module.
We can see the exact rules by writing them out the long way:
-authorize {
- preprocess {
- notfound = 1
- noop = 2
- ok = 3
- updated = 4
- fail = return
- reject = return
- userlock = return
- invalid = return
- handled = return
- }
- files {
- notfound = 1
- noop = 2
- ok = 3
- updated = 4
- fail = return
- reject = return
- userlock = return
- invalid = return
- handled = return
+::
+
+ authorize {
+ preprocess {
+ notfound = 1
+ noop = 2
+ ok = 3
+ updated = 4
+ fail = return
+ reject = return
+ userlock = return
+ invalid = return
+ handled = return
+ }
+ files {
+ notfound = 1
+ noop = 2
+ ok = 3
+ updated = 4
+ fail = return
+ reject = return
+ userlock = return
+ invalid = return
+ handled = return
+ }
}
-}
This is the same as the first example, with the behavior explicitly
spelled out. Each SINGLE becomes its own section, containing a list of
then the reject=return rule is applied, and the authorize{...} GROUP
itself immediately returns RLM_MODULE_REJECT.
-If preprocess returns RLM_MODULE_NOOP, the corresponding ACTION is "2". An
+If preprocess returns RLM_MODULE_NOOP, the corresponding ACTION is ``2``. An
integer ACTION serves two purposes - first, it tells the parent GROUP to go
on to the next module. Second, it is a hint as to how desirable this RESULT
is as a candidate for the GROUP's own RESULT. So files is called... suppose
it returns RLM_MODULE_NOTFOUND. The ACTION for notfound inside the files{...}
-block is "1". We have now reached the end of the authorize{...} GROUP and we
+block is ``1``. We have now reached the end of the authorize{...} GROUP and we
look at the RESULTs we accumulated along the way - there is a noop with
preference level 2, and a notfound with preference level 1, so the
authorize{...} GROUP as a whole returns RLM_MODULE_NOOP, which makes sense
because to say the user was not found at all would be a lie, since preprocess
apparently found him, or else it would have returned RLM_MODULE_NOTFOUND too.
-We could use the "default" code to simplify the above example a
+We could use the ``default`` code to simplify the above example a
little. The following two configurations are identical:
-...
+::
+
files {
notfound = 1
noop = 2
updated = 4
default = return
}
-...
-When putting the "default" first, later definitions over-ride it's
+
+When putting the ``default`` first, later definitions over-ride it's
return code:
-...
+::
+
files {
default = return
notfound = 1
ok = 3
updated = 4
}
-...
-
[Take a deep breath - the worst is over]
So where does redundant{...} fit in with all that? Well, redundant{...} is
simply a group that changes the default ACTIONs to something like
+::
+
fail = 1
everythingelse = return
the redundant GROUP as a whole returns RLM_MODULE_FAIL, just as you'd want it
to (I hope).
-There are two other kinds of grouping: group{...} which does not have any
-specialized default ACTIONs, and append{...}, which should be used when you
+There are two other kinds of grouping: ``group{...}`` which does not have any
+specialized default ACTIONs, and ``append{...}``, which should be used when you
have separate but similarly structured databases that are guaranteed not to
overlap.
That's all that really needs to be said. But now a few random notes:
-1. GROUPs may have RESULT=ACTION specifiers too! It would look like this:
+GROUPs may have RESULT=ACTION
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It would look like this:
+
+::
authorize {
preprocess
files
}
-which would prevent rlm_files from being called if neither of the SQL
+which would prevent ``files`` from being called if neither of the SQL
instances could find the user.
-2. redundant{...} and append{...} are just shortcuts. You could write
+redundant{...} and append{...} are just shortcuts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You could write:
+
+::
+
group {
sql1 {
fail = 1
sql1
sql2
}
- but the latter is just a whole lot easier to read.
-3. "authenticate{...}" itself is not a GROUP, even though it contains a list
-of Auth-Type GROUPs, because its semantics are totally different - it uses
-Auth-Type to decide which of its members to call, and their order is
-irrelevant.
+but the latter is just a whole lot easier to read.
+
+``authenticate{...}`` is not a GROUP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+even though it contains a list of ``Auth-Type`` GROUPs, because its
+semantics are totally different - it uses ``Auth-Type`` to decide which of
+its members to call, and their order is irrelevant.
-4. The default rules are context-sensitive - for authorize, the defaults are
+The default rules are context-sensitive
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For ``authorize``, the defaults are
what you saw above - notfound, noop, ok, and updated are considered
-success, and anything else has an ACTION of "return". For authenticate, the
+success, and anything else has an ACTION of ``return``. For authenticate, the
default is to return on success *or* reject, and only try the second and
following items if the first one fails. You can read all the default ACTIONs
in modcall.c (int defaultactions[][][]), or just trust me. They do the right
thing.
-5. There are some rules that can't be implemented in this language - things
-like "notfound = 1-reject", "noop = 2-ok", "ok = 3-ok", etc. But I don't feel
+There are some rules that can't be implemented in this language
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+things like ``notfound = 1-reject``, ``noop = 2-ok``, ``ok = 3-ok``, etc. But I don't feel
justified adding that complexity in the first draft.
There are already enough things here that may never see real-world usage.
Like append{...}
+How is the USERS file processed?
+================================
+See ``man users`` for more detailed documentation.
- How is the USERS file processed?
-
-
-After the items of a request have been mangled by the "hints" and
-"huntgroups" files, the users file is processed.
+After the items of a request have been mangled by the ``hints`` and
+``huntgroups`` files, the ``users`` file is processed.
A request has initially an empty check list and an empty reply list
-attached to it. So each request has 3 A/V pairlists associated with it
+attached to it. So each request has 3 "value-pair" lists associated with it
- the request list (as originated from the terminal server)
- the check list (initially empty)
- the reply list (initially empty)
-For every entry in the users file, the Username VP (Value-Pair) is checked.
-If it matches or it is a DEFAULT entry, a check pairlist is created
-(call it tmpcheck) by adding the check pairlist of the current usersfile
-entry to the check pairlist of the request. If an attribute is already
-present in the check pairlist of the request it will not be changed
-(see files.c:movepair).
-
-Then the request pairlist is compared with the tmpcheck pairlist. If
-all items match (except for password-related items at this time!)
+For every entry in the users file, the User-Name attribute
+(Value-Pair) is checked. If it matches, or it is a ``DEFAULT`` entry,
+then the items on the first line of the entry are compared with the
+attributes from the request. If all items match (logical "and") then
the following actions are taken:
-- The reply pairlist of the usersfile entry is appended to the reply
- pairlist of the request
-- The check pairlist of the request is replaced by the tmpcheck pairlist
- (this is the same as: the check pairlist from the usersfile entry is
- appended to the pairlist of the request)
-
-Then a check is made to see if the reply pairlist contains an A-V pair
-of "Fall-Through = Yes". If so, the next entry in the usersfile is processed
-as above. If not, we stop processing the users file.
-
-Then after all this is done, the Authentication information is filtered
-from the check pairlist, the password of the users is checked, and we
-send a reply back to the terminal server.
+- the check items from the current entry are added to the check list
+ of the request.
+- The reply list of the ``users`` file entry is appended to the reply
+ list of the request
+Then a check is made to see if the reply pairlist contains a special
+line of ``Fall-Through = Yes``. If so, the next entry in the ``users``
+file is processed as above. If not, we stop processing the ``users``
+file.
-
- FreeRADIUS as a proxy RADIUS server.
-
-
-0. INTRODUCTION
-
- It is possible to use FreeRADIUS as a proxy RADIUS server. This
- means that it can consult a remote RADIUS server to validate a user.
- This is handy for roaming setups, or for renting ports to someone else.
-
-1. FILES
-
- If a user logs in with a defined realm syntax, the "realm" portion is
- matched against the configuration to determine how the request should
- be handled. Common realm formats are:
-
- username@realm
- realm/username
- username%realm
- realm\username
-
- The realm parsing syntax ( and search order ) is user definable via the
- realm module config in the /etc/raddb/radiusd.conf configuration file.
-
- You can define multiple instances of the realm module to support multiple
- realm syntax's at the same time. Be sure to pay close attention to the
- search order that you define, as you may inadvertently get unexpected
- behaviour ( by having a user use 'realm1/username@realm2' for instance ).
- If you need to proxy to IPASS, it should go first, because usernames will
- be in the form IPASS/username@realm and you want to proxy these users to
- IPASS, not to the realm behind the @.
-
- The realms are configured in the file /etc/raddb/proxy.conf, which is
- included by radiusd.conf. The formats and sample configurations are
- included as comments.
-
- The realm "DEFAULT" (without the quotes) matches all realms.
- The realm "NULL" matches any requests WITHOUT a realm.
-
- If you set the remote server to "LOCAL", the request will be handled
- locally as usual, without sending it to a remote radius server.
-
- There are several options you can add in both files:
-
- - nostrip:
- By default the realm is stripped from the username before sending it
- on to the remote radius server. By specifying the "nostrip" option
- the @realm suffix will not be stripped.
- - hints
- By default the original username is sent to the remote radius
- server. By specifying the "hints" option the username will be
- sent as it is after the "hints" file was processed.
- - notrealm:
- By default if a realm is matched, it will be proxied to the server
- specified. However, if you are using Replication functionality, you
- may want to override this behaviour. This option will prevent a
- user who enters 'user@foobar' from being proxied if the 'foobar'
- realm configuration contains 'notrealm'. This function used to be
- called 'notsuffix', and the old syntax is still supported.
-
- The /etc/raddb/realms file is deprecated and should not be used anymore.
- If you use the /etc/raddb/realms file to enter realm configurations you will
- need to add the hostname and secret for the remote server in the
- file /etc/raddb/clients.
- It is not recommended to use both the realms file and the proxy.conf file,
- as that could cause confusion.
-
-2. ACCOUNTING
-
- All accounting data for proxied requests does NOT get stored in the
- standard logfiles, but in a separate directory. The name of this
- directory is the name of the remote radius server, and if you want you
- can define a nickname for it in /etc/raddb/naslist just as for normal NASes.
-
-3. REMOTE SERVER
-
- When your server proxies requests to another server, it acts as a NAS for
- the remote server. On the remote server, you need to add the hostname of
- your server and the same secret to /etc/raddb/clients.conf as well.
-
- As you might not control the remote radius server, you might want to
- control the attributes sent back by the remote server in an Access-Accept
- packet. Have a look at the attrs file for this!
-
-4. WHAT HAPPENS
-
- The exact thing that happens is this:
-
- - A user logs in with a realm
- - The hints file gets processed as usual
- - The user is checked against the huntgroups file. At this point
- the user _might_ already be rejected.
- - The realm is looked up in the realms file. If it isn't defined,
- the users file is processed normally.
- - If the 'notrealm' option is defined, the user is processed
- locally.
- - The realm is stripped from the username unless "nostrip" was
- set, and the request is sent to a remote radius server. Note that
- any stripping done in the hints file doesn't have an effect on the
- username sent to the remote radius server unless you set the
- "hints" option.
- - The remote server replies with ACK or REJECT
-
- On ACK: The initial Auth-Type is set to Accept
- On REJECT: The initial Auth-Type is set to Reject
-
- Then the users file is processed as usual. The username used at
- this point is the one after hints file processing (regardless of
- the "hints" option). It also includes the realm (regardless of the
- setting of the "nostrip" option) unless the realm is LOCAL.
+FreeRADIUS as a proxy RADIUS server.
+====================================
+
+
+Introduction
+------------
+
+It is possible to use FreeRADIUS as a proxy RADIUS server. This
+means that it can consult a remote RADIUS server to validate a user.
+This is handy for roaming setups, or for renting ports to someone else.
+
+Files
+-----
+
+If a user logs in with a defined realm syntax, the "realm" portion is
+matched against the configuration to determine how the request should
+be handled. Common realm formats are:
+
+::
+
+ username@realm
+ realm/username
+ username%realm
+ realm\username
+
+The realm parsing syntax ( and search order ) is user definable via the
+realm module config in the ``/etc/raddb/radiusd.conf`` configuration file.
+
+You can define multiple instances of the realm module to support multiple
+realm syntax's at the same time. Be sure to pay close attention to the
+search order that you define, as you may inadvertently get unexpected
+behaviour ( by having a user use ``realm1/username@realm2`` for instance ).
+If you need to proxy to IPASS, it should go first, because usernames will
+be in the form ``IPASS/username@realm`` and you want to proxy these users to
+IPASS, not to the realm behind the ``@``.
+
+The realms are configured in the file ``/etc/raddb/proxy.conf``, which is
+included by ``radiusd.conf``. The formats and sample configurations are
+included as comments.
+
+The realm ``DEFAULT`` (without the quotes) matches all realms.
+The realm ``NULL`` matches any requests WITHOUT a realm.
+
+If you set the remote server to ``LOCAL``, the request will be handled
+locally as usual, without sending it to a remote radius server.
+
+There are several options you can add in both files:
+
+- nostrip:
+ By default the realm is stripped from the username before sending it
+ on to the remote radius server. By specifying the "nostrip" option
+ the @realm suffix will not be stripped.
+- hints
+ By default the original username is sent to the remote radius
+ server. By specifying the "hints" option the username will be
+ sent as it is after the "hints" file was processed.
+- notrealm:
+ By default if a realm is matched, it will be proxied to the server
+ specified. However, if you are using Replication functionality, you
+ may want to override this behaviour. This option will prevent a
+ user who enters ``user@foobar`` from being proxied if the ``foobar``
+ realm configuration contains ``notrealm``. This function used to be
+ called ``notsuffix``, and the old syntax is still supported.
+
+The ``/etc/raddb/realms`` file is deprecated and should not be used anymore.
+If you use the ``/etc/raddb/realms`` file to enter realm configurations you will
+need to add the hostname and secret for the remote server in the
+file ``/etc/raddb/clients.conf``.
+It is not recommended to use both the realms file and the proxy.conf file,
+as that could cause confusion.
+
+Accounting
+----------
+
+All accounting data for proxied requests does `not` get stored in the
+standard logfiles, but in a separate directory. The name of this
+directory is the name of the remote radius server.
+
+Remote Server
+----------------
+
+When your server proxies requests to another server, it acts as a NAS for
+the remote server. On the remote server, you need to add the hostname of
+your server and the same secret to ``/etc/raddb/clients.conf`` as well.
+
+As you might not control the remote radius server, you might want to
+control the attributes sent back by the remote server in an Access-Accept
+packet. Have a look at the attrs file for this!
+
+What Happens
+---------------
+The exact thing that happens is this:
+
+- A user logs in with a realm
+- The hints file gets processed as usual
+- The user is checked against the huntgroups file. At this point
+ the user `might` already be rejected.
+- The realm is looked up in the realms file. If it isn't defined,
+ the users file is processed normally.
+- If the ``notrealm`` option is defined, the user is processed
+ locally.
+- The realm is stripped from the username unless ``nostrip`` was
+ set, and the request is sent to a remote radius server. Note that
+ any stripping done in the hints file doesn't have an effect on the
+ username sent to the remote radius server unless you set the
+ ``hints`` option.
+- The remote server replies with Access-Accept or Access-Reject
+
+::
+
+ On Access-Accept: The initial Auth-Type is set to Accept
+ On Access-Reject: The initial Auth-Type is set to Reject
+
+Then the users file is processed as usual. The username used at
+this point is the one after hints file processing (regardless of
+the ``hints`` option). It also includes the realm (regardless of the
+setting of the ``nostrip`` option) unless the realm is ``LOCAL``.
- Run-time variables
- ------------------
+Run-time variables
+==================
- See "man unlang" for more complete documentation on the run-time
+See "man unlang" for more complete documentation on the run-time
variables. This file is here only for historical purposes.
-
- The above variable expansions also support the following
+The above variable expansions also support the following
meta-attributes. These are not normal RADIUS attributes, but are
created by the server to be used like them, for ease of use. They can
only be queried, and cannot be assigned.
- Packet-Type RADIUS packet type (Access-Request, etc.)
-
- Packet-Src-IP-Address IP address from which the packet was sent
-
- Packet-Dst-IP-Address IP address to which the packet was sent
- This may be "0.0.0.0", if the server
- was configured with "bind_address = *".
-
- Packet-Src-Port UDP port from which the packet was sent
-
- Packet-Dst-Port UDP port to which the packet was sent.
-
- %{config:section.subsection.item} Corresponding value in 'radiusd.conf'
- for the string value of that item.
-
- The %{config:...} variables should be used VERY carefully, as they
++-----------------------+-------------------------------------------------+
+| Packet-Type | RADIUS packet type (Access-Request, etc.) |
++-----------------------+-------------------------------------------------+
+| Packet-Src-IP-Address | IP address from which the packet was sent |
++-----------------------+-------------------------------------------------+
+| Packet-Dst-IP-Address | IP address to which the packet was sent. |
+| | This may be "0.0.0.0", if the server |
+| | was configured with ``bind_address = *``. |
++-----------------------+-------------------------------------------------+
+| Packet-Src-Port | UDP port from which the packet was sent |
++-----------------------+-------------------------------------------------+
+| Packet-Dst-Port | UDP port to which the packet was sent. |
++-----------------------+-------------------------------------------------+
+
+``%{config:section.subsection.item}``
+ Corresponding value in ``radiusd.conf`` for the string value of that item.
+
+The ``%{config:...}`` variables should be used VERY carefully, as they
may leak secret information from your RADIUS server, if you use them
in reply attributes to the NAS!
+::
-DEFAULT User-Name =~ "^([^@]+)@(.*)"
- All-That-Matched = `%{0}`
- Just-The-User-Name = `%{1}`
- Just-The-Realm-Name = `%{2}`
+ DEFAULT User-Name =~ "^([^@]+)@(.*)"
+ All-That-Matched = `%{0}`
+ Just-The-User-Name = `%{1}`
+ Just-The-Realm-Name = `%{2}`
- The variables are used in dynamically translated strings. Most of
-the configuration entries in radiusd.conf (and related files) will do
+The variables are used in dynamically translated strings. Most of the
+configuration entries in ``radiusd.conf`` (and related files) will do
dynamic string translation. To do the same dynamic translation in a
RADIUS attribute (when pulling it from a database, or "users" file),
you must put the string into an back-quoted string:
- Session-Timeout = `%{expr: 2 + 3}`
+::
+
+ Session-Timeout = `%{expr: 2 + 3}`
- To do the dynamic translation in the 'radiusd.conf' (or some other
-configuration files), just use the variable as-is. See 'radiusd.conf'
-for examples.
+To do the dynamic translation in the ``radiusd.conf`` (or some other
+configuration files), just use the variable as-is. See
+``radiusd.conf`` for examples.
- Attributes as environment variables in executed programs
- --------------------------------------------------------
+Attributes as environment variables in executed programs
+--------------------------------------------------------
- When calling an external program (e.g. from 'rlm_exec' module),
-these variables can be passed on the command line to the program.
-In addition, the server places all of the attributes in the RADIUS
+When calling an external program (e.g. from ``rlm_exec`` module), these
+variables can be passed on the command line to the program. In
+addition, the server places all of the attributes in the RADIUS
request into environment variables for the external program. The
variables are renamed under the following rules:
- 1. All letters are made upper-case.
-
- 2. All hyphens '-' are turned into underscores '_'
+ #. All letters are made upper-case.
+ #. All hyphens '-' are turned into underscores '_'
-so the attribute User-Name can be passed on the command line to the
-program as %{User-Name}, or used inside the program as the environment
-variable USER_NAME (or $USER_NAME for shell scripts).
+so the attribute ``User-Name`` can be passed on the command line to the
+program as ``%{User-Name}``, or used inside the program as the environment
+variable ``USER_NAME`` (or ``$USER_NAME`` for shell scripts).
- If you want to see the list of all of the variables, try adding a
-line 'printenv > /tmp/exec-program-wait' to the script. Then look in
-the file for a complete list of variables.
+If you want to see the list of all of the variables, try adding a line
+``printenv > /tmp/exec-program-wait`` to the script. Then look in the
+file for a complete list of variables.
+One-character variables
+-----------------------
- One-character variables
- -----------------------
-
- The following one-character variables are also defined. However, they
+The following one-character variables are also defined. However, they
are duplicates of the previous general cases, and are only provided
for backwards compatibility. They WILL BE removed in a future
release. They also do NOT permit the use of conditional syntax
-(':-'), as described above.
-
-
- Variable Description Proper Equivalent
- -------- ----------- ----------------
- %a Protocol (SLIP/PPP) %{Framed-Protocol}
- %c Callback-Number %{Callback-Number}
- %d request day (DD)
- %f Framed IP address %{Framed-IP-Address}
- %i Calling Station ID %{Calling-Station-Id}
- %l request timestamp
- %m request month (MM)
- %n NAS IP address %{NAS-IP-Address}
- %p Port number %{NAS-Port}
- %s Speed (PW_CONNECT_INFO) %{Connect-Info}
- %t request in ctime format
- %u User name %{User-Name}
- %A radacct_dir %{config:radacctdir}
- %C clientname
- %D request date (YYYYMMDD)
- %H request hour
- %L radlog_dir %{config:logdir}
- %M MTU %{Framed-MTU}
- %R radius_dir %{config:raddbdir}
- %S request timestamp
- in SQL format
- %T request timestamp
- in database format
- %U Stripped User name %{Stripped-User-Name}
- %V Request-Authenticator
- (Verified/None)
- %Y request year (YYYY)
- %Z All request attributes
- except password
- (must have a big buffer)
+(i.e. ``:-``, as described above.
+
++-----------+---------------------------+-----------------------+
+| Variable | Description | Proper Equivalent |
++===========+===========================+=======================+
+|%a |Protocol (SLIP/PPP) |%{Framed-Protocol} |
++-----------+---------------------------+-----------------------+
+|%c |Callback-Number |%{Callback-Number} |
++-----------+---------------------------+-----------------------+
+|%d |request day (DD) | |
++-----------+---------------------------+-----------------------+
+|%f |Framed IP address |%{Framed-IP-Address} |
++-----------+---------------------------+-----------------------+
+|%i |Calling Station ID |%{Calling-Station-Id} |
++-----------+---------------------------+-----------------------+
+|%l |request timestamp | |
++-----------+---------------------------+-----------------------+
+|%m |request month (MM) | |
++-----------+---------------------------+-----------------------+
+|%n |NAS IP address |%{NAS-IP-Address} |
++-----------+---------------------------+-----------------------+
+|%p |Port number |%{NAS-Port} |
++-----------+---------------------------+-----------------------+
+|%s |Speed (PW_CONNECT_INFO) |%{Connect-Info} |
++-----------+---------------------------+-----------------------+
+|%t |request in ctime format | |
++-----------+---------------------------+-----------------------+
+|%u |User name |%{User-Name} |
++-----------+---------------------------+-----------------------+
+|%A |radacct_dir |%{config:radacctdir} |
++-----------+---------------------------+-----------------------+
+|%C |clientname | |
++-----------+---------------------------+-----------------------+
+|%D |request date (YYYYMMDD) | |
++-----------+---------------------------+-----------------------+
+|%H |request hour | |
++-----------+---------------------------+-----------------------+
+|%L |radlog_dir |%{config:logdir} |
++-----------+---------------------------+-----------------------+
+|%M |MTU |%{Framed-MTU} |
++-----------+---------------------------+-----------------------+
+|%R |radius_dir |%{config:raddbdir} |
++-----------+---------------------------+-----------------------+
+|%S |request timestamp | |
+| |in SQL format | |
++-----------+---------------------------+-----------------------+
+|%T |request timestamp | |
+| |in database format | |
++-----------+---------------------------+-----------------------+
+|%U |Stripped User name |%{Stripped-User-Name} |
++-----------+---------------------------+-----------------------+
+|%V |Request-Authenticator | |
+| |(Verified/None) | |
++-----------+---------------------------+-----------------------+
+|%Y |request year (YYYY) | |
++-----------+---------------------------+-----------------------+
+|%Z |All request attributes | |
+| |except password | |
+| |(must have a big buffer) | |
++-----------+---------------------------+-----------------------+
+
$Id$