Hi there,

The problem that I encountered was with a call to ERR_get_error_line_data(), and has not yet been solved.  I was not encountering any memory leaks with SSL_connect().  We are using OpenSSL V 0.9.6b currently, we plan to upgrade in the near future.

When creating an SSL*, I tend to do the following:

SSL*
SSLConnection::createSSLConnection(int socket)
{
    assert(_sslContext != 0);

    SSL* sslConnection = SSL_new(_sslContext);
    assert(sslConnection != 0);

    SSL_clear(sslConnection);

    SSL_set_fd(sslConnection, socket);

    return sslConnection;
}

I don't do anything special in the destruction, simply call SSL_shutdown().  I leave it to another part of the application to close the socket for me.

Hope it helps!

-Anthony
 

"Jack Y." wrote:

Hi,
    I am sorry to send you directly, hope it not bother.
    Openssl mail list seem does not work, I can not subscript one. I also send my mail to [EMAIL PROTECTED], but get no response.
    You seem had the same problem as me, pls give me hints, many thanks, if you do not solve the problem yet, please post this mail on mail list, many thanks.
    I ran into a tribble problem, my client application that use openssl 0.9.6h lose 4K memory every SSL_connect()...
    The product is under release, things become very clear, remove the leak, or throw openssl lib, do the total job, authentication, encryption by myself.
    In list, I saw many persons solve the problem by close socket before free ssl object. But it does not work in my program. So, if you are one of them, send a copy of your client program, MANY THANKS.
    Purify says I leak memory allocated in CRYPTO_malloc, I think it is no use.
    I tried
        CRYPTO_malloc_debug_init();
        CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
        CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
        for
        ...
        end for
        CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
        CRYPTO_mem_leaks_fp(stderr);
    the program crash at CRYPTO_mem_leaks_fp(..)!!!
    I saw a post long time ago says there do have memory leak in openssl, http://marc.theaimsgroup.com/?l=openssl-users&m=99973677617001&w=2, is it fixed now, if not, ...oh, hurt!
    My environment is: w2k professional, .9.6h

The code flow of the client is as follows

* SSL_CTX_new(...)
* SSL_CTX_use_certificate_ASN1(...)
* SSL_CTX_use_RSAPrivateKey_ASN1(...)
* X509_STORE_add_cert(....) // To add CA cert
* SSL_CTX_sess_set_cache_size(ctx, 0);
* SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_OFF);
* other init actions

* for ever
    * SSL_new(...)
    * create read & write BIOs
    * SSL_connect(...)
    *  .....
    * SSL_shutdown(...)
    * closesock(...)
    * SSL_free(...)
    * ERR_remove_state(0);
    * ERR_free_strings();
    * EVP_cleanup();
    * sleep
* endfor

I also tried:

* for ever
    * SSL_CTX_new(...)
    * SSL_CTX_use_certificate_ASN1(...)
    * SSL_CTX_use_RSAPrivateKey_ASN1(...)
    * X509_STORE_add_cert(....) // To add CA cert
    * other init actions

    * SSL_new(...)
    * create read & write BIOs
    * SSL_connect(...)
    *  .....
    * SSL_shutdown(...)
    * closesock(...)
    * SSL_free(...)
    * SSL_CTX_free(...)
    * ERR_remove_state(0);
    * ERR_free_strings();
    * EVP_cleanup();
    * sleep
* endfor

but I still lose 4K memory every loop...

My code is below for details.

// TestClntSSL.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "TestClntSSL.h"
#include "Winsock2.h"

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/rand.h>

#include <stdio.h>
#include <stdlib.h>

typedef struct CLIENT_PARA
{
    SSL_CTX * pctx;
    char * szFile;
    unsigned long ulAddr;
    int server_port;
} CLIENT_PARA;

static int port = 4433;
static char* server_ip = "192.168.xx.xx";

static char *ciphers = "DES-CBC3-SHA";
static int s_server_session_id_context = 1;
static char *passwd = "n1234";
static char *srvr_cert_file = "c:\\VCDebug\\nnn.crt";
static char *srvr_key_file = "c:\\VCDebug\\nnn.key";
static char *ca_cert_file = "c:\\VCDebug\\ca.crt";
static char *host = "CN=mmm";

static int password_cb(char *buf,int num,
        int rwflag,void *userdata);

SSL_CTX *initialize_ctx()
{
    SSL_METHOD *meth;
    SSL_CTX *ctx;
    int seed_int[1000];

    /* Global system initialization*/
    SSL_library_init();
    SSL_load_error_strings();

    /* Set up a SIGPIPE handler */
//    signal(SIGPIPE,sigpipe_handle);

    /* Create our context*/
    meth=SSLv3_client_method();
    ctx=SSL_CTX_new(meth);

    /* Load our keys and certificates*/
    if(!(SSL_CTX_use_certificate_file(ctx,
        srvr_cert_file, SSL_FILETYPE_PEM)))
    {
        char szTemp[100] = "Can't read certificate file";
        Log(szTemp);
        return NULL;
    }

    SSL_CTX_set_default_passwd_cb(ctx,
        password_cb);
    if(!(SSL_CTX_use_PrivateKey_file(ctx,
        srvr_key_file, SSL_FILETYPE_PEM)))
    {
        char szTemp[100] = "Can't read key file";
        Log(szTemp);
        return NULL;
    }

    /* Load the CAs we trust*/
    if(!(SSL_CTX_load_verify_locations(ctx,
        ca_cert_file,0)))
    {
        Log("Can't read CA list");
        return NULL;
    }

    // Set our cipher list
    if(ciphers)
    {
        SSL_CTX_set_cipher_list(ctx,ciphers);
    }

    SSL_CTX_set_session_id_context(ctx,
            (const unsigned char*)&s_server_session_id_context,
            sizeof s_server_session_id_context);

    SSL_CTX_sess_set_cache_size(ctx, 0);
    SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_OFF);

#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
    SSL_CTX_set_verify_depth(ctx,1);
#endif

    return ctx;
}

/* Check that the common name matches the
host name*/
void check_cert(SSL *ssl, char *host)
{
    X509 *peer;
    char peer_CN[256];

    if(SSL_get_verify_result(ssl)!=X509_V_OK)
    {
        char szTemp[100] = "Certificate doesn't verify!";
        Log(szTemp);
    }

    /*Check the cert chain. The chain length
    is automatically checked by OpenSSL when
    we set the verify depth in the ctx */

    /*Check the common name*/
    peer=SSL_get_peer_certificate(ssl);
    X509_NAME_get_text_by_NID
    (X509_get_subject_name(peer),
    NID_commonName, peer_CN, 256);
    if(strstr(peer_CN,host))
    {
        char szTemp[100] = "Common name doesn't match host name!";
        Log(szTemp);
    }
}

int SendSSLData(CLIENT_PARA * ppara)
{
    SSL *ssl = NULL;
    BIO *sbio = NULL;

    struct sockaddr_in sa;
    int sd;
    unsigned long addr;

    CString sTemp = _T("");
    int nTempLen = 0;
    CStdioFile f;
    int r = 0, nTotal = 0, i;
    BOOL bStill = TRUE;

    sd = socket (AF_INET, SOCK_STREAM, 0);
    if(sd == INVALID_SOCKET )
    {
        char szTemp[100] = "socket() failed: %d";
        Log(szTemp, WSAGetLastError());
        goto cleansock;
    }
    memset (&sa, '\0', sizeof(sa));
    addr = ppara->ulAddr;
    sa.sin_family      = AF_INET;
    sa.sin_addr.s_addr = addr;  /* Server IP */
    sa.sin_port        = htons     (port);          /* Server Port number */

    if(connect(sd, (struct sockaddr *)&sa, sizeof(sa))<0)
    {
        char szTemp[100] = "connect() failed: %d";
        Log(szTemp, WSAGetLastError());
        goto cleansock;
    }

    // Connect the SSL socket
    ssl=SSL_new(ppara->pctx);
    sbio=BIO_new_socket(sd,BIO_NOCLOSE);
    SSL_set_bio(ssl,sbio,sbio);
    if(SSL_connect(ssl)<=0)
    {
        char szTemp[100] = "SSL_connect() failed: %d";
        Log(szTemp, WSAGetLastError());
        goto cleansock;
    }
    check_cert(ssl,host);

    f.Open(szFile, CFile::modeRead | CFile::typeText);
    bStill = f.ReadString(sTemp);
    if (sTemp == _T(""))
        sTemp = _T(" ");
    nTempLen = sTemp.GetLength();

    while (1)
    {
        // Try to write
        r=SSL_write(ssl, sTemp, nTempLen);

        int rr = SSL_get_error(ssl,r);
        switch(rr){
            // We wrote something
            case SSL_ERROR_NONE:
                if (r != nTempLen)
                {
                    goto shutdown_actively;
                }
                nTotal+=r;
                break;
            // We would have blocked
            case SSL_ERROR_WANT_WRITE:
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_SSL:
            default:
                goto shutdown_actively;
        }
        bStill = f.ReadString(sTemp);
        if (bStill)
        {
            if (sTemp == _T(""))
            {
                sTemp = _T(" ");
                nTempLen = 1;
            }
        }
        else
        {
//                SSL_SESSION_free (SSL_get_session(ssl));
            goto shutdown_actively;
        }
    } // end of while (bStill)
shutdown_actively:
    r=SSL_shutdown(ssl);
    if(!r)
    {
        // If we called SSL_shutdown() first then
        // we always get return value of '0'. In
        // this case, try again, but first send a
        // TCP FIN to trigger the other side's
        // close_notify
        shutdown(sd, SD_SEND);
        r=SSL_shutdown(ssl);
    }
    switch(r)
    {
        case 1:
            break; // Success
        case 0:
        case -1:
        default:
            char szTemp[100] = "SSL_shutdown() passively in client failed";
            Log(szTemp);
    }

    if (ssl != NULL)
    {
        // ==============
        SSL_clear(ssl);
        SSL_free(ssl);
        ssl = NULL;
    }
    EVP_cleanup();
    ERR_remove_state(0);
    ERR_free_strings();
    OBJ_NAME_cleanup(-1);
cleansock:
    closesocket (sd); // i also tried to put this line before SSL_shutdown() and SSL_free.

    return nTotal;
}//End of create_client;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    //³õʼ»¯WinSock;
    static struct WSAData wsa_state;
    if(WSAStartup(0x0101, &wsa_state)!=0)
    {
        printf("Failed to load Winsock!");
        return 1;
    }

    // Build our SSL context
    SSL_CTX *ctx = NULL;
    ctx = initialize_ctx();
    if (ctx == NULL)
        return 0;

    unsigned long addr = inet_addr(server_ip);
    printf("Sending Data...\n");

    struct CLIENT_PARA client_para[2];
    for (int i = 0; i < 2; i++)
    {
        client_para[i].pctx = ctx;
        client_para[i].szFile = szFile;
        client_para[i].ulAddr = addr;
        client_para[i].server_port = atoi(argv[i+1]);
    }

    for (i = 0; i < 10; i++)
    {
        printf("%d Bytes sended.\n", SendSSLData( &client_para[0] ));
        Sleep (1000);
        printf("%d Bytes sended.\n", SendSSLData( &client_para[1] ));
        Sleep (1000);
    }
    Sleep (1000);
    printf("%d Bytes sended.\n", SendSSLData( &client_para[1] ));
    printf("Hello World!\n");

    SSL_CTX_free(ctx);
    WSACleanup( );

    return 0;
}

static int password_cb(char *buf, int num,
    int rwflag,void *userdata)
{
    if(num < (int)strlen(passwd)+1)
        return(0);

    strcpy(buf,passwd);
    return(strlen(passwd));
}
 


Do You Yahoo!?
"IBMÓŻݼÛÌØȨ£¬Ë­ÏÈÀ´Ë­Ïȵã¡"

Reply via email to