|
Popcornrus 0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
||||
|
1 |
||||
|
15.09.2016, 19:25. Показов 15367. Ответов 17 Метки delphi 7, delphi7, error connecting with ssl, https, indy, indy 10, indy10, libeay32, method, ssl, ssl library, ssleay32, tidhttp, tidsocksinfo, tidssliohandlersocket, tidssloptions, tidssloptions.method, tidsslversion (Все метки)
При компиляции проекта, и нажатия на кнопку, выходит ошибка указанная в заголовке!
__________________
0 |
|
587 / 454 / 147 Регистрация: 09.12.2013 Сообщений: 2,385 Записей в блоге: 2 |
|
|
15.09.2016, 21:24 |
2 |
|
Если с Библиотеки libeay32.dll ssleay32.dll разобрались (то есть они подходящие и с большинства сайтов качает нормально), то… Добавлено через 44 секунды Добавлено через 33 секунды Добавлено через 41 секунду Добавлено через 2 минуты
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
15.09.2016, 22:53 [ТС] |
3 |
|
Можно твой скайп? Если можно.
0 |
|
BOGG ART 587 / 454 / 147 Регистрация: 09.12.2013 Сообщений: 2,385 Записей в блоге: 2 |
||||||||
|
16.09.2016, 00:03 |
4 |
|||||||
|
Не обладаю.
Перепробуйте по очереди все TIdSSLVersion что имеется в вашей версии, возможно что-то покажет.
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 14:02 |
5 |
|
Popcornrus, у меня абсолютно не выдал ошибок. Я это писал в Вашей предыдущей теме. Вы заменили библиотеки на те, которые я выкладывал? Проверено на XE10 Seattle Upd1+c библиотеками из архива: текстовый файл был успешно загружен в каталог с приложением. Не по теме: BOGG ART, всё работает у него. Опции менять не надо. Достаточно библиотеки заменить и всё. Голову морочат просто.
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 15:09 [ТС] |
6 |
|
droider, не работает ‘Could not load SLL Library’ Добавлено через 8 минут
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 15:15 |
7 |
|
Popcornrus, сказки не рассказывайте. Сейчас приложу проект.
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 15:32 [ТС] |
8 |
|
Может это из-за того что у меня Indy 9 и Delphi 7?
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 15:35 |
9 |
|
Popcornrus, пробуйте
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 15:51 [ТС] |
10 |
|
Само приложение запускается, но я не могу редактировать его!
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 16:24 |
11 |
|
Popcornrus, Вы видите, что это Ваш код и что он работает?? Добавлено через 45 секунд
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 16:51 [ТС] |
12 |
|
У вас мой код работает я согласен, но у меня в Delphi7 редактировать не получается! Добавлено через 1 минуту
0 |
|
droider 4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
||||||||
|
16.09.2016, 17:00 |
13 |
|||||||
|
у меня в Delphi7
не компилируется Ну замените
на
Добавлено через 1 минуту Не по теме: А вообще выкиньте Delphi 7 на «помойку»
0 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 17:10 [ТС] |
14 |
|
Теперь нету ошибок,но он не качает
0 |
|
BOGG ART |
|
16.09.2016, 17:12
|
|
Не по теме: Нормальная Делфи7, нормальная. Заголовочники новые поставить и всё.
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 17:15 |
16 |
|
Ну как не качает когда файл лежит в папке с приложением? Добавлено через 1 минуту Добавлено через 46 секунд Не по теме:
Нормальная Делфи7, нормальная Если у него не «обрубок» типа Lite и пр.
1 |
|
0 / 0 / 0 Регистрация: 07.09.2016 Сообщений: 39 |
|
|
16.09.2016, 17:33 [ТС] |
17 |
|
Спасибо всем, была верcия Lite
0 |
|
4881 / 2754 / 848 Регистрация: 04.10.2012 Сообщений: 10,039 |
|
|
16.09.2016, 17:35 |
18 |
|
Не по теме: BOGG ART, я был прав. У ТС стояла «Delphi 7 Lite Edition» — самопальная, урезанная сборка Добавлено через 1 минуту
0 |
I’m trying to connecto to this url, just using a get request.
Goberment page
But always get the error EIdOSSLConnectError «Error connecting with SSL»
The code I use, is this, it works with other pages, but not this one
IdHTTP1.HandleRedirects := true;
IdHTTP1.AllowCookies := true;
IdHTTP1.IOHandler := TIdSSLIOHandlerSocket.Create(IdHTTP1);
IdHTTP1.CookieManager := TIdCookieManager.Create(IdHTTP1);
with TIdSSLIOHandlerSocket(IdHTTP1.IOHandler) do begin
SSLOptions.Method := sslvTLSv1;
SSLOptions.Mode := sslmUnassigned;
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 0;
PassThrough := True;
end;
IdHttp1.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0';
IdHTTP1.RedirectMaximum := 30;
sHtml := IdHTTP1.Get('https://loginc.mat.sat.gob.mx/nidp/app/login?id=XACCertiSAT&sid=0&option=credential&sid=0');//<----Error here
Delphi 7, Indy 9.00.10
Thanks for any advice
asked Aug 15, 2017 at 16:16
6
It seems that site wants TLS v1.2, since that is what gets negotiated when I go there with a browser.
Also, if in my PaleMoon browser I next go to about:config and set the pref named security.tls.version.max to 1, I revisit your url then wit TLS v1.0 and I get:
Secure Connection Failed
An error occurred during a connection to loginc.mat.sat.gob.mx.
Cannot communicate securely with peer: no common encryption algorithm(s).
(Error code: ssl_error_no_cypher_overlap)
However, other sites I tried (such as banks) still work okay with TLS v1 set that way. It seems your target site is finicky, so I’d try adjusting your line:
SSLOptions.Method := sslvTLSv1;
answered Aug 15, 2017 at 18:01
1
Проверка серверного сертификата SSL в Delphi
Понадобилось мне осуществить проверку серверного сертификата в моей программе на Delphi. Эта программа была написана довольно давно, на Delphi 7 с использованием Indy 9.
Вот как выглядит проверка сертификата:
Если попробовать выполнить выше приведенный код, то результат будет всегда такой: Error connecting with SSL.
Проблема тут в том, что в Indy используется OpenSSL, который не умеет работать с хранилищем сертификатов Windows и не может проверить подписан ли сертификат, полученный от сервера, одним из доверенных корневых сертификатов из этого хранилища.
Посмотрим в исходник модуля IdSSLOpenSSL. В нем есть такая функция:
Эта callback-функция вызывается при проверке сертификата библиотекой OpenSSL, и для того, чтобы не случилось ошибки “Error connecting with SSL” она должна возвращать значение Result = 1. Видно, что VerifyCallback возвращает Result = 1 только в том случае, когда Ok > 0. А параметр Ok для последнего сертификата в цепочке проверяемых всегда будет = 0, т.к. корневой сертификат, с помощью которого его можно проверить, не определен.
Таким образом, задача в следующем: проверить — подписан ли последний в цепочке сертификат одним из доверенных корневых (ROOT) сертификатов в хранилище Windows, и если подписан, то присвоить Ok = 1.
К сожалению, при проектировании Indy 9 было допущено много ошибок, и для того, чтобы решить поставленную задачу, придется вносить изменения в код модуля IdSSLOpenSSL, а затем перекомпилировать пакет
Indy70.dpk.
Внесем следующие изменения:
1. Изменим определение события TVerifyPeerEvent на следующее:
2. Изменим определение метода DoVerifyPeer в классах TIdSSLIOHandlerSocket и TIdServerIOHandlerSSL на следующее:
3. Изменим реализации метода DoVerifyPeer в классах TIdSSLIOHandlerSocket и TIdServerIOHandlerSSL на следующие:
4. Добавим public-свойство X509 классу TIdX509:
5. Изменим функцию VerifyCallback на следующую:
Теперь нужно перекомпилировать Indy70.dpk.
В результате наших изменений обработчик события OnVerifyPeer получает два дополнительных параметра: Error — код ошибки проверки сертификата (это может быть, например, OPENSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) и параметр Ok, который можно изменить. Ниже приведена реализация обработчика:
В этом обработчике использованы функции OpenSSL и СryptoAPI, объявления которых можно найти в libeay32.pas и wcrypt2.pas. Собственно, из-за необходимости подключения этих модулей я и вынес проверку в обработчик события OnVerifyPeer, вместо того, чтобы сделать все в функции VerifyCallback.
Подключаем обработчик SSLIOHandlerVerifyPeer к IdSSLIOHandlerSocket и окончательно получаем загрузку страницы по протоколу https: с проверкой серверного сертификата:
Источник
Delphi error connection with ssl
Воть.
procedure TForm1.Button1Click(Sender: TObject);
var
data: TIdMultiPartFormDataStream;
red: TIdMultiPartFormDataStream;
begin
data := TIdMultiPartFormDataStream.Create;
red := TIdMultiPartFormDataStream.Create;
data.AddFormField(‘request’, req_type);
data.AddFormField(‘id=’, req_id );
data.AddFormField(‘checkid=’,req_ch eckid);
data.AddFormField(‘product=’,req_pr oduct );
data.AddFormField(‘value=’, req_value);
data.AddFormField(‘account’, req_account );
data.AddFormField(‘timeout=’, req_timeout);
data.AddFormField(‘cnfmode=’, req_cnfmode );
red.AddFormField(‘X-Eport-Auth’,’point=’+point+’;’+’card=’+ca rd+’;’+’pin=’+pin);
red.AddFormField(‘X-Eport-Mode’, ‘1’ );
red.AddFormField(‘Content-Type’,’text/plain; charset=koi8-r’);
IdHTTP1.IOHandler:=IdSSLIOHandlerSo cket1;
IdSSLIOHandlerSocket1.SocksInfo:=Id http1.Socket.SocksInfo;
Выдаёт Error connecting with SSL
================
Короче вот код на Перле —>
Мне надо его перевести в Delphi
помогите срочно надо.
use strict;
use Net::SSLeay qw(post_https make_headers);
# номер точки e-port
my $point = 123;
# номер карты e-port
my $card = «249000-00000»;
# пин-код карты e-port
my $pin = «1234567890»;
##### исходные данные запроса операции #####
# тип запроса (OPERATION/CONFIRM/CANCEL)
my $req_type = «OPERATION»;
# идентификатор операции
my $req_id = «12345»;
# номер чека
my $req_checkid = «12345»;
# артикул товара из справочника(в данном случае — МТС ESPP)
my $req_product = 4420;
# объем сделки (в данном случае — 100 рублей)
my $req_value = «100.00RUR»;
# реквизиты л/с клиента, объединенные точкой с запятой
# в данном случае ракуизит один — номер телефона
my $req_account = «9161234567»;
# тайм-аут запроса в синхронном режиме
my $req_timeout = 15;
# режим транзакции (0 — однофазный, 1 — двухфазный)
my $req_cnfmode = 1;
##### Формирование запроса text/plain#####
my $CRLF = «rn»;
my $request = $req_type . $CRLF .
«id=» . $req_id . $CRLF .
«checkid=» . $req_checkid . $CRLF .
«product=» . $req_product . $CRLF .
«value=» . $req_value . $CRLF .
«account=» . $req_account . $CRLF .
«timeout=» . $req_timeout . $CRLF .
«cnfmode=» . $req_cnfmode . $CRLF;
print «=== Operation Request ===n»;
print $request;
##### формируем http-заголовки запроса #####
my $reqHeaders;
# добавляем заголовок аутентификации
$reqHeaders .= make_headers(«X-Eport-Auth»=>»point=$point; card=$card; pin=$pin»);
# добавляем признак синхронного режима
$reqHeaders .= make_headers(«X-Eport-Mode»=>»1»);
# указываем кодировку сообщения и формат данных
$reqHeaders .= make_headers(«Content-Type»=>»text/plain; charset=koi8-r»);
##### обмениваемся данными с сервером #####
my $host = «dealer.e-port.ru»;
my $port = «443»;
my $uri = «/cp/fe»;
my ($body, $status, %resHeaders) = post_https($host,$port,$uri,$reqHea ders,$request);
# http-код ответа указывает на ошибку
if($status ne ‘HTTP/1.1 200 OK’) <
print «HTTP ERROR: $statusn»;
print «$bodyn»;
# http-код ответа 200 (успешно)
>else <
# разбираем построчно
my @lines = split(/rn/, $body);
my $i = 0;
# ответ по операции должен начинаться с ключевого слова «RESULT»
die «Response: Bad format, RESULT requiredn» unless $lines[$i++] eq ‘RESULT’;
# затем следуют обязательные параметры ответа в определенном порядке
# идентификатор операции
die «Response: Bad format, id requiredn» unless $lines[$i++] =
# код ответа
die «Response: Bad format, code requiredn» unless $lines[$i++] =
# сообщение для разработчика/оператора системы
die «Response: Bad format, omsg requiredn» unless $lines[$i++] =
# сообщение для клиента
die «Response: Bad format, cmsg requiredn» unless $lines[$i++] =
# далее следуют необязательные параметры операции
my ($res_time, $res_pmsg, $res_card, $res_pin);
while( my $line = $lines[$i++]) <
# дата/время операции на сервере
if($line=
/^time=(.*)$/) <
$res_time = $1
# сообщение для печати
>elsif($line=
/^pmsg=(.*)$/) <
$res_pmsg = $1
# номер карты e-port клиента
>elsif($line=
/^card=(.*)$/) <
$res_card = $1
# пин-код карты e-port клиента
>elsif($line=
# обрабатываем полученные данные
print «=== Operation result ===n»;
print «id :» . $res_id . «n»;
print «code :» . $res_code . «n»;
print «omsg :» . $res_omsg . «n»;
print «cmsg :» . $res_cmsg . «n»;
print «time :» . $res_time . «n»;
print «pmsg :» . $res_pmsg . «n»;
print «card :» . $res_card . «n»;
print «pin :» . $res_pin . «n»;
>
Источник
8 hours ago, david_navigator said:
If you mean the version numbers of libeay32.dll & ssleay32.dll, then they’re 1.0.1.3 (1.0.1c) — dated 27/01/2014 !!!
Yes, I do, and that is a VERY old version of OpenSSL, you need to upgrade. Indy currently supports up to 1.0.2u dated 21/12/2019, which you can find at https://github.com/IndySockets/OpenSSL-Binaries/ Work on supporting 1.1.x is in progress: https://github.com/IndySockets/Indy/pull/299
8 hours ago, david_navigator said:
SSLOptions.Method := sslvTLSv1;
The Method property is deprecated, you should be using the SSLVersions property instead.
TLS 1.0 has been (almost) completely phased out of modern servers. Most modern servers support, if not require, TLS 1.2, so that really should be your minimum going forward nowadays. You should also have TLS 1.1 enabled as a fallback, just in case, but even that is being phased out as well.
To enable multiple TLS versions with the Method property, you would have to set it to sslvSSLv23, which will set the SSLVersions property to all SSL/TLS versions supported by Indy (including SSL 2.0, SSL 3.0, and TLS 1.x), but it is better to use the SSLVersions property directly (ie, don’t enable SSL 2.0 and 3.0 anymore), eg:
SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
Having multiple TLS versions enabled at a time will allow OpenSSL to negotiate the highest version that both client and server support.
That being said, on a side note, you do not need to assign ANY of the following SSLIOHandler properties, as Indy handles them internally for you:
8 hours ago, david_navigator said:
with IdSSLIOHandlerSocketOpenSSL1 do begin ... Destination := format('%s:%s', [EditServerHost.text, EditPort.text]); // 'imap.gmail.com:993'; Host := EditServerHost.text; ... Port := strtoint(EditPort.text); DefaultPort := 0; ... end;
Setup the necessary Host/Port only in the client component, ie TIdIMAP4. The Connect() method will then copy them into the IOHandler as needed.
Edited October 22, 2021 by Remy Lebeau
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Open
jfgreco opened this issue
May 2, 2018
· 2 comments
Comments
raised exception class EIdOSSLConnectError with message ‘Error connecting with SSL. EOF was observed that violates the protocol’.
My application is raising the above error. I can’t seem to find what exactly is causing it. We are using Indy to make the connection.
Are you using Windows 7? I have come across similar symptoms when dealing with REST and GitHub. Please review this comment that I posted in exercism/windows-installer#33. For me, the upshot was that Windows is trying to use an older version of TLS (likely 1.0) and the REST server doesn’t support that version. My comment contains instructions from Microsoft on how to update settings in the registry to allow Windows to support newer versions of TLS.
Disclaimer: I am not using any code from this REPO. My experience stems from using the REST Client libraries provided by Delphi 10.2.x.
I hope there is some value for you in this, I just re-read your original comment, your error message is different than what I dealt with recently…
Понадобилось мне осуществить проверку серверного сертификата в моей программе на Delphi. Эта программа была написана довольно давно, на Delphi 7 с использованием Indy 9.
Вот как выглядит проверка сертификата:
var
IdHTTP: TIdHTTP;
IdSSLIOHandlerSocket: TIdSSLIOHandlerSocket;
begin
IdHTTP := TIdHTTP.Create(nil);
IdSSLIOHandlerSocket := TIdSSLIOHandlerSocket.Create(nil);
IdHTTP.IOHandler := IdSSLIOHandlerSocket;
with IdSSLIOHandlerSocket do
begin
SSLOptions.Method := sslvSSLv23;
SSLOptions.Mode := sslmClient;
SSLOptions.VerifyMode := [sslvrfPeer];
SSLOptions.VerifyDepth := 10;
end;
IdHTTP.Get('https://www.google.com');
FreeAndNil(IdHTTP);
FreeAndNil(IdSSLIOHandlerSocket);
end;
Если попробовать выполнить выше приведенный код, то результат будет всегда такой: Error connecting with SSL.
Проблема тут в том, что в Indy используется OpenSSL, который не умеет работать с хранилищем сертификатов Windows и не может проверить подписан ли сертификат, полученный от сервера, одним из доверенных корневых сертификатов из этого хранилища.
Посмотрим в исходник модуля IdSSLOpenSSL. В нем есть такая функция:
function VerifyCallback(Ok: Integer; ctx: PX509_STORE_CTX): Integer; cdecl;
var
hcert: PX509;
Certificate: TIdX509;
hSSL: PSSL;
IdSSLSocket: TIdSSLSocket;
// str: String;
VerifiedOK: Boolean;
Depth: Integer;
// Error: Integer;
begin
LockVerifyCB.Enter;
try
VerifiedOK := True;
try
hcert := IdSslX509StoreCtxGetCurrentCert(ctx);
hSSL := IdSslX509StoreCtxGetAppData(ctx);
Certificate := TIdX509.Create(hcert);
if hSSL <> nil then begin
IdSSLSocket := TIdSSLSocket(IdSslGetAppData(hSSL));
end
else begin
Result := Ok;
exit;
end;
//Error :=
IdSslX509StoreCtxGetError(ctx);
//
Depth := IdSslX509StoreCtxGetErrorDepth(ctx);
// str := Format('Certificate: %s', [Certificate.Subject.OneLine]); {Do not Localize}
// str := IdSSLSocket.GetSessionIDAsString;
// ShowMessage(str);
if (IdSSLSocket.fParent is TIdSSLIOHandlerSocket) then begin
VerifiedOK := TIdSSLIOHandlerSocket(IdSSLSocket.fParent).DoVerifyPeer(Certificate);
end;
if (IdSSLSocket.fParent is TIdServerIOHandlerSSL) then begin
VerifiedOK := TIdServerIOHandlerSSL(IdSSLSocket.fParent).DoVerifyPeer(Certificate);
end;
if not ((Ok>0) and (IdSSLSocket.fSSLContext.VerifyDepth>=Depth)) then begin
Ok := 0;
{if Error = OPENSSL_X509_V_OK then begin
Error := OPENSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG;
end;}
end;
FreeAndNil(Certificate);
except
end;
if VerifiedOK and (Ok > 0) then begin
Result := 1;
end
else begin
Result := 0;
end;
// Result := Ok; // testing
finally
LockVerifyCB.Leave;
end;
end;
Эта callback-функция вызывается при проверке сертификата библиотекой OpenSSL, и для того, чтобы не случилось ошибки “Error connecting with SSL” она должна возвращать значение Result = 1. Видно, что VerifyCallback возвращает Result = 1 только в том случае, когда Ok > 0. А параметр Ok для последнего сертификата в цепочке проверяемых всегда будет = 0, т.к. корневой сертификат, с помощью которого его можно проверить, не определен.
Таким образом, задача в следующем: проверить — подписан ли последний в цепочке сертификат одним из доверенных корневых (ROOT) сертификатов в хранилище Windows, и если подписан, то присвоить Ok = 1.
К сожалению, при проектировании Indy 9 было допущено много ошибок, и для того, чтобы решить поставленную задачу, придется вносить изменения в код модуля IdSSLOpenSSL, а затем перекомпилировать пакет
Indy70.dpk.
Внесем следующие изменения:
1. Изменим определение события TVerifyPeerEvent на следующее:
TVerifyPeerEvent = function(Certificate: TIdX509; Error: Integer; var Ok: Integer): Boolean of object;
2. Изменим определение метода DoVerifyPeer в классах TIdSSLIOHandlerSocket и TIdServerIOHandlerSSL на следующее:
function DoVerifyPeer(Certificate: TIdX509; Error: Integer; var Ok: Integer): Boolean; virtual;
3. Изменим реализации метода DoVerifyPeer в классах TIdSSLIOHandlerSocket и TIdServerIOHandlerSSL на следующие:
function TIdServerIOHandlerSSL.DoVerifyPeer(Certificate: TIdX509;
Error: Integer; var Ok: Integer): Boolean;
begin
Result := True;
if Assigned(fOnVerifyPeer) then
Result := fOnVerifyPeer(Certificate, Error, Ok);
end;
function TIdSSLIOHandlerSocket.DoVerifyPeer(Certificate: TIdX509;
Error: Integer; var Ok: Integer): Boolean;
begin
Result := True;
if Assigned(fOnVerifyPeer) then
Result := fOnVerifyPeer(Certificate, Error, Ok);
end;
4. Добавим public-свойство X509 классу TIdX509:
property X509: PX509 read FX509;
5. Изменим функцию VerifyCallback на следующую:
function VerifyCallback(Ok: Integer; ctx: PX509_STORE_CTX): Integer; cdecl;
var
hcert: PX509;
Certificate: TIdX509;
hSSL: PSSL;
IdSSLSocket: TIdSSLSocket;
// str: String;
VerifiedOK: Boolean;
Depth: Integer;
Error: Integer;
begin
LockVerifyCB.Enter;
try
VerifiedOK := True;
try
hcert := IdSslX509StoreCtxGetCurrentCert(ctx);
hSSL := IdSslX509StoreCtxGetAppData(ctx);
Certificate := TIdX509.Create(hcert);
if hSSL <> nil then begin
IdSSLSocket := TIdSSLSocket(IdSslGetAppData(hSSL));
end
else begin
Result := Ok;
exit;
end;
Error :=
IdSslX509StoreCtxGetError(ctx);
//
Depth := IdSslX509StoreCtxGetErrorDepth(ctx);
// str := Format('Certificate: %s', [Certificate.Subject.OneLine]); {Do not Localize}
// str := IdSSLSocket.GetSessionIDAsString;
// ShowMessage(str);
if (IdSSLSocket.fParent is TIdSSLIOHandlerSocket) then begin
VerifiedOK := TIdSSLIOHandlerSocket(IdSSLSocket.fParent).DoVerifyPeer(Certificate, Error, Ok);
end;
if (IdSSLSocket.fParent is TIdServerIOHandlerSSL) then begin
VerifiedOK := TIdServerIOHandlerSSL(IdSSLSocket.fParent).DoVerifyPeer(Certificate, Error, Ok);
end;
if not ((Ok>0) and (IdSSLSocket.fSSLContext.VerifyDepth>=Depth)) then begin
Ok := 0;
{if Error = OPENSSL_X509_V_OK then begin
Error := OPENSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG;
end;}
end;
FreeAndNil(Certificate);
except
end;
if VerifiedOK and (Ok > 0) then begin
Result := 1;
end
else begin
Result := 0;
end;
// Result := Ok; // testing
finally
LockVerifyCB.Leave;
end;
end;
Теперь нужно перекомпилировать Indy70.dpk.
В результате наших изменений обработчик события OnVerifyPeer получает два дополнительных параметра: Error — код ошибки проверки сертификата (это может быть, например, OPENSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) и параметр Ok, который можно изменить. Ниже приведена реализация обработчика:
function TForm1.SSLIOHandlerVerifyPeer(ThePeerCert: TIdX509; Error: Integer; var Ok: Integer): Boolean;
var
LBIO: PBIO;
LLen: Integer;
LStr: String;
hStore: HCERTSTORE;
pCert, pIssuer: PCCERT_CONTEXT;
dwFlags: DWORD;
begin
//Result := False;
//
if (Ok = 0)
then begin
hStore := nil;
pCert := nil;
pIssuer := nil;
LBIO := BIO_new(BIO_s_mem());
try
i2d_X509_bio(LBIO, ThePeerCert.X509);
LLen := BIO_ctrl_pending(LBIO);
SetLength(LStr, LLen);
BIO_read(LBIO, @LStr[1], LLen);
BIO_free(LBIO);
LBIO := nil;
hStore := CertOpenSystemStore(0, 'ROOT');
if hStore <> nil then
begin
pCert := CertCreateCertificateContext(
PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, @LStr[1], LLen);
if pCert <> nil then
begin
dwFlags := CERT_STORE_REVOCATION_FLAG or
CERT_STORE_SIGNATURE_FLAG or
CERT_STORE_TIME_VALIDITY_FLAG;
pIssuer := CertGetIssuerCertificateFromStore(
hStore, pCert, nil, @dwFlags);
if pIssuer <> nil then
begin
Ok := 1;
CertFreeCertificateContext(pIssuer);
pIssuer := nil;
end;
CertFreeCertificateContext(pCert);
pCert := nil;
end;
CertCloseStore(hStore, 0);
hStore := nil;
end;
finally
if LBIO <> nil then
BIO_free(LBIO);
if pIssuer <> nil then
CertFreeCertificateContext(pIssuer);
if pCert <> nil then
CertFreeCertificateContext(pCert);
if hStore <> nil then
CertCloseStore(hStore, 0);
end;
end;
//
Result := (Ok > 0);
end;
В этом обработчике использованы функции OpenSSL и СryptoAPI, объявления которых можно найти в libeay32.pas и wcrypt2.pas. Собственно, из-за необходимости подключения этих модулей я и вынес проверку в обработчик события OnVerifyPeer, вместо того, чтобы сделать все в функции VerifyCallback.
Подключаем обработчик SSLIOHandlerVerifyPeer к IdSSLIOHandlerSocket и окончательно получаем загрузку страницы по протоколу https: с проверкой серверного сертификата:
var
IdHTTP: TIdHTTP;
IdSSLIOHandlerSocket: TIdSSLIOHandlerSocket;
begin
IdHTTP := TIdHTTP.Create(nil);
IdSSLIOHandlerSocket := TIdSSLIOHandlerSocket.Create(nil);
IdHTTP.IOHandler := IdSSLIOHandlerSocket;
with IdSSLIOHandlerSocket do
begin
SSLOptions.Method := sslvSSLv23;
SSLOptions.Mode := sslmClient;
SSLOptions.VerifyMode := [sslvrfPeer];
SSLOptions.VerifyDepth := 10;
OnVerifyPeer := SSLIOHandlerVerifyPeer;
end;
IdHTTP.Get('https://www.google.com');
FreeAndNil(IdHTTP);
FreeAndNil(IdSSLIOHandlerSocket);
end;
PS. Проверка серверного сертификата и Enhanced Security
===
Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru
Topic: [SOLVED] Indy and SSL (Read 22839 times)
Solution: I found that the DateTime handling in the DLL was mixed up and had to be rewritten to form the dynamic URL
Hi,
I am going NUTS… over Indy and their OpenSSL….
I am trying to create a DLL which collects some JSON data from a website, I have got to work perfectly on numerous of other sites, however, this sites really got got my brains out…
If I create this app an run it directly as an EXE with only this changed in the SSLOptions.Method := sslvTLSv1_2 and SSLOptions.Versions := [sslvTLSv1_2] to the IdSSLIOHandlerSocketOpenSSL it works perfectly
but as DLL NOT:
-
function CreateSSLHandler: TIdSSLIOHandlerSocketOpenSSL;
-
var
-
SSL_org: TIdSSLIOHandlerSocketOpenSSL;
-
begin
-
SSL_org := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
-
SSL_org.IPVersion := Id_IPv4;
-
SSL_org.MaxLineAction := maException;
-
SSL_org.MaxLineLength := 16384;
-
SSL_org.Port := 0;
-
SSL_org.ReadTimeout := —1;
-
SSL_org.ReuseSocket := rsOSDependent;
-
SSL_org.SendBufferSize := 32768;
-
SSL_org.SSLOptions.Method := sslvTLSv1_2;
-
SSL_org.SSLOptions.Mode := sslmUnassigned;
-
SSL_org.SSLOPtions.SSLVersions := [sslvTLSv1_2];
-
SSL_org.SSLOptions.VerifyDepth := 0;
-
SSL_org.UseNagle := True;
-
CreateSSLHandler := SSL_org;
-
end;
-
function CreateHTTP: TIdHTTP;
-
var
-
HTTP_org: TIdHTTP;
-
begin
-
HTTP_org := TIdHTTP.Create(nil);
-
HTTP_org.IOHandler := CreateSSLHandler;
-
HTTP_org.Request.ContentType := ‘text/html’;
-
HTTP_org.AllowCookies := True;
-
HTTP_org.ProxyParams.BasicAuthentication := False;
-
HTTP_org.ProxyParams.ProxyPort := 0;
-
HTTP_org.Request.ContentLength := —1;
-
HTTP_org.Request.ContentRangeEnd := —1;
-
HTTP_org.Request.ContentRangeStart := —1;
-
HTTP_org.Request.ContentRangeInstanceLength := —1;
-
HTTP_org.Request.Date := 0;
-
HTTP_org.Request.Expires := 0;
-
HTTP_org.Request.LastModified := 0;
-
HTTP_org.Request.Accept := ‘text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8’;
-
HTTP_org.Request.BasicAuthentication := False;
-
HTTP_org.Request.UserAgent := ‘My Custom UserAgent’;
-
HTTP_org.Request.Ranges.Units := ‘bytes’;
-
HTTP_org.HTTPOptions := [hoForceEncodeParams];
-
HTTP_org.ProtocolVersion := pv1_1;
-
CreateHTTP := HTTP_org;
-
end;
It’s exactly the same settings as in the EXE file .. which works
I am getting desperate ….
« Last Edit: February 25, 2017, 01:32:31 am by DanishMale »
Logged
Lazarus 2.2.4 x64 | Windows 10 x64 | Windows Server 2019 x64 | OpenVix 5.4 (Linux) | MySQL Community Server 8.0 x64 | MariaDB 10.5.8 x64 | SQLite 3.40.0 x64 | PostgresSQL 13.1 x64
Which site you are trying to access?
Can you show to us your application main source code?
Logged
Logged
Lazarus 2.2.4 x64 | Windows 10 x64 | Windows Server 2019 x64 | OpenVix 5.4 (Linux) | MySQL Community Server 8.0 x64 | MariaDB 10.5.8 x64 | SQLite 3.40.0 x64 | PostgresSQL 13.1 x64
Which version of Indy you are using?
Logged
If I create this app an run it directly as an EXE with only this changed in the SSLOptions.Method := sslvTLSv1_2 and SSLOptions.Versions := [sslvTLSv1_2] to the IdSSLIOHandlerSocketOpenSSL it works perfectly but as DLL NOT:
Ok and how exactly fails? What is the error message? I see in your description Lazarus 1.6 x64, are you creating 64bit application/dll? Make sure libeay32.dll and ssleay32.dll match your binary format so you don’t mix 32 with 64 and vice versa. Of course this is just guessing…the problem may be something completely different.
Logged
The error looks like this:
Error connecting with SSL.
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
I have used the libeay32.dll and ssleay32.dll in previous x64 DLL / Apps
Logged
Lazarus 2.2.4 x64 | Windows 10 x64 | Windows Server 2019 x64 | OpenVix 5.4 (Linux) | MySQL Community Server 8.0 x64 | MariaDB 10.5.8 x64 | SQLite 3.40.0 x64 | PostgresSQL 13.1 x64
Error connecting with SSL.
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
I feel your pain.
I would spend the day searching that error message. I solved a recent Indy problem by trying various suggestions given here:
https://stackoverflow.com/questions/35987485/eidosslconnecterror-error-connecting-with-ssl-eof-was-observed#
Interestingly, FPC’s HTTP client did not have this EOF problem at all. You could try FPC’s just to see if there’s any difference.
I’ve had a lot of problems keeping code that retrieves data from Web sites running, as they transition from http to https, change APIs, change handshake policies, change WSDL, etc. No two http clients in my experience work the same and they all have problems if you’re hitting against enough different sites. I work with 4: Indy, FPC, Synapse and Foundation (Mac).
Also, who’s responsible for freeing the TIdSSLIOHandlerSocketOpenSSL object? It looks like you’re assuming that Indy is.
Edit: I’ve never seen a problem where it works in an executable and not in a dynamic library. In my experience, if it works in one, it will work in the other and vice versa. Make sure both the executable and the library are using the same SSL libraries.
« Last Edit: February 23, 2017, 04:42:13 pm by Phil »
Logged
I am going NUTS… over Indy and their OpenSSL….
It is not OUR OpenSSL. OpenSSL is a 3rd party open source library independent of Indy.
To use TLS 1.2 in Indy, make sure you are using up-to-date versions of Indy and OpenSSL 1.0.2 (Indy does not support OpenSSL 1.1.0 yet).
If I create this app an run it directly as an EXE with only this changed in the SSLOptions.Method := sslvTLSv1_2 and SSLOptions.Versions := [sslvTLSv1_2] to the IdSSLIOHandlerSocketOpenSSL it works perfectly
but as DLL NOT
Neither Indy nor OpenSSL behave differently whether used in an EXE or a DLL. So something else is going on.
It’s exactly the same settings as in the EXE file .. which works
Have you tried using a packet sniffer, like Wireshark, to look at the actual TLS handshake to see if anything is different between the EXE and DLL handshakes?
Error connecting with SSL.
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
A TLS alert comes from the peer. So, in this case, it means the HTTP server is rejecting the TLS handshake. Now you need to figure out why. And that is where Wireshark comes into play.
« Last Edit: February 24, 2017, 04:28:32 am by Remy Lebeau »
Logged





