COM安全的基础是Windows安全,在Windows中,安全的最小边界是进程,所以进程内组件通常不需要考虑安全,但是如果编写进程外组件,客户是否有权访问进程外的组件,就需要通过安全检查。
COM安全主要包括认证、访问控制和令牌管理:
检验发送消息者的身份的确就是他所声称的那个身份,并且消息也的确是他发送的。
我们可以选择认证协议,可以选择认证级别。下面的代码片断选择了Kerberos认证协议,并选择了在第一个方法调用时客户的安全凭证需要在服务器上认证
SOLE_AUTHENTICATION_SERVICE AuthSvc[1];
AuthSvc[0].dwAuthnSvc=RPC_C_AUTHN_GSS_KERBEROS;
AuthSvc[0].dwAuthzSvc=NULL;
AuthSvc[0].pPrincipalName=NULL;
hr=::CoInitializeSecurity(pAccessCtl.p,1,AuthSvc,NULL,RPC_C_AUTHN_LEVEL_CONNECT,RPC_C_IMP_LEVEL_IDENTIFY ,NULL,EOAC_ACCESS_CONTROL,NULL);
1)允许谁启动服务器进程
在注册表中组件的APPID键中有一项LaunchPermission,记录了系统中可以启动服务器进程的账号的二进制码,通常我们创建了EXE形式的组件后,注册表中并没有这一项,需要通过DCOMNCNFG.EXE来设置。如果启动进程时找不到这一项,会从HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Ole/中寻找DefaultLaunchPermission的值。如果连DefaultLaunchPermission都找不到,系统将拒绝任何激活请求。
2)检验访问者是否具有权限访问服务器的对象
在注册表中组件的APPID键中有一项AccessPermission,记录了系统中可以访问服务器进程的账号的二进制码。同样我们可以通过DCOMNCNFG.EXE进行设置。如果跨进程调用时COM没有找到AccessPermission,就会查找机器范围内有无默认设置,通常找不到,这时,COM会创建一个新的访问控制列表,只允许SYSTEM账号访问。
启动服务器的进程权限检查总是通过注册表来设置,而访问进程的权限也可以通过调用
CoInitializeSecurity函数来解决。我们可以通过将IAccessControl接口作为第一个参数传递给该函数,同时指定dwCapabilities参数为EOAC_ACCESS_CONTROL。
负责控制方法内部执行和启动服务进程时采用谁的令牌。扮演的实质就是服务器是否能够使用客户的令牌对系统资源进行调用。
主要包括:
1)认证服务----使用什么安全软件包进行安全检查
可以同时使用多个安全包,也可以为不同的接口代理配置不同的安全包
目前的Windows平台上提供的安全包参考MSDN链接:ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_m2z_22yg.htm
2)授权服务
参考ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_m2z_77js.htm
3)主要名称
1)---3)项都包含在SOLE_AUTHENTICATION_SERVICE结构中,该结构作为参数传递给CoInitializeSecurity函数。
4)认证级别
ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_m2z_3lo8.htm
5)扮演级别
ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_m2z_2jco.htm
1)注册表设置(可以通过DCOMCNFG.EXE程序调整)
组件的APPID健,比如我们创建了一个EXE形式的组件Server,注册表中APPID默认是没有安全设置,如果我们使用了DCOMCNFG.EXE进行配置,就可以看到注册表中多出了一项AuthenticationLevel,值为0x00000002,身份验证级别为连接。
通过DCOMCFNG.EXE我们还可以设置访问权限、启动权限、进程用什么身份令牌运行,如图:
MSDN: ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/com/htm/security_1xbb.htm
2)调用API函数设置
将忽略组件注册表中保存的APPID值对应的安全设置
安全协商机制是COM在创建一个新的代理时,为该代理进行安全设置的一个过程。
(参见ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_m2z_22yg.htm)
客户和服务器都可以通过调用CoInitializeSecurity函数进行自己的安全设置。CoInitializeSecurity用来设置进程内的默认的安全设置。注意:这里的客户和服务器是相对的,一个组件当它调用另一个进程外的组件的时候,它是客户,当它被另一个程序调用时它又是服务器。
客户可以设置的包括:
an authentication level 认证级别
an impersonation level 扮演级别
the authentication identity 认证身份
capabilities
服务器可以设置的包括:
an ACL 安全描述表
a list of authentication service/authorization service/principal name tuples
一组 认证服务/授权服务/主要名称
and an authentication level 认证级别
当COM对客户和服务器的安全设置进行协商时,COM会选择客户和服务器的认证服务中相同的作为认证服务,同时COM选择的认证级别是两者的设置中最高的,扮演级别取决于客户端的设置。当COM选定了适合客户和服务器的安全设置后,新创建的客户端的接口代理就继承了这个安全设置,但是客户端仍然可以调用IClientSecurity::SetBlanket对接口代理的安全设置进行修改。
参考MSDN:ms-help://MS.MSDNQTR.2003FEB.2052/com/htm/cmf_a2c_8ayh.htm
例一:服务器安全设置
extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/, int nShowCmd)
{
//访问控制设置:允许cs账号访问组件,但是拒绝guest账号
CComPtr<IAccessControl> pAccessCtl;
HRESULT hr=pAccessCtl.CoCreateInstance(CLSID_DCOMAccessControl);
ACTRL_ACCESS_ENTRYW rgaae[]=
{
{ {0,NO_MULTIPLE_TRUSTEE,TRUSTEE_IS_NAME,TRUSTEE_IS_USER,L"FREEBIRD//guest"},ACTRL_ACCESS_DENIED,COM_RIGHTS_EXECUTE,0,NO_INHERITANCE,0},
//{ {0,NO_MULTIPLE_TRUSTEE,TRUSTEE_IS_NAME,TRUSTEE_IS_GROUP,L"FREEBIRD//Administrators"},ACTRL_ACCESS_ALLOWED,COM_RIGHTS_EXECUTE,0,NO_INHERITANCE,0},
{ {0,NO_MULTIPLE_TRUSTEE,TRUSTEE_IS_NAME,TRUSTEE_IS_USER,L"FREEBIRD//cs"},ACTRL_ACCESS_ALLOWED,COM_RIGHTS_EXECUTE,0,NO_INHERITANCE,0}
};
ACTRL_ACCESS_ENTRY_LISTW aael={sizeof(rgaae)/sizeof(*rgaae),rgaae};
ACTRL_PROPERTY_ENTRYW ape={0,&aael,0};
ACTRL_ACCESSW aa={1,&ape};
hr=pAccessCtl->SetAccessRights(&aa);
/////////////////////////////
SOLE_AUTHENTICATION_SERVICE AuthSvc[1];
AuthSvc[0].dwAuthnSvc=RPC_C_AUTHN_GSS_KERBEROS;
AuthSvc[0].dwAuthzSvc=NULL;
AuthSvc[0].pPrincipalName=NULL;
//注意:传递RPC_C_IMP_LEVEL_DEFAULT会出错
hr=::CoInitializeSecurity(pAccessCtl.p,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_CONNECT,RPC_C_IMP_LEVEL_IDENTIFY ,NULL,EOAC_ACCESS_CONTROL,NULL);
return _AtlModule.WinMain(nShowCmd);
}
如果我们把{ {0,NO_MULTIPLE_TRUSTEE,TRUSTEE_IS_NAME,TRUSTEE_IS_USER,L"FREEBIRD//cs"},ACTRL_ACCESS_ALLOWED,COM_RIGHTS_EXECUTE,0,NO_INHERITANCE,0}中的红色部分
修改成ACTRL_ACCESS_DENIED,这样当我们通过cs登陆windows,然后执行一个客户程序,而这个客户程序没有显式调用CoInitializeSecurity函数的情况下,创建进程外组件将会遇到E_ACCESSDENIED。这里连激活权限都已经禁止了,我认为ACTRL_ACCESS_DENIED中的ACCESS用词不当。客户端代码如下:
#include "stdafx.h"
#import "Server.tlb" no_namespace raw_interfaces_only named_guids
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
CComPtr<IA> pA;
HRESULT hr=pA.CoCreateInstance(__uuidof(A));
if(hr==E_ACCESSDENIED)
{
cout<<"激活请求被拒绝"<<endl;
pA.Release();
::CoUninitialize();
return 1;
}
hr=pA->f();
if(hr!=S_OK)
{
cout<<"调用f方法时被拒绝"<<endl;
pA.Release();
::CoUninitialize();
return 1;
}
pA.Release();
::CoUninitialize();
return 0;
}
// Client.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#import "Server.tlb" no_namespace raw_interfaces_only named_guids
#include <iostream>
#include <iaccess.h>
//#include <objidl.h>
#include <objbase.h>
using namespace std;
#pragma comment(lib,"ole32.lib")
HRESULT SetSecurity();
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
HRESULT hr=SetSecurity();
if(hr!=S_OK)
{
cout<<"设置客户端安全出错"<<endl;
return 1;
}
CComPtr<IA> pA;
hr=pA.CoCreateInstance(__uuidof(A));
if(hr==E_ACCESSDENIED)
{
cout<<"激活请求被拒绝"<<endl;
pA.Release();
::CoUninitialize();
return 1;
}
hr=pA->f();
if(hr!=S_OK)
{
cout<<"调用f方法时被拒绝"<<endl;
pA.Release();
::CoUninitialize();
return 1;
}
pA.Release();
::CoUninitialize();
return 0;
}
HRESULT SetSecurity()
{
SOLE_AUTHENTICATION_SERVICE AuthSvc[1];
AuthSvc[0].dwAuthnSvc=RPC_C_AUTHN_GSS_KERBEROS;
AuthSvc[0].dwAuthzSvc=NULL;
AuthSvc[0].pPrincipalName=NULL;
//注意:传递RPC_C_AUTHN_LEVEL_NONE以外的参数会出错
//注意:传递非NULL的IAccessControl接口指针作为第一个参数会出错
HRESULT hr=::CoInitializeSecurity(NULL,1,AuthSvc,NULL,RPC_C_AUTHN_LEVEL_NONE,RPC_C_IMP_LEVEL_IDENTIFY,NULL,EOAC_ACCESS_CONTROL,NULL);
return hr;
}
该函数用于激活指定计算机上的组件,多用于客户端。
该函数在CoInitializeSecurity函数后面调用。具体使用方法可以参考下面的函数:
SetClientDefaultSecurity(感谢高岿、程悟、张亮的整理)
// 设置客户方默认安全级别
HRESULT SetClientDefaultSecurity(
LPOLESTR wszUser, // 用户名
LPOLESTR wszDomain, // 服务器名
LPOLESTR wszPassword, // 密码
REFCLSID rclsid, // 组件GUID
MULTI_QI* mqi, // 多接口数组
int nItf // 数组中接口数
)
{
HRESULT hr = 0;
IUnknown* pIUnk = 0;
//
// The COAUTHIDENTITY structure represents a username and password
//
COAUTHIDENTITY auid;
auid.User = wszUser;
auid.UserLength = wcslen(wszUser);
auid.Domain = wszDomain;
auid.DomainLength = wcslen(wszDomain);
auid.Password = wszPassword;
auid.PasswordLength = wcslen(wszPassword);
auid.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
//
// The COAUTHINFO structure specifys the authentication settings
// used while making a remote activation request from the client
// machine to server machine.
//
COAUTHINFO auinfo;
auinfo.dwAuthnSvc = RPC_C_AUTHN_WINNT;
auinfo.dwAuthzSvc = RPC_C_AUTHZ_NONE;
auinfo.pwszServerPrincName = NULL;
auinfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
auinfo.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
auinfo.pAuthIdentityData = &auid;
auinfo.dwCapabilities = EOAC_NONE;
//
// Indentifies a remote machine resource to the new or enhanced
// activation functions.
//
COSERVERINFO svrinfo;
svrinfo.dwReserved1 = 0;
svrinfo.dwReserved2 = 0;
svrinfo.pAuthInfo = &auinfo;
svrinfo.pwszName = wszDomain;
hr = CoCreateInstanceEx(rclsid, 0, CLSCTX_ALL, &svrinfo, nItf, mqi);
if ( FAILED(hr) )
return hr;
pIUnk = (IUnknown*) mqi[0].pItf;
if ( pIUnk == NULL )
return hr;
IClientSecurity* pcs = 0;
hr = pIUnk->QueryInterface(IID_IClientSecurity, (void**) &pcs);
if ( FAILED(hr) )
return hr;
for (int i=0; i < nItf; i++)
{
hr = pcs->SetBlanket(mqi[i].pItf,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
&auid,
EOAC_NONE);
if ( FAILED(hr) )
{
pcs->Release();
return hr;
}
}
pcs->Release();
return S_OK;
}
该函数主要分为两个部分:第一部分是调用CoCreateInstanceEx函数在指定计算机上创建组件对象,复杂在于传递的参数,但是只要搞清楚了什么是认证、扮演等COM安全术语,就没有多大的问题了;第二部分是调用IClientSecurity::SetBlancket对接口代理进行有别于进程的安全设置。
2005-9-27
陈抒
分享到:
相关推荐
### 网络安全编程基础知识点详解 #### 一、网络安全编程概述 网络安全编程是确保网络数据传输过程中信息完整性和保密性的关键技术之一。随着互联网技术的发展,网络安全的重要性日益凸显,网络安全编程也成为了...
Windows安全机制一向被认为是一个枯燥而难懂的问题。多年来,有关安全机制编程的实例仅仅是在...本书是介绍COM(+)安全机制最全面的书籍,精选自作者对COM安全机制问题诊断的丰富经验和DCOM邮件发送清单上的信件...
### JSP安全编程实例浅析 #### 一、引言 在现代Web开发中,JavaServer Pages (JSP)作为一种动态网页技术被广泛应用于构建复杂的企业级应用。然而,随着互联网的发展,各种针对Web应用程序的安全威胁也日益增多。...
网络安全编程基础是IT领域的核心部分,它涉及到操作系统编程,尤其是Windows平台下的C/C++语言应用。C语言在网络安全编程中有四个主要的发展阶段,每个阶段都伴随着具体的案例来深入理解。本章将详细阐述Windows操作...
VC++网络安全编程基础 VC++网络安全编程基础是指在网络安全领域使用C/C++语言实现各种编程技术,包括Socket编程、注册表编程、定时器编程、驻留程序编程和多线程编程等。下面是对该领域的详细介绍: 1. 网络安全...
COM(Component Object Model)是微软提出的一种组件对象模型,它是一种二进制标准,允许不同编程语言之间进行互操作。Delphi,作为基于Pascal语言的集成开发环境,以其高效性和与COM的紧密集成而闻名。在“Delphi ...
【网络安全编程基础】是关于如何在信息技术领域中确保网络及应用程序的安全性,特别是通过使用C/C++语言进行编程。网络安全编程不仅涉及编写安全的代码,还涵盖了对操作系统底层原理的理解,如Windows操作系统。 ...
Microsoft 对象技术概述、对象的演变、创建COM对象和接口、实现COM客户和服务器、使用MFC进行以COM编程、使用聚合模拟继承、使用本地服务器打破过程边界、使用ActiveX模板库创建COM对象、分布式对象概述、安全性、...
内容简介回到顶部↑ pki是解决开放式互联网络信息安全需求的成熟体系...下载中: [精通PKI网络安全认证技术与编程实现].马臣云 & 王彦.配套光盘.rar | 10.8 MB http://hotfile.com/dl/78343749/98d1473/PKI.__..rar.html
COM+,全称为Component Object Model Plus,是微软公司推出的一种组件技术,它是COM(Component Object Model)的增强版,主要用于构建分布式、事务处理、安全性和性能优化的企业级应用程序。COM+将COM的组件化思想...
本篇将深入探讨COM高级编程的知识点,帮助你掌握COM的核心原理和实践技巧。 1. **COM基础概念**:COM是基于接口的编程模型,它定义了组件如何通过接口进行通信。每个COM对象都有一个全局唯一的标识符(CLSID),并...
通过分析和运行这些源码,可以直观地理解C# COM编程的实际应用,例如如何创建COM服务器,如何在C#客户端中消费这些服务,以及如何处理线程安全性和错误处理等问题。 毕业设计和开题报告是学习过程中的重要环节,这...
【网络安全编程基础】是计算机网络安全教程中的重要章节,主要探讨如何使用C和C++语言进行系统编程以确保网络的安全性。网络安全编程不仅涉及语言技能,还需要深入理解操作系统的基本原理。 在这一章中,首先提到了...
这也是我自己所见的唯一一本中文原创的从汇编和反汇编角度来学习Windows内核编程和信息安全软件开发的书。希望读者多多支持。有想购买的读者请发邮件给我。我会在本书出版的第一时间,回复邮件告知购买的方法。 ...
3. **考虑线程安全问题**:在多线程环境中使用COM时,需要确保组件具有良好的线程安全性。 4. **错误处理**:正确处理COM调用中的异常和错误,提高程序的健壮性。 #### 五、COM组件实例 假设我们要创建一个简单的...
《Delphi.COM深入编程》是一本专为Delphi开发者深入理解COM(Component Object Model)技术而编写的书籍。COM是微软提出的一种组件标准,它在Windows平台上广泛应用于软件开发,尤其是面向对象的组件构建。Delphi,...
COM+编程指南是一本深入解析COM+技术的书籍,其提供的源代码可以帮助读者更好地理解和实践COM+编程。COM+是Microsoft公司开发的一种组件对象模型,它扩展了传统的COM(Component Object Model),旨在提供更高级别的...
7. **线程模型和多线程安全性**:理解COM组件的线程模型,如Apartment Threading(公寓模型)、Free Threading(自由线程模型)和Neutral Threading(中立线程模型),以及如何处理多线程安全问题。 8. **延迟加载...
《C#.COM+编程指南》是一本专注于C#与COM+技术结合应用的教程,旨在帮助开发者深入理解和熟练掌握在.NET环境下使用COM+组件进行软件开发的方法和技巧。COM+,全称为Component Object Model Plus,是微软推出的一种...