IdHTTP + SOCKS + Socks5 - delphi

I'm getting a general Indy error when using the IdHTTP client component in
conjunction with a SOCKS5 proxy server and using SSL.
If I use the IdHTTP component with my SOCKS5 proxy (and a non https URL),
everything works without problems.
If I use the IdHTTP component with an SSL URL (and no SOCKS5 proxy),
everything works without problems.
If I use the IdHTTP component with an SSL URL and a SOCKS5 proxy i get following error:
Line 405 of the error output
idSocks.pas (raise EIdSocksServerGeneralError.Create(RSSocksServerGeneralError);
Here is my code
var
HTTP : TIdHTTP;
Cookie : TIdCookieManager;
SSL : TIdSSLIOHandlerSocketOpenSSL;
Params : TStringList;
HTMLSource : String;
CurrentProxy : String;
ProxyPort : Integer;
ProxyHost : String;
ProxyUsername : String;
ProxyPW : String;
begin
Synchronize(AddItem);
HTTP := TIdHTTP.Create(NIL);
Cookie := TIdCookieManager.Create(HTTP);
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
HTTP.CookieManager := Cookie;
HTTP.IOHandler := SSL;
HTTP.HandleRedirects := True;
Params := TStringList.Create;
HTTP.Request.UserAgent := Task^.Useragent;
try
while True do begin
if terminated then Exit;
Params.Clear;
Cookie.CookieCollection.Clear;
if Task^.Proxytype >= 0 then begin // if proxy enabled
CurrentProxy := Task^.Form.GetProxyFromPool;
ProxyHost := ParsingW(':', CurrentProxy, 1);
ProxyPort := strtoint(ParsingW(':', CurrentProxy, 2));
HTTP.ConnectTimeout := (Task^.Proxytimeout * 1000);
if Task^.ProxyAuth then begin
ProxyUsername := ParsingW(':', CurrentProxy, 3);
ProxyPW := ParsingW(':', CurrentProxy, 4);
end;
end;
if Task^.Proxytype = 0 then begin //HTTP(s)
HTTP.ProxyParams.ProxyServer := ProxyHost;
HTTP.ProxyParams.ProxyPort := ProxyPort;
if Task^.ProxyAuth then begin
HTTP.ProxyParams.ProxyUsername := ProxyUsername;
HTTP.ProxyParams.ProxyPassword := ProxyPW;
end;
end;
if (Task^.Proxytype = 1) or (Task^.Proxytype = 2) then begin // Socks 4 or 5
SSL.TransparentProxy := TIdSocksInfo.Create(HTTP);
(SSL.TransparentProxy as TIdSocksInfo).Port := ProxyPort;
(SSL.TransparentProxy as TIdSocksInfo).Host := ProxyHost;
if Task^.ProxyAuth then begin
(SSL.TransparentProxy as TIdSocksInfo).Username := ProxyUsername;
(SSL.TransparentProxy as TIdSocksInfo).Password := ProxyPW;
(SSL.TransparentProxy as TIdSocksInfo).Authentication := saUsernamePassword;
end else begin
(SSL.TransparentProxy as TIdSocksInfo).Authentication := saNoAuthentication;
end;
if (Task^.Proxytype = 1) then (SSL.TransparentProxy as TIdSocksInfo).Version := svSocks4;
if (Task^.Proxytype = 2) then (SSL.TransparentProxy as TIdSocksInfo).Version := svSocks5;
end;
Did I miss something or is it not possible to connect to a a SSL site with a Socks5 Proxy?

The fact that you are getting an EIdSocksServerGeneralError raised means that TIdHTTP is successfully communicating with the SOCKS proxy and it is validating your request to access it with no authentication, but it is then failing to establish a connection with the target server that you specified in your HTTPS url. The proxy is replying with error code 1 (general failure). Make sure that the url is accurate. Either the proxy cannot resolve the hostname to an IP (try specifying an IP instead of a hostname in the url and see if it makes a difference), or the proxy does not have a valid route to reach that IP, or some other error is occurring on the proxy end. If you have access to the proxy, try looking at its logs to see what actually went wrong.

Related

Delphi: TOAuth2Authenticator with client_credentials

A while ago I wrote a method in Delphi 2010 to get the OAuth2 token using the Indy components (TidHttp). See code below.
I am now doing something new in Delphi 10.4 and would like to use the REST components such as RESTClient, RESTRequest, TOAuth2Authenticator, etc.
Our grant type is Client Credentials but in none of the examples on the net could I find on how to use TOAuth2Authenticator with Client Credentials. Is it even possible?
We have a client id, client secret and token URL. We do not have authorization or redirect endpoints. In Insomnia, the setup will look like this:
Does somebody know how to get the token using TOAuth2Authenticator with grant type = client_credentials?
Here is the Delphi 2010 code:
procedure TfrmToken.btnGetTokenClick(Sender: TObject);
var
IdHTTP: TidHttp;
lsHttpError: string;
loRequest: TStringStream;
loRespJson: TMemoryStream;
liSuper: iSuperObject;
ldtExpiry: TDateTime;
begin
IdHTTP := TIdHTTP.Create();
loRespJson := TMemoryStream.Create();
try
IdHTTP.HandleRedirects := False;
loRequest := TStringStream.Create('grant_type=client_credentials&client_id=' +
edtKey.Text + '&client_secret='+edtSecret.Text);
try
IdHttp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHttp);
IdHttp.Request.ContentType := 'application/x-www-form-urlencoded';
try
IdHTTP.Post(edtURL.Text, loRequest, loRespJson);
except
on E: EIdHTTPProtocolException do
begin
lsHttpError := E.ErrorMessage;
end;
on E: Exception do
begin
lsHttpError := E.Message;
end;
end;
if idHTTP.ResponseCode = 200 then
begin
liSuper := SO(StreamToString(loRespJSon));
edtToken.Text := liSuper.S['access_token'];
ldtExpiry := IncSecond(Now, liSuper.i['expires_in']);
edtExpiry.Text := 'Expires in ' + liSuper.S['expires_in'] +
' seconds. Time: ' +
FormatDateTime('yyyy/dd/mm hh:nn:ss', ldtExpiry);
end
else
begin
liSuper := SO(lsHttpError);
edtToken.Text := IdHTTP.ResponseText;
edtExpiry.Text := '';
end;
finally
FreeAndNil(loRequest);
end;
finally
FreeAndNil(IdHTTP);
FreeAndNil(loRespJson);
end;
end;

Delphi XE7 Indy Rest Api post with Ssl Connection Timeout 10060

I am trying post under the ssl address service and i got connection timeout 10060., My ssl library and Indy SSl configurations is true because i used same code on email sending with gmail and another services.
I posted with postman it works.
my code
const
Api = 'https://xxxx.xxxx.com/api/detection/Insert';
procedure TRestSender.SendThreats(CustomerId: Integer;
DetectionName, Filename: String);
var
PostData: TStringList;
res: string;
Https: TIdHttp;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
Https := Tidhttp.Create(nil);
PostData := TStringList.Create;
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Https.ReadTimeout := 10000;
Https.ConnectTimeout:= 10000;
IdSSL.SSLOptions.Method := sslvTLSv1;
// IdSSL.OnStatusInfo:= ssl1StatusInfo;
IdSSL.SSLOptions.Mode := sslmClient;
Https.IOHandler := IdSSL;
try
PostData.Add('Content-Type:application/x-www-form-urlencoded');
PostData.Add('CustomerId=' + IntToStr(CustomerId));
PostData.Add('DetectionName=' + DetectionName);
PostData.Add('DeviceName=' + ComputerName());
PostData.Add('Filename=' + Filename);
PostData.Add('ApiUser=' + 'some-code');
PostData.Add('ApiPass=' + 'some-paswd');
res := Https.Post(Api, PostData);
finally
PostData.Free;
Https.Free;
IdSSL.Free;
end;
end;
I have two suggestions:
Wrong TLS version: More and more services disable TLS 1.0 and/or TLS1.1. The default version is TLS 1.0.
const
DEF_SSLVERSION = sslvTLSv1;
DEF_SSLVERSIONS = [sslvTLSv1];
So add the following line:
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1];
Missing SNI support (an example for SNI).

IdHttpServerexception:Error accepting connection with SSL. EOF was observed that violates the protocol;

I have a Delphi 2007 TIdHttpServer Web App (Version 10). My IdHTTPServer1.onexception handler is handling a lot of these exceptions:
Error accepting connection with SSL. EOF was observed that violates
the protocol
I also have the latest version of OpenSSL (1.0.2.4).
I know it is protocol to have a MCVE (Minimal, Complete, and Verifiable example). However I am not able to replicate this. These exceptions are occurring in production environment. All I have been able to do is log the ip address. And the IP Addresses are random. So it does not appear to be any single "spam bot" that could be doing this.
Do these exceptions mean something is making requests using a version of SSL that I am not supporting?
Is there something I can do to fix this?
Or is this something I should not worry about?
Below is my code for setting up the server:
ServerIOHandler := TIdServerIOHandlerSSLOpenSSL.Create(self);
ServerIOHandler.SSLOptions.CertFile := 'C:\xxxxx.crt';
ServerIOHandler.SSLOptions.KeyFile := 'C:\xxxxx.key';
ServerIOHandler.SSLOptions.RootCertFile := 'C:\yyyyyyy.crt';
ServerIOHandler.SSLOptions.Method := sslvSSLv23;
ServerIOHandler.SSLOptions.SSLVersions := [sslvSSLv23,sslvSSLv2, sslvSSLv3, sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
ServerIOHandler.OnGetPassword := GetSSLPassword;
IdHTTPServer1 := TEAIdHTTPServer.Create;
IdHTTPServer1.MaxConnections := 1000;
IdHTTPServer1.AutoStartSession := True;
IdHTTPServer1.SessionState := True;
IdHTTPServer1.OnCommandGet := MainGet;
IdHTTPServer1.onexception := IdHttpServerexception;
IdHTTPServer1.onlistenexception := IdHttpServerlistenexception;
IdHTTPServer1.onconnect := IdHttpServerConnect;
IdHTTPServer1.ondisconnect := IdHttpServerDisconnect;
idHttpServer1.ParseParams := True;
idHttpServer1.OnQuerySSLPort := QuerySSLPort;
idHttpServer1.IOHandler := ServerIOHandler;
idHttpServer1.Bindings.Add.Port := 80;
idHttpServer1.Bindings.Add.Port := 443;
IdHTTPServer1.Active := True;
procedure TMyProject.QuerySSLPort(APort: TIdPort; var VUseSSL: Boolean);
begin
if APort=80 then begin
vUseSSL := False;
end else if APort=443 then begin
vUseSSL := True;
end else begin
vUseSSL := False;
end;
end;

403/Forbidden using delphi application to access my Google calendar

Can anyone tell me why i'm having trouble accessing my calendar information? I'm getting 403 forbidden.
procedure TForm1.Button1Click(Sender: TObject);
var
stringStream: TStringStream;
slPost, slReply: TStringList;
sPostResult: string;
begin
slPost := TStringList.Create;
slReply := TStringList.Create;
try
slPost.LineBreak := '&';
slPost.Values['Email'] := 'me#gmail.com';
slPost.Values['Passwd'] := 'pass';
slPost.Values['service'] := 'cl';
slPost.Values['source'] := 'company-program-version';
stringStream := TStringStream.Create(slPost.Text);
try
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded';
sPostResult := IdHTTP1.Post('https://www.google.com/accounts/ClientLogin', stringStream);
slReply.LineBreak:=#10;
slReply.Text:=sPostResult;
slReply.LineBreak:=#13#10;
Memo1.Lines.Add(slReply.Text);
Memo1.Lines.Add('response=' + IdHTTP1.ResponseText);
// 200 OK
sPostResult := IdHTTP1.Post('https://www.google.com/accounts/ClientLogin', stringStream);
IdHTTP1.Request.CustomHeaders.FoldLines:=false;
IdHTTP1.Request.CustomHeaders.Clear;
IdHTTP1.Request.CustomHeaders.Values['GData-Version']:='2.0';
IdHTTP1.Request.CustomHeaders.Values['Authorization']:='GoogleLogin auth=' + slReply.Values['auth'];
(* custom headers:
GData-Version: 2.0
Authorization: GoogleLogin (line continues) auth=DQwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhateverwhatever *)
IdHTTP1.Request.ContentType := 'application/atom+xml';
// 403 Forbidden
memo1.Lines.Add(IdHTTP1.Get('https://www.googleapis.com/calendar/v3/users/me/calendarList'));
finally
stringStream.Free;
end;
finally
slPost.Free;
slReply.Free;
end;
end;
thank you!
mp
After some reading, I think you need to deal with Redirect. So If response is redirect, get the new url, reattach the authorization to the new request header with the new url. Otherwise your redirection request will be missing the required authorization and give you 403 error.

Sending message to gmail fails with "Start SSL negotiation command failed." error

Tips i followed is found here.
I do have libeay32.dll and ssleay32.dll in win32 folder.
dfm file:
object tidSMTP: TIdSMTP
IOHandler = tidSMTP_SSL
SASLMechanisms = <>
UseTLS = utUseExplicitTLS
end
object tidSMTP_SSL: TIdSSLIOHandlerSocketOpenSSL
Destination = 'smtp.gmail.com:587'
Host = 'smtp.gmail.com'
MaxLineAction = maException
Port = 587
DefaultPort = 0
SSLOptions.Mode = sslmUnassigned
SSLOptions.VerifyMode = []
SSLOptions.VerifyDepth = 0
end
and Send button click event:
procedure TForm1.btnSendClick(Sender: TObject);
var
mes:TIdMessage;
fromAddress:TIdEmailAddressItem;
toAddress:TIdEMailAddressItem;
begin
tidSMTP.Username := txtUsername.Text;
tidSMTP.Password := txtPassword.Text;
tidSMTP.Host := txtSMTPserver.Text; //smtp.gmail.com
tidSMTP.Port := StrToInt(txtSMTPport.Text); //587
fromAddress := TIdEMailAddressItem.Create;
fromAddress.Address := txtUsername.Text;
toAddress := TIdEMailAddressItem.Create;
toAddress.Address := txtTo.Text;
mes := TIdMessage.Create;
mes.ContentType := 'text/plain';
mes.From := fromAddress;
mes.ReceiptRecipient := toAddress;
mes.Subject := txtSubject.Text;
mes.Body := memoText.Lines;
tidSMTP.Connect;
tidSMTP.Send(mes);
tidSMTP.Disconnect;
end;
Any help would be appreciated!
Set you SSL Method to SSL version 3 (tidSMTP_SSL.SSLOptions.Method). I think it defaults to SSL version 2, but GMail does not support that.
SSLOptions.Method := sslvSSLv3;
Edit:
You can log the SSL Status info by assigning an eventhandler to the OnStatusInfo event of your IOHandler:
tidSMTP_SSL.OnStatusInfo := DoOnStatusInfo;
proceudre TForm1.DoOnStatusInfo(Msg: string);
begin
// when running from IDE, message will appear in
// EventLog (Ctrl+Alt+V), otherwise,
// use DebugViewer.exe
OutputDebugString(PChar(Msg));
end;
Maybe this will give you a clue about the failing negotation.
PS: I'm on Indy 9.0.0.18, so things may have changed for you.
Edit2:
If above does not help, please check if there is not a firewall / antivirus that is blocking smtp.gmail.com or port 587
I successfully make it worked like this:
procedure TForm1.btn2Click(Sender: TObject);
var
email : TIdMessage;
idSMTPGMail: TIdSMTP;
idSSLGMail : TIdSSLIOHandlerSocketOpenSSL;
begin
idSSLGMail := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
idSSLGMail.SSLOptions.Method := sslvTLSv1;
idSSLGMail.SSLOptions.Mode := sslmUnassigned;
idSMTPGMail := TIdSMTP.Create(nil);
idSMTPGMail.IOHandler := idSSLGMail;
idSMTPGMail.UseTLS := utUseExplicitTLS;
email := TIdMessage.Create(nil);
email.From.Address := txtUsername.Text;
email.Recipients.EMailAddresses := txtTo.Text;
email.Subject := txtSubject.Text;
email.Body.Text := memoText.Text;
idSMTPGMail.Host := 'smtp.gmail.com';
idSMTPGMail.Port := 587;
idSMTPGMail.UserName := txtUsername.Text;
idSMTPGMail.Password := txtPassword.Text;
idSMTPGMail.Connect;
idSMTPGMail.Send(email);
idSMTPGMail.Disconnect;
email.Free;
idSSLGMail.Free;
idSMTPGMail.Free;
Beep;
end;
I use the same TEdit, TMemo, but dynamically create the Indy components...

Resources