[ https://issues.apache.org/jira/browse/AXISCPP-899?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12671290#action_12671290 ]
Ryan McCullough commented on AXISCPP-899: ----------------------------------------- I think I have a solution for this incident. I had to change 4 files, all under axis/transport/axis3/: HTTPTransport.cpp: cut all of the #define ASCII_* stuff IChannel.hpp: Paste all of the #define ASCII_* stuff from HTTPTransport.cpp. I needed to do this so that they were available to the SSL channel. HTTPSSLChannel\HTTPSSLChannel.hpp: add the following to the protected section: bool proxyConnect(); int writeProxyConnect(); int readProxyConnect(char* pRxBuffer); HTTPSSLChannel\HTTPSSLChannel.cpp: add the following: /** * HTTPSSLChannel::writeProxyConnect() * * This method writes the CONNECT method unencrypted to the open channel. * * 02/04/2009 rmccullough * * Based off the "CONNECT" method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.9), * part of "Hypertext Transfer Protocol -- HTTP/1.1" (http://www.w3.org/Protocols/rfc2616/rfc2616.html) * * "Tunneling SSL Through a WWW Proxy" * by Ari Luotonen, December 14, 1995 * http://muffin.doit.org/docs/rfc/tunneling_ssl.html * * "Tunneling TCP based protocols through Web proxy servers" * by Ari Luotonen, August 1998 * http://www.web-cache.com/Writings/Internet-Drafts/draft-luotonen-web-proxy-tunneling-01.txt * * SSL tunneling patch for CERN httpd * http://www.w3.org/Daemon/User/Patch/SSL.patch * * * @param buf Character pointer pointing to the array of character containing the message to be transmitted. * @param numBytes The number of bytes in the message to be transmitted. * @return The number of bytes sent. */ bool HTTPSSLChannel:: proxyConnect() { // return value, default to failure bool bSuccess = (bool)AXIS_FAIL; // request a CONNECT to the server int nBytesSent = writeProxyConnect(); // variables needed for recieving data int iHTTPStatus = 100; int iBytesReceived = 0; int iBytesLeft = 0; char* pRxBuffer = new char [BUF_SIZE]; string strBytesReceived; string strResponseHTTPHeaders; // loop while the response is valid do { while (strBytesReceived.find(ASCII_S_HTTP) == std::string::npos || strBytesReceived.find(ASCII_S_CRLFCRLF) == std::string::npos) { iBytesReceived = readProxyConnect(pRxBuffer); if (iBytesReceived > 0) { strBytesReceived += pRxBuffer; iBytesLeft = strBytesReceived.length(); } else { throw HTTPTransportException(SERVER_TRANSPORT_INPUT_STREAMING_ERROR, "Socket connection has been closed."); } } // At this point the HTTP header has been found. Seperate the response headers // from the payload (i.e. SOAP message). string::size_type iHTTPStart = strBytesReceived.find(ASCII_S_HTTP); string::size_type iHTTPEnd = strBytesReceived.find(ASCII_S_CRLFCRLF, iHTTPStart); strResponseHTTPHeaders = strBytesReceived.substr(iHTTPStart, iHTTPEnd + 4 - iHTTPStart); // Process the HTTP header PLATFORM_ASCTOSTR(strBytesReceived.c_str()); string strHTTPStatus = strBytesReceived.substr(strlen("HTTP/1.x "), 3); iHTTPStatus = atoi(strHTTPStatus.c_str()); } while(iHTTPStatus == 100); // delete the Rx buffer delete[] pRxBuffer; // Now have a valid HTTP header that is not 100. Throw an exception if some unexpected error. // Note that error 500 are for for SOAP faults. if (iHTTPStatus != 500 && (iHTTPStatus < 200 || iHTTPStatus >= 300)) { throw HTTPTransportException(SERVER_TRANSPORT_HTTP_EXCEPTION, "Server sent HTTP error: \n"); } if (iHTTPStatus == 200) { bSuccess = (bool)AXIS_SUCCESS; } return bSuccess; } int HTTPSSLChannel:: writeProxyConnect() { // send buffer char buf[1024]; // server port, not proxy port unsigned int uiPort = m_URL.getPort(); // the header should look liks this: // CONNECT home1.netscape.com:443 HTTP/1.0 sprintf(buf, "CONNECT %s:%u HTTP/1.1\r\n\r\n", m_URL.getHostName(), uiPort); // get the number of bytes, needed for send() int numBytes = strlen(buf); // // SEND THE CONNECT // if (INVALID_SOCKET == m_Sock) { m_LastError = "No valid socket to perform write operation."; throw HTTPTransportException( SERVER_TRANSPORT_INVALID_SOCKET, m_LastError.c_str()); } int nByteSent = 0; #ifdef __OS400__ if ((nByteSent = send( m_Sock, (char *)buf, numBytes, 0)) == SOCKET_ERROR) #else if ((nByteSent = send( m_Sock, buf, numBytes, 0)) == SOCKET_ERROR) #endif { // This must be done first before closing channel in order to get actual error. m_LastError = "Error sending data."; // Close the channel and throw an exception. CloseChannel(); throw HTTPTransportException( SERVER_TRANSPORT_OUTPUT_STREAMING_ERROR, m_LastError.c_str()); } return nByteSent; } int HTTPSSLChannel:: readProxyConnect(char* buf) { // // RECEIVE THE CONNECT // if (INVALID_SOCKET == m_Sock) { m_LastError = "Unable to perform read operation."; throw HTTPTransportException( SERVER_TRANSPORT_INVALID_SOCKET, m_LastError.c_str()); } int nByteRecv = 0; int iBufSize = BUF_SIZE - 10; // If timeout set then wait for maximum amount of time for data if (m_lTimeoutSeconds) { int iTimeoutStatus = applyTimeout(); // Handle timeout outcome if (iTimeoutStatus < 0) { throw HTTPTransportException( SERVER_TRANSPORT_TIMEOUT_EXCEPTION, m_LastError.c_str()); } if (iTimeoutStatus == 0) { m_LastError = "Read operation timed-out while waiting for data."; throw HTTPTransportException( SERVER_TRANSPORT_TIMEOUT_EXPIRED, m_LastError.c_str() ); } } // Either timeout was not set or data available before timeout; so read nByteRecv = recv( m_Sock, buf, iBufSize, 0); if (nByteRecv == SOCKET_ERROR) { // This must be done first before closing channel in order to get actual error. m_LastError = "Error receiving data."; // Close the channel and throw an exception. CloseChannel(); if(!bNoExceptionOnForceClose) { throw HTTPTransportException( SERVER_TRANSPORT_INPUT_STREAMING_ERROR, m_LastError.c_str()); } } else if ( 0 == nByteRecv ) { // read-side of socket is closed. } else if (nByteRecv) { buf[nByteRecv] = '\0'; } return nByteRecv; } My source files are somewhat out of date with what is in subversion, but I attached them. > tunnel https connections over http proxies > ------------------------------------------ > > Key: AXISCPP-899 > URL: https://issues.apache.org/jira/browse/AXISCPP-899 > Project: Axis-C++ > Issue Type: New Feature > Components: Transport (Client) > Affects Versions: 1.6 Beta > Reporter: Franz Fehringer > > The necessary steps for this scheme would be (to my best knowledge) > 1) connect normally to proxy > 2) send http CONNECT request (with remote address as argument) > 3) now we have a connection to the remote host (descriptor from step 1) > 4) do SSL handshake > 5) ready for normal SSL/HTTPS communication -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.