Windows NT安全性API简介(1)
安全性在操作系统中应该是相当容易实现的,对吗?就是说,为任意对象指定某个安全级别所需要做的所有工作只是一个简单的函数调用,例如GrantAccessTo或者DenyAccessTo,对吗?
不幸的是,Windows NT安全性应用程序接口(API)看起来并不是那么简单。它包含了过多的与安全性有关的函数,并且仅仅为一个用户打开一个对象的工作就已经非常复杂了。
要正确使用安全性API,需要按照下面几个层次去理解:
- 第一个层次是理解数据结构:访问控制表(ACLs),访问控制元素(ACEs),安全性描述符(SDs)和安全性IDs (SIDs)。
- 第二个层次是理解ACLs的语义(虽然不需要理解它们是如何工作的)。根据ACLs建立顺序的不同,对同一个用户的访问可能允许,也可能不允许。
- 第三个层次是理解操作系统本身如何使用安全性。可以将安全性API理解成为服务器应用程序提供用来保护对象不被未授权的用户访问的服务集合,同事务日志帮助设备驱动程序和应用程序记录错误以及确认事件提供服务的方法相同。
在这些服务只被第三方应用程序使用时,相当容易理解安全性是如何工作的。然而,Windows NT是一个安全的操作系统,此外,基于Windows NT的网络也非常依赖于安全性。因此,安全性结合到系统的方法就显得很模糊。
谁需要安全?在进入任何细节之前,先要明确为什么会需要安全性。如果不是处于下面的情况,就根本不必为安全性担心:
正在写一个服务器应用程序,即几个用户都可以访问的一个应用程序,而且此服务器应用程序只限于为这些用户的一个子集提供数据结构。
注意这是一个相当广泛的定义。下面是满足条件的几个例子程序。
对于单机(没有连网的计算机),编写一个服务,Windows NT启动以后一直运行,并且有多个用户在此计算机上登录及退出。该服务提供的信息只对少数用户可见。例如,想收集使用模式或者登录数据,就可能只限于管理员访问该数据。
许多特权限制在系统级。例如,系统注册表受保护,使得只有具有特殊特权的用户能够向系统中添加设备驱动程序。这是由于安全性的原因。例如,一个恶意的用户能够利用设备驱动程序监控用户输入的能力窃取其它用户的工作。安全性也有助于系统的稳定。设想一个未经授权的用户安装了一个粗制滥造的设备驱动程序。当其它用户工作时,这样的驱动程序会造成系统崩溃。通过将注册新设备驱动程序的权利限制给可信赖的用户,能够防止Windows NT的计算机上出现这种情况。
许多在网络上工作得与单机上同样好的服务器程序得益于与安全性系统的某种挂钩。例如,一个数据库服务器可能同时为几个用户服务,某些用户不允许查看给定数据库中的某些数据。假设公司内的每个人都能够查询员工数据库。管理人员需要访问员工的全部信息,而其他人则应该只能看到工作头衔和办公室编号。如果将包含工资和奖金信息的字段限制于管理人员访问,就可以允许公司内所有的人使用同一个数据库,而不会危及安全性和机密。
安全性的微观视图安全性的一个问题是使用安全性API毫无新奇刺激可言。其他人编写的代码可以旋转茶壶、在窗口中显示动画、弹出很酷的Windows 95控件、通过MAPI来回发送数据等等,而安全性编程却总是令人厌烦的事情。
Windows NT安全性表现的非常复杂,相比之下,从微观水平上看则比较简单。每个Windows NT域(或域组)保存有一个该域所知道的用户的数据库。用户想要在Windows NT的域中工作,必须先使用一个用户名和口令证明自己。一旦安全性系统证明了口令,用户就会被关联到一个访问令牌,识别用户的内部数据结构。
关于Windows NT下安全性必须知道的首要事情是它是以用户为中心的;也就是说,试图访问受保护对象的每一行代码都必须与一个特殊用户关联,该用户必须用口令向客户机证明自己的身份。每次安全性检查都要依靠用户鉴别。例如,编写代码阻止Microsoft Excel访问一个对象是不可能的。可以保护一个对象防止Joe Blow运行Microsoft Excel访问,但是如果允许Carla Vip访问该对象,她可以使用Microsoft Excel或者其它喜欢的程序访问,只要Carla使用只有自己知道的口令向客户机证明自己的身份就行。
安全性API虽然看起来很复杂,但是却只完成两件事:
审核:每次对特定的对象试图有特定的操作时生成一个日志条目。
限制对象访问:客户程序调用的函数,可能会成功,失败返回错误代码5(访问被拒绝),或者因其它原因失败,取决于服务器如何指定特权。
用户可能不是直接看到错误信息,而是一个对话框,上面写着:“你没有特权将鸡蛋从纸盒中拿走。”弹出此对话框的程序内部可能包含下面的代码行:
if (!RemoveEggsFromCarton() && GetLastError() == ACCESS_DENIED)
AfxMessageBox("You do not have the privilege to remove the eggs from the carton");