Handling Self-Signed Certificates (Delphi)
Remoting SDK's client channels for Delphi allow to enable TLS/SSL protection quite easily: simply by using the appropriate
supertcps:// URL Scheme, the clients will automatically choose Secure Socket Layer and communicate securely with the server.
For that, your server has to be set up with a "proper" certificate – that is, a certificate signed by (and usually bought from) a known certificate authority that is implicitly trusted by the OS. For production applications that is recommended practice, but sometimes – for example in Enterprise deployment or during debugging – it is helpful to be able to work with "invalid" or self-signed certificates, just to get things going before spending money on a real certificate.
Depending on the target OS and used channel type (see below), the channel will either refuse to connect or just accept the formally invalid certificate. Unfortunately, accepting unknown certificates blindly could enable Man-in-the-middle Attacks and essentially negate any security you aim to gain by using SSL. Even more, blindly accepting a formally valid certificate is still not MITM-attacks proof.
So a more advanced certificate validity check is required for real-worlds applications.
In Remoting SDK for Delphi there are 4 different kinds of, based on different libraries:
- Indy library
- WinInet API library
- NetHTTP library (XE8+ only)
- Synapse library
These channel kinds require different approaches to handle self-signed certificates and will be covered separately.
IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode + [sslvrfPeer];
OnVerifyPeer event like
function TMyForm.IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean; begin result := ValidateCertificate(Certificate); end;
TIdSSLIOHandlerSocketOpenSSL instance with
implement OnInvalidCertificate method:
procedure TMyForm.ROWinInetHTTPChannel1InvalidCertificate(Sender: TObject; const aIssuer, aSubject: AnsiString; var aAllow: Boolean); begin aAllow := ValidateCertificate(aIssuer, aSubject); end;
procedure TServerForm.NetHTTPClientValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest; const Certificate: TCertificate; var Accepted: Boolean); begin Accepted = ValidateCertificate(Certificate); end;
Synapse-based channels aren't supported yet.