]> jfr.im git - irc/rizon/znc.git/blame - Csocket.cpp
Write forceserver and webircpassword to conf
[irc/rizon/znc.git] / Csocket.cpp
CommitLineData
ed120ee5 1/** @file
8a769a6f 2*
9a2e17c6 3* Copyright (c) 1999-2009 Jim Hull <imaginos@imaginos.net>
8a769a6f 4* All rights reserved
79aaf3d5 5*
6* Redistribution and use in source and binary forms, with or without modification,
8a769a6f 7* are permitted provided that the following conditions are met:
79aaf3d5 8* Redistributions of source code must retain the above copyright notice, this
8a769a6f 9* list of conditions and the following disclaimer.
79aaf3d5 10* Redistributions in binary form must reproduce the above copyright notice, this list
8a769a6f 11* of conditions and the following disclaimer in the documentation and/or other materials
12* provided with the distribution.
79aaf3d5 13* Redistributions in any form must be accompanied by information on how to obtain
ed120ee5 14* complete source code for this software and any accompanying software that uses this software.
79aaf3d5 15* The source code must either be included in the distribution or be available for no more than
16* the cost of distribution plus a nominal fee, and must be freely redistributable
17* under reasonable conditions. For an executable file, complete source code means the source
18* code for all modules it contains. It does not include source code for modules or files
8a769a6f 19* that typically accompany the major components of the operating system on which the executable file runs.
20*
79aaf3d5 21* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
22* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
ed120ee5 23* OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF THIS SOFTWARE BE LIABLE FOR ANY DIRECT,
79aaf3d5 24* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
8a769a6f 28* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*
30*
8a769a6f 31*/
32
8a769a6f 33#include "Csocket.h"
b63b7d03 34#ifdef __NetBSD__
35#include <sys/param.h>
36#endif /* __NetBSD__ */
37
e77adef0 38#ifdef HAVE_LIBSSL
88e7f093 39#include <stdio.h>
e77adef0 40#include <openssl/conf.h>
41#include <openssl/engine.h>
42#endif /* HAVE_LIBSSL */
43
493d5154 44#include <list>
45
b63b7d03 46#define CS_SRANDBUFFER 128
8a769a6f 47
2d1602ec 48using namespace std;
49
f1515361 50#define CREATE_ARES_VER( a, b, c ) ((a<<16)|(b<<8)|c)
25ef3439 51
2d1602ec 52#ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
53namespace Csocket
54{
55#endif /* _NO_CSOCKET_NS */
56
b63b7d03 57static int g_iCsockSSLIdx = 0; //!< this get setup once in InitSSL
58int GetCsockClassIdx()
59{
60 return( g_iCsockSSLIdx );
61}
62
c6664d5a 63#ifdef _WIN32
583b91f7 64static const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
65{
66 if( af == AF_INET )
67 {
68 struct sockaddr_in in;
69 memset(&in, 0, sizeof(in));
70 in.sin_family = AF_INET;
71 memcpy( &in.sin_addr, src, sizeof(struct in_addr) );
72 getnameinfo( (struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST );
73 return dst;
74 }
75 else if( af == AF_INET6 )
76 {
77 struct sockaddr_in6 in;
78 memset( &in, 0, sizeof(in) );
79 in.sin6_family = AF_INET6;
80 memcpy( &in.sin6_addr, src, sizeof(struct in_addr6) );
81 getnameinfo( (struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST );
82 return dst;
83 }
84 return( NULL );
85}
86
5ea1f8cc 87#if defined(_WIN32) && (!defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600))
88//! thanks to KiNgMaR @ #znc for this wrapper
89static int inet_pton( int af, const char *src, void *dst )
90{
91 sockaddr_storage aAddress;
92 int iAddrLen = sizeof( sockaddr_storage );
93 memset( &aAddress, 0, iAddrLen );
94 char *pTmp = strdup( src );
95 aAddress.ss_family = af; // this is important:
96 // The function fails if the sin_family member of the SOCKADDR_IN structure is not set to AF_INET or AF_INET6.
97 int iRet = WSAStringToAddressA( pTmp, af, NULL, (sockaddr *)&aAddress, &iAddrLen );
98 free( pTmp );
99 if( iRet == 0 )
100 {
101 if( af == AF_INET6 )
102 memcpy(dst, &((sockaddr_in6 *)&aAddress)->sin6_addr, sizeof(in6_addr));
103 else
104 memcpy(dst, &((sockaddr_in *)&aAddress)->sin_addr, sizeof(in_addr));
105 return( 1 );
106 }
107 return( -1 );
108}
109#endif
110
25ef3439 111static inline void set_non_blocking(cs_sock_t fd)
c6664d5a 112{
113 u_long iOpts = 1;
114 ioctlsocket( fd, FIONBIO, &iOpts );
115}
116
25ef3439 117static inline void set_blocking(cs_sock_t fd)
c6664d5a 118{
119 u_long iOpts = 0;
120 ioctlsocket( fd, FIONBIO, &iOpts );
121}
122
25ef3439 123static inline void set_close_on_exec(cs_sock_t fd)
c6664d5a 124{
125 // TODO add this for windows
126 // see http://gcc.gnu.org/ml/java-patches/2002-q1/msg00696.html
127 // for infos on how to do this
128}
129#else
25ef3439 130static inline void set_non_blocking(cs_sock_t fd)
c6664d5a 131{
132 int fdflags = fcntl(fd, F_GETFL, 0);
133 if ( fdflags < 0 )
134 return; // Ignore errors
135 fcntl( fd, F_SETFL, fdflags|O_NONBLOCK );
136}
137
25ef3439 138static inline void set_blocking(cs_sock_t fd)
c6664d5a 139{
140 int fdflags = fcntl(fd, F_GETFL, 0);
141 if ( fdflags < 0 )
142 return; // Ignore errors
143 fdflags &= ~O_NONBLOCK;
144 fcntl( fd, F_SETFL, fdflags );
145}
146
25ef3439 147static inline void set_close_on_exec(cs_sock_t fd)
c6664d5a 148{
149 int fdflags = fcntl(fd, F_GETFD, 0);
150 if ( fdflags < 0 )
151 return; // Ignore errors
152 fcntl( fd, F_SETFD, fdflags|FD_CLOEXEC);
153}
154#endif /* _WIN32 */
155
babc0f9f 156#ifdef HAVE_LIBSSL
b63b7d03 157Csock *GetCsockFromCTX( X509_STORE_CTX *pCTX )
158{
159 Csock *pSock = NULL;
160 SSL *pSSL = (SSL *)X509_STORE_CTX_get_ex_data( pCTX, SSL_get_ex_data_X509_STORE_CTX_idx() );
161 if( pSSL )
162 pSock = (Csock *)SSL_get_ex_data( pSSL, GetCsockClassIdx() );
163 return( pSock );
164}
babc0f9f 165#endif /* HAVE_LIBSSL */
166
b63b7d03 167
168#ifndef HAVE_IPV6
169
170// this issue here is getaddrinfo has a significant behavior difference when dealing with round robin dns on an
171// ipv4 network. This is not desirable IMHO. so when this is compiled without ipv6 support backwards compatibility
172// is maintained.
173
174static int __GetHostByName( const CS_STRING & sHostName, struct in_addr *paddr, u_int iNumRetries )
175{
176 int iReturn = HOST_NOT_FOUND;
177 struct hostent *hent = NULL;
178#ifdef __linux__
179 char hbuff[2048];
180 struct hostent hentbuff;
181
182 int err;
183 for( u_int a = 0; a < iNumRetries; a++ )
184 {
185 memset( (char *)hbuff, '\0', 2048 );
186 iReturn = gethostbyname_r( sHostName.c_str(), &hentbuff, hbuff, 2048, &hent, &err );
187
188 if ( iReturn == 0 )
189 break;
190
191 if ( iReturn != TRY_AGAIN )
294c82a9 192 {
193 CS_DEBUG( "gethostyname_r: " << hstrerror( h_errno ) );
b63b7d03 194 break;
294c82a9 195 }
b63b7d03 196
b63b7d03 197 }
198 if ( ( !hent ) && ( iReturn == 0 ) )
199 iReturn = HOST_NOT_FOUND;
200#else
294c82a9 201 for( u_int a = 0; a < iNumRetries; a++ )
202 {
203 iReturn = HOST_NOT_FOUND;
204 hent = gethostbyname( sHostName.c_str() );
b63b7d03 205
294c82a9 206 if ( hent )
207 {
208 iReturn = 0;
209 break;
210 }
211
212 if( h_errno != TRY_AGAIN )
213 {
583b91f7 214#ifndef _WIN32
294c82a9 215 CS_DEBUG( "gethostyname: " << hstrerror( h_errno ) );
583b91f7 216#endif /* _WIN32 */
294c82a9 217 break;
218 }
219 }
b63b7d03 220
221#endif /* __linux__ */
222
223 if ( iReturn == 0 )
224 memcpy( &paddr->s_addr, hent->h_addr_list[0], sizeof( paddr->s_addr ) );
225
6faf0980 226 return( iReturn == TRY_AGAIN ? EAGAIN : iReturn );
b63b7d03 227}
228#endif /* !HAVE_IPV6 */
229
6ce29e77 230#ifdef HAVE_C_ARES
231void Csock::FreeAres()
232{
233 if( m_pARESChannel )
234 {
235 ares_destroy( m_pARESChannel );
236 m_pARESChannel = NULL;
237 }
238}
239#endif /* HAVE_C_ARES */
240
241#ifdef HAVE_C_ARES
1b51f15d 242static void AresHostCallback( void *pArg, int status, int timeouts, struct hostent *hent )
6ce29e77 243{
244 Csock *pSock = (Csock *)pArg;
88e7f093 245 if( status == ARES_SUCCESS && hent && hent->h_addr_list[0] != NULL )
6ce29e77 246 {
247 CSSockAddr *pSockAddr = pSock->GetCurrentAddr();
248 if( hent->h_addrtype == AF_INET )
249 {
250 pSock->SetIPv6( false );
251 memcpy( pSockAddr->GetAddr(), hent->h_addr_list[0], sizeof( *(pSockAddr->GetAddr()) ) );
252 }
253#ifdef HAVE_IPV6
254 else if( hent->h_addrtype == AF_INET6 )
255 {
256 pSock->SetIPv6( true );
257 memcpy( pSockAddr->GetAddr6(), hent->h_addr_list[0], sizeof( *(pSockAddr->GetAddr6()) ) );
258 }
259#endif /* HAVE_IPV6 */
260 else
261 {
262 status = ARES_ENOTFOUND;
263 }
264 }
265 else
266 {
267 CS_DEBUG( ares_strerror( status ) );
88e7f093
US
268 if( status == ARES_SUCCESS )
269 {
270 CS_DEBUG("Received ARES_SUCCESS without any useful reply, using NODATA instead");
271 status = ARES_ENODATA;
272 }
6ce29e77 273 }
274 pSock->SetAresFinished( status );
275}
276#endif /* HAVE_C_ARES */
277
9d4be439 278int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockAddr )
279{
b63b7d03 280#ifndef HAVE_IPV6
493d5154 281 // if ipv6 is not enabled, then simply use gethostbyname, nothing special outside of this is done
b63b7d03 282 if( pSock )
283 pSock->SetIPv6( false );
284 csSockAddr.SetIPv6( false );
285 if( __GetHostByName( sHostname, csSockAddr.GetAddr(), 3 ) == 0 )
286 return( 0 );
be3edeee 287
b63b7d03 288#else /* HAVE_IPV6 */
9d4be439 289 struct addrinfo *res = NULL;
290 struct addrinfo hints;
291 memset( (struct addrinfo *)&hints, '\0', sizeof( hints ) );
acb90125 292 hints.ai_family = csSockAddr.GetAFRequire();
293
9d4be439 294 hints.ai_socktype = SOCK_STREAM;
295 hints.ai_protocol = IPPROTO_TCP;
a89fa461 296#ifdef AI_ADDRCONFIG
493d5154 297 // this is suppose to eliminate host from appearing that this system can not support
298 hints.ai_flags = AI_ADDRCONFIG;
a89fa461 299#endif /* AI_ADDRCONFIG */
300
4059f8c3 301 if( pSock && ( pSock->GetType() == Csock::LISTENER || pSock->GetConState() == Csock::CST_BINDVHOST ) )
493d5154 302 { // when doing a dns for bind only, set the AI_PASSIVE flag as suggested by the man page
303 hints.ai_flags |= AI_PASSIVE;
304 }
a89fa461 305
9d4be439 306 int iRet = getaddrinfo( sHostname.c_str(), NULL, &hints, &res );
307 if( iRet == EAI_AGAIN )
493d5154 308 return( EAGAIN ); // need to return telling the user to try again
9d4be439 309 else if( ( iRet == 0 ) && ( res ) )
88e7f093 310 {
493d5154 311 std::list<struct addrinfo *> lpTryAddrs;
312 bool bFound = false;
9d4be439 313 for( struct addrinfo *pRes = res; pRes; pRes = pRes->ai_next )
493d5154 314 { // pass through the list building out a lean list of candidates to try. AI_CONFIGADDR doesn't always seem to work
577d7528 315#ifdef __sun
316 if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP && pRes->ai_protocol != IPPROTO_IP ) )
317#else
9d4be439 318 if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP ) )
577d7528 319#endif /* __sun work around broken impl of getaddrinfo */
5e8c075c 320 continue;
88e7f093 321
acb90125 322 if( ( csSockAddr.GetAFRequire() != CSSockAddr::RAF_ANY ) && ( pRes->ai_family != csSockAddr.GetAFRequire() ) )
323 continue; // they requested a special type, so be certain we woop past anything unwanted
493d5154 324 lpTryAddrs.push_back( pRes );
325 }
326 for( std::list<struct addrinfo *>::iterator it = lpTryAddrs.begin(); it != lpTryAddrs.end(); )
327 { // cycle through these, leaving the last iterator for the outside caller to call, so if there is an error it can call the events
328 struct addrinfo * pRes = *it;
329 bool bTryConnect = false;
9d4be439 330 if( pRes->ai_family == AF_INET )
331 {
493d5154 332 if( pSock )
333 pSock->SetIPv6( false );
334 csSockAddr.SetIPv6( false );
335 struct sockaddr_in *pTmp = (struct sockaddr_in *)pRes->ai_addr;
336 memcpy( csSockAddr.GetAddr(), &(pTmp->sin_addr), sizeof( *(csSockAddr.GetAddr()) ) );
337 if( pSock && pSock->GetConState() == Csock::CST_DESTDNS && pSock->GetType() == Csock::OUTBOUND )
338 {
339 bTryConnect = true;
340 }
341 else
342 {
343 bFound = true;
344 break;
345 }
9d4be439 346 }
9d4be439 347 else if( pRes->ai_family == AF_INET6 )
348 {
493d5154 349 if( pSock )
350 pSock->SetIPv6( true );
351 csSockAddr.SetIPv6( true );
352 struct sockaddr_in6 *pTmp = (struct sockaddr_in6 *)pRes->ai_addr;
353 memcpy( csSockAddr.GetAddr6(), &(pTmp->sin6_addr), sizeof( *(csSockAddr.GetAddr6()) ) );
354 if( pSock && pSock->GetConState() == Csock::CST_DESTDNS && pSock->GetType() == Csock::OUTBOUND )
355 {
356 bTryConnect = true;
357 }
358 else
359 {
360 bFound = true;
361 break;
362 }
b63b7d03 363 }
493d5154 364
365 it++; // increment the iterator her so we know if its the last element or not
366
367 if( bTryConnect && it != lpTryAddrs.end() )
368 { // save the last attempt for the outer loop, the issue then becomes that the error is thrown on the last failure
369 if( pSock->CreateSocksFD() && pSock->Connect( pSock->GetBindHost(), true ) )
370 {
371 pSock->SetSkipConnect( true ); // this tells the socket that the connection state has been started
372 bFound = true;
373 break;
374 }
ebbc126b 375 pSock->CloseSocksFD();
9d4be439 376 }
493d5154 377 else if( bTryConnect )
b63b7d03 378 {
493d5154 379 bFound = true;
b63b7d03 380 }
381 }
b63b7d03 382
9d4be439 383 freeaddrinfo( res );
493d5154 384 if( bFound ) // the data pointed to here is invalid now, but the pointer itself is a good test
1fb00397 385 {
9d4be439 386 return( 0 );
1fb00397 387 }
61920317 388 }
b63b7d03 389#endif /* ! HAVE_IPV6 */
9d4be439 390 return( ETIMEDOUT );
487b6b65 391}
9d4be439 392
c03bd915 393bool InitCsocket()
394{
395#ifdef _WIN32
396 WSADATA wsaData;
397 int iResult = WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
398 if( iResult != NO_ERROR )
399 return( false );
400#endif /* _WIN32 */
f1515361 401#ifdef HAVE_C_ARES
402#if ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 )
403 if( ares_library_init( ARES_LIB_INIT_ALL ) != 0 )
404 return( false );
405#endif /* ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 ) */
406#endif /* HAVE_C_ARES */
c03bd915 407#ifdef HAVE_LIBSSL
408 if( !InitSSL() )
409 return( false );
410#endif /* HAVE_LIBSSL */
411 return( true );
412}
413
414void ShutdownCsocket()
415{
416#ifdef HAVE_LIBSSL
e77adef0 417 ERR_remove_state(0);
418 ENGINE_cleanup();
419 CONF_modules_unload(1);
c03bd915 420 ERR_free_strings();
e77adef0 421 EVP_cleanup();
422 CRYPTO_cleanup_all_ex_data();
c03bd915 423#endif /* HAVE_LIBSSL */
f1515361 424#ifdef HAVE_C_ARES
425#if ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 )
426 ares_library_cleanup();
427#endif /* ARES_VERSION >= CREATE_ARES_VER( 1, 6, 1 ) */
428#endif /* HAVE_C_ARES */
c03bd915 429#ifdef _WIN32
430 WSACleanup();
431#endif /* _WIN32 */
432}
433
8a769a6f 434#ifdef HAVE_LIBSSL
435bool InitSSL( ECompType eCompressionType )
436{
437 SSL_load_error_strings();
438 if ( SSL_library_init() != 1 )
439 {
440 CS_DEBUG( "SSL_library_init() failed!" );
441 return( false );
442 }
443
2d1602ec 444#ifndef _WIN32
8a769a6f 445 if ( access( "/dev/urandom", R_OK ) == 0 )
446 RAND_load_file( "/dev/urandom", 1024 );
447 else if( access( "/dev/random", R_OK ) == 0 )
448 RAND_load_file( "/dev/random", 1024 );
449 else
450 {
451 CS_DEBUG( "Unable to locate entropy location! Tried /dev/urandom and /dev/random" );
452 return( false );
453 }
2d1602ec 454#endif /* _WIN32 */
8a769a6f 455
456 COMP_METHOD *cm = NULL;
457
458 if ( CT_ZLIB & eCompressionType )
459 {
460 cm = COMP_zlib();
461 if ( cm )
462 SSL_COMP_add_compression_method( CT_ZLIB, cm );
463 }
464
dba60545 465#if 0
8a769a6f 466 if ( CT_RLE & eCompressionType )
467 {
468 cm = COMP_rle();
469 if ( cm )
470 SSL_COMP_add_compression_method( CT_RLE, cm );
471 }
dba60545 472#endif
8a769a6f 473
b63b7d03 474 // setting this up once in the begining
475 g_iCsockSSLIdx = SSL_get_ex_new_index( 0, (void *)"CsockGlobalIndex", NULL, NULL, NULL);
476
8a769a6f 477 return( true );
478}
479
480void SSLErrors( const char *filename, u_int iLineNum )
481{
482 unsigned long iSSLError = 0;
483 while( ( iSSLError = ERR_get_error() ) != 0 )
484 {
485 CS_DEBUG( "at " << filename << ":" << iLineNum );
486 char szError[512];
487 memset( (char *) szError, '\0', 512 );
488 ERR_error_string_n( iSSLError, szError, 511 );
e48a6be4 489 if ( *szError )
8a769a6f 490 CS_DEBUG( szError );
491 }
492}
493#endif /* HAVE_LIBSSL */
494
4c5d81b2 495void __Perror( const CS_STRING & s, const char *pszFile, unsigned int iLineNo )
8a769a6f 496{
88e7f093 497#if defined( sgi ) || defined(__sun) || defined(_WIN32) || (defined(__NetBSD_Version__) && __NetBSD_Version__ < 4000000000)
4c5d81b2 498 std::cerr << s << "(" << pszFile << ":" << iLineNo << "): " << strerror( GetSockError() ) << endl;
8a769a6f 499#else
500 char buff[512];
501 memset( (char *)buff, '\0', 512 );
2d1602ec 502 if ( strerror_r( GetSockError(), buff, 511 ) == 0 )
4c5d81b2 503 std::cerr << s << "(" << pszFile << ":" << iLineNo << "): " << buff << endl;
8a769a6f 504 else
4c5d81b2 505 std::cerr << s << "(" << pszFile << ":" << iLineNo << "): Unknown Error Occured " << endl;
8a769a6f 506#endif /* __sun */
507}
508
509unsigned long long millitime()
510{
8a769a6f 511 unsigned long long iTime = 0;
2d1602ec 512#ifdef _WIN32
513 struct timeb tm;
514 ftime( &tm );
515 iTime = tm.time * 1000;
516 iTime += tm.millitm;
517#else
518 struct timeval tv;
8a769a6f 519 gettimeofday( &tv, NULL );
520 iTime = (unsigned long long )tv.tv_sec * 1000;
79aaf3d5 521 iTime += ( (unsigned long long)tv.tv_usec / 1000 );
2d1602ec 522#endif /* _WIN32 */
8a769a6f 523 return( iTime );
524}
525
2d1602ec 526#ifndef _NO_CSOCKET_NS // some people may not want to use a namespace
527}
528using namespace Csocket;
529#endif /* _NO_CSOCKET_NS */
530
79aaf3d5 531CCron::CCron()
8a769a6f 532{
533 m_iCycles = 0;
534 m_iMaxCycles = 0;
535 m_bActive = true;
536 m_iTime = 0;
537 m_iTimeSequence = 60;
538 m_bPause = false;
c3b6a4b2 539 m_bRunOnNextCall = false;
8a769a6f 540}
541
2bbdb72a 542void CCron::run( time_t & iNow )
8a769a6f 543{
544 if ( m_bPause )
545 return;
546
2bbdb72a 547 if( iNow == 0 )
548 iNow = time( NULL );
549
c3b6a4b2 550 if ( ( m_bActive ) && ( iNow >= m_iTime || m_bRunOnNextCall ) )
8a769a6f 551 {
c3b6a4b2 552 m_bRunOnNextCall = false; // Setting this here because RunJob() could set it back to true
8a769a6f 553 RunJob();
554
555 if ( ( m_iMaxCycles > 0 ) && ( ++m_iCycles >= m_iMaxCycles ) )
556 m_bActive = false;
557 else
30cf3a30 558 m_iTime = iNow + m_iTimeSequence;
8a769a6f 559 }
560}
561
8a769a6f 562void CCron::StartMaxCycles( int TimeSequence, u_int iMaxCycles )
563{
564 m_iTimeSequence = TimeSequence;
565 m_iTime = time( NULL ) + m_iTimeSequence;
566 m_iMaxCycles = iMaxCycles;
567}
568
8a769a6f 569void CCron::Start( int TimeSequence )
570{
571 m_iTimeSequence = TimeSequence;
572 m_iTime = time( NULL ) + m_iTimeSequence;
573 m_iMaxCycles = 0;
574}
575
8a769a6f 576void CCron::Stop()
577{
578 m_bActive = false;
579}
580
8a769a6f 581void CCron::Pause()
582{
583 m_bPause = true;
584}
585
8a769a6f 586void CCron::UnPause()
587{
588 m_bPause = false;
589}
590
591int CCron::GetInterval() const { return( m_iTimeSequence ); }
592u_int CCron::GetMaxCycles() const { return( m_iMaxCycles ); }
593u_int CCron::GetCyclesLeft() const { return( ( m_iMaxCycles > m_iCycles ? ( m_iMaxCycles - m_iCycles ) : 0 ) ); }
594
8a769a6f 595bool CCron::isValid() { return( m_bActive ); }
596const CS_STRING & CCron::GetName() const { return( m_sName ); }
597void CCron::SetName( const CS_STRING & sName ) { m_sName = sName; }
d8f4e319 598void CCron::RunJob() { CS_DEBUG( "This should be overridden" ); }
8a769a6f 599
79aaf3d5 600Csock::Csock( int itimeout )
601{
ed120ee5 602#ifdef HAVE_LIBSSL
603 m_pCerVerifyCB = NULL;
604#endif /* HAVE_LIBSSL */
79aaf3d5 605 Init( "", 0, itimeout );
8a769a6f 606}
607
6dbb196e 608Csock::Csock( const CS_STRING & sHostname, u_short iport, int itimeout )
8a769a6f 609{
ed120ee5 610#ifdef HAVE_LIBSSL
611 m_pCerVerifyCB = NULL;
612#endif /* HAVE_LIBSSL */
8a769a6f 613 Init( sHostname, iport, itimeout );
614}
615
616// override this for accept sockets
6dbb196e 617Csock *Csock::GetSockObj( const CS_STRING & sHostname, u_short iPort )
79aaf3d5 618{
619 return( NULL );
8a769a6f 620}
621
2d1602ec 622#ifdef _WIN32
623#define CS_CLOSE closesocket
624#else
625#define CS_CLOSE close
626#endif /* _WIN32 */
627
8a769a6f 628Csock::~Csock()
629{
6ce29e77 630#ifdef HAVE_C_ARES
631 if( m_pARESChannel )
632 ares_cancel( m_pARESChannel );
633 FreeAres();
634#endif /* HAVE_C_ARES */
635
ba619d0b 636#ifdef HAVE_LIBSSL
637 FREE_SSL();
638 FREE_CTX();
639#endif /* HAVE_LIBSSL */
640
ebbc126b 641 CloseSocksFD();
642
643 // delete any left over crons
644 for( vector<CCron *>::size_type i = 0; i < m_vcCrons.size(); i++ )
645 CS_Delete( m_vcCrons[i] );
646}
647
648void Csock::CloseSocksFD()
649{
8a769a6f 650 if ( m_iReadSock != m_iWriteSock )
651 {
c7546c0c 652 if( m_iReadSock != CS_INVALID_SOCK )
9736711c 653 CS_CLOSE( m_iReadSock );
c7546c0c 654 if( m_iWriteSock != CS_INVALID_SOCK )
9736711c 655 CS_CLOSE( m_iWriteSock );
b18e42df 656 } else if( m_iReadSock != CS_INVALID_SOCK )
2d1602ec 657 CS_CLOSE( m_iReadSock );
8a769a6f 658
25ef3439 659 m_iReadSock = CS_INVALID_SOCK;
660 m_iWriteSock = CS_INVALID_SOCK;
8a769a6f 661}
662
ebbc126b 663
9736711c 664void Csock::Dereference()
665{
25ef3439 666 m_iWriteSock = m_iReadSock = CS_INVALID_SOCK;
9736711c 667
668#ifdef HAVE_LIBSSL
669 m_ssl = NULL;
670 m_ssl_ctx = NULL;
671#endif /* HAVE_LIBSSL */
672
673 m_vcCrons.clear();
9210bdc9 674 Close( CLT_DEREFERENCE );
9736711c 675}
676
677void Csock::Copy( const Csock & cCopy )
678{
b63b7d03 679 m_iTcount = cCopy.m_iTcount;
680 m_iLastCheckTimeoutTime = cCopy.m_iLastCheckTimeoutTime;
25ef3439 681 m_uPort = cCopy.m_uPort;
be3edeee 682 m_iRemotePort = cCopy.m_iRemotePort;
9736711c 683 m_iLocalPort = cCopy.m_iLocalPort;
684 m_iReadSock = cCopy.m_iReadSock;
685 m_iWriteSock = cCopy.m_iWriteSock;
2137d5a7 686 m_itimeout = cCopy.m_itimeout;
be3edeee 687 m_iConnType = cCopy.m_iConnType;
9736711c 688 m_iMethod = cCopy.m_iMethod;
689 m_bssl = cCopy.m_bssl;
690 m_bIsConnected = cCopy.m_bIsConnected;
691 m_bBLOCK = cCopy.m_bBLOCK;
9736711c 692 m_bsslEstablished = cCopy.m_bsslEstablished;
be3edeee 693 m_bEnableReadLine = cCopy.m_bEnableReadLine;
be3edeee 694 m_bPauseRead = cCopy.m_bPauseRead;
9736711c 695 m_shostname = cCopy.m_shostname;
be3edeee 696 m_sbuffer = cCopy.m_sbuffer;
697 m_sSockName = cCopy.m_sSockName;
698 m_sPemFile = cCopy.m_sPemFile;
699 m_sCipherType = cCopy.m_sCipherType;
700 m_sParentName = cCopy.m_sParentName;
9736711c 701 m_sSend = cCopy.m_sSend;
be3edeee 702 m_sPemPass = cCopy.m_sPemPass;
703 m_sLocalIP = cCopy.m_sLocalIP;
704 m_sRemoteIP = cCopy.m_sRemoteIP;
9736711c 705 m_eCloseType = cCopy.m_eCloseType;
706
707 m_iMaxMilliSeconds = cCopy.m_iMaxMilliSeconds;
be3edeee 708 m_iLastSendTime = cCopy.m_iLastSendTime;
709 m_iBytesRead = cCopy.m_iBytesRead;
710 m_iBytesWritten = cCopy.m_iBytesWritten;
711 m_iStartTime = cCopy.m_iStartTime;
9736711c 712 m_iMaxBytes = cCopy.m_iMaxBytes;
be3edeee 713 m_iLastSend = cCopy.m_iLastSend;
714 m_iMaxStoredBufferLength = cCopy.m_iMaxStoredBufferLength;
715 m_iTimeoutType = cCopy.m_iTimeoutType;
9736711c 716
717 m_address = cCopy.m_address;
be3edeee 718 m_bindhost = cCopy.m_bindhost;
9736711c 719 m_bIsIPv6 = cCopy.m_bIsIPv6;
493d5154 720 m_bSkipConnect = cCopy.m_bSkipConnect;
6ce29e77 721#ifdef HAVE_C_ARES
722 FreeAres(); // Not copying this state, but making sure its nulled out
723 m_iARESStatus = -1; // set it to unitialized
724 m_pCurrAddr = NULL;
725#endif /* HAVE_C_ARES */
9736711c 726
727#ifdef HAVE_LIBSSL
37d0c5e5 728 m_iRequireClientCertFlags = cCopy.m_iRequireClientCertFlags;
1fb00397 729 m_sSSLBuffer = cCopy.m_sSSLBuffer;
730
9736711c 731 FREE_SSL();
732 FREE_CTX(); // be sure to remove anything that was already here
733 m_ssl = cCopy.m_ssl;
734 m_ssl_ctx = cCopy.m_ssl_ctx;
9736711c 735
736 m_pCerVerifyCB = cCopy.m_pCerVerifyCB;
737
738#endif /* HAVE_LIBSSL */
739
8d37abf3 740 if( !m_vcCrons.empty() )
9736711c 741 {
742 for( u_long a = 0; a < m_vcCrons.size(); a++ )
743 {
744 CS_Delete( m_vcCrons[a] );
745 }
746 m_vcCrons.clear();
747 }
748 m_vcCrons = cCopy.m_vcCrons;
749
750 m_eConState = cCopy.m_eConState;
751 m_sBindHost = cCopy.m_sBindHost;
752 m_iCurBindCount = cCopy.m_iCurBindCount;
be3edeee 753 m_iDNSTryCount = cCopy.m_iDNSTryCount;
9736711c 754
9736711c 755}
756
79aaf3d5 757Csock & Csock::operator<<( const CS_STRING & s )
8a769a6f 758{
759 Write( s );
760 return( *this );
761}
762
763Csock & Csock::operator<<( ostream & ( *io )( ostream & ) )
764{
765 Write( "\r\n" );
766 return( *this );
767}
768
79aaf3d5 769Csock & Csock::operator<<( int i )
8a769a6f 770{
771 stringstream s;
772 s << i;
773 Write( s.str() );
774 return( *this );
775}
79aaf3d5 776Csock & Csock::operator<<( unsigned int i )
8a769a6f 777{
778 stringstream s;
779 s << i;
780 Write( s.str() );
781 return( *this );
782}
79aaf3d5 783Csock & Csock::operator<<( long i )
784{
8a769a6f 785 stringstream s;
786 s << i;
787 Write( s.str() );
788 return( *this );
789}
79aaf3d5 790Csock & Csock::operator<<( unsigned long i )
8a769a6f 791{
792 stringstream s;
793 s << i;
794 Write( s.str() );
795 return( *this );
796}
79aaf3d5 797Csock & Csock::operator<<( unsigned long long i )
8a769a6f 798{
799 stringstream s;
800 s << i;
801 Write( s.str() );
802 return( *this );
803}
79aaf3d5 804Csock & Csock::operator<<( float i )
8a769a6f 805{
806 stringstream s;
807 s << i;
808 Write( s.str() );
809 return( *this );
810}
79aaf3d5 811Csock & Csock::operator<<( double i )
8a769a6f 812{
813 stringstream s;
814 s << i;
815 Write( s.str() );
816 return( *this );
79aaf3d5 817}
8a769a6f 818
6dbb196e 819bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup )
8a769a6f 820{
493d5154 821 if( m_bSkipConnect )
822 { // this was already called, so skipping now. this is to allow easy pass through
3583b4b5 823 if ( m_eConState != CST_OK )
824 {
825 m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK );
826 }
493d5154 827 return( true );
828 }
c287c5cd 829 // bind to a hostname if requested
830 m_sBindHost = sBindHost;
6dbb196e 831 if ( !bSkipSetup )
8a769a6f 832 {
6dbb196e 833 if ( !sBindHost.empty() )
8a769a6f 834 {
6dbb196e 835 // try to bind 3 times, otherwise exit failure
836 bool bBound = false;
837 for( int a = 0; a < 3 && !bBound; a++ )
8a769a6f 838 {
6dbb196e 839 if ( SetupVHost() )
840 bBound = true;
2d1602ec 841#ifdef _WIN32
6dbb196e 842 Sleep( 5000 );
2d1602ec 843#else
6dbb196e 844 usleep( 5000 ); // quick pause, common lets BIND!)(!*!
2d1602ec 845#endif /* _WIN32 */
6dbb196e 846 }
8a769a6f 847
6dbb196e 848 if ( !bBound )
849 {
850 CS_DEBUG( "Failure to bind to " << sBindHost );
851 return( false );
852 }
8a769a6f 853 }
1fb00397 854
855 int iDNSRet = ETIMEDOUT;
856 while( true )
857 {
858 iDNSRet = DNSLookup( DNS_VHOST );
859 if ( iDNSRet == EAGAIN )
860 continue;
861
862 break;
863 }
864 if ( iDNSRet != 0 )
865 return( false );
866
8a769a6f 867 }
868
869 // set it none blocking
c6664d5a 870 set_non_blocking( m_iReadSock );
2d1602ec 871
8a769a6f 872 m_iConnType = OUTBOUND;
873
487b6b65 874 int ret = -1;
875 if( !GetIPv6() )
876 ret = connect( m_iReadSock, (struct sockaddr *)m_address.GetSockAddr(), m_address.GetSockAddrLen() );
877#ifdef HAVE_IPV6
878 else
879 ret = connect( m_iReadSock, (struct sockaddr *)m_address.GetSockAddr6(), m_address.GetSockAddrLen6() );
880#endif /* HAVE_IPV6 */
2d1602ec 881#ifndef _WIN32
882 if ( ( ret == -1 ) && ( GetSockError() != EINPROGRESS ) )
883#else
884 if ( ( ret == -1 ) && ( GetSockError() != EINPROGRESS ) && ( GetSockError() != WSAEWOULDBLOCK ) )
885#endif /* _WIN32 */
886
8a769a6f 887 {
2d1602ec 888 CS_DEBUG( "Connect Failed. ERRNO [" << GetSockError() << "] FD [" << m_iReadSock << "]" );
8a769a6f 889 return( false );
890 }
891
892 if ( m_bBLOCK )
79aaf3d5 893 {
c6664d5a 894 set_blocking( m_iReadSock );
8a769a6f 895 }
896
6dbb196e 897 if ( m_eConState != CST_OK )
3583b4b5 898 {
899 m_eConState = ( GetSSL() ? CST_CONNECTSSL : CST_OK );
900 }
6dbb196e 901
8a769a6f 902 return( true );
903}
904
905int Csock::WriteSelect()
906{
c7546c0c 907 if ( m_iWriteSock == CS_INVALID_SOCK )
8a769a6f 908 return( SEL_ERR );
909
910 struct timeval tv;
911 fd_set wfds;
912
913 TFD_ZERO( &wfds );
914 TFD_SET( m_iWriteSock, &wfds );
915
916 tv.tv_sec = m_itimeout;
917 tv.tv_usec = 0;
918
919 int ret = select( FD_SETSIZE, NULL, &wfds, NULL, &tv );
920
921 if ( ret == 0 )
922 return( SEL_TIMEOUT );
923
924 if ( ret == -1 )
925 {
2d1602ec 926 if ( GetSockError() == EINTR )
8a769a6f 927 return( SEL_EAGAIN );
928 else
929 return( SEL_ERR );
930 }
931
932 return( SEL_OK );
933}
934
935int Csock::ReadSelect()
936{
c7546c0c 937 if ( m_iReadSock == CS_INVALID_SOCK )
8a769a6f 938 return( SEL_ERR );
939
940 struct timeval tv;
941 fd_set rfds;
942
943 TFD_ZERO( &rfds );
944 TFD_SET( m_iReadSock, &rfds );
945
946 tv.tv_sec = m_itimeout;
947 tv.tv_usec = 0;
948
949 int ret = select( FD_SETSIZE, &rfds, NULL, NULL, &tv );
950
951 if ( ret == 0 )
952 return( SEL_TIMEOUT );
953
954 if ( ret == -1 )
955 {
2d1602ec 956 if ( GetSockError() == EINTR )
8a769a6f 957 return( SEL_EAGAIN );
958 else
959 return( SEL_ERR );
960 }
961
962 return( SEL_OK );
963}
964
6dbb196e 965bool Csock::Listen( u_short iPort, int iMaxConns, const CS_STRING & sBindHost, u_int iTimeout )
8a769a6f 966{
8a769a6f 967 m_iConnType = LISTENER;
968 m_itimeout = iTimeout;
969
6dbb196e 970 m_sBindHost = sBindHost;
487b6b65 971 if ( !sBindHost.empty() )
972 {
3fd82a60 973 // forcing this to block regardless of resolver overloading, because listen is not currently setup to
974 // to handle nonblocking operations. This is used to resolve local ip's for binding anyways and should be instant
975 if( ::GetAddrInfo( sBindHost, this, m_address ) != 0 )
9d4be439 976 return( false );
487b6b65 977 }
9d4be439 978
25ef3439 979 m_iReadSock = m_iWriteSock = CreateSocket( true );
9d4be439 980
25ef3439 981 if ( m_iReadSock == CS_INVALID_SOCK )
9d4be439 982 return( false );
983
f5ede26c 984#ifdef HAVE_IPV6
8d37abf3 985// there's no IPPROTO_IPV6 below Win XP. - KiNgMaR
986#if (!defined(_WIN32) && defined(IPV6_V6ONLY)) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0501)
987 if( GetIPv6() )
988 {
989 // per RFC3493#5.3
990 const int on = ( m_address.GetAFRequire() == CSSockAddr::RAF_INET6 ? 1 : 0 );
991 if( setsockopt( m_iReadSock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof( on ) ) != 0 )
992 PERROR( "IPV6_V6ONLY" );
993 }
f5ede26c 994#endif /* IPV6_V6ONLY */
995#endif /* HAVE_IPV6 */
996
9d4be439 997 m_address.SinFamily();
487b6b65 998 m_address.SinPort( iPort );
487b6b65 999 if( !GetIPv6() )
1000 {
1001 if ( bind( m_iReadSock, (struct sockaddr *) m_address.GetSockAddr(), m_address.GetSockAddrLen() ) == -1 )
1002 return( false );
1003 }
1004#ifdef HAVE_IPV6
8a769a6f 1005 else
1006 {
487b6b65 1007 if ( bind( m_iReadSock, (struct sockaddr *) m_address.GetSockAddr6(), m_address.GetSockAddrLen6() ) == -1 )
8a769a6f 1008 return( false );
1009 }
487b6b65 1010#endif /* HAVE_IPV6 */
8a769a6f 1011
1012 if ( listen( m_iReadSock, iMaxConns ) == -1 )
1013 return( false );
1014
1015 if ( !m_bBLOCK )
1016 {
1017 // set it none blocking
c6664d5a 1018 set_non_blocking( m_iReadSock );
8a769a6f 1019 }
1020
1021 return( true );
1022}
1023
c7546c0c 1024cs_sock_t Csock::Accept( CS_STRING & sHost, u_short & iRPort )
8a769a6f 1025{
c7546c0c 1026 cs_sock_t iSock = CS_INVALID_SOCK;
487b6b65 1027 if( !GetIPv6() )
1028 {
1029 struct sockaddr_in client;
1030 socklen_t clen = sizeof( client );
1031 iSock = accept( m_iReadSock, (struct sockaddr *) &client, &clen );
c7546c0c 1032 if( iSock != CS_INVALID_SOCK )
69f44c35 1033 {
1034 getpeername( iSock, (struct sockaddr *) &client, &clen );
635fb4bc 1035 sHost = ConvertAddress( &client.sin_addr, false );
69f44c35 1036 iRPort = ntohs( client.sin_port );
1037 }
487b6b65 1038 }
1039#ifdef HAVE_IPV6
1040 else
1041 {
487b6b65 1042 struct sockaddr_in6 client;
1043 socklen_t clen = sizeof( client );
1044 iSock = accept( m_iReadSock, (struct sockaddr *) &client, &clen );
c7546c0c 1045 if( iSock != CS_INVALID_SOCK )
487b6b65 1046 {
69f44c35 1047 getpeername( iSock, (struct sockaddr *) &client, &clen );
635fb4bc 1048 sHost = ConvertAddress( &client.sin6_addr, true );
1049 iRPort = ntohs( client.sin6_port );
487b6b65 1050 }
1051 }
1052#endif /* HAVE_IPV6 */
8a769a6f 1053
c7546c0c 1054 if ( iSock != CS_INVALID_SOCK )
8a769a6f 1055 {
c6664d5a 1056 // Make it close-on-exec
1057 set_close_on_exec( iSock );
1058
8a769a6f 1059 if ( !m_bBLOCK )
1060 {
88e7f093 1061 // make it none blocking
331f8b1e 1062 set_non_blocking( iSock );
8a769a6f 1063 }
1064
8a769a6f 1065 if ( !ConnectionFrom( sHost, iRPort ) )
1066 {
a2abf0fd 1067 CS_CLOSE( iSock );
c7546c0c 1068 iSock = CS_INVALID_SOCK;
8a769a6f 1069 }
1070
1071 }
1072
1073 return( iSock );
1074}
1075
1076bool Csock::AcceptSSL()
1077{
1078#ifdef HAVE_LIBSSL
1079 if ( !m_ssl )
1080 if ( !SSLServerSetup() )
1081 return( false );
1082
1083 int err = SSL_accept( m_ssl );
1084
1085 if ( err == 1 )
1086 {
79aaf3d5 1087 return( true );
8a769a6f 1088 }
1089
8a769a6f 1090 int sslErr = SSL_get_error( m_ssl, err );
1091
1092 if ( ( sslErr == SSL_ERROR_WANT_READ ) || ( sslErr == SSL_ERROR_WANT_WRITE ) )
1093 return( true );
1094
1095 SSLErrors( __FILE__, __LINE__ );
1096
1097#endif /* HAVE_LIBSSL */
1098
79aaf3d5 1099 return( false );
8a769a6f 1100}
1101
8a769a6f 1102bool Csock::SSLClientSetup()
1103{
79aaf3d5 1104#ifdef HAVE_LIBSSL
8a769a6f 1105 m_bssl = true;
1106 FREE_SSL();
1107 FREE_CTX();
1108
25ef3439 1109#ifdef _WIN64
1110 if( m_iReadSock != (int)m_iReadSock || m_iWriteSock != (int)m_iWriteSock )
1111 {
1112 // sanity check the FD to be sure its compatible with openssl
1113 CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
1114 return( false );
1115 }
5ea1f8cc 1116#endif /* _WIN64 */
25ef3439 1117
dba60545
A
1118 m_ssl_ctx = SSL_CTX_new(TLS_client_method());
1119 if (!m_ssl_ctx)
8a769a6f 1120 {
dba60545
A
1121 CS_DEBUG( "WARNING: MakeConnection .... TLS_client_method failed!" );
1122 return( false );
8a769a6f 1123 }
1124
9210bdc9 1125 SSL_CTX_set_default_verify_paths( m_ssl_ctx );
1126
8a769a6f 1127 if ( !m_sPemFile.empty() )
1128 { // are we sending a client cerificate ?
1129 SSL_CTX_set_default_passwd_cb( m_ssl_ctx, PemPassCB );
1130 SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, (void *)this );
1131
1132 //
1133 // set up the CTX
1134 if ( SSL_CTX_use_certificate_file( m_ssl_ctx, m_sPemFile.c_str() , SSL_FILETYPE_PEM ) <= 0 )
1135 {
1136 CS_DEBUG( "Error with PEM file [" << m_sPemFile << "]" );
1137 SSLErrors( __FILE__, __LINE__ );
1138 }
1139
1140 if ( SSL_CTX_use_PrivateKey_file( m_ssl_ctx, m_sPemFile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
1141 {
1142 CS_DEBUG( "Error with PEM file [" << m_sPemFile << "]" );
1143 SSLErrors( __FILE__, __LINE__ );
1144 }
1145 }
1146
1147 m_ssl = SSL_new ( m_ssl_ctx );
1148 if ( !m_ssl )
1149 return( false );
1150
25ef3439 1151 SSL_set_rfd( m_ssl, (int)m_iReadSock );
1152 SSL_set_wfd( m_ssl, (int)m_iWriteSock );
ed120ee5 1153 SSL_set_verify( m_ssl, SSL_VERIFY_PEER, ( m_pCerVerifyCB ? m_pCerVerifyCB : CertVerifyCB ) );
b63b7d03 1154 SSL_set_ex_data( m_ssl, GetCsockClassIdx(), this );
8a769a6f 1155
ed120ee5 1156 SSLFinishSetup( m_ssl );
8a769a6f 1157 return( true );
1158#else
1159 return( false );
1160
79aaf3d5 1161#endif /* HAVE_LIBSSL */
8a769a6f 1162}
1163
1164bool Csock::SSLServerSetup()
1165{
1166#ifdef HAVE_LIBSSL
1167 m_bssl = true;
79aaf3d5 1168 FREE_SSL();
8a769a6f 1169 FREE_CTX();
1170
25ef3439 1171#ifdef _WIN64
1172 if( m_iReadSock != (int)m_iReadSock || m_iWriteSock != (int)m_iWriteSock )
1173 {
1174 // sanity check the FD to be sure its compatible with openssl
1175 CS_DEBUG( "ERROR: sockfd larger than OpenSSL can handle" );
1176 return( false );
1177 }
5ea1f8cc 1178#endif /* _WIN64 */
25ef3439 1179
1180
dba60545
A
1181 m_ssl_ctx = SSL_CTX_new(TLS_server_method());
1182 if ( !m_ssl_ctx )
8a769a6f 1183 {
dba60545
A
1184 CS_DEBUG( "WARNING: MakeConnection .... TLS_server_method failed!" );
1185 return( false );
8a769a6f 1186 }
1187
9210bdc9 1188 SSL_CTX_set_default_verify_paths( m_ssl_ctx );
8a769a6f 1189
1190 // set the pemfile password
1191 SSL_CTX_set_default_passwd_cb( m_ssl_ctx, PemPassCB );
1192 SSL_CTX_set_default_passwd_cb_userdata( m_ssl_ctx, (void *)this );
1193
1194 if ( ( m_sPemFile.empty() ) || ( access( m_sPemFile.c_str(), R_OK ) != 0 ) )
79aaf3d5 1195 {
8a769a6f 1196 CS_DEBUG( "There is a problem with [" << m_sPemFile << "]" );
1197 return( false );
1198 }
1199
1200 //
1201 // set up the CTX
88e7f093 1202 if( SSL_CTX_use_certificate_chain_file( m_ssl_ctx, m_sPemFile.c_str() ) <= 0 )
8a769a6f 1203 {
1204 CS_DEBUG( "Error with PEM file [" << m_sPemFile << "]" );
1205 SSLErrors( __FILE__, __LINE__ );
1206 return( false );
1207 }
1208
88e7f093 1209 if( SSL_CTX_use_PrivateKey_file( m_ssl_ctx, m_sPemFile.c_str(), SSL_FILETYPE_PEM ) <= 0 )
8a769a6f 1210 {
1211 CS_DEBUG( "Error with PEM file [" << m_sPemFile << "]" );
1212 SSLErrors( __FILE__, __LINE__ );
1213 return( false );
1214 }
1215
88e7f093
US
1216 // check to see if this pem file contains a DH structure for use with DH key exchange
1217 // https://github.com/znc/znc/pull/46
1218 FILE *dhParamsFile = fopen( m_sPemFile.c_str(), "r" );
1219 if( !dhParamsFile )
1220 {
1221 CS_DEBUG( "There is a problem with [" << m_sPemFile << "]" );
1222 return( false );
1223 }
1224
1225 DH * dhParams = PEM_read_DHparams( dhParamsFile, NULL, NULL, NULL );
1226 fclose( dhParamsFile );
1227 if( dhParams )
1228 {
1229 SSL_CTX_set_options( m_ssl_ctx, SSL_OP_SINGLE_DH_USE );
1230 if( !SSL_CTX_set_tmp_dh( m_ssl_ctx, dhParams ) )
1231 {
1232 CS_DEBUG( "Error setting ephemeral DH parameters from [" << m_sPemFile << "]" );
1233 SSLErrors( __FILE__, __LINE__ );
1234 DH_free( dhParams );
1235 return( false );
1236 }
1237 DH_free( dhParams );
1238 }
1239 else
1240 { // Presumably PEM_read_DHparams failed, as there was no DH structure. Clearing those errors here so they are removed off the stack
1241 ERR_clear_error();
1242 }
1243
1244 if( SSL_CTX_set_cipher_list( m_ssl_ctx, m_sCipherType.c_str() ) <= 0 )
8a769a6f 1245 {
1246 CS_DEBUG( "Could not assign cipher [" << m_sCipherType << "]" );
1247 return( false );
1248 }
1249
1250 //
1251 // setup the SSL
88e7f093 1252 m_ssl = SSL_new( m_ssl_ctx );
8a769a6f 1253 if ( !m_ssl )
1254 return( false );
1255
1256 // Call for client Verification
25ef3439 1257 SSL_set_rfd( m_ssl, (int)m_iReadSock );
1258 SSL_set_wfd( m_ssl, (int)m_iWriteSock );
8a769a6f 1259 SSL_set_accept_state( m_ssl );
37d0c5e5 1260 if ( m_iRequireClientCertFlags )
b63b7d03 1261 {
37d0c5e5 1262 SSL_set_verify( m_ssl, m_iRequireClientCertFlags, ( m_pCerVerifyCB ? m_pCerVerifyCB : CertVerifyCB ) );
b63b7d03 1263 SSL_set_ex_data( m_ssl, GetCsockClassIdx(), this );
1264 }
8a769a6f 1265
ed120ee5 1266 SSLFinishSetup( m_ssl );
8a769a6f 1267 return( true );
1268#else
1269 return( false );
79aaf3d5 1270#endif /* HAVE_LIBSSL */
1271}
8a769a6f 1272
1273bool Csock::ConnectSSL( const CS_STRING & sBindhost )
1274{
79aaf3d5 1275#ifdef HAVE_LIBSSL
25ef3439 1276 if ( m_iReadSock == CS_INVALID_SOCK )
8a769a6f 1277 if ( !Connect( sBindhost ) )
1278 return( false );
8a769a6f 1279 if ( !m_ssl )
1280 if ( !SSLClientSetup() )
1281 return( false );
1282
1283 bool bPass = true;
1284
1285 if ( m_bBLOCK )
1286 {
c6664d5a 1287 set_non_blocking( m_iReadSock );
79aaf3d5 1288 }
8a769a6f 1289
1290 int iErr = SSL_connect( m_ssl );
1291 if ( iErr != 1 )
1292 {
1293 int sslErr = SSL_get_error( m_ssl, iErr );
583b91f7 1294 bPass = false;
1295 if( sslErr == SSL_ERROR_WANT_READ || sslErr == SSL_ERROR_WANT_WRITE )
1296 bPass = true;
1297#ifdef _WIN32
1298 else if( sslErr == SSL_ERROR_SYSCALL && iErr < 0 && GetLastError() == WSAENOTCONN )
88e7f093 1299 {
583b91f7 1300 // this seems to be an issue with win32 only. I've seen it happen on slow connections
1301 // the issue is calling this before select(), which isn't a problem on unix. Allowing this
1302 // to pass in this case is fine because subsequent ssl transactions will occur and the handshake
1303 // will finish. At this point, its just instantiating the handshake.
1304 bPass = true;
1305 }
1306#endif /* _WIN32 */
8a769a6f 1307 } else
1308 bPass = true;
1309
1310 if ( m_bBLOCK )
79aaf3d5 1311 {
8a769a6f 1312 // unset the flags afterwords, rather then have connect block
c6664d5a 1313 set_blocking( m_iReadSock );
79aaf3d5 1314 }
8a769a6f 1315
3583b4b5 1316 if ( m_eConState != CST_OK )
1317 m_eConState = CST_OK;
8a769a6f 1318 return( bPass );
1319#else
1320 return( false );
1321#endif /* HAVE_LIBSSL */
1322}
1323
2bbdb72a 1324bool Csock::AllowWrite( unsigned long long & iNOW ) const
ed120ee5 1325{
1326 if ( ( m_iMaxBytes > 0 ) && ( m_iMaxMilliSeconds > 0 ) )
1327 {
2bbdb72a 1328 if( iNOW == 0 )
1329 iNOW = millitime();
1330
ed120ee5 1331 if( m_iLastSend < m_iMaxBytes )
1332 return( true ); // allow sending if our out buffer was less than what we can send
1333 if ( ( iNOW - m_iLastSendTime ) < m_iMaxMilliSeconds )
1334 return( false );
1335 }
1336 return( true );
1337}
1338
f5ede26c 1339bool Csock::Write( const char *data, size_t len )
8a769a6f 1340{
1341 m_sSend.append( data, len );
1342
1343 if ( m_sSend.empty() )
1344 return( true );
1345
6dbb196e 1346 if ( m_eConState != CST_OK )
1347 return( true );
1348
8a769a6f 1349 if ( m_bBLOCK )
1350 {
1351 if ( WriteSelect() != SEL_OK )
1352 return( false );
1353
1354 }
1355 // rate shaping
f5ede26c 1356 u_long iBytesToSend = 0;
8a769a6f 1357
a2abf0fd 1358#ifdef HAVE_LIBSSL
1359 if( m_bssl && m_sSSLBuffer.empty() && !m_bsslEstablished )
1360 {
1361 // to keep openssl from spinning, just initiate the connection with 1 byte so the connection establishes faster
1362 iBytesToSend = 1;
1363 }
9a2e17c6 1364 else
a2abf0fd 1365#endif /* HAVE_LIBSSL */
9a2e17c6 1366 if ( ( m_iMaxBytes > 0 ) && ( m_iMaxMilliSeconds > 0 ) )
8a769a6f 1367 {
1368 unsigned long long iNOW = millitime();
79aaf3d5 1369 // figure out the shaping here
8a769a6f 1370 // if NOW - m_iLastSendTime > m_iMaxMilliSeconds then send a full length of ( iBytesToSend )
1371 if ( ( iNOW - m_iLastSendTime ) > m_iMaxMilliSeconds )
1372 {
1373 m_iLastSendTime = iNOW;
1374 iBytesToSend = m_iMaxBytes;
1375 m_iLastSend = 0;
1376
1377 } else // otherwise send m_iMaxBytes - m_iLastSend
1378 iBytesToSend = m_iMaxBytes - m_iLastSend;
1379
1380 // take which ever is lesser
1381 if ( m_sSend.length() < iBytesToSend )
1382 iBytesToSend = m_sSend.length();
1383
1384 // add up the bytes sent
1385 m_iLastSend += iBytesToSend;
1386
1387 // so, are we ready to send anything ?
1388 if ( iBytesToSend == 0 )
1389 return( true );
1390
1391 } else
1392 iBytesToSend = m_sSend.length();
1393
79aaf3d5 1394#ifdef HAVE_LIBSSL
8a769a6f 1395 if ( m_bssl )
79aaf3d5 1396 {
8a769a6f 1397
1398 if ( m_sSSLBuffer.empty() ) // on retrying to write data, ssl wants the data in the SAME spot and the SAME size
1399 m_sSSLBuffer.append( m_sSend.data(), iBytesToSend );
1400
f5ede26c 1401 int iErr = SSL_write( m_ssl, m_sSSLBuffer.data(), (int)m_sSSLBuffer.length() );
8a769a6f 1402
2d1602ec 1403 if ( ( iErr < 0 ) && ( GetSockError() == ECONNREFUSED ) )
79aaf3d5 1404 {
8a769a6f 1405 // If ret == -1, the underlying BIO reported an I/O error (man SSL_get_error)
1406 ConnectionRefused();
1407 return( false );
1408 }
1409
1410 switch( SSL_get_error( m_ssl, iErr ) )
1411 {
1412 case SSL_ERROR_NONE:
79aaf3d5 1413 m_bsslEstablished = true;
8a769a6f 1414 // all ok
1415 break;
1416
1417 case SSL_ERROR_ZERO_RETURN:
1418 {
1419 // weird closer alert
1420 return( false );
1421 }
1422
1423 case SSL_ERROR_WANT_READ:
1424 // retry
1425 break;
1426
1427 case SSL_ERROR_WANT_WRITE:
1428 // retry
1429 break;
1430
1431 case SSL_ERROR_SSL:
1432 {
1433 SSLErrors( __FILE__, __LINE__ );
1434 return( false );
1435 }
1436 }
1437
79aaf3d5 1438 if ( iErr > 0 )
8a769a6f 1439 {
1440 m_sSSLBuffer.clear();
1441 m_sSend.erase( 0, iErr );
1442 // reset the timer on successful write (we have to set it here because the write
1443 // bit might not always be set, so need to trigger)
1444 if ( TMO_WRITE & GetTimeoutType() )
79aaf3d5 1445 ResetTimer();
8a769a6f 1446
1447 m_iBytesWritten += (unsigned long long)iErr;
1448 }
1449
1450 return( true );
1451 }
1452#endif /* HAVE_LIBSSL */
2d1602ec 1453#ifdef _WIN32
8d37abf3 1454 cs_ssize_t bytes = send( m_iWriteSock, m_sSend.data(), iBytesToSend, 0 );
2d1602ec 1455#else
8d37abf3 1456 cs_ssize_t bytes = write( m_iWriteSock, m_sSend.data(), iBytesToSend );
2d1602ec 1457#endif /* _WIN32 */
8a769a6f 1458
2d1602ec 1459 if ( ( bytes == -1 ) && ( GetSockError() == ECONNREFUSED ) )
8a769a6f 1460 {
1461 ConnectionRefused();
1462 return( false );
1463 }
1464
2d1602ec 1465#ifdef _WIN32
1466 if ( ( bytes <= 0 ) && ( GetSockError() != WSAEWOULDBLOCK ) )
1467 return( false );
1468#else
1469 if ( ( bytes <= 0 ) && ( GetSockError() != EAGAIN ) )
8a769a6f 1470 return( false );
2d1602ec 1471#endif /* _WIN32 */
8a769a6f 1472
1473 // delete the bytes we sent
1474 if ( bytes > 0 )
1475 {
1476 m_sSend.erase( 0, bytes );
1477 if ( TMO_WRITE & GetTimeoutType() )
1478 ResetTimer(); // reset the timer on successful write
1479 m_iBytesWritten += (unsigned long long)bytes;
1480 }
1481
1482 return( true );
1483}
1484
1485bool Csock::Write( const CS_STRING & sData )
1486{
1487 return( Write( sData.c_str(), sData.length() ) );
1488}
1489
8d37abf3 1490cs_ssize_t Csock::Read( char *data, size_t len )
8a769a6f 1491{
8d37abf3 1492 cs_ssize_t bytes = 0;
8a769a6f 1493
88e7f093 1494 if ( IsReadPaused() && SslIsEstablished() )
8a769a6f 1495 return( READ_EAGAIN ); // allow the handshake to complete first
1496
1497 if ( m_bBLOCK )
1498 {
1499 switch( ReadSelect() )
1500 {
1501 case SEL_OK:
1502 break;
1503 case SEL_TIMEOUT:
1504 return( READ_TIMEDOUT );
1505 default:
1506 return( READ_ERR );
1507 }
1508 }
1509
1510#ifdef HAVE_LIBSSL
1511 if ( m_bssl )
88e7f093 1512 {
f5ede26c 1513 bytes = SSL_read( m_ssl, data, (int)len );
88e7f093
US
1514 if( bytes >= 0 )
1515 m_bsslEstablished = true; // this means all is good in the realm of ssl
1516 }
8a769a6f 1517 else
1518#endif /* HAVE_LIBSSL */
2d1602ec 1519#ifdef _WIN32
1520 bytes = recv( m_iReadSock, data, len, 0 );
1521#else
8a769a6f 1522 bytes = read( m_iReadSock, data, len );
2d1602ec 1523#endif /* _WIN32 */
8a769a6f 1524 if ( bytes == -1 )
1525 {
2d1602ec 1526 if ( GetSockError() == ECONNREFUSED )
79aaf3d5 1527 return( READ_CONNREFUSED );
8a769a6f 1528
2d1602ec 1529 if ( GetSockError() == ETIMEDOUT )
8a769a6f 1530 return( READ_TIMEDOUT );
1531
2d1602ec 1532 if ( ( GetSockError() == EINTR ) || ( GetSockError() == EAGAIN ) )
1533 return( READ_EAGAIN );
1534
1535#ifdef _WIN32
1536 if ( GetSockError() == WSAEWOULDBLOCK )
8a769a6f 1537 return( READ_EAGAIN );
2d1602ec 1538#endif /* _WIN32 */
1539
8a769a6f 1540#ifdef HAVE_LIBSSL
1541 if ( m_bssl )
1542 {
f5ede26c 1543 int iErr = SSL_get_error( m_ssl, (int)bytes );
8a769a6f 1544 if ( ( iErr != SSL_ERROR_WANT_READ ) && ( iErr != SSL_ERROR_WANT_WRITE ) )
1545 return( READ_ERR );
1546 else
1547 return( READ_EAGAIN );
1548 }
1549#else
1550 return( READ_ERR );
79aaf3d5 1551#endif /* HAVE_LIBSSL */
8a769a6f 1552 }
1553
ed120ee5 1554 if( bytes > 0 ) // becareful not to add negative bytes :P
1555 m_iBytesRead += (unsigned long long)bytes;
8a769a6f 1556
1557 return( bytes );
1558}
1559
1560CS_STRING Csock::GetLocalIP()
1561{
1562 if ( !m_sLocalIP.empty() )
1563 return( m_sLocalIP );
1564
c7546c0c 1565 cs_sock_t iSock = GetSock();
8a769a6f 1566
c7546c0c 1567 if ( iSock == CS_INVALID_SOCK )
8a769a6f 1568 return( "" );
1569
487b6b65 1570 if( !GetIPv6() )
1571 {
cc552fb3 1572 char straddr[INET_ADDRSTRLEN];
487b6b65 1573 struct sockaddr_in mLocalAddr;
1574 socklen_t mLocalLen = sizeof( mLocalAddr );
cc552fb3
US
1575 if ( ( getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen ) == 0 )
1576 && ( inet_ntop( AF_INET, &mLocalAddr.sin_addr, straddr, sizeof(straddr) ) ) )
1577 {
1578 m_sLocalIP = straddr;
1579 }
487b6b65 1580 }
1581#ifdef HAVE_IPV6
1582 else
1583 {
1584 char straddr[INET6_ADDRSTRLEN];
1585 struct sockaddr_in6 mLocalAddr;
1586 socklen_t mLocalLen = sizeof( mLocalAddr );
be3edeee 1587 if ( ( getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen ) == 0 )
487b6b65 1588 && ( inet_ntop( AF_INET6, &mLocalAddr.sin6_addr, straddr, sizeof(straddr) ) ) )
1589 {
1590 m_sLocalIP = straddr;
1591 }
1592 }
1593#endif /* HAVE_IPV6 */
8a769a6f 1594
1595 return( m_sLocalIP );
1596}
1597
1598CS_STRING Csock::GetRemoteIP()
1599{
1600 if ( !m_sRemoteIP.empty() )
1601 return( m_sRemoteIP );
1602
c7546c0c 1603 cs_sock_t iSock = GetSock();
8a769a6f 1604
c7546c0c 1605 if ( iSock == CS_INVALID_SOCK )
8a769a6f 1606 return( "" );
8a769a6f 1607
487b6b65 1608 if( !GetIPv6() )
1609 {
1610 struct sockaddr_in mRemoteAddr;
1611 socklen_t mRemoteLen = sizeof( mRemoteAddr );
1612 if ( getpeername( iSock, (struct sockaddr *) &mRemoteAddr, &mRemoteLen ) == 0 )
635fb4bc 1613 m_sRemoteIP = ConvertAddress( &mRemoteAddr.sin_addr, false );
487b6b65 1614 }
1615#ifdef HAVE_IPV6
1616 else
1617 {
487b6b65 1618 struct sockaddr_in6 mRemoteAddr;
1619 socklen_t mRemoteLen = sizeof( mRemoteAddr );
635fb4bc 1620 if ( getpeername( iSock, (struct sockaddr *) &mRemoteAddr, &mRemoteLen ) == 0 )
1621 m_sRemoteIP = ConvertAddress( &mRemoteAddr.sin6_addr, true );
487b6b65 1622 }
1623#endif /* HAVE_IPV6 */
8a769a6f 1624
1625 return( m_sRemoteIP );
1626}
1627
635fb4bc 1628CS_STRING Csock::ConvertAddress( void *addr, bool bIPv6 )
1629{
1630 CS_STRING sRet;
1631
88e7f093 1632 if( !bIPv6 )
635fb4bc 1633 {
1634 in_addr *p = (in_addr*) addr;
1635 sRet = inet_ntoa(*p);
88e7f093
US
1636 }
1637 else
635fb4bc 1638 {
1639 char straddr[INET6_ADDRSTRLEN];
1640 if( inet_ntop( AF_INET6, addr, straddr, sizeof(straddr) ) > 0 )
1641 sRet = straddr;
1642 }
1643
1644 return( sRet );
1645}
1646
d8f4e319 1647bool Csock::IsConnected() const { return( m_bIsConnected ); }
79aaf3d5 1648void Csock::SetIsConnected( bool b ) { m_bIsConnected = b; }
8a769a6f 1649
25ef3439 1650cs_sock_t & Csock::GetRSock() { return( m_iReadSock ); }
1651void Csock::SetRSock( cs_sock_t iSock ) { m_iReadSock = iSock; }
1652cs_sock_t & Csock::GetWSock() { return( m_iWriteSock ); }
1653void Csock::SetWSock( cs_sock_t iSock ) { m_iWriteSock = iSock; }
1654void Csock::SetSock( cs_sock_t iSock ) { m_iWriteSock = iSock; m_iReadSock = iSock; }
1655cs_sock_t & Csock::GetSock() { return( m_iReadSock ); }
b63b7d03 1656void Csock::ResetTimer() { m_iLastCheckTimeoutTime = 0; m_iTcount = 0; }
8a769a6f 1657void Csock::PauseRead() { m_bPauseRead = true; }
1658bool Csock::IsReadPaused() { return( m_bPauseRead ); }
1659
79aaf3d5 1660void Csock::UnPauseRead()
1661{
1662 m_bPauseRead = false;
8a769a6f 1663 ResetTimer();
4f2599e7 1664 PushBuff( "", 0, true );
8a769a6f 1665}
1666
79aaf3d5 1667void Csock::SetTimeout( int iTimeout, u_int iTimeoutType )
1668{
8a769a6f 1669 m_iTimeoutType = iTimeoutType;
79aaf3d5 1670 m_itimeout = iTimeout;
8a769a6f 1671}
1672
1673void Csock::SetTimeoutType( u_int iTimeoutType ) { m_iTimeoutType = iTimeoutType; }
1674int Csock::GetTimeout() const { return m_itimeout; }
1675u_int Csock::GetTimeoutType() const { return( m_iTimeoutType ); }
1676
b63b7d03 1677bool Csock::CheckTimeout( time_t iNow )
8a769a6f 1678{
b63b7d03 1679 if( m_iLastCheckTimeoutTime == 0 )
1680 {
1681 m_iLastCheckTimeoutTime = iNow;
1682 return( false );
1683 }
1684
8a769a6f 1685 if ( IsReadPaused() )
1686 return( false );
1687
b63b7d03 1688 time_t iDiff = 0;
1689 if( iNow > m_iLastCheckTimeoutTime )
1690 iDiff = iNow - m_iLastCheckTimeoutTime;
1691 else
babc0f9f 1692 {
1693 // 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
1694 // the worst case scenario is the timeout is about to it and the clock changes, it would then cause
1695 // this to pass over the last half the time
be3edeee 1696 m_iLastCheckTimeoutTime = iNow;
babc0f9f 1697 }
b63b7d03 1698
8a769a6f 1699 if ( m_itimeout > 0 )
1700 {
babc0f9f 1701 // this is basically to help stop a clock adjust ahead, stuff could reset immediatly on a clock jump
1702 // otherwise
b63b7d03 1703 time_t iRealTimeout = m_itimeout;
1704 if( iRealTimeout <= 1 )
1705 m_iTcount++;
1706 else if( m_iTcount == 0 )
1707 iRealTimeout /= 2;
1708 if( iDiff >= iRealTimeout )
8a769a6f 1709 {
b63b7d03 1710 if( m_iTcount == 0 )
1711 m_iLastCheckTimeoutTime = iNow - iRealTimeout;
1712 if( m_iTcount++ >= 1 )
1713 {
1714 Timeout();
1715 return( true );
1716 }
8a769a6f 1717 }
79aaf3d5 1718 }
8a769a6f 1719 return( false );
1720}
1721
f5ede26c 1722void Csock::PushBuff( const char *data, size_t len, bool bStartAtZero )
8a769a6f 1723{
1724 if ( !m_bEnableReadLine )
1725 return; // If the ReadLine event is disabled, just ditch here
1726
f5ede26c 1727 size_t iStartPos = ( m_sbuffer.empty() || bStartAtZero ? 0 : m_sbuffer.length() - 1 );
8a769a6f 1728
1729 if ( data )
1730 m_sbuffer.append( data, len );
1731
c6664d5a 1732 while( !m_bPauseRead && GetCloseType() == CLT_DONT )
8a769a6f 1733 {
1734 CS_STRING::size_type iFind = m_sbuffer.find( "\n", iStartPos );
1735
1736 if ( iFind != CS_STRING::npos )
1737 {
1738 CS_STRING sBuff = m_sbuffer.substr( 0, iFind + 1 ); // read up to(including) the newline
1739 m_sbuffer.erase( 0, iFind + 1 ); // erase past the newline
1740 ReadLine( sBuff );
1741 iStartPos = 0; // reset this back to 0, since we need to look for the next newline here.
1742
1743 } else
1744 break;
1745 }
1746
1747 if ( ( m_iMaxStoredBufferLength > 0 ) && ( m_sbuffer.length() > m_iMaxStoredBufferLength ) )
1748 ReachedMaxBuffer(); // call the max read buffer event
1749
1750}
1751
5665fd87 1752CS_STRING & Csock::GetInternalReadBuffer() { return( m_sbuffer ); }
1753CS_STRING & Csock::GetInternalWriteBuffer() { return( m_sSend ); }
8a769a6f 1754void Csock::SetMaxBufferThreshold( u_int iThreshold ) { m_iMaxStoredBufferLength = iThreshold; }
583b91f7 1755u_int Csock::GetMaxBufferThreshold() const { return( m_iMaxStoredBufferLength ); }
1756int Csock::GetType() const { return( m_iConnType ); }
8a769a6f 1757void Csock::SetType( int iType ) { m_iConnType = iType; }
583b91f7 1758const CS_STRING & Csock::GetSockName() const { return( m_sSockName ); }
8a769a6f 1759void Csock::SetSockName( const CS_STRING & sName ) { m_sSockName = sName; }
583b91f7 1760const CS_STRING & Csock::GetHostName() const { return( m_shostname ); }
8a769a6f 1761void Csock::SetHostName( const CS_STRING & sHostname ) { m_shostname = sHostname; }
79aaf3d5 1762unsigned long long Csock::GetStartTime() const { return( m_iStartTime ); }
8a769a6f 1763void Csock::ResetStartTime() { m_iStartTime = 0; }
1764unsigned long long Csock::GetBytesRead() const { return( m_iBytesRead ); }
1765void Csock::ResetBytesRead() { m_iBytesRead = 0; }
1766unsigned long long Csock::GetBytesWritten() const { return( m_iBytesWritten ); }
1767void Csock::ResetBytesWritten() { m_iBytesWritten = 0; }
1768
1769double Csock::GetAvgRead( unsigned long long iSample )
1770{
1771 unsigned long long iDifference = ( millitime() - m_iStartTime );
1772
1773 if ( ( m_iBytesRead == 0 ) || ( iSample > iDifference ) )
1774 return( (double)m_iBytesRead );
1775
1776 return( ( (double)m_iBytesRead / ( (double)iDifference / (double)iSample ) ) );
1777}
1778
1779double Csock::GetAvgWrite( unsigned long long iSample )
1780{
1781 unsigned long long iDifference = ( millitime() - m_iStartTime );
1782
1783 if ( ( m_iBytesWritten == 0 ) || ( iSample > iDifference ) )
1784 return( (double)m_iBytesWritten );
1785
1786 return( ( (double)m_iBytesWritten / ( (double)iDifference / (double)iSample ) ) );
1787}
1788
6dbb196e 1789u_short Csock::GetRemotePort()
8a769a6f 1790{
1791 if ( m_iRemotePort > 0 )
1792 return( m_iRemotePort );
1793
c7546c0c 1794 cs_sock_t iSock = GetSock();
8a769a6f 1795
c7546c0c 1796 if ( iSock != CS_INVALID_SOCK )
8a769a6f 1797 {
487b6b65 1798 if( !GetIPv6() )
1799 {
1800 struct sockaddr_in mAddr;
1801 socklen_t mLen = sizeof( mAddr );
1802 if ( getpeername( iSock, (struct sockaddr *) &mAddr, &mLen ) == 0 )
1803 m_iRemotePort = ntohs( mAddr.sin_port );
1804 }
1805#ifdef HAVE_IPV6
1806 else
1807 {
1808 struct sockaddr_in6 mAddr;
1809 socklen_t mLen = sizeof( mAddr );
1810 if ( getpeername( iSock, (struct sockaddr *) &mAddr, &mLen ) == 0 )
1811 m_iRemotePort = ntohs( mAddr.sin6_port );
1812 }
1813#endif /* HAVE_IPV6 */
8a769a6f 1814 }
1815
1816 return( m_iRemotePort );
1817}
1818
6dbb196e 1819u_short Csock::GetLocalPort()
8a769a6f 1820{
1821 if ( m_iLocalPort > 0 )
1822 return( m_iLocalPort );
1823
c7546c0c 1824 cs_sock_t iSock = GetSock();
8a769a6f 1825
c7546c0c 1826 if ( iSock != CS_INVALID_SOCK )
8a769a6f 1827 {
487b6b65 1828 if( !GetIPv6() )
1829 {
1830 struct sockaddr_in mLocalAddr;
9bb57639 1831 socklen_t mLocalLen = sizeof( mLocalAddr );
487b6b65 1832 if ( getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen ) == 0 )
1833 m_iLocalPort = ntohs( mLocalAddr.sin_port );
1834 }
1835#ifdef HAVE_IPV6
1836 else
1837 {
1838 struct sockaddr_in6 mLocalAddr;
9bb57639 1839 socklen_t mLocalLen = sizeof( mLocalAddr );
487b6b65 1840 if ( getsockname( iSock, (struct sockaddr *) &mLocalAddr, &mLocalLen ) == 0 )
1841 m_iLocalPort = ntohs( mLocalAddr.sin6_port );
1842 }
1843#endif /* HAVE_IPV6 */
8a769a6f 1844 }
1845
1846 return( m_iLocalPort );
1847}
1848
25ef3439 1849u_short Csock::GetPort() { return( m_uPort ); }
1850void Csock::SetPort( u_short iPort ) { m_uPort = iPort; }
e41a7f46 1851void Csock::Close( ECloseType eCloseType )
be3edeee 1852{
e41a7f46 1853 m_eCloseType = eCloseType;
1854}
8a769a6f 1855void Csock::BlockIO( bool bBLOCK ) { m_bBLOCK = bBLOCK; }
1856
1857void Csock::NonBlockingIO()
1858{
c6664d5a 1859 set_non_blocking( m_iReadSock );
8a769a6f 1860
1861 if ( m_iReadSock != m_iWriteSock )
1862 {
c6664d5a 1863 set_non_blocking( m_iWriteSock );
8a769a6f 1864 }
1865
1866 BlockIO( false );
1867}
1868
8a769a6f 1869bool Csock::GetSSL() { return( m_bssl ); }
1870void Csock::SetSSL( bool b ) { m_bssl = b; }
1871
1872#ifdef HAVE_LIBSSL
1873void Csock::SetCipher( const CS_STRING & sCipher ) { m_sCipherType = sCipher; }
1874const CS_STRING & Csock::GetCipher() { return( m_sCipherType ); }
1875void Csock::SetPemLocation( const CS_STRING & sPemFile ) { m_sPemFile = sPemFile; }
1876const CS_STRING & Csock::GetPemLocation() { return( m_sPemFile ); }
1877void Csock::SetPemPass( const CS_STRING & sPassword ) { m_sPemPass = sPassword; }
1878const CS_STRING & Csock::GetPemPass() const { return( m_sPemPass ); }
1879
1880int Csock::PemPassCB( char *buf, int size, int rwflag, void *pcSocket )
1881{
1882 Csock *pSock = (Csock *)pcSocket;
1883 const CS_STRING & sPassword = pSock->GetPemPass();
1884 memset( buf, '\0', size );
1885 strncpy( buf, sPassword.c_str(), size );
1886 buf[size-1] = '\0';
c7546c0c 1887 return( (int)strlen( buf ) );
8a769a6f 1888}
1889
1890int Csock::CertVerifyCB( int preverify_ok, X509_STORE_CTX *x509_ctx )
1891{
b63b7d03 1892 /*
1893 * A small quick example on how to get ahold of the Csock in the data portion of x509_ctx
1894 Csock *pSock = GetCsockFromCTX( x509_ctx );
1895 assert( pSock );
1896 cerr << pSock->GetRemoteIP() << endl;
1897 */
1898
8a769a6f 1899 /* return 1 always for now, probably want to add some code for cert verification */
1900 return( 1 );
1901}
1902
8a769a6f 1903void Csock::SetSSLMethod( int iMethod ) { m_iMethod = iMethod; }
1904int Csock::GetSSLMethod() { return( m_iMethod ); }
1905void Csock::SetSSLObject( SSL *ssl ) { m_ssl = ssl; }
1906void Csock::SetCTXObject( SSL_CTX *sslCtx ) { m_ssl_ctx = sslCtx; }
8a769a6f 1907
79aaf3d5 1908SSL_SESSION * Csock::GetSSLSession()
8a769a6f 1909{
79aaf3d5 1910 if ( m_ssl )
1911 return( SSL_get_session( m_ssl ) );
8a769a6f 1912
1913 return( NULL );
1914}
1915#endif /* HAVE_LIBSSL */
1916
1917const CS_STRING & Csock::GetWriteBuffer() { return( m_sSend ); }
1918void Csock::ClearWriteBuffer() { m_sSend.clear(); }
8a769a6f 1919bool Csock::SslIsEstablished() { return ( m_bsslEstablished ); }
1920
1921bool Csock::ConnectInetd( bool bIsSSL, const CS_STRING & sHostname )
1922{
1923 if ( !sHostname.empty() )
1924 m_sSockName = sHostname;
1925
1926 // set our hostname
1927 if ( m_sSockName.empty() )
1928 {
1929 struct sockaddr_in client;
1930 socklen_t clen = sizeof( client );
1931 if ( getpeername( 0, (struct sockaddr *)&client, &clen ) < 0 )
1932 m_sSockName = "0.0.0.0:0";
1933 else
1934 {
1935 stringstream s;
1936 s << inet_ntoa( client.sin_addr ) << ":" << ntohs( client.sin_port );
1937 m_sSockName = s.str();
1938 }
1939 }
1940
1941 return( ConnectFD( 0, 1, m_sSockName, bIsSSL, INBOUND ) );
1942}
1943
1944bool Csock::ConnectFD( int iReadFD, int iWriteFD, const CS_STRING & sName, bool bIsSSL, ETConn eDirection )
1945{
1946 if ( eDirection == LISTENER )
1947 {
1948 CS_DEBUG( "You can not use a LISTENER type here!" );
1949 return( false );
1950 }
1951
1952 // set our socket type
1953 SetType( eDirection );
1954
1955 // set the hostname
1956 m_sSockName = sName;
1957
1958 // set the file descriptors
1959 SetRSock( iReadFD );
1960 SetWSock( iWriteFD );
1961
1962 // set it up as non-blocking io
1963 NonBlockingIO();
1964
1965 if ( bIsSSL )
1966 {
1967 if ( ( eDirection == INBOUND ) && ( !AcceptSSL() ) )
1968 return( false );
1969 else if ( ( eDirection == OUTBOUND ) && ( !ConnectSSL() ) )
1970 return( false );
1971 }
1972
1973 return( true );
1974}
1975
1976#ifdef HAVE_LIBSSL
1977X509 *Csock::getX509()
1978{
1979 if ( m_ssl )
1980 return( SSL_get_peer_certificate( m_ssl ) );
1981
1982 return( NULL );
1983}
1984
1985CS_STRING Csock::GetPeerPubKey()
1986{
1987 CS_STRING sKey;
1988
dba60545
A
1989 X509 *pCert = getX509();
1990 if( pCert )
8a769a6f 1991 {
dba60545
A
1992 EVP_PKEY * pKey = X509_get_pubkey( pCert );
1993 if( pKey )
8a769a6f 1994 {
dba60545
A
1995 const BIGNUM * pPubKey = NULL;
1996 int iType = EVP_PKEY_base_id( pKey );
1997 switch( iType )
8a769a6f 1998 {
dba60545
A
1999#ifndef OPENSSL_NO_RSA
2000 case EVP_PKEY_RSA:
2001 RSA_get0_key( EVP_PKEY_get0_RSA( pKey ), &pPubKey, NULL, NULL );
2002 break;
2003#endif /* OPENSSL_NO_RSA */
2004#ifndef OPENSSL_NO_DSA
2005 case EVP_PKEY_DSA:
2006 DSA_get0_key( EVP_PKEY_get0_DSA( pKey ), &pPubKey, NULL );
2007 break;
2008#endif /* OPENSSL_NO_DSA */
2009 default:
2010 CS_DEBUG( "Not Prepared for Public Key Type [" << iType << "]" );
2011 break;
8a769a6f 2012 }
dba60545 2013 if( pPubKey )
8a769a6f 2014 {
dba60545 2015 char *hxKey = BN_bn2hex( pPubKey );
8a769a6f 2016 sKey = hxKey;
2017 OPENSSL_free( hxKey );
2018 }
2019 EVP_PKEY_free( pKey );
2020 }
dba60545 2021 X509_free( pCert );
79aaf3d5 2022 }
8a769a6f 2023 return( sKey );
2024}
dba60545 2025
e77adef0 2026int Csock::GetPeerFingerprint( CS_STRING & sFP )
2027{
2028 sFP.clear();
2029
2030 if ( !GetSSL() )
2031 return 0;
2032
2033 X509* pCert = getX509();
2034
dba60545
A
2035 unsigned char sha1_hash[SHA_DIGEST_LENGTH];
2036
2037 if( pCert && X509_digest( pCert, EVP_sha1(), sha1_hash, NULL ) )
e77adef0 2038 {
2039 for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
2040 {
2041 char buf[3];
dba60545 2042 snprintf(buf, 3, "%02x", sha1_hash[i]);
e77adef0 2043 sFP += buf;
2044 }
e77adef0 2045 }
dba60545 2046 X509_free(pCert);
e77adef0 2047
2048 return SSL_get_verify_result(m_ssl);
2049}
37d0c5e5 2050unsigned int Csock::GetRequireClientCertFlags() { return( m_iRequireClientCertFlags ); }
2051void Csock::SetRequiresClientCert( bool bRequiresCert ) { m_iRequireClientCertFlags = ( bRequiresCert ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT|SSL_VERIFY_PEER : 0 ); }
8a769a6f 2052
2053#endif /* HAVE_LIBSSL */
2054
2055void Csock::SetParentSockName( const CS_STRING & sParentName ) { m_sParentName = sParentName; }
2056const CS_STRING & Csock::GetParentSockName() { return( m_sParentName ); }
2057
2058void Csock::SetRate( u_int iBytes, unsigned long long iMilliseconds )
2059{
2060 m_iMaxBytes = iBytes;
2061 m_iMaxMilliSeconds = iMilliseconds;
2062}
2063
2064u_int Csock::GetRateBytes() { return( m_iMaxBytes ); }
2065unsigned long long Csock::GetRateTime() { return( m_iMaxMilliSeconds ); }
2066
2067void Csock::Cron()
2068{
2bbdb72a 2069 time_t iNow = 0;
2070
8a769a6f 2071 for( vector<CCron *>::size_type a = 0; a < m_vcCrons.size(); a++ )
79aaf3d5 2072 {
8a769a6f 2073 CCron *pcCron = m_vcCrons[a];
2074
2075 if ( !pcCron->isValid() )
2076 {
2077 CS_Delete( pcCron );
2078 m_vcCrons.erase( m_vcCrons.begin() + a-- );
2079 } else
30cf3a30 2080 pcCron->run( iNow );
8a769a6f 2081 }
2082}
2083
8a769a6f 2084void Csock::AddCron( CCron * pcCron )
2085{
2086 m_vcCrons.push_back( pcCron );
2087}
2088
8a769a6f 2089void Csock::DelCron( const CS_STRING & sName, bool bDeleteAll, bool bCaseSensitive )
2090{
2091 for( u_int a = 0; a < m_vcCrons.size(); a++ )
2092 {
2093 int (*Cmp)(const char *, const char *) = ( bCaseSensitive ? strcmp : strcasecmp );
2094 if ( Cmp( m_vcCrons[a]->GetName().c_str(), sName.c_str() ) == 0 )
2095 {
2096 m_vcCrons[a]->Stop();
2097 CS_Delete( m_vcCrons[a] );
2098 m_vcCrons.erase( m_vcCrons.begin() + a-- );
b63b7d03 2099 if( !bDeleteAll )
2100 break;
8a769a6f 2101 }
2102 }
2103}
2104
8a769a6f 2105void Csock::DelCron( u_int iPos )
2106{
2107 if ( iPos < m_vcCrons.size() )
2108 {
2109 m_vcCrons[iPos]->Stop();
2110 CS_Delete( m_vcCrons[iPos] );
2111 m_vcCrons.erase( m_vcCrons.begin() + iPos );
2112 }
2113}
ed120ee5 2114
8a769a6f 2115void Csock::DelCronByAddr( CCron *pcCron )
2116{
2117 for( u_int a = 0; a < m_vcCrons.size(); a++ )
2118 {
2119 if ( m_vcCrons[a] == pcCron )
2120 {
2121 m_vcCrons[a]->Stop();
2122 CS_Delete( m_vcCrons[a] );
2123 m_vcCrons.erase( m_vcCrons.begin() + a );
2124 return;
2125 }
2126 }
2127}
2128
2129void Csock::EnableReadLine() { m_bEnableReadLine = true; }
2809dd11 2130void Csock::DisableReadLine() {
2131 m_bEnableReadLine = false;
2132 m_sbuffer.clear();
2133}
8a769a6f 2134
2135void Csock::ReachedMaxBuffer()
2136{
2d1602ec 2137 std::cerr << "Warning, Max Buffer length Warning Threshold has been hit" << endl;
2138 std::cerr << "If you don't care, then set SetMaxBufferThreshold to 0" << endl;
8a769a6f 2139}
2140
2141int Csock::GetPending()
2142{
2143#ifdef HAVE_LIBSSL
2144 if( m_ssl )
9f7c0db4 2145 {
2146 // in v23 method, the pending function is initialized to ssl_undefined_const_function
2147 // which throws SSL_UNDEFINED_CONST_FUNCTION on to the error stack
2148 // this is one of the more stupid things in openssl, it seems bizarre that even though SSL_pending
2149 // returns an int, they don't bother returning in error to notify us, so basically
2150 // we have to always clear errors here generated by SSL_pending, otherwise the stack could
2151 // have a lame error on it causing SSL_write to fail in certain instances.
94479f39 2152#if defined( OPENSSL_VERSION_NUMBER ) && OPENSSL_VERSION_NUMBER >= 0x00908000
9f7c0db4 2153 ERR_set_mark();
2154 int iBytes = SSL_pending( m_ssl );
2155 ERR_pop_to_mark();
2156 return( iBytes );
88e7f093 2157#else
558e2779 2158 int iBytes = SSL_pending( m_ssl );
2159 ERR_clear_error(); // to get safer handling, upgrade your openssl version!
635fb4bc 2160 return( iBytes );
558e2779 2161#endif /* OPENSSL_VERSION_NUMBER */
9f7c0db4 2162 }
8a769a6f 2163 else
2164 return( 0 );
2165#else
2166 return( 0 );
2167#endif /* HAVE_LIBSSL */
2168}
2169
6faf0980 2170int Csock::GetAddrInfo( const CS_STRING & sHostname, CSSockAddr & csSockAddr )
2171{
6ce29e77 2172#ifdef HAVE_IPV6
2173 if( csSockAddr.GetAFRequire() != AF_INET && inet_pton( AF_INET6, sHostname.c_str(), csSockAddr.GetAddr6() ) > 0 )
2174 {
2175 SetIPv6( true );
2176 return( 0 );
2177 }
2178#endif /* HAVE_IPV6 */
2179 if( inet_pton( AF_INET, sHostname.c_str(), csSockAddr.GetAddr() ) > 0 )
2180 {
2181#ifdef HAVE_IPV6
2182 SetIPv6( false );
2183#endif /* HAVE_IPV6 */
2184 return( 0 );
2185 }
2186
2187#ifdef HAVE_C_ARES
2188 if( GetType() != LISTENER )
2189 { // right now the current function in Listen() is it blocks, the easy way around this at the moment is to use ip
f1515361 2190 // need to compute this up here
6ce29e77 2191 if( !m_pARESChannel )
2192 {
2193 if( ares_init( &m_pARESChannel ) != ARES_SUCCESS )
2194 { // TODO throw some debug?
2195 FreeAres();
2196 return( ETIMEDOUT );
2197 }
2198 m_pCurrAddr = &csSockAddr; // flag its starting
6ce29e77 2199
e566a535 2200 int iFamily = AF_INET;
6ce29e77 2201#ifdef HAVE_IPV6
25ef3439 2202 // as of ares 1.6.0 if it fails on af_inet6, it falls back to af_inet, this code was here in the previous Csocket version, just adding the comment as a reminder
e566a535 2203 iFamily = csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY ? AF_INET6 : csSockAddr.GetAFRequire();
6ce29e77 2204#endif /* HAVE_IPV6 */
2205 ares_gethostbyname( m_pARESChannel, sHostname.c_str(), iFamily, AresHostCallback, this );
2206 }
2207 if( !m_pCurrAddr )
2208 { // this means its finished
2209 FreeAres();
f1515361 2210#ifdef HAVE_IPV6
ca1e8d43 2211 if( m_iARESStatus == ARES_SUCCESS && csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY && GetIPv6() )
2212 {
2213 // this means that ares_host returned an ipv6 host, so try a connect right away
2214 if( CreateSocksFD() && Connect( GetBindHost(), true ) )
2215 {
2216 SetSkipConnect( true );
2217 }
2218 else if( GetSockError() == ENETUNREACH )
2219 {
2220 // the Connect() failed, so throw a retry back in with ipv4, and let it process normally
2221 CS_DEBUG( "Failed ipv6 connection with PF_UNSPEC, falling back to ipv4" );
2222 m_iARESStatus = -1;
ebbc126b 2223 CloseSocksFD();
ca1e8d43 2224 SetAFRequire( CSSockAddr::RAF_INET );
2225 return( GetAddrInfo( sHostname, csSockAddr ) );
2226 }
2227 }
f1515361 2228#if ARES_VERSION < CREATE_ARES_VER( 1, 5, 3 )
e566a535 2229 if( m_iARESStatus != ARES_SUCCESS && csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY )
f1515361 2230 { // this is a workaround for ares < 1.5.3 where the builtin retry on failed AF_INET6 isn't there yet
2231 CS_DEBUG( "Retry for older version of c-ares with AF_INET only" );
2232 // this means we tried previously with AF_INET6 and failed, so force AF_INET and retry
2233 SetAFRequire( CSSockAddr::RAF_INET );
2234 return( GetAddrInfo( sHostname, csSockAddr ) );
2235 }
2236#endif /* ARES_VERSION < CREATE_ARES_VER( 1, 5, 3 ) */
2237#endif /* HAVE_IPV6 */
6ce29e77 2238 return( m_iARESStatus == ARES_SUCCESS ? 0 : ETIMEDOUT );
2239 }
2240 return( EAGAIN );
2241 }
2242#endif /* HAVE_C_ARES */
2243
6faf0980 2244 return( ::GetAddrInfo( sHostname, this, csSockAddr ) );
2245}
2246
6dbb196e 2247int Csock::DNSLookup( EDNSLType eDNSLType )
2248{
2249 if ( eDNSLType == DNS_VHOST )
2250 {
2251 if ( m_sBindHost.empty() )
2252 {
2253 if ( m_eConState != CST_OK )
493d5154 2254 m_eConState = CST_DESTDNS; // skip binding, there is no vhost
6dbb196e 2255 return( 0 );
2256 }
2257
487b6b65 2258 m_bindhost.SinFamily();
2259 m_bindhost.SinPort( 0 );
6dbb196e 2260 }
2261
fd90be44 2262 int iRet = ETIMEDOUT;
6dbb196e 2263 if ( eDNSLType == DNS_VHOST )
487b6b65 2264 {
6faf0980 2265 iRet = GetAddrInfo( m_sBindHost, m_bindhost );
b5e6518f 2266#ifdef HAVE_IPV6
2267 if( m_bindhost.GetIPv6() )
2268 {
2269 SetAFRequire( CSSockAddr::RAF_INET6 );
2270 }
2271 else
2272 {
2273 SetAFRequire( CSSockAddr::RAF_INET );
2274 }
2275#endif /* HAVE_IPV6 */
487b6b65 2276 }
6dbb196e 2277 else
487b6b65 2278 {
6faf0980 2279 iRet = GetAddrInfo( m_shostname, m_address );
487b6b65 2280 }
6dbb196e 2281
2282 if ( iRet == 0 )
2283 {
4c14b1bf 2284 if( !CreateSocksFD() )
2285 {
2286 m_iDNSTryCount = 0;
9bb57639 2287 return( ETIMEDOUT );
4c14b1bf 2288 }
6dbb196e 2289 if ( m_eConState != CST_OK )
fc191e49 2290 m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_CONNECT );
6dbb196e 2291 m_iDNSTryCount = 0;
2292 return( 0 );
2293 }
6faf0980 2294 else if ( iRet == EAGAIN )
6dbb196e 2295 {
25ef3439 2296#ifndef HAVE_C_ARES
6dbb196e 2297 m_iDNSTryCount++;
2298 if ( m_iDNSTryCount > 20 )
2299 {
2300 m_iDNSTryCount = 0;
2301 return( ETIMEDOUT );
2302 }
25ef3439 2303#endif /* HAVE_C_ARES */
6dbb196e 2304 return( EAGAIN );
2305 }
2306 m_iDNSTryCount = 0;
2307 return( ETIMEDOUT );
6dbb196e 2308}
2309
2310bool Csock::SetupVHost()
2311{
2312 if ( m_sBindHost.empty() )
2313 {
2314 if ( m_eConState != CST_OK )
493d5154 2315 m_eConState = CST_DESTDNS;
6dbb196e 2316 return( true );
2317 }
12ed0475 2318 int iRet = -1;
2319 if( !GetIPv6() )
2320 iRet = bind( m_iReadSock, (struct sockaddr *) m_bindhost.GetSockAddr(), m_bindhost.GetSockAddrLen() );
2321#ifdef HAVE_IPV6
2322 else
2323 iRet = bind( m_iReadSock, (struct sockaddr *) m_bindhost.GetSockAddr6(), m_bindhost.GetSockAddrLen6() );
2324#endif /* HAVE_IPV6 */
2325
2326 if ( iRet == 0 )
6dbb196e 2327 {
2328 if ( m_eConState != CST_OK )
493d5154 2329 m_eConState = CST_DESTDNS;
6dbb196e 2330 return( true );
2331 }
2332 m_iCurBindCount++;
2333 if ( m_iCurBindCount > 3 )
2334 {
2335 CS_DEBUG( "Failure to bind to " << m_sBindHost );
2336 return( false );
2337 }
2338
2339 return( true );
2340}
2341
8a769a6f 2342#ifdef HAVE_LIBSSL
2343void Csock::FREE_SSL()
2344{
2345 if ( m_ssl )
2346 {
2347 SSL_shutdown( m_ssl );
2348 SSL_free( m_ssl );
2349 }
2350 m_ssl = NULL;
2351}
2352
2353void Csock::FREE_CTX()
2354{
2355 if ( m_ssl_ctx )
2356 SSL_CTX_free( m_ssl_ctx );
2357
2358 m_ssl_ctx = NULL;
2359}
2360
2361#endif /* HAVE_LIBSSL */
2362
25ef3439 2363cs_sock_t Csock::CreateSocket( bool bListen )
8a769a6f 2364{
ed120ee5 2365#ifdef HAVE_IPV6
25ef3439 2366 cs_sock_t iRet = socket( ( GetIPv6() ? PF_INET6 : PF_INET ), SOCK_STREAM, IPPROTO_TCP );
ed120ee5 2367#else
25ef3439 2368 cs_sock_t iRet = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
ed120ee5 2369#endif /* HAVE_IPV6 */
2370
88e7f093 2371 if ( iRet != CS_INVALID_SOCK )
f5ede26c 2372 {
c6664d5a 2373 set_close_on_exec( iRet );
8a769a6f 2374
88e7f093 2375 if ( bListen )
f5ede26c 2376 {
c6664d5a 2377 const int on = 1;
8a769a6f 2378
f5ede26c 2379 if ( setsockopt( iRet, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof( on ) ) != 0 )
2380 PERROR( "SO_REUSEADDR" );
c6664d5a 2381 }
88e7f093 2382 }
f5ede26c 2383 else
8a769a6f 2384 PERROR( "socket" );
2385
2386 return( iRet );
2387}
2388
6ce29e77 2389void Csock::Init( const CS_STRING & sHostname, u_short uPort, int itimeout )
8a769a6f 2390{
79aaf3d5 2391#ifdef HAVE_LIBSSL
8a769a6f 2392 m_ssl = NULL;
2393 m_ssl_ctx = NULL;
37d0c5e5 2394 m_iRequireClientCertFlags = 0;
79aaf3d5 2395#endif /* HAVE_LIBSSL */
b63b7d03 2396 m_iTcount = 0;
25ef3439 2397 m_iReadSock = CS_INVALID_SOCK;
2398 m_iWriteSock = CS_INVALID_SOCK;
8a769a6f 2399 m_itimeout = itimeout;
2400 m_bssl = false;
2401 m_bIsConnected = false;
25ef3439 2402 m_uPort = uPort;
8a769a6f 2403 m_shostname = sHostname;
8a769a6f 2404 m_sbuffer.clear();
e41a7f46 2405 m_eCloseType = CLT_DONT;
8a769a6f 2406 m_bBLOCK = true;
2407 m_iMethod = SSL23;
2408 m_sCipherType = "ALL";
2409 m_iMaxBytes = 0;
2410 m_iMaxMilliSeconds = 0;
2411 m_iLastSendTime = 0;
2412 m_iLastSend = 0;
8a769a6f 2413 m_bsslEstablished = false;
2414 m_bEnableReadLine = false;
8a769a6f 2415 m_iMaxStoredBufferLength = 1024;
2416 m_iConnType = INBOUND;
2417 m_iRemotePort = 0;
2418 m_iLocalPort = 0;
2419 m_iBytesRead = 0;
2420 m_iBytesWritten = 0;
2421 m_iStartTime = millitime();
2422 m_bPauseRead = false;
2423 m_iTimeoutType = TMO_ALL;
6dbb196e 2424 m_eConState = CST_OK; // default should be ok
2425 m_iDNSTryCount = 0;
2426 m_iCurBindCount = 0;
487b6b65 2427 m_bIsIPv6 = false;
493d5154 2428 m_bSkipConnect = false;
b63b7d03 2429 m_iLastCheckTimeoutTime = 0;
6ce29e77 2430#ifdef HAVE_C_ARES
2431 m_pARESChannel = NULL;
2432 m_pCurrAddr = NULL;
2433 m_iARESStatus = -1;
2434#endif /* HAVE_C_ARES */
8a769a6f 2435}
2d1602ec 2436