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>
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
00019
00020
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
00034 meth = SSLv23_method();
00035 SSL_load_error_strings();
00036
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
00109
00110
00111
00112
00113 inline Socket_TCP_SSL::Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck)
00114 {
00115 SetNonBlocking();
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
00126 }
00127
00128
00129
00130
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
00146
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
00161
00162
00163
00164
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
00179
00180
00181
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
00192
00193
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
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 inline int Socket_TCP_SSL::SendData(const char * data, int size)
00226 {
00227 if(_ssl == NULL)
00228 return -1;
00229
00230
00231
00232 return SSL_write(_ssl, data, size);
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
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
00256
00257
00258
00259
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
00280 answer = true;
00281 break;
00282
00283 case SSL_ERROR_SYSCALL:
00284 if(GETERROR() == LOCAL_BLOCKING_ERROR)
00285 answer = true;
00286 else
00287 {
00288 DetailErrorFormat();
00289
00290 }
00291 break;
00292 default:
00293 DetailErrorFormat();
00294
00295 answer = false;
00296 break;
00297 }
00298
00299
00300 return answer;
00301 }
00302
00303 inline void Socket_TCP_SSL::DetailErrorFormat(void)
00304 {
00305 return;
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