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