行云无鸣

2008-08-09

BCB6+Indy10完成HTTPS验证服务器证书

Filed under: 未分类 — 标签:, , , , , , — hellyguo @ 10:19

在项目中用到了HTTPS,但仅仅是加密,没有使用证书验证。客户要求加入。
看着Indy简陋的文档,翻阅了无数Delphi英文及中文网页后,始终不得要领。
在拜读了IndySSL – using certificate authentication – Client side issues [zz]一文(此文源头已无法打开,故就不提供URL了,请诸君自行Google)后,终于开始有点头绪了:得设置校验模式,并编写回调函数处理校验事件。
拙劣的BCB功底,让我在申明函数时吃够了苦!
.h
//必须申明函数指针,而且是闭包的,也就是说必须封闭在某个Class中
typedef bool __fastcall (__closure *OnDealVerifyPeer)(TIdX509* Certificate) ;
//在某Class中申明函数,参数与上述函数指针一致
public:
bool __fastcall OnMyDealVerifyPeer(TIdX509* Certificate);

.cpp
//具体回调函数代码
bool __fastcall THttpText::OnMyDealVerifyPeer(TIdX509* Certificate)
{
Application->MessageBoxA(Certificate->Subject->OneLine.c_str(),"info",0);
return true;
}
//初始化SSL环境
void __fastcall InitHttp (TIdHTTP *Http, OnDealVerifyPeer DealMethod1, OnDealStatusInfo DealMethod2)
{
...;
if (NeedSecurity)
{
TIdSSLIOHandlerSocket *InterceptSSL = new TIdSSLIOHandlerSocket (NULL);
//校验模式设置
TIdSSLVerifyModeSet verifyModeSet ;
verifyModeSet << sslvrfPeer << sslvrfFailIfNoPeerCert << sslvrfClientOnce ;
InterceptSSL->SSLOptions->VerifyMode = verifyModeSet;
//校验深度
InterceptSSL->SSLOptions->VerifyDepth = 3;
//SSL运作模式,一度曾认为该参数是校验模式,卡死在这里。在这里,我是客户端,故设置为Client
InterceptSSL->SSLOptions->Mode = sslmClient;
//SSL版本
InterceptSSL->SSLOptions->Method = sslvSSLv3;
//证书配对校验的回调函数设置
InterceptSSL->OnVerifyPeer = DealMethod1;
//SSL状态变化时的回调函数,可在此处设置,借以在回调函数中输出SSL握手信息
InterceptSSL->OnStatusInfo = DealMethod2;
Http->IOHandler = InterceptSSL;
}
...;
}

在尝试了上述代码后,发现的确可以在回调函数中获得证书信息。但,却只是得到根证书的信息。而且,一旦开启了校验,原本可以正常运行的SSL,就会无法连接上服务器,报“SSL Error”。
在诸多Delphi代码中搜寻后,在某pas文件发现了下述语句:

// TODO: Indy9 problems... if we try and verify, it disconnects us.

伤心啊,我用的也是Indy9,看来得升级了。
安装好Indy10后,再度编译程序,就直接报错了:Indy10相对于Indy9,变化还蛮大。
.h
//必须申明函数指针,而且是闭包的,也就是说必须封闭在某个Class中,添加了两个参数
typedef bool __fastcall (__closure *OnDealVerifyPeer)(TIdX509* Certificate) ;
//在某Class中申明函数,参数与上述函数指针一致,添加了两个参数
public:
bool __fastcall OnMyDealVerifyPeer(TIdX509* Certificate,bool aOK,int depth);

.cpp
//具体回调函数代码,添加了两个参数
bool __fastcall THttpText::OnMyDealVerifyPeer(TIdX509* Certificate,bool aOK,int depth)
{
Application->MessageBoxA(Certificate->Subject->OneLine.c_str(),"info",0);
return true;
}
//初始化SSL环境
void __fastcall InitHttp (TIdHTTP *Http, OnDealVerifyPeer DealMethod1, OnDealStatusInfo DealMethod2)
{
...;
if (NeedSecurity)
{
//TIdSSLIOHandlerSocket不存在了,改为TIdSSLIOHandlerSocketOpenSSL
TIdSSLIOHandlerSocketOpenSSL *InterceptSSL = new TIdSSLIOHandlerSocketOpenSSL (NULL);
//校验模式设置
TIdSSLVerifyModeSet verifyModeSet ;
verifyModeSet << sslvrfPeer << sslvrfFailIfNoPeerCert << sslvrfClientOnce ;
InterceptSSL->SSLOptions->VerifyMode = verifyModeSet;
//校验深度
InterceptSSL->SSLOptions->VerifyDepth = 3;
//SSL运作模式,一度曾认为该参数是校验模式,卡死在这里。在这里,我是客户端,故设置为Client
InterceptSSL->SSLOptions->Mode = sslmClient;
//SSL版本
InterceptSSL->SSLOptions->Method = sslvSSLv3;
//根证书,直接从Windows的证书库中导出的VeriSign根证书
InterceptSSL->SSLOptions->RootCertFile = "VeriSign.cer";
//证书配对校验的回调函数设置
InterceptSSL->OnVerifyPeer = DealMethod1;
//SSL状态变化时的回调函数,可在此处设置,借以在回调函数中输出SSL握手信息
InterceptSSL->OnStatusInfo = DealMethod2;
Http->IOHandler = InterceptSSL;
}
...;
}

自此,终于成功在回调函数处获得整个证书链上的每个证书信息,可以进行进一步的校验了

2008-04-14

ihs+was报"Invalid method in request \x80L\x01\x03"

Filed under: 未分类 — 标签:, , , — hellyguo @ 09:43

配置完成,报错:

[Fri Apr 11 13:01:20 2008] [error] [client x.x.x.x] Invalid method in request \x80L\x01\x03

千辛万苦排查,怎么都排查不出原因。结果是URL输入错误,输入了本地回环地址!配置SSL后,是无法使用本地回环地址来访问HTTPS服务的。

%d 博主赞过: