Hello,

I tested your small program and it seems to work properly, which, I
suppose, means that the problem resides in my client code. I
copy-pasted the output below.

I just find something strange on the server : to write my server code,
I followed a tuto where they initialised a diffie-helman key in the
server side. I was not sure of the utility of that and thus, I
performed several tests with the command you provided : with and
without this initialisation on the server side. In both cases, this
works properly. So, I am a little bit confused about that. I would
want to remove that part, but I am not sure if it may be useful...

I joined my client code. The interesting function is
"wxSSLSocketClient::InitiateSSLSession". This code uses the wxWidgets
library and thus, it uses the wxSocketClient (wxWidgets socket
implementation) with a dedicated BIO so that openssl can handle it.
This code is extracted from the wxEMail project (I am the maintaniner
of this project). But, in this project, I did not implement the server
certificate check stuff. Thus, this version is slighlty modified to
perform those additional checks.

You will easily identify which part is original code and which one is
not because original code was designed to work in static link as well
as dynamic link (with a manual load of library). So, in original code,
all ssl calls are encapsulated in a macro. The modified version
currenlty only support static link, and thus ssl calls are not
encapsulated in the macro.

Note that this code allows performing ssl connection on different
servers and thus, I really think that the BIO part and so on is OK.
The only part that has never been tested is the new part performing
the server certificate check.

Thanks for your help.

Regards,
Brice


D:\home\DbSync1>C:\OpenSSL-Win32\bin\openssl s_client -connect localhost:1212 -C
Afile server.crt
Loading 'screen' into random state - done
CONNECTED(00000738)
depth=0 C = BE, ST = Hainaut, L = Charleroi, O = AMS-Solutions, CN = Brice Andre
, emailAddress = brice.an...@xxx.be
verify return:1
---
Certificate chain
 0 s:/C=BE/ST=Hainaut/L=Charleroi/O=AMS-Solutions/CN=Brice Andre/emailAddress=br
ice.an...@xxx.be
   i:/C=BE/ST=Hainaut/L=Charleroi/O=AMS-Solutions/CN=Brice Andre/emailAddress=br
ice.an...@xxx.be
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDnDCCAoQCCQDc4fMRV+0qfzANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMC
QkUxEDAOBgNVBAgTB0hhaW5hdXQxEjAQBgNVBAcTCUNoYXJsZXJvaTEWMBQGA1UE
ChMNQU1TLVNvbHV0aW9uczEUMBIGA1UEAxMLQnJpY2UgQW5kcmUxKzApBgkqhkiG
9w0BCQEWHGJyaWNlLmFuZHJlQGFtcy1zb2x1dGlvbnMuYmUwIBcNMTMwNTI2MDUw
MzUyWhgPMjA2ODAyMjcwNTAzNTJaMIGOMQswCQYDVQQGEwJCRTEQMA4GA1UECBMH
SGFpbmF1dDESMBAGA1UEBxMJQ2hhcmxlcm9pMRYwFAYDVQQKEw1BTVMtU29sdXRp
b25zMRQwEgYDVQQDEwtCcmljZSBBbmRyZTErMCkGCSqGSIb3DQEJARYcYnJpY2Uu
YW5kcmVAYW1zLXNvbHV0aW9ucy5iZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBAKEDpEF1+IOPim2EPvgVjOtdnSal4UjSdl1Bg2dTpGWZpUAwacoCT7kB
sTwkGqgSHs/3Zt171oa14qZrBequpjcMCKOD/JLsMYNZaJLIhLIMHUbNiq0xEIeu
dwy81MhwzKIKm/4SAta++x6/wLVGsgJ+GgLMEs7oDpAVgiOot1xV4SEUfsanrl8e
QQkjP43pPTtWbdDsTZ4XKl2LStH5hFVnYAC7Y6KEbZJvkqcfMG92mSsOR/4JrSWe
0WtjBjoDhkPxnmlpuFkyfk5EFep5/Qg7Ut+fi0k4/9O28POXbFEwnstDqTbSJdsN
N0C665u9167J+AmkeZ3n7z41HGgB1TcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
K7t53eIY+rMjyCk9IDtcD+SUDa4AltuVcSq0xADzjjtH+11QQvI4/l20eDBV/bnm
HpbNZP2Z8jBnbrCn7bEOqY1HzQrc9KBipy+kbNHknq1MzcteB6b1qIOgr92A0e6A
qVqaULuXKsIj0Ot/g6eh//e4IBJGOg+kbSpB3mDO9G9utP3W8KB7leUDmsBRW1ld
tQ4wtmqknr1WZSXkxa4JDFDBwP6DWymbSl0S7xQO9/5kPWIubL77FxxUZ73jC/G+
iz+rAM2LrqN3Lppp3aH7gkH9pKTWciE7f8kEHfSUKU7LQ87bood0R8XOTvE5xuJq
lJSl3bu6XXt/u/ZibObTyw==
-----END CERTIFICATE-----
subject=/C=BE/ST=Hainaut/L=Charleroi/O=AMS-Solutions/CN=Brice Andre/emailAddress
=brice.an...@xxx.be
issuer=/C=BE/ST=Hainaut/L=Charleroi/O=AMS-Solutions/CN=Brice Andre/emailAddress=
brice.an...@xxx.be
---
No client certificate CA names sent
---
SSL handshake has read 1774 bytes and written 519 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: 6F265E53749453BE5C3DD2BFFF4B99A1DBDA559AF76E8C8974A90ABEEED34AF1

    Session-ID-ctx:
    Master-Key: 142C4C0BA297D034922C619C9C6EF658D66C476386CE0FECD502B3B990FD01BE
FA3C6B067055860A7BD8632B69E49810
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    0000 - 86 89 a4 c4 44 8f a9 e4-0d 76 5f 7e 95 3c 3d aa   ....D....v_~.<=.
    0010 - 05 4b f0 33 bc 09 7e 08-42 0d f6 81 41 52 81 62   .K.3..~.B...AR.b
    0020 - 0f cc 2d de 32 84 b2 57-28 fc c3 2c cc 4b 26 42   ..-.2..W(..,.K&B
    0030 - 8b f0 8e 99 37 8e fb 63-50 fe ee c6 10 b1 37 da   ....7..cP.....7.
    0040 - 90 1c 03 ad cb 08 db ff-93 dc 40 1c a1 7a e1 43   ..........@..z.C
    0050 - f2 fc d2 3d 86 46 9a 88-d6 6f 25 62 aa 59 41 a9   ...=.F...o%b.YA.
    0060 - a6 29 45 dc 47 3b a9 2f-60 bb 34 d2 42 74 d7 48   .)E.G;./`.4.Bt.H
    0070 - d7 82 71 66 d5 5c 1d fb-84 86 10 93 d9 59 d1 cd   ..qf.\.......Y..
    0080 - 72 ac be d8 bc af 23 a1-00 90 a7 4b 68 ef 58 69   r.....#....Kh.Xi
    0090 - f5 e7 75 b0 be 33 d4 19-d8 e0 81 b4 b8 37 bc 79   ..u..3.......7.y

    Start Time: 1369897977
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

2013/5/29 Dave Thompson <dthomp...@prinpay.com>:
>> From: owner-openssl-us...@openssl.org On Behalf Of Brice André
>> Sent: Wednesday, 29 May, 2013 03:14
>
>> I performed a test yesterday with the instruction
>> SSL_CTX_use_certificate_file(tx,path_to_file, SSL_FILETYPE_PEM);
>> replaced by
>> SSL_CTX_load_verify_locations(ctx, path_to_file, NULL);
>>
>> Where path_to_file points to my file "server.crt". The function
>> returns 1 so, I expect my certificate to be properly initialised.
>>
> To be exact, the client's trustore containing your cert.
>
> One possible problem here: _load_verify_ accepts a sequence of
> (PEM) certs, including zero, skipping any invalid format(s).
> Make sure the client's file is/contains an exact copy of the
> server's certfile, at least the lines from dash-BEGIN to dash-END,
> including eol (either NL or CRLF okay) after each line (including
> the dash-END line) and body lines not longer than 76 characters.
> If you copied the content by cut-and-paste or sending in an email
> or something like that, these sometimes go wrong. If you transferred
> the file using FTP or SCP or similar, they shouldn't. (FTP mode A
> may convert but not add/delete/move eols, and that is okay.)
>
>> But, whn I perform the connect, I get an error. The corresponding
>> error message is :
>> error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate
>> verify failed
>>
>> After the connect failed, the function SSL_get_peer_certificate(ssl)
>> returns NULL and the function SSL_get_verify_result(ssl) returns 18
>> (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT), which is exactly the same
>> problem as before.
>>
> It should work and does for me, as long as the client CAfile is
> exactly the (selfsigned) cert the server is using; and you don't have
> KeyUsage excluding certSign, but that gives a different error.
>
> If it isn't damaged per above and you have commandline on the client try
>   openssl s_client -connect host:port -CAfile same.server.crt.file
> and see what it says for Verify return code at the end of SSL-session
> (note s_client unlike a real app will proceed even if verify error).
>
>> My server is also printing an error message:
>> error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
>>
> That's consistent; if the client decides the server cert is bad,
> the client aborts the handshake with an alert like that.
> (The exact alert may vary SSL vs TLS, but always some alert.)
>
> ______________________________________________________________________
> OpenSSL Project                                 http://www.openssl.org
> User Support Mailing List                    openssl-users@openssl.org
> Automated List Manager                           majord...@openssl.org
////////////////////////////////////////////////////////////////////////////
// Name:        wxSSLSocketClient.cpp
// Purpose:     This class implements the wxSSLSocketClient
// Author:      Brice Andr�
// Created:     2011/01/25
// RCS-ID:      $Id: mycomp.cpp 505 2007-03-31 10:31:46Z frm $
// Copyright:   (c) 2011 Brice Andr�
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////

#ifdef OPEN_SSL_STATIC_LINK
#define CALL_SSL(lib,func) func
#else
#define CALL_SSL(lib,func) lib.func
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

// includes
#ifndef WX_PRECOMP
   // here goes the #include <wx/abc.h> directives for those
   // files which are not included by wxprec.h
#endif

#include <wx/ssl/wxSSLSocketClient.h>

wxSSLSocketClient::OpenSslInitialisator::OpenSslInitialisator()
{
   /* We perform a lazy load of lib so that it does not fail if openssl lib could not be loaded in case it is not requested */
   lib_is_initialised = false;
}

wxSSLSocketClient::OpenSslInitialisator::~OpenSslInitialisator()
{

}

const wxSSLSocketClient::OpenSslInitialisator::LibIf_t& wxSSLSocketClient::OpenSslInitialisator::GetLibIf()
{
   /* Check if lib was already loaded */
   if (!lib_is_initialised)
   {
#ifndef OPEN_SSL_STATIC_LINK
      /* load the library */
      if (!ssl_lib.Load(wxT("ssleay32")))
      {
         throw Exception(wxT("Unable to load ssleay32 dynamic library"));
      }
      if (!lib_eay.Load(wxT("libeay32")))
      {
         throw Exception(wxT("Unable to load libeay32 dynamic library"));
      }

      /* Initialise the library */
      ((void(*)(void))LoadSymbol(ssl_lib, wxT("SSL_load_error_strings"), wxT("ssleay32")))();
      ((void(*)(void))LoadSymbol(ssl_lib, wxT("SSL_library_init"), wxT("ssleay32")))();

      /* Initialise all requested symbols */
      lib_if.SSLv23_client_method = (const SSL_METHOD*(*)(void))LoadSymbol(ssl_lib, wxT("SSLv23_client_method"), wxT("ssleay32"));
      lib_if.SSL_CTX_new = (SSL_CTX*(*)(const SSL_METHOD*))LoadSymbol(ssl_lib, wxT("SSL_CTX_new"), wxT("ssleay32"));
      lib_if.SSL_CTX_free = (void(*)(SSL_CTX*))LoadSymbol(ssl_lib, wxT("SSL_CTX_free"), wxT("ssleay32"));
      lib_if.SSL_CTX_ctrl = (long(*)(SSL_CTX*, int,long,void*))LoadSymbol(ssl_lib, wxT("SSL_CTX_ctrl"), wxT("ssleay32"));
      lib_if.SSL_new = (SSL*(*)(SSL_CTX*))LoadSymbol(ssl_lib, wxT("SSL_new"), wxT("ssleay32"));
      lib_if.SSL_free = (void (*)(SSL*))LoadSymbol(ssl_lib, wxT("SSL_free"), wxT("ssleay32"));
      lib_if.SSL_set_cipher_list = (int(*)(SSL*,const char*))LoadSymbol(ssl_lib, wxT("SSL_set_cipher_list"), wxT("ssleay32"));
      lib_if.SSL_set_bio = (void(*)(SSL*,BIO*,BIO*))LoadSymbol(ssl_lib, wxT("SSL_set_bio"), wxT("ssleay32"));
      lib_if.SSL_set_connect_state = (void(*)(SSL*))LoadSymbol(ssl_lib, wxT("SSL_set_connect_state"), wxT("ssleay32"));
      lib_if.SSL_connect = (int(*)(SSL*))LoadSymbol(ssl_lib, wxT("SSL_connect"), wxT("ssleay32"));
      lib_if.SSL_shutdown = (int(*)(SSL*))LoadSymbol(ssl_lib, wxT("SSL_shutdown"), wxT("ssleay32"));
      lib_if.SSL_read = (int(*)(SSL*,void*,int))LoadSymbol(ssl_lib, wxT("SSL_read"), wxT("ssleay32"));
      lib_if.SSL_write = (int(*)(SSL*,const void*,int))LoadSymbol(ssl_lib, wxT("SSL_write"), wxT("ssleay32"));
      lib_if.SSL_get_error = (int(*)(const SSL *ssl, int ret))LoadSymbol(ssl_lib, wxT("SSL_get_error"), wxT("ssleay32"));

      lib_if.BIO_new = (BIO*(*)(BIO_METHOD*))LoadSymbol(lib_eay, wxT("BIO_new"), wxT("libeay32"));
      lib_if.BIO_free = (int(*)(BIO*))LoadSymbol(lib_eay, wxT("BIO_free"), wxT("libeay32"));
      lib_if.ERR_get_error = (unsigned long(*)(void))LoadSymbol(lib_eay, wxT("ERR_get_error"), wxT("libeay32"));
      lib_if.ERR_error_string = (char*(*)(unsigned long e, char *buf))LoadSymbol(lib_eay, wxT("ERR_error_string"), wxT("libeay32"));
#else
      SSL_load_error_strings();
      SSL_library_init();
#endif
      lib_is_initialised = true;

   }
   return lib_if;
}

void* wxSSLSocketClient::OpenSslInitialisator::LoadSymbol(wxDynamicLibrary& lib, const wxString& name, const wxString& lib_name)
{
   void* result = lib.GetSymbol(name);
   if (result == NULL)
   {
      throw Exception(wxString::Format(_("Unable to load symbol \"%s\" from library \"%s\""),
                                       name.fn_str(),
                                       lib_name.fn_str()));
   }
   return result;
}

wxSSLSocketClient::wxSSLSocketClient(wxSocketFlags flags,
                                     bool check_certificate,
                                     const wxString& certificate_file)
                  :wxSocketClient(flags),
                   connection_state(NoSslConnectionState),
                   check_certificate(check_certificate),
                   certificate_file(certificate_file)
{
   /* configure internal stuff */
   ctx = NULL;
   ssl = NULL;
   bio = NULL;

   last_ssl_count = 0;
   ssl_error = true;
}

wxSSLSocketClient::~wxSSLSocketClient()
{
   /* Check if we are currently in SSL connection */
   if (connection_state != NoSslConnectionState)
   {
      /* We shall first switch to blocking mode because, if object is destroyed during
       * wxWidgets cleanup, no more event loop is running
       */
      //TODO : note that if we detect that we are in cleanup phase, we could avoid configuring socket in
      // blocking mode when not requested...
      SetFlags(wxSOCKET_WAITALL|wxSOCKET_BLOCK);

      /* Now, we can safely cleanup socket stuff */
      TerminateSSLSession();
   }
}

wxSSLSocketClient::SslSessionStatus_t wxSSLSocketClient::InitiateSSLSession()
{
   /* Check if we are not already in SSL session */
   if (connection_state == SslConnectedState)
   {
      /* We are already in SSL session... */
      return SslFailed;
   }

   /* Get lib info */
   const OpenSslInitialisator::LibIf_t& ssl_lib = open_ssl_initialisator.GetLibIf();

   /* Check if connection is pending */
   if (connection_state == NoSslConnectionState)
   {
      /* Configure ssl context */
      ctx = CALL_SSL(ssl_lib,SSL_CTX_new)(CALL_SSL(ssl_lib,SSLv23_client_method)());
      //ssl_lib.SSL_CTX_ctrl(ctx,SSL_CTRL_OPTIONS,SSL_OP_ALL,NULL);

      /* Check if we shall request server authentication */
      if (check_certificate)
      {
         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
         int res = SSL_CTX_load_verify_locations(ctx, certificate_file.mb_str().data(), NULL);
         wxLogDebug("Function returned %d", res);
      }

      /* Create SSL connection */
      ssl = CALL_SSL(ssl_lib,SSL_new)(ctx);
      if (ssl != NULL)
      {
         /* Configure cypher algorithms supported */
         CALL_SSL(ssl_lib,SSL_set_cipher_list)(ssl, "ALL");

         bio = CALL_SSL(ssl_lib,BIO_new)(SslBio::GetBio());
         bio->ptr = this;
         CALL_SSL(ssl_lib,SSL_set_bio)(ssl,bio,bio);

         CALL_SSL(ssl_lib,SSL_set_connect_state)(ssl);
      }
      else
      {
         /* Release context */
         CALL_SSL(ssl_lib,SSL_CTX_free)(ctx);
         ctx = NULL;

         /* Return error status */
         return SslFailed;
      }
   }

   /* Try connection */
   int ret = CALL_SSL(ssl_lib,SSL_connect)(ssl);
   if (ret <= 0)
   {
      /* check if we are just in a retry mode */
      int error = CALL_SSL(ssl_lib,SSL_get_error)(ssl, ret);
      if ((error == SSL_ERROR_WANT_READ) ||
          (error == SSL_ERROR_WANT_WRITE))
      {
         /* mark connection as pending */
         connection_state = SsConnectionPendingState;
         return SslPending;
      }
      else
      {
         /* Try to get some info */
         char msg[65535];
         ERR_error_string_n(ERR_get_error(), msg, 65535);
         wxString error_message =
               wxString::Format("Error: %s (got certificate : %s, error id %d)\n\n",
                                msg,
                                SSL_get_peer_certificate(ssl)==NULL?"false":"true",
                                SSL_get_verify_result(ssl));
         wxLogDebug(error_message);

         /* Release connection*/
         CALL_SSL(ssl_lib,SSL_free)(ssl);
         ssl = NULL;

         /* Release context */
         CALL_SSL(ssl_lib,SSL_CTX_free)(ctx);
         ctx = NULL;

         /* reset connection state */
         connection_state = NoSslConnectionState;
         return SslFailed;
      }
   }

   /* check certificate stuff */
   if (check_certificate)
   {
      int error = SSL_get_verify_result(ssl);
      wxLogDebug("Error : %d", error);
      if ((SSL_get_peer_certificate(ssl) == NULL) ||
          ((SSL_get_verify_result(ssl) != X509_V_OK) &&
           (SSL_get_verify_result(ssl) != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) &&
           (SSL_get_verify_result(ssl) != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)))
      {
         //TODO : on ne peut pas faire comme ça : une fois ce check raté, les autres ne sont plus faits!!!
         if (SSL_get_peer_certificate(ssl) == NULL)
         {
            wxLogDebug("Certificate not received !");
         }
         else
         {
            wxLogDebug("Could not validate received certificate !");
         }
         return SslCertificateNotChecked;
      }
   }

   /* We are properly connected */
   connection_state = SslConnectedState;
   return SslConnected;
}

bool wxSSLSocketClient::TerminateSSLSession()
{
   /* check if we are connected */
   if (connection_state == NoSslConnectionState)
   {
      return false;
   }

   /* Get lib info */
   const OpenSslInitialisator::LibIf_t& ssl_lib = open_ssl_initialisator.GetLibIf();

   /* Close session */
   CALL_SSL(ssl_lib,SSL_shutdown)(ssl);

   /* Release connection*/
   CALL_SSL(ssl_lib,SSL_free)(ssl);
   ssl = NULL;

   /* Release context */
   CALL_SSL(ssl_lib,SSL_CTX_free)(ctx);
   ctx = NULL;

   /* Mark as no ssl */
   connection_state = NoSslConnectionState;

   /* We are now properly disconnected from SSL session */
   return true;
}

bool wxSSLSocketClient::IsInSSLSession() const
{
   return connection_state == SslConnectedState;
}

bool wxSSLSocketClient::SslSessionPending() const
{
   return connection_state == SsConnectionPendingState;
}

wxSSLSocketClient& wxSSLSocketClient::Read(void* buffer, wxUint32 nbytes)
{
   /* check if we are in ssl mode */
   if (connection_state == SslConnectedState)
   {
      /* Perform a SSL read */
      int nb_bytes_read = CALL_SSL(open_ssl_initialisator.GetLibIf(),SSL_read)(ssl, buffer, nbytes);
      if (nb_bytes_read < 0)
      {
         last_ssl_count = 0;
         ssl_error = true;
      }
      else
      {
         last_ssl_count = nb_bytes_read;
         ssl_error = false;
      }
   }
   else if (connection_state == NoSslConnectionState)
   {
      /* perform a normal read */
      wxSocketClient::Read(buffer, nbytes);
   }
   else
   {
      last_ssl_count = 0;
      ssl_error = true;
   }

   return *this;
}

wxSSLSocketClient& wxSSLSocketClient::Write(const void *buffer, wxUint32 nbytes)
{
   /* check if we are in ssl mode */
   if (connection_state == SslConnectedState)
   {
      /* Perform a SSL read */
      int nb_bytes_written = CALL_SSL(open_ssl_initialisator.GetLibIf(),SSL_write)(ssl, buffer, nbytes);
      if (nb_bytes_written < 0)
      {
         last_ssl_count = 0;
         ssl_error = true;
      }
      else
      {
         last_ssl_count = nb_bytes_written;
         ssl_error = false;
      }
   }
   else if (connection_state == NoSslConnectionState)
   {
      /* perform a normal read */
      wxSocketClient::Write(buffer, nbytes);
   }
   else
   {
      last_ssl_count = 0;
      ssl_error = true;
   }

   return *this;
}

wxSSLSocketClient& wxSSLSocketClient::BasicRead(void* buffer, wxUint32 nbytes)
{
   return (wxSSLSocketClient&)wxSocketClient::Read(buffer, nbytes);
}

wxSSLSocketClient& wxSSLSocketClient::BasicWrite(const void *buffer, wxUint32 nbytes)
{
   return (wxSSLSocketClient&)wxSocketClient::Write(buffer, nbytes);
}

wxUint32 wxSSLSocketClient::LastCount() const
{
   if (connection_state != NoSslConnectionState)
   {
      return last_ssl_count;
   }
   else
   {
      return wxSocketClient::LastCount();
   }
}

wxUint32 wxSSLSocketClient::BasicLastCount() const
{
   return wxSocketClient::LastCount();
}

bool wxSSLSocketClient::Error() const
{
   if (connection_state != NoSslConnectionState)
   {
      return ssl_error;
   }
   else
   {
      return wxSocketClient::Error();
   }
}

bool wxSSLSocketClient::BasicError() const
{
   return wxSocketClient::Error();
}

bool wxSSLSocketClient::Close()
{
   if (IsInSSLSession())
   {
      TerminateSSLSession();
   }
   return wxSocketClient::Close();
}

BIO_METHOD* wxSSLSocketClient::SslBio::GetBio()
{
   static BIO_METHOD methods =
   {
      BIO_TYPE_SOCKET,
      "wxEmail Socket",
      Write,
      Read,
      Puts,
      Gets,
      Ctrl,
      Create,
      Destroy,
      NULL,
   };
   return &methods;
}

int wxSSLSocketClient::SslBio::Write(BIO* bio, const char* buffer, int nbytes)
{
   wxSSLSocketClient* ptr = (wxSSLSocketClient*)bio->ptr;
   ptr->BasicWrite(buffer, nbytes);
   if (ptr->BasicError())
   {
      return -1;
   }
   else
   {
      return ptr->BasicLastCount();
   }
}

int wxSSLSocketClient::SslBio::Read(BIO* bio, char* buffer, int nbytes)
{
   wxSSLSocketClient* ptr = (wxSSLSocketClient*)bio->ptr;
   ptr->BasicRead(buffer, nbytes);
   if (ptr->BasicError())
   {
      return -1;
   }
   else
   {
      return ptr->BasicLastCount();
   }
}

int wxSSLSocketClient::SslBio::Puts(BIO*, const char*)
{
   throw Exception(wxT("wxSSLSocketClient::SslBio::Puts : not implemented"));
}

int wxSSLSocketClient::SslBio::Gets(BIO*, char*, int)
{
   throw Exception(wxT("wxSSLSocketClient::SslBio::Gets : not implemented"));
}

long wxSSLSocketClient::SslBio::Ctrl(BIO* WXUNUSED(bio), int WXUNUSED(ctrl), long WXUNUSED(arg), void* WXUNUSED(clbk))
{
   return 1;
}

int wxSSLSocketClient::SslBio::Create(BIO* bio)
{
   bio->init=1;
   bio->num=-1;
   bio->ptr=NULL;
   bio->flags=0;
   return 1;
}

int wxSSLSocketClient::SslBio::Destroy(BIO* bio)
{
   if (bio == NULL)
   {
      return 0;
   }
   if (bio->shutdown)
   {
      bio->init=0;
      bio->flags=0;
   }
   return 1;
}

wxSSLSocketClient::OpenSslInitialisator wxSSLSocketClient::open_ssl_initialisator;

Reply via email to