Logo Search packages:      
Sourcecode: filezilla version File versions

tlssocket.cpp

#include "FileZilla.h"
#include "tlssocket.h"
#include "ControlSocket.h"

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <errno.h>

BEGIN_EVENT_TABLE(CTlsSocket, wxEvtHandler)
EVT_SOCKET(wxID_ANY, CTlsSocket::OnSocketEvent)
END_EVENT_TABLE()

CTlsSocket::CTlsSocket(wxEvtHandler* pEvtHandler, wxSocketBase* pSocket, CControlSocket* pOwner)
      : CBackend(pEvtHandler), m_pOwner(pOwner)
{
      m_pSocket = pSocket;
      m_pSocketBackend = new CSocketBackend(this, m_pSocket);

      m_session = 0;
      m_initialized = false;
      m_certCredentials = 0;
      
      m_canReadFromSocket = true;
      m_canWriteToSocket = true;
      m_canCheckCloseSocket = false;

      m_canTriggerRead = true;
      m_canTriggerWrite = true;

      m_tlsState = noconn;

      m_lastError = 0;
      m_lastCount = 0;
      m_lastSuccessful = false;

      m_lastWriteFailed = false;
      m_writeSkip = 0;

      m_peekData = 0;
      m_peekDataLen = 0;

      m_socketClosed = false;

      m_implicitTrustedCert.data = 0;
      m_implicitTrustedCert.size = 0;

      m_shutdown_requested = false;
}

CTlsSocket::~CTlsSocket()
{
      Uninit();
      delete m_pSocketBackend;
}

bool CTlsSocket::Init()
{
      // This function initializes GnuTLS
      int res = gnutls_global_init();
      if (res)
      {
            LogError(res);
            return false;
      }
      m_initialized = true;

      res = gnutls_certificate_allocate_credentials(&m_certCredentials);
      if (res < 0)
      {
            LogError(res);
            Uninit();
            return false;
      }

      res = gnutls_init(&m_session, GNUTLS_CLIENT);
      if (res)
      {
            LogError(res);
            Uninit();
            return false;
      }

      res = gnutls_set_default_priority(m_session);
      if (res)
      {
            LogError(res);
            Uninit();
            return false;
      }
      
      // Set which type of certificates we accept
      const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
      gnutls_certificate_type_set_priority(m_session, cert_type_priority);
      if (res)
      {
            LogError(res);
            Uninit();
            return false;
      }

      gnutls_credentials_set(m_session, GNUTLS_CRD_CERTIFICATE, m_certCredentials);

      // Setup transport functions
      gnutls_transport_set_push_function(m_session, PushFunction);
      gnutls_transport_set_pull_function(m_session, PullFunction);
      gnutls_transport_set_ptr(m_session, (gnutls_transport_ptr_t)this);
      gnutls_transport_set_lowat(m_session, 0);

      m_shutdown_requested = false;

      // At this point, we can start shaking hands.

      return true;
}

void CTlsSocket::Uninit()
{
      if (m_session)
      {
            gnutls_deinit(m_session);
            m_session = 0;
      }

      if (m_certCredentials)
      {
            gnutls_certificate_free_credentials(m_certCredentials);
            m_certCredentials = 0;
      }

      if (m_initialized)
      {
            m_initialized = false;
            gnutls_global_deinit();
      }

      m_tlsState = noconn;

      delete [] m_peekData;
      m_peekData = 0;
      m_peekDataLen = 0;

      delete [] m_implicitTrustedCert.data;
      m_implicitTrustedCert.data = 0;
}

void CTlsSocket::LogError(int code)
{
      if (code == GNUTLS_E_WARNING_ALERT_RECEIVED || code == GNUTLS_E_FATAL_ALERT_RECEIVED)
            PrintAlert();

      const char* error = gnutls_strerror(code);

      if (error)
      {
#if wxUSE_UNICODE
            wxString str(error, wxConvLocal);
#else
            wxString str(error);
#endif
            m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS error %d: %s"), code, str.c_str());
      }
      else
            m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS error %d"), code);
}

void CTlsSocket::PrintAlert()
{
      gnutls_alert_description_t last_alert = gnutls_alert_get(m_session);
      const char* alert = gnutls_alert_get_name(last_alert);
      if (alert)
      {
#if wxUSE_UNICODE
            wxString str(alert, wxConvLocal);
#else
            wxString str(alert);
#endif
            m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d: %s"), last_alert, str.c_str());
      }
      else
            m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d"), last_alert);
}

ssize_t CTlsSocket::PushFunction(gnutls_transport_ptr_t ptr, const void* data, size_t len)
{
      return ((CTlsSocket*)ptr)->PushFunction(data, len);
}

ssize_t CTlsSocket::PullFunction(gnutls_transport_ptr_t ptr, void* data, size_t len)
{
      return ((CTlsSocket*)ptr)->PullFunction(data, len);
}

ssize_t CTlsSocket::PushFunction(const void* data, size_t len)
{
      if (!m_canWriteToSocket)
      {
            gnutls_transport_set_errno(m_session, EAGAIN);
            return -1;
      }

      if (!m_pSocketBackend)
      {
            gnutls_transport_set_errno(m_session, 0);
            return -1;
      }

      m_pSocketBackend->Write(data, len);

      if (m_pSocketBackend->Error())
      {
            const int error = m_pSocketBackend->LastError();
            if (error == wxSOCKET_WOULDBLOCK)
            {
                  m_canWriteToSocket = false;
                  gnutls_transport_set_errno(m_session, EAGAIN);
                  return -1;
            }

            gnutls_transport_set_errno(m_session, 0);
            return -1;
      }

      return m_pSocketBackend->LastCount();
}

ssize_t CTlsSocket::PullFunction(void* data, size_t len)
{
      if (!m_pSocketBackend)
      {
            gnutls_transport_set_errno(m_session, 0);
            return -1;
      }

      if (m_socketClosed)
            return 0;

      if (!m_canReadFromSocket)
      {
            gnutls_transport_set_errno(m_session, EAGAIN);
            return -1;
      }

      m_canReadFromSocket = false;

      m_pSocketBackend->Read(data, len);
      if (m_pSocketBackend->Error())
      {
            if (m_pSocketBackend->LastError() == wxSOCKET_WOULDBLOCK)
            {
                  if (m_canCheckCloseSocket)
                  {
                        wxSocketEvent evt(m_pSocketBackend->GetId());
                        evt.m_event = wxSOCKET_LOST;
                        wxPostEvent(this, evt);
                  }

                  gnutls_transport_set_errno(m_session, EAGAIN);
                  return -1;
            }

            gnutls_transport_set_errno(m_session, 0);
            return -1;
      }

      if (m_canCheckCloseSocket)
      {
            wxSocketEvent evt(m_pSocketBackend->GetId());
            evt.m_event = wxSOCKET_LOST;
            wxPostEvent(this, evt);
      }

      return m_pSocketBackend->LastCount();
}

void CTlsSocket::OnSocketEvent(wxSocketEvent& event)
{
      wxASSERT(m_pSocket);
      if (!m_session)
            return;

      if (event.GetId() != m_pSocketBackend->GetId())
            return;

      switch (event.GetSocketEvent())
      {
      case wxSOCKET_INPUT:
            OnRead();
            break;
      case wxSOCKET_OUTPUT:
            OnSend();
            break;
      case wxSOCKET_LOST:
            {
                  m_canCheckCloseSocket = true;
                  char tmp[100];
                  m_pSocketBackend->Peek(&tmp, 100);
                  if (!m_pSocketBackend->Error())
                  {
                        int lastCount = m_pSocketBackend->LastCount();

                        if (lastCount)
                              m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::OnSocketEvent(): pending data, postponing wxSOCKET_LOST"));
                        else
                              m_socketClosed = true;
                        OnRead();

                        if (lastCount)
                              return;
                  }

                  m_pOwner->LogMessage(Debug_Info, _T("CTlsSocket::OnSocketEvent(): wxSOCKET_LOST received"));

                  //Uninit();
                  wxSocketEvent evt(GetId());
                  evt.m_event = wxSOCKET_LOST;
                  wxPostEvent(m_pEvtHandler, evt);
            }
            break;
      default:
            break;
      }
}

void CTlsSocket::OnRead()
{
      m_pOwner->LogMessage(Debug_Debug, _T("CTlsSocket::OnRead()"));

      m_canReadFromSocket = true;

      if (!m_session)
            return;

      if (gnutls_record_get_direction(m_session))
            return;
            
      if (m_tlsState == handshake)
            Handshake();
      if (m_tlsState == closing)
            ContinueShutdown();
      else if (m_tlsState == conn)
      {
            CheckResumeFailedWrite();
            TriggerEvents();
      }
}

void CTlsSocket::OnSend()
{
      m_pOwner->LogMessage(Debug_Debug, _T("CTlsSocket::OnSend()"));

      m_canWriteToSocket = true;

      if (!m_session)
            return;

      if (!gnutls_record_get_direction(m_session))
            return;

      if (m_tlsState == handshake)
            Handshake();
      else if (m_tlsState == closing)
            ContinueShutdown();
      else if (m_tlsState == conn)
      {
            CheckResumeFailedWrite();
            TriggerEvents();
      }
}

int CTlsSocket::Handshake(const CTlsSocket* pPrimarySocket /*=0*/)
{
      m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::Handshake()"));
      wxASSERT(m_session);

      m_tlsState = handshake;

      if (pPrimarySocket)
      {
            // Implicitly trust certificate of primary socket
            unsigned int cert_list_size;
            const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(pPrimarySocket->m_session, &cert_list_size);
            if (cert_list && cert_list_size)
            {
                  m_implicitTrustedCert.data = new unsigned char[cert_list[0].size];
                  memcpy(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size);
                  m_implicitTrustedCert.size = cert_list[0].size;
            }
      }

      int res = gnutls_handshake(m_session);
      if (!res)
      {
            m_pOwner->LogMessage(Debug_Info, _T("Handshake successful"));

            wxString cipherName;
            const char* cipher = gnutls_cipher_get_name(gnutls_cipher_get(m_session));
            if (cipher)
                  cipherName = wxString(cipher, wxConvUTF8);
            else
                  cipherName = _T("unknown");

            wxString macName;
            const char* mac = gnutls_mac_get_name(gnutls_mac_get(m_session));
            if (mac)
                  macName = wxString(mac, wxConvUTF8);
            else
                  macName = _T("unknown");

            m_pOwner->LogMessage(Debug_Info, _T("Cipher: %s, MAC: %s"), cipherName.c_str(), macName.c_str());

            res = VerifyCertificate();
            if (res != FZ_REPLY_OK)
                  return res;

            m_tlsState = conn;

            wxSocketEvent evt(GetId());
            evt.m_event = wxSOCKET_CONNECTION;
            wxPostEvent(m_pEvtHandler, evt);
            TriggerEvents();

            if (m_shutdown_requested)
            {
                  Shutdown();
                  if (!Error() || LastError() != wxSOCKET_WOULDBLOCK)
                  {
                        wxSocketEvent evt(GetId());
                        evt.m_event = wxSOCKET_LOST;
                        wxPostEvent(m_pEvtHandler, evt);
                  }
            }

            return FZ_REPLY_OK;
      }
      else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED)
            return FZ_REPLY_WOULDBLOCK;

      Failure(res);

      return FZ_REPLY_ERROR;
}

void CTlsSocket::Read(void *buffer, unsigned int len)
{
      if (m_tlsState == handshake)
      {
            m_lastError = wxSOCKET_WOULDBLOCK;
            m_lastSuccessful = false;
            return;
      }
      else if (m_tlsState != conn)
      {
            m_lastError = wxSOCKET_IOERR;
            m_lastSuccessful = false;
            return;
      }

      m_canTriggerRead = true;

      if (m_peekDataLen)
      {
            unsigned int min = wxMin(len, m_peekDataLen);
            memcpy(buffer, m_peekData, min);
            
            if (min == m_peekDataLen)
            {
                  m_peekDataLen = 0;
                  delete [] m_peekData;
                  m_peekData = 0;
            }
            else
            {
                  memmove(m_peekData, m_peekData + min, m_peekDataLen - min);
                  m_peekDataLen -= min;
            }

            TriggerEvents();

            m_lastSuccessful = true;
            m_lastCount = min;
            return;
      }
      
      int res = gnutls_record_recv(m_session, buffer, len);
      if (res >= 0)
      {
            m_lastSuccessful = true;
            m_lastCount = res;

            if (res > 0)
                  TriggerEvents();

            return;
      }

      if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
            m_lastError = wxSOCKET_WOULDBLOCK;
      else
      {
            Failure(res);
            m_lastError = wxSOCKET_IOERR;
      }

      m_lastSuccessful = false;
      return;
}

void CTlsSocket::Write(const void *buffer, unsigned int len)
{
      if (m_tlsState == handshake)
      {
            m_lastError = wxSOCKET_WOULDBLOCK;
            m_lastSuccessful = false;
            return;
      }
      else if (m_tlsState != conn)
      {
            m_lastError = wxSOCKET_IOERR;
            m_lastSuccessful = false;
            return;
      }

      if (m_lastWriteFailed)
      {
            m_lastError = wxSOCKET_WOULDBLOCK;
            m_lastSuccessful = false;
            return;
      }

      if (m_writeSkip >= len)
      {
            m_writeSkip -= len;
            m_lastCount = len;
            m_lastSuccessful = true;
            return;
      }

      len -= m_writeSkip;
      buffer = (char*)buffer + m_writeSkip;

      int res = gnutls_record_send(m_session, buffer, len);
      if (res >= 0)
      {
            m_lastSuccessful = true;
            m_lastCount = res + m_writeSkip;
            m_writeSkip = 0;

            TriggerEvents();
            return;
      }

      if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
      {
            if (m_writeSkip)
            {
                  m_lastSuccessful = true;
                  m_lastCount = m_writeSkip;
                  m_writeSkip = 0;
            }
            else
            {
                  m_lastSuccessful = false;
                  m_lastError = wxSOCKET_WOULDBLOCK;
                  m_lastWriteFailed = true;
            }
      }
      else
      {
            m_lastSuccessful = false;
            Failure(res);
            m_lastError = wxSOCKET_IOERR;
      }
}

void CTlsSocket::TriggerEvents()
{
      if (m_tlsState != conn)
            return;

      if (m_canTriggerRead)
      {
            wxSocketEvent evt(GetId());
            evt.m_event = wxSOCKET_INPUT;
            wxPostEvent(m_pEvtHandler, evt);
            m_canTriggerRead = false;
      }

      if (m_canTriggerWrite)
      {
            wxSocketEvent evt(GetId());
            evt.m_event = wxSOCKET_OUTPUT;
            wxPostEvent(m_pEvtHandler, evt);
            m_canTriggerWrite = false;
      }
}

void CTlsSocket::CheckResumeFailedWrite()
{
      if (m_lastWriteFailed)
      {
            int res = gnutls_record_send(m_session, 0, 0);
            if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
                  return;
            
            if (res < 0)
            {
                  Failure(res);
                  return;
            }

            m_writeSkip += res;
            m_lastWriteFailed = false;
            m_canTriggerWrite = true;

            wxASSERT(GNUTLS_E_INVALID_REQUEST == gnutls_record_send(m_session, 0, 0));
      }
}

void CTlsSocket::Failure(int code)
{
      if (code)
            LogError(code);
      Uninit();

      wxSocketEvent evt(GetId());
      evt.m_event = wxSOCKET_LOST;
      wxPostEvent(m_pEvtHandler, evt);
}

void CTlsSocket::Peek(void *buffer, unsigned int len)
{
      if (m_peekData)
      {
            int min = wxMin(len, m_peekDataLen);
            memcpy(buffer, m_peekData, min);
            
            m_lastCount = min;
            m_lastSuccessful = true;
            return;
      }

      Read(buffer, len);
      if (Error() || !LastCount())
            return;

      m_peekDataLen = LastCount();
      m_peekData = new char[m_peekDataLen];
      memcpy(m_peekData, buffer, m_peekDataLen);
}

void CTlsSocket::Shutdown()
{
      m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::Shutdown()"));

      if (m_tlsState == closed)
      {
            m_lastSuccessful = true;
            return;
      }

      if (m_tlsState == closing)
      {
            m_lastSuccessful = false;
            m_lastError = wxSOCKET_WOULDBLOCK;
            return;
      }

      if (m_tlsState == handshake || m_tlsState == verifycert)
      {
            // Shutdown during handshake is not a good idea.
            m_pOwner->LogMessage(Debug_Verbose, _T("Shutdown during handshake, postponing"));
            m_shutdown_requested = true;
            m_lastSuccessful = false;
            m_lastError = wxSOCKET_WOULDBLOCK;
            return;
      }

      if (m_tlsState != conn)
      {
            m_lastSuccessful = false;
            m_lastError = wxSOCKET_IOERR;
            return;
      }

      m_tlsState = closing;

      int res = gnutls_bye(m_session, GNUTLS_SHUT_WR);
      if (!res)
      {
            m_tlsState = closed;
            m_lastSuccessful = true;
            return;
      }

      m_lastSuccessful = false;
      if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
            m_lastError = wxSOCKET_WOULDBLOCK;
      else
      {
            Failure(res);
            m_lastError = wxSOCKET_IOERR;
      }
}

void CTlsSocket::ContinueShutdown()
{
      m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::ContinueShutdown()"));

      int res = gnutls_bye(m_session, GNUTLS_SHUT_WR);
      if (!res)
      {
            m_tlsState = closed;

            wxSocketEvent evt(GetId());
            evt.m_event = wxSOCKET_LOST;
            wxPostEvent(m_pEvtHandler, evt);

            return;
      }

      if (res != GNUTLS_E_INTERRUPTED && res != GNUTLS_E_AGAIN)
            Failure(res);
}

void CTlsSocket::TrustCurrentCert(bool trusted)
{
      if (m_tlsState != verifycert)
      {
            m_pOwner->LogMessage(Debug_Warning, _T("TrustCurrentCert called at wrong time."));
            return;
      }

      if (trusted)
      {
            m_tlsState = conn;

            wxSocketEvent evt(GetId());
            evt.m_event = wxSOCKET_CONNECTION;
            wxPostEvent(m_pEvtHandler, evt);
            TriggerEvents();
            return;
      }

      m_pOwner->LogMessage(::Error, _("Remote certificate not trusted."));
      Failure(0);
}

static wxString bin2hex(const unsigned char* in, size_t size)
{
      wxString str;
      for (size_t i = 0; i < size; i++)
      {
            if (i)
                  str += _T(":");
            str += wxString::Format(_T("%.2x"), (int)in[i]);
      }

      return str;
}

int CTlsSocket::VerifyCertificate()
{
      if (m_tlsState != handshake)
      {
            m_pOwner->LogMessage(Debug_Warning, _T("VerifyCertificate called at wrong time"));
            return FZ_REPLY_ERROR;
      }

      m_tlsState = verifycert;

      if (gnutls_certificate_type_get(m_session) != GNUTLS_CRT_X509)
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("Unsupported certificate type"));
            Failure(0);
            return FZ_REPLY_ERROR;
      }

      unsigned int cert_list_size;
      const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(m_session, &cert_list_size);
      if (!cert_list || !cert_list_size)
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_certificate_get_peers returned no certificates"));
            Failure(0);
            return FZ_REPLY_ERROR;
      }

      if (m_implicitTrustedCert.data)
      {
            if (m_implicitTrustedCert.size != cert_list[0].size ||
                  memcmp(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size))
            {
                  m_pOwner->LogMessage(::Error, _("Primary connection and data connection certificates don't match."));
                  Failure(0);
                  return FZ_REPLY_ERROR;
            }
            
            TrustCurrentCert(true);
            return FZ_REPLY_OK;
      }

      gnutls_x509_crt_t cert;
      if (gnutls_x509_crt_init(&cert))
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_crt_init failed"));
            Failure(0);
            return FZ_REPLY_ERROR;
      }

      if (gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER))
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_crt_import failed"));
            Failure(0);
            gnutls_x509_crt_deinit(cert);
            return FZ_REPLY_ERROR;
      }

      wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert);
      wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert);

      // Get the serial number of the certificate
      unsigned char buffer[40];
      size_t size = sizeof(buffer);
      int res = gnutls_x509_crt_get_serial(cert, buffer, &size);

      wxString serial = bin2hex(buffer, size);

      unsigned int bits;
      int algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits);

      wxString algoName;
      const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo);
      if (pAlgo)
            algoName = wxString(pAlgo, wxConvUTF8);

      //int version = gnutls_x509_crt_get_version(cert);
      
      wxString subject, issuer;

      size = 0;
      res = gnutls_x509_crt_get_dn(cert, 0, &size);
      if (size)
      {
            char* dn = new char[size + 1];
            dn[size] = 0;
            if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size)))
            {
                  dn[size] = 0;
                  subject = wxString(dn, wxConvUTF8);
            }
            else
                  LogError(res);
            delete [] dn;
      }
      else
            LogError(res);
      if (subject == _T(""))
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_get_dn failed"));
            Failure(0);
            gnutls_x509_crt_deinit(cert);
            return FZ_REPLY_ERROR;
      }

      size = 0;
      res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size);
      if (size)
      {
            char* dn = new char[size + 1];
            dn[size] = 0;
            if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size)))
            {
                  dn[size] = 0;
                  issuer = wxString(dn, wxConvUTF8);
            }
            else
                  LogError(res);
            delete [] dn;
      }
      else
            LogError(res);
      if (issuer == _T(""))
      {
            m_pOwner->LogMessage(::Debug_Warning, _T("gnutls_x509_get_issuer_dn failed"));
            Failure(0);
            gnutls_x509_crt_deinit(cert);
            return FZ_REPLY_ERROR;
      }

      wxString fingerprint_md5;
      wxString fingerprint_sha1;

      unsigned char digest[100];
      size = sizeof(digest) - 1;
      if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size))
      {
            digest[size] = 0;
            fingerprint_md5 = bin2hex(digest, size);
      }
      size = sizeof(digest) - 1;
      if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size))
      {
            digest[size] = 0;
            fingerprint_sha1 = bin2hex(digest, size);
      }

      CCertificateNotification *pNotification = new CCertificateNotification(
            m_pOwner->GetCurrentServer()->GetHost(),
            m_pOwner->GetCurrentServer()->GetPort(),
            cert_list->data, cert_list->size,
            activationTime, expirationTime,
            serial,
            algoName, bits,
            fingerprint_md5,
            fingerprint_sha1,
            subject,
            issuer);

      pNotification->requestNumber = m_pOwner->GetEngine()->GetNextAsyncRequestNumber();
      
      m_pOwner->GetEngine()->AddNotification(pNotification);

      m_pOwner->LogMessage(Status, _("Verifying certificate..."));

      return FZ_REPLY_WOULDBLOCK;
}

void CTlsSocket::OnRateAvailable(enum CRateLimiter::rate_direction direction)
{
}

Generated by  Doxygen 1.6.0   Back to index