TCPSocketAsyncSSL.hGo to the documentation of this file.00001 /* 00002 * Copyright (c) 2000-2003 Barak Weichselbaum <barak@komodia.com> 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 00015 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00016 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00017 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 00018 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00019 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00020 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00021 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00022 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00023 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00024 * SUCH DAMAGE. 00025 * 00026 * Contact info: 00027 * ------------- 00028 * 00029 * Site: http://www.komodia.com 00030 * Main contact: barak@komodia.com 00031 * For custom projects, 00032 * consulting, or other 00033 * paid services: sales@komodia.com 00034 */ 00035 00036 #if !defined(AFX_TCPSOCKETASYNCSSL_H__551A1459_9C4D_44CD_B8B3_C062C9661384__INCLUDED_) 00037 #define AFX_TCPSOCKETASYNCSSL_H__551A1459_9C4D_44CD_B8B3_C062C9661384__INCLUDED_ 00038 00039 #if _MSC_VER > 1000 00040 #pragma once 00041 #endif // _MSC_VER > 1000 00042 00043 #include <deque> 00044 00045 #ifdef _SSLInheritance 00046 #include "TCPSocketAsyncMsg.h" 00047 #else 00048 #include "TCPSocketAsync.h" 00049 #endif 00050 00051 KOMODIA_NAMESPACE_START 00052 00053 class CGenericCriticalSection; 00054 00055 struct SSLData; 00056 00057 #ifdef _SSLInheritance 00058 typedef CTCPSocketAsyncMsg SSLBaseClass; 00059 #else 00060 typedef CTCPSocketAsync SSLBaseClass; 00061 #endif 00062 00063 class CTCPSocketAsyncSSL : public SSLBaseClass 00064 { 00065 public: 00066 //Load a certificate store (must be a PEM file) 00067 //Visit http://curl.haxx.se/docs/caextract.html to get most up to date file 00068 //Make sure to first call Create() 00069 bool LoadCertificateStore(const std::string& rPEMPath); 00070 00071 //Load certificates for a server socket (only if you want to create https server, and call "listen") 00072 //No need to set it for client that uses "connect" method 00073 //rPublicKey - .PEM file of the public key 00074 //rPrivateKey - .PEM file of the private key 00075 //Make sure to first call Create() 00076 //To learn how to get these files you can visit: http://panoptic.com/wiki/aolserver/How_to_generate_self-signed_SSL_certificates 00077 bool LoadCertificatesForServer(const std::string& rPublicKey, 00078 const std::string& rPrivateKey); 00079 00080 //Is ready for send, while session not yet established 00081 //Can we try to send 00082 bool IsReadyForSend()const; 00083 00084 //Did we finish the handshake 00085 bool IsHandshakeComplete()const; 00086 00087 //Set socket to not deque 00088 void DontQueue(); 00089 00090 //Create the socket 00091 //Must be called before any SSL operations are made 00092 virtual BOOL Create(); 00093 00094 //Accept a connection, supply an already made socket 00095 virtual BOOL Accept(CTCPSocket* pNewSocket); 00096 00097 //Connect with default source port as zero 00098 //bDisableAsync - Connect blockingly to destination 00099 // (user event will not be called) 00100 //bForceErrorEvent - Will call OnSocketConnect event if an 00101 // immediate error occured (only if bDisableAsync==FALSE) 00102 //Connect will only spawn the OnSocketConnect event after the socket has been connected 00103 //This doesn't work with the flag bDisableAsync 00104 virtual BOOL Connect(IP aDestinationAddress, 00105 unsigned short usDestinationPort, 00106 BOOL bDisableAsync=FALSE, 00107 BOOL bForceErrorEvent=FALSE); 00108 virtual BOOL Connect(const std::string& rDestinationAddress, 00109 unsigned short usDestinationPort, 00110 BOOL bDisableAsync=FALSE, 00111 BOOL bForceErrorEvent=FALSE); 00112 00113 //Our async connection 00114 virtual BOOL Connect(unsigned short usSourcePort, 00115 IP aDestinationAddress, 00116 unsigned short usDestinationPort, 00117 BOOL bDisableAsync=FALSE, 00118 BOOL bForceErrorEvent=FALSE); 00119 virtual BOOL Connect(unsigned short usSourcePort, 00120 const std::string& rDestinationAddress, 00121 unsigned short usDestinationPort, 00122 BOOL bDisableAsync=FALSE, 00123 BOOL bForceErrorEvent=FALSE); 00124 00125 //Send data over the sockets 00126 //Send may fail because the system isn't ready to 00127 //send the data, check out the value of the send 00128 //SOCKET_ERROR - Failure 00129 //0 - Send couldn't finish because it would block 00130 // if there was a blocking buffer, it was queued 00131 // (check out AllowBlockedBuffer in CAsyncSocket) 00132 //-2 - Still in SSL operations, data is buffered and will be sent as soon as possible 00133 //Value - Bytes sent, actual size may differe because of SSL encryption 00134 //This method will encrypt the data 00135 virtual int Send(const char* pBuffer, 00136 unsigned long ulBufferLength); 00137 00138 //Recieve data from remote socket, can be used with all 00139 //sub sockets (protocols) 00140 //Return value: 00141 //Positive - The number of bytes received. 00142 //Zero - No data to receive. 00143 //-2 - Still in SSL operations, no data available yet 00144 //Negative - Error 00145 //This method will decrypt the data 00146 virtual int Receive(char* pBuffer, 00147 unsigned long ulBufferLength); 00148 00149 //Get data from remote socket with out deleting data from buffer 00150 //Return value: 00151 //Positive - The number of bytes received. 00152 //Zero - No data to receive. 00153 //Negative - Error 00154 virtual int Peek(char* pBuffer, 00155 unsigned long ulBufferLength); 00156 00157 //Initialize the SSL engine, must be called before using any SSL enabled classes 00158 static void InitializeSSL(); 00159 00160 //Uninitialize the SSL engine, must be called before the application exits 00161 static void UninitializeSSL(); 00162 00163 //Disable SSL, incase wasn't called in CTor 00164 //Must be called before Create 00165 void DisableSSL(); 00166 00167 //Ctor and Dtor 00168 //bDisableSSL - If true, socket will act as a normal socket 00169 CTCPSocketAsyncSSL(bool bDisableSSL=false); 00170 virtual ~CTCPSocketAsyncSSL(); 00171 protected: 00172 //SSL Possible events 00173 typedef enum _SSLEvents 00174 { 00175 seBadCertificate=0, //Handshake is complete, user needs to decide if he wants this session or not 00176 seHandshakeFinished 00177 } SSLEvents; 00178 protected: 00179 //Method to receive SSL errors 00180 //Return value: True - Terminate connection, false - keep alive 00181 virtual bool OnSSLError(const std::string& rMethod, 00182 const std::string& rMessage, 00183 const std::string& rSSLError)const; 00184 00185 //Method to receive completion of handshake 00186 //If handshake is finished it means that the hashes are OK 00187 //Certificate can be invalid, but it's only checked if the method LoadCertificateStore was called 00188 virtual void OnSSLEvent(SSLEvents)const; 00189 00190 //Event handler for socket connections 00191 virtual BOOL SocketConnected(int iErrorCode, 00192 BOOL bNoEvent); 00193 00194 //Event handler for socket receive 00195 virtual BOOL SocketReceive(int iErrorCode, 00196 BOOL bNoEvent); 00197 00198 //When we have data to write 00199 virtual BOOL SocketWrite(int iErrorCode); 00200 private: 00201 //Our data deque 00202 typedef std::deque<char> DataDeque; 00203 private: 00204 //Flush the data in the queue 00205 int FlushData(); 00206 00207 //Handle an SSL error 00208 //Will return true if need to ignore this error 00209 bool HandleSSLError(const std::string& rMethod, 00210 const std::string& rMessage, 00211 int iResult, 00212 bool& rKeepAlive, 00213 bool& rSSLWantRead)const; 00214 00215 //Get data from the deque 00216 int GetDataFromDeque(DataDeque& rDeque, 00217 char* pData, 00218 int iDataSize)const; 00219 00220 //Add data to deque 00221 void AddDataToDeque(DataDeque& rDeque, 00222 const char* pData, 00223 int iDataSize, 00224 bool bBack=false)const; 00225 00226 //Local send function 00227 int LocalSend(const char* pBuffer, 00228 unsigned long ulBufferLength, 00229 bool bDontDeque, 00230 bool bDontFlush); 00231 00232 //Local receive function 00233 int LocalReceive(char* pBuffer, 00234 unsigned long ulBufferLength, 00235 bool bFlush); 00236 00237 //Flush the SSL data we have so far 00238 int FlushSSLWrite(); 00239 00240 //Flush the pending non encryped data 00241 int FlushWrite(); 00242 00243 //Set father, for server sockets 00244 void SetFather(CTCPSocketAsyncSSL* pFather); 00245 00246 //Create the SSL data 00247 void CreateSSLData(); 00248 00249 //Send initial SSL data 00250 //Then SSL must initiate the start of handshake 00251 void StartSSLHandshake(); 00252 00253 //Our SSL data 00254 SSLData* m_pData; 00255 00256 //Our CS, for general purposes 00257 CGenericCriticalSection* m_pCS; 00258 00259 //Our CS, for reading and writing the read deque 00260 CGenericCriticalSection* m_pCSWrite; 00261 00262 //Pending data to write (plain text the SSL rejected) 00263 DataDeque m_aPendingDataWrite; 00264 00265 //Our data to write (SSL encrypted) 00266 DataDeque m_aDataToWrite; 00267 00268 //Our data to read (plain text that the SSL decrypted) 00269 DataDeque m_aDataToRead; 00270 00271 //Did we finish the session 00272 bool m_bSession; 00273 00274 //Do we need to verify the certificate? 00275 bool m_bVerify; 00276 00277 //Do we have server certificate? 00278 bool m_bServerCert; 00279 00280 //Did we had any send? 00281 //Needed to know if we can send SSL handshake 00282 //Incase user explicitly asks for this 00283 bool m_bSend; 00284 00285 //Our father, for server sockets 00286 //So we can use the SSL context var 00287 CTCPSocketAsyncSSL* m_pFather; 00288 00289 //Do we have SSL disabled 00290 bool m_bDisableSSL; 00291 00292 //Save event status 00293 bool m_bEvent; 00294 00295 //Did we had the event spawn? 00296 bool m_bEventSpawned; 00297 00298 //An option to not queue data, upper layer will try to resend again if something went wrong 00299 bool m_bDontQueue; 00300 00301 //Can send data? 00302 bool m_bCanSend; 00303 }; 00304 00305 KOMODIA_NAMESPACE_END 00306 00307 #endif // !defined(AFX_TCPSOCKETASYNCSSL_H__551A1459_9C4D_44CD_B8B3_C062C9661384__INCLUDED_) |