1 /**
2 * @file Csocket.cc
3 * @author Jim Hull <csocket@jimloco.com>
4 *
5 * Copyright (c) 1999-2012 Jim Hull <csocket@jimloco.com>
6 * All rights reserved
7 *
8 * Redistribution and use in source and binary forms, with or without modification,
9 * are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 * Redistributions in any form must be accompanied by information on how to obtain
16 * complete source code for this software and any accompanying software that uses this software.
17 * The source code must either be included in the distribution or be available for no more than
18 * the cost of distribution plus a nominal fee, and must be freely redistributable
19 * under reasonable conditions. For an executable file, complete source code means the source
20 * code for all modules it contains. It does not include source code for modules or files
21 * that typically accompany the major components of the operating system on which the executable file runs.
22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
25 * OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /***
34 * doing this because there seems to be a bug that is losing the "short" on htons when in optimize mode turns into a macro
35 * gcc 4.3.4
36 */
37 #if defined(__OPTIMIZE__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3
38 #pragma GCC diagnostic warning "-Wconversion"
39 #endif /* defined(__OPTIMIZE__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 */
40
41 #include "Csocket.h"
42 #ifdef __NetBSD__
43 #include <sys/param.h>
44 #endif /* __NetBSD__ */
45
46 #ifdef HAVE_LIBSSL
47 #include <stdio.h>
48 #include <openssl/ssl.h>
49 #include <openssl/conf.h>
50 #include <openssl/engine.h>
51 #ifndef OPENSSL_NO_COMP
52 #include <openssl/comp.h>
53 #endif
54 #define HAVE_ERR_REMOVE_STATE
55 #ifdef OPENSSL_VERSION_NUMBER
56 # if OPENSSL_VERSION_NUMBER >= 0x10000000
57 # undef HAVE_ERR_REMOVE_STATE
58 # define HAVE_ERR_REMOVE_THREAD_STATE
59 # endif
60 # if OPENSSL_VERSION_NUMBER < 0x10001000
61 # define OPENSSL_NO_TLS1_1 /* 1.0.1-pre~: openssl/openssl@637f374ad49d5f6d4f81d87d7cdd226428aa470c */
62 # define OPENSSL_NO_TLS1_2 /* 1.0.1-pre~: openssl/openssl@7409d7ad517650db332ae528915a570e4e0ab88b */
63 # endif
64 # ifndef LIBRESSL_VERSION_NUMBER /* forked from OpenSSL 1.0.1g, sets high version "with the idea of discouraging software from relying on magic numbers for detecting features"(!) */
65 # if OPENSSL_VERSION_NUMBER >= 0x10100000
66 # undef HAVE_ERR_REMOVE_THREAD_STATE /* 1.1.0-pre4: openssl/openssl@8509dcc9f319190c565ab6baad7c88d37a951d1c */
67 # undef OPENSSL_NO_SSL2 /* 1.1.0-pre4: openssl/openssl@e80381e1a3309f5d4a783bcaa508a90187a48882 */
68 # define OPENSSL_NO_SSL2 /* 1.1.0-pre1: openssl/openssl@45f55f6a5bdcec411ef08a6f8aae41d5d3d234ad */
69 # define HAVE_FLEXIBLE_TLS_METHOD /* 1.1.0-pre1: openssl/openssl@32ec41539b5b23bc42503589fcc5be65d648d1f5 */
70 # define HAVE_OPAQUE_SSL
71 # endif
72 # endif /* LIBRESSL_VERSION_NUMBER */
73 #endif /* OPENSSL_VERSION_NUMBER */
74 #endif /* HAVE_LIBSSL */
75
76 #ifdef HAVE_ICU
77 #include <unicode/ustring.h>
78 #include <unicode/errorcode.h>
79 #include <unicode/ucnv_cb.h>
80 #endif /* HAVE_ICU */
81
82 #include <list>
83 #include <algorithm>
84
85 #define CS_SRANDBUFFER 128
86
87 /*
88 * timeradd/timersub is missing on solaris' sys/time.h, provide
89 * some fallback macros
90 */
91 #ifndef timeradd
92 #define timeradd(a, b, result) \
93 do { \
94 (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
95 (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
96 if ((result)->tv_usec >= 1000000) { \
97 ++(result)->tv_sec; \
98 (result)->tv_usec -= 1000000; \
99 } \
100 } while (0)
101 #endif
102
103 #ifndef timersub
104 #define timersub(a, b, result) \
105 do { \
106 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
107 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
108 if ((result)->tv_usec < 0) { \
109 --(result)->tv_sec; \
110 (result)->tv_usec += 1000000; \
111 } \
112 } while (0)
113 #endif
114
115 using std::stringstream;
116 using std::ostream;
117 using std::endl;
118 using std::min;
119 using std::vector;
120
121 #define CREATE_ARES_VER( a, b, c ) ((a<<16)|(b<<8)|c)
122
123 #ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
124 namespace Csocket
125 {
126 #endif /* _NO_CSOCKET_NS */
127
128 static int s_iCsockSSLIdx = 0; //!< this gets setup once in InitSSL
GetCsockSSLIdx()129 int GetCsockSSLIdx()
130 {
131 return( s_iCsockSSLIdx );
132 }
133
134 #ifdef _WIN32
135
136 #if defined(_WIN32) && (!defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600))
137 //! thanks to KiNgMaR @ #znc for this wrapper
inet_pton(int af,const char * src,void * dst)138 static int inet_pton( int af, const char *src, void *dst )
139 {
140 sockaddr_storage aAddress;
141 int iAddrLen = sizeof( sockaddr_storage );
142 memset( &aAddress, 0, iAddrLen );
143 char * pTmp = strdup( src );
144 aAddress.ss_family = af; // this is important:
145 // The function fails if the sin_family member of the SOCKADDR_IN structure is not set to AF_INET or AF_INET6.
146 int iRet = WSAStringToAddressA( pTmp, af, NULL, ( sockaddr * )&aAddress, &iAddrLen );
147 free( pTmp );
148 if( iRet == 0 )
149 {
150 if( af == AF_INET6 )
151 memcpy( dst, &( ( sockaddr_in6 * ) &aAddress )->sin6_addr, sizeof( in6_addr ) );
152 else
153 memcpy( dst, &( ( sockaddr_in * ) &aAddress )->sin_addr, sizeof( in_addr ) );
154 return( 1 );
155 }
156 return( -1 );
157 }
158 #endif
159
set_non_blocking(cs_sock_t fd)160 static inline void set_non_blocking( cs_sock_t fd )
161 {
162 u_long iOpts = 1;
163 ioctlsocket( fd, FIONBIO, &iOpts );
164 }
165
166 /*
167 * not used by anything anymore
168 static inline void set_blocking(cs_sock_t fd)
169 {
170 u_long iOpts = 0;
171 ioctlsocket( fd, FIONBIO, &iOpts );
172 }
173 */
174
set_close_on_exec(cs_sock_t fd)175 static inline void set_close_on_exec( cs_sock_t fd )
176 {
177 // TODO add this for windows
178 // see http://gcc.gnu.org/ml/java-patches/2002-q1/msg00696.html
179 // for infos on how to do this
180 }
181
182 #else // _WIN32
183
set_non_blocking(cs_sock_t fd)184 static inline void set_non_blocking( cs_sock_t fd )
185 {
186 int fdflags = fcntl( fd, F_GETFL, 0 );
187 if( fdflags < 0 )
188 return; // Ignore errors
189 fcntl( fd, F_SETFL, fdflags|O_NONBLOCK );
190 }
191
192 /*
193 * not used by anything anymore
194 static inline void set_blocking(cs_sock_t fd)
195 {
196 int fdflags = fcntl(fd, F_GETFL, 0);
197 if( fdflags < 0 )
198 return; // Ignore errors
199 fdflags &= ~O_NONBLOCK;
200 fcntl( fd, F_SETFL, fdflags );
201 }
202 */
203
set_close_on_exec(cs_sock_t fd)204 static inline void set_close_on_exec( cs_sock_t fd )
205 {
206 int fdflags = fcntl( fd, F_GETFD, 0 );
207 if( fdflags < 0 )
208 return; // Ignore errors
209 fcntl( fd, F_SETFD, fdflags|FD_CLOEXEC );
210 }
211 #endif /* _WIN32 */
212
SinFamily()213 void CSSockAddr::SinFamily()
214 {
215 #ifdef HAVE_IPV6
216 m_saddr6.sin6_family = PF_INET6;
217 #endif /* HAVE_IPV6 */
218 m_saddr.sin_family = PF_INET;
219 }
220
SinPort(uint16_t iPort)221 void CSSockAddr::SinPort( uint16_t iPort )
222 {
223 #ifdef HAVE_IPV6
224 m_saddr6.sin6_port = htons( iPort );
225 #endif /* HAVE_IPV6 */
226 m_saddr.sin_port = htons( iPort );
227 }
228
SetIPv6(bool b)229 void CSSockAddr::SetIPv6( bool b )
230 {
231 #ifndef HAVE_IPV6
232 if( b )
233 {
234 CS_DEBUG( "-DHAVE_IPV6 must be set during compile time to enable this feature" );
235 m_bIsIPv6 = false;
236 return;
237 }
238 #endif /* HAVE_IPV6 */
239 m_bIsIPv6 = b;
240 SinFamily();
241 }
242
243
244 #ifdef HAVE_LIBSSL
_PemPassCB(char * pBuff,int iBuffLen,int rwflag,void * pcSocket)245 static int _PemPassCB( char *pBuff, int iBuffLen, int rwflag, void * pcSocket )
246 {
247 Csock * pSock = static_cast<Csock *>( pcSocket );
248 const CS_STRING & sPassword = pSock->GetPemPass();
249 if( iBuffLen <= 0 )
250 return( 0 );
251 memset( pBuff, '\0', iBuffLen );
252 if( sPassword.empty() )
253 return( 0 );
254 int iUseBytes = min( iBuffLen - 1, ( int )sPassword.length() );
255 memcpy( pBuff, sPassword.data(), iUseBytes );
256 return( iUseBytes );
257 }
258
_CertVerifyCB(int preverify_ok,X509_STORE_CTX * x509_ctx)259 static int _CertVerifyCB( int preverify_ok, X509_STORE_CTX *x509_ctx )
260 {
261 Csock * pSock = GetCsockFromCTX( x509_ctx );
262 if( pSock )
263 return( pSock->VerifyPeerCertificate( preverify_ok, x509_ctx ) );
264
265 return( preverify_ok );
266 }
267
_InfoCallback(const SSL * pSSL,int where,int ret)268 static void _InfoCallback( const SSL * pSSL, int where, int ret )
269 {
270 if( ( where & SSL_CB_HANDSHAKE_DONE ) && ret != 0 )
271 {
272 Csock * pSock = static_cast<Csock *>( SSL_get_ex_data( pSSL, GetCsockSSLIdx() ) );
273 if( pSock )
274 pSock->SSLHandShakeFinished();
275 }
276 }
277
278
GetCsockFromCTX(X509_STORE_CTX * pCTX)279 Csock * GetCsockFromCTX( X509_STORE_CTX * pCTX )
280 {
281 Csock * pSock = NULL;
282 SSL * pSSL = ( SSL * ) X509_STORE_CTX_get_ex_data( pCTX, SSL_get_ex_data_X509_STORE_CTX_idx() );
283 if( pSSL )
284 pSock = ( Csock * ) SSL_get_ex_data( pSSL, GetCsockSSLIdx() );
285 return( pSock );
286 }
287 #endif /* HAVE_LIBSSL */
288
289
290 #ifdef USE_GETHOSTBYNAME
291
292 // this issue here is getaddrinfo has a significant behavior difference when dealing with round robin dns on an
293 // ipv4 network. This is not desirable IMHO. so when this is compiled without ipv6 support backwards compatibility
294 // is maintained.
__GetHostByName(const CS_STRING & sHostName,struct in_addr * paddr,u_int iNumRetries)295 static int __GetHostByName( const CS_STRING & sHostName, struct in_addr * paddr, u_int iNumRetries )
296 {
297 int iReturn = HOST_NOT_FOUND;
298 struct hostent * hent = NULL;
299 #ifdef __linux__
300 char hbuff[2048];
301 struct hostent hentbuff;
302
303 int err;
304 for( u_int a = 0; a < iNumRetries; ++a )
305 {
306 memset( ( char * ) hbuff, '\0', 2048 );
307 iReturn = gethostbyname_r( sHostName.c_str(), &hentbuff, hbuff, 2048, &hent, &err );
308
309 if( iReturn == 0 )
310 break;
311
312 if( iReturn != TRY_AGAIN )
313 {
314 CS_DEBUG( "gethostyname_r: " << hstrerror( h_errno ) );
315 break;
316 }
317 }
318 if( !hent && iReturn == 0 )
319 iReturn = HOST_NOT_FOUND;
320 #else
321 for( u_int a = 0; a < iNumRetries; ++a )
322 {
323 iReturn = HOST_NOT_FOUND;
324 hent = gethostbyname( sHostName.c_str() );
325
326 if( hent )
327 {
328 iReturn = 0;
329 break;
330 }
331
332 if( h_errno != TRY_AGAIN )
333 {
334 #ifndef _WIN32
335 CS_DEBUG( "gethostyname: " << hstrerror( h_errno ) );
336 #endif /* _WIN32 */
337 break;
338 }
339 }
340
341 #endif /* __linux__ */
342
343 if( iReturn == 0 )
344 memcpy( &paddr->s_addr, hent->h_addr_list[0], sizeof( paddr->s_addr ) );
345
346 return( iReturn == TRY_AGAIN ? EAGAIN : iReturn );
347 }
348 #endif /* !USE_GETHOSTBYNAME */
349
350
351 #ifdef HAVE_C_ARES
FreeAres()352 void Csock::FreeAres()
353 {
354 if( m_pARESChannel )
355 {
356 ares_destroy( m_pARESChannel );
357 m_pARESChannel = NULL;
358 }
359 }
360
AresHostCallback(void * pArg,int status,int timeouts,struct hostent * hent)361 static void AresHostCallback( void * pArg, int status, int timeouts, struct hostent *hent )
362 {
363 Csock * pSock = ( Csock * )pArg;
364 if( status == ARES_SUCCESS && hent && hent->h_addr_list[0] != NULL )
365 {
366 CSSockAddr * pSockAddr = pSock->GetCurrentAddr();
367 if( hent->h_addrtype == AF_INET )
368 {
369 pSock->SetIPv6( false );
370 memcpy( pSockAddr->GetAddr(), hent->h_addr_list[0], sizeof( *( pSockAddr->GetAddr() ) ) );
371 }
372 #ifdef HAVE_IPV6
373 else if( hent->h_addrtype == AF_INET6 )
374 {
375 pSock->SetIPv6( true );
376 memcpy( pSockAddr->GetAddr6(), hent->h_addr_list[0], sizeof( *( pSockAddr->GetAddr6() ) ) );
377 }
378 #endif /* HAVE_IPV6 */
379 else
380 {
381 status = ARES_ENOTFOUND;
382 }
383 }
384 else
385 {
386 CS_DEBUG( ares_strerror( status ) );
387 if( status == ARES_SUCCESS )
388 {
389 CS_DEBUG( "Received ARES_SUCCESS without any useful reply, using NODATA instead" );
390 status = ARES_ENODATA;
391 }
392 }
393 pSock->SetAresFinished( status );
394 }
395 #endif /* HAVE_C_ARES */
396
CGetAddrInfo(const CS_STRING & sHostname,Csock * pSock,CSSockAddr & csSockAddr)397 CGetAddrInfo::CGetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr )
398 : m_pSock( pSock ), m_csSockAddr( csSockAddr )
399 {
400 m_sHostname = sHostname;
401 m_pAddrRes = NULL;
402 m_iRet = ETIMEDOUT;
403 }
404
~CGetAddrInfo()405 CGetAddrInfo::~CGetAddrInfo()
406 {
407 if( m_pAddrRes )
408 freeaddrinfo( m_pAddrRes );
409 m_pAddrRes = NULL;
410 }
411
Init()412 void CGetAddrInfo::Init()
413 {
414 memset( ( struct addrinfo * )&m_cHints, '\0', sizeof( m_cHints ) );
415 m_cHints.ai_family = m_csSockAddr.GetAFRequire();
416
417 m_cHints.ai_socktype = SOCK_STREAM;
418 m_cHints.ai_protocol = IPPROTO_TCP;
419 #ifdef AI_ADDRCONFIG
420 // this is suppose to eliminate host from appearing that this system can not support
421 m_cHints.ai_flags = AI_ADDRCONFIG;
422 #endif /* AI_ADDRCONFIG */
423
424 if( m_pSock && ( m_pSock->GetType() == Csock::LISTENER || m_pSock->GetConState() == Csock::CST_BINDVHOST ) )
425 {
426 // when doing a dns for bind only, set the AI_PASSIVE flag as suggested by the man page
427 m_cHints.ai_flags |= AI_PASSIVE;
428 }
429 }
430
Process()431 int CGetAddrInfo::Process()
432 {
433 m_iRet = getaddrinfo( m_sHostname.c_str(), NULL, &m_cHints, &m_pAddrRes );
434 if( m_iRet == EAI_AGAIN )
435 return( EAGAIN );
436 else if( m_iRet == 0 )
437 return( 0 );
438 return( ETIMEDOUT );
439 }
440
Finish()441 int CGetAddrInfo::Finish()
442 {
443 if( m_iRet == 0 && m_pAddrRes )
444 {
445 std::list<struct addrinfo *> lpTryAddrs;
446 bool bFound = false;
447 for( struct addrinfo * pRes = m_pAddrRes; pRes; pRes = pRes->ai_next )
448 {
449 // pass through the list building out a lean list of candidates to try. AI_CONFIGADDR doesn't always seem to work
450 #ifdef __sun
451 if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP && pRes->ai_protocol != IPPROTO_IP ) )
452 #else
453 if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP ) )
454 #endif /* __sun work around broken impl of getaddrinfo */
455 continue;
456
457 if( ( m_csSockAddr.GetAFRequire() != CSSockAddr::RAF_ANY ) && ( pRes->ai_family != m_csSockAddr.GetAFRequire() ) )
458 continue; // they requested a special type, so be certain we woop past anything unwanted
459 lpTryAddrs.push_back( pRes );
460 }
461 for( std::list<struct addrinfo *>::iterator it = lpTryAddrs.begin(); it != lpTryAddrs.end(); )
462 {
463 // cycle through these, leaving the last iterator for the outside caller to call, so if there is an error it can call the events
464 struct addrinfo * pRes = *it;
465 bool bTryConnect = false;
466 if( pRes->ai_family == AF_INET )
467 {
468 if( m_pSock )
469 m_pSock->SetIPv6( false );
470 m_csSockAddr.SetIPv6( false );
471 struct sockaddr_in * pTmp = ( struct sockaddr_in * )pRes->ai_addr;
472 memcpy( m_csSockAddr.GetAddr(), &( pTmp->sin_addr ), sizeof( *( m_csSockAddr.GetAddr() ) ) );
473 if( m_pSock && m_pSock->GetConState() == Csock::CST_DESTDNS && m_pSock->GetType() == Csock::OUTBOUND )
474 {
475 bTryConnect = true;
476 }
477 else
478 {
479 bFound = true;
480 break;
481 }
482 }
483 #ifdef HAVE_IPV6
484 else if( pRes->ai_family == AF_INET6 )
485 {
486 if( m_pSock )
487 m_pSock->SetIPv6( true );
488 m_csSockAddr.SetIPv6( true );
489 struct sockaddr_in6 * pTmp = ( struct sockaddr_in6 * )pRes->ai_addr;
490 memcpy( m_csSockAddr.GetAddr6(), &( pTmp->sin6_addr ), sizeof( *( m_csSockAddr.GetAddr6() ) ) );
491 if( m_pSock && m_pSock->GetConState() == Csock::CST_DESTDNS && m_pSock->GetType() == Csock::OUTBOUND )
492 {
493 bTryConnect = true;
494 }
495 else
496 {
497 bFound = true;
498 break;
499 }
500 }
501 #endif /* HAVE_IPV6 */
502
503 ++it; // increment the iterator her so we know if its the last element or not
504
505 if( bTryConnect && it != lpTryAddrs.end() )
506 {
507 // save the last attempt for the outer loop, the issue then becomes that the error is thrown on the last failure
508 if( m_pSock->CreateSocksFD() && m_pSock->Connect() )
509 {
510 m_pSock->SetSkipConnect( true ); // this tells the socket that the connection state has been started
511 bFound = true;
512 break;
513 }
514 m_pSock->CloseSocksFD();
515 }
516 else if( bTryConnect )
517 {
518 bFound = true;
519 }
520 }
521
522 if( bFound ) // the data pointed to here is invalid now, but the pointer itself is a good test
523 {
524 return( 0 );
525 }
526 }
527 return( ETIMEDOUT );
528 }
529
CS_GetAddrInfo(const CS_STRING & sHostname,Csock * pSock,CSSockAddr & csSockAddr)530 int CS_GetAddrInfo( const CS_STRING & sHostname, Csock * pSock, CSSockAddr & csSockAddr )
531 {
532 #ifdef USE_GETHOSTBYNAME
533 if( pSock )
534 pSock->SetIPv6( false );
535 csSockAddr.SetIPv6( false );
536 int iRet = __GetHostByName( sHostname, csSockAddr.GetAddr(), 3 );
537 return( iRet );
538 #else
539 CGetAddrInfo cInfo( sHostname, pSock, csSockAddr );
540 cInfo.Init();
541 int iRet = cInfo.Process();
542 if( iRet != 0 )
543 return( iRet );
544 return( cInfo.Finish() );
545 #endif /* USE_GETHOSTBYNAME */
546 }
547
ConvertAddress(const struct sockaddr_storage * pAddr,socklen_t iAddrLen,CS_STRING & sIP,uint16_t * piPort) const548 int Csock::ConvertAddress( const struct sockaddr_storage * pAddr, socklen_t iAddrLen, CS_STRING & sIP, uint16_t * piPort ) const
549 {
550 char szHostname[NI_MAXHOST];
551 char szServ[NI_MAXSERV];
552 int iRet = getnameinfo( ( const struct sockaddr * )pAddr, iAddrLen, szHostname, NI_MAXHOST, szServ, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV );
553 if( iRet == 0 )
554 {
555 sIP = szHostname;
556 if( piPort )
557 *piPort = ( uint16_t )atoi( szServ );
558 }
559 return( iRet );
560 }
561
InitCsocket()562 bool InitCsocket()
563 {
564 #ifdef _WIN32
565 WSADATA wsaData;
566 int iResult = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
567 if( iResult != NO_ERROR )
568 return( false );
569 #endif /* _WIN32 */
570 #ifdef HAVE_C_ARES
571 #if ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 )
572 if( ares_library_init( ARES_LIB_INIT_ALL ) != 0 )
573 return( false );
574 #endif /* ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 ) */
575 #endif /* HAVE_C_ARES */
576 #ifdef HAVE_LIBSSL
577 if( !InitSSL() )
578 return( false );
579 #endif /* HAVE_LIBSSL */
580 return( true );
581 }
582
ShutdownCsocket()583 void ShutdownCsocket()
584 {
585 #ifdef HAVE_LIBSSL
586 #if defined( HAVE_ERR_REMOVE_THREAD_STATE )
587 ERR_remove_thread_state( NULL );
588 #elif defined( HAVE_ERR_REMOVE_STATE )
589 ERR_remove_state( 0 );
590 #endif
591 #ifndef OPENSSL_NO_ENGINE
592 ENGINE_cleanup();
593 #endif
594 #ifndef OPENSSL_IS_BORINGSSL
595 CONF_modules_unload( 1 );
596 #endif
597 ERR_free_strings();
598 EVP_cleanup();
599 CRYPTO_cleanup_all_ex_data();
600 #endif /* HAVE_LIBSSL */
601 #ifdef HAVE_C_ARES
602 #if ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 )
603 ares_library_cleanup();
604 #endif /* ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 ) */
605 #endif /* HAVE_C_ARES */
606 #ifdef _WIN32
607 WSACleanup();
608 #endif /* _WIN32 */
609 }
610
611 #ifdef HAVE_LIBSSL
InitSSL(ECompType eCompressionType)612 bool InitSSL( ECompType eCompressionType )
613 {
614 SSL_load_error_strings();
615 if( SSL_library_init() != 1 )
616 {
617 CS_DEBUG( "SSL_library_init() failed!" );
618 return( false );
619 }
620
621 #ifndef _WIN32
622 if( access( "/dev/urandom", R_OK ) == 0 )
623 {
624 RAND_load_file( "/dev/urandom", 1024 );
625 }
626 else if( access( "/dev/random", R_OK ) == 0 )
627 {
628 RAND_load_file( "/dev/random", 1024 );
629 }
630 else
631 {
632 CS_DEBUG( "Unable to locate entropy location! Tried /dev/urandom and /dev/random" );
633 return( false );
634 }
635 #endif /* _WIN32 */
636
637 #ifndef OPENSSL_NO_COMP
638 COMP_METHOD *cm = NULL;
639
640 if( CT_ZLIB & eCompressionType )
641 {
642 cm = COMP_zlib();
643 if( cm )
644 SSL_COMP_add_compression_method( CT_ZLIB, cm );
645 }
646 #endif
647
648 // setting this up once in the begining
649 s_iCsockSSLIdx = SSL_get_ex_new_index( 0, NULL, NULL, NULL, NULL );
650
651 return( true );
652 }
653
SSLErrors(const char * filename,u_int iLineNum)654 void SSLErrors( const char *filename, u_int iLineNum )
655 {
656 unsigned long iSSLError = 0;
657 while( ( iSSLError = ERR_get_error() ) != 0 )
658 {
659 CS_DEBUG( "at " << filename << ":" << iLineNum );
660 char szError[512];
661 memset( ( char * ) szError, '\0', 512 );
662 ERR_error_string_n( iSSLError, szError, 511 );
663 if( *szError )
664 CS_DEBUG( szError );
665 }
666 }
667 #endif /* HAVE_LIBSSL */
668
CSAdjustTVTimeout(struct timeval & tv,long iTimeoutMS)669 void CSAdjustTVTimeout( struct timeval & tv, long iTimeoutMS )
670 {
671 if( iTimeoutMS >= 0 )
672 {
673 long iCurTimeout = tv.tv_usec / 1000;
674 iCurTimeout += tv.tv_sec * 1000;
675 if( iCurTimeout > iTimeoutMS )
676 {
677 tv.tv_sec = iTimeoutMS / 1000;
678 tv.tv_usec = iTimeoutMS % 1000;
679 }
680 }
681 }
682
683 #define CS_UNKNOWN_ERROR "Unknown Error"
CS_StrError(int iErrno,char * pszBuff,size_t uBuffLen)684 static const char * CS_StrError( int iErrno, char * pszBuff, size_t uBuffLen )
685 {
686 #if defined( sgi ) || defined(__sun) || (defined(__NetBSD_Version__) && __NetBSD_Version__ < 4000000000)
687 return( strerror( iErrno ) );
688 #else
689 memset( pszBuff, '\0', uBuffLen );
690 #if defined( _WIN32 )
691 if ( strerror_s( pszBuff, uBuffLen, iErrno ) == 0 )
692 return( pszBuff );
693 #elif !defined( _GNU_SOURCE ) || !defined(__GLIBC__) || defined( __FreeBSD__ )
694 if( strerror_r( iErrno, pszBuff, uBuffLen ) == 0 )
695 return( pszBuff );
696 #else
697 return( strerror_r( iErrno, pszBuff, uBuffLen ) );
698 #endif /* (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined( _GNU_SOURCE ) */
699 #endif /* defined( sgi ) || defined(__sun) || defined(_WIN32) || (defined(__NetBSD_Version__) && __NetBSD_Version__ < 4000000000) */
700 return( CS_UNKNOWN_ERROR );
701 }
702
__Perror(const CS_STRING & s,const char * pszFile,u_int iLineNo)703 void __Perror( const CS_STRING & s, const char * pszFile, u_int iLineNo )
704 {
705 char szBuff[0xff];
706 std::cerr << s << "(" << pszFile << ":" << iLineNo << "): " << CS_StrError( GetSockError(), szBuff, 0xff ) << endl;
707 }
708
millitime()709 uint64_t millitime()
710 {
711 uint64_t iTime = 0;
712 #ifdef _WIN32
713 struct timeb tm;
714 ftime( &tm );
715 iTime = tm.time * 1000;
716 iTime += tm.millitm;
717 #else
718 struct timeval tv;
719 gettimeofday( &tv, NULL );
720 iTime = ( uint64_t )tv.tv_sec * 1000;
721 iTime += ( ( uint64_t )tv.tv_usec / 1000 );
722 #endif /* _WIN32 */
723 return( iTime );
724 }
725
726 #ifndef _MSC_VER
727 #define CS_GETTIMEOFDAY gettimeofday
728 #else
729 #define CS_GETTIMEOFDAY win32_gettimeofday
730
731 // timezone-agnostic implementation of gettimeofday
732 static int
win32_gettimeofday(struct timeval * now,void *)733 win32_gettimeofday( struct timeval* now, void* )
734 {
735 static const ULONGLONG epoch = 116444736000000000ULL; // Jan 1st 1970
736
737 ULARGE_INTEGER file_time;
738 SYSTEMTIME system_time;
739
740 GetSystemTime( &system_time );
741 if ( !SystemTimeToFileTime( &system_time, ( LPFILETIME )&file_time) )
742 return( 1 );
743
744 now->tv_sec = ( long )( ( file_time.QuadPart - epoch ) / 10000000L );
745 now->tv_usec = ( long )( system_time.wMilliseconds * 1000 );
746
747 return 0;
748 }
749 #endif
750
751 #ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
752 }
753 using namespace Csocket;
754 #endif /* _NO_CSOCKET_NS */
755
CCron()756 CCron::CCron()
757 {
758 m_iCycles = 0;
759 m_iMaxCycles = 0;
760 m_bActive = true;
761 timerclear( &m_tTime );
762 m_tTimeSequence.tv_sec = 60;
763 m_tTimeSequence.tv_usec = 0;
764 m_bPause = false;
765 m_bRunOnNextCall = false;
766 }
767
run(timeval & tNow)768 void CCron::run( timeval & tNow )
769 {
770 if( m_bPause )
771 return;
772
773 if( !timerisset( &tNow ) )
774 CS_GETTIMEOFDAY( &tNow, NULL );
775
776 if( m_bActive && ( !timercmp( &tNow, &m_tTime, < ) || m_bRunOnNextCall ) )
777 {
778 m_bRunOnNextCall = false; // Setting this here because RunJob() could set it back to true
779 RunJob();
780
781 if( m_iMaxCycles > 0 && ++m_iCycles >= m_iMaxCycles )
782 m_bActive = false;
783 else
784 timeradd( &tNow, &m_tTimeSequence, &m_tTime );
785 }
786 }
787
StartMaxCycles(double dTimeSequence,u_int iMaxCycles)788 void CCron::StartMaxCycles( double dTimeSequence, u_int iMaxCycles )
789 {
790 timeval tNow;
791 m_tTimeSequence.tv_sec = ( time_t ) dTimeSequence;
792 // this could be done with modf(), but we're avoiding bringing in libm just for the one function.
793 m_tTimeSequence.tv_usec = ( suseconds_t )( ( dTimeSequence - ( double )( ( time_t ) dTimeSequence ) ) * 1000000 );
794 CS_GETTIMEOFDAY( &tNow, NULL );
795 timeradd( &tNow, &m_tTimeSequence, &m_tTime );
796 m_iMaxCycles = iMaxCycles;
797 m_bActive = true;
798 }
799
StartMaxCycles(const timeval & tTimeSequence,u_int iMaxCycles)800 void CCron::StartMaxCycles( const timeval& tTimeSequence, u_int iMaxCycles )
801 {
802 timeval tNow;
803 m_tTimeSequence = tTimeSequence;
804 CS_GETTIMEOFDAY( &tNow, NULL );
805 timeradd( &tNow, &m_tTimeSequence, &m_tTime );
806 m_iMaxCycles = iMaxCycles;
807 m_bActive = true;
808 }
809
Start(double dTimeSequence)810 void CCron::Start( double dTimeSequence )
811 {
812 StartMaxCycles( dTimeSequence, 0 );
813 }
814
Start(const timeval & tTimeSequence)815 void CCron::Start( const timeval& tTimeSequence )
816 {
817 StartMaxCycles( tTimeSequence, 0 );
818 }
819
Stop()820 void CCron::Stop()
821 {
822 m_bActive = false;
823 }
824
Pause()825 void CCron::Pause()
826 {
827 m_bPause = true;
828 }
829
UnPause()830 void CCron::UnPause()
831 {
832 m_bPause = false;
833 }
834
Reset()835 void CCron::Reset()
836 {
837 Stop();
838 Start(m_tTimeSequence);
839 }
840
GetInterval() const841 timeval CCron::GetInterval() const { return( m_tTimeSequence ); }
GetMaxCycles() const842 u_int CCron::GetMaxCycles() const { return( m_iMaxCycles ); }
GetCyclesLeft() const843 u_int CCron::GetCyclesLeft() const { return( ( m_iMaxCycles > m_iCycles ? ( m_iMaxCycles - m_iCycles ) : 0 ) ); }
844
isValid() const845 bool CCron::isValid() const { return( m_bActive ); }
GetName() const846 const CS_STRING & CCron::GetName() const { return( m_sName ); }
SetName(const CS_STRING & sName)847 void CCron::SetName( const CS_STRING & sName ) { m_sName = sName; }
RunJob()848 void CCron::RunJob() { CS_DEBUG( "This should be overridden" ); }
849
GatherFDsForSelect(std::map<cs_sock_t,short> & miiReadyFds,long & iTimeoutMS)850 bool CSMonitorFD::GatherFDsForSelect( std::map< cs_sock_t, short > & miiReadyFds, long & iTimeoutMS )
851 {
852 iTimeoutMS = -1; // don't bother changing anything in the default implementation
853 for( std::map< cs_sock_t, short >::iterator it = m_miiMonitorFDs.begin(); it != m_miiMonitorFDs.end(); ++it )
854 {
855 miiReadyFds[it->first] = it->second;
856 }
857 return( m_bEnabled );
858 }
859
CheckFDs(const std::map<cs_sock_t,short> & miiReadyFds)860 bool CSMonitorFD::CheckFDs( const std::map< cs_sock_t, short > & miiReadyFds )
861 {
862 std::map< cs_sock_t, short > miiTriggerdFds;
863 for( std::map< cs_sock_t, short >::iterator it = m_miiMonitorFDs.begin(); it != m_miiMonitorFDs.end(); ++it )
864 {
865 std::map< cs_sock_t, short >::const_iterator itFD = miiReadyFds.find( it->first );
866 if( itFD != miiReadyFds.end() )
867 miiTriggerdFds[itFD->first] = itFD->second;
868 }
869 if( !miiTriggerdFds.empty() )
870 return( FDsThatTriggered( miiTriggerdFds ) );
871 return( m_bEnabled );
872 }
873
~CSockCommon()874 CSockCommon::~CSockCommon()
875 {
876 // delete any left over crons
877 CleanupCrons();
878 CleanupFDMonitors();
879 }
880
CleanupCrons()881 void CSockCommon::CleanupCrons()
882 {
883 for( size_t a = 0; a < m_vcCrons.size(); ++a )
884 CS_Delete( m_vcCrons[a] );
885 m_vcCrons.clear();
886 }
887
CleanupFDMonitors()888 void CSockCommon::CleanupFDMonitors()
889 {
890 for( size_t a = 0; a < m_vcMonitorFD.size(); ++a )
891 CS_Delete( m_vcMonitorFD[a] );
892 m_vcMonitorFD.clear();
893 }
894
CheckFDs(const std::map<cs_sock_t,short> & miiReadyFds)895 void CSockCommon::CheckFDs( const std::map< cs_sock_t, short > & miiReadyFds )
896 {
897 for( size_t uMon = 0; uMon < m_vcMonitorFD.size(); ++uMon )
898 {
899 if( !m_vcMonitorFD[uMon]->IsEnabled() || !m_vcMonitorFD[uMon]->CheckFDs( miiReadyFds ) )
900 m_vcMonitorFD.erase( m_vcMonitorFD.begin() + uMon-- );
901 }
902 }
903
AssignFDs(std::map<cs_sock_t,short> & miiReadyFds,struct timeval * tvtimeout)904 void CSockCommon::AssignFDs( std::map< cs_sock_t, short > & miiReadyFds, struct timeval * tvtimeout )
905 {
906 for( size_t uMon = 0; uMon < m_vcMonitorFD.size(); ++uMon )
907 {
908 long iTimeoutMS = -1;
909 if( m_vcMonitorFD[uMon]->IsEnabled() && m_vcMonitorFD[uMon]->GatherFDsForSelect( miiReadyFds, iTimeoutMS ) )
910 {
911 CSAdjustTVTimeout( *tvtimeout, iTimeoutMS );
912 }
913 else
914 {
915 CS_Delete( m_vcMonitorFD[uMon] );
916 m_vcMonitorFD.erase( m_vcMonitorFD.begin() + uMon-- );
917 }
918 }
919 }
920
921
Cron()922 void CSockCommon::Cron()
923 {
924 timeval tNow;
925 timerclear( &tNow );
926
927 for( vector<CCron *>::size_type a = 0; a < m_vcCrons.size(); ++a )
928 {
929 CCron * pcCron = m_vcCrons[a];
930
931 if( !pcCron->isValid() )
932 {
933 CS_Delete( pcCron );
934 m_vcCrons.erase( m_vcCrons.begin() + a-- );
935 }
936 else
937 {
938 pcCron->run( tNow );
939 }
940 }
941 }
942
AddCron(CCron * pcCron)943 void CSockCommon::AddCron( CCron * pcCron )
944 {
945 m_vcCrons.push_back( pcCron );
946 }
947
DelCron(const CS_STRING & sName,bool bDeleteAll,bool bCaseSensitive)948 void CSockCommon::DelCron( const CS_STRING & sName, bool bDeleteAll, bool bCaseSensitive )
949 {
950 for( size_t a = 0; a < m_vcCrons.size(); ++a )
951 {
952 int ( *Cmp )( const char *, const char * ) = ( bCaseSensitive ? strcmp : strcasecmp );
953 if( Cmp( m_vcCrons[a]->GetName().c_str(), sName.c_str() ) == 0 )
954 {
955 m_vcCrons[a]->Stop();
956 CS_Delete( m_vcCrons[a] );
957 m_vcCrons.erase( m_vcCrons.begin() + a-- );
958 if( !bDeleteAll )
959 break;
960 }
961 }
962 }
963
DelCron(u_int iPos)964 void CSockCommon::DelCron( u_int iPos )
965 {
966 if( iPos < m_vcCrons.size() )
967 {
968 m_vcCrons[iPos]->Stop();
969 CS_Delete( m_vcCrons[iPos] );
970 m_vcCrons.erase( m_vcCrons.begin() + iPos );
971 }
972 }
973
DelCronByAddr(CCron * pcCron)974 void CSockCommon::DelCronByAddr( CCron * pcCron )
975 {
976 for( size_t a = 0; a < m_vcCrons.size(); ++a )
977 {
978 if( m_vcCrons[a] == pcCron )
979 {
980 m_vcCrons[a]->Stop();
981 CS_Delete( m_vcCrons[a] );
982 m_vcCrons.erase( m_vcCrons.begin() + a );
983 return;
984 }
985 }
986 }
987
Csock(int iTimeout)988 Csock::Csock( int iTimeout ) : CSockCommon()
989 {
990 #ifdef HAVE_LIBSSL
991 m_pCerVerifyCB = _CertVerifyCB;
992 #endif /* HAVE_LIBSSL */
993 Init( "", 0, iTimeout );
994 }
995
Csock(const CS_STRING & sHostname,uint16_t iport,int iTimeout)996 Csock::Csock( const CS_STRING & sHostname, uint16_t iport, int iTimeout ) : CSockCommon()
997 {
998 #ifdef HAVE_LIBSSL
999 m_pCerVerifyCB = _CertVerifyCB;
1000 #endif /* HAVE_LIBSSL */
1001 Init( sHostname, iport, iTimeout );
1002 }
1003
1004 // override this for accept sockets
GetSockObj(const CS_STRING & sHostname,uint16_t iPort)1005 Csock *Csock::GetSockObj( const CS_STRING & sHostname, uint16_t iPort )
1006 {
1007 return( NULL );
1008 }
1009
1010 #ifdef HAVE_LIBSSL
SNIConfigureClient(CS_STRING & sHostname)1011 bool Csock::SNIConfigureClient( CS_STRING & sHostname )
1012 {
1013 if( m_shostname.empty() )
1014 return( false );
1015 sHostname = m_shostname;
1016 return( true );
1017 }
1018 #endif
1019
1020 #ifdef _WIN32
1021 #define CS_CLOSE closesocket
1022 #else
1023 #define CS_CLOSE close
1024 #endif /* _WIN32 */
1025
~Csock()1026 Csock::~Csock()
1027 {
1028 #ifdef _WIN32
1029 // prevent successful closesocket() calls and such from
1030 // overwriting any possible previous errors.
1031 int iOldError = ::WSAGetLastError();
1032 #endif /* _WIN32 */
1033
1034 #ifdef HAVE_ICU
1035 if( m_cnvExt ) ucnv_close( m_cnvExt );
1036 if( m_cnvInt ) ucnv_close( m_cnvInt );
1037 #endif
1038
1039 #ifdef HAVE_C_ARES
1040 if( m_pARESChannel )
1041 ares_cancel( m_pARESChannel );
1042 FreeAres();
1043 #endif /* HAVE_C_ARES */
1044
1045 #ifdef HAVE_LIBSSL
1046 FREE_SSL();
1047 FREE_CTX();
1048 #endif /* HAVE_LIBSSL */
1049
1050 CloseSocksFD();
1051
1052 #ifdef _WIN32
1053 ::WSASetLastError( iOldError );
1054 #endif /* _WIN32 */
1055 }
1056
CloseSocksFD()1057 void Csock::CloseSocksFD()
1058 {
1059 if( m_iReadSock != m_iWriteSock )
1060 {
1061 if( m_iReadSock != CS_INVALID_SOCK )
1062 CS_CLOSE( m_iReadSock );
1063 if( m_iWriteSock != CS_INVALID_SOCK )
1064 CS_CLOSE( m_iWriteSock );
1065 }
1066 else if( m_iReadSock != CS_INVALID_SOCK )
1067 {
1068 CS_CLOSE( m_iReadSock );
1069 }
1070
1071 m_iReadSock = CS_INVALID_SOCK;
1072 m_iWriteSock = CS_INVALID_SOCK;
1073 }
1074
1075
Dereference()1076 void Csock::Dereference()
1077 {
1078 m_iWriteSock = m_iReadSock = CS_INVALID_SOCK;
1079
1080 #ifdef HAVE_LIBSSL
1081 m_ssl = NULL;
1082 m_ssl_ctx = NULL;
1083 #endif /* HAVE_LIBSSL */
1084
1085 // don't delete and erase, just erase since they were moved to the copied sock
1086 m_vcCrons.clear();
1087 m_vcMonitorFD.clear();
1088 Close( CLT_DEREFERENCE );
1089 }
1090
Copy(const Csock & cCopy)1091 void Csock::Copy( const Csock & cCopy )
1092 {
1093 m_iTcount = cCopy.m_iTcount;
1094 m_iLastCheckTimeoutTime = cCopy.m_iLastCheckTimeoutTime;
1095 m_uPort = cCopy.m_uPort;
1096 m_iRemotePort = cCopy.m_iRemotePort;
1097 m_iLocalPort = cCopy.m_iLocalPort;
1098 m_iReadSock = cCopy.m_iReadSock;
1099 m_iWriteSock = cCopy.m_iWriteSock;
1100 m_iTimeout = cCopy.m_iTimeout;
1101 m_iMaxConns = cCopy.m_iMaxConns;
1102 m_iConnType = cCopy.m_iConnType;
1103 m_iMethod = cCopy.m_iMethod;
1104 m_bUseSSL = cCopy.m_bUseSSL;
1105 m_bIsConnected = cCopy.m_bIsConnected;
1106 m_bsslEstablished = cCopy.m_bsslEstablished;
1107 m_bEnableReadLine = cCopy.m_bEnableReadLine;
1108 m_bPauseRead = cCopy.m_bPauseRead;
1109 m_shostname = cCopy.m_shostname;
1110 m_sbuffer = cCopy.m_sbuffer;
1111 m_sSockName = cCopy.m_sSockName;
1112 m_sKeyFile = cCopy.m_sKeyFile;
1113 m_sDHParamFile = cCopy.m_sDHParamFile;
1114 m_sPemFile = cCopy.m_sPemFile;
1115 m_sCipherType = cCopy.m_sCipherType;
1116 m_sParentName = cCopy.m_sParentName;
1117 m_sSend = cCopy.m_sSend;
1118 m_sPemPass = cCopy.m_sPemPass;
1119 m_sLocalIP = cCopy.m_sLocalIP;
1120 m_sRemoteIP = cCopy.m_sRemoteIP;
1121 m_eCloseType = cCopy.m_eCloseType;
1122
1123 m_iMaxMilliSeconds = cCopy.m_iMaxMilliSeconds;
1124 m_iLastSendTime = cCopy.m_iLastSendTime;
1125 m_iBytesRead = cCopy.m_iBytesRead;
1126 m_iBytesWritten = cCopy.m_iBytesWritten;
1127 m_iStartTime = cCopy.m_iStartTime;
1128 m_iMaxBytes = cCopy.m_iMaxBytes;
1129 m_iLastSend = cCopy.m_iLastSend;
1130 m_uSendBufferPos = cCopy.m_uSendBufferPos;
1131 m_iMaxStoredBufferLength = cCopy.m_iMaxStoredBufferLength;
1132 m_iTimeoutType = cCopy.m_iTimeoutType;
1133
1134 m_address = cCopy.m_address;
1135 m_bindhost = cCopy.m_bindhost;
1136 m_bIsIPv6 = cCopy.m_bIsIPv6;
1137 m_bSkipConnect = cCopy.m_bSkipConnect;
1138 #ifdef HAVE_C_ARES
1139 FreeAres(); // Not copying this state, but making sure its nulled out
1140 m_iARESStatus = -1; // set it to unitialized
1141 m_pCurrAddr = NULL;
1142 #endif /* HAVE_C_ARES */
1143
1144 #ifdef HAVE_LIBSSL
1145 m_bNoSSLCompression = cCopy.m_bNoSSLCompression;
1146 m_bSSLCipherServerPreference = cCopy.m_bSSLCipherServerPreference;
1147 m_uDisableProtocols = cCopy.m_uDisableProtocols;
1148 m_iRequireClientCertFlags = cCopy.m_iRequireClientCertFlags;
1149 m_sSSLBuffer = cCopy.m_sSSLBuffer;
1150
1151 FREE_SSL();
1152 FREE_CTX(); // be sure to remove anything that was already here
1153 m_ssl = cCopy.m_ssl;
1154 m_ssl_ctx = cCopy.m_ssl_ctx;
1155
1156 m_pCerVerifyCB = cCopy.m_pCerVerifyCB;
1157
1158 if( m_ssl )
1159 {
1160 SSL_set_ex_data( m_ssl, GetCsockSSLIdx(), this );
1161 #if defined( SSL_CTX_set_tlsext_servername_callback )
1162 SSL_CTX_set_tlsext_servername_arg( m_ssl_ctx, this );
1163 #endif /* SSL_CTX_set_tlsext_servername_callback */
1164 }
1165
1166 #endif /* HAVE_LIBSSL */
1167
1168 #ifdef HAVE_ICU
1169 SetEncoding(cCopy.m_sEncoding);
1170 #endif
1171
1172 CleanupCrons();
1173 CleanupFDMonitors();
1174 m_vcCrons = cCopy.m_vcCrons;
1175 m_vcMonitorFD = cCopy.m_vcMonitorFD;
1176
1177 m_eConState = cCopy.m_eConState;
1178 m_sBindHost = cCopy.m_sBindHost;
1179 m_iCurBindCount = cCopy.m_iCurBindCount;
1180 m_iDNSTryCount = cCopy.m_iDNSTryCount;
1181
1182 }
1183
operator <<(const CS_STRING & s)1184 Csock & Csock::operator<<( const CS_STRING & s )
1185 {
1186 Write( s );
1187 return( *this );
1188 }
1189
operator <<(ostream & (* io)(ostream &))1190 Csock & Csock::operator<<( ostream & ( *io )( ostream & ) )
1191 {
1192 Write( "\r\n" );
1193 return( *this );
1194 }
1195
operator <<(int32_t i)1196 Csock & Csock::operator<<( int32_t i )
1197 {
1198 stringstream s;
1199 s << i;
1200 Write( s.str() );
1201 return( *this );
1202 }
1203
operator <<(uint32_t i)1204 Csock & Csock::operator<<( uint32_t i )
1205 {
1206 stringstream s;
1207 s << i;
1208 Write( s.str() );
1209 return( *this );
1210 }
1211
operator <<(int64_t i)1212 Csock & Csock::operator<<( int64_t i )
1213 {
1214 stringstream s;
1215 s << i;
1216 Write( s.str() );
1217 return( *this );
1218 }
1219
operator <<(uint64_t i)1220 Csock & Csock::operator<<( uint64_t i )
1221 {
1222 stringstream s;
1223 s << i;
1224 Write( s.str() );
1225 return( *this );
1226 }
1227
operator <<(float i)1228 Csock & Csock::operator<<( float i )
1229 {
1230 stringstream s;
1231 s << i;
1232 Write( s.str() );
1233 return( *this );
1234 }
1235
operator <<(double i)1236 Csock & Csock::operator<<( double i )
1237 {
1238 stringstream s;
1239 s << i;
1240 Write( s.str() );
1241 return( *this );
1242 }
1243
Connect()1244 bool Csock::Connect()
1245 {
1246 if( m_bSkipConnect )
1247 {
1248 // this was already called, so skipping now. this is to allow easy pass through
1249 if( m_eConState != CST_OK )
1250 {
1251 m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK );
1252 }
1253 return( true );
1254 }
1255
1256 #ifndef _WIN32
1257 set_non_blocking( m_iReadSock );
1258 #else
1259 if( !GetIPv6() )
1260 set_non_blocking( m_iReadSock );
1261 // non-blocking sockets on Win32 do *not* return ENETUNREACH/EHOSTUNREACH if there's no IPv6 gateway.
1262 // we need those error codes for the v4 fallback in GetAddrInfo!
1263 #endif /* _WIN32 */
1264
1265 m_iConnType = OUTBOUND;
1266
1267 int ret = -1;
1268 if( !GetIPv6() )
1269 ret = connect( m_iReadSock, ( struct sockaddr * )m_address.GetSockAddr(), m_address.GetSockAddrLen() );
1270 #ifdef HAVE_IPV6
1271 else
1272 ret = connect( m_iReadSock, ( struct sockaddr * )m_address.GetSockAddr6(), m_address.GetSockAddrLen6() );
1273 #endif /* HAVE_IPV6 */
1274 #ifndef _WIN32
1275 if( ret == -1 && GetSockError() != EINPROGRESS )
1276 #else
1277 if( ret == -1 && GetSockError() != EINPROGRESS && GetSockError() != WSAEWOULDBLOCK )
1278 #endif /* _WIN32 */
1279
1280 {
1281 CS_DEBUG( "Connect Failed. ERRNO [" << GetSockError() << "] FD [" << m_iReadSock << "]" );
1282 return( false );
1283 }
1284
1285 #ifdef _WIN32
1286 // do what we didn't do above since connect() is now over!
1287 if( GetIPv6() )
1288 set_non_blocking( m_iReadSock );
1289 #endif /* _WIN32 */
1290
1291 if( m_eConState != CST_OK )
1292 {
1293 m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK );
1294 }
1295
1296 return( true );
1297 }
1298
1299
1300 #ifdef HAVE_UNIX_SOCKET
prepare_sockaddr(struct sockaddr_un * addr,const CS_STRING & sPath)1301 static bool prepare_sockaddr(struct sockaddr_un * addr, const CS_STRING & sPath)
1302 {
1303 memset( addr, 0, sizeof(*addr) );
1304 addr->sun_family = AF_UNIX;
1305 if( sizeof(addr->sun_path) <= sPath.length() )
1306 return( false );
1307 memcpy( &addr->sun_path, sPath.c_str(), sPath.length() + 1 );
1308 return true;
1309 }
1310
ConnectUnix(const CS_STRING & sPath)1311 bool Csock::ConnectUnix( const CS_STRING & sPath )
1312 {
1313 if( m_iReadSock != m_iWriteSock )
1314 return( false );
1315 if( m_iReadSock == CS_INVALID_SOCK )
1316 m_iReadSock = m_iWriteSock = CreateSocket( false, true );
1317
1318 set_non_blocking( m_iReadSock );
1319 m_iConnType = OUTBOUND;
1320
1321 struct sockaddr_un addr;
1322 if( !prepare_sockaddr( &addr, sPath) )
1323 {
1324 CallSockError( EADDRNOTAVAIL );
1325 return( false );
1326 }
1327 if( connect( m_iReadSock, ( struct sockaddr * )&addr, sizeof(addr) ) == -1)
1328 {
1329 CS_DEBUG( "Connect Failed. ERRNO [" << GetSockError() << "] FD [" << m_iReadSock << "]" );
1330 return( false );
1331 }
1332
1333 if( m_eConState != CST_OK )
1334 {
1335 m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK );
1336 }
1337
1338 return( true );
1339 }
1340
ListenUnix(const CS_STRING & sBindFile,int iMaxConns,u_int iTimeout)1341 bool Csock::ListenUnix( const CS_STRING & sBindFile, int iMaxConns, u_int iTimeout )
1342 {
1343 m_iConnType = LISTENER;
1344 m_iTimeout = iTimeout;
1345 m_sBindHost = sBindFile;
1346 m_iMaxConns = iMaxConns;
1347
1348 SetConState( Csock::CST_OK );
1349
1350 // Should m_address be set up somehow?
1351
1352 struct sockaddr_un addr;
1353 if( !prepare_sockaddr( &addr, sBindFile) )
1354 {
1355 CallSockError( EADDRNOTAVAIL );
1356 return( false );
1357 }
1358
1359 m_iReadSock = m_iWriteSock = CreateSocket( true, true );
1360
1361 if( m_iReadSock == CS_INVALID_SOCK )
1362 {
1363 CallSockError( EBADF );
1364 return( false );
1365 }
1366
1367 if( bind( m_iReadSock, ( struct sockaddr * ) &addr, sizeof(addr) ) == -1 )
1368 {
1369 CallSockError( GetSockError() );
1370 return( false );
1371 }
1372
1373 if( listen( m_iReadSock, iMaxConns ) == -1 )
1374 {
1375 CallSockError( GetSockError() );
1376 return( false );
1377 }
1378
1379 // set it none blocking
1380 set_non_blocking( m_iReadSock );
1381
1382 // TODO: The following callback makes no sense here; should a
1383 // ListeningUnix() be added? We aren't doing anything asynchronous...
1384 //Listening( m_sBindHost, m_uPort );
1385
1386 return( true );
1387 }
1388 #endif
1389
Listen(uint16_t iPort,int iMaxConns,const CS_STRING & sBindHost,u_int iTimeout,bool bDetach)1390 bool Csock::Listen( uint16_t iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout, bool bDetach )
1391 {
1392 m_iConnType = LISTENER;
1393 m_iTimeout = iTimeout;
1394 m_sBindHost = sBindHost;
1395 m_iMaxConns = iMaxConns;
1396
1397 SetConState( Csock::CST_OK );
1398 if( !m_sBindHost.empty() )
1399 {
1400 if( bDetach )
1401 {
1402 int iRet = GetAddrInfo( m_sBindHost, m_address );
1403 if( iRet == ETIMEDOUT )
1404 {
1405 CallSockError( EADDRNOTAVAIL );
1406 return( false );
1407 }
1408 else if( iRet == EAGAIN )
1409 {
1410 SetConState( Csock::CST_BINDVHOST );
1411 return( true );
1412 }
1413 }
1414 else
1415 {
1416 // if not detaching, then must block to do DNS resolution, so might as well use internal resolver
1417 if( ::CS_GetAddrInfo( m_sBindHost, this, m_address ) != 0 )
1418 {
1419 CallSockError( EADDRNOTAVAIL );
1420 return( false );
1421 }
1422 }
1423 }
1424
1425 m_iReadSock = m_iWriteSock = CreateSocket( true );
1426
1427 if( m_iReadSock == CS_INVALID_SOCK )
1428 {
1429 CallSockError( EBADF );
1430 return( false );
1431 }
1432
1433 #ifdef HAVE_IPV6
1434 # ifdef _WIN32
1435 # ifndef IPPROTO_IPV6
1436 # define IPPROTO_IPV6 41 /* define for apps with _WIN32_WINNT < 0x0501 (XP) */
1437 # endif /* !IPPROTO_IPV6 */
1438 # ifndef IPV6_V6ONLY
1439 # define IPV6_V6ONLY 27
1440 # endif
1441 /* check for IPV6_V6ONLY support at runtime: only supported on Windows Vista or later */
1442 OSVERSIONINFOEX osvi = { 0 };
1443 DWORDLONG dwlConditionMask = 0;
1444
1445 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
1446 osvi.dwMajorVersion = 6;
1447
1448 VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
1449
1450 if( VerifyVersionInfo( &osvi, VER_MAJORVERSION, dwlConditionMask ) )
1451 {
1452 # endif /* _WIN32 */
1453 # ifdef IPV6_V6ONLY
1454 if( GetIPv6() )
1455 {
1456 // per RFC3493#5.3
1457 const int on = ( m_address.GetAFRequire() == CSSockAddr::RAF_INET6 ? 1 : 0 );
1458 if( setsockopt( m_iReadSock, IPPROTO_IPV6, IPV6_V6ONLY, ( char * )&on, sizeof( on ) ) != 0 )
1459 PERROR( "IPV6_V6ONLY" );
1460 }
1461 # endif /* IPV6_V6ONLY */
1462 # ifdef _WIN32
1463 }
1464 # endif /* _WIN32 */
1465 #endif /* HAVE_IPV6 */
1466
1467 m_address.SinFamily();
1468 m_address.SinPort( iPort );
1469 if( !GetIPv6() )
1470 {
1471 if( bind( m_iReadSock, ( struct sockaddr * ) m_address.GetSockAddr(), m_address.GetSockAddrLen() ) == -1 )
1472 {
1473 CallSockError( GetSockError() );
1474 return( false );
1475 }
1476 }
1477 #ifdef HAVE_IPV6
1478 else
1479 {
1480 if( bind( m_iReadSock, ( struct sockaddr * ) m_address.GetSockAddr6(), m_address.GetSockAddrLen6() ) == -1 )
1481 {
1482 CallSockError( GetSockError() );
1483 return( false );
1484 }
1485 }
1486 #endif /* HAVE_IPV6 */
1487
1488 if( listen( m_iReadSock, iMaxConns ) == -1 )
1489 {
1490 CallSockError( GetSockError() );
1491 return( false );
1492 }
1493
1494 // set it none blocking
1495 set_non_blocking( m_iReadSock );
1496 if( m_uPort == 0 || !m_sBindHost.empty() )
1497 {
1498 struct sockaddr_storage cAddr;
1499 socklen_t iAddrLen = sizeof( cAddr );
1500 if( getsockname( m_iReadSock, ( struct sockaddr * )&cAddr, &iAddrLen ) == 0 )
1501 {
1502 ConvertAddress( &cAddr, iAddrLen, m_sBindHost, &m_uPort );
1503 }
1504 }
1505 Listening( m_sBindHost, m_uPort );
1506
1507 return( true );
1508 }
1509
Accept(CS_STRING & sHost,uint16_t & iRPort)1510 cs_sock_t Csock::Accept( CS_STRING & sHost, uint16_t & iRPort )
1511 {
1512 cs_sock_t iSock = CS_INVALID_SOCK;
1513 struct sockaddr_storage cAddr;
1514 socklen_t iAddrLen = sizeof( cAddr );
1515 iSock = accept( m_iReadSock, ( struct sockaddr * )&cAddr, &iAddrLen );
1516 if( iSock != CS_INVALID_SOCK && getpeername( iSock, ( struct sockaddr * )&cAddr, &iAddrLen ) == 0 )
1517 {
1518 ConvertAddress( &cAddr, iAddrLen, sHost, &iRPort );
1519 }
1520
1521 if( iSock != CS_INVALID_SOCK )
1522 {
1523 // Make it close-on-exec
1524 set_close_on_exec( iSock );
1525
1526 // make it none blocking
1527 set_non_blocking( iSock );
1528
1529 if( !ConnectionFrom( sHost, iRPort ) )
1530 {
1531 CS_CLOSE( iSock );
1532 iSock = CS_INVALID_SOCK;
1533 }
1534
1535 }
1536
1537 return( iSock );
1538 }
1539
1540 #ifdef HAVE_LIBSSL
1541 #if defined( SSL_CTX_set_tlsext_servername_callback )
__SNICallBack(SSL * pSSL,int * piAD,void * pData)1542 static int __SNICallBack( SSL *pSSL, int *piAD, void *pData )
1543 {
1544 if( !pSSL || !pData )
1545 return( SSL_TLSEXT_ERR_NOACK );
1546
1547 const char * pServerName = SSL_get_servername( pSSL, TLSEXT_NAMETYPE_host_name );
1548 if( !pServerName )
1549 return( SSL_TLSEXT_ERR_NOACK );
1550
1551 Csock * pSock = static_cast<Csock *>( pData );
1552
1553 CS_STRING sDHParamFile, sKeyFile, sPemFile, sPemPass;
1554 if( !pSock->SNIConfigureServer( pServerName, sPemFile, sPemPass ) )
1555 return( SSL_TLSEXT_ERR_NOACK );
1556
1557 pSock->SetDHParamLocation( sDHParamFile );
1558 pSock->SetKeyLocation( sKeyFile );
1559 pSock->SetPemLocation( sPemFile );
1560 pSock->SetPemPass( sPemPass );
1561 SSL_CTX * pCTX = pSock->SetupServerCTX();
1562 SSL_set_SSL_CTX( pSSL, pCTX );
1563 pSock->SetCTXObject( pCTX, true );
1564 return( SSL_TLSEXT_ERR_OK );
1565 }
1566 #endif /* SSL_CTX_set_tlsext_servername_callback */
1567 #endif /* HAVE_LIBSSL */
1568
AcceptSSL()1569 bool Csock::AcceptSSL()
1570 {
1571 #ifdef HAVE_LIBSSL
1572 if( !m_ssl )
1573 if( !SSLServerSetup() )
1574 return( false );
1575
1576 #if defined( SSL_CTX_set_tlsext_servername_callback )
1577 SSL_CTX_set_tlsext_servername_callback( m_ssl_ctx, __SNICallBack );
1578 SSL_CTX_set_tlsext_servername_arg( m_ssl_ctx, this );
1579 #endif /* SSL_CTX_set_tlsext_servername_callback */
1580
1581 int err = SSL_accept( m_ssl );
1582
1583 if( err == 1 )
1584 {
1585 return( true );
1586 }
1587
1588 int sslErr = SSL_get_error( m_ssl, err );
1589
1590 if( sslErr == SSL_ERROR_WANT_READ || sslErr == SSL_ERROR_WANT_WRITE )
1591 return( true );
1592
1593 SSLErrors( __FILE__, __LINE__ );
1594
1595 #endif /* HAVE_LIBSSL */
1596
1597 return( false );
1598 }
1599
1600 #ifdef HAVE_LIBSSL
ConfigureCTXOptions(SSL_CTX * pCTX)1601 bool Csock::ConfigureCTXOptions( SSL_CTX * pCTX )
1602 {
1603 if( pCTX )
1604 {
1605 if( SSL_CTX_set_cipher_list( pCTX, m_sCipherType.c_str() ) <= 0 )
1606 {
1607 CS_DEBUG( "Could not assign cipher [" << m_sCipherType << "]" );
1608 return( false );
1609 }
1610
1611 long uCTXOptions = 0;
1612 if( m_uDisableProtocols > 0 )
1613 {
1614 #ifdef SSL_OP_NO_SSLv2
1615 if( EDP_SSLv2 & m_uDisableProtocols )
1616 uCTXOptions |= SSL_OP_NO_SSLv2;
1617 #endif /* SSL_OP_NO_SSLv2 */
1618 #ifdef SSL_OP_NO_SSLv3
1619 if( EDP_SSLv3 & m_uDisableProtocols )
1620 uCTXOptions |= SSL_OP_NO_SSLv3;
1621 #endif /* SSL_OP_NO_SSLv3 */
1622 #ifdef SSL_OP_NO_TLSv1
1623 if( EDP_TLSv1 & m_uDisableProtocols )
1624 uCTXOptions |= SSL_OP_NO_TLSv1;
1625 #endif /* SSL_OP_NO_TLSv1 */
1626 #ifdef SSL_OP_NO_TLSv1_1
1627 if( EDP_TLSv1_1 & m_uDisableProtocols )
1628 uCTXOptions |= SSL_OP_NO_TLSv1_1;
1629 #endif /* SSL_OP_NO_TLSv1 */
1630 #ifdef SSL_OP_NO_TLSv1_2
1631 if( EDP_TLSv1_2 & m_uDisableProtocols )
1632 uCTXOptions |= SSL_OP_NO_TLSv1_2;
1633 #endif /* SSL_OP_NO_TLSv1_2 */
1634 }
1635 #ifdef SSL_OP_NO_COMPRESSION
1636 if( m_bNoSSLCompression )
1637 uCTXOptions |= SSL_OP_NO_COMPRESSION;
1638 #endif /* SSL_OP_NO_COMPRESSION */
1639 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
1640 if( m_bSSLCipherServerPreference )
1641 uCTXOptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
1642 #endif /* SSL_OP_CIPHER_SERVER_PREFERENCE */
1643 if( uCTXOptions )
1644 SSL_CTX_set_options( pCTX, uCTXOptions );
1645 }
1646 return true;
1647 }
1648 #endif /* HAVE_LIBSSL */
1649
1650
1651 #ifdef HAVE_LIBSSL
GetSSLCTX(int iMethod)1652 static SSL_CTX * GetSSLCTX( int iMethod )
1653 {
1654 const SSL_METHOD *pMethod = NULL;
1655
1656 #ifdef HAVE_FLEXIBLE_TLS_METHOD
1657 int iProtoVersion = 0;
1658 pMethod = TLS_method();
1659 #else
1660 pMethod = SSLv23_method();
1661 #endif // HAVE_FLEXIBLE_TLS_METHOD
1662
1663 switch( iMethod )
1664 {
1665 case Csock::TLS:
1666 break; // defaults already set above, anything else can either match a case or fall through and use defaults anyway
1667 #ifdef HAVE_FLEXIBLE_TLS_METHOD
1668 #ifndef OPENSSL_NO_TLS1_2
1669 case Csock::TLS12:
1670 iProtoVersion = TLS1_2_VERSION;
1671 break;
1672 #endif /* OPENSSL_NO_TLS1_2 */
1673 #ifndef OPENSSL_NO_TLS1_1
1674 case Csock::TLS11:
1675 iProtoVersion = TLS1_1_VERSION;
1676 break;
1677 #endif /* OPENSSL_NO_TLS1_1 */
1678 #ifndef OPENSSL_NO_TLS1
1679 case Csock::TLS1:
1680 iProtoVersion = TLS1_VERSION;
1681 break;
1682 #endif /* OPENSSL_NO_TLS1 */
1683 #ifndef OPENSSL_NO_SSL3
1684 case Csock::SSL3:
1685 iProtoVersion = SSL3_VERSION;
1686 break;
1687 #endif /* OPENSSL_NO_SSL3 */
1688 #ifndef OPENSSL_NO_SSL2
1689 case Csock::SSL2:
1690 pMethod = SSLv2_method();
1691 break;
1692 #endif /* OPENSSL_NO_SSL2 */
1693
1694
1695 #else /* HAVE_FLEXIBLE_TLS_METHOD */
1696
1697
1698 #ifndef OPENSSL_NO_TLS1_2
1699 case Csock::TLS12:
1700 pMethod = TLSv1_2_method();
1701 break;
1702 #endif /* OPENSSL_NO_TLS1_2 */
1703 #ifndef OPENSSL_NO_TLS1_1
1704 case Csock::TLS11:
1705 pMethod = TLSv1_1_method();
1706 break;
1707 #endif /* OPENSSL_NO_TLS1_1 */
1708 #ifndef OPENSSL_NO_TLS1
1709 case Csock::TLS1:
1710 pMethod = TLSv1_method();
1711 break;
1712 #endif /* OPENSSL_NO_TLS1 */
1713 #ifndef OPENSSL_NO_SSL3
1714 case Csock::SSL3:
1715 pMethod = SSLv3_method();
1716 break;
1717 #endif /* OPENSSL_NO_SSL3 */
1718 #ifndef OPENSSL_NO_SSL2
1719 case Csock::SSL2:
1720 pMethod = SSLv2_method();
1721 break;
1722 #endif /* OPENSSL_NO_SSL2 */
1723 #endif /* HAVE_FLEXIBLE_TLS_METHOD */
1724
1725 default:
1726 CS_DEBUG( "WARNING: SSL Client Method other than SSLv23 specified, but has passed through" );
1727 break;
1728 }
1729
1730 SSL_CTX * pCTX = SSL_CTX_new( pMethod );
1731 if( !pCTX )
1732 {
1733 CS_DEBUG( "WARNING: GetSSLCTX failed!" );
1734 return( NULL );
1735 }
1736
1737 #ifdef HAVE_FLEXIBLE_TLS_METHOD
1738 if( iProtoVersion )
1739 {
1740 SSL_CTX_set_min_proto_version( pCTX, iProtoVersion );
1741 SSL_CTX_set_max_proto_version( pCTX, iProtoVersion );
1742 }
1743 #endif /* HAVE_FLEXIBLE_TLS_METHOD */
1744
1745 return( pCTX );
1746 }
1747 #endif
1748
SSLClientSetup()1749 bool Csock::SSLClientSetup()
1750 {
1751 #ifdef HAVE_LIBSSL
1752 m_bUseSSL = true;
1753 FREE_SSL();
1754 FREE_CTX();
1755
1756 #ifdef _WIN64
1757 if( m_iReadSock != ( int )m_iReadSock || m_iWriteSock != ( int )m_iWriteSock )
1758 {
1759 // sanity check the FD to be sure its compatible with openssl
1760 CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
1761 return( false );
1762 }
1763 #endif /* _WIN64 */
1764
1765 m_ssl_ctx = GetSSLCTX( m_iMethod );
1766 if( !m_ssl_ctx )
1767 {
1768 CS_DEBUG( "WARNING: Failed to retrieve a valid ctx" );
1769 return( false );
1770 }
1771
1772 SSL_CTX_set_default_verify_paths( m_ssl_ctx );
1773
1774 if( !m_sPemFile.empty() )
1775 {
1776 // are we sending a client cerificate ?
1777 SSL_CTX_set_default_passwd_cb( m_ssl_ctx, _PemPassCB );
1778 SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, ( void * )this );
1779
1780 //
1781 // set up the CTX
1782 if( SSL_CTX_use_certificate_file( m_ssl_ctx, m_sPemFile.c_str() , SSL_FILETYPE_PEM ) <= 0 )
1783 {
1784 CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" );
1785 SSLErrors( __FILE__, __LINE__ );
1786 }
1787 CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile;
1788 if( SSL_CTX_use_PrivateKey_file( m_ssl_ctx, privKeyFile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
1789 {
1790 CS_DEBUG( "Error with SSLKey file [" << privKeyFile << "]" );
1791 SSLErrors( __FILE__, __LINE__ );
1792 }
1793 }
1794
1795 if( !ConfigureCTXOptions( m_ssl_ctx ) )
1796 {
1797 SSL_CTX_free( m_ssl_ctx );
1798 m_ssl_ctx = NULL;
1799 return( false );
1800 }
1801
1802 m_ssl = SSL_new( m_ssl_ctx );
1803 if( !m_ssl )
1804 return( false );
1805
1806 SSL_set_rfd( m_ssl, ( int )m_iReadSock );
1807 SSL_set_wfd( m_ssl, ( int )m_iWriteSock );
1808 SSL_set_verify( m_ssl, SSL_VERIFY_PEER, m_pCerVerifyCB );
1809 SSL_set_info_callback( m_ssl, _InfoCallback );
1810 SSL_set_ex_data( m_ssl, GetCsockSSLIdx(), this );
1811
1812 #if defined( SSL_set_tlsext_host_name )
1813 CS_STRING sSNIHostname;
1814 if( SNIConfigureClient( sSNIHostname ) )
1815 SSL_set_tlsext_host_name( m_ssl, sSNIHostname.c_str() );
1816 #endif /* SSL_set_tlsext_host_name */
1817
1818 SSLFinishSetup( m_ssl );
1819 return( true );
1820 #else
1821 return( false );
1822
1823 #endif /* HAVE_LIBSSL */
1824 }
1825
1826 #ifdef HAVE_LIBSSL
SetupServerCTX()1827 SSL_CTX * Csock::SetupServerCTX()
1828 {
1829 SSL_CTX * pCTX = GetSSLCTX( m_iMethod );
1830 if( !pCTX )
1831 {
1832 CS_DEBUG( "WARNING: Failed to retrieve a valid ctx" );
1833 return( NULL );
1834 }
1835
1836 SSL_CTX_set_default_verify_paths( pCTX );
1837
1838 // set the pemfile password
1839 SSL_CTX_set_default_passwd_cb( pCTX, _PemPassCB );
1840 SSL_CTX_set_default_passwd_cb_userdata( pCTX, ( void * )this );
1841
1842 if( m_sPemFile.empty() || access( m_sPemFile.c_str(), R_OK ) != 0 )
1843 {
1844 CS_DEBUG( "Empty, missing, or bad pemfile ... [" << m_sPemFile << "]" );
1845 SSL_CTX_free( pCTX );
1846 return( NULL );
1847 }
1848
1849 if( ! m_sKeyFile.empty() && access( m_sKeyFile.c_str(), R_OK ) != 0 )
1850 {
1851 CS_DEBUG( "Bad keyfile ... [" << m_sKeyFile << "]" );
1852 SSL_CTX_free( pCTX );
1853 return( NULL );
1854 }
1855
1856 //
1857 // set up the CTX
1858 if( SSL_CTX_use_certificate_chain_file( pCTX, m_sPemFile.c_str() ) <= 0 )
1859 {
1860 CS_DEBUG( "Error with SSLCert file [" << m_sPemFile << "]" );
1861 SSLErrors( __FILE__, __LINE__ );
1862 SSL_CTX_free( pCTX );
1863 return( NULL );
1864 }
1865
1866 CS_STRING privKeyFile = m_sKeyFile.empty() ? m_sPemFile : m_sKeyFile;
1867 if( SSL_CTX_use_PrivateKey_file( pCTX, privKeyFile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
1868 {
1869 CS_DEBUG( "Error with SSLKey file [" << privKeyFile << "]" );
1870 SSLErrors( __FILE__, __LINE__ );
1871 SSL_CTX_free( pCTX );
1872 return( NULL );
1873 }
1874
1875 // check to see if this pem file contains a DH structure for use with DH key exchange
1876 // https://github.com/znc/znc/pull/46
1877 CS_STRING DHParamFile = m_sDHParamFile.empty() ? m_sPemFile : m_sDHParamFile;
1878 FILE *dhParamsFile = fopen( DHParamFile.c_str(), "r" );
1879 if( !dhParamsFile )
1880 {
1881 CS_DEBUG( "Error with DHParam file [" << DHParamFile << "]" );
1882 SSL_CTX_free( pCTX );
1883 return( NULL );
1884 }
1885
1886 DH * dhParams = PEM_read_DHparams( dhParamsFile, NULL, NULL, NULL );
1887 fclose( dhParamsFile );
1888 if( dhParams )
1889 {
1890 SSL_CTX_set_options( pCTX, SSL_OP_SINGLE_DH_USE );
1891 if( !SSL_CTX_set_tmp_dh( pCTX, dhParams ) )
1892 {
1893 CS_DEBUG( "Error setting ephemeral DH parameters from [" << m_sPemFile << "]" );
1894 SSLErrors( __FILE__, __LINE__ );
1895 DH_free( dhParams );
1896 SSL_CTX_free( pCTX );
1897 return( NULL );
1898 }
1899 DH_free( dhParams );
1900 }
1901 else
1902 {
1903 // Presumably PEM_read_DHparams failed, as there was no DH structure. Clearing those errors here so they are removed off the stack
1904 ERR_clear_error();
1905 }
1906 #ifndef OPENSSL_NO_ECDH
1907 // Errors for the following block are non-fatal (ECDHE is nice to have
1908 // but not a requirement)
1909 #ifndef OPENSSL_IS_BORINGSSL
1910 // BoringSSL does this thing automatically
1911 #if defined( SSL_CTX_set_ecdh_auto )
1912 // Auto-select sensible curve
1913 if( !SSL_CTX_set_ecdh_auto( pCTX , 1 ) )
1914 ERR_clear_error();
1915 #elif defined( SSL_CTX_set_tmp_ecdh )
1916 // Use a standard, widely-supported curve
1917 EC_KEY * ecdh = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
1918 if( ecdh )
1919 {
1920 if( !SSL_CTX_set_tmp_ecdh( pCTX, ecdh ) )
1921 ERR_clear_error();
1922 EC_KEY_free( ecdh );
1923 }
1924 else
1925 {
1926 ERR_clear_error();
1927 }
1928 #endif /* SSL_CTX_set_tmp_ecdh */
1929 #endif /* !OPENSSL_IS_BORINGSSL */
1930 #endif /* OPENSSL_NO_ECDH */
1931
1932 if( !ConfigureCTXOptions( pCTX ) )
1933 {
1934 SSL_CTX_free( pCTX );
1935 return( NULL );
1936 }
1937 return( pCTX );
1938 }
1939 #endif /* HAVE_LIBSSL */
1940
SSLServerSetup()1941 bool Csock::SSLServerSetup()
1942 {
1943 #ifdef HAVE_LIBSSL
1944 m_bUseSSL = true;
1945 FREE_SSL();
1946 FREE_CTX();
1947
1948 #ifdef _WIN64
1949 if( m_iReadSock != ( int )m_iReadSock || m_iWriteSock != ( int )m_iWriteSock )
1950 {
1951 // sanity check the FD to be sure its compatible with openssl
1952 CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
1953 return( false );
1954 }
1955 #endif /* _WIN64 */
1956
1957 m_ssl_ctx = SetupServerCTX();
1958
1959 //
1960 // setup the SSL
1961 m_ssl = SSL_new( m_ssl_ctx );
1962 if( !m_ssl )
1963 return( false );
1964
1965 #if defined( SSL_MODE_SEND_FALLBACK_SCSV )
1966 SSL_set_mode( m_ssl, SSL_MODE_SEND_FALLBACK_SCSV );
1967 #endif /* SSL_MODE_SEND_FALLBACK_SCSV */
1968
1969 // Call for client Verification
1970 SSL_set_rfd( m_ssl, ( int )m_iReadSock );
1971 SSL_set_wfd( m_ssl, ( int )m_iWriteSock );
1972 SSL_set_accept_state( m_ssl );
1973 if( m_iRequireClientCertFlags )
1974 {
1975 SSL_set_verify( m_ssl, m_iRequireClientCertFlags, m_pCerVerifyCB );
1976 }
1977 SSL_set_info_callback( m_ssl, _InfoCallback );
1978 SSL_set_ex_data( m_ssl, GetCsockSSLIdx(), this );
1979
1980 SSLFinishSetup( m_ssl );
1981 return( true );
1982 #else
1983 return( false );
1984 #endif /* HAVE_LIBSSL */
1985 }
1986
StartTLS()1987 bool Csock::StartTLS()
1988 {
1989 if( m_iConnType == INBOUND )
1990 return( AcceptSSL() );
1991 if( m_iConnType == OUTBOUND )
1992 return( ConnectSSL() );
1993 CS_DEBUG( "Invalid connection type with StartTLS" );
1994 return( false );
1995 }
1996
ConnectSSL()1997 bool Csock::ConnectSSL()
1998 {
1999 #ifdef HAVE_LIBSSL
2000 if( m_iReadSock == CS_INVALID_SOCK )
2001 return( false ); // this should be long passed at this point
2002 if( !m_ssl && !SSLClientSetup() )
2003 return( false );
2004
2005 bool bPass = true;
2006
2007 int iErr = SSL_connect( m_ssl );
2008 if( iErr != 1 )
2009 {
2010 int sslErr = SSL_get_error( m_ssl, iErr );
2011 bPass = false;
2012 if( sslErr == SSL_ERROR_WANT_READ || sslErr == SSL_ERROR_WANT_WRITE )
2013 bPass = true;
2014 #ifdef _WIN32
2015 else if( sslErr == SSL_ERROR_SYSCALL && iErr < 0 && GetLastError() == WSAENOTCONN )
2016 {
2017 // this seems to be an issue with win32 only. I've seen it happen on slow connections
2018 // the issue is calling this before select(), which isn't a problem on unix. Allowing this
2019 // to pass in this case is fine because subsequent ssl transactions will occur and the handshake
2020 // will finish. At this point, its just instantiating the handshake.
2021 bPass = true;
2022 }
2023 #endif /* _WIN32 */
2024 }
2025 else
2026 {
2027 bPass = true;
2028 }
2029
2030 if( m_eConState != CST_OK )
2031 m_eConState = CST_OK;
2032 return( bPass );
2033 #else
2034 return( false );
2035 #endif /* HAVE_LIBSSL */
2036 }
2037
2038 #ifdef HAVE_ICU
icuConv(const CS_STRING & src,CS_STRING & tgt,UConverter * cnv_in,UConverter * cnv_out)2039 inline bool icuConv( const CS_STRING& src, CS_STRING& tgt, UConverter* cnv_in, UConverter* cnv_out )
2040 {
2041 const char* indata = src.c_str();
2042 const char* indataend = indata + src.length();
2043 tgt.clear();
2044 char buf[100];
2045 UChar pivotStart[100];
2046 UChar* pivotSource = pivotStart;
2047 UChar* pivotTarget = pivotStart;
2048 UChar* pivotLimit = pivotStart + sizeof pivotStart / sizeof pivotStart[0];
2049 const char* outdataend = buf + sizeof buf;
2050 bool reset = true;
2051 while( true )
2052 {
2053 char* outdata = buf;
2054 UErrorCode e = U_ZERO_ERROR;
2055 ucnv_convertEx( cnv_out, cnv_in, &outdata, outdataend, &indata, indataend, pivotStart, &pivotSource, &pivotTarget, pivotLimit, reset, true, &e );
2056 reset = false;
2057 if( U_SUCCESS( e ) )
2058 {
2059 if( e != U_ZERO_ERROR )
2060 {
2061 CS_DEBUG( "Warning during converting string encoding: " << u_errorName( e ) );
2062 }
2063 tgt.append( buf, outdata - buf );
2064 break;
2065 }
2066 if( e == U_BUFFER_OVERFLOW_ERROR )
2067 {
2068 tgt.append( buf, outdata - buf );
2069 continue;
2070 }
2071 CS_DEBUG( "Error during converting string encoding: " << u_errorName( e ) );
2072 return false;
2073 }
2074 return true;
2075 }
2076
isUTF8(const CS_STRING & src,CS_STRING & target)2077 static bool isUTF8( const CS_STRING& src, CS_STRING& target)
2078 {
2079 UErrorCode e = U_ZERO_ERROR;
2080 // Convert to UTF-16 without actually converting. This will still count
2081 // the number of output characters, so we either get
2082 // U_BUFFER_OVERFLOW_ERROR or U_INVALID_CHAR_FOUND.
2083 u_strFromUTF8( NULL, 0, NULL, src.c_str(), (int32_t) src.length(), &e );
2084 if( e != U_BUFFER_OVERFLOW_ERROR)
2085 return false;
2086 target = src;
2087 return true;
2088 }
2089 #endif /* HAVE_ICU */
2090
AllowWrite(uint64_t & iNOW) const2091 bool Csock::AllowWrite( uint64_t & iNOW ) const
2092 {
2093 if( m_iMaxBytes > 0 && m_iMaxMilliSeconds > 0 )
2094 {
2095 if( iNOW == 0 )
2096 iNOW = millitime();
2097
2098 if( m_iLastSend < m_iMaxBytes )
2099 return( true ); // allow sending if our out buffer was less than what we can send
2100 if( ( iNOW - m_iLastSendTime ) < m_iMaxMilliSeconds )
2101 return( false );
2102 }
2103 return( true );
2104 }
2105
ShrinkSendBuff()2106 void Csock::ShrinkSendBuff()
2107 {
2108 if( m_uSendBufferPos > 0 )
2109 {
2110 // just doing this to keep m_sSend from growing out of control
2111 m_sSend.erase( 0, m_uSendBufferPos );
2112 m_uSendBufferPos = 0;
2113 }
2114 }
IncBuffPos(size_t uBytes)2115 void Csock::IncBuffPos( size_t uBytes )
2116 {
2117 m_uSendBufferPos += uBytes;
2118 if( m_uSendBufferPos >= m_sSend.size() )
2119 {
2120 m_uSendBufferPos = 0;
2121 m_sSend.clear();
2122 }
2123 }
2124
Write(const char * data,size_t len)2125 bool Csock::Write( const char *data, size_t len )
2126 {
2127 if( len > 0 )
2128 {
2129 ShrinkSendBuff();
2130 m_sSend.append( data, len );
2131 }
2132
2133 if( m_sSend.empty() )
2134 return( true );
2135
2136 if( m_eConState != CST_OK )
2137 return( true );
2138
2139 // rate shaping
2140 size_t iBytesToSend = 0;
2141
2142 size_t uBytesInSend = m_sSend.size() - m_uSendBufferPos;
2143
2144 #ifdef HAVE_LIBSSL
2145 if( m_bUseSSL && m_sSSLBuffer.empty() && !m_bsslEstablished )
2146 {
2147 // to keep openssl from spinning, just initiate the connection with 1 byte so the connection establishes faster
2148 iBytesToSend = 1;
2149 }
2150 else
2151 #endif /* HAVE_LIBSSL */
2152 if( m_iMaxBytes > 0 && m_iMaxMilliSeconds > 0 )
2153 {
2154 uint64_t iNOW = millitime();
2155 // figure out the shaping here
2156 // if NOW - m_iLastSendTime > m_iMaxMilliSeconds then send a full length of ( iBytesToSend )
2157 if( ( iNOW - m_iLastSendTime ) > m_iMaxMilliSeconds )
2158 {
2159 m_iLastSendTime = iNOW;
2160 iBytesToSend = m_iMaxBytes;
2161 m_iLastSend = 0;
2162 }
2163 else // otherwise send m_iMaxBytes - m_iLastSend
2164 iBytesToSend = m_iMaxBytes - m_iLastSend;
2165
2166 // take which ever is lesser
2167 if( uBytesInSend < iBytesToSend )
2168 iBytesToSend = uBytesInSend;
2169
2170 // add up the bytes sent
2171 m_iLastSend += iBytesToSend;
2172
2173 // so, are we ready to send anything ?
2174 if( iBytesToSend == 0 )
2175 return( true );
2176 }
2177 else
2178 {
2179 iBytesToSend = uBytesInSend;
2180 }
2181
2182 #ifdef HAVE_LIBSSL
2183 if( m_bUseSSL )
2184 {
2185 if( !m_ssl )
2186 {
2187 CS_DEBUG( "SSL object is NULL but m_bUseSSL is true" );
2188 return( false );
2189 }
2190
2191 if( m_sSSLBuffer.empty() ) // on retrying to write data, ssl wants the data in the SAME spot and the SAME size
2192 m_sSSLBuffer.append( m_sSend.data() + m_uSendBufferPos, iBytesToSend );
2193
2194 int iErr = SSL_write( m_ssl, m_sSSLBuffer.data(), ( int )m_sSSLBuffer.length() );
2195
2196 if( iErr < 0 && GetSockError() == ECONNREFUSED )
2197 {
2198 // If ret == -1, the underlying BIO reported an I/O error (man SSL_get_error)
2199 ConnectionRefused();
2200 return( false );
2201 }
2202
2203 switch( SSL_get_error( m_ssl, iErr ) )
2204 {
2205 case SSL_ERROR_NONE:
2206 m_bsslEstablished = true;
2207 // all ok
2208 break;
2209
2210 case SSL_ERROR_ZERO_RETURN:
2211 {
2212 // weird closer alert
2213 return( false );
2214 }
2215
2216 case SSL_ERROR_WANT_READ:
2217 // retry
2218 break;
2219
2220 case SSL_ERROR_WANT_WRITE:
2221 // retry
2222 break;
2223
2224 case SSL_ERROR_SSL:
2225 {
2226 SSLErrors( __FILE__, __LINE__ );
2227 return( false );
2228 }
2229 }
2230
2231 if( iErr > 0 )
2232 {
2233 m_sSSLBuffer.clear();
2234 IncBuffPos( ( size_t )iErr );
2235 // reset the timer on successful write (we have to set it here because the write
2236 // bit might not always be set, so need to trigger)
2237 if( TMO_WRITE & GetTimeoutType() )
2238 ResetTimer();
2239
2240 m_iBytesWritten += ( uint64_t )iErr;
2241 }
2242
2243 return( true );
2244 }
2245 #endif /* HAVE_LIBSSL */
2246 #ifdef _WIN32
2247 cs_ssize_t bytes = send( m_iWriteSock, m_sSend.data() + m_uSendBufferPos, iBytesToSend, 0 );
2248 #else
2249 cs_ssize_t bytes = write( m_iWriteSock, m_sSend.data() + m_uSendBufferPos, iBytesToSend );
2250 #endif /* _WIN32 */
2251
2252 if( bytes == -1 && GetSockError() == ECONNREFUSED )
2253 {
2254 ConnectionRefused();
2255 return( false );
2256 }
2257
2258 #ifdef _WIN32
2259 if( bytes <= 0 && GetSockError() != WSAEWOULDBLOCK )
2260 return( false );
2261 #else
2262 if( bytes <= 0 && GetSockError() != EAGAIN )
2263 return( false );
2264 #endif /* _WIN32 */
2265
2266 // delete the bytes we sent
2267 if( bytes > 0 )
2268 {
2269 IncBuffPos( ( size_t )bytes );
2270 if( TMO_WRITE & GetTimeoutType() )
2271 ResetTimer(); // reset the timer on successful write
2272 m_iBytesWritten += ( uint64_t )bytes;
2273 }
2274
2275 return( true );
2276 }
2277
Write(const CS_STRING & sData)2278 bool Csock::Write( const CS_STRING & sData )
2279 {
2280 #ifdef HAVE_ICU
2281 if( m_cnvExt && !m_cnvSendUTF8 )
2282 {
2283 CS_STRING sBinary;
2284 if( icuConv( sData, sBinary, m_cnvInt, m_cnvExt ) )
2285 {
2286 return( Write( sBinary.c_str(), sBinary.length() ) );
2287 }
2288 }
2289 // can't convert our UTF-8 string to that encoding, just put it as is...
2290 #endif /* HAVE_ICU */
2291 return( Write( sData.c_str(), sData.length() ) );
2292 }
2293
Read(char * data,size_t len)2294 cs_ssize_t Csock::Read( char *data, size_t len )
2295 {
2296 cs_ssize_t bytes = 0;
2297
2298 if( IsReadPaused() && SslIsEstablished() )
2299 return( READ_EAGAIN ); // allow the handshake to complete first
2300
2301 #ifdef HAVE_LIBSSL
2302 if( m_bUseSSL )
2303 {
2304 if( !m_ssl )
2305 {
2306 CS_DEBUG( "SSL object is NULL but m_bUseSSL is true" );
2307 return( READ_ERR );
2308 }
2309
2310 bytes = SSL_read( m_ssl, data, ( int )len );
2311 if( bytes >= 0 )
2312 m_bsslEstablished = true; // this means all is good in the realm of ssl
2313 }
2314 else
2315 #endif /* HAVE_LIBSSL */
2316 #ifdef _WIN32
2317 bytes = recv( m_iReadSock, data, len, 0 );
2318 #else
2319 bytes = read( m_iReadSock, data, len );
2320 #endif /* _WIN32 */
2321 if( bytes == -1 )
2322 {
2323 if( GetSockError() == ECONNREFUSED )
2324 return( READ_CONNREFUSED );
2325
2326 if( GetSockError() == ETIMEDOUT )
2327 return( READ_TIMEDOUT );
2328
2329 if( GetSockError() == EINTR || GetSockError() == EAGAIN )
2330 return( READ_EAGAIN );
2331
2332 #ifdef _WIN32
2333 if( GetSockError() == WSAEWOULDBLOCK )
2334 return( READ_EAGAIN );
2335 #endif /* _WIN32 */
2336
2337 #ifdef HAVE_LIBSSL
2338 if( m_ssl )
2339 {
2340 int iErr = SSL_get_error( m_ssl, ( int )bytes );
2341 if( iErr != SSL_ERROR_WANT_READ && iErr != SSL_ERROR_WANT_WRITE )
2342 return( READ_ERR );
2343 else
2344 return( READ_EAGAIN );
2345 }
2346 #else
2347 return( READ_ERR );
2348 #endif /* HAVE_LIBSSL */
2349 }
2350
2351 if( bytes > 0 ) // becareful not to add negative bytes :P
2352 m_iBytesRead += ( uint64_t )bytes;
2353
2354 return( bytes );
2355 }
2356
GetLocalIP() const2357 CS_STRING Csock::GetLocalIP() const
2358 {
2359 if( !m_sLocalIP.empty() )
2360 return( m_sLocalIP );
2361
2362 cs_sock_t iSock = GetSock();
2363
2364 if( iSock == CS_INVALID_SOCK )
2365 return( "" );
2366
2367 struct sockaddr_storage cAddr;
2368 socklen_t iAddrLen = sizeof( cAddr );
2369 if( getsockname( iSock, ( struct sockaddr * )&cAddr, &iAddrLen ) == 0 )
2370 {
2371 ConvertAddress( &cAddr, iAddrLen, m_sLocalIP, &m_iLocalPort );
2372 }
2373
2374 return( m_sLocalIP );
2375 }
2376
GetRemoteIP() const2377 CS_STRING Csock::GetRemoteIP() const
2378 {
2379 if( !m_sRemoteIP.empty() )
2380 return( m_sRemoteIP );
2381
2382 cs_sock_t iSock = GetSock();
2383
2384 if( iSock == CS_INVALID_SOCK )
2385 return( "" );
2386
2387 struct sockaddr_storage cAddr;
2388 socklen_t iAddrLen = sizeof( cAddr );
2389 if( getpeername( iSock, ( struct sockaddr * )&cAddr, &iAddrLen ) == 0 )
2390 {
2391 ConvertAddress( &cAddr, iAddrLen, m_sRemoteIP, &m_iRemotePort );
2392 }
2393
2394 return( m_sRemoteIP );
2395 }
2396
IsConnected() const2397 bool Csock::IsConnected() const { return( m_bIsConnected ); }
SetIsConnected(bool b)2398 void Csock::SetIsConnected( bool b ) { m_bIsConnected = b; }
2399
GetRSock()2400 cs_sock_t & Csock::GetRSock() { return( m_iReadSock ); }
GetRSock() const2401 const cs_sock_t & Csock::GetRSock() const { return( m_iReadSock ); }
SetRSock(cs_sock_t iSock)2402 void Csock::SetRSock( cs_sock_t iSock ) { m_iReadSock = iSock; }
GetWSock()2403 cs_sock_t & Csock::GetWSock() { return( m_iWriteSock ); }
GetWSock() const2404 const cs_sock_t & Csock::GetWSock() const { return( m_iWriteSock ); }
SetWSock(cs_sock_t iSock)2405 void Csock::SetWSock( cs_sock_t iSock ) { m_iWriteSock = iSock; }
SetSock(cs_sock_t iSock)2406 void Csock::SetSock( cs_sock_t iSock ) { m_iWriteSock = iSock; m_iReadSock = iSock; }
GetSock()2407 cs_sock_t & Csock::GetSock() { return( m_iReadSock ); }
GetSock() const2408 const cs_sock_t & Csock::GetSock() const { return( m_iReadSock ); }
ResetTimer()2409 void Csock::ResetTimer() { m_iLastCheckTimeoutTime = 0; m_iTcount = 0; }
PauseRead()2410 void Csock::PauseRead() { m_bPauseRead = true; }
IsReadPaused() const2411 bool Csock::IsReadPaused() const { return( m_bPauseRead ); }
2412
UnPauseRead()2413 void Csock::UnPauseRead()
2414 {
2415 m_bPauseRead = false;
2416 ResetTimer();
2417 PushBuff( "", 0, true );
2418 }
2419
SetTimeout(int iTimeout,u_int iTimeoutType)2420 void Csock::SetTimeout( int iTimeout, u_int iTimeoutType )
2421 {
2422 m_iTimeoutType = iTimeoutType;
2423 m_iTimeout = iTimeout;
2424 }
2425
CallSockError(int iErrno,const CS_STRING & sDescription)2426 void Csock::CallSockError( int iErrno, const CS_STRING & sDescription )
2427 {
2428 if( !sDescription.empty() )
2429 {
2430 SockError( iErrno, sDescription );
2431 }
2432 else
2433 {
2434 char szBuff[0xff];
2435 SockError( iErrno, CS_StrError( iErrno, szBuff, 0xff ) );
2436 }
2437 }
SetTimeoutType(u_int iTimeoutType)2438 void Csock::SetTimeoutType( u_int iTimeoutType ) { m_iTimeoutType = iTimeoutType; }
GetTimeout() const2439 int Csock::GetTimeout() const { return m_iTimeout; }
GetTimeoutType() const2440 u_int Csock::GetTimeoutType() const { return( m_iTimeoutType ); }
2441
CheckTimeout(time_t iNow)2442 bool Csock::CheckTimeout( time_t iNow )
2443 {
2444 if( m_iLastCheckTimeoutTime == 0 )
2445 {
2446 m_iLastCheckTimeoutTime = iNow;
2447 return( false );
2448 }
2449
2450 if( IsReadPaused() )
2451 return( false );
2452
2453 time_t iDiff = 0;
2454 if( iNow > m_iLastCheckTimeoutTime )
2455 {
2456 iDiff = iNow - m_iLastCheckTimeoutTime;
2457 }
2458 else
2459 {
2460 // this is weird, but its possible if someone changes a clock and it went back in time, this essentially has to reset the last check
2461 // the worst case scenario is the timeout is about to it and the clock changes, it would then cause
2462 // this to pass over the last half the time
2463 m_iLastCheckTimeoutTime = iNow;
2464 }
2465
2466 if( m_iTimeout > 0 )
2467 {
2468 // this is basically to help stop a clock adjust ahead, stuff could reset immediatly on a clock jump
2469 // otherwise
2470 time_t iRealTimeout = m_iTimeout;
2471 if( iRealTimeout <= 1 )
2472 m_iTcount++;
2473 else if( m_iTcount == 0 )
2474 iRealTimeout /= 2;
2475 if( iDiff >= iRealTimeout )
2476 {
2477 if( m_iTcount == 0 )
2478 m_iLastCheckTimeoutTime = iNow - iRealTimeout;
2479 if( m_iTcount++ >= 1 )
2480 {
2481 Timeout();
2482 return( true );
2483 }
2484 }
2485 }
2486 return( false );
2487 }
2488
PushBuff(const char * data,size_t len,bool bStartAtZero)2489 void Csock::PushBuff( const char *data, size_t len, bool bStartAtZero )
2490 {
2491 if( !m_bEnableReadLine )
2492 return; // If the ReadLine event is disabled, just ditch here
2493
2494 size_t iStartPos = ( m_sbuffer.empty() || bStartAtZero ? 0 : m_sbuffer.length() - 1 );
2495
2496 if( data )
2497 m_sbuffer.append( data, len );
2498
2499 while( !m_bPauseRead && GetCloseType() == CLT_DONT )
2500 {
2501 CS_STRING::size_type iFind = m_sbuffer.find( "\n", iStartPos );
2502
2503 if( iFind != CS_STRING::npos )
2504 {
2505 CS_STRING sBuff = m_sbuffer.substr( 0, iFind + 1 ); // read up to(including) the newline
2506 m_sbuffer.erase( 0, iFind + 1 ); // erase past the newline
2507 #ifdef HAVE_ICU
2508 if( m_cnvExt )
2509 {
2510 CS_STRING sUTF8;
2511 if( ( m_cnvTryUTF8 && isUTF8( sBuff, sUTF8 ) ) // maybe it's already UTF-8?
2512 || icuConv( sBuff, sUTF8, m_cnvExt, m_cnvInt ) )
2513 {
2514 ReadLine( sUTF8 );
2515 }
2516 else
2517 {
2518 CS_DEBUG( "Can't convert received line to UTF-8" );
2519 }
2520 }
2521 else
2522 #endif /* HAVE_ICU */
2523 {
2524 ReadLine( sBuff );
2525 }
2526 iStartPos = 0; // reset this back to 0, since we need to look for the next newline here.
2527 }
2528 else
2529 {
2530 break;
2531 }
2532 }
2533
2534 if( m_iMaxStoredBufferLength > 0 && m_sbuffer.length() > m_iMaxStoredBufferLength )
2535 ReachedMaxBuffer(); // call the max read buffer event
2536 }
2537
2538 #ifdef HAVE_ICU
IcuExtToUCallback(UConverterToUnicodeArgs * toArgs,const char * codeUnits,int32_t length,UConverterCallbackReason reason,UErrorCode * err)2539 void Csock::IcuExtToUCallback(
2540 UConverterToUnicodeArgs* toArgs,
2541 const char* codeUnits,
2542 int32_t length,
2543 UConverterCallbackReason reason,
2544 UErrorCode* err)
2545 {
2546 if( reason <= UCNV_IRREGULAR )
2547 {
2548 *err = U_ZERO_ERROR;
2549 ucnv_cbToUWriteSub( toArgs, 0, err );
2550 }
2551 }
2552
IcuExtFromUCallback(UConverterFromUnicodeArgs * fromArgs,const UChar * codeUnits,int32_t length,UChar32 codePoint,UConverterCallbackReason reason,UErrorCode * err)2553 void Csock::IcuExtFromUCallback(
2554 UConverterFromUnicodeArgs* fromArgs,
2555 const UChar* codeUnits,
2556 int32_t length,
2557 UChar32 codePoint,
2558 UConverterCallbackReason reason,
2559 UErrorCode* err)
2560 {
2561 if( reason <= UCNV_IRREGULAR )
2562 {
2563 *err = U_ZERO_ERROR;
2564 ucnv_cbFromUWriteSub( fromArgs, 0, err );
2565 }
2566 }
2567
icuExtToUCallback(const void * context,UConverterToUnicodeArgs * toArgs,const char * codeUnits,int32_t length,UConverterCallbackReason reason,UErrorCode * err)2568 static void icuExtToUCallback(
2569 const void* context,
2570 UConverterToUnicodeArgs* toArgs,
2571 const char* codeUnits,
2572 int32_t length,
2573 UConverterCallbackReason reason,
2574 UErrorCode* err)
2575 {
2576 Csock* pcSock = (Csock*)context;
2577 pcSock->IcuExtToUCallback(toArgs, codeUnits, length, reason, err);
2578 }
2579
icuExtFromUCallback(const void * context,UConverterFromUnicodeArgs * fromArgs,const UChar * codeUnits,int32_t length,UChar32 codePoint,UConverterCallbackReason reason,UErrorCode * err)2580 static void icuExtFromUCallback(
2581 const void* context,
2582 UConverterFromUnicodeArgs* fromArgs,
2583 const UChar* codeUnits,
2584 int32_t length,
2585 UChar32 codePoint,
2586 UConverterCallbackReason reason,
2587 UErrorCode* err)
2588 {
2589 Csock* pcSock = (Csock*)context;
2590 pcSock->IcuExtFromUCallback(fromArgs, codeUnits, length, codePoint, reason, err);
2591 }
2592
SetEncoding(const CS_STRING & sEncoding)2593 void Csock::SetEncoding( const CS_STRING& sEncoding )
2594 {
2595 if( m_cnvExt ) ucnv_close( m_cnvExt );
2596 m_cnvExt = NULL;
2597 m_sEncoding = sEncoding;
2598 if( !sEncoding.empty() )
2599 {
2600 m_cnvTryUTF8 = sEncoding[0] == '*' || sEncoding[0] == '^';
2601 m_cnvSendUTF8 = sEncoding[0] == '^';
2602 const char* sEncodingName = sEncoding.c_str();
2603 if( m_cnvTryUTF8 )
2604 sEncodingName++;
2605 UErrorCode e = U_ZERO_ERROR;
2606 m_cnvExt = ucnv_open( sEncodingName, &e );
2607 if( U_FAILURE( e ) )
2608 {
2609 CS_DEBUG( "Can't set encoding to " << sEncoding << ": " << u_errorName( e ) );
2610 }
2611 if( m_cnvExt )
2612 {
2613 ucnv_setToUCallBack( m_cnvExt, icuExtToUCallback, this, NULL, NULL, &e );
2614 ucnv_setFromUCallBack( m_cnvExt, icuExtFromUCallback, this, NULL, NULL, &e );
2615 }
2616 }
2617 }
2618 #endif /* HAVE_ICU */
2619
GetInternalReadBuffer()2620 CS_STRING & Csock::GetInternalReadBuffer() { return( m_sbuffer ); }
GetInternalWriteBuffer()2621 CS_STRING & Csock::GetInternalWriteBuffer()
2622 {
2623 // in the event that some is grabbing this for some reason, we need to
2624 // clean it up so it's what they are expecting.
2625 ShrinkSendBuff();
2626 return( m_sSend );
2627 }
SetMaxBufferThreshold(u_int iThreshold)2628 void Csock::SetMaxBufferThreshold( u_int iThreshold ) { m_iMaxStoredBufferLength = iThreshold; }
GetMaxBufferThreshold() const2629 u_int Csock::GetMaxBufferThreshold() const { return( m_iMaxStoredBufferLength ); }
GetType() const2630 int Csock::GetType() const { return( m_iConnType ); }
SetType(int iType)2631 void Csock::SetType( int iType ) { m_iConnType = iType; }
GetSockName() const2632 const CS_STRING & Csock::GetSockName() const { return( m_sSockName ); }
SetSockName(const CS_STRING & sName)2633 void Csock::SetSockName( const CS_STRING & sName ) { m_sSockName = sName; }
GetHostName() const2634 const CS_STRING & Csock::GetHostName() const { return( m_shostname ); }
SetHostName(const CS_STRING & sHostname)2635 void Csock::SetHostName( const CS_STRING & sHostname ) { m_shostname = sHostname; }
GetStartTime() const2636 uint64_t Csock::GetStartTime() const { return( m_iStartTime ); }
ResetStartTime()2637 void Csock::ResetStartTime() { m_iStartTime = 0; }
GetBytesRead() const2638 uint64_t Csock::GetBytesRead() const { return( m_iBytesRead ); }
ResetBytesRead()2639 void Csock::ResetBytesRead() { m_iBytesRead = 0; }
GetBytesWritten() const2640 uint64_t Csock::GetBytesWritten() const { return( m_iBytesWritten ); }
ResetBytesWritten()2641 void Csock::ResetBytesWritten() { m_iBytesWritten = 0; }
2642
GetAvgRead(uint64_t iSample) const2643 double Csock::GetAvgRead( uint64_t iSample ) const
2644 {
2645 uint64_t iDifference = ( millitime() - m_iStartTime );
2646
2647 if( m_iBytesRead == 0 || iSample > iDifference )
2648 return( ( double )m_iBytesRead );
2649
2650 return( ( ( double )m_iBytesRead / ( ( double )iDifference / ( double )iSample ) ) );
2651 }
2652
GetAvgWrite(uint64_t iSample) const2653 double Csock::GetAvgWrite( uint64_t iSample ) const
2654 {
2655 uint64_t iDifference = ( millitime() - m_iStartTime );
2656
2657 if( m_iBytesWritten == 0 || iSample > iDifference )
2658 return( ( double )m_iBytesWritten );
2659
2660 return( ( ( double )m_iBytesWritten / ( ( double )iDifference / ( double )iSample ) ) );
2661 }
2662
GetRemotePort() const2663 uint16_t Csock::GetRemotePort() const
2664 {
2665 if( m_iRemotePort > 0 )
2666 return( m_iRemotePort );
2667 GetRemoteIP();
2668 return( m_iRemotePort );
2669 }
2670
GetLocalPort() const2671 uint16_t Csock::GetLocalPort() const
2672 {
2673 if( m_iLocalPort > 0 )
2674 return( m_iLocalPort );
2675 GetLocalIP();
2676 return( m_iLocalPort );
2677 }
2678
GetPort() const2679 uint16_t Csock::GetPort() const { return( m_uPort ); }
SetPort(uint16_t iPort)2680 void Csock::SetPort( uint16_t iPort ) { m_uPort = iPort; }
Close(ECloseType eCloseType)2681 void Csock::Close( ECloseType eCloseType )
2682 {
2683 m_eCloseType = eCloseType;
2684 }
2685
NonBlockingIO()2686 void Csock::NonBlockingIO()
2687 {
2688 set_non_blocking( m_iReadSock );
2689
2690 if( m_iReadSock != m_iWriteSock )
2691 {
2692 set_non_blocking( m_iWriteSock );
2693 }
2694 }
2695
GetSSL() const2696 bool Csock::GetSSL() const { return( m_bUseSSL ); }
SetSSL(bool b)2697 void Csock::SetSSL( bool b ) { m_bUseSSL = b; }
2698
2699 #ifdef HAVE_LIBSSL
SetCipher(const CS_STRING & sCipher)2700 void Csock::SetCipher( const CS_STRING & sCipher ) { m_sCipherType = sCipher; }
GetCipher() const2701 const CS_STRING & Csock::GetCipher() const { return( m_sCipherType ); }
2702
SetDHParamLocation(const CS_STRING & sDHParamFile)2703 void Csock::SetDHParamLocation( const CS_STRING & sDHParamFile ) { m_sDHParamFile = sDHParamFile; }
GetDHParamLocation() const2704 const CS_STRING & Csock::GetDHParamLocation() const { return( m_sDHParamFile ); }
2705
SetKeyLocation(const CS_STRING & sKeyFile)2706 void Csock::SetKeyLocation( const CS_STRING & sKeyFile ) { m_sKeyFile = sKeyFile; }
GetKeyLocation() const2707 const CS_STRING & Csock::GetKeyLocation() const { return( m_sKeyFile ); }
2708
SetPemLocation(const CS_STRING & sPemFile)2709 void Csock::SetPemLocation( const CS_STRING & sPemFile ) { m_sPemFile = sPemFile; }
GetPemLocation() const2710 const CS_STRING & Csock::GetPemLocation() const { return( m_sPemFile ); }
2711
SetPemPass(const CS_STRING & sPassword)2712 void Csock::SetPemPass( const CS_STRING & sPassword ) { m_sPemPass = sPassword; }
GetPemPass() const2713 const CS_STRING & Csock::GetPemPass() const { return( m_sPemPass ); }
2714
SetSSLMethod(int iMethod)2715 void Csock::SetSSLMethod( int iMethod ) { m_iMethod = iMethod; }
GetSSLMethod() const2716 int Csock::GetSSLMethod() const { return( m_iMethod ); }
SetSSLObject(SSL * ssl,bool bDeleteExisting)2717 void Csock::SetSSLObject( SSL *ssl, bool bDeleteExisting )
2718 {
2719 if( bDeleteExisting )
2720 FREE_SSL();
2721 m_ssl = ssl;
2722 }
GetSSLObject() const2723 SSL * Csock::GetSSLObject() const
2724 {
2725 if( m_ssl )
2726 return( m_ssl );
2727
2728 return( NULL );
2729 }
SetCTXObject(SSL_CTX * sslCtx,bool bDeleteExisting)2730 void Csock::SetCTXObject( SSL_CTX *sslCtx, bool bDeleteExisting )
2731 {
2732 if( bDeleteExisting )
2733 FREE_CTX();
2734 m_ssl_ctx = sslCtx;
2735 }
2736
GetSSLSession() const2737 SSL_SESSION * Csock::GetSSLSession() const
2738 {
2739 if( m_ssl )
2740 return( SSL_get_session( m_ssl ) );
2741
2742 return( NULL );
2743 }
2744 #endif /* HAVE_LIBSSL */
2745
HasWriteBuffer() const2746 bool Csock::HasWriteBuffer() const
2747 {
2748 // the fact that this has data in it is good enough. Checking m_uSendBufferPos is a moot point
2749 // since once m_uSendBufferPos is at the same position as m_sSend it's cleared (in Write)
2750 return( !m_sSend.empty() );
2751 }
ClearWriteBuffer()2752 void Csock::ClearWriteBuffer() { m_sSend.clear(); m_uSendBufferPos = 0; }
SslIsEstablished() const2753 bool Csock::SslIsEstablished() const { return ( m_bsslEstablished ); }
2754
ConnectInetd(bool bIsSSL,const CS_STRING & sHostname)2755 bool Csock::ConnectInetd( bool bIsSSL, const CS_STRING & sHostname )
2756 {
2757 if( !sHostname.empty() )
2758 m_sSockName = sHostname;
2759
2760 // set our hostname
2761 if( m_sSockName.empty() )
2762 {
2763 struct sockaddr_in client;
2764 socklen_t clen = sizeof( client );
2765 if( getpeername( 0, ( struct sockaddr * )&client, &clen ) < 0 )
2766 {
2767 m_sSockName = "0.0.0.0:0";
2768 }
2769 else
2770 {
2771 stringstream s;
2772 s << inet_ntoa( client.sin_addr ) << ":" << ntohs( client.sin_port );
2773 m_sSockName = s.str();
2774 }
2775 }
2776
2777 return( ConnectFD( 0, 1, m_sSockName, bIsSSL, INBOUND ) );
2778 }
2779
ConnectFD(int iReadFD,int iWriteFD,const CS_STRING & sName,bool bIsSSL,ETConn eDirection)2780 bool Csock::ConnectFD( int iReadFD, int iWriteFD, const CS_STRING & sName, bool bIsSSL, ETConn eDirection )
2781 {
2782 if( eDirection == LISTENER )
2783 {
2784 CS_DEBUG( "You can not use a LISTENER type here!" );
2785 return( false );
2786 }
2787
2788 // set our socket type
2789 SetType( eDirection );
2790
2791 // set the hostname
2792 m_sSockName = sName;
2793
2794 // set the file descriptors
2795 SetRSock( iReadFD );
2796 SetWSock( iWriteFD );
2797
2798 // set it up as non-blocking io
2799 NonBlockingIO();
2800
2801 if( bIsSSL )
2802 {
2803 if( eDirection == INBOUND && !AcceptSSL() )
2804 return( false );
2805 else if( eDirection == OUTBOUND && !ConnectSSL() )
2806 return( false );
2807 }
2808
2809 return( true );
2810 }
2811
2812 #ifdef HAVE_LIBSSL
GetX509() const2813 X509 *Csock::GetX509() const
2814 {
2815 if( m_ssl )
2816 return( SSL_get_peer_certificate( m_ssl ) );
2817
2818 return( NULL );
2819 }
2820
GetPeerPubKey() const2821 CS_STRING Csock::GetPeerPubKey() const
2822 {
2823 CS_STRING sKey;
2824
2825 X509 * pCert = GetX509();
2826
2827 if( pCert )
2828 {
2829 EVP_PKEY * pKey = X509_get_pubkey( pCert );
2830 if( pKey )
2831 {
2832 const BIGNUM * pPubKey = NULL;
2833 #ifdef HAVE_OPAQUE_SSL
2834 int iType = EVP_PKEY_base_id( pKey );
2835 #else
2836 int iType = pKey->type;
2837 #endif /* HAVE_OPAQUE_SSL */
2838 switch( iType )
2839 {
2840 #ifndef OPENSSL_NO_RSA
2841 case EVP_PKEY_RSA:
2842 # ifdef HAVE_OPAQUE_SSL
2843 RSA_get0_key( EVP_PKEY_get0_RSA( pKey ), &pPubKey, NULL, NULL );
2844 # else
2845 pPubKey = pKey->pkey.rsa->n;
2846 # endif /* HAVE_OPAQUE_SSL */
2847 break;
2848 #endif /* OPENSSL_NO_RSA */
2849 #ifndef OPENSSL_NO_DSA
2850 case EVP_PKEY_DSA:
2851 # ifdef HAVE_OPAQUE_SSL
2852 DSA_get0_key( EVP_PKEY_get0_DSA( pKey ), &pPubKey, NULL );
2853 # else
2854 pPubKey = pKey->pkey.dsa->pub_key;
2855 # endif /* HAVE_OPAQUE_SSL */
2856 break;
2857 #endif /* OPENSSL_NO_DSA */
2858 default:
2859 CS_DEBUG( "Not Prepared for Public Key Type [" << iType << "]" );
2860 break;
2861 }
2862 if( pPubKey )
2863 {
2864 char *hxKey = BN_bn2hex( pPubKey );
2865 sKey = hxKey;
2866 OPENSSL_free( hxKey );
2867 }
2868 EVP_PKEY_free( pKey );
2869 }
2870 X509_free( pCert );
2871 }
2872 return( sKey );
2873 }
2874
GetPeerFingerprint(CS_STRING & sFP) const2875 long Csock::GetPeerFingerprint( CS_STRING & sFP ) const
2876 {
2877 sFP.clear();
2878
2879 if( !m_ssl )
2880 return( 0 );
2881
2882 X509 * pCert = GetX509();
2883
2884 #ifdef HAVE_OPAQUE_SSL
2885 unsigned char sha1_hash[SHA_DIGEST_LENGTH];
2886
2887 if( pCert && X509_digest( pCert, EVP_sha1(), sha1_hash, NULL ) )
2888 #else
2889 unsigned char * sha1_hash = NULL;
2890
2891 // Inspired by charybdis
2892 if( pCert && (sha1_hash = pCert->sha1_hash) )
2893 #endif /* HAVE_OPAQUE_SSL */
2894 {
2895 for( int i = 0; i < SHA_DIGEST_LENGTH; i++ )
2896 {
2897 char buf[3];
2898 snprintf( buf, 3, "%02x", sha1_hash[i] );
2899 sFP += buf;
2900 }
2901 }
2902 X509_free( pCert );
2903
2904 return( SSL_get_verify_result( m_ssl ) );
2905 }
GetRequireClientCertFlags() const2906 u_int Csock::GetRequireClientCertFlags() const { return( m_iRequireClientCertFlags ); }
SetRequiresClientCert(bool bRequiresCert)2907 void Csock::SetRequiresClientCert( bool bRequiresCert ) { m_iRequireClientCertFlags = ( bRequiresCert ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER : 0 ); }
2908
2909 #endif /* HAVE_LIBSSL */
2910
SetParentSockName(const CS_STRING & sParentName)2911 void Csock::SetParentSockName( const CS_STRING & sParentName ) { m_sParentName = sParentName; }
GetParentSockName() const2912 const CS_STRING & Csock::GetParentSockName() const { return( m_sParentName ); }
2913
SetRate(u_int iBytes,uint64_t iMilliseconds)2914 void Csock::SetRate( u_int iBytes, uint64_t iMilliseconds )
2915 {
2916 m_iMaxBytes = iBytes;
2917 m_iMaxMilliSeconds = iMilliseconds;
2918 }
2919
GetRateBytes() const2920 u_int Csock::GetRateBytes() const { return( m_iMaxBytes ); }
GetRateTime() const2921 uint64_t Csock::GetRateTime() const { return( m_iMaxMilliSeconds ); }
2922
2923
EnableReadLine()2924 void Csock::EnableReadLine() { m_bEnableReadLine = true; }
DisableReadLine()2925 void Csock::DisableReadLine()
2926 {
2927 m_bEnableReadLine = false;
2928 m_sbuffer.clear();
2929 }
2930
ReachedMaxBuffer()2931 void Csock::ReachedMaxBuffer()
2932 {
2933 std::cerr << "Warning, Max Buffer length Warning Threshold has been hit" << endl;
2934 std::cerr << "If you don't care, then set SetMaxBufferThreshold to 0" << endl;
2935 }
2936
GetTimeSinceLastDataTransaction(time_t iNow) const2937 time_t Csock::GetTimeSinceLastDataTransaction( time_t iNow ) const
2938 {
2939 if( m_iLastCheckTimeoutTime == 0 )
2940 return( 0 );
2941 return( ( iNow > 0 ? iNow : time( NULL ) ) - m_iLastCheckTimeoutTime );
2942 }
2943
GetNextCheckTimeout(time_t iNow) const2944 time_t Csock::GetNextCheckTimeout( time_t iNow ) const
2945 {
2946 if( iNow == 0 )
2947 iNow = time( NULL );
2948 time_t iTimeout = m_iTimeout;
2949 time_t iDiff = iNow - m_iLastCheckTimeoutTime;
2950 /* CheckTimeout() wants to be called after half the timeout */
2951 if( m_iTcount == 0 )
2952 iTimeout /= 2;
2953 if( iDiff > iTimeout )
2954 iTimeout = 0;
2955 else
2956 iTimeout -= iDiff;
2957 return( iNow + iTimeout );
2958 }
2959
GetPending() const2960 int Csock::GetPending() const
2961 {
2962 #ifdef HAVE_LIBSSL
2963 if( m_ssl )
2964 {
2965 // in v23 method, the pending function is initialized to ssl_undefined_const_function
2966 // which throws SSL_UNDEFINED_CONST_FUNCTION on to the error stack
2967 // this is one of the more stupid things in openssl, it seems bizarre that even though SSL_pending
2968 // returns an int, they don't bother returning in error to notify us, so basically
2969 // we have to always clear errors here generated by SSL_pending, otherwise the stack could
2970 // have a lame error on it causing SSL_write to fail in certain instances.
2971 #if defined( OPENSSL_VERSION_NUMBER ) && OPENSSL_VERSION_NUMBER >= 0x00908000
2972 ERR_set_mark();
2973 int iBytes = SSL_pending( m_ssl );
2974 ERR_pop_to_mark();
2975 return( iBytes );
2976 #else
2977 int iBytes = SSL_pending( m_ssl );
2978 ERR_clear_error(); // to get safer handling, upgrade your openssl version!
2979 return( iBytes );
2980 #endif /* OPENSSL_VERSION_NUMBER */
2981 }
2982 else
2983 return( 0 );
2984 #else
2985 return( 0 );
2986 #endif /* HAVE_LIBSSL */
2987 }
2988
CreateSocksFD()2989 bool Csock::CreateSocksFD()
2990 {
2991 if( m_iReadSock != CS_INVALID_SOCK )
2992 return( true );
2993
2994 m_iReadSock = m_iWriteSock = CreateSocket();
2995 if( m_iReadSock == CS_INVALID_SOCK )
2996 return( false );
2997
2998 m_address.SinFamily();
2999 m_address.SinPort( m_uPort );
3000
3001 return( true );
3002 }
3003
3004
GetAddrInfo(const CS_STRING & sHostname,CSSockAddr & csSockAddr)3005 int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr )
3006 {
3007 #ifdef HAVE_IPV6
3008 if( csSockAddr.GetAFRequire() != AF_INET && inet_pton( AF_INET6, sHostname.c_str(), csSockAddr.GetAddr6() ) > 0 )
3009 {
3010 SetIPv6( true );
3011 return( 0 );
3012 }
3013 #endif /* HAVE_IPV6 */
3014 if( inet_pton( AF_INET, sHostname.c_str(), csSockAddr.GetAddr() ) > 0 )
3015 {
3016 #ifdef HAVE_IPV6
3017 SetIPv6( false );
3018 #endif /* HAVE_IPV6 */
3019 return( 0 );
3020 }
3021
3022 #ifdef HAVE_C_ARES
3023 // need to compute this up here
3024 if( !m_pARESChannel )
3025 {
3026 if( ares_init( &m_pARESChannel ) != ARES_SUCCESS )
3027 {
3028 // TODO throw some debug?
3029 FreeAres();
3030 return( ETIMEDOUT );
3031 }
3032 m_pCurrAddr = &csSockAddr; // flag its starting
3033
3034 int iFamily = AF_INET;
3035 #ifdef HAVE_IPV6
3036 #if ARES_VERSION >= CREATE_ARES_VER( 1, 7, 5 )
3037 // as of ares 1.7.5, it falls back to af_inet only when AF_UNSPEC is specified
3038 // so this can finally let the code flow through as anticipated :)
3039 iFamily = csSockAddr.GetAFRequire();
3040 #else
3041 // as of ares 1.6.0 if it fails on af_inet6, it falls back to af_inet,
3042 // this code was here in the previous Csocket version, just adding the comment as a reminder
3043 iFamily = csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY ? AF_INET6 : csSockAddr.GetAFRequire();
3044 #endif /* CREATE_ARES_VER( 1, 7, 5 ) */
3045 #endif /* HAVE_IPV6 */
3046 ares_gethostbyname( m_pARESChannel, sHostname.c_str(), iFamily, AresHostCallback, this );
3047 }
3048 if( !m_pCurrAddr )
3049 {
3050 // this means its finished
3051 FreeAres();
3052 #ifdef HAVE_IPV6
3053 if( GetType() != LISTENER && m_iARESStatus == ARES_SUCCESS && csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY && GetIPv6() )
3054 {
3055 // this means that ares_host returned an ipv6 host, so try a connect right away
3056 if( CreateSocksFD() && Connect() )
3057 {
3058 SetSkipConnect( true );
3059 }
3060 #ifndef _WIN32
3061 else if( GetSockError() == ENETUNREACH )
3062 #else
3063 else if( GetSockError() == WSAENETUNREACH || GetSockError() == WSAEHOSTUNREACH )
3064 #endif /* !_WIN32 */
3065 {
3066 // the Connect() failed, so throw a retry back in with ipv4, and let it process normally
3067 CS_DEBUG( "Failed ipv6 connection with PF_UNSPEC, falling back to ipv4" );
3068 m_iARESStatus = -1;
3069 CloseSocksFD();
3070 SetAFRequire( CSSockAddr::RAF_INET );
3071 return( GetAddrInfo( sHostname, csSockAddr ) );
3072 }
3073 }
3074 #if ARES_VERSION < CREATE_ARES_VER( 1, 5, 3 )
3075 if( m_iARESStatus != ARES_SUCCESS && csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY )
3076 {
3077 // this is a workaround for ares < 1.5.3 where the builtin retry on failed AF_INET6 isn't there yet
3078 CS_DEBUG( "Retry for older version of c-ares with AF_INET only" );
3079 // this means we tried previously with AF_INET6 and failed, so force AF_INET and retry
3080 SetAFRequire( CSSockAddr::RAF_INET );
3081 return( GetAddrInfo( sHostname, csSockAddr ) );
3082 }
3083 #endif /* ARES_VERSION < CREATE_ARES_VER( 1, 5, 3 ) */
3084 #endif /* HAVE_IPV6 */
3085 return( m_iARESStatus == ARES_SUCCESS ? 0 : ETIMEDOUT );
3086 }
3087 return( EAGAIN );
3088 #else /* HAVE_C_ARES */
3089 return( ::CS_GetAddrInfo( sHostname, this, csSockAddr ) );
3090 #endif /* HAVE_C_ARES */
3091 }
3092
DNSLookup(EDNSLType eDNSLType)3093 int Csock::DNSLookup( EDNSLType eDNSLType )
3094 {
3095 if( eDNSLType == DNS_VHOST )
3096 {
3097 if( m_sBindHost.empty() )
3098 {
3099 if( m_eConState != CST_OK )
3100 m_eConState = CST_DESTDNS; // skip binding, there is no vhost
3101 return( 0 );
3102 }
3103
3104 m_bindhost.SinFamily();
3105 m_bindhost.SinPort( 0 );
3106 }
3107
3108 int iRet = ETIMEDOUT;
3109 if( eDNSLType == DNS_VHOST )
3110 {
3111 iRet = GetAddrInfo( m_sBindHost, m_bindhost );
3112 #ifdef HAVE_IPV6
3113 if( m_bindhost.GetIPv6() )
3114 {
3115 SetAFRequire( CSSockAddr::RAF_INET6 );
3116 }
3117 else
3118 {
3119 SetAFRequire( CSSockAddr::RAF_INET );
3120 }
3121 #endif /* HAVE_IPV6 */
3122 }
3123 else
3124 {
3125 iRet = GetAddrInfo( m_shostname, m_address );
3126 }
3127
3128 if( iRet == 0 )
3129 {
3130 if( !CreateSocksFD() )
3131 {
3132 m_iDNSTryCount = 0;
3133 return( ETIMEDOUT );
3134 }
3135 if( m_eConState != CST_OK )
3136 m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_CONNECT );
3137 m_iDNSTryCount = 0;
3138 return( 0 );
3139 }
3140 else if( iRet == EAGAIN )
3141 {
3142 #ifndef HAVE_C_ARES
3143 m_iDNSTryCount++;
3144 if( m_iDNSTryCount > 20 )
3145 {
3146 m_iDNSTryCount = 0;
3147 return( ETIMEDOUT );
3148 }
3149 #endif /* HAVE_C_ARES */
3150 return( EAGAIN );
3151 }
3152 m_iDNSTryCount = 0;
3153 return( ETIMEDOUT );
3154 }
3155
SetupVHost()3156 bool Csock::SetupVHost()
3157 {
3158 if( m_sBindHost.empty() )
3159 {
3160 if( m_eConState != CST_OK )
3161 m_eConState = CST_DESTDNS;
3162 return( true );
3163 }
3164 int iRet = -1;
3165 if( !GetIPv6() )
3166 iRet = bind( m_iReadSock, ( struct sockaddr * ) m_bindhost.GetSockAddr(), m_bindhost.GetSockAddrLen() );
3167 #ifdef HAVE_IPV6
3168 else
3169 iRet = bind( m_iReadSock, ( struct sockaddr * ) m_bindhost.GetSockAddr6(), m_bindhost.GetSockAddrLen6() );
3170 #endif /* HAVE_IPV6 */
3171
3172 if( iRet == 0 )
3173 {
3174 if( m_eConState != CST_OK )
3175 m_eConState = CST_DESTDNS;
3176 return( true );
3177 }
3178 m_iCurBindCount++;
3179 if( m_iCurBindCount > 3 )
3180 {
3181 CS_DEBUG( "Failure to bind to " << m_sBindHost );
3182 return( false );
3183 }
3184
3185 return( true );
3186 }
3187
3188 #ifdef HAVE_LIBSSL
FREE_SSL()3189 void Csock::FREE_SSL()
3190 {
3191 if( m_ssl )
3192 {
3193 SSL_shutdown( m_ssl );
3194 SSL_free( m_ssl );
3195 }
3196 m_ssl = NULL;
3197 }
3198
FREE_CTX()3199 void Csock::FREE_CTX()
3200 {
3201 if( m_ssl_ctx )
3202 SSL_CTX_free( m_ssl_ctx );
3203
3204 m_ssl_ctx = NULL;
3205 }
3206
3207 #endif /* HAVE_LIBSSL */
3208
CreateSocket(bool bListen,bool bUnix)3209 cs_sock_t Csock::CreateSocket( bool bListen, bool bUnix )
3210 {
3211 int domain, protocol;
3212 if ( !bUnix )
3213 {
3214 #ifdef HAVE_IPV6
3215 domain = ( GetIPv6() ? PF_INET6 : PF_INET );
3216 #else
3217 domain = PF_INET;
3218 #endif /* HAVE_IPV6 */
3219 protocol = IPPROTO_TCP;
3220 }
3221 else
3222 {
3223 #ifdef HAVE_UNIX_SOCKET
3224 domain = AF_UNIX;
3225 protocol = 0;
3226 #else
3227 return CS_INVALID_SOCK;
3228 #endif
3229 }
3230 cs_sock_t iRet = socket( domain, SOCK_STREAM, protocol );
3231
3232 if( iRet != CS_INVALID_SOCK )
3233 {
3234 set_close_on_exec( iRet );
3235
3236 if( bListen )
3237 {
3238 const int on = 1;
3239 if( setsockopt( iRet, SOL_SOCKET, SO_REUSEADDR, ( char * ) &on, sizeof( on ) ) != 0 )
3240 PERROR( "SO_REUSEADDR" );
3241 }
3242 }
3243 else
3244 {
3245 PERROR( "socket" );
3246 }
3247 return( iRet );
3248 }
3249
Init(const CS_STRING & sHostname,uint16_t uPort,int iTimeout)3250 void Csock::Init( const CS_STRING & sHostname, uint16_t uPort, int iTimeout )
3251 {
3252 #ifdef HAVE_LIBSSL
3253 m_ssl = NULL;
3254 m_ssl_ctx = NULL;
3255 m_iRequireClientCertFlags = 0;
3256 m_uDisableProtocols = 0;
3257 m_bNoSSLCompression = false;
3258 m_bSSLCipherServerPreference = false;
3259 #endif /* HAVE_LIBSSL */
3260 m_iTcount = 0;
3261 m_iReadSock = CS_INVALID_SOCK;
3262 m_iWriteSock = CS_INVALID_SOCK;
3263 m_iTimeout = iTimeout;
3264 m_iMaxConns = SOMAXCONN;
3265 m_bUseSSL = false;
3266 m_bIsConnected = false;
3267 m_uPort = uPort;
3268 m_shostname = sHostname;
3269 m_sbuffer.clear();
3270 m_eCloseType = CLT_DONT;
3271 /*
3272 * While I appreciate the line ...
3273 * "It's 2014, no idea how this made it as a default for the past 16 years..."
3274 * TLS 1.2 was introduced in 2008. That being said, it's still not widely supported so I'm not
3275 * ready to make it the default. SSL 3.0 is still the most widely supported standard and that's
3276 * what a sane default is supposed to be. Additionally, OpenSSL is smart with SSLv23_client_method
3277 * as it will check for TLS in addition to SSL (per the manual) which is the reason for its choice.
3278 *
3279 * https://www.openssl.org/docs/ssl/SSL_CTX_new.html
3280 */
3281 m_iMethod = SSL23;
3282 m_sCipherType = "ALL";
3283 m_iMaxBytes = 0;
3284 m_iMaxMilliSeconds = 0;
3285 m_iLastSendTime = 0;
3286 m_iLastSend = 0;
3287 m_uSendBufferPos = 0;
3288 m_bsslEstablished = false;
3289 m_bEnableReadLine = false;
3290 m_iMaxStoredBufferLength = 1024;
3291 m_iConnType = INBOUND;
3292 m_iRemotePort = 0;
3293 m_iLocalPort = 0;
3294 m_iBytesRead = 0;
3295 m_iBytesWritten = 0;
3296 m_iStartTime = millitime();
3297 m_bPauseRead = false;
3298 m_iTimeoutType = TMO_ALL;
3299 m_eConState = CST_OK; // default should be ok
3300 m_iDNSTryCount = 0;
3301 m_iCurBindCount = 0;
3302 m_bIsIPv6 = false;
3303 m_bSkipConnect = false;
3304 m_iLastCheckTimeoutTime = 0;
3305 #ifdef HAVE_C_ARES
3306 m_pARESChannel = NULL;
3307 m_pCurrAddr = NULL;
3308 m_iARESStatus = -1;
3309 #endif /* HAVE_C_ARES */
3310 #ifdef HAVE_ICU
3311 m_cnvTryUTF8 = false;
3312 m_cnvSendUTF8 = false;
3313 UErrorCode e = U_ZERO_ERROR;
3314 m_cnvExt = NULL;
3315 m_cnvInt = ucnv_open( "UTF-8", &e );
3316 #endif /* HAVE_ICU */
3317 }
3318
3319 ////////////////////////// CSocketManager //////////////////////////
CSocketManager()3320 CSocketManager::CSocketManager() : std::vector<Csock *>(), CSockCommon()
3321 {
3322 m_errno = SUCCESS;
3323 m_iCallTimeouts = millitime();
3324 m_iSelectWait = 100000; // Default of 100 milliseconds
3325 m_iBytesRead = 0;
3326 m_iBytesWritten = 0;
3327 }
3328
~CSocketManager()3329 CSocketManager::~CSocketManager()
3330 {
3331 clear();
3332 }
3333
clear()3334 void CSocketManager::clear()
3335 {
3336 while( !this->empty() )
3337 DelSock( 0 );
3338 }
3339
Cleanup()3340 void CSocketManager::Cleanup()
3341 {
3342 CleanupCrons();
3343 CleanupFDMonitors();
3344 clear();
3345 }
3346
GetSockObj(const CS_STRING & sHostname,uint16_t uPort,int iTimeout)3347 Csock * CSocketManager::GetSockObj( const CS_STRING & sHostname, uint16_t uPort, int iTimeout )
3348 {
3349 return( new Csock( sHostname, uPort, iTimeout ) );
3350 }
3351
Connect(const CSConnection & cCon,Csock * pcSock)3352 void CSocketManager::Connect( const CSConnection & cCon, Csock * pcSock )
3353 {
3354 // create the new object
3355 if( !pcSock )
3356 pcSock = GetSockObj( cCon.GetHostname(), cCon.GetPort(), cCon.GetTimeout() );
3357 else
3358 {
3359 pcSock->SetHostName( cCon.GetHostname() );
3360 pcSock->SetPort( cCon.GetPort() );
3361 pcSock->SetTimeout( cCon.GetTimeout() );
3362 }
3363
3364 if( cCon.GetAFRequire() != CSSockAddr::RAF_ANY )
3365 pcSock->SetAFRequire( cCon.GetAFRequire() );
3366
3367 // bind the vhost
3368 pcSock->SetBindHost( cCon.GetBindHost() );
3369
3370 #ifdef HAVE_LIBSSL
3371 pcSock->SetSSL( cCon.GetIsSSL() );
3372 if( cCon.GetIsSSL() )
3373 {
3374 if( !cCon.GetPemLocation().empty() )
3375 {
3376 pcSock->SetDHParamLocation( cCon.GetDHParamLocation() );
3377 pcSock->SetKeyLocation( cCon.GetKeyLocation() );
3378 pcSock->SetPemLocation( cCon.GetPemLocation() );
3379 pcSock->SetPemPass( cCon.GetPemPass() );
3380 }
3381 if( !cCon.GetCipher().empty() )
3382 pcSock->SetCipher( cCon.GetCipher() );
3383 }
3384 #endif /* HAVE_LIBSSL */
3385
3386 pcSock->SetType( Csock::OUTBOUND );
3387
3388 pcSock->SetConState( Csock::CST_START );
3389 AddSock( pcSock, cCon.GetSockName() );
3390 }
3391
Listen(const CSListener & cListen,Csock * pcSock,uint16_t * piRandPort)3392 bool CSocketManager::Listen( const CSListener & cListen, Csock * pcSock, uint16_t * piRandPort )
3393 {
3394 if( !pcSock )
3395 pcSock = GetSockObj( "", 0 );
3396
3397 if( cListen.GetAFRequire() != CSSockAddr::RAF_ANY )
3398 {
3399 pcSock->SetAFRequire( cListen.GetAFRequire() );
3400 #ifdef HAVE_IPV6
3401 if( cListen.GetAFRequire() == CSSockAddr::RAF_INET6 )
3402 pcSock->SetIPv6( true );
3403 #endif /* HAVE_IPV6 */
3404 }
3405 #ifdef HAVE_IPV6
3406 else
3407 {
3408 pcSock->SetIPv6( true );
3409 }
3410 #endif /* HAVE_IPV6 */
3411 #ifdef HAVE_LIBSSL
3412 pcSock->SetSSL( cListen.GetIsSSL() );
3413 if( cListen.GetIsSSL() && !cListen.GetPemLocation().empty() )
3414 {
3415 pcSock->SetDHParamLocation( cListen.GetDHParamLocation() );
3416 pcSock->SetKeyLocation( cListen.GetKeyLocation() );
3417 pcSock->SetPemLocation( cListen.GetPemLocation() );
3418 pcSock->SetPemPass( cListen.GetPemPass() );
3419 pcSock->SetCipher( cListen.GetCipher() );
3420 pcSock->SetRequireClientCertFlags( cListen.GetRequireClientCertFlags() );
3421 }
3422 #endif /* HAVE_LIBSSL */
3423
3424 if( piRandPort )
3425 *piRandPort = 0;
3426
3427 bool bDetach = ( cListen.GetDetach() && !piRandPort ); // can't detach if we're waiting for the port to come up right now
3428 if( pcSock->Listen( cListen.GetPort(), cListen.GetMaxConns(), cListen.GetBindHost(), cListen.GetTimeout(), bDetach ) )
3429 {
3430 AddSock( pcSock, cListen.GetSockName() );
3431 if( piRandPort && cListen.GetPort() == 0 )
3432 {
3433 cs_sock_t iSock = pcSock->GetSock();
3434
3435 if( iSock == CS_INVALID_SOCK )
3436 {
3437 CS_DEBUG( "Failed to attain a valid file descriptor" );
3438 pcSock->Close();
3439 return( false );
3440 }
3441 struct sockaddr_in mLocalAddr;
3442 socklen_t mLocalLen = sizeof( mLocalAddr );
3443 getsockname( iSock, ( struct sockaddr * ) &mLocalAddr, &mLocalLen );
3444 *piRandPort = ntohs( mLocalAddr.sin_port );
3445 }
3446 return( true );
3447 }
3448
3449 CS_Delete( pcSock );
3450 return( false );
3451 }
3452
3453
HasFDs() const3454 bool CSocketManager::HasFDs() const
3455 {
3456 return( !this->empty() || !m_vcMonitorFD.empty() );
3457 }
3458
Loop()3459 void CSocketManager::Loop()
3460 {
3461 for( size_t a = 0; a < this->size(); ++a )
3462 {
3463 Csock * pcSock = this->at( a );
3464 if( pcSock->GetType() != Csock::OUTBOUND || pcSock->GetConState() == Csock::CST_OK )
3465 continue;
3466 if( pcSock->GetConState() == Csock::CST_DNS )
3467 {
3468 if( pcSock->DNSLookup( Csock::DNS_VHOST ) == ETIMEDOUT )
3469 {
3470 pcSock->CallSockError( EDOM, "DNS Lookup for bind host failed" );
3471 DelSock( a-- );
3472 continue;
3473 }
3474 }
3475
3476 if( pcSock->GetConState() == Csock::CST_BINDVHOST )
3477 {
3478 if( !pcSock->SetupVHost() )
3479 {
3480 pcSock->CallSockError( GetSockError(), "Failed to setup bind host" );
3481 DelSock( a-- );
3482 continue;
3483 }
3484 }
3485
3486 if( pcSock->GetConState() == Csock::CST_DESTDNS )
3487 {
3488 if( pcSock->DNSLookup( Csock::DNS_DEST ) == ETIMEDOUT )
3489 {
3490 pcSock->CallSockError( EADDRNOTAVAIL, "Unable to resolve requested address" );
3491 DelSock( a-- );
3492 continue;
3493 }
3494 }
3495 if( pcSock->GetConState() == Csock::CST_CONNECT )
3496 {
3497 if( !pcSock->Connect() )
3498 {
3499 if( GetSockError() == ECONNREFUSED )
3500 pcSock->ConnectionRefused();
3501 else
3502 pcSock->CallSockError( GetSockError() );
3503
3504 DelSock( a-- );
3505 continue;
3506 }
3507 }
3508 #ifdef HAVE_LIBSSL
3509 if( pcSock->GetConState() == Csock::CST_CONNECTSSL )
3510 {
3511 if( pcSock->GetSSL() )
3512 {
3513 if( !pcSock->ConnectSSL() )
3514 {
3515 if( GetSockError() == ECONNREFUSED )
3516 pcSock->ConnectionRefused();
3517 else
3518 pcSock->CallSockError( GetSockError() == 0 ? ECONNABORTED : GetSockError() );
3519
3520 DelSock( a-- );
3521 continue;
3522 }
3523 }
3524 }
3525 #endif /* HAVE_LIBSSL */
3526 }
3527
3528 std::map<Csock *, EMessages> mpeSocks;
3529 Select( mpeSocks );
3530
3531 switch( m_errno )
3532 {
3533 case SUCCESS:
3534 {
3535 for( std::map<Csock *, EMessages>::iterator itSock = mpeSocks.begin(); itSock != mpeSocks.end(); itSock++ )
3536 {
3537 Csock * pcSock = itSock->first;
3538 EMessages iErrno = itSock->second;
3539
3540 if( iErrno == SUCCESS )
3541 {
3542 // read in data
3543 // if this is a
3544 int iLen = 0;
3545
3546 if( pcSock->GetSSL() )
3547 iLen = pcSock->GetPending();
3548
3549 if( iLen <= 0 )
3550 iLen = CS_BLOCKSIZE;
3551
3552 CSCharBuffer cBuff( iLen );
3553
3554 cs_ssize_t bytes = pcSock->Read( cBuff(), iLen );
3555
3556 if( bytes != Csock::READ_TIMEDOUT && bytes != Csock::READ_CONNREFUSED && bytes != Csock::READ_ERR && !pcSock->IsConnected() )
3557 {
3558 pcSock->SetIsConnected( true );
3559 pcSock->Connected();
3560 }
3561
3562 switch( bytes )
3563 {
3564 case Csock::READ_EOF:
3565 {
3566 DelSockByAddr( pcSock );
3567 break;
3568 }
3569
3570 case Csock::READ_ERR:
3571 {
3572 bool bHandled = false;
3573 #ifdef HAVE_LIBSSL
3574 if( pcSock->GetSSL() )
3575 {
3576 unsigned long iSSLError = ERR_peek_error();
3577 if( iSSLError )
3578 {
3579 char szError[512];
3580 memset( ( char * ) szError, '\0', 512 );
3581 ERR_error_string_n( iSSLError, szError, 511 );
3582 SSLErrors( __FILE__, __LINE__ );
3583 pcSock->CallSockError( GetSockError(), szError );
3584 bHandled = true;
3585 }
3586 }
3587 #endif
3588 if( !bHandled )
3589 pcSock->CallSockError( GetSockError() );
3590 DelSockByAddr( pcSock );
3591 break;
3592 }
3593
3594 case Csock::READ_EAGAIN:
3595 break;
3596
3597 case Csock::READ_CONNREFUSED:
3598 pcSock->ConnectionRefused();
3599 DelSockByAddr( pcSock );
3600 break;
3601
3602 case Csock::READ_TIMEDOUT:
3603 pcSock->Timeout();
3604 DelSockByAddr( pcSock );
3605 break;
3606
3607 default:
3608 {
3609 if( Csock::TMO_READ & pcSock->GetTimeoutType() )
3610 pcSock->ResetTimer(); // reset the timeout timer
3611
3612 pcSock->ReadData( cBuff(), bytes ); // Call ReadData() before PushBuff() so that it is called before the ReadLine() event - LD 07/18/05
3613 pcSock->PushBuff( cBuff(), bytes );
3614 break;
3615 }
3616 }
3617 }
3618 else if( iErrno == SELECT_ERROR )
3619 {
3620 // a socket came back with an error
3621 // usually means it was closed
3622 DelSockByAddr( pcSock );
3623 }
3624 }
3625 break;
3626 }
3627
3628 case SELECT_TIMEOUT:
3629 case SELECT_TRYAGAIN:
3630 case SELECT_ERROR:
3631 default :
3632 break;
3633 }
3634
3635 uint64_t iMilliNow = millitime();
3636 if( ( iMilliNow - m_iCallTimeouts ) >= 1000 )
3637 {
3638 m_iCallTimeouts = iMilliNow;
3639 // call timeout on all the sockets that recieved no data
3640 for( size_t i = 0; i < this->size(); ++i )
3641 {
3642 if( this->at( i )->GetConState() != Csock::CST_OK )
3643 continue;
3644
3645 if( this->at( i )->CheckTimeout( ( time_t )( iMilliNow / 1000 ) ) )
3646 DelSock( i-- );
3647 }
3648 }
3649 // run any Manager Crons we may have
3650 Cron();
3651 }
3652
DynamicSelectLoop(uint64_t iLowerBounds,uint64_t iUpperBounds,time_t iMaxResolution)3653 void CSocketManager::DynamicSelectLoop( uint64_t iLowerBounds, uint64_t iUpperBounds, time_t iMaxResolution )
3654 {
3655 SetSelectTimeout( iLowerBounds );
3656 if( m_errno == SELECT_TIMEOUT )
3657 {
3658 // only do this if the previous call to select was a timeout
3659 timeval tMaxResolution;
3660 timeval tNow;
3661 tMaxResolution.tv_sec = iMaxResolution;
3662 tMaxResolution.tv_usec = 0;
3663 CS_GETTIMEOFDAY( &tNow, NULL );
3664 timeval tSelectTimeout = GetDynamicSleepTime( tNow, tMaxResolution );
3665 uint64_t iSelectTimeout = tSelectTimeout.tv_sec * 1000000 + tSelectTimeout.tv_usec;
3666 iSelectTimeout = std::max( iLowerBounds, iSelectTimeout );
3667 iSelectTimeout = std::min( iSelectTimeout, iUpperBounds );
3668 if( iLowerBounds != iSelectTimeout )
3669 SetSelectTimeout( iSelectTimeout );
3670 }
3671 Loop();
3672 }
3673
AddSock(Csock * pcSock,const CS_STRING & sSockName)3674 void CSocketManager::AddSock( Csock * pcSock, const CS_STRING & sSockName )
3675 {
3676 pcSock->SetSockName( sSockName );
3677 this->push_back( pcSock );
3678 }
3679
FindSockByRemotePort(uint16_t iPort)3680 Csock * CSocketManager::FindSockByRemotePort( uint16_t iPort )
3681 {
3682 for( size_t i = 0; i < this->size(); ++i )
3683 {
3684 if( this->at( i )->GetRemotePort() == iPort )
3685 return( this->at( i ) );
3686 }
3687 return( NULL );
3688 }
3689
FindSockByLocalPort(uint16_t iPort)3690 Csock * CSocketManager::FindSockByLocalPort( uint16_t iPort )
3691 {
3692 for( size_t i = 0; i < this->size(); ++i )
3693 {
3694 if( this->at( i )->GetLocalPort() == iPort )
3695 return( this->at( i ) );
3696 }
3697 return( NULL );
3698 }
3699
FindSockByName(const CS_STRING & sName)3700 Csock * CSocketManager::FindSockByName( const CS_STRING & sName )
3701 {
3702 std::vector<Csock *>::iterator it;
3703 std::vector<Csock *>::iterator it_end = this->end();
3704 for( it = this->begin(); it != it_end; it++ )
3705 {
3706 if( ( *it )->GetSockName() == sName )
3707 return( *it );
3708 }
3709 return( NULL );
3710 }
3711
FindSockByFD(cs_sock_t iFD)3712 Csock * CSocketManager::FindSockByFD( cs_sock_t iFD )
3713 {
3714 for( size_t i = 0; i < this->size(); ++i )
3715 {
3716 if( this->at( i )->GetRSock() == iFD || this->at( i )->GetWSock() == iFD )
3717 return( this->at( i ) );
3718 }
3719 return( NULL );
3720 }
3721
FindSocksByName(const CS_STRING & sName)3722 std::vector<Csock *> CSocketManager::FindSocksByName( const CS_STRING & sName )
3723 {
3724 std::vector<Csock *> vpSocks;
3725 for( size_t i = 0; i < this->size(); ++i )
3726 {
3727 if( this->at( i )->GetSockName() == sName )
3728 vpSocks.push_back( this->at( i ) );
3729 }
3730 return( vpSocks );
3731 }
3732
FindSocksByRemoteHost(const CS_STRING & sHostname)3733 std::vector<Csock *> CSocketManager::FindSocksByRemoteHost( const CS_STRING & sHostname )
3734 {
3735 std::vector<Csock *> vpSocks;
3736 for( size_t i = 0; i < this->size(); ++i )
3737 {
3738 if( this->at( i )->GetHostName() == sHostname )
3739 vpSocks.push_back( this->at( i ) );
3740 }
3741 return( vpSocks );
3742 }
3743
DelSockByAddr(Csock * pcSock)3744 void CSocketManager::DelSockByAddr( Csock * pcSock )
3745 {
3746 for( size_t a = 0; a < this->size(); ++a )
3747 {
3748 if( pcSock == this->at( a ) )
3749 {
3750 DelSock( a );
3751 return;
3752 }
3753 }
3754 }
3755
DelSock(size_t iPos)3756 void CSocketManager::DelSock( size_t iPos )
3757 {
3758 if( iPos >= this->size() )
3759 {
3760 CS_DEBUG( "Invalid Sock Position Requested! [" << iPos << "]" );
3761 return;
3762 }
3763
3764 Csock * pSock = this->at( iPos );
3765
3766 if( pSock->GetCloseType() != Csock::CLT_DEREFERENCE )
3767 {
3768 if( pSock->IsConnected() )
3769 {
3770 pSock->SetIsConnected( false );
3771 pSock->Disconnected(); // only call disconnected event if connected event was called (IE IsConnected was set)
3772 }
3773
3774 m_iBytesRead += pSock->GetBytesRead();
3775 m_iBytesWritten += pSock->GetBytesWritten();
3776 }
3777
3778 CS_Delete( pSock );
3779 this->erase( this->begin() + iPos );
3780 }
3781
SwapSockByIdx(Csock * pNewSock,size_t iOrginalSockIdx)3782 bool CSocketManager::SwapSockByIdx( Csock * pNewSock, size_t iOrginalSockIdx )
3783 {
3784 if( iOrginalSockIdx >= this->size() )
3785 {
3786 CS_DEBUG( "Invalid Sock Position Requested! [" << iOrginalSockIdx << "]" );
3787 return( false );
3788 }
3789
3790 Csock * pSock = this->at( iOrginalSockIdx );
3791 pNewSock->Copy( *pSock );
3792 pSock->Dereference();
3793 this->at( iOrginalSockIdx ) = ( Csock * )pNewSock;
3794 this->push_back( ( Csock * )pSock ); // this allows it to get cleaned up
3795 return( true );
3796 }
3797
SwapSockByAddr(Csock * pNewSock,Csock * pOrigSock)3798 bool CSocketManager::SwapSockByAddr( Csock * pNewSock, Csock * pOrigSock )
3799 {
3800 for( size_t a = 0; a < this->size(); ++a )
3801 {
3802 if( this->at( a ) == pOrigSock )
3803 return( SwapSockByIdx( pNewSock, a ) );
3804 }
3805 return( false );
3806 }
3807
GetBytesRead() const3808 uint64_t CSocketManager::GetBytesRead() const
3809 {
3810 // Start with the total bytes read from destroyed sockets
3811 uint64_t iRet = m_iBytesRead;
3812
3813 // Add in the outstanding bytes read from active sockets
3814 for( size_t a = 0; a < this->size(); ++a )
3815 iRet += this->at( a )->GetBytesRead();
3816
3817 return( iRet );
3818 }
3819
GetBytesWritten() const3820 uint64_t CSocketManager::GetBytesWritten() const
3821 {
3822 // Start with the total bytes written to destroyed sockets
3823 uint64_t iRet = m_iBytesWritten;
3824
3825 // Add in the outstanding bytes written to active sockets
3826 for( size_t a = 0; a < this->size(); ++a )
3827 iRet += this->at( a )->GetBytesWritten();
3828
3829 return( iRet );
3830 }
3831
FDSetCheck(cs_sock_t iFd,std::map<cs_sock_t,short> & miiReadyFds,ECheckType eType)3832 void CSocketManager::FDSetCheck( cs_sock_t iFd, std::map< cs_sock_t, short > & miiReadyFds, ECheckType eType )
3833 {
3834 std::map< cs_sock_t, short >::iterator it = miiReadyFds.find( iFd );
3835 if( it != miiReadyFds.end() )
3836 it->second = ( short )( it->second | eType ); // TODO need to figure out why |= throws 'short int' from 'int' may alter its value
3837 else
3838 miiReadyFds[iFd] = eType;
3839 }
3840
FDHasCheck(cs_sock_t iFd,std::map<cs_sock_t,short> & miiReadyFds,ECheckType eType)3841 bool CSocketManager::FDHasCheck( cs_sock_t iFd, std::map< cs_sock_t, short > & miiReadyFds, ECheckType eType )
3842 {
3843 std::map< cs_sock_t, short >::iterator it = miiReadyFds.find( iFd );
3844 if( it != miiReadyFds.end() )
3845 return( ( it->second & eType ) != 0 );
3846 return( false );
3847 }
3848
Select(std::map<cs_sock_t,short> & miiReadyFds,struct timeval * tvtimeout)3849 int CSocketManager::Select( std::map< cs_sock_t, short > & miiReadyFds, struct timeval *tvtimeout )
3850 {
3851 AssignFDs( miiReadyFds, tvtimeout );
3852 #ifdef CSOCK_USE_POLL
3853 if( miiReadyFds.empty() )
3854 return( select( 0, NULL, NULL, NULL, tvtimeout ) );
3855
3856 struct pollfd * pFDs = ( struct pollfd * )malloc( sizeof( struct pollfd ) * miiReadyFds.size() );
3857 size_t uCurrPoll = 0;
3858 for( std::map< cs_sock_t, short >::iterator it = miiReadyFds.begin(); it != miiReadyFds.end(); ++it, ++uCurrPoll )
3859 {
3860 short iEvents = 0;
3861 if( it->second & ECT_Read )
3862 iEvents |= POLLIN;
3863 if( it->second & ECT_Write )
3864 iEvents |= POLLOUT;
3865 pFDs[uCurrPoll].fd = it->first;
3866 pFDs[uCurrPoll].events = iEvents;
3867 pFDs[uCurrPoll].revents = 0;
3868 }
3869 int iTimeout = ( int )( tvtimeout->tv_usec / 1000 );
3870 iTimeout += ( int )( tvtimeout->tv_sec * 1000 );
3871 size_t uMaxFD = miiReadyFds.size();
3872 int iRet = poll( pFDs, uMaxFD, iTimeout );
3873 miiReadyFds.clear();
3874 for( uCurrPoll = 0; uCurrPoll < uMaxFD; ++uCurrPoll )
3875 {
3876 short iEvents = 0;
3877 if( pFDs[uCurrPoll].revents & ( POLLIN|POLLERR|POLLHUP|POLLNVAL ) )
3878 iEvents |= ECT_Read;
3879 if( pFDs[uCurrPoll].revents & POLLOUT )
3880 iEvents |= ECT_Write;
3881 std::map< cs_sock_t, short >::iterator it = miiReadyFds.find( pFDs[uCurrPoll].fd );
3882 if( it != miiReadyFds.end() )
3883 it->second = ( short )( it->second | iEvents ); // TODO need to figure out why |= throws 'short int' from 'int' may alter its value
3884 else
3885 miiReadyFds[pFDs[uCurrPoll].fd] = iEvents;
3886 }
3887 free( pFDs );
3888 #else
3889 fd_set rfds, wfds;
3890 TFD_ZERO( &rfds );
3891 TFD_ZERO( &wfds );
3892 bool bHasWrite = false;
3893 int iHighestFD = 0;
3894 for( std::map< cs_sock_t, short >::iterator it = miiReadyFds.begin(); it != miiReadyFds.end(); ++it )
3895 {
3896 #ifndef _WIN32
3897 // the first argument to select() is not used on Win32.
3898 iHighestFD = std::max( it->first, iHighestFD );
3899 #endif /* _WIN32 */
3900 if( it->second & ECT_Read )
3901 {
3902 TFD_SET( it->first, &rfds );
3903 }
3904 if( it->second & ECT_Write )
3905 {
3906 bHasWrite = true;
3907 TFD_SET( it->first, &wfds );
3908 }
3909 }
3910
3911 int iRet = select( iHighestFD + 1, &rfds, ( bHasWrite ? &wfds : NULL ), NULL, tvtimeout );
3912 if( iRet <= 0 )
3913 {
3914 miiReadyFds.clear();
3915 }
3916 else
3917 {
3918 for( std::map< cs_sock_t, short >::iterator it = miiReadyFds.begin(); it != miiReadyFds.end(); ++it )
3919 {
3920 if( ( it->second & ECT_Read ) && !TFD_ISSET( it->first, &rfds ) )
3921 it->second &= ~ECT_Read;
3922 if( ( it->second & ECT_Write ) && !TFD_ISSET( it->first, &wfds ) )
3923 it->second &= ~ECT_Write;
3924 }
3925 }
3926 #endif /* CSOCK_USE_POLL */
3927
3928 return( iRet );
3929 }
3930
Select(std::map<Csock *,EMessages> & mpeSocks)3931 void CSocketManager::Select( std::map<Csock *, EMessages> & mpeSocks )
3932 {
3933 mpeSocks.clear();
3934 struct timeval tv;
3935
3936 std::map< cs_sock_t, short > miiReadyFds;
3937 tv.tv_sec = ( time_t )( m_iSelectWait / 1000000 );
3938 tv.tv_usec = ( time_t )( m_iSelectWait % 1000000 );
3939 u_int iQuickReset = 1000;
3940 if( m_iSelectWait == 0 )
3941 iQuickReset = 0;
3942
3943 bool bHasAvailSocks = false;
3944 uint64_t iNOW = 0;
3945 for( size_t i = 0; i < this->size(); ++i )
3946 {
3947 Csock * pcSock = this->at( i );
3948
3949 Csock::ECloseType eCloseType = pcSock->GetCloseType();
3950
3951 if( eCloseType == Csock::CLT_NOW || eCloseType == Csock::CLT_DEREFERENCE || ( eCloseType == Csock::CLT_AFTERWRITE && !pcSock->HasWriteBuffer() ) )
3952 {
3953 DelSock( i-- ); // close any socks that have requested it
3954 continue;
3955 }
3956 else
3957 {
3958 pcSock->Cron(); // call the Cron handler here
3959 }
3960
3961 cs_sock_t & iRSock = pcSock->GetRSock();
3962 cs_sock_t & iWSock = pcSock->GetWSock();
3963 #if !defined(CSOCK_USE_POLL) && !defined(_WIN32)
3964 if( iRSock > ( cs_sock_t )FD_SETSIZE || iWSock > ( cs_sock_t )FD_SETSIZE )
3965 {
3966 CS_DEBUG( "FD is larger than select() can handle" );
3967 DelSock( i-- );
3968 continue;
3969 }
3970 #endif /* CSOCK_USE_POLL */
3971
3972 #ifdef HAVE_C_ARES
3973 ares_channel pChannel = pcSock->GetAresChannel();
3974 if( pChannel )
3975 {
3976 ares_socket_t aiAresSocks[1];
3977 aiAresSocks[0] = ARES_SOCKET_BAD;
3978 int iSockMask = ares_getsock( pChannel, aiAresSocks, 1 );
3979 if( ARES_GETSOCK_READABLE( iSockMask, 0 ) )
3980 FDSetCheck( aiAresSocks[0], miiReadyFds, ECT_Read );
3981 if( ARES_GETSOCK_WRITABLE( iSockMask, 0 ) )
3982 FDSetCheck( aiAresSocks[0], miiReadyFds, ECT_Write );
3983 // let ares drop the timeout if it has something timing out sooner then whats in tv currently
3984 ares_timeout( pChannel, &tv, &tv );
3985 }
3986 #endif /* HAVE_C_ARES */
3987 if( pcSock->GetType() == Csock::LISTENER && pcSock->GetConState() == Csock::CST_BINDVHOST )
3988 {
3989 if( !pcSock->Listen( pcSock->GetPort(), pcSock->GetMaxConns(), pcSock->GetBindHost(), pcSock->GetTimeout(), true ) )
3990 {
3991 pcSock->Close();
3992 DelSock( i-- );
3993 }
3994 continue;
3995 }
3996
3997 pcSock->AssignFDs( miiReadyFds, &tv );
3998
3999 if( pcSock->GetConState() != Csock::CST_OK )
4000 continue;
4001
4002 bHasAvailSocks = true;
4003
4004 bool bIsReadPaused = pcSock->IsReadPaused();
4005 if( bIsReadPaused )
4006 {
4007 pcSock->ReadPaused();
4008 bIsReadPaused = pcSock->IsReadPaused(); // re-read it again, incase it changed status)
4009 }
4010 if( iRSock == CS_INVALID_SOCK || iWSock == CS_INVALID_SOCK )
4011 {
4012 SelectSock( mpeSocks, SUCCESS, pcSock );
4013 continue; // invalid sock fd
4014 }
4015
4016 if( pcSock->GetType() != Csock::LISTENER )
4017 {
4018 bool bHasWriteBuffer = pcSock->HasWriteBuffer();
4019
4020 if( !bIsReadPaused )
4021 FDSetCheck( iRSock, miiReadyFds, ECT_Read );
4022
4023 if( pcSock->AllowWrite( iNOW ) && ( !pcSock->IsConnected() || bHasWriteBuffer ) )
4024 {
4025 if( !pcSock->IsConnected() )
4026 {
4027 // set the write bit if not connected yet
4028 FDSetCheck( iWSock, miiReadyFds, ECT_Write );
4029 }
4030 else if( bHasWriteBuffer && !pcSock->GetSSL() )
4031 {
4032 // always set the write bit if there is data to send when NOT ssl
4033 FDSetCheck( iWSock, miiReadyFds, ECT_Write );
4034 }
4035 else if( bHasWriteBuffer && pcSock->GetSSL() && pcSock->SslIsEstablished() )
4036 {
4037 // ONLY set the write bit if there is data to send and the SSL handshake is finished
4038 FDSetCheck( iWSock, miiReadyFds, ECT_Write );
4039 }
4040 }
4041
4042 if( pcSock->GetSSL() && !pcSock->SslIsEstablished() && bHasWriteBuffer )
4043 {
4044 // if this is an unestabled SSL session with data to send ... try sending it
4045 // do this here, cause otherwise ssl will cause a small
4046 // cpu spike waiting for the handshake to finish
4047 // resend this data
4048 if( !pcSock->Write( "" ) )
4049 {
4050 pcSock->Close();
4051 }
4052 // warning ... setting write bit in here causes massive CPU spinning on invalid SSL servers
4053 // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=631590
4054 // however, we can set the select WAY down and it will retry quickly, but keep it from spinning at 100%
4055 tv.tv_usec = iQuickReset;
4056 tv.tv_sec = 0;
4057 }
4058 }
4059 else
4060 {
4061 FDSetCheck( iRSock, miiReadyFds, ECT_Read );
4062 }
4063
4064 if( pcSock->GetSSL() && pcSock->GetType() != Csock::LISTENER )
4065 {
4066 if( pcSock->GetPending() > 0 && !pcSock->IsReadPaused() )
4067 SelectSock( mpeSocks, SUCCESS, pcSock );
4068 }
4069 }
4070
4071 // old fashion select, go fer it
4072 int iSel;
4073
4074 if( !mpeSocks.empty() ) // .1 ms pause to see if anything else is ready (IE if there is SSL data pending, don't wait too long)
4075 {
4076 tv.tv_usec = iQuickReset;
4077 tv.tv_sec = 0;
4078 }
4079 else if( !this->empty() && !bHasAvailSocks )
4080 {
4081 tv.tv_usec = iQuickReset;
4082 tv.tv_sec = 0;
4083 }
4084
4085 iSel = Select( miiReadyFds, &tv );
4086
4087 if( iSel == 0 )
4088 {
4089 if( mpeSocks.empty() )
4090 m_errno = SELECT_TIMEOUT;
4091 else
4092 m_errno = SUCCESS;
4093 #ifdef HAVE_C_ARES
4094 // run through ares channels and process timeouts
4095 for( size_t uSock = 0; uSock < this->size(); ++uSock )
4096 {
4097 Csock * pcSock = this->at( uSock );
4098 ares_channel pChannel = pcSock->GetAresChannel();
4099 if( pChannel )
4100 ares_process_fd( pChannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD );
4101 }
4102 #endif /* HAVE_C_ARES */
4103
4104 return;
4105 }
4106
4107 if( iSel == -1 && errno == EINTR )
4108 {
4109 if( mpeSocks.empty() )
4110 m_errno = SELECT_TRYAGAIN;
4111 else
4112 m_errno = SUCCESS;
4113
4114 return;
4115 }
4116 else if( iSel == -1 )
4117 {
4118 if( mpeSocks.empty() )
4119 m_errno = SELECT_ERROR;
4120 else
4121 m_errno = SUCCESS;
4122
4123 return;
4124 }
4125 else
4126 {
4127 m_errno = SUCCESS;
4128 }
4129
4130 CheckFDs( miiReadyFds );
4131
4132 // find out wich one is ready
4133 for( size_t i = 0; i < this->size(); ++i )
4134 {
4135 Csock * pcSock = this->at( i );
4136
4137 #ifdef HAVE_C_ARES
4138 ares_channel pChannel = pcSock->GetAresChannel();
4139 if( pChannel )
4140 {
4141 ares_socket_t aiAresSocks[1];
4142 aiAresSocks[0] = ARES_SOCKET_BAD;
4143 ares_getsock( pChannel, aiAresSocks, 1 );
4144 if( FDHasCheck( aiAresSocks[0], miiReadyFds, ECT_Read ) || FDHasCheck( aiAresSocks[0], miiReadyFds, ECT_Write ) )
4145 ares_process_fd( pChannel, aiAresSocks[0], aiAresSocks[0] );
4146 }
4147 #endif /* HAVE_C_ARES */
4148 pcSock->CheckFDs( miiReadyFds );
4149
4150 if( pcSock->GetConState() != Csock::CST_OK )
4151 continue;
4152
4153 cs_sock_t & iRSock = pcSock->GetRSock();
4154 cs_sock_t & iWSock = pcSock->GetWSock();
4155 EMessages iErrno = SUCCESS;
4156
4157 if( iRSock == CS_INVALID_SOCK || iWSock == CS_INVALID_SOCK )
4158 {
4159 // trigger a success so it goes through the normal motions
4160 // and an error is produced
4161 SelectSock( mpeSocks, SUCCESS, pcSock );
4162 continue; // watch for invalid socks
4163 }
4164
4165 if( FDHasCheck( iWSock, miiReadyFds, ECT_Write ) )
4166 {
4167 if( iSel > 0 )
4168 {
4169 iErrno = SUCCESS;
4170 if( pcSock->HasWriteBuffer() && pcSock->IsConnected() )
4171 {
4172 // write whats in the socks send buffer
4173 if( !pcSock->Write( "" ) )
4174 {
4175 // write failed, sock died :(
4176 iErrno = SELECT_ERROR;
4177 }
4178 }
4179 }
4180 else
4181 {
4182 iErrno = SELECT_ERROR;
4183 }
4184
4185 SelectSock( mpeSocks, iErrno, pcSock );
4186
4187 }
4188 else if( FDHasCheck( iRSock, miiReadyFds, ECT_Read ) )
4189 {
4190 if( iSel > 0 )
4191 iErrno = SUCCESS;
4192 else
4193 iErrno = SELECT_ERROR;
4194
4195 if( pcSock->GetType() != Csock::LISTENER )
4196 {
4197 SelectSock( mpeSocks, iErrno, pcSock );
4198 }
4199 else // someone is coming in!
4200 {
4201 CS_STRING sHost;
4202 uint16_t port;
4203 cs_sock_t inSock = pcSock->Accept( sHost, port );
4204
4205 if( inSock != CS_INVALID_SOCK )
4206 {
4207 if( Csock::TMO_ACCEPT & pcSock->GetTimeoutType() )
4208 pcSock->ResetTimer(); // let them now it got dinged
4209
4210 // if we have a new sock, then add it
4211 Csock * NewpcSock = ( Csock * )pcSock->GetSockObj( sHost, port );
4212
4213 if( !NewpcSock )
4214 NewpcSock = GetSockObj( sHost, port );
4215
4216 NewpcSock->SetType( Csock::INBOUND );
4217 NewpcSock->SetRSock( inSock );
4218 NewpcSock->SetWSock( inSock );
4219 NewpcSock->SetIPv6( pcSock->GetIPv6() );
4220
4221 bool bAddSock = true;
4222 #ifdef HAVE_LIBSSL
4223 //
4224 // is this ssl ?
4225 if( pcSock->GetSSL() )
4226 {
4227 NewpcSock->SetCipher( pcSock->GetCipher() );
4228 NewpcSock->SetDHParamLocation( pcSock->GetDHParamLocation() );
4229 NewpcSock->SetKeyLocation( pcSock->GetKeyLocation() );
4230 NewpcSock->SetPemLocation( pcSock->GetPemLocation() );
4231 NewpcSock->SetPemPass( pcSock->GetPemPass() );
4232 NewpcSock->SetRequireClientCertFlags( pcSock->GetRequireClientCertFlags() );
4233 bAddSock = NewpcSock->AcceptSSL();
4234 }
4235
4236 #endif /* HAVE_LIBSSL */
4237 if( bAddSock )
4238 {
4239 // set the name of the listener
4240 NewpcSock->SetParentSockName( pcSock->GetSockName() );
4241 NewpcSock->SetRate( pcSock->GetRateBytes(), pcSock->GetRateTime() );
4242 #ifdef HAVE_ICU
4243 NewpcSock->SetEncoding( pcSock->GetEncoding() );
4244 #endif
4245 if( NewpcSock->GetSockName().empty() )
4246 {
4247 std::stringstream s;
4248 s << sHost << ":" << port;
4249 AddSock( NewpcSock, s.str() );
4250 }
4251 else
4252 {
4253 AddSock( NewpcSock, NewpcSock->GetSockName() );
4254 }
4255 }
4256 else
4257 {
4258 CS_Delete( NewpcSock );
4259 }
4260 }
4261 #ifdef _WIN32
4262 else if( GetSockError() != WSAEWOULDBLOCK )
4263 #else /* _WIN32 */
4264 else if( GetSockError() != EAGAIN )
4265 #endif /* _WIN32 */
4266 {
4267 pcSock->CallSockError( GetSockError() );
4268 }
4269 }
4270 }
4271 }
4272 }
4273
MinimizeTime(timeval & min,const timeval & another)4274 inline void MinimizeTime( timeval& min, const timeval& another )
4275 {
4276 if( timercmp( &min, &another, > ) )
4277 {
4278 min = another;
4279 }
4280 }
4281
GetDynamicSleepTime(const timeval & tNow,const timeval & tMaxResolution) const4282 timeval CSocketManager::GetDynamicSleepTime( const timeval& tNow, const timeval& tMaxResolution ) const
4283 {
4284 timeval tNextRunTime;
4285 timeradd( &tNow, &tMaxResolution, &tNextRunTime );
4286 std::vector<Csock *>::const_iterator it;
4287 // This is safe, because we don't modify the vector.
4288 std::vector<Csock *>::const_iterator it_end = this->end();
4289 for( it = this->begin(); it != it_end; ++it )
4290 {
4291 Csock* pSock = *it;
4292
4293 if( pSock->GetConState() != Csock::CST_OK )
4294 tNextRunTime = tNow; // this is in a nebulous state, need to let it proceed like normal
4295
4296 time_t iTimeoutInSeconds = pSock->GetTimeout();
4297 if( iTimeoutInSeconds > 0 )
4298 {
4299 timeval tNextTimeout;
4300 tNextTimeout.tv_sec = pSock->GetNextCheckTimeout( 0 ); // TODO convert socket timeouts to timeval too?
4301 tNextTimeout.tv_usec = 0;
4302 MinimizeTime( tNextRunTime, tNextTimeout );
4303 }
4304
4305 const std::vector<CCron *> & vCrons = pSock->GetCrons();
4306 std::vector<CCron *>::const_iterator cit;
4307 std::vector<CCron *>::const_iterator cit_end = vCrons.end();
4308 for( cit = vCrons.begin(); cit != cit_end; ++cit )
4309 MinimizeTime( tNextRunTime, ( *cit )->GetNextRun() );
4310 }
4311 std::vector<CCron *>::const_iterator cit;
4312 std::vector<CCron *>::const_iterator cit_end = m_vcCrons.end();
4313 for( cit = m_vcCrons.begin(); cit != cit_end; ++cit )
4314 MinimizeTime( tNextRunTime, ( *cit )->GetNextRun() );
4315
4316 timeval tReturnValue;
4317 if( timercmp( &tNextRunTime, &tNow, < ) )
4318 {
4319 timerclear( &tReturnValue );
4320 return( tReturnValue ); // smallest unit possible
4321 }
4322 timersub( &tNextRunTime, &tNow, &tReturnValue );
4323 MinimizeTime( tReturnValue, tMaxResolution );
4324 return( tReturnValue );
4325 }
4326
SelectSock(std::map<Csock *,EMessages> & mpeSocks,EMessages eErrno,Csock * pcSock)4327 void CSocketManager::SelectSock( std::map<Csock *, EMessages> & mpeSocks, EMessages eErrno, Csock * pcSock )
4328 {
4329 if( mpeSocks.find( pcSock ) != mpeSocks.end() )
4330 return;
4331
4332 mpeSocks[pcSock] = eErrno;
4333 }
4334
4335