12
12
#include " hash.h"
13
13
#include " sync.h"
14
14
#include " uint256.h"
15
+ #include " random.h"
15
16
#include " util.h"
16
17
#include " utilstrencodings.h"
17
18
@@ -38,7 +39,7 @@ using namespace std;
38
39
39
40
// Settings
40
41
static proxyType proxyInfo[NET_MAX];
41
- static CService nameProxy;
42
+ static proxyType nameProxy;
42
43
static CCriticalSection cs_proxyInfos;
43
44
int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
44
45
bool fNameLookup = false ;
@@ -285,59 +286,100 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock
285
286
return len == 0 ;
286
287
}
287
288
288
- bool static Socks5 (string strDest, int port, SOCKET& hSocket)
289
+ struct ProxyCredentials
290
+ {
291
+ std::string username;
292
+ std::string password;
293
+ };
294
+
295
+ /* * Connect using SOCKS5 (as described in RFC1928) */
296
+ bool static Socks5 (string strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
289
297
{
290
298
LogPrintf (" SOCKS5 connecting %s\n " , strDest);
291
- if (strDest.size () > 255 )
292
- {
299
+ if (strDest.size () > 255 ) {
293
300
CloseSocket (hSocket);
294
301
return error (" Hostname too long" );
295
302
}
296
- char pszSocks5Init[] = " \5\1\0 " ;
297
- ssize_t nSize = sizeof (pszSocks5Init) - 1 ;
298
-
299
- ssize_t ret = send (hSocket, pszSocks5Init, nSize, MSG_NOSIGNAL);
300
- if (ret != nSize)
301
- {
303
+ // Accepted authentication methods
304
+ std::vector<uint8_t > vSocks5Init;
305
+ vSocks5Init.push_back (0x05 );
306
+ if (auth) {
307
+ vSocks5Init.push_back (0x02 ); // # METHODS
308
+ vSocks5Init.push_back (0x00 ); // X'00' NO AUTHENTICATION REQUIRED
309
+ vSocks5Init.push_back (0x02 ); // X'02' USERNAME/PASSWORD (RFC1929)
310
+ } else {
311
+ vSocks5Init.push_back (0x01 ); // # METHODS
312
+ vSocks5Init.push_back (0x00 ); // X'00' NO AUTHENTICATION REQUIRED
313
+ }
314
+ ssize_t ret = send (hSocket, (const char *)begin_ptr (vSocks5Init), vSocks5Init.size (), MSG_NOSIGNAL);
315
+ if (ret != (ssize_t )vSocks5Init.size ()) {
302
316
CloseSocket (hSocket);
303
317
return error (" Error sending to proxy" );
304
318
}
305
319
char pchRet1[2 ];
306
- if (!InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket))
307
- {
320
+ if (!InterruptibleRecv (pchRet1, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
308
321
CloseSocket (hSocket);
309
322
return error (" Error reading proxy response" );
310
323
}
311
- if (pchRet1[0 ] != 0x05 || pchRet1[1 ] != 0x00 )
312
- {
324
+ if (pchRet1[0 ] != 0x05 ) {
313
325
CloseSocket (hSocket);
314
326
return error (" Proxy failed to initialize" );
315
327
}
316
- string strSocks5 (" \5\1 " );
317
- strSocks5 += ' \000 ' ; strSocks5 += ' \003 ' ;
318
- strSocks5 += static_cast <char >(std::min ((int )strDest.size (), 255 ));
319
- strSocks5 += strDest;
320
- strSocks5 += static_cast <char >((port >> 8 ) & 0xFF );
321
- strSocks5 += static_cast <char >((port >> 0 ) & 0xFF );
322
- ret = send (hSocket, strSocks5.data (), strSocks5.size (), MSG_NOSIGNAL);
323
- if (ret != (ssize_t )strSocks5.size ())
324
- {
328
+ if (pchRet1[1 ] == 0x02 && auth) {
329
+ // Perform username/password authentication (as described in RFC1929)
330
+ std::vector<uint8_t > vAuth;
331
+ vAuth.push_back (0x01 );
332
+ if (auth->username .size () > 255 || auth->password .size () > 255 )
333
+ return error (" Proxy username or password too long" );
334
+ vAuth.push_back (auth->username .size ());
335
+ vAuth.insert (vAuth.end (), auth->username .begin (), auth->username .end ());
336
+ vAuth.push_back (auth->password .size ());
337
+ vAuth.insert (vAuth.end (), auth->password .begin (), auth->password .end ());
338
+ ret = send (hSocket, (const char *)begin_ptr (vAuth), vAuth.size (), MSG_NOSIGNAL);
339
+ if (ret != (ssize_t )vAuth.size ()) {
340
+ CloseSocket (hSocket);
341
+ return error (" Error sending authentication to proxy" );
342
+ }
343
+ LogPrint (" proxy" , " SOCKS5 sending proxy authentication %s:%s\n " , auth->username , auth->password );
344
+ char pchRetA[2 ];
345
+ if (!InterruptibleRecv (pchRetA, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
346
+ CloseSocket (hSocket);
347
+ return error (" Error reading proxy authentication response" );
348
+ }
349
+ if (pchRetA[0 ] != 0x01 || pchRetA[1 ] != 0x00 ) {
350
+ CloseSocket (hSocket);
351
+ return error (" Proxy authentication unsuccesful" );
352
+ }
353
+ } else if (pchRet1[1 ] == 0x00 ) {
354
+ // Perform no authentication
355
+ } else {
356
+ CloseSocket (hSocket);
357
+ return error (" Proxy requested wrong authentication method %02x" , pchRet1[1 ]);
358
+ }
359
+ std::vector<uint8_t > vSocks5;
360
+ vSocks5.push_back (0x05 ); // VER protocol version
361
+ vSocks5.push_back (0x01 ); // CMD CONNECT
362
+ vSocks5.push_back (0x00 ); // RSV Reserved
363
+ vSocks5.push_back (0x03 ); // ATYP DOMAINNAME
364
+ vSocks5.push_back (strDest.size ()); // Length<=255 is checked at beginning of function
365
+ vSocks5.insert (vSocks5.end (), strDest.begin (), strDest.end ());
366
+ vSocks5.push_back ((port >> 8 ) & 0xFF );
367
+ vSocks5.push_back ((port >> 0 ) & 0xFF );
368
+ ret = send (hSocket, (const char *)begin_ptr (vSocks5), vSocks5.size (), MSG_NOSIGNAL);
369
+ if (ret != (ssize_t )vSocks5.size ()) {
325
370
CloseSocket (hSocket);
326
371
return error (" Error sending to proxy" );
327
372
}
328
373
char pchRet2[4 ];
329
- if (!InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket))
330
- {
374
+ if (!InterruptibleRecv (pchRet2, 4 , SOCKS5_RECV_TIMEOUT, hSocket)) {
331
375
CloseSocket (hSocket);
332
376
return error (" Error reading proxy response" );
333
377
}
334
- if (pchRet2[0 ] != 0x05 )
335
- {
378
+ if (pchRet2[0 ] != 0x05 ) {
336
379
CloseSocket (hSocket);
337
380
return error (" Proxy failed to accept request" );
338
381
}
339
- if (pchRet2[1 ] != 0x00 )
340
- {
382
+ if (pchRet2[1 ] != 0x00 ) {
341
383
CloseSocket (hSocket);
342
384
switch (pchRet2[1 ])
343
385
{
@@ -352,8 +394,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
352
394
default : return error (" Proxy error: unknown" );
353
395
}
354
396
}
355
- if (pchRet2[2 ] != 0x00 )
356
- {
397
+ if (pchRet2[2 ] != 0x00 ) {
357
398
CloseSocket (hSocket);
358
399
return error (" Error: malformed proxy response" );
359
400
}
@@ -375,13 +416,11 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
375
416
}
376
417
default : CloseSocket (hSocket); return error (" Error: malformed proxy response" );
377
418
}
378
- if (!ret)
379
- {
419
+ if (!ret) {
380
420
CloseSocket (hSocket);
381
421
return error (" Error reading from proxy" );
382
422
}
383
- if (!InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket))
384
- {
423
+ if (!InterruptibleRecv (pchRet3, 2 , SOCKS5_RECV_TIMEOUT, hSocket)) {
385
424
CloseSocket (hSocket);
386
425
return error (" Error reading from proxy" );
387
426
}
@@ -471,7 +510,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
471
510
return true ;
472
511
}
473
512
474
- bool SetProxy (enum Network net, CService addrProxy) {
513
+ bool SetProxy (enum Network net, const proxyType & addrProxy) {
475
514
assert (net >= 0 && net < NET_MAX);
476
515
if (!addrProxy.IsValid ())
477
516
return false ;
@@ -489,15 +528,15 @@ bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
489
528
return true ;
490
529
}
491
530
492
- bool SetNameProxy (CService addrProxy) {
531
+ bool SetNameProxy (const proxyType & addrProxy) {
493
532
if (!addrProxy.IsValid ())
494
533
return false ;
495
534
LOCK (cs_proxyInfos);
496
535
nameProxy = addrProxy;
497
536
return true ;
498
537
}
499
538
500
- bool GetNameProxy (CService &nameProxyOut) {
539
+ bool GetNameProxy (proxyType &nameProxyOut) {
501
540
LOCK (cs_proxyInfos);
502
541
if (!nameProxy.IsValid ())
503
542
return false ;
@@ -513,37 +552,49 @@ bool HaveNameProxy() {
513
552
bool IsProxy (const CNetAddr &addr) {
514
553
LOCK (cs_proxyInfos);
515
554
for (int i = 0 ; i < NET_MAX; i++) {
516
- if (addr == (CNetAddr)proxyInfo[i])
555
+ if (addr == (CNetAddr)proxyInfo[i]. proxy )
517
556
return true ;
518
557
}
519
558
return false ;
520
559
}
521
560
522
- bool ConnectSocket (const CService &addrDest , SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
561
+ static bool ConnectThroughProxy (const proxyType &proxy, const std::string strDest, int port , SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
523
562
{
524
- proxyType proxy;
525
- if (outProxyConnectionFailed)
526
- *outProxyConnectionFailed = false ;
527
- // no proxy needed (none set for target network)
528
- if (!GetProxy (addrDest.GetNetwork (), proxy))
529
- return ConnectSocketDirectly (addrDest, hSocketRet, nTimeout);
530
-
531
563
SOCKET hSocket = INVALID_SOCKET;
532
-
533
564
// first connect to proxy server
534
- if (!ConnectSocketDirectly (proxy, hSocket, nTimeout)) {
565
+ if (!ConnectSocketDirectly (proxy. proxy , hSocket, nTimeout)) {
535
566
if (outProxyConnectionFailed)
536
567
*outProxyConnectionFailed = true ;
537
568
return false ;
538
569
}
539
570
// do socks negotiation
540
- if (!Socks5 (addrDest.ToStringIP (), addrDest.GetPort (), hSocket))
541
- return false ;
571
+ if (proxy.randomize_credentials ) {
572
+ ProxyCredentials random_auth;
573
+ random_auth.username = strprintf (" %i" , insecure_rand ());
574
+ random_auth.password = strprintf (" %i" , insecure_rand ());
575
+ if (!Socks5 (strDest, (unsigned short )port, &random_auth, hSocket))
576
+ return false ;
577
+ } else {
578
+ if (!Socks5 (strDest, (unsigned short )port, 0 , hSocket))
579
+ return false ;
580
+ }
542
581
543
582
hSocketRet = hSocket;
544
583
return true ;
545
584
}
546
585
586
+ bool ConnectSocket (const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
587
+ {
588
+ proxyType proxy;
589
+ if (outProxyConnectionFailed)
590
+ *outProxyConnectionFailed = false ;
591
+
592
+ if (GetProxy (addrDest.GetNetwork (), proxy))
593
+ return ConnectThroughProxy (proxy, addrDest.ToStringIP (), addrDest.GetPort (), hSocketRet, nTimeout, outProxyConnectionFailed);
594
+ else // no proxy needed (none set for target network)
595
+ return ConnectSocketDirectly (addrDest, hSocketRet, nTimeout);
596
+ }
597
+
547
598
bool ConnectSocketByName (CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
548
599
{
549
600
string strDest;
@@ -554,9 +605,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
554
605
555
606
SplitHostPort (string (pszDest), port, strDest);
556
607
557
- SOCKET hSocket = INVALID_SOCKET;
558
-
559
- CService nameProxy;
608
+ proxyType nameProxy;
560
609
GetNameProxy (nameProxy);
561
610
562
611
CService addrResolved (CNetAddr (strDest, fNameLookup && !HaveNameProxy ()), port);
@@ -569,18 +618,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
569
618
570
619
if (!HaveNameProxy ())
571
620
return false ;
572
- // first connect to name proxy server
573
- if (!ConnectSocketDirectly (nameProxy, hSocket, nTimeout)) {
574
- if (outProxyConnectionFailed)
575
- *outProxyConnectionFailed = true ;
576
- return false ;
577
- }
578
- // do socks negotiation
579
- if (!Socks5 (strDest, (unsigned short )port, hSocket))
580
- return false ;
581
-
582
- hSocketRet = hSocket;
583
- return true ;
621
+ return ConnectThroughProxy (nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
584
622
}
585
623
586
624
void CNetAddr::Init ()
0 commit comments