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]

Reply via email to