bool TLS_SOCKET_CLASS::isPendingDataInNetworkInputBuffer() // DESCRIPTION : Check for pending data. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { /*int nrOfBytes; if(sslM_ptr != NULL) nrOfBytes = SSL_pending(sslM_ptr); if(nrOfBytes > 0) return true; else return false;*/ DWORD available; int handle = SSL_get_rfd(sslM_ptr); ioctlsocket(handle, FIONREAD, &available); if(available > 0) return true; else return false; }
gint ssl_peek(SSL *ssl, gchar *buf, gint len) { gint err, ret; if (SSL_pending(ssl) == 0) { if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0) return -1; } ret = SSL_peek(ssl, buf, len); switch ((err = SSL_get_error(ssl, ret))) { case SSL_ERROR_NONE: return ret; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: errno = EAGAIN; return -1; case SSL_ERROR_ZERO_RETURN: return 0; default: g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret); if (ret == 0) return 0; return -1; } }
/* Return the incoming_fd for a given stream */ int stream_get_incoming_fd(PTSTREAM *pts) { if (!pts->ssl) return pts->incoming_fd; else #ifdef USE_SSL return SSL_get_rfd(pts->ssl); #else return pts->incoming_fd; #endif /* USE_SSL */ }
static int openssl_ssl_get(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); for (i = 2; i <= top; i++) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { lua_pushinteger(L, SSL_get_fd(s)); } else if (strcmp(what, "rfd") == 0) { lua_pushinteger(L, SSL_get_rfd(s)); } else if (strcmp(what, "wfd") == 0) { lua_pushinteger(L, SSL_get_wfd(s)); } else if (strcmp(what, "client_CA_list") == 0) { STACK_OF(X509_NAME)* sn = SSL_get_client_CA_list(s); PUSH_OBJECT(sn, "openssl.sk_x509_name"); } else if (strcmp(what, "read_ahead") == 0) { lua_pushboolean(L, SSL_get_read_ahead(s)); } else if (strcmp(what, "shared_ciphers") == 0) { char buf[LUAL_BUFFERSIZE] = {0}; lua_pushstring(L, SSL_get_shared_ciphers(s, buf, sizeof(buf))); } else if (strcmp(what, "cipher_list") == 0) { //TODO FIX lua_pushstring(L, SSL_get_cipher_list(s, 0)); } else if (strcmp(what, "verify_mode") == 0) { //FIX lua_pushinteger(L, SSL_get_verify_mode(s)); } else if (strcmp(what, "verify_depth") == 0) { lua_pushinteger(L, SSL_get_verify_depth(s)); } else if (strcmp(what, "state_string") == 0) { lua_pushstring(L, SSL_state_string(s)); } else if (strcmp(what, "state_string_long") == 0) { lua_pushstring(L, SSL_state_string_long(s)); } else if (strcmp(what, "rstate_string") == 0) { lua_pushstring(L, SSL_rstate_string(s)); } else if (strcmp(what, "rstate_string_long") == 0) { lua_pushstring(L, SSL_rstate_string_long(s)); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "iversion") == 0) { lua_pushinteger(L, SSL_version(s)); } else if (strcmp(what, "default_timeout") == 0) { lua_pushinteger(L, SSL_get_default_timeout(s)); } else if (strcmp(what, "certificate") == 0) { X509* cert = SSL_get_certificate(s); PUSH_OBJECT(cert, "openssl.x509"); } else if (strcmp(what, "verify_result") == 0) { long l = SSL_get_verify_result(s); lua_pushinteger(L, l); } else if (strcmp(what, "version") == 0) { lua_pushstring(L, SSL_get_version(s)); } else if (strcmp(what, "state") == 0) { lua_pushinteger(L, SSL_state(s)); } else if (strcmp(what, "hostname") == 0) { lua_pushstring(L, SSL_get_servername(s, TLSEXT_NAMETYPE_host_name)); } else luaL_argerror(L, i, "can't understant"); } return top - 1; }
bool TLS_SOCKET_CLASS::writeBinary(const BYTE *buffer_ptr, UINT length) // DESCRIPTION : Write given data to socket. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { int written_bytes = 0; int readFileDesc; int writeFileDesc; struct fd_set readFds; struct fd_set writeFds; bool waitOnWrite; int timeoutRemaining; // the amount of time left in the timeout period struct timeval tv = {1, 0}; // always timeout in 1 second if (terminatingM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating. Cannot write."); } // return - in process of termintating return false; } if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::write(%d bytes)", length); } if (!connectedM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Not connected to peer - can't write data"); } return false; } // get the file descriptors and set up the file descriptor sets for select() readFileDesc = SSL_get_rfd(sslM_ptr); if (readFileDesc == -1) { openSslError("getting read socket file descriptor"); return false; } writeFileDesc = SSL_get_wfd(sslM_ptr); if (writeFileDesc == -1) { openSslError("getting write socket file descriptor"); return false; } waitOnWrite = true; timeoutRemaining = socketTimeoutM; // write the buffer contents to socket while (written_bytes < (int) length) { int bytes; int sel; if (waitOnWrite) { FD_ZERO(&writeFds); FD_SET(writeFileDesc, &writeFds); // wait for something to write sel = select(writeFileDesc + 1, NULL, &writeFds, NULL, &tv); } else { FD_ZERO(&readFds); FD_SET(readFileDesc, &readFds); // wait for something to read sel = select(readFileDesc + 1, &readFds, NULL, NULL, &tv); } if (terminatingM) { return false; } waitOnWrite = true; if (sel == 1) { // data read to write (or possibly read - but use the same call) bytes = SSL_write(sslM_ptr, (char *)(buffer_ptr + written_bytes), (length - written_bytes)); if (bytes > 0) { // wrote some data written_bytes += bytes; timeoutRemaining = socketTimeoutM; // reset the timeout } else if (bytes == 0) { // socket closed if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Secure connection closed during socket write"); } return false; } else { // operation did not complete, see what happened int err = SSL_get_error(sslM_ptr, bytes); if (err == SSL_ERROR_WANT_READ) { // need to wait for data to be available for reading, and then retry the same operation waitOnWrite = false; timeoutRemaining = socketTimeoutM; // reset the timeout } if (err == SSL_ERROR_WANT_WRITE) { // need to wait for the write file descriptor to be able to write and then try again timeoutRemaining = socketTimeoutM; // reset the timeout } else { // an error occured if ((err == SSL_ERROR_SYSCALL) && (ERR_peek_error() == 0) && (bytes == -1)) { // an error in the system call occured openSslError("writing to secure socket"); if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_ERROR)) { loggerM_ptr->text(LOG_NONE, 1, " write() error code = %d", WSAGetLastError()); } } else { openSslError("reading from secure socket"); } return false; } } } else if (sel == 0) { // no data at the end of the timeout if (--timeoutRemaining > 0) { // still have time left on the timeout, go back and wait some more } else { // timeout expired if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Connection timed-out while waiting to send data"); } return false; } } else if (sel == SOCKET_ERROR) { // socket error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Error waiting to send data (error code %d)", WSAGetLastError()); } return false; } else { // unknown error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Unknown error while waiting to send data (select returned %d)", sel); } return false; } } return (written_bytes == (int) length) ? true : false; }
INT TLS_SOCKET_CLASS::readBinary(BYTE *buffer_ptr, UINT length) // DESCRIPTION : Read data from socket to given buffer. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : Blocks until all of the requested data is read or a timeout occurs. //<<=========================================================================== { int read_bytes = 0; // number of bytes read from the socket int readFileDesc; int writeFileDesc; struct fd_set readFds; struct fd_set writeFds; bool sslWaitOnRead; // indicates that the OpenSSL library is waiting for data to be sent on the socket bool sslWaitOnWrite; // indicates that the OpenSSL library is waiting to be able to write to the socket interface int timeoutRemaining; // the amount of time left in the timeout period struct timeval tv = {1, 0}; // always timeout in 1 second if (terminatingM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating. Cannot read."); } // return - in process of termintating return -1; } if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::read(%d bytes)", length); } if (!connectedM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Not connected to peer - can't read data"); } return -1; } // get the file descriptors and set up the file descriptor sets for select() readFileDesc = SSL_get_rfd(sslM_ptr); if (readFileDesc == -1) { openSslError("getting read socket file descriptor"); return -1; } writeFileDesc = SSL_get_wfd(sslM_ptr); if (writeFileDesc == -1) { openSslError("getting write socket file descriptor"); return -1; } sslWaitOnRead = false; sslWaitOnWrite = false; timeoutRemaining = socketTimeoutM; // fill the buffer from the socket while (read_bytes < (int) length) { int bytes; int sel; if (sslWaitOnWrite) { FD_ZERO(&writeFds); FD_SET(writeFileDesc, &writeFds); // wait for the socket to be able to accept a write operation sel = select(writeFileDesc + 1, NULL, &writeFds, NULL, &tv); } else if (sslWaitOnRead || // OpenSSL asked us to wait (SSL_pending(sslM_ptr) == 0)) // there is no data in the SSL buffer { FD_ZERO(&readFds); FD_SET(readFileDesc, &readFds); // wait for something on the socket sel = select(readFileDesc + 1, &readFds, NULL, NULL, &tv); } else { // don't wait, there is data to be read from the SSL buffer sel = 1; } if (terminatingM) { return -1; } sslWaitOnRead = false; sslWaitOnWrite = false; if (sel == 1) { // data ready to be read (or possibly write - but use the same call) bytes = SSL_read(sslM_ptr, (char *)(buffer_ptr + read_bytes), (length - read_bytes)); if (bytes > 0) { // read some data read_bytes += bytes; timeoutRemaining = socketTimeoutM; // reset the timeout } else if (bytes == 0) { // socket closed if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Secure connection closed during socket read"); } return -1; } else { // operation did not complete, see what happened int err = SSL_get_error(sslM_ptr, bytes); if (err == SSL_ERROR_WANT_READ) { // need to wait for data to be available for reading, and then retry the same operation sslWaitOnRead = true; timeoutRemaining = socketTimeoutM; // reset the timeout } if (err == SSL_ERROR_WANT_WRITE) { // need to wait for the write file descriptor to be able to write and then try again sslWaitOnWrite = true; timeoutRemaining = socketTimeoutM; // reset the timeout } else { // an error occured if ((err == SSL_ERROR_SYSCALL) && (ERR_peek_error() == 0) && (bytes == -1)) { // an error in the system call occured openSslError("reading from secure socket"); if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_ERROR)) { loggerM_ptr->text(LOG_NONE, 1, " read() error code = %d", WSAGetLastError()); } } else { openSslError("reading from secure socket"); } return -1; } } } else if (sel == 0) { // no data at the end of the timeout if (--timeoutRemaining > 0) { // still have time left on the timeout, go back and wait some more } else { // timeout expired if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Connection timed-out while waiting to receive data"); } return -1; } } else if (sel == SOCKET_ERROR) { // socket error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Error waiting to receive data (error code %d)", WSAGetLastError()); } return -1; } else { // unknown error if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Unknown error while waiting to receive data (select returned %d)", sel); } return -1; } } return read_bytes; }