Covered all GTS changes by new sections:
authorshort <>
Mon, 9 Jul 2001 11:18:09 +0000 (11:18 +0000)
committershort <>
Mon, 9 Jul 2001 11:18:09 +0000 (11:18 +0000)
  MEMBERSHIP IN MULTIPLE GROUPS
  CONFIGURATION RESPECTING NAS HOST OF THE USER
  FULL RECURSIVITY

users_guide

index cc9aac4..13204b7 100644 (file)
@@ -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
 -------------------------------
 
@@ -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
 ----------------------------------