SocketTlsHandshake

Avvia connessione TLS sicura (SSL) ad un host specificato tramite il protocollo TLS Handshake. Durante l'handshake, un client ed un server concordano sui parametri di connessione: versione del protocollo applicata e metodo di crittografia dei dati.

bool  SocketTlsHandshake(
   int           socket,               // socket
   const string  host                  // indirizzo dell'host
   );

Parametri

socket

[in] Handle del socket restituito dalla funzione SocketCreate. Quando viene passato un handle errato, viene scritto l'errore 5270 (ERR_NETSOCKET_INVALIDHANDLE) _LastError.

host

[in] L'indirizzo di un host con cui è stabilita una connessione sicura.

Valore di Ritorno

Restituisce true se ha successo, altrimenti false.

Note

Prima di una connessione sicura, il programma dovrebbe stabilire una connessione TCP standard con l'host che utilizza SocketConnect.

Se la connessione protetta non riesce, viene scritto l'errore 5274 (ERR_NETSOCKET_HANDSHAKE_FAILED) in _LastError.

Non è necessario chiamare la funzione quando vi è collegamento alla porta 443. Questa è una porta TCP standard utilizzata per connessioni TLS (SSL) sicure.

La funzione può essere chiamata solo da Expert Advisors e scripts, poiché vengono eseguiti nei relativi thread di esecuzione. Se si chiama da un indicatore, GetLastError() restituisce l'errore 4014 - "Function is not allowed for call (la funzione non è consentita per la chiamata)".

Esempio:

//+------------------------------------------------------------------+
//|                                           SocketTlsHandshake.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com
#property version     "1.00"
 
#define   SERVER    "smtp.gmail.com"
#define   PORT      587
//+------------------------------------------------------------------+
//| Passare manualmente alla connessione sicura                      |
//+------------------------------------------------------------------+
bool TlsHandshake(int socket)
  {
//--- ottenere il saluto del server
   string rsp;
 
   if(!RecvString(socket,rsp))
      return(false);
//--- salutare il server
   if(!SendString(socket,"EHLO my.domain.com\r\n"))
      return(false);
//--- ottenere una risposta del server con un elenco di comandi supportati
   if(!RecvString(socket,rsp))
      return(false);
//--- stampare il saluto
   Print("SERVER: ",rsp);
//--- informare il server che vogliamo passare da una connessione non sicura a una sicura utilizzando TLS
   if(!SendString(socket,"STARTTLS\r\n"))
      return(false);
//--- ottenere la risposta del server
   if(!RecvString(socket,rsp))
      return(false);
//--- nell'esempio, non controlliamo la risposta del server sulla disponibilità nel passare a TLS ('Ready to start TLS')
 
//--- avviamo una connessione TLS sicura (SSL) con l'host specificato utilizzando il protocollo TLS Handshake
   if(SocketTlsHandshake(socket,InpTimeout))
      return(true);
 
   Print("SocketTlsHandshake() failed. Error ",GetLastError());
   return(false);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart(void)
  {
//--- creare un socket e ottenere il suo handle (gestore)
   int socket=SocketCreate();
 
   if(socket==INVALID_HANDLE)
     {
      Print("SocketCreate() failed. Error ",GetLastError());
      return;
     }
//--- collegarsi al SERVER tramite PORT
   if(!SocketConnect(socket,SERVER,PORT,10000))
     {
      Print("SocketConnect() failed. Error ",GetLastError());
     }
   else
     {
 //--- connessione non sicura stabilita
      PrintFormat("%s connection has been established to %s:%d",(PORT==443 ? "A secured" : "An unsecured"),SERVER,PORT);
 //--- passare alla connessione sicura
      if(PORT!=443 && TlsHandshake(socket))
        {
         PrintFormat("Unsecured connection to %s:%d switched to secured",SERVER,PORT);
 //--- se la connessione è protetta da un certificato, visualizzare i dati di tale certificato
         string   subject,issuer,serial,thumbprint;
         datetime expiration;
 
         if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration))
           {
            Print("TLS certificate:");
            Print("   Owner:      ",subject);
            Print("   Issuer:     ",issuer);
            Print("   Number:     ",serial);
            Print("   Print:      ",thumbprint);
            Print("   Expiration: ",expiration);
           }
        }
     }
//--- chiudere il socket dopo l'uso
   SocketClose(socket);
   /*
   risultato:
   An unsecured connection has been established to smtp.gmail.com:587
   SERVER220 smtp.gmail.com ESMTP a640c23a62f3a-a9b1f298319sm82305866b.105 - gsmtp
 
   SERVER250-smtp.gmail.com at your service, [37.193.40.122]
   250-SIZE 35882577
   250-8BITMIME
   250-STARTTLS
   250-ENHANCEDSTATUSCODES
   250-PIPELINING
   250-CHUNKING
   250 SMTPUTF8
 
   SERVER220 2.0.0 Ready to start TLS
 
   SocketTlsHandshake(): A secure connection to smtp.gmail.com:587 is now established
   TLS certificate:
      Owner:  /CN=smtp.gmail.com
      Issuer:  /C=US/O=Google Trust Services/CN=WR2
      Number:     1f:f4:db:2a:5a:e6:dc:52:0a:4c:05:ce:81:cc:c3:f7
      Printd6be8af229b5329cd3d4c2789c02aa94f89b421c
      Expiration2024.12.30 08:25:30
   */
  }
//+------------------------------------------------------------------+
//| Inviare una stringa al server                                    |
//+------------------------------------------------------------------+
bool SendString(int socket,const string str)
  {
//--- convertire la stringa in un array di caratteri
   uchar data[];
   int   size=StringToCharArray(str,data,0,str.Length(),CP_UTF8);
//--- inviare i dati al socket
   ResetLastError();
   if(SocketSend(socket,data,size)==size)
      return(true);
//-- errore nell'invio dei dati
   Print("Failed to send data to server. Error ",GetLastError());
   return false;
  }
//+------------------------------------------------------------------+
//| Ottenere una stringa dal server                                  |
//+------------------------------------------------------------------+
bool RecvString(int socket,stringresult,uint timeout_ms=1000)
  {
//--- attendere che i dati appaiano sul socket
   ulong wait_time_end=GetMicrosecondCount()+timeout_ms*1000;
 
   while(!SocketIsReadable(socket))
     {
      Sleep(10);
      //--- tempo scaduto per l'attesa dei dati - restituisci NULL come risposta
      if(wait_time_end<GetMicrosecondCount())
        {
         Print("ERROR: No response from server");
         return(false);
        }
     }
//--- leggere i dati dal socket
   uchar  data[128];
   uint   size=0;
   string resp=NULL;
 
   do
     {
      uchar b[1];
      int   n=SocketRead(socket,b,1,1000);
 
      if(n < 0)
         break;
 
      if(n)
        {
         data[size++]=b[0];
 
         if(size==data.Size())
           {
            resp += CharArrayToString(data,0,data.Size(),CP_UTF8);
            size = 0;
           }
        }
     }
   while(SocketIsReadable(socket));
//--- copiare i dati letti nella stringa
   if(size)
      resp+=CharArrayToString(data,0,size,CP_UTF8);
//--- se la stringa è vuota, allora errore
   if(!resp.Length())
     {
      Print("ERROR: No response from server");
      return(false);
     }
//--- restituire la stringa
   result=resp;
   return(true);
  }