7.2 约束语句
constrain语句包含三个元素:将要应用约束的一套客体类别,为那些受约束的类别指定的一套许可和一个约束的布尔表达式。约束是由客体类别进行组织并存储在策略中的,下面是constrain语句的完整语法。
|
约束语句语法 constrain语句使你可以通过基于源和目标安全上下文之间的关系定义约束,对特定客体类别限制特定的许可。完整的constrain语句语法如下: constrain 类别集 许可集 表达式; 类别集 一个或多个客体类别,多个客体之间必须用空格分隔,并且要用大括号将它们括起来,如{file lnk_file},在这个语句中不接受特殊操作符*,~和-。 许可集 一个或多个许可,所有许可对类别集中的客体类别必须是有效的,多个许可之间必须使用空格分隔,并且要用大括号将它们括起来,如{read create},在这个语句中也不接受接受特殊操作符*,~和-。 表达式 约束的布尔表达式。 布尔表达式支持下列关键字: t1,r1,u1 分别是源类型,角色和用户 t2,r2,u2 分别是目标类型,角色和用户 约束表达式语法还支持下列操作符: = = 等于或是…的成员 != 不等于或不是…的成员 eq (仅角色关键字)等于 dom (仅角色关键字)优先于 domby (仅角色关键字)被… 优先 incomp (仅角色关键字)不可比 完整的语义含义和每个操作符接受的变量列在表7-1中。 constrain语句仅在单个策略和基础载入模块中有效,在条件语句和非基础模块中无效。 |
constrain语句让你可以在安全上下文的三个元素(用户,角色和类型)中做任意限制,约束表达式比较源(主体)进程的上下文和目标(客体)的上下文,或直接使用明确的名字进行比较,如类型或角色标识符。
约束表达式本身可以很复杂,但实际上很少这么做,如下面的例子:
constrain process transition (u1 == u2) ; |
让我们仔细来研究一下这个约束语句,首先,它只应用到process客体类别,并且只对transition许可做了约束,前面的章节已经讨论过了,在域转换过程中是需要transition许可的,实际上,这个约束对域转换做了进一步的限制。
再来看一看约束表达式(u1 == u2),u1和u2分别表示安全上下文的源和目标用户标识符,因此,当源和目标用户标识符相同时,表达式返回的值为true,在域转换的情况下,源就是进程当前的安全上下文,目标就是进程新的安全上下文。
再完整地看一看前面这条约束语句,它要求对于所有的域转换,源和目标用户标识符要保持一致。如何保持一致呢?回顾一下前面讨论过的访问算法,当某个进程请求转换许可时,AVC就将请求转发给安全服务器,由安全服务器为源-目标-类别决定访问权,前面的约束将会生效(对于process客体类别),并将会检查源和目标安全上下文中的用户标识符,如果用户标识符不同,在将授予的访问许可掩码返回给AVC前,将会先移除代表转换许可的掩码。
再来看另一个例子:
constrain process transition (r1 == r2) ; |
这个约束语句和前面的例子类似,除了这里约束的是角色标识符外,关键字r1和r2分别代表源和目标角色标识符,这个约束要求在域转换过程中角色标识符不能改变,和前面要求的不能改变用户标识符一样。
因为这两个约束都是关联到相同的客体类别和许可,constrain表达式语法允许我们将它们合并为一条约束语句,如下:
constrain process transition (u1 == u2 and r1 == r2) ; |
这一条约束语句等同于前面那两条约束语句,它们都能起到在域转换过程中限制用户和角色标识符不能改变的效果。
将我们的例子做进一步延伸,在某些情况下,我们想要用户和/或角色标识符在域转换过程中发生变化,如登陆进程需要改变用户和角色标识符到那些登陆的用户和角色,另一个例子是一个允许你改变你的角色的程序,在域转换过程中,它必须要能够改变角色标识符,通常,那样的程序是受信任的进程,我们需要一个方法允许它们改变用户/角色标识符,并且还要确保约束对所有其它的程序都是有效的。
为了实现这个目标,我们首先定义一个方法来识别出那些受信任的可以改变用户或角色标识符的域类型,可以通过类型属性来实现,我们假设在策略中已经定义好了两个属性:privuser和privrole。前者与所有能够改变用户标识符的类型关联,后者与那些允许改变角色标识符的类型关联。使用这两个属性,我们可以将前面的约束语句改为:
constrain process transition (u1 == u2 or t1 == privuser) ; |
在这两条语句中,t1指的是源类型(如果使用了t2,那就指的是目标类型),第一条语句指出,只要源类型具有privuser属性,就允许在域转换过程中改变用户标识符,同样,只要源类型具有privrole属性,就可以在域转换过程中改变角色标识符。
确定你已经理解了属性是如何影响约束的,回顾一下内核是如何将属性扩展开为一个类型列表的,对于内核而言,这些约束实际上一串类型列表而不是单个的属性,要是类型列表或属性在操作符的右边,= =操作符的真实意思是"类型列表的一个成员",同样,!=操作符就意味着"不是类型列表的一个成员",因此,在我们前面的例子中,t1 == privuser意味着"如果源类型在具有privuser属性的类型列表中"。
注意:对于约束表达式,所有操作符的左边必须是一个允许的关键字,如u1,u2等,而不应该是一个类型、属性、角色或用户标识符(或标识符列表),操作符的右边可以是一个关键词,或一个或多个标识符名字。
如果操作符的左边和右边分别是关键字r1和r2,此时,你还可以选择更多的操作符,如eq,dom,domby和incomp,但这些都很少使用,表7-1总结了在constrain语句可以使用的操作符。
表7-1.约束表达式中允许的参数和对应的语义
|
操作符 |
左边 |
右边 |
语义含义 |
|
t1 |
t2 |
源类型等于目标类型 | |
|
t1(t2) |
类型和/或属性名 |
源(目标)类型是由右边的名字指出的类型集的一个成员 | |
|
r1 |
r2 |
源角色等于目标角色 | |
|
r1(r2) |
角色名 |
源(目标)角色是由右边角色指出的角色集的一个成员 | |
|
u1 |
u2 |
源用户等于目标用户 | |
|
u1(u2) |
用户名 |
源(目标)用户是由右边用户名指出的用户集的一个成员 | |
|
!= |
t1 |
t2 |
源类型不等于目标类型 |
|
t1(t2) |
类型和/或属性名 |
源(目标)类型不是由右边的名字指出的类型集的一个成员 | |
|
r1 |
r2 |
源角色不等于目标角色 | |
|
r1(r2) |
角色名 |
源(目标)角色不是由右边角色指出的角色集的一个成员 | |
|
u1 |
u2 |
源用户不等于目标用户 | |
|
u1(u2) |
用户名 |
源(目标)用户不是由右边用户名指出的用户集的一个成员 | |
|
eq |
r1 |
r2 |
源角色等于目标角色,和r1= =r2的语义相同 |
|
dom |
r1 |
r2 |
源角色优先于目标角色 |
|
domby |
r1 |
r2 |
目标角色优先于源角色 |
|
incomp |
r1 |
r2 |
源角色和目标角色不可比 |
| 回书目 上一节 下一节 |