Hi Viktor, > Initially, does your client build an SSL connection over an already > (TCP) established connection passed to it as a file descriptor?
yes. > Initially, does your server accept an SSL connection over an already > (TCP) established connection passed to it as a file descriptor? yes. > Do both parties call SSL_shutdown() at least once, and a second time if > the initial return value is zero? yes. > Do you use an external session cache (store serialized SSL_SESSION > objects) in a store accessible to multiple processes via IPC or an > appropriate shared resource with robust locking? If so, the re-connect > will be efficient, if you pre-load the saved session into the client > SSL state. No, for various reasons shared memory is not an option for this application. The socket ID is passed from the listener to the worker process on the server via a pipe. Here's some over-simplified snippets of the relevant parts of the code (assume undeclared/uninitialized variables have been defined and setup correctly):- CLIENT: /* connect socket */ if (-1 == connect( iSock, (struct sockaddr *)&SA, sizeof(SA) ) exit_error("couldn't connect etc"); /* test message to/from the server, no encryption */ send( iSock, szSendBuf1, 127, 0 ); recv( iSock, szRecvBuf1, 127, 0); if (strncmp(szSendBuf1, szRecvBuf1, 127)) exit_error("problem communicating with server"); /* setup SSL session */ if (!(pBio = BIO_new_socket( iSock, BIO_NOCLOSE ))) exit_error("failed to create BIO"); if (!(pSSL = SSL_new( pCTX ))) exit_error("failed to create SSL"); SSL_set_bio( pSSL, pBIO, pBIO ); if (SSL_connect( pSSL ) <= 0) exit_error("SSL_connect failed"); /* send test message with SSL encryption */ if (SSL_write( pSSL, szSendBuf2, strlen(szSendBuf2) ) <= 0) exit_error("SSL_write 1 failed"); if (SSL_read( pSSL, szRecvBuf2, sizeof(sRecvBuf2) ) <= 0) exit_error("SSL_read 1 failed"); if (strncmp(szSendBuf2, szRecvBuf2, strlen(szSendBuf2)) exit_error("SSL write/read test failed"); /* close down connection */ if (!SSL_shutdown( pSSL )) SSL_shutdown( pSSL ); SSL_free( pSSL ); /* wait for server to tell us its ok to start ssl again */ recv( iSock, szRecvBuf3, 127, 0 ); if (strncmp( szRecvBuf3, RESTART_SSL_MESSAGE, 127 )) exit_error("Unexpected message from server"); /* restart SSL */ if (!(pBio = BIO_new_socket( iSock, BIO_NOCLOSE ))) exit_error("failed to create BIO"); if (!(pSSL = SSL_new( pCTX ))) exit_error("failed to create SSL"); SSL_set_bio( pSSL, pBIO, pBIO ); if (SSL_connect( pSSL ) <= 0) exit_error("SSL_connect failed"); /* send test message with SSL encryption */ if (SSL_write( pSSL, szSendBuf2, strlen(szSendBuf2) ) <= 0) exit_error("SSL_write 1 failed"); if (SSL_read( pSSL, szRecvBuf2, sizeof(sRecvBuf2) ) <= 0) /* THIS READ IS FAILING */ exit_error("SSL_read 1 failed"); if (strncmp(szSendBuf2, szRecvBuf2, strlen(szSendBuf2)) exit_error("SSL write/read test failed"); -- end snippet. SERVER - LISTENER SNIPPET if (-1 == listen( iListenSock, 5 )) exit_error("listen failed"); iSock = accept( iListenSock, 0, 0 ); /* wait for unencrypted test message from client */ recv( iSock, szBuf, 127, 0 ); send( iSock, szBuf, strlen(szBuf), 0 ); if (!(pSSL = SSL_new( pCTX ))) exit_error("failed to create SSL"); SSL_set_bio( pSSL, pBIO, pBIO ); if (SSL_accept( pSSL ) <= 0) exit_error("SSL_connect failed"); /* wait for test message from client */ if (SSL_read( pSSL, szBuf, sizeof(szBuf) ) <= 0) exit_error("SSL_read failed"); if (SSL_write( pSSL, szBuf, strlen(szBuf) ) <= 0) exit_error("SSL_write failed"); /* shutdown SSL */ if (!(SSL_shutdown( pSSL )) SSL_shutdown( pSSL ); SSL_free( pSSL ); /* create new worker process (not shown here) */ /* hand off socket ID to worker (not shown) */ -- end snippet SERVER - WORKER SNIPPET /* send message in the clear telling client to restart SSL */ send( iSock, RESTART_SSL_MESSAGE, strlen(RESTART_SSL_MESSAGE), 0 ); /* start SSL */ if (!(pSSL = SSL_new( pCTX ))) exit_error("failed to create SSL"); SSL_set_bio( pSSL, pBIO, pBIO ); if (SSL_accept( pSSL ) <= 0) exit_error("SSL_connect failed"); /* wait for test message from client */ if (SSL_read( pSSL, szBuf, sizeof(szBuf) ) <= 0) exit_error("SSL_read failed"); if (SSL_write( pSSL, szBuf, strlen(szBuf) ) <= 0) exit_error("SSL_write failed"); -- end snippet I've tried it with a single process on the server end (ie eliminating the socket handoff to another process, just starting, stopping, re-starting SSL on the socket). The re-started SSL appears to work - the SSL_connect and SSL_accept both succeed, the server receives the string sent to it by the client, but when it sends it back the client just doesn't receive it - its SSL_read blocks indefinitely until the server closes the connection. I can send additional SSL_writes from the server - they all report success, but the client will hang on that first SSL_read after restarting SSL. It really feels like I'm missing something incredibly simple, but for the life of me I can't see what it is. Unless, of course, what I'm trying to do isn't supported by openssl. cheers Andrew