From 73309951d2c9b91aca5641a77c28b1f150b31cfe Mon Sep 17 00:00:00 2001 From: short <> Date: Mon, 9 Jul 2001 11:18:09 +0000 Subject: [PATCH] Covered all GTS changes by new sections: MEMBERSHIP IN MULTIPLE GROUPS CONFIGURATION RESPECTING NAS HOST OF THE USER FULL RECURSIVITY --- users_guide | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) diff --git a/users_guide b/users_guide index cc9aac4..13204b7 100644 --- a/users_guide +++ b/users_guide @@ -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 ---------------------------------- -- 1.8.3.1