This is on a WIN2000 server using VC++6.0. Eventually the server side will
be multi-threaded, that's why the Mutex setup. Any help is appreciated.
BTW - I'm also encountering Memory leaks so if anyone has any suggestions
along those lines I could use them.
Server side Error:
1832:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version
number:.\ssl\s3_pkt.c:290:
Server Side/Client Side Common class methods/functions (cMemoryBlob is a
dynaiclly growing memory buffer):
cSSL g_objSSL;
bool cSSL::m_bLockCreated = false;
HANDLE *cSSL::m_pMutex=NULL;
int cSSL::m_iNumLocks=0;
cSSL::cSSL()
{
if(!m_bLockCreated)
{
int iLoop;
m_iNumLocks = CRYPTO_num_locks();
m_bLockCreated = true;
m_pMutex = new HANDLE[m_iNumLocks];
for(iLoop=0; iLoop<m_iNumLocks; iLoop++)
m_pMutex[iLoop] = CreateMutex(NULL, FALSE, NULL);
}
CRYPTO_set_locking_callback(&cSSL::ssl_lock);
// CRYPTO_set_id_callback(); // Not needed for Windows or Linux
m_bErrorStringsLoaded=true;
SSL_load_error_strings();
m_pServerCTX=NULL;
m_bServerCTXCreated=false;
m_pClientCTX=NULL;
m_bClientCTXCreated=false;
rSeed();
OpenSSL_add_ssl_algorithms();
ssl_thread_start();
}
cSSL::~cSSL()
{
ssl_thread_done();
if(m_bServerCTXCreated)
SSL_CTX_free(m_pServerCTX);
if(m_bClientCTXCreated)
SSL_CTX_free(m_pClientCTX);
if(m_bErrorStringsLoaded)
ERR_free_strings();
RAND_cleanup(); // frees memory used by the PRNG
OBJ_cleanup();
EVP_cleanup(); // for OpenSSL_add_all_algorithms()
EVP_PBE_cleanup();
//ASN1_STRING_TABLE_cleanup();
BIO_sock_cleanup();
/*X509V3_EXT_cleanup();
X509_PURPOSE_cleanup();
X509_TRUST_cleanup();
*/
//ERR_remove_state(0);
OBJ_NAME_cleanup(-1); /* -1 for everything */
CRYPTO_set_locking_callback(NULL);
if(m_bLockCreated)
{
int iLoop;
m_bLockCreated = false;
for(iLoop=0; iLoop<m_iNumLocks; iLoop++)
CloseHandle(m_pMutex[iLoop]);
delete[] m_pMutex;
m_pMutex=NULL;
m_iNumLocks=0;
}
}
void cSSL::ssl_thread_start(void)
{
}
void cSSL::ssl_thread_done(void)
{
ERR_remove_state(0);
}
SSL_CTX *cSSL::ClientCTX(void)
{
if(!m_bClientCTXCreated)
{
SSL_METHOD *meth = SSLv3_client_method();
m_pClientCTX = SSL_CTX_new(meth);
SSL_CTX_set_options(m_pClientCTX, 0 /* ALL off*/);
SSL_CTX_set_cipher_list(m_pClientCTX, "ADH-DES-CBC3-SHA");
//"EXP-ADH-DES-CBC-SHA");
m_bClientCTXCreated = true;
}
return m_pClientCTX;
}
SSL_CTX *cSSL::ServerCTX(void)
{
if(!m_bServerCTXCreated)
{
SSL_METHOD *meth = SSLv3_server_method();
m_pServerCTX = SSL_CTX_new(meth);
SSL_CTX_set_quiet_shutdown(m_pServerCTX, 1 /* on */);
SSL_CTX_set_options(m_pServerCTX, 0 /* ALL off*/);
DH *dh = get_dh1024();
SSL_CTX_set_tmp_dh(m_pServerCTX, dh);
DH_free(dh);
SSL_CTX_set_cipher_list(m_pServerCTX, "ADH-DES-CBC3-SHA");
//"EXP-ADH-DES-CBC-SHA");
int sess_id_ctx=1;
SSL_CTX_set_session_id_context(m_pServerCTX,
(const unsigned char*)&sess_id_ctx, sizeof(sess_id_ctx));
m_bServerCTXCreated = true;
}
return m_pServerCTX;
}
void cSSL::rSeed(void)
{
RAND_screen();
::rSeed();
}
long cSSL::sendBIO(BIO *pBio, long lLength, BYTE *pData, long &lTimeOut)
{
long lOffset = 0;
long lWritten = 0;
while(lLength - lOffset> 0)
{
lWritten = BIO_write(pBio, &(pData[lOffset]), lLength - lOffset);
if(lWritten <=0)
{
if(BIO_should_retry(pBio) && lTimeOut-- > 0)
{
if(!SwitchToThread())
Sleep(1);
lWritten = 0;
continue;
}
ERR_print_errors_fp(stderr);
return -1;
}
lOffset += lWritten;
}
return lOffset;
}
long cSSL::sendBIOPrefixed(BIO *pBio, long lLength, BYTE *pData, long
&lTimeOut)
{
long lWritten = 0;
lWritten = sendBIO(pBio, sizeof(lLength), (BYTE *) &lLength, lTimeOut);
if(lWritten == sizeof(lLength))
lWritten += sendBIO(pBio, lLength, pData, lTimeOut);
return lWritten;
}
long cSSL::sendBIOSuffixed(BIO *pBio, long lLength, BYTE *pData, char
cSuffix, long &lTimeOut)
{
long lWritten = 0;
lWritten = sendBIO(pBio, lLength, pData, lTimeOut);
if(lWritten == lLength)
lWritten += sendBIO(pBio, sizeof(cSuffix), (BYTE *) &cSuffix,
lTimeOut);
return lWritten;
}
long cSSL::readBIO(BIO *pBio, long lLength, BYTE **ppData, long &lTimeOut)
{
BYTE buf[4096];
long lRead = 0;
cMemoryBlob objMemBlob;
*ppData = NULL;
if(lLength <= 0 || lLength > 2000000000)
lLength = 2000000000;
do
{
lRead=BIO_read(pBio, buf, __min(sizeof(buf), lLength));
if(lRead == 0)
break;
if(lRead < 0)
{
if(BIO_should_retry(pBio) && lTimeOut-- > 0)
{
if(!SwitchToThread())
Sleep(1);
lRead = 1;
continue;
}
ERR_print_errors_fp(stderr);
return -1;
}
objMemBlob.Append(lRead, buf);
lLength -= lRead;
}
while(lRead && lLength);
lRead = objMemBlob.GetBufSize();
if(lRead > 0)
{
objMemBlob.Reset();
*ppData = new BYTE[lRead];
objMemBlob.Read(lRead, *ppData);
}
return lRead;
}
long cSSL::readBIOPrefixed(BIO *pBio, BYTE **ppData, long &lTimeOut)
{
long *plLength = NULL;
long lLength;
long lOut;
if((lOut = readBIO(pBio, sizeof(long), (BYTE **) &plLength, lTimeOut)) >
0)
{
lLength = *plLength;
delete plLength;
if(lLength > 0)
if((lOut = readBIO(pBio, lLength, ppData, lTimeOut)) < 0)
return lLength;
}
return lOut;
}
long cSSL::readBIOSuffixed(BIO *pBio, BYTE **ppData, char cSuffix, long
&lTimeOut)
{
long lRead = 0;
long lOut;
BYTE *pData = NULL;
cMemoryBlob objMemBlob;
do
{
if(pData)
delete pData;
if((lOut = readBIO(pBio, sizeof(char), &pData, lTimeOut)) <= 0)
return lOut;
objMemBlob.Append(sizeof(char), pData);
lRead++;
}
while(*pData != cSuffix && lRead < 2000000000);
lRead = objMemBlob.GetBufSize() - 1;
if(lRead > 0)
{
objMemBlob.Reset();
*ppData = new BYTE[lRead];
objMemBlob.Read(lRead, *ppData);
}
return lRead;
}
void cSSL::ssl_lock(int mode, int n, const char *file, int line)
{
if(mode & CRYPTO_LOCK)
{
WaitForSingleObject(m_pMutex[n-1], INFINITE);
}
else
{
ReleaseMutex(m_pMutex[n-1]);
}
}
Simple Server program:
int main(void)
{
BIO *pBio = BIO_new_accept("*:1111");
BIO_set_nbio(pBio, 1);
BIO *pSSLBio = BIO_new_ssl(g_objSSL.ServerCTX(), 0);
BIO_set_accept_bios(pBio, pSSLBio);
{
char cOutput[] = "I hear you.";
int iLen = strlen(cOutput);
char buf[4096];
int iRead=1;
long lTimeOut = 1000000;
char *pData=NULL;
if((iRead = g_objSSL.readBIOPrefixed(pBio, (BYTE **) &pData,
lTimeOut)) > 0)
{
strncpy(buf, pData, iRead);
buf[iRead]=0;
printf ("Got %d chars:'%s'\n", iRead, buf);
delete pData;
if(g_objSSL.sendBIOPrefixed(pBio, iLen, (BYTE *) cOutput,
lTimeOut) <= 0)
puts("Error in encrypted Write!");
}
else
puts("Error in encrypted Read!");
}
BIO_ssl_shutdown(pBio);
BIO_free_all(pBio);
return 0;
}
Simple Client program:
int main () {
BIO *pBio = BIO_new_connect("localhost:1111");
BIO_set_nbio(pBio, 1);
BIO *pSSLBio = BIO_new_ssl_connect(g_objSSL.ClientCTX());
BIO_push(pSSLBio, pBio);
{
char cOutput[] = "Hello World!";
int iLen = strlen(cOutput);
char buf[4096];
int iRead=1;
long lTimeOut = 10000;
char *pData=NULL;
if(g_objSSL.sendBIOPrefixed(pBio, iLen, (BYTE *) cOutput, lTimeOut)
> 0)
{
if((iRead = g_objSSL.readBIOPrefixed(pBio, (BYTE **) &pData,
lTimeOut)) > 0)
{
strncpy(buf, pData, iRead);
buf[iRead]=0;
printf ("Got %d chars:'%s'\n", iRead, buf);
}
else
puts("Error in encrypted Read!");
delete pData;
}
else
puts("Error in encrypted Write!");
}
BIO_ssl_shutdown(pSSLBio);
BIO_free_all(pSSLBio);
return 0;
}
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]