You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TcpSocket.cxx 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #ifdef WIN32
  22. //#include <io.h>
  23. #include <winsock2.h>
  24. #include <ws2tcpip.h>
  25. #define errorNumber WSAGetLastError()
  26. #else
  27. #define errorNumber errno
  28. #define closesocket close
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31. #include <arpa/inet.h>
  32. #include <netinet/tcp.h>
  33. #include <netdb.h>
  34. #include <errno.h>
  35. #include <string.h>
  36. #include <signal.h>
  37. #include <fcntl.h>
  38. #endif
  39. #include <stdlib.h>
  40. #include <unistd.h>
  41. #include <network/TcpSocket.h>
  42. #include <rfb/util.h>
  43. #include <rfb/LogWriter.h>
  44. #include <rfb/Configuration.h>
  45. #ifdef WIN32
  46. #include <os/winerrno.h>
  47. #endif
  48. #ifndef INADDR_NONE
  49. #define INADDR_NONE ((unsigned long)-1)
  50. #endif
  51. #ifndef INADDR_LOOPBACK
  52. #define INADDR_LOOPBACK ((unsigned long)0x7F000001)
  53. #endif
  54. #ifndef IN6_ARE_ADDR_EQUAL
  55. #define IN6_ARE_ADDR_EQUAL(a,b) \
  56. (memcmp ((const void*)(a), (const void*)(b), sizeof (struct in6_addr)) == 0)
  57. #endif
  58. // Missing on older Windows and OS X
  59. #ifndef AI_NUMERICSERV
  60. #define AI_NUMERICSERV 0
  61. #endif
  62. using namespace network;
  63. using namespace rdr;
  64. static rfb::LogWriter vlog("TcpSocket");
  65. static rfb::BoolParameter UseIPv4("UseIPv4", "Use IPv4 for incoming and outgoing connections.", true);
  66. static rfb::BoolParameter UseIPv6("UseIPv6", "Use IPv6 for incoming and outgoing connections.", true);
  67. /* Tunnelling support. */
  68. int network::findFreeTcpPort (void)
  69. {
  70. int sock;
  71. struct sockaddr_in addr;
  72. memset(&addr, 0, sizeof(addr));
  73. addr.sin_family = AF_INET;
  74. addr.sin_addr.s_addr = INADDR_ANY;
  75. if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  76. throw SocketException ("unable to create socket", errorNumber);
  77. addr.sin_port = 0;
  78. if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
  79. throw SocketException ("unable to find free port", errorNumber);
  80. socklen_t n = sizeof(addr);
  81. if (getsockname (sock, (struct sockaddr *)&addr, &n) < 0)
  82. throw SocketException ("unable to get port number", errorNumber);
  83. closesocket (sock);
  84. return ntohs(addr.sin_port);
  85. }
  86. // -=- Socket initialisation
  87. static bool socketsInitialised = false;
  88. static void initSockets() {
  89. if (socketsInitialised)
  90. return;
  91. #ifdef WIN32
  92. WORD requiredVersion = MAKEWORD(2,0);
  93. WSADATA initResult;
  94. if (WSAStartup(requiredVersion, &initResult) != 0)
  95. throw SocketException("unable to initialise Winsock2", errorNumber);
  96. #else
  97. signal(SIGPIPE, SIG_IGN);
  98. #endif
  99. socketsInitialised = true;
  100. }
  101. // -=- TcpSocket
  102. TcpSocket::TcpSocket(int sock, bool close)
  103. : Socket(new FdInStream(sock), new FdOutStream(sock), true), closeFd(close)
  104. {
  105. }
  106. TcpSocket::TcpSocket(const char *host, int port)
  107. : closeFd(true)
  108. {
  109. int sock, err, result;
  110. struct addrinfo *ai, *current, hints;
  111. // - Create a socket
  112. initSockets();
  113. memset(&hints, 0, sizeof(struct addrinfo));
  114. hints.ai_family = AF_UNSPEC;
  115. hints.ai_socktype = SOCK_STREAM;
  116. hints.ai_canonname = NULL;
  117. hints.ai_addr = NULL;
  118. hints.ai_next = NULL;
  119. if ((result = getaddrinfo(host, NULL, &hints, &ai)) != 0) {
  120. throw Exception("unable to resolve host by name: %s",
  121. gai_strerror(result));
  122. }
  123. sock = -1;
  124. err = 0;
  125. for (current = ai; current != NULL; current = current->ai_next) {
  126. int family;
  127. vnc_sockaddr_t sa;
  128. socklen_t salen;
  129. char ntop[NI_MAXHOST];
  130. family = current->ai_family;
  131. switch (family) {
  132. case AF_INET:
  133. if (!UseIPv4)
  134. continue;
  135. break;
  136. case AF_INET6:
  137. if (!UseIPv6)
  138. continue;
  139. break;
  140. default:
  141. continue;
  142. }
  143. salen = current->ai_addrlen;
  144. memcpy(&sa, current->ai_addr, salen);
  145. if (family == AF_INET)
  146. sa.u.sin.sin_port = htons(port);
  147. else
  148. sa.u.sin6.sin6_port = htons(port);
  149. getnameinfo(&sa.u.sa, salen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST);
  150. vlog.debug("Connecting to %s [%s] port %d", host, ntop, port);
  151. sock = socket (family, SOCK_STREAM, 0);
  152. if (sock == -1) {
  153. err = errorNumber;
  154. freeaddrinfo(ai);
  155. throw SocketException("unable to create socket", err);
  156. }
  157. /* Attempt to connect to the remote host */
  158. while ((result = connect(sock, &sa.u.sa, salen)) == -1) {
  159. err = errorNumber;
  160. #ifndef WIN32
  161. if (err == EINTR)
  162. continue;
  163. #endif
  164. vlog.debug("Failed to connect to address %s port %d: %d",
  165. ntop, port, err);
  166. closesocket(sock);
  167. sock = -1;
  168. break;
  169. }
  170. if (result == 0)
  171. break;
  172. }
  173. freeaddrinfo(ai);
  174. if (sock == -1) {
  175. if (err == 0)
  176. throw Exception("No useful address for host");
  177. else
  178. throw SocketException("unable connect to socket", err);
  179. }
  180. #ifndef WIN32
  181. // - By default, close the socket on exec()
  182. fcntl(sock, F_SETFD, FD_CLOEXEC);
  183. #endif
  184. // Disable Nagle's algorithm, to reduce latency
  185. enableNagles(sock, false);
  186. // Create the input and output streams
  187. instream = new FdInStream(sock);
  188. outstream = new FdOutStream(sock);
  189. ownStreams = true;
  190. }
  191. TcpSocket::~TcpSocket() {
  192. if (closeFd)
  193. closesocket(getFd());
  194. }
  195. int TcpSocket::getMyPort() {
  196. return getSockPort(getFd());
  197. }
  198. char* TcpSocket::getPeerAddress() {
  199. vnc_sockaddr_t sa;
  200. socklen_t sa_size = sizeof(sa);
  201. if (getpeername(getFd(), &sa.u.sa, &sa_size) != 0) {
  202. vlog.error("unable to get peer name for socket");
  203. return rfb::strDup("");
  204. }
  205. if (sa.u.sa.sa_family == AF_INET6) {
  206. char buffer[INET6_ADDRSTRLEN + 2];
  207. int ret;
  208. buffer[0] = '[';
  209. ret = getnameinfo(&sa.u.sa, sizeof(sa.u.sin6),
  210. buffer + 1, sizeof(buffer) - 2, NULL, 0,
  211. NI_NUMERICHOST);
  212. if (ret != 0) {
  213. vlog.error("unable to convert peer name to a string");
  214. return rfb::strDup("");
  215. }
  216. strcat(buffer, "]");
  217. return rfb::strDup(buffer);
  218. }
  219. if (sa.u.sa.sa_family == AF_INET) {
  220. char *name;
  221. name = inet_ntoa(sa.u.sin.sin_addr);
  222. if (name == NULL) {
  223. vlog.error("unable to convert peer name to a string");
  224. return rfb::strDup("");
  225. }
  226. return rfb::strDup(name);
  227. }
  228. vlog.error("unknown address family for socket");
  229. return rfb::strDup("");
  230. }
  231. int TcpSocket::getPeerPort() {
  232. vnc_sockaddr_t sa;
  233. socklen_t sa_size = sizeof(sa);
  234. getpeername(getFd(), &sa.u.sa, &sa_size);
  235. switch (sa.u.sa.sa_family) {
  236. case AF_INET6:
  237. return ntohs(sa.u.sin6.sin6_port);
  238. case AF_INET:
  239. return ntohs(sa.u.sin.sin_port);
  240. default:
  241. return 0;
  242. }
  243. }
  244. char* TcpSocket::getPeerEndpoint() {
  245. rfb::CharArray address; address.buf = getPeerAddress();
  246. int port = getPeerPort();
  247. int buflen = strlen(address.buf) + 32;
  248. char* buffer = new char[buflen];
  249. sprintf(buffer, "%s::%d", address.buf, port);
  250. return buffer;
  251. }
  252. bool TcpSocket::sameMachine() {
  253. vnc_sockaddr_t peeraddr, myaddr;
  254. socklen_t addrlen;
  255. addrlen = sizeof(peeraddr);
  256. if (getpeername(getFd(), &peeraddr.u.sa, &addrlen) < 0)
  257. throw SocketException ("unable to get peer address", errorNumber);
  258. addrlen = sizeof(myaddr); /* need to reset, since getpeername overwrote */
  259. if (getsockname(getFd(), &myaddr.u.sa, &addrlen) < 0)
  260. throw SocketException ("unable to get my address", errorNumber);
  261. if (peeraddr.u.sa.sa_family != myaddr.u.sa.sa_family)
  262. return false;
  263. if (peeraddr.u.sa.sa_family == AF_INET6)
  264. return IN6_ARE_ADDR_EQUAL(&peeraddr.u.sin6.sin6_addr,
  265. &myaddr.u.sin6.sin6_addr);
  266. if (peeraddr.u.sa.sa_family == AF_INET)
  267. return (peeraddr.u.sin.sin_addr.s_addr == myaddr.u.sin.sin_addr.s_addr);
  268. // No idea what this is. Assume we're on different machines.
  269. return false;
  270. }
  271. void TcpSocket::shutdown()
  272. {
  273. Socket::shutdown();
  274. ::shutdown(getFd(), 2);
  275. }
  276. bool TcpSocket::enableNagles(int sock, bool enable) {
  277. int one = enable ? 0 : 1;
  278. if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
  279. (char *)&one, sizeof(one)) < 0) {
  280. int e = errorNumber;
  281. vlog.error("unable to setsockopt TCP_NODELAY: %d", e);
  282. return false;
  283. }
  284. return true;
  285. }
  286. bool TcpSocket::cork(bool enable) {
  287. #ifndef TCP_CORK
  288. return false;
  289. #else
  290. int one = enable ? 1 : 0;
  291. if (setsockopt(getFd(), IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one)) < 0)
  292. return false;
  293. return true;
  294. #endif
  295. }
  296. bool TcpSocket::isListening(int sock)
  297. {
  298. int listening = 0;
  299. socklen_t listening_size = sizeof(listening);
  300. if (getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN,
  301. (char *)&listening, &listening_size) < 0)
  302. return false;
  303. return listening != 0;
  304. }
  305. int TcpSocket::getSockPort(int sock)
  306. {
  307. vnc_sockaddr_t sa;
  308. socklen_t sa_size = sizeof(sa);
  309. if (getsockname(sock, &sa.u.sa, &sa_size) < 0)
  310. return 0;
  311. switch (sa.u.sa.sa_family) {
  312. case AF_INET6:
  313. return ntohs(sa.u.sin6.sin6_port);
  314. default:
  315. return ntohs(sa.u.sin.sin_port);
  316. }
  317. }
  318. TcpListener::TcpListener(int sock)
  319. {
  320. fd = sock;
  321. }
  322. TcpListener::TcpListener(const struct sockaddr *listenaddr,
  323. socklen_t listenaddrlen)
  324. {
  325. int one = 1;
  326. vnc_sockaddr_t sa;
  327. int sock;
  328. initSockets();
  329. if ((sock = socket (listenaddr->sa_family, SOCK_STREAM, 0)) < 0)
  330. throw SocketException("unable to create listening socket", errorNumber);
  331. memcpy (&sa, listenaddr, listenaddrlen);
  332. #ifdef IPV6_V6ONLY
  333. if (listenaddr->sa_family == AF_INET6) {
  334. if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&one, sizeof(one))) {
  335. int e = errorNumber;
  336. closesocket(sock);
  337. throw SocketException("unable to set IPV6_V6ONLY", e);
  338. }
  339. }
  340. #endif /* defined(IPV6_V6ONLY) */
  341. #ifdef FD_CLOEXEC
  342. // - By default, close the socket on exec()
  343. fcntl(sock, F_SETFD, FD_CLOEXEC);
  344. #endif
  345. // SO_REUSEADDR is broken on Windows. It allows binding to a port
  346. // that already has a listening socket on it. SO_EXCLUSIVEADDRUSE
  347. // might do what we want, but requires investigation.
  348. #ifndef WIN32
  349. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
  350. (char *)&one, sizeof(one)) < 0) {
  351. int e = errorNumber;
  352. closesocket(sock);
  353. throw SocketException("unable to create listening socket", e);
  354. }
  355. #endif
  356. if (bind(sock, &sa.u.sa, listenaddrlen) == -1) {
  357. int e = errorNumber;
  358. closesocket(sock);
  359. throw SocketException("failed to bind socket", e);
  360. }
  361. // - Set it to be a listening socket
  362. if (listen(sock, 5) < 0) {
  363. int e = errorNumber;
  364. closesocket(sock);
  365. throw SocketException("unable to set socket to listening mode", e);
  366. }
  367. fd = sock;
  368. }
  369. TcpListener::~TcpListener() {
  370. closesocket(fd);
  371. }
  372. void TcpListener::shutdown()
  373. {
  374. #ifdef WIN32
  375. closesocket(getFd());
  376. #else
  377. ::shutdown(getFd(), 2);
  378. #endif
  379. }
  380. Socket*
  381. TcpListener::accept() {
  382. int new_sock = -1;
  383. // Accept an incoming connection
  384. if ((new_sock = ::accept(fd, 0, 0)) < 0)
  385. throw SocketException("unable to accept new connection", errorNumber);
  386. #ifndef WIN32
  387. // - By default, close the socket on exec()
  388. fcntl(new_sock, F_SETFD, FD_CLOEXEC);
  389. #endif
  390. // Disable Nagle's algorithm, to reduce latency
  391. TcpSocket::enableNagles(new_sock, false);
  392. // Create the socket object & check connection is allowed
  393. TcpSocket* s = new TcpSocket(new_sock);
  394. if (filter && !filter->verifyConnection(s)) {
  395. delete s;
  396. return 0;
  397. }
  398. return s;
  399. }
  400. void TcpListener::getMyAddresses(std::list<char*>* result) {
  401. struct addrinfo *ai, *current, hints;
  402. initSockets();
  403. memset(&hints, 0, sizeof(struct addrinfo));
  404. hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
  405. hints.ai_family = AF_UNSPEC;
  406. hints.ai_socktype = SOCK_STREAM;
  407. hints.ai_canonname = NULL;
  408. hints.ai_addr = NULL;
  409. hints.ai_next = NULL;
  410. // Windows doesn't like NULL for service, so specify something
  411. if ((getaddrinfo(NULL, "1", &hints, &ai)) != 0)
  412. return;
  413. for (current= ai; current != NULL; current = current->ai_next) {
  414. switch (current->ai_family) {
  415. case AF_INET:
  416. if (!UseIPv4)
  417. continue;
  418. break;
  419. case AF_INET6:
  420. if (!UseIPv6)
  421. continue;
  422. break;
  423. default:
  424. continue;
  425. }
  426. char *addr = new char[INET6_ADDRSTRLEN];
  427. getnameinfo(current->ai_addr, current->ai_addrlen, addr, INET6_ADDRSTRLEN,
  428. NULL, 0, NI_NUMERICHOST);
  429. result->push_back(addr);
  430. }
  431. freeaddrinfo(ai);
  432. }
  433. int TcpListener::getMyPort() {
  434. return TcpSocket::getSockPort(getFd());
  435. }
  436. void network::createLocalTcpListeners(std::list<TcpListener*> *listeners,
  437. int port)
  438. {
  439. struct addrinfo ai[2];
  440. vnc_sockaddr_t sa[2];
  441. memset(ai, 0, sizeof(ai));
  442. memset(sa, 0, sizeof(sa));
  443. sa[0].u.sin.sin_family = AF_INET;
  444. sa[0].u.sin.sin_port = htons (port);
  445. sa[0].u.sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  446. ai[0].ai_family = sa[0].u.sin.sin_family;
  447. ai[0].ai_addr = &sa[0].u.sa;
  448. ai[0].ai_addrlen = sizeof(sa[0].u.sin);
  449. ai[0].ai_next = &ai[1];
  450. sa[1].u.sin6.sin6_family = AF_INET6;
  451. sa[1].u.sin6.sin6_port = htons (port);
  452. sa[1].u.sin6.sin6_addr = in6addr_loopback;
  453. ai[1].ai_family = sa[1].u.sin6.sin6_family;
  454. ai[1].ai_addr = &sa[1].u.sa;
  455. ai[1].ai_addrlen = sizeof(sa[1].u.sin6);
  456. ai[1].ai_next = NULL;
  457. createTcpListeners(listeners, ai);
  458. }
  459. void network::createTcpListeners(std::list<TcpListener*> *listeners,
  460. const char *addr,
  461. int port)
  462. {
  463. struct addrinfo *ai, hints;
  464. char service[16];
  465. int result;
  466. initSockets();
  467. memset(&hints, 0, sizeof(struct addrinfo));
  468. hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
  469. hints.ai_family = AF_UNSPEC;
  470. hints.ai_socktype = SOCK_STREAM;
  471. hints.ai_canonname = NULL;
  472. hints.ai_addr = NULL;
  473. hints.ai_next = NULL;
  474. snprintf (service, sizeof (service) - 1, "%d", port);
  475. service[sizeof (service) - 1] = '\0';
  476. if ((result = getaddrinfo(addr, service, &hints, &ai)) != 0)
  477. throw rdr::Exception("unable to resolve listening address: %s",
  478. gai_strerror(result));
  479. try {
  480. createTcpListeners(listeners, ai);
  481. } catch(...) {
  482. freeaddrinfo(ai);
  483. throw;
  484. }
  485. }
  486. void network::createTcpListeners(std::list<TcpListener*> *listeners,
  487. const struct addrinfo *ai)
  488. {
  489. const struct addrinfo *current;
  490. std::list<TcpListener*> new_listeners;
  491. initSockets();
  492. for (current = ai; current != NULL; current = current->ai_next) {
  493. switch (current->ai_family) {
  494. case AF_INET:
  495. if (!UseIPv4)
  496. continue;
  497. break;
  498. case AF_INET6:
  499. if (!UseIPv6)
  500. continue;
  501. break;
  502. default:
  503. continue;
  504. }
  505. try {
  506. new_listeners.push_back(new TcpListener(current->ai_addr,
  507. current->ai_addrlen));
  508. } catch (SocketException& e) {
  509. // Ignore this if it is due to lack of address family support on
  510. // the interface or on the system
  511. if (e.err != EADDRNOTAVAIL && e.err != EAFNOSUPPORT) {
  512. // Otherwise, report the error
  513. while (!new_listeners.empty()) {
  514. delete new_listeners.back();
  515. new_listeners.pop_back();
  516. }
  517. throw;
  518. }
  519. }
  520. }
  521. if (new_listeners.empty ())
  522. throw SocketException("createTcpListeners: no addresses available",
  523. EADDRNOTAVAIL);
  524. listeners->splice (listeners->end(), new_listeners);
  525. }
  526. TcpFilter::TcpFilter(const char* spec) {
  527. rfb::CharArray tmp;
  528. tmp.buf = rfb::strDup(spec);
  529. while (tmp.buf) {
  530. rfb::CharArray first;
  531. rfb::strSplit(tmp.buf, ',', &first.buf, &tmp.buf);
  532. if (strlen(first.buf))
  533. filter.push_back(parsePattern(first.buf));
  534. }
  535. }
  536. TcpFilter::~TcpFilter() {
  537. }
  538. static bool
  539. patternMatchIP(const TcpFilter::Pattern& pattern, vnc_sockaddr_t *sa) {
  540. switch (pattern.address.u.sa.sa_family) {
  541. unsigned long address;
  542. case AF_INET:
  543. if (sa->u.sa.sa_family != AF_INET)
  544. return false;
  545. address = sa->u.sin.sin_addr.s_addr;
  546. if (address == htonl (INADDR_NONE)) return false;
  547. return ((pattern.address.u.sin.sin_addr.s_addr &
  548. pattern.mask.u.sin.sin_addr.s_addr) ==
  549. (address & pattern.mask.u.sin.sin_addr.s_addr));
  550. case AF_INET6:
  551. if (sa->u.sa.sa_family != AF_INET6)
  552. return false;
  553. for (unsigned int n = 0; n < 16; n++) {
  554. unsigned int bits = (n + 1) * 8;
  555. unsigned int mask;
  556. if (pattern.prefixlen > bits)
  557. mask = 0xff;
  558. else {
  559. unsigned int lastbits = 0xff;
  560. lastbits <<= bits - pattern.prefixlen;
  561. mask = lastbits & 0xff;
  562. }
  563. if ((pattern.address.u.sin6.sin6_addr.s6_addr[n] & mask) !=
  564. (sa->u.sin6.sin6_addr.s6_addr[n] & mask))
  565. return false;
  566. if (mask < 0xff)
  567. break;
  568. }
  569. return true;
  570. case AF_UNSPEC:
  571. // Any address matches
  572. return true;
  573. default:
  574. break;
  575. }
  576. return false;
  577. }
  578. bool
  579. TcpFilter::verifyConnection(Socket* s) {
  580. rfb::CharArray name;
  581. vnc_sockaddr_t sa;
  582. socklen_t sa_size = sizeof(sa);
  583. if (getpeername(s->getFd(), &sa.u.sa, &sa_size) != 0)
  584. return false;
  585. name.buf = s->getPeerAddress();
  586. std::list<TcpFilter::Pattern>::iterator i;
  587. for (i=filter.begin(); i!=filter.end(); i++) {
  588. if (patternMatchIP(*i, &sa)) {
  589. switch ((*i).action) {
  590. case Accept:
  591. vlog.debug("ACCEPT %s", name.buf);
  592. return true;
  593. case Query:
  594. vlog.debug("QUERY %s", name.buf);
  595. s->setRequiresQuery();
  596. return true;
  597. case Reject:
  598. vlog.debug("REJECT %s", name.buf);
  599. return false;
  600. }
  601. }
  602. }
  603. vlog.debug("[REJECT] %s", name.buf);
  604. return false;
  605. }
  606. TcpFilter::Pattern TcpFilter::parsePattern(const char* p) {
  607. TcpFilter::Pattern pattern;
  608. rfb::CharArray addr, pref;
  609. bool prefix_specified;
  610. int family;
  611. initSockets();
  612. prefix_specified = rfb::strSplit(&p[1], '/', &addr.buf, &pref.buf);
  613. if (addr.buf[0] == '\0') {
  614. // Match any address
  615. memset (&pattern.address, 0, sizeof (pattern.address));
  616. pattern.address.u.sa.sa_family = AF_UNSPEC;
  617. pattern.prefixlen = 0;
  618. } else {
  619. struct addrinfo hints;
  620. struct addrinfo *ai;
  621. char *p = addr.buf;
  622. int result;
  623. memset (&hints, 0, sizeof (hints));
  624. hints.ai_family = AF_UNSPEC;
  625. hints.ai_flags = AI_NUMERICHOST;
  626. // Take out brackets, if present
  627. if (*p == '[') {
  628. size_t len;
  629. p++;
  630. len = strlen (p);
  631. if (len > 0 && p[len - 1] == ']')
  632. p[len - 1] = '\0';
  633. }
  634. if ((result = getaddrinfo (p, NULL, &hints, &ai)) != 0) {
  635. throw Exception("unable to resolve host by name: %s",
  636. gai_strerror(result));
  637. }
  638. memcpy (&pattern.address.u.sa, ai->ai_addr, ai->ai_addrlen);
  639. freeaddrinfo (ai);
  640. family = pattern.address.u.sa.sa_family;
  641. if (prefix_specified) {
  642. if (family == AF_INET &&
  643. rfb::strContains(pref.buf, '.')) {
  644. throw Exception("mask no longer supported for filter, "
  645. "use prefix instead");
  646. }
  647. pattern.prefixlen = (unsigned int) atoi(pref.buf);
  648. } else {
  649. switch (family) {
  650. case AF_INET:
  651. pattern.prefixlen = 32;
  652. break;
  653. case AF_INET6:
  654. pattern.prefixlen = 128;
  655. break;
  656. default:
  657. throw Exception("unknown address family");
  658. }
  659. }
  660. }
  661. family = pattern.address.u.sa.sa_family;
  662. if (pattern.prefixlen > (family == AF_INET ? 32: 128))
  663. throw Exception("invalid prefix length for filter address: %u",
  664. pattern.prefixlen);
  665. // Compute mask from address and prefix length
  666. memset (&pattern.mask, 0, sizeof (pattern.mask));
  667. switch (family) {
  668. unsigned long mask;
  669. case AF_INET:
  670. mask = 0;
  671. for (unsigned int i=0; i<pattern.prefixlen; i++)
  672. mask |= 1<<(31-i);
  673. pattern.mask.u.sin.sin_addr.s_addr = htonl(mask);
  674. break;
  675. case AF_INET6:
  676. for (unsigned int n = 0; n < 16; n++) {
  677. unsigned int bits = (n + 1) * 8;
  678. if (pattern.prefixlen > bits)
  679. pattern.mask.u.sin6.sin6_addr.s6_addr[n] = 0xff;
  680. else {
  681. unsigned int lastbits = 0xff;
  682. lastbits <<= bits - pattern.prefixlen;
  683. pattern.mask.u.sin6.sin6_addr.s6_addr[n] = lastbits & 0xff;
  684. break;
  685. }
  686. }
  687. break;
  688. case AF_UNSPEC:
  689. // No mask to compute
  690. break;
  691. default:
  692. ; /* not reached */
  693. }
  694. switch(p[0]) {
  695. case '+': pattern.action = TcpFilter::Accept; break;
  696. case '-': pattern.action = TcpFilter::Reject; break;
  697. case '?': pattern.action = TcpFilter::Query; break;
  698. };
  699. return pattern;
  700. }
  701. char* TcpFilter::patternToStr(const TcpFilter::Pattern& p) {
  702. rfb::CharArray addr;
  703. char buffer[INET6_ADDRSTRLEN + 2];
  704. if (p.address.u.sa.sa_family == AF_INET) {
  705. getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin),
  706. buffer, sizeof (buffer), NULL, 0, NI_NUMERICHOST);
  707. addr.buf = rfb::strDup(buffer);
  708. } else if (p.address.u.sa.sa_family == AF_INET6) {
  709. buffer[0] = '[';
  710. getnameinfo(&p.address.u.sa, sizeof(p.address.u.sin6),
  711. buffer + 1, sizeof (buffer) - 2, NULL, 0, NI_NUMERICHOST);
  712. strcat(buffer, "]");
  713. addr.buf = rfb::strDup(buffer);
  714. } else if (p.address.u.sa.sa_family == AF_UNSPEC)
  715. addr.buf = rfb::strDup("");
  716. char action;
  717. switch (p.action) {
  718. case Accept: action = '+'; break;
  719. case Reject: action = '-'; break;
  720. default:
  721. case Query: action = '?'; break;
  722. };
  723. size_t resultlen = (1 // action
  724. + strlen (addr.buf) // address
  725. + 1 // slash
  726. + 3 // prefix length, max 128
  727. + 1); // terminating nul
  728. char* result = new char[resultlen];
  729. if (addr.buf[0] == '\0')
  730. snprintf(result, resultlen, "%c", action);
  731. else
  732. snprintf(result, resultlen, "%c%s/%u", action, addr.buf, p.prefixlen);
  733. return result;
  734. }