Coverage Report

Created: 2025-08-26 06:32

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