"referenced entity .* not found" message fixed to be fatal
[tac_plus.git] / users_guide
index 2626115..13204b7 100644 (file)
@@ -113,12 +113,12 @@ TACACS, XTACACS and TACACS+
 ---------------------------
 
 Note that there are now at least 3 versions of authentication protocol
-that people commonly refer to as "TACACS".  
+that people commonly refer to as "TACACS".
 
 The first is ordinary tacacs, which was the first one offered on Cisco
 boxes and has been in use for many years. The second is an extension
 to the first, commonly called Extended Tacacs or XTACACS, introduced
-in 1990. 
+in 1990.
 
 The third one is TACACS+ (or T+ or tac_plus) which is what is documented
 here. TACACS+ is NOT COMPATIBLE with any previous versions of tacacs.
@@ -230,7 +230,7 @@ version of tacacs, use the convert.pl perl script as follows:
 
 convert.pl <passwd file> [-g] [<supplementary file>]
 
-1). If you have no supplementary file, simply omit it. 
+1). If you have no supplementary file, simply omit it.
 
 2). If the groupid field of your passwd file does NOT represent a
 valid acl number (e.g if it's really a unix passwd file this field is
@@ -267,7 +267,7 @@ Confusingly, even if your key does contain spaces, you should NEVER
 use double quotes when you configure the matching key on the NAS.
 
 During debugging, it may be convenient to temporarily switch off
-encryption by not specifying any key.  Be careful to remember to 
+encryption by not specifying any key.  Be careful to remember to
 switch encryption back on again after you've finished debugging.
 
 The current code does not support host-specific keys (left as an
@@ -294,7 +294,7 @@ Each user may belong to a group (but only one group).  Each group may
 in turn belong to one other group and so on ad infinitum.
 
 Users and groups are declared as follows. Here we declare two users
-"fred" and "lily", and two groups, "admin" and "staff". 
+"fred" and "lily", and two groups, "admin" and "staff".
 
 Fred is a member of group "admin", and group "admin" is in turn a
 member of group "staff". Lily is not a member of any group.
@@ -337,6 +337,79 @@ and specify as many groupwide characteristics in the group declaration
 as possible. Then, individual user declarations can be used to
 override the group settings for selected users as needed.
 
+MEMBERSHIP IN MULTIPLE GROUPS
+-----------------------------
+
+Besides the descibed single-membership of user to some group, you may also find
+useful if user (or host) belongs to multiple groups at once.  You can naturally
+specify multiple "member = group_X" commands for such user:
+
+user = fred {
+    # fred is a member of both groups: admins_company_A, admins_company_B
+    member = admins_company_A
+    member = admins_company_B
+}
+
+group = admins_company_A {
+    # group admins_company_A is not a member of any group
+    member = admins_company_A_privilege_X
+    member = admins_company_A_privilege_Y
+}
+group = admins_company_A_privilege_X {
+}
+group = admins_company_A_privilege_Y {
+}
+
+group = admins_company_B {
+    # group admins_company_B is not a member of any group
+}
+
+Here it is important to respect the ordering of "member" commands: Any
+searching for attributes/values is done by Depth-First Search - so Daemon would
+first try to look all members of admins_company_A and THEN (after it would
+failed to find any) it would start to searching through admins_company_B.  The
+searching through the proposed example would be done in the following order:
+
+       fred
+       admins_company_A
+       admins_company_A_privilege_X
+       admins_company_A_privilege_Y
+       admins_company_B
+
+Sometimes you would want to only list some members (users, hosts or groups) but
+you don't want to specify any attributes for them. You would be able to do it:
+
+group = city_X_NASes {
+}
+host  first.NAS.X.city {
+       member = city_X_NASes
+}
+host second.NAS.X.city {
+       member = city_X_NASes
+}
+
+But you will probably find more comfortable to use "enlist" keyword. It has
+the same functionality but it goes from the other way:
+
+    member: current entity is connected as CHILD to the specified PARENT entity
+    enlist: specified entity is connected as CHILD to the current one as PARENT
+
+The example would be re-written using "enlist" keyword as:
+
+group = city_X_NASes {
+       enlist = host  first.NAS.X.city
+       enlist = host second.NAS.X.city
+}
+
+As you can see, "enlist" doesn't require the existence of the given entity as
+it would loose its primary purpose. If the entity doesn't exist it will be
+automatically created (as empty one) - this doesn't apply to "member"! Any
+argument to "member" MUST exist.
+
+All forward references are not a problem, you can still make membership or
+enlistment on the top of the file with the entity which will be defined on the
+end of the configuration file.
+
 CONFIGURING USER AUTHENTICATION
 -------------------------------
 
@@ -505,7 +578,7 @@ vty and console lines)
 NOTE: As soon as you issue this command, you will no longer be able to
 create new logins to your NAS without a functioning tacacs+ daemon
 appropriately configured with usernames and password, so make sure you
-have this ready. 
+have this ready.
 
 As a safety measure while setting up, we suggest you configure an
 enable secret and make it the last resort authentication method, so
@@ -621,7 +694,7 @@ the command:
 
 and permit all other arguments, since the last line will match any
 argument list. All other commands and services are permitted due to
-the "default service = permit" clause. 
+the "default service = permit" clause.
 
 Note: the default statement must be the first in the user clause
 
@@ -770,7 +843,7 @@ differently from command authorization.
 When authorizing these services, the NAS sends a request containing a
 number of attribute-value (AV) pairs, each having the form
 
-       attribute=value 
+       attribute=value
 
 (Note: during debugging, you may see AV pairs whose separator
 character is a "*" instead of a "=" sign. This is to signify that the
@@ -854,9 +927,9 @@ aaa authentication ppp default if-needed
 explicit login step if you do this (so it's the only possibility if
 you are using autoselect). This authentication gets done before you
 see the first LCP authorization request of course.  Typically you
-configure this by doing: 
+configure this by doing:
 
-aaa authentication ppp default tacacs+ 
+aaa authentication ppp default tacacs+
 int async 1
 ppp authentication chap
 
@@ -918,7 +991,7 @@ for each AV pair sent from the NAS:
        deny, or
 
        j). If the default is permit add the NAS AV pair to the output.
+
     k). After all AV pairs have been processed, for each mandatory
     DAEMON AV pair, if there is no attribute match already in the
     output list, add the AV pair (but add only ONE AV pair for each
@@ -963,7 +1036,7 @@ user=fred {
     }
 
     service = ppp protocol = ip {
-       # Fred can run ip over ppp only if he uses one 
+       # Fred can run ip over ppp only if he uses one
         # of the following mandatory addresses. If he supplies no
        # address, the first one here will be mandated
 
@@ -1013,6 +1086,225 @@ group = admin {
 }
 
 
+CONFIGURATION RESPECTING NAS HOST OF THE USER
+---------------------------------------------
+
+Sometimes you would want to modify the configuration file according to the
+source NAS where the user is being authenticated/authorized. For example if you
+are big ISP you want to permit administrator of company X to be able to monitor
+status of the links on NAS in company X but, of course, she should be able to
+monitor any other links on any other NAS of the same ISP. As all the NASes are
+authorized from the same Daemon, it seems as a problem. (You can workaround it
+by using custom authorization program - see "USING PROGRAMS TO DO
+AUTHORIZATION" section below - but it is not nice solution.)
+
+For this purposes there exists another entity 'host':
+
+               user wilma
+               group admin
+               host 198.133.219.25
+               host nas.cisco.com
+
+As you can see you may use either IP address or DNS name. Anyway, we strongly
+recommend to always use only IP addresses - DNS subsystem may fail or it may be
+forged by the enemy.
+
+You have two methods of utilizing the differences between NASes:
+
+1) Current user is always automatically enlisted (=given membership to) to its
+   current NAS host. This looks weird as only groups can have members but this
+   is the only exception to this rule, current NAS host can really have a
+   member:
+
+       ( user "current_user" |  user DEFAULT )
+        |
+        +-- host "current_NAS_IP_address"
+        |    |
+        |    +- group DEFAULT
+        |
+        +-- host "current_NAS_hostname"
+        |    |
+        |    +-- group DEFAULT
+        |
+        +-- group DEFAULT
+
+   Each link only exists in the case it there exist both its peers, of course.
+   user/group DEFAULT is written here only for the completeness of the chart.
+   DEFAULT is discussed elsewhere in this documentation.
+
+   According to the shown ordering, attributes/values in the host of current
+   NAS identified by its IP address has _higher_ precence over the attributes
+   in the current NAS identified by its (reverse-resolved) hostname.
+
+   According to this auto-connections, you can for example permit some command
+   to ALL the users on such NAS:
+
+user = fred {
+    login = cleartext LLLL
+}
+host = machine.A.company {
+    cmd = write  {
+       permit terminal
+    }
+}
+
+   In this configuration file ALL the valid users can do "write terminal" when
+   logged in on NAS "machine.A.company".
+
+2) Sometimes you need to do the authorization specific only to some users on
+   some NASes. For example to permit "write terminal" ONLY to user fred
+   connected to NAS "machine.A.company". That means that you want to forbid it
+   to user fred on any other NAS and yuo also want to forbid it to all the
+   other users on NAS "machine.A.company". (Line "authorization = recursive" is
+   required but read the following section "FULL RECURSIVITY" to know all its
+   consequences.)
+
+authorization = recursive
+user = fred {
+    login = cleartext LLLL
+}
+host = machine.A.company {
+    when = user fred {
+       cmd = write  {
+           permit terminal
+       }
+    }
+}
+
+    This file has the same effect as:
+
+authorization = recursive
+user = fred {
+   login = cleartext LLLL
+   when = host machine.A.company {
+       cmd = write  {
+           permit terminal
+       }
+    }
+}
+host = machine.A.company {
+}
+
+   You can see the (nested) command "when" can limit the scope of existence of
+   its contents. Unfortunately you cannot use "when" to limit any items, just
+   a few are possible:
+
+member
+enlist
+cmd
+cmd arguments    (to limit specific "permit"/"deny" lines)
+service          (or incl. "protocol" specification)
+service AV pairs (to limit specific "attr=value" lines)
+when             (enabling pure nesting of "when" blocks)
+
+   Full flexibility to limit any contents may be done in future (needs complete
+   cfgfile.c rewrite) but currently it is not supported. Fortunately you can
+   get the same behaviour by appropriate usage of "member" keyword - all the
+   attributes to be conditioned are put into separate group and you limit only
+   the "member" keyword to such group.
+
+   "when" command has the form "when = CONDITION { BLOCK }", CONDITION can be:
+
+user  USR       i.e. that current user is "USR")
+host  HOSTNAME  i.e. that current user is on NAS "HOSTNAME")
+group GRP       i.e. current user belongs to the group "GRP",
+                  All possible "when" conditions to reach such belonging
+                  have to be successfuly met to make this condition successful.
+                  Realize that "member" can be limited by "when" keyword.
+CONDITION and CONDITION and CONDITION ...
+CONDITION or  CONDITION or  CONDITION ...
+not CONDITION
+( CONDITION )
+
+   You can see that you CANNOT use for example "user A and user B or user C",
+   such condition would have ambiguous precedence of operators, you must
+   explicitly write:  ( user A and user B ) or user C
+                or:  user A and ( user B or user C )
+
+   Both parentheses have to be written as separate words, NOT "(user A)"
+   but "( user A )" instead.
+   (Proper solution would also need the complete cfgfile.c rewrite.)
+
+   "not" operator has the highest precendence, so: not user A or user B
+   has the same meaning as: ( not user A ) or user B
+
+   Sometimes the "when" condition is so-called unresolvable. Example:
+
+group = GRP { }
+user = USR {
+    when = group GRP {
+       member = GRP
+       }
+}
+
+   It is looping, when we would be the member of GRP, we would be really the
+   member of GRP but otherwise sould wouldn't be the member of GRP. Weird?
+   Yes, such case is considered as configuration bug, it is reported as:
+
+       Unable to resolve expression from line 243, some looping occured
+
+   Generally such unresolvable conditional expression is considered as UNKNOWN
+   and the "when" keyword is then evaluated as "false" (=skip it's block).
+   This MAY produce unwanted privilege access (if you were conditionally
+   forbidding some privileges) so always watch out all the error messages in
+   logs! (You should generally do default deny and specifically only "permit"
+   all the privileges so the unintentional unresolvable expressions shouldn't
+   hurt you in real.)
+
+FULL RECURSIVITY
+----------------
+
+We have written in the previous examples line:
+
+authorization = recursive
+
+This changes some behaviour of Daemon:
+
+1) Looping of memberships: By default any looped memberships are reported as
+   error with message: recursively defined groups: ...
+
+   After "authorization = recursive" any looping is silently accepted as it
+   would be sometimes hard to prevent it in some complex configurations.
+   Searching is done in normal Depth-First Search, but traversion is
+   backtracked one step when the entity was already visited. Simply it will
+   work 'magically', just safely ignore the fact.
+
+2) "default service = default" is supported only with:
+               authorization = recursive
+   This isn't any real change, just some formality. In fact each entity block
+   has "default service = default" in effect as default (in the case you don't
+   write any "default service =" assign).
+
+   "authorization = recursive" is enforced here due to the change of Daemon
+   behaviour: In non-recursive (old) case the Daemon assumes "deny .*" as the
+   last line of "cmd" block. This makes proper NAS-host based permissions
+   impossible. In "authorization = recursive" mode it requires appropriate
+   "permit" or "deny" line to apply - otherwise the Depth-First Search through
+   the entities will continue to find another applicable "cmd" block (toplevel
+   "default authorization" may get into effect as the last resort).
+
+   "default service" keyword takes then another meaning: In non-recursive mode
+   it will mean "if the command wasn't found". In fully-recursive mode it will
+   mean "if any cmd block didn't decide".
+
+   Please keep in mind that "service =" (with its possible "protocol =" mate)
+   has always the same behaviour, nothing is changed with "authorization =
+   recursive" enabled. Its functionality is already a bit complex (with AV
+   pairs get erased, which added, which copied, which are optional from NAS,
+   which optional from Daemon, whether to do default permit or deny etc.).
+   Fortunately we didn't found that there would be needed some extended
+   'recursiveness' functionality of "service" for application of NAS-host based
+   authorization.
+
+3) "host" entities are not recursive at all (=its attributes aren't looked up
+   in its parent groups) without "authorization = recursive".  This isn't any
+   much change as in the previous versions of Daemon "host" entity was either
+   completely unsupported or it was supported only with the only one attribute:
+
+   "key": Attribute defines different protocol key (instead of the specified
+         toplevel one) for the specified host. Its use is recommended to
+         improve overall network security (by using unique key for each NAS).
+
 USING PROGRAMS TO DO AUTHORIZATION
 ----------------------------------
 
@@ -1079,7 +1371,7 @@ follows (consult the API specification for more details).
     service -- (a digit, 1 to 7)
     status  -- (pass, fail, error, unknown)
 
-Unrecognized variables will appear as the string "unknown". 
+Unrecognized variables will appear as the string "unknown".
 
 If the program returns a status of 0, authorization is unconditionally
 permitted. No further processing is done on this request and no AV
@@ -1119,14 +1411,14 @@ NAS and change the authorization status if required.
 
 group = auth1 {
     # call /usr/bin/post_authorize passing it the username, port
-    # and current authorization status. 
+    # and current authorization status.
     after authorization "/usr/bin/post_authorize $user $port $status"
 }
 
 The AV pairs resulting from the authorization algorithm that the
 daemon proposes to return to the NAS, are supplied to the program on
 standard input, one AV pair per line, so they can be modified if
-required. 
+required.
 
 Fields from the incoming authorization packet which the NAS sent to
 the daemon can also be passed to the program on its command line by
@@ -1202,9 +1494,9 @@ daemon, where anything not explicitly permitted is denied by default.
 To configure command authorization on the NAS, issue the following NAS
 configuration commands:
 
-    aaa authorization commands 1 tacacs+ 
-    aaa authorization commands 15 tacacs+ 
-   
+    aaa authorization commands 1 tacacs+
+    aaa authorization commands 15 tacacs+
+
 
 This will make the NAS send tacacs+ requests for all level 1 (ordinary
 user) and level 15 (privileged level) commands on all lines/interfaces.
@@ -1213,12 +1505,12 @@ NOTE: As soon as you configure the above on your NAS, you will only be
 permitted to execute NAS commands which are permitted by your tacacs+
 daemon. So make sure you have configured, on the daemon, an
 authenticated user who is authorized to run commands, or you will be
-unable to do much on the NAS after turning on authorization. 
+unable to do much on the NAS after turning on authorization.
 
 Alternatively, or in addition, you may also want to configure the
 following:
 
-    aaa authorization commands 1 tacacs+ if-authenticated 
+    aaa authorization commands 1 tacacs+ if-authenticated
 
 This will use tacacs+ authorization for level 1 (user-level commands)
 but if problems arise, you can just switch off the tacacs+ server and
@@ -1260,7 +1552,7 @@ To get accounting records equivalent to previous versions of tacacs,
 the following is sufficient. "Stop" records contain elapsed time for
 connections and exec sessions.
 
-aaa accounting network stop-only tacacs+ 
+aaa accounting network stop-only tacacs+
 aaa accounting exec stop-only tacacs+
 
 
@@ -1273,7 +1565,7 @@ configured on the NAS but cannot be controlled via AAA.
 
 Here is an example of AAA configuration (with exec and network
 accounting enabled):
+
 NAS configuration:
 
 aaa new-model
@@ -1283,7 +1575,7 @@ aaa accounting exec wait-start tacacs+
 aaa accounting network wait-start tacacs+
 
 ! Example of AAA configuration for Exec:
-aaa authentication login execcheck tacacs+ 
+aaa authentication login execcheck tacacs+
 aaa authorization network tacacs+
 service exec-callback
 :
@@ -1291,7 +1583,7 @@ line 4
 login authentication execcheck
 
 ! Example of AAA configuration for ARAP:
-aaa authentication arap arapcheck tacacs+ 
+aaa authentication arap arapcheck tacacs+
 aaa authorization network tacacs+
 arap callback
 :
@@ -1300,7 +1592,7 @@ arap authentication arapcheck
 
 ! Example of AAA-specific configuration for PPP callback:
 aaa new-model
-aaa authentication ppp pppcheck tacacs+ 
+aaa authentication ppp pppcheck tacacs+
 aaa authorization network tacacs+
 :
 int async 6
@@ -1323,19 +1615,19 @@ user = foobar {
    service = arap {
         callback-dialstring=2345678
    }
-   service = exec { 
+   service = exec {
         callback-dialstring=3456789
         callback-line=7
         nocallback-verify=1
    }
-}  
+}
 
 
 
 
 DEBUGGING CONFIGURATION FILES
 -----------------------------
-       
+
 When creating configuration files, it is convenient to check their
 syntax using the -P flag to tac_plus e.g.
 
@@ -1350,7 +1642,7 @@ DEBUGGING A RUNNING SERVER
 There is a myriad of debugging values that can be used in conjunction
 with the -d flag to produce debugging output in /var/log/tac_plus.log.
 
-For example, starting the daemon with 
+For example, starting the daemon with
 
        tac_plus -C CONFIG -d 16
 
@@ -1479,10 +1771,10 @@ Q). How is the typical login authentication sequence done?
 A).    NAS sends START packet to daemon
        Daemon send GETUSER containing login prompt to NAS
        NAS prompts user for username
-       NAS sends pkt to daemon 
+       NAS sends pkt to daemon
        Daemon sends GETPASS containing password prompt to the NAS
        NAS prompts user for password
-       NAS sends pkt to daemon 
+       NAS sends pkt to daemon
        Daemon sends accept, reject or error to NAS
 
 
@@ -1545,7 +1837,7 @@ A).  The best way to restrict telnet access is by applying an outbound
 access list via the access class command (or equivalently, via the
 "acl" avpair). The NAS configuration command "access-class <n> out"
 for example applies a pre-defined standard IP access list (where n is
-a number from 1 through 99) that governs telnet access from a NAS. 
+a number from 1 through 99) that governs telnet access from a NAS.
 
 E.g. the following configuration commands permit outgoing Telnet
 access from line 1 on the NAS *only* to hosts on network 192.85.55.0:
@@ -1710,7 +2002,7 @@ Current attributes are:
 "callback-line"
 "callback-rotary"
 
-I expect more will be added over time. 
+I expect more will be added over time.
 
 Example records are thus:
 
@@ -1727,7 +2019,7 @@ Q). How do I limit the number of sessions a user can have?
 
 A). The TACACS+ daemon can enforce how many simultaneous sessions a
 given user is allowed to have.  You must compile the daemon with the
-MAXSESS symbol defined (see the Makefile).  
+MAXSESS symbol defined (see the Makefile).
 
 Maximum sessions are configured on the daemon for a user as follows:
 
@@ -1889,7 +2181,7 @@ source-ip: (This is now deprecated. It began in release 11.2(1.4),
 
 Tacacs+ syntax
 --------------
-               
+
 The following syntax is used on the public domain Tacacs+ server.
 
 username = domain {
@@ -1955,7 +2247,7 @@ A). Most attributes are mandatory i.e. if the daemon sends them to the
 NAS, the NAS must obey them or deny the authorization. This is the
 default. It is possible to mark attributes as optional, in which case
 a NAS which cannot support the attribute is free to simply ignore it
-without causing the authorization to fail. 
+without causing the authorization to fail.
 
 This was intended to be useful in cutover situations where you have
 multiple NASes running different versions of IOS, some of which
@@ -2058,7 +2350,7 @@ tacacs-server key <some key>
 2). A canned configuration for command authorization. This will allow
 user fred to login with password abcdef and to run the privileged
 (level 15) commands 'write terminal' and 'configure'. All other
-privileged commands will be denied. 
+privileged commands will be denied.
 
 The "none" keyword in the NAS configuration line means that if the
 tacacs+ server dies, any command will be allowed.
@@ -2112,7 +2404,7 @@ aaa authentication login default tacacs+
 ! authorize network services via tacacs+
 aaa authorization network tacacs+
 ! use tacacs+ for authenticating ppp users
-aaa authentication ppp default tacacs+ 
+aaa authentication ppp default tacacs+
 tacacs-server host <some host ip address>
 tacacs-server key <some key>
 interface Async1
@@ -2173,16 +2465,16 @@ The following AV pairs specify which service is being authorized. They
 are typically accompanied by protocol AV pairs and other, additional
 pairs from the lists below.
 
-service=arap 
+service=arap
 service=shell (for exec startup, and also for command authorizations)
-service=ppp 
+service=ppp
 service=slip
 
 service=system (not used).
 
 service=raccess
        Used for managing reverse telnet connections e.g.
+
        user = jim {
            login = cleartext lab
            service = raccess {
@@ -2191,7 +2483,7 @@ service=raccess
            }
        }
 
-       Requires IOS configuration 
+       Requires IOS configuration
 
                aaa authorization reverse-access tacacs+
 
@@ -2227,14 +2519,14 @@ protocol=cdp
 protocol=multilink
        Authorization of multilink PPP. See 'max-links' and 'load-threshold'.
 
-protocol=unknown 
+protocol=unknown
        For undefined/unsupported conditions. Should not occur under
        normal circumstances.
 
-cmd (EXEC) 
+cmd (EXEC)
        If the value of cmd is NULL e.g. the AV pair is cmd=, then
        this is an authorization request for starting an exec.
-       
+
        If cmd is non-null, this is a command authorization request,
        It contains the name of the command being authorized
        e.g. cmd=telnet
@@ -2248,7 +2540,7 @@ cmd-arg (EXEC)
        It is used internally by the daemon to construct a string
        which is then matched against the regular expressions which appear
        in a cmd clause in the configuration file.
-       
+
 acl (ARAP, EXEC)
        For ARAP this contains an access-list number.  For EXEC
        authorization it contains an access-class number, e.g. acl=2.
@@ -2261,7 +2553,7 @@ acl (ARAP, EXEC)
        An outbound access-class is the best way to restrict outgoing telnet
        connections. Note that a suitable access list (in this case,
        numbered 2) must be predefined on the NAS.
-               
+
 inacl (PPP/IP/IPX)
        This AV pair contains an IP or IPX input access list number
        for slip or PPP e.g. inacl=2. The access list itself must be
@@ -2290,7 +2582,7 @@ inacl#<n> (PPP/IP, PPP/IPX, 11.2(4)F)
        See also:
        sho ip access-lists
        sho ip interface
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        debug aaa author
        debug aaa per-user
@@ -2323,7 +2615,7 @@ outacl#<n> (PPP/IP, PPP/IPX, 11.2(4)F)
        See also:
        sho ip access-lists
        sho ip interface
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        debug aaa author
        debug aaa per-user
@@ -2336,7 +2628,7 @@ routing (SLIP, PPP/IP)
        Equivalent to the /routing flag in slip and ppp commands. Can
        have as its value the string "true" or "false".
 
-timeout (11.0 onwards, ARAP, EXEC) 
+timeout (11.0 onwards, ARAP, EXEC)
        Sets the time until an arap or exec session disconnects
        unconditionally (in minutes), e.g. timeout=60
 
@@ -2350,20 +2642,20 @@ noescape (EXEC)
        noescape option to the username configuration command.  Can
        have as its value the string "true" or "false",
        e.g. noescape=true
-       
+
 nohangup (EXEC)
        During exec startup, this specifies "nohangup", like the
        nohangup option to the username configuration command.  Can
        have as its value the string "true" or "false",
        e.g. nohangup=true
-       
+
 priv-lvl (EXEC)
        Specifies the current privilege level for command
        authorizations, a number from zero to 15 e.g. priv_lvl=5.
 
-       Note: in 10.3 this attribute was priv_lvl i.e. 
+       Note: in 10.3 this attribute was priv_lvl i.e.
        it contained an underscore instead of a hyphen.
-       
+
 zonelist (ARAP)
        An Appletalk zonelist for arap equivalent to the line
        configuration command "arap zonelist" e.g. zonelist=5
@@ -2423,7 +2715,7 @@ route#<n> (PPP/IP/IPX, 11.2(4)F)
        route#2="4.0.0.0 255.0.0.0"
 
 
-       or, for IPX, 
+       or, for IPX,
 
        route#1="4C000000 ff000000 30.12.3.4"
        route#2="5C000000 ff000000 30.12.3.5"
@@ -2439,7 +2731,7 @@ callback-rotary (11.1 onwards, valid for ARAP, EXEC, SLIP or PPP)
        to use for callback e.g. callback-rotary=34. Not valid for ISDN.
 
 callback-dialstring (11.1 onwards, valid for ARAP, EXEC, SLIP or PPP)
-       sets the telephone number for a callback e.g. 
+       sets the telephone number for a callback e.g.
        callback-dialstring=408-555-1212. Not valid for ISDN.
 
 callback-line (11.1 onwards, valid for ARAP, EXEC, SLIP or PPP)
@@ -2455,7 +2747,7 @@ idletime (11.1 onwards, EXEC)
        Sets a value, in minutes, after which an IDLE session will be
        terminated. N.B. Does NOT work for PPP.
 
-tunnel-id (11.2 onwards, PPP/VPDN) 
+tunnel-id (11.2 onwards, PPP/VPDN)
        This AV pair specifies the username that will be used to
        authenticate the tunnel over which the individual user MID
        will be projected.  This is analogous to the "NAS name" in the
@@ -2463,7 +2755,7 @@ tunnel-id (11.2 onwards, PPP/VPDN)
 
 ip-addresses (11.2 onwards, PPP/VPDN)
        This is a space separated list of possible IP addresses that
-       can be used for the end-point of the tunnel.  
+       can be used for the end-point of the tunnel.
 
        In 11.2(5.4)F, this attribute was extended as follows:
 
@@ -2471,7 +2763,7 @@ ip-addresses (11.2 onwards, PPP/VPDN)
        For example the avpair can now be written as
 
        ip-addresses = 172.21.9.26,172.21.9.15,172.21.9.4
+
        2) '/' is considered a priority delimiter. When you have a
        number of Home Gateway routers, it is desirable to consider some
        as the primary routers and some as backup routers.
@@ -2483,11 +2775,11 @@ ip-addresses (11.2 onwards, PPP/VPDN)
        For example in the following avpair:
 
        ip-addresses = "172.21.9.26 / 172.21.9.15 / 172.21.9.4"
+
        172.21.9.26 is considered to be priority 1
        172.21.9.15 is considered to be priority 2
        172.21.9.4  is considered to be priority 3
+
        The NAS will try to forward the users to 172.21.9.26, before
        trying 172.21.9.15.  If the NAS can't forward users to
        172.21.9.26, it will try 172.21.9.15 next. If it fails with
@@ -2510,7 +2802,7 @@ gw-password (PPP/VPDN, 11.2(3.4)F, 11.2(4.0.2)F)
 rte-ftr-in#<n> (PPP -- IP/IPX, 11.2(4)F)
        This AV pair specifies an input access list definition to be
        installed and applied to routing updates on the current
-       interface, for the duration of the current connection. 
+       interface, for the duration of the current connection.
 
        For IP, both standard and extended Cisco access list syntax is
        recognised, but it is an error to mix the two within a given
@@ -2536,11 +2828,11 @@ rte-ftr-in#<n> (PPP -- IP/IPX, 11.2(4)F)
 
        show ip access-lists
        show ip protocols
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        debug aaa author
        debug aaa per-user
-       
+
        Related IOS commands:
        IP:
                router <routing process identifier>
@@ -2553,7 +2845,7 @@ rte-ftr-in#<n> (PPP -- IP/IPX, 11.2(4)F)
 rte-ftr-out#<n> (PPP/IP, 11.2(4)F)
        This AV pair specifies an input access list definition to be
        installed and applied to routing updates on the current
-       interface, for the duration of the current connection. 
+       interface, for the duration of the current connection.
 
        For IP, both standard and extended Cisco access list syntax is
        recognised, but it is an error to mix the two within a given
@@ -2575,13 +2867,13 @@ rte-ftr-out#<n> (PPP/IP, 11.2(4)F)
 
        See also:
 
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        show ip access-lists
        show ip protocols
        debug aaa author
        debug aaa per-user
-       
+
        Related IOS commands:
        IP:
                router <routing process identifier>
@@ -2620,7 +2912,7 @@ route#<n> (PPP/IP/IPX, 11.2(4)F)
        route#2="4.0.0.0 255.0.0.0"
 
 
-       or, for IPX, 
+       or, for IPX,
 
        route#1="4C000000 ff000000 30.12.3.4"
        route#2="5C000000 ff000000 30.12.3.5"
@@ -2630,7 +2922,7 @@ route#<n> (PPP/IP/IPX, 11.2(4)F)
        sho ipx route
        debug aaa author
        debug aaa per-user
-       
+
 
 sap-fltr-in#<n> (PPP/IPX, 11.2(4)F)
        This AV pair specifies an input sap filter access list
@@ -2644,7 +2936,7 @@ sap-fltr-in#<n> (PPP/IPX, 11.2(4)F)
 
        Attributes are sorted numerically before being applied.
 
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        debug aaa author
        debug aaa per-user
@@ -2664,7 +2956,7 @@ sap-fltr-out#<n> (PPP/IPX 11.2(4)F)
 
        Attributes are sorted numerically before being applied.
 
-       sho ipx access-lists 
+       sho ipx access-lists
        sho ipx interface
        debug aaa author
        debug aaa per-user
@@ -2778,24 +3070,24 @@ old-prompts (PPP/SLIP)
        appear identical to those of earlier systems (tacacs and
        xtacacs). This will allow administrators to upgrade from
        tacacs/xtacacs to T+ transparently to users.
+
        The difference between the prompts is as follows:
+
        In xtacacs, when the user types "slip" or "ppp" the system
        prompts for an address followed by a password, whereas T+
        prompts only for an address.
+
        In xtacacs, if the user types "slip host" or "ppp host", the
        system prompts for a password. In T+, there is no prompt.
+
        Using this attribute, T+ can be made to mimic the prompting
        behaviour of xtacacs, by configuring network authorization on
        IOS, and using the "old-prompts=true" attribute value pair for
        slip and ppp/ip, viz:
+
        user = joe {
            global = cleartext foo
+
            service = exec {
            }
            service = slip {
@@ -2806,7 +3098,7 @@ old-prompts (PPP/SLIP)
                default attribute = permit
                old-prompts=true
            }
-       }        
+       }
 
        i.e. the prompts are controlled by the addition of the
        "old-prompts=true" attribute.