`
yangyou230
  • 浏览: 1647990 次
文章分类
社区版块
存档分类

COM安全编程

 
阅读更多
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。
负责控制方法内部执行和启动服务进程时采用谁的令牌。扮演的实质就是服务器是否能够使用客户的令牌对系统资源进行调用。
COM的安全设置参考
主要包括:
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
COM的安全设置方式:
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安全性编程

    Windows安全机制一向被认为是一个枯燥而难懂的问题。多年来,有关安全机制编程的实例仅仅是在...本书是介绍COM(+)安全机制最全面的书籍,精选自作者对COM安全机制问题诊断的丰富经验和DCOM邮件发送清单上的信件...

    精通PKI网络安全认证技术与编程实现_PDF书签高清版.7z.005(共5个压缩包)

    内容简介回到顶部↑ pki是解决开放式互联网络信息安全需求的成熟体系...下载中: [精通PKI网络安全认证技术与编程实现].马臣云 & 王彦.配套光盘.rar | 10.8 MB http://hotfile.com/dl/78343749/98d1473/PKI.__..rar.html

    COM/DCOM编程指南

    Microsoft 对象技术概述、对象的演变、创建COM对象和接口、实现COM客户和服务器、使用MFC进行以COM编程、使用聚合模拟继承、使用本地服务器打破过程边界、使用ActiveX模板库创建COM对象、分布式对象概述、安全性、...

    DOTNET安全编程下载

    在本书中,经验丰富的开发人员Adam Freeman和Allen Jones不仅通俗易懂地全面介绍了.NET的安全功能和API,而且还清晰地阐述了开发人员必须...如果用户想在编程领域快速取得进展,那么本书确实是一本不可多得的实用书籍。

    精通PKI网络安全认证技术与编程实现_PDF书签高清版.7z.003(共5个压缩包)

    内容简介 pki是解决开放式互联网络信息安全需求的成熟体系。...下载中: [精通PKI网络安全认证技术与编程实现].马臣云 & 王彦.配套光盘.rar | 10.8 MB http://hotfile.com/dl/78343749/98d1473/PKI.__..rar.html

    C# COM+编程指南

    .NET框架是Mocrosoft公司为适应Internet发展与市场形势而提出的开发平台。...如何用C#语言创建全新的符合.NET规范的COM+组件这些组件可用于事物处理、安全、事件、对象共享、事件排队心脏远程处理。

    C# COM编程指南

    C#是Microsoft公司为.NET框架量身定做的首选语言。本书向读者概要地介绍了.NET框架和通用...如何用C#语言创建全新的符合.NET规范的COM+组件,这些组件可用于事物处理、安全、事件、对象共享、事件排队以及远程处理。

    浅谈ASP.net安全编程

    于是,我们会想到很多安全措施,比如使用SSL、建立网上银行一样的强认证方式等,但是,对于大部分网站而言,可能这些方法具有一定的困难性,因为要实现这些比较强的安全措施,最起码需要一台服务器,在经济上显然...

    编程技巧 Dot_net的安全机制-电脑教程QQread_com

    编程技巧 Dot_net的安全机制-电脑教程QQread_com

    寒江独钓:Windows内核安全编程 高清 电子版文

    这也是我自己所见的唯一一本中文原创的从汇编和反汇编角度来学习Windows内核编程和信息安全软件开发的书。希望读者多多支持。有想购买的读者请发邮件给我。我会在本书出版的第一时间,回复邮件告知购买的方法。 ...

    s7200 usb ppi 编程电缆使用手册

    USB/PPI+是通过USB接口提供串行连接及RS485信号转换和PPI协议转换的编程电缆,在电脑中运行的驱动程序控制下,将电脑的USB接口仿真成传统串口(俗称COM口),从而使用现有的各种编程软件、通信软件和监控软件等。...

    java安全性编程指南(pdg)

    java安全性编程指南(pdg)(转载) www.pigkrtv.com

    [天书夜读-从汇编语言到Windows内核编程].谭文.邵坚磊.扫描版

    谭文:从2002年到2008年,从事信息安全类软件的Windows内核驱动的开发工作。从2008年开始参与一个主要涉及不同架构之间二进制指令的实时翻译技术的项目的开发。业余时间在驱动开发音(www.driverdevelop.com)以楚...

    C++编程思想 第2卷:实用编程技术(Bruce Eckel著)

    ·深入探究异常处理方法,清晰解释异常安全设计 ·介绍被认为是标准C++下一版特征之一的多线程处理编程技术,并提供最新研究成果 ·对书中包含的所有示例代码都提供免费下载,这些代码段经过多个软件平台和编译器...

    Python编程入门经典

    在Amazon.com上寻找 廉价商品 419 20.8.2 WishListBargainFinder 简介 422 20.8.3 向BittyWiki提供 REST API 425 20.8.4 使用REST Web服务 实现搜索和替换功能 428 20.9 XML-RPC 432 20.9.1 XML-RPC请求 434 20.9.2 ...

    Tcl_TK编程权威指南pdf

    Tcl_TK编程权威指南pdf 内容简介回到顶部↑Tcl/Tk是第一种能通过Windows、Macintosh和Solaris等主要平台处理企业级任务的脚本语言。本书共分为55章,依次详细讲述了Tcl基础、Tcl高级特性、TK基础、TK组件、TK详解、...

    C++编程思想 第2卷 实用编程技术

    在《C++编程思想第2卷实用编程技术》作者的个人网站www.BruceEckel.com上提供: ·《C++编程思想第2卷实用编程技术》的全文、源代码、练习解答指南、勘误表及补充材料。 ·《C++编程思想第2卷实用编程技术》相关...

    Windows驱动编程基础教程.doc

    这也是我自己所见的唯一一本中文原创的从汇编和反汇编角度来学习Windows内核编程和信息安全软件开发的书。希望读者多多支持。有想购买的读者请发邮件给我。我会在本书出版的第一时间,回复邮件告知购买的方法。 ...

    C#.NET网络编程.part1

    基于asp.net的网络编程 3.1 webforms 3.1.1 创建第一个web窗体 3.1.2 在web窗体上添加控件 3.1.3 将控件与数据绑定 3.1.4 webforms的事件响应 3.2 服务器端控件 3.3 自定义控件 3.3.1 创建...

Global site tag (gtag.js) - Google Analytics