Greetings,

I have a multi-threaded openssl server-based daemon whose function is to
service requests from any number of clients.  The application follows
the conventions for threaded openssl programming, such as registering
the two required callbacks. The openssl version being used is 0.9.7a on
both the Linux server and Win32 client. 

Unfortunately, the following sequence of events is giving me
difficulties:
- Connect from client A
- Connect from client B
- Disconnect from client B
- Connect from client B
- Disconnect from client A
-> this results in an SSL_ERROR_SYSCALL error in client B's thread upon
its next SSL_read() call, with a non-zero return value from SSL_read().
The client application, not knowing that its connection was terminated,
must be restarted to sync up using a new thread of the daemon.

The following, hopefully relevant, code snippets form the basis of the
daemon's SSL usage.  For brevity, both the thread id and locking
callbacks follow the format in openssl/crypto/threads/mttest.c.  I've
tried several variations on both threading and openssl, with the same or
worse results.

Accept thread:
        tci = malloc(sizeof(comm_info));
        memset(tci, 0, sizeof(comm_info));
        lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * 
                sizeof(pthread_mutex_t));
        for (i=0; i<CRYPTO_num_locks(); i++)
                pthread_mutex_init(&(lock_cs[i]),NULL);
        CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
        CRYPTO_set_locking_callback((void
(*)())pthreads_locking_callback);

        while(1)
        {
                ...
                tci->sd = accept(sd, (struct sockaddr *)(&(tci->si)), 
                        &address_len);
                ...
                pthread_create(&th, &thread_attr, comm_main, (void *)
tci);
                ...
                tci = malloc(sizeof(comm_info));        // set up for
next accept...
                memset(tci, 0, sizeof(comm_info));
        }
        CRYPTO_set_locking_callback(NULL);
        for (i=0; i<CRYPTO_num_locks(); i++)
                pthread_mutex_destroy(&(lock_cs[i]));
        OPENSSL_free(lock_cs);

Client communications thread (spawned by pthread_create() above):
        comm_main (void *argv)
        {
                comm_info *tci = (comm_info *)argv;
                // negotiate TLS, authenticate, etc...
                for (;;)
                {
                        retval = my_read(tci, buf, count);
                        if (retval > 0)
                        {
                                // ...process request in buf, then
respond to client
                                my_write(tci, outbuf, count);
                        }
                        else if (retval == 0)
                                my_shutdown(tci);
                        else
                                my_error(tci);
                }
        }

        int my_read (comm_info *tci, char *buf, int *count)
        {
                while (1)
                {
                        retval = SSL_read(tci->ssl, buf, count);
                        switch (SSL_get_error(tci->ssl, retval))
                        {
                        case SSL_ERROR_NONE:
                                return retval;
                        case SSL_ERROR_WANT_WRITE:
                        case SSL_ERROR_WANT_READ:
                        case SSL_ERROR_WANT_X509_LOOKUP:
                                continue;
                        case SSL_ERROR_SYSCALL:
                                if (retval == 0)
                                        return 0; // EOF without
close_notify
                                return -1;
                        case SSL_ERROR_ZERO_RETURN:
                                return 0; // SSL connection has been
closed
                        case SSL_ERROR_SSL:
                                return -1;
                        default:
                                return -1;  // Unknown SSL error
                        }
                }
        }

        void my_shutdown(comm_info *tci)
        {
                if (tci->ssl)
                {
                        ret = SSL_shutdown(tci->ssl);
                        if (ret == 0) // send TCP FIN to trigger
close_notify
                                ret = SSL_shutdown(tci->ssl);
                        if (ret == 1)
                                SSL_free(tci->ssl);
                }
                if (tci)
                        free((void *) tci);

                pthread_exit((void *)0);
        }

If anyone has had experience in this area and has suggestions, please
respond.  

Thanks in advance,
Stan
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to