Panda3D
|
00001 #ifndef __SOCKET_TCP_SSL_H__ 00002 #define __SOCKET_TCP_SSL_H__ 00003 00004 #include "pandabase.h" 00005 #include "socket_ip.h" 00006 #include "numeric_types.h" 00007 00008 #ifdef HAVE_OPENSSL 00009 00010 #include <openssl/rsa.h> /* SSLeay stuff */ 00011 #include <openssl/crypto.h> 00012 #include <openssl/x509.h> 00013 #include <openssl/pem.h> 00014 #include <openssl/ssl.h> 00015 #include <openssl/err.h> 00016 00017 ///////////////////////////////////////////////////////////////////// 00018 // Class : Socket_TCP_SSL 00019 // 00020 // Description : 00021 // 00022 ///////////////////////////////////////////////////////////////////// 00023 00024 extern EXPCL_PANDA_NATIVENET SSL_CTX *global_ssl_ctx; 00025 00026 00027 struct SSlStartup 00028 { 00029 SSlStartup() 00030 { 00031 const SSL_METHOD *meth; 00032 SSLeay_add_ssl_algorithms(); 00033 //meth = SSLv23_server_method(); 00034 meth = SSLv23_method(); 00035 SSL_load_error_strings(); 00036 // I hate this cast, but older versions of OpenSSL need it. 00037 global_ssl_ctx = SSL_CTX_new ((SSL_METHOD *) meth); 00038 } 00039 00040 ~SSlStartup() 00041 { 00042 SSL_CTX_free (global_ssl_ctx); 00043 global_ssl_ctx = NULL; 00044 } 00045 00046 00047 bool isactive() { return global_ssl_ctx != NULL; }; 00048 }; 00049 00050 00051 class EXPCL_PANDA_NATIVENET Socket_TCP_SSL : public Socket_IP 00052 { 00053 public: 00054 00055 inline Socket_TCP_SSL(SOCKET); 00056 inline Socket_TCP_SSL() : _ssl(NULL) {} 00057 00058 virtual inline ~Socket_TCP_SSL() 00059 { 00060 CleanSslUp(); 00061 } 00062 00063 inline int SetNoDelay(); 00064 inline int SetLinger(int interval_seconds = 0); 00065 inline int DontLinger(); 00066 00067 inline int SetSendBufferSize(int insize); 00068 inline bool ActiveOpen(const Socket_Address & theaddress); 00069 inline int SendData(const char * data, int size); 00070 inline int RecvData(char * data, int size); 00071 inline bool ErrorIs_WouldBlocking(int err); 00072 00073 inline SSL * get_ssl() { return _ssl; }; 00074 00075 inline void DetailErrorFormat(void); 00076 private: 00077 SSL* _ssl; 00078 00079 void CleanSslUp() 00080 { 00081 if(_ssl != NULL) 00082 { 00083 SSL_shutdown(_ssl); 00084 SSL_free(_ssl); 00085 _ssl = NULL; 00086 } 00087 } 00088 00089 public: 00090 static TypeHandle get_class_type() { 00091 return _type_handle; 00092 } 00093 static void init_type() { 00094 Socket_IP::init_type(); 00095 register_type(_type_handle, "Socket_TCP_SSL", 00096 Socket_IP::get_class_type()); 00097 } 00098 virtual TypeHandle get_type() const { 00099 return get_class_type(); 00100 } 00101 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00102 00103 private: 00104 static TypeHandle _type_handle; 00105 }; 00106 00107 ////////////////////////////////////////////////////////////// 00108 // Function name : Socket_TCP_SSL::Socket_TCP_SSL 00109 // Description : 00110 ////////////////////////////////////////////////////////////// 00111 // right know this will only work for a 00112 // accepted ie a server socket ?? 00113 inline Socket_TCP_SSL::Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck) 00114 { 00115 SetNonBlocking(); // maybe should be blocking? 00116 00117 _ssl = SSL_new (global_ssl_ctx); 00118 if(_ssl == NULL) 00119 return; 00120 SSL_set_fd (_ssl,(int)GetSocket() ); 00121 00122 SSL_accept(_ssl); 00123 ERR_clear_error(); 00124 00125 // printf(" Ssl Accept = %d \n",err); 00126 } 00127 00128 //////////////////////////////////////////////////////////////////// 00129 // Function name : SetNoDelay 00130 // Description : Disable Nagle algorithm. Don't delay send to coalesce packets 00131 //////////////////////////////////////////////////////////////////// 00132 inline int Socket_TCP_SSL::SetNoDelay() 00133 { 00134 int nodel = 1; 00135 int ret1; 00136 ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel)); 00137 00138 if (ret1 != 0) 00139 return BASIC_ERROR; 00140 00141 return ALL_OK; 00142 } 00143 00144 //////////////////////////////////////////////////////////////////// 00145 // Function name : SetLinger 00146 // Description : will control the behavior of SO_LINGER for a TCP socket 00147 //////////////////////////////////////////////////////////////////// 00148 int Socket_TCP_SSL::SetLinger(int interval_seconds) 00149 { 00150 linger ll; 00151 ll.l_linger = interval_seconds; 00152 ll.l_onoff = 1; 00153 int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); 00154 if (ret1 != 0) 00155 return BASIC_ERROR; 00156 return ALL_OK; 00157 } 00158 00159 //////////////////////////////////////////////////////////////////// 00160 // Function name : Socket_TCP_SSL::DontLinger 00161 // Description : Turn off the linger flag. The socket will quickly release 00162 // buffered items and free up OS resources. You may lose 00163 // a stream if you use this flag and do not negotiate the close 00164 // at the application layer. 00165 //////////////////////////////////////////////////////////////////// 00166 int Socket_TCP_SSL::DontLinger() 00167 { 00168 linger ll; 00169 ll.l_linger = 0; 00170 ll.l_onoff = 0; 00171 int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger)); 00172 if (ret1 != 0) 00173 return BASIC_ERROR; 00174 return ALL_OK; 00175 } 00176 00177 //////////////////////////////////////////////////////////////////// 00178 // Function name : SetSendBufferSize 00179 // Description : Just like it sounds. Sets a buffered socket recv buffer size. 00180 // This function does not refuse ranges outside hard-coded OS 00181 // limits 00182 //////////////////////////////////////////////////////////////////// 00183 int Socket_TCP_SSL::SetSendBufferSize(int insize) 00184 { 00185 if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int))) 00186 return BASIC_ERROR; 00187 return ALL_OK; 00188 } 00189 00190 //////////////////////////////////////////////////////////////////// 00191 // Function name : ActiveOpen 00192 // Description : This function will try and set the socket up for active open to a specified 00193 // address and port provided by the input parameter 00194 //////////////////////////////////////////////////////////////////// 00195 bool Socket_TCP_SSL::ActiveOpen(const Socket_Address & theaddress) 00196 { 00197 _socket = DO_NEWTCP(); 00198 if (_socket == BAD_SOCKET) 00199 return false; 00200 00201 if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) 00202 return ErrorClose(); 00203 00204 00205 _ssl = SSL_new (global_ssl_ctx); 00206 if(_ssl == NULL) 00207 return false; 00208 SSL_set_fd (_ssl,(int)GetSocket() ); 00209 if(SSL_connect(_ssl) == -1) 00210 return false; 00211 return true; 00212 00213 //return SetSslUp(); 00214 } 00215 00216 //////////////////////////////////////////////////////////////////// 00217 // Function name : Socket_TCP_SSL::SendData 00218 // Description : Ok Lets Send the Data 00219 // 00220 // Return type : int 00221 // - if error 00222 // 0 if socket closed for write or lengh is 0 00223 // + bytes writen ( May be smaller than requested) 00224 //////////////////////////////////////////////////////////////////// 00225 inline int Socket_TCP_SSL::SendData(const char * data, int size) 00226 { 00227 if(_ssl == NULL) 00228 return -1; 00229 00230 // ERR_clear_error(); 00231 00232 return SSL_write(_ssl, data, size); 00233 } 00234 00235 //////////////////////////////////////////////////////////////////// 00236 // Function name : Socket_TCP_SSL::RecvData 00237 // Description : Read the data from the connection 00238 // 00239 // Return type : int 00240 // - if error 00241 // 0 if socket closed for read or length is 0 00242 // + bytes read ( May be smaller than requested) 00243 //////////////////////////////////////////////////////////////////// 00244 inline int Socket_TCP_SSL::RecvData(char * data, int len) 00245 { 00246 if(_ssl == NULL) 00247 return -1; 00248 00249 ERR_clear_error(); 00250 00251 return SSL_read(_ssl, data, len); 00252 } 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function name : ErrorIs_WouldBlocking 00256 // Description : Is last error a blocking error ?? 00257 // 00258 // Return type : Bool 00259 // True is last error was a blocking error 00260 //////////////////////////////////////////////////////////////////// 00261 inline bool Socket_TCP_SSL::ErrorIs_WouldBlocking(int err) 00262 { 00263 if(_ssl == NULL || err >= 0) 00264 { 00265 nativenet_cat.warning() 00266 << "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number " 00267 << err << " or _ssl is NULL\n"; 00268 return false; 00269 } 00270 00271 int ssl_error_code = SSL_get_error(_ssl,err); 00272 bool answer = false; 00273 00274 switch(ssl_error_code) 00275 { 00276 case SSL_ERROR_WANT_READ: 00277 case SSL_ERROR_WANT_WRITE: 00278 case SSL_ERROR_WANT_CONNECT: 00279 // case SSL_ERROR_WANT_ACCEPT: 00280 answer = true; 00281 break; 00282 // hmm not sure we need this .. hmmmm 00283 case SSL_ERROR_SYSCALL: 00284 if(GETERROR() == LOCAL_BLOCKING_ERROR) 00285 answer = true; 00286 else 00287 { 00288 DetailErrorFormat(); 00289 // LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error1 SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR()); 00290 } 00291 break; 00292 default: 00293 DetailErrorFormat(); 00294 // LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error2 SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR()); 00295 answer = false; 00296 break; 00297 } 00298 00299 // ERR_clear_error(); 00300 return answer; 00301 } 00302 00303 inline void Socket_TCP_SSL::DetailErrorFormat(void) 00304 { 00305 return; // turn on fir debuging 00306 00307 PN_uint32 l; 00308 char buf[256]; 00309 char buf2[4096]; 00310 const char *file,*data; 00311 int line,flags; 00312 PN_uint32 es; 00313 00314 es=CRYPTO_thread_id(); 00315 while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0) 00316 { 00317 ERR_error_string_n(l, buf, sizeof( buf) ); 00318 BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", (unsigned long) es, buf,file, line, (flags & ERR_TXT_STRING) ? data : "NoText"); 00319 nativenet_cat.warning() 00320 << "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n"; 00321 } 00322 } 00323 00324 #endif // HAVE_OPENSSL 00325 00326 #endif //__SOCKET_TCP_SSL_H__ 00327