1 /*
2  * Copyright (c) 1997, 1998, 1999, 2001, 2005, 2008, 2009, 2010, 2011, 2012,
3  *               2013, 2014, 2016, 2017, 2020
4  *      Inferno Nettverk A/S, Norway.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. The above copyright notice, this list of conditions and the following
10  *    disclaimer must appear in all copies of the software, derivative works
11  *    or modified versions, and any portions thereof, aswell as in all
12  *    supporting documentation.
13  * 2. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by
16  *      Inferno Nettverk A/S, Norway.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Inferno Nettverk A/S requests users of this software to return to
32  *
33  *  Software Distribution Coordinator  or  sdc@inet.no
34  *  Inferno Nettverk A/S
35  *  Oslo Research Park
36  *  Gaustadall�en 21
37  *  NO-0349 Oslo
38  *  Norway
39  *
40  * any improvements or extensions that they make and grant Inferno Nettverk A/S
41  * the rights to redistribute these changes.
42  *
43  */
44 
45 #include "common.h"
46 
47 static const char rcsid[] =
48 "$Id: socket.c,v 1.218.4.7.2.7.4.3 2020/11/11 16:11:54 karls Exp $";
49 
50 int
socks_connecthost(s,side,host,laddr,raddr,timeout,emsg,emsglen)51 socks_connecthost(s,
52 #if !SOCKS_CLIENT
53                   side,
54 #endif /* !SOCKS_CLIENT */
55                   host,
56                   laddr,
57                   raddr,
58                   timeout,
59                   emsg,
60                   emsglen)
61    int s;
62 #if !SOCKS_CLIENT
63    const interfaceside_t side;
64 #endif /* !SOCKS_CLIENT */
65    const sockshost_t *host;
66    struct sockaddr_storage *laddr;
67    struct sockaddr_storage *raddr;
68    const long timeout;
69    char *emsg;
70    const size_t emsglen;
71 {
72    const char *function = "socks_connecthost()";
73    static fd_set *wset;
74 #if SOCKS_CLIENT
75    interfaceside_t side = EXTERNALIF; /* doesn't matter. */
76 #endif
77    dnsinfo_t resmem;
78    struct sockaddr_storage laddr_mem, raddr_mem;
79    struct addrinfo hints, *res, *next;
80    socklen_t len;
81    char addrstr[MAXSOCKADDRSTRING], hoststr[MAXSOCKSHOSTSTRING],
82         laddrstr[MAXSOCKADDRSTRING];
83    int failed, rc;
84 
85    /*
86     * caller depends on errno to know whether the connect(2) failed
87     * permanently, or whether things are now in progress, so make sure
88     * errno is correct upon return, and definitely not some old residue.
89     */
90    errno = 0;
91 
92    if (wset == NULL)
93       wset = allocate_maxsize_fdset();
94 
95    if (laddr == NULL)
96       laddr = &laddr_mem;
97 
98    if (raddr == NULL)
99       raddr = &raddr_mem;
100 
101    len = sizeof(*laddr);
102    if (getsockname(s, TOSA(laddr), &len) == -1) {
103       snprintf(emsg, emsglen, "getsockname(2) failed: %s", strerror(errno));
104       return -1;
105    }
106 
107    sockaddr2string(laddr, laddrstr, sizeof(laddrstr));
108 
109    slog(LOG_NEGOTIATE,
110         "%s: connect to %s on %s side from %s, fd %d.  Timeout is %ld\n",
111         function,
112         sockshost2string(host, hoststr, sizeof(hoststr)),
113 
114 #if !SOCKS_CLIENT
115 
116         interfaceside2string(side),
117 
118 #else /* SOCKS_CLIENT */
119 
120         "<N/A>",
121 
122 #endif /* SOCKS_CLIENT */
123 
124         laddrstr,
125         s,
126         timeout);
127 
128    bzero(raddr, sizeof(*raddr));
129 
130    switch (host->atype) {
131       case SOCKS_ADDR_IPV4:
132       case SOCKS_ADDR_IPV6: {
133          int connect_errno, flags, changed_to_nonblocking;
134 
135          changed_to_nonblocking = 0;
136          flags                  = -1;
137 
138          if (timeout != -1) {
139             if ((flags = fcntl(s, F_GETFL, 0)) == -1) {
140                snprintf(emsg, emsglen, "fcntl(F_GETFL) failed: %s",
141                         strerror(errno));
142 
143                return -1;
144             }
145 
146             if (!(flags & O_NONBLOCK)) {
147                slog(LOG_DEBUG,
148                     "%s: temporarily changing fd %d to nonblocking in order "
149                     "to facilitate the specified connect timeout (%ld)",
150                     function, s, timeout);
151 
152                if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) {
153                   snprintf(emsg, emsglen,
154                            "could not change fd %d to nonblocking: %s",
155                            s, strerror(errno));
156 
157                   return -1;
158                }
159 
160                changed_to_nonblocking = 1;
161             }
162          }
163 
164          switch (host->atype) {
165             case SOCKS_ADDR_IPV4:
166                SET_SOCKADDR(raddr, AF_INET);
167                TOIN(raddr)->sin_addr = host->addr.ipv4;
168                break;
169 
170             case SOCKS_ADDR_IPV6:
171                SET_SOCKADDR(raddr, AF_INET6);
172                TOIN6(raddr)->sin6_addr     = host->addr.ipv6.ip;
173                TOIN6(raddr)->sin6_scope_id = host->addr.ipv6.scopeid;
174                break;
175 
176             default:
177                SERRX(host->atype);
178          }
179 
180          SET_SOCKADDRPORT(raddr, host->port);
181 
182          rc            = connect(s, TOSA(raddr), salen(raddr->ss_family));
183          connect_errno = errno;
184 
185          if (rc == 0 || errno == EINPROGRESS) {
186             /*
187              * if local addr was incomplete before, it should be complete now.
188              */
189             if (!IPADDRISBOUND(laddr)) {
190                len = sizeof(*laddr);
191                if (getsockname(s, TOSA(laddr), &len) == -1) {
192                   snprintf(emsg, emsglen,
193                            "getsockname(2) after connect(2) failed: %s",
194                            strerror(errno));
195 
196                   return -1;
197                }
198 
199                sockaddr2string(laddr, laddrstr, sizeof(laddrstr));
200             }
201          }
202 
203          snprintf(emsg, emsglen,
204                   "connect(2) to %s from %s on fd %d returned %ld (%s)",
205                   hoststr, laddrstr, s, (long)rc, strerror(errno));
206 
207          slog(LOG_DEBUG, "%s: %s", function, emsg);
208 
209          if (changed_to_nonblocking) {
210             SASSERTX(flags != -1);
211 
212             if (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) == -1)
213                swarn("%s: failed reverting fd %d back to blocking",
214                      function, s);
215          }
216 
217          if (rc == 0)
218             /*
219              * OpenBSD 4.5 sometimes sets errno even though the
220              * connect was successful.  Seems to be an artifact of the
221              * buggy threads library, where it does a select(2)/poll(2)
222              * after making the socket non-blocking, but forgets to
223              * reset errno.
224              */
225             connect_errno = 0;
226 
227          errno = connect_errno;
228 
229 #if SOCKS_CLIENT
230          /*
231           * if errno is EINTR, it may be due to the client having set up an
232           * alarm for this.  We can't know for sure, so better not
233           * retry in that case.
234           */
235           if (rc == -1) {
236             if (errno == EINTR) {
237                snprintf(emsg, emsglen, "connect(2) to %s from %s failed: %s",
238                         sockaddr2string(raddr, NULL, 0),
239                         laddrstr,
240                         strerror(errno));
241 
242                return rc;
243             }
244 
245             if (!changed_to_nonblocking) {
246                /*
247                 * was passed a non-blocking fd by the client, so client does
248                 * not want to wait for the connect to complete.  Let the
249                 * connect child handle this then, if applicable.
250                 */
251                snprintf(emsg, emsglen,
252                         "non-blocking connect(2): %s", strerror(errno));
253 
254                return rc;
255             }
256          }
257 #endif /* SOCKS_CLIENT */
258 
259          while (timeout != 0
260          &&     rc      == -1
261          &&   (  errno == EINPROGRESS
262 #if !SOCKS_CLIENT
263               || errno == EINTR
264 #endif /* !SOCKS_CLIENT */
265          )) {
266             struct timeval tval = { timeout, (long)0 };
267 
268             FD_ZERO(wset);
269             FD_SET(s, wset);
270 
271             rc = selectn(s + 1,
272                          NULL,
273                          NULL,
274                          NULL,
275                          wset,
276                          NULL,
277                          timeout >= 0 ? &tval : NULL);
278 
279             switch (rc) {
280                case -1:
281                   if (ERRNOISTMP(errno))
282                      continue;
283                   else {
284                      snprintf(emsg, emsglen, "select(2) on fd %d failed: %s",
285                               s, strerror(errno));
286 
287                      return -1;
288                   }
289 
290                case 0:
291                   errno = ETIMEDOUT;
292                   break;
293 
294                default:
295                   len = sizeof(errno);
296                   getsockopt(s, SOL_SOCKET, SO_ERROR, &errno, &len);
297             }
298 
299             if (errno == 0)
300                rc = 0;
301             else
302                /*
303                 * connect(2)-attempt finished, but failed.
304                 */
305                rc = -1;
306          }
307 
308          slog(LOG_NEGOTIATE, "%s: connect to %s from %s on fd %d %s (%s)",
309               function,
310               sockaddr2string(raddr, addrstr, sizeof(addrstr)),
311               laddrstr,
312               s,
313               rc == 0 ?   "ok"
314                         : errno == EINPROGRESS ? "in progress" : "failed",
315               strerror(errno));
316 
317          if (rc == -1) {
318             log_connectfailed(side, addrstr);
319 
320             snprintf(emsg, emsglen, "connect(2) to %s from %s %s: %s",
321                      sockaddr2string(raddr, NULL, 0),
322                      laddrstr,
323                      errno == EINPROGRESS ? "is in progress" : "failed",
324                      strerror(errno));
325          }
326 
327          return rc;
328       }
329 
330       case SOCKS_ADDR_DOMAIN: {
331          socklen_t len;
332          char visbuf[MAXHOSTNAMELEN * 4];
333 
334          bzero(&hints, sizeof(hints));
335 
336          /*
337           * We'd like to set ai_family to laddr->ss_family, but
338           * IPv4-mapped IPv6 addresses screw that up since if laddr
339           * is an IPv4 address (and thus 's' is an IPv4 socket),
340           * we can connect to the IPv4-mapped IPv6 address, but we need to
341           * include IPv6 in the hints.ai_family in order to get those
342           * IPv4-mapped IPv6 addresses from getaddrinfo(3).
343           * (cgetaddrinfo() converts them to regular IPv4-addresses for us,
344           * but in order for it to get them in the first place ...).
345           *
346           * A defect in the getaddrinfo() api, not having a flag for us
347           * to request it includes IPv4-mapped IPv6 addresses, converted to
348           * regular IPv4 addresses.
349           */
350          if (laddr->ss_family == AF_INET)
351             hints.ai_family = 0; /* or we will not get the IPv4-mapped IPv6. */
352          else {
353             SASSERTX(laddr->ss_family == AF_INET6);
354             hints.ai_family = laddr->ss_family;
355          }
356 
357          len = sizeof(hints.ai_socktype);
358          if (getsockopt(s, SOL_SOCKET, SO_TYPE, &hints.ai_socktype, &len) != 0){
359             snprintf(emsg, emsglen,
360                      "could not determine type of socket for fd %d "
361                      "- getsockopt(SO_TYPE) failed: %s",
362                      s, strerror(errno));
363 
364             return -1;
365          }
366 
367          if ((rc = cgetaddrinfo(host->addr.domain, NULL, &hints, &res, &resmem))
368          != 0) {
369             snprintf(emsg, emsglen,
370                      "could not resolve hostname \"%s\": %s",
371                      str2vis(host->addr.domain,
372                              strlen(host->addr.domain),
373                              visbuf,
374                              sizeof(visbuf)),
375                      gai_strerror(rc));
376 
377             errno = EHOSTUNREACH; /* anything but EINPROGRESS. */
378             return -1;
379          }
380 
381 #if DIAGNOSTIC
382          SASSERTX(hints.ai_family  == 0 || res->ai_family == hints.ai_family);
383          SASSERTX(res->ai_socktype == hints.ai_socktype);
384 #endif /* DIAGNOSTIC */
385 
386          break;
387       }
388 
389       default:
390          SERRX(host->atype);
391    }
392 
393    SASSERTX(host->atype == SOCKS_ADDR_DOMAIN);
394    SASSERTX(res->ai_addr != NULL);
395 
396    /*
397     * try all ipaddresses hostname resolved to.
398     */
399 
400    failed = 0;
401    next   = res;
402    do {
403       sockshost_t newhost;
404 
405       if (next->ai_family != laddr->ss_family) {
406          snprintf(emsg, emsglen,
407                   "can not attempt connect to address %s (resolved from %s) "
408                   "from our %s-socket on the external side",
409                   sockaddr2string(TOSS(next->ai_addr), NULL, 0),
410                   hoststr,
411                   safamily2string(laddr->ss_family));
412          errno = EAFNOSUPPORT;
413 
414          next  = next->ai_next;
415          continue;
416       }
417 
418       if (failed) { /* previously failed, need to create a new socket. */
419          int new_s;
420 
421          if ((new_s = socketoptdup(s, -1)) == -1) {
422             snprintf(emsg, emsglen, "socketoptdup() failed: %s",
423                      strerror(errno));
424 
425             return -1;
426          }
427 
428          if (dup2(new_s, s) == -1) {
429             snprintf(emsg, emsglen, "dup2() failed: %s", strerror(errno));
430             close(new_s);
431 
432             return -1;
433          }
434          close(new_s); /* s is now a new socket but keeps the same index. */
435 
436          /*
437           * try to bind the same address/port on the new socket.
438           */
439 
440          if (socks_bind(s, laddr, 1) != 0) {
441             snprintf(emsg, emsglen, "socks_bind() failed: %s", strerror(errno));
442             return -1;
443          }
444       }
445 
446       /*
447        * Convert next address to sockshost_t and call ourselves again.
448        */
449 
450       sockaddrcpy(raddr, TOSS(next->ai_addr), sizeof(*raddr));
451       SET_SOCKADDRPORT(raddr, host->port);
452 
453       sockaddr2sockshost(raddr, &newhost);
454 
455       if (next->ai_next == NULL) {
456          /*
457           * no more ip addresses to try.  That means we can simply call
458           * socks_connecthost() with the timeout as received.
459           * If not, we will need to disregard the passed in timeout and
460           * connect to one address at a time and await the result. :-/
461           *
462           * XXX improve this by keeping track of how much time we've used
463           * so far, so we can decrement the timeout on each connecthost()
464           * call?
465           */
466          rc = socks_connecthost(s,
467 #if !SOCKS_CLIENT
468                                 side,
469 #endif /* !SOCKS_CLIENT */
470                                 &newhost,
471                                 laddr,
472                                 raddr,
473                                 timeout,
474                                 emsg,
475                                 emsglen);
476       }
477       else
478          rc = socks_connecthost(s,
479 #if !SOCKS_CLIENT
480                                 side,
481 #endif /* !SOCKS_CLIENT */
482                                 &newhost,
483                                 laddr,
484                                 raddr,
485                                 sockscf.timeout.connect ?
486                                     (long)sockscf.timeout.connect : (long)-1,
487                                 emsg,
488                                 emsglen);
489 
490       if (rc == 0) {
491          errno = 0;
492 
493          if (emsg != NULL)
494             *emsg = NUL;
495 
496          return 0;
497       }
498 
499       /*
500        * Only retry/try next address if errno indicates server/network error.
501        */
502       switch (errno) {
503          case ETIMEDOUT:
504          case EINVAL:
505          case ECONNREFUSED:
506          case ENETUNREACH:
507          case EHOSTUNREACH:
508             break;
509 
510          default:
511             return -1;
512       }
513 
514       failed = 1;
515       next   = next->ai_next;
516    } while (next != NULL);
517 
518    /*
519     * list exhausted, no successful connect.
520     */
521 
522    SASSERTX(errno != 0);
523 
524    if (emsg != NULL)
525       SASSERTX(*emsg != NUL);
526 
527    return -1;
528 }
529 
530 #undef socket
531 int
socks_socket(domain,type,protocol)532 socks_socket(domain, type, protocol)
533    const int domain;
534    const int type;
535    const int protocol;
536 {
537    const char *function = "socks_socket()";
538    int s;
539 
540    if ((s = socket(domain, type, protocol)) == -1)
541       return -1;
542 
543 #if !SOCKS_CLIENT
544    if (domain == AF_INET6) {
545       socklen_t len;
546       int value;
547 
548       value = 1;
549       len   = sizeof(value);
550 
551       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &value, len) != 0)
552          swarn("%s: setsockopt(IPV6_V6ONLY) on fd %d failed", function, s);
553    }
554 #endif /* !SOCKS_CLIENT */
555 
556    return s;
557 }
558 
559 
560 int
acceptn(s,addr,addrlen)561 acceptn(s, addr, addrlen)
562    int s;
563    struct sockaddr_storage *addr;
564    socklen_t *addrlen;
565 {
566    const char *function = "acceptn()";
567    struct sockaddr_storage fulladdr;
568    socklen_t fulladdrlen = sizeof(fulladdr);
569    int rc;
570 
571 #if DEBUG /* for occasional internal debugging/analysis. */
572 
573 #ifdef SO_LISTENQLEN
574    if (sockscf.option.debug) {
575       socklen_t len;
576       int listenqlen, listeninqclen, failed;
577 
578       failed = 0;
579 
580       len = sizeof(listenqlen);
581       if (getsockopt(s, SOL_SOCKET, SO_LISTENQLEN, &listenqlen, &len) == -1) {
582          swarn("%s: getsockopt(SO_LISTENQLEN) failed", function);
583          failed = 1;
584       }
585 
586       len  = sizeof(listeninqclen);
587       if (getsockopt(s, SOL_SOCKET, SO_LISTENINCQLEN, &listeninqclen, &len)
588       == -1) {
589          swarn("%s: getsockopt(SO_LISTENINCQLEN) failed", function);
590          failed = 1;
591       }
592 
593       if (!failed)
594          slog(LOG_DEBUG, "%s: fd %d.  listenqlen: %d, listeninqclen: %d",
595               function, s, listenqlen, listeninqclen);
596    }
597 #endif /* SO_LISTENQLEN */
598 
599 #endif /* DEBUG */
600 
601    while ((rc = accept(s, TOSA(&fulladdr), &fulladdrlen)) == -1
602    &&     errno == EINTR)
603 #if !SOCKS_CLIENT
604       /*
605        * XXX only here because request children block on accept(2).
606        * Remove it if we some day improve the request children so they no
607        * longer do that.
608        */
609       (void)sockd_handledsignals();
610 #else /* SOCKS_CLIENT */
611       ;
612 #endif /* SOCKS_CLIENT */
613 
614 #if !SOCKS_CLIENT && HAVE_LINUX_BUGS
615    if (rc != -1) {
616       /*
617        * On Linux fd-flags are not inherited by accept(2) for some reason.
618        */
619       if (fcntl(rc, F_SETFL, fcntl(s, F_GETFL, 0)) != 0) {
620          swarn("%s: attempt to work around Linux bug via fcntl(2) failed",
621                function);
622 
623          close(rc);
624          return -1;
625       }
626    }
627 #endif /* !SOCKS_CLIENT && HAVE_LINUX_BUGS */
628 
629    if (rc != -1)
630       /*
631        * Avoids Valgrind complaining about us sendmsg(2)-ing uninitialized
632        * parts of the sockaddr_storage struct accept(2)-ed above.
633        */
634       sockaddrcpy(addr, &fulladdr, (size_t)*addrlen);
635 
636    *addrlen = MIN(*addrlen, (socklen_t)fulladdrlen);
637 
638    return rc;
639 }
640 
641 int
setnonblocking(fd,ctx)642 setnonblocking(fd, ctx)
643    const int fd;
644    const char *ctx;
645 {
646    const char *function = "setnonblocking()";
647    int flags;
648 
649    SASSERTX(ctx != NULL);
650 
651    if ((flags = fcntl(fd, F_GETFL, 0))                 != -1
652    &&           fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1) {
653       slog(LOG_DEBUG, "%s: fd %d: %s", function, fd, ctx);
654       return flags;
655    }
656    else {
657       swarn("failed to make fd %d, used for %s, non-blocking", fd, ctx);
658       return -1;
659    }
660 }
661 
662 int
setblocking(fd,ctx)663 setblocking(fd, ctx)
664    const int fd;
665    const char *ctx;
666 {
667    const char *function = "setblocking()";
668    int flags;
669 
670    SASSERTX(ctx != NULL);
671 
672    if ((flags = fcntl(fd, F_GETFL, 0))                  != -1
673    &&           fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) != -1) {
674       slog(LOG_DEBUG, "%s: fd %d: %s", function, fd, ctx);
675       return flags;
676    }
677    else {
678       swarn("failed to make fd %d, used for %s, blocking", fd, ctx);
679       return -1;
680    }
681 }
682 
683 int
socks_socketisforlan(s)684 socks_socketisforlan(s)
685    const int s;
686 {
687    const char *function = "socks_socketisforlan()";
688    struct in_addr addr;
689    socklen_t len;
690    unsigned char ttl;
691    const int errno_s = errno;
692 
693    /*
694     * make an educated guess as to whether the socket is intended for
695     * lan-only use or not.
696     */
697 
698    len = sizeof(addr);
699    if (getsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, &len) != 0) {
700       slog(LOG_DEBUG, "%s: getsockopt(IP_MULTICAST_IF) failed: %s",
701            function, strerror(errno));
702 
703       errno = errno_s;
704       return 0;
705    }
706 
707    if (addr.s_addr == htonl(INADDR_ANY))
708       return 0;
709 
710    len = sizeof(ttl);
711    if (getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &len) != 0) {
712       swarn("%s: getsockopt(IP_MULTICAST_TTL)", function);
713 
714       errno = errno_s;
715       return 0;
716    }
717 
718    return ttl == 1;
719 }
720 
721 struct sockaddr_storage *
socketisconnected(s,addr,addrlen)722 socketisconnected(s, addr, addrlen)
723    const int s;
724    struct sockaddr_storage *addr;
725    socklen_t addrlen;
726 {
727    const char *function = "socketisconnected()";
728    socklen_t len;
729    int err;
730 
731    if (addr == NULL || addrlen == 0) {
732       static struct sockaddr_storage addrmem;
733 
734       addr     = &addrmem;
735    }
736 
737    len = sizeof(err);
738    (void)getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len);
739 
740    if (err == 0) {
741       if (getpeername(s, TOSA(addr), &len) == -1) { /* strange. */
742          /*
743           * presumably a timing issue; connection failed between
744           * our getsockopt(2) call and now.
745           */
746          return NULL;
747       }
748    }
749    else
750       return NULL;
751 
752    return addr;
753 }
754 
755 int
socks_rebind(s,protocol,from,to,emsg,emsglen)756 socks_rebind(s, protocol, from, to, emsg, emsglen)
757    int s;
758    int protocol;
759    struct sockaddr_storage *from;
760    const struct ruleaddr_t *to;
761    char *emsg;
762    const size_t emsglen;
763 {
764    const char *function = "socks_rebind()";
765    struct sockaddr_storage tobind;
766 
767    slog(LOG_NEGOTIATE, "%s: fd %d, protocol %s, from %s, to %s",
768         function,
769         s,
770         protocol2string(protocol),
771         sockaddr2string(from, NULL, 0),
772         ruleaddr2string(to, ADDRINFO_PORT, NULL, 0));
773 
774    ruleaddr2sockaddr(to, &tobind, protocol);
775    if (!IPADDRISBOUND(&tobind)) {
776       snprintf(emsg, emsglen, "could not convert %s to an IP-address",
777                ruleaddr2string(to, 0, NULL, 0));
778       swarnx("%s: %s", function, emsg);
779 
780       errno = EADDRNOTAVAIL;
781       return -1;
782    }
783 
784    if (IPADDRISBOUND(from) || PORTISBOUND(from)) {
785 #if SOCKS_CLIENT
786 
787       rlim_t maxofiles;
788       int i;
789 
790 #endif /* SOCKS_CLIENT */
791 
792       int new_s, rc;
793 
794       /*
795        * bound locally already.  Does it by coincidence match what we
796        * want, or do we need to create a new socket and bind that instead?
797        */
798       if (addrmatch(to, sockaddr2sockshost(from, NULL), NULL, protocol, 0))
799          return 0; /* matches already. */
800 
801       /*
802        * Nope, need to create a new socket so we can bind wanted address.
803        */
804 
805       if ((new_s = socketoptdup(s, -1)) == -1) {
806          snprintf(emsg, emsglen,
807                   "could not dup(2) fd %d with socketopdup(): %s",
808                   s, strerror(errno));
809 
810          swarnx("%s: %s", function, emsg);
811          return -1;
812       }
813 
814 #if SOCKS_CLIENT
815 
816       /*
817        * The problem now is that caller may also have created dup(2)'s
818        * of this socket, so us creating a new socket and assigning it the
819        * index of the old socket won't do much good if the caller keeps using
820        * his own dup(2)-ed version of the old socket.
821        * We try to handle this by searching through the fd index space
822        * for dups of 's', and dup2(2)'ing them too.
823        */
824       maxofiles = getmaxofiles(softlimit);
825       for (i = 0; i < (int)maxofiles; ++i) {
826          if (i == s)
827             continue;
828 
829          if (fdisdup(i, s)) {
830             slog(LOG_INFO,
831                  "%s: found socket duped by client, fd %d is dup of fd %d",
832                  function, i, s);
833 
834             if (dup2(new_s, i) == -1) {
835                snprintf(emsg, emsglen,
836                         "could not dup2(2) fd %d to %d (for clients dup): %s",
837                         new_s, i, strerror(errno));
838 
839                swarnx("%s: %s", function, emsg);
840                close(new_s);
841 
842                /*
843                 * If we previously found sockets to dup2(), we are basically
844                 * SOL and things will be screwed up for the client.  Sorry. :-/
845                 */
846                return -1;
847             }
848          }
849       }
850 
851 #endif /* SOCKS_CLIENT */
852 
853       rc = dup2(new_s, s);
854       close(new_s);
855 
856       if (rc == -1) {
857          snprintf(emsg, emsglen, "could not dup2(2) fd %d to %d: %s",
858                   new_s, s, strerror(errno));
859 
860          swarnx("%s: %s", function, emsg);
861          return -1;
862       }
863 
864       /*
865        * Fist try to close the old socket and rebind the new with the same
866        * portnumber as the old used, if the old portnumber matches what
867        * caller wants.
868        */
869 
870       SET_SOCKADDRPORT(&tobind, GET_SOCKADDRPORT(from));
871       if (addrmatch(to, sockaddr2sockshost(&tobind, NULL), NULL, protocol, 0)) {
872          if (socks_bind(s, &tobind, 0) == 0)
873             return 0;
874       }
875       SET_SOCKADDRPORT(&tobind, htons(0));
876    }
877    /* else: socket is not bound, so can just bind it with the right address. */
878 
879    if (socks_bindinrange(s,
880                          &tobind,
881                          protocol == SOCKS_TCP ? to->port.tcp : to->port.udp,
882                          to->portend,
883                          to->operator) != 0) {
884       snprintf(emsg, emsglen, "could not bind(2) fd %d in range %s: %s",
885                s, ruleaddr2string(to, ADDRINFO_PORT, NULL, 0), strerror(errno));
886 
887       swarnx("%s: %s", function, emsg);
888 
889       errno = EADDRNOTAVAIL;
890       return -1;
891    }
892 
893    slog(LOG_NEGOTIATE, "%s: successfully rebound %s-fd %d.  New address is %s",
894         function,
895         protocol2string(protocol),
896         s,
897         sockaddr2string(&tobind, NULL, 0));
898 
899    return 0;
900 }
901 
902 int
socks_bindinrange(s,addr,first,last,op)903 socks_bindinrange(s, addr, first, last, op)
904    int s;
905    struct sockaddr_storage *addr;
906    in_port_t first, last;
907    const enum operator_t op;
908 {
909    const char *function = "socks_bindinrange()";
910    in_port_t port;
911    int exhausted;
912 
913    slog(LOG_DEBUG, "%s: %s %u %s %u",
914         function,
915         sockaddr2string(addr, NULL, 0),
916         ntohs(first),
917         operator2string(op),
918         ntohs(last));
919 
920 
921    /*
922     * use ports in host order to make it easier.  Only convert before bind.
923     */
924 
925    /* try this one first, if possible. */
926    port        = 0;
927    first       = ntohs(first);
928    last        = ntohs(last);
929    exhausted   = 0;
930 
931    do {
932       if (port + 1 == 0) /* wrapped. */
933          exhausted = 1;
934 
935       /* find next port to try. */
936       switch (op) {
937          case none:
938             port = 0; /* any port is good. */
939             break;
940 
941          case eq:
942             port = first;
943             break;
944 
945          case neq:
946             if (++port == first)
947                ++port;
948             break;
949 
950          case ge:
951             if (port < first)
952                port = first;
953             else
954                ++port;
955             break;
956 
957          case gt:
958             if (port <= first)
959                port = first + 1;
960             else
961                ++port;
962             break;
963 
964          case le:
965             if (++port > first)
966                exhausted = 1;
967             break;
968 
969          case lt:
970             if (++port >= first)
971                exhausted = 1;
972             break;
973 
974          case range:
975             if (port < first)
976                port = first;
977             else
978                ++port;
979 
980             if (port > last)
981                exhausted = 1;
982             break;
983 
984          default:
985             SERRX(op);
986       }
987 
988       if (exhausted) {
989          slog(LOG_NEGOTIATE,
990               "%s: exhausted search for port to bind in range %u %s %u",
991               function, first, operator2string(op), last);
992 
993          return -1;
994       }
995 
996       SET_SOCKADDRPORT(addr,  htons(port));
997       if (socks_bind(s, addr, 0) == 0)
998          return 0;
999 
1000       if (errno == EACCES) {
1001          if  (op == gt || op == ge || op == range)
1002             port = 1023; /* short-circuit to first possibility - 1. */
1003          else if (op == lt || op == le)
1004             exhausted = 1; /* going down, will get same error for all. */
1005       }
1006 
1007       if (op == eq || op == none)
1008          break; /* nothing to retry for these. */
1009    } while (!exhausted);
1010 
1011    return -1;
1012 }
1013 
1014 int
socks_bind(s,addr,retries)1015 socks_bind(s, addr, retries)
1016    int s;
1017    struct sockaddr_storage *addr;
1018    size_t retries;
1019 {
1020    const char *function = "socks_bind()";
1021    int p;
1022 
1023    slog(LOG_DEBUG, "%s: trying to bind address %s on fd %d.  Retries is %lu",
1024         function, sockaddr2string(addr, NULL, 0), s, (unsigned long)retries);
1025 
1026    errno = 0;
1027    while (1) {
1028 #if !SOCKS_CLIENT
1029       if (PORTISRESERVED(GET_SOCKADDRPORT(addr)))
1030          sockd_priv(SOCKD_PRIV_NET_ADDR, PRIV_ON);
1031 #endif /* !SOCKS_CLIENT */
1032 
1033       p = bind(s, TOSA(addr), salen(addr->ss_family));
1034 
1035 #if !SOCKS_CLIENT
1036       if (PORTISRESERVED(GET_SOCKADDRPORT(addr)))
1037          sockd_priv(SOCKD_PRIV_NET_ADDR, PRIV_OFF);
1038 #endif /* !SOCKS_CLIENT */
1039 
1040       if (p == 0) {
1041          socklen_t addrlen = sizeof(*addr);
1042          p                 = getsockname(s, TOSA(addr), &addrlen);
1043          break;
1044       }
1045 
1046       slog(LOG_DEBUG, "%s: failed to bind %s (%s)",
1047            function, sockaddr2string(addr, NULL, 0), strerror(errno));
1048 
1049       /*
1050        * else;  non-fatal error and retry?
1051        */
1052       switch (errno) {
1053          case EINTR:
1054             continue; /* don't count this attempt. */
1055 
1056          case EADDRINUSE:
1057             if (retries--) {
1058                sleep(1);
1059                continue;
1060             }
1061             break;
1062 
1063          /* default: fatal error. */
1064       }
1065 
1066       break;
1067    }
1068 
1069    if (p == 0)
1070       slog(LOG_DEBUG, "%s: bound address %s on fd %d",
1071            function, sockaddr2string(addr, NULL, 0), s);
1072 
1073    return p;
1074 }
1075 
1076 int
fdisdup(fd1,fd2)1077 fdisdup(fd1, fd2)
1078    const int fd1;
1079    const int fd2;
1080 {
1081    const char *function = "fdisdup()";
1082 #if HAVE_UNIQUE_SOCKET_INODES
1083    struct stat sb1, sb2;
1084 #endif /* HAVE_UNIQUE_SOCKET_INODES */
1085    socklen_t len1, len2;
1086    int isdup, rc1, rc2, errno1, errno2, flags1, flags2,  newflags1, newflags2,
1087        testflag = SO_REUSEADDR, setflag;
1088 
1089    slog(LOG_DEBUG, "%s: fd %d, fd %d", function, fd1, fd2);
1090 
1091    if (fd1 == fd2)
1092       return 1;
1093 
1094 #if HAVE_UNIQUE_SOCKET_INODES
1095    rc1    = fstat(fd1, &sb1);
1096    errno1 = errno;
1097 
1098    rc2    = fstat(fd2, &sb2);
1099    errno2 = errno;
1100 
1101    if (rc1 != rc2 || errno1 != errno2) {
1102       if (sockscf.option.debug >= DEBUG_VERBOSE)
1103          slog(LOG_DEBUG, "%s: failed due to fstat() on line %d",
1104                function, __LINE__);
1105 
1106       return 0;
1107    }
1108 
1109    if (rc1 == -1) {
1110       SASSERTX(rc2 == -1 && errno1 == errno2);
1111 
1112       if (sockscf.option.debug >= DEBUG_VERBOSE)
1113          slog(LOG_DEBUG, "%s: failed due to rc1 on line %d",
1114               function, __LINE__);
1115 
1116       return 1; /* assume any failed socket is as good as any other. */
1117    }
1118 
1119    if (sb1.st_ino == 0)
1120       slog(LOG_DEBUG, "%s: socket inode is 0.  Assuming kernel does "
1121                       "not support the inode field for (this) socket, so "
1122                       "continuing with other tests",
1123                       function);
1124    else if (sb1.st_dev != sb2.st_dev
1125    ||       sb1.st_ino != sb2.st_ino) {
1126       if (sockscf.option.debug >= DEBUG_VERBOSE)
1127          slog(LOG_DEBUG, "%s: failed due to inode-compare on line %d "
1128                          "(sb1.st_dev = %d, sb2.st_dev = %d, "
1129                          "sb1.st_ino = %d, sb2.st_ino = %d)",
1130                          function, __LINE__,
1131                          (int)sb1.st_dev, (int)sb2.st_dev,
1132                          (int)sb1.st_ino, (int)sb2.st_ino);
1133 
1134       return 0;
1135    }
1136 #endif /* HAVE_UNIQUE_SOCKET_INODES */
1137 
1138    len1   = sizeof(flags1);
1139    rc1    = getsockopt(fd1, SOL_SOCKET, testflag, &flags1, &len1);
1140    errno1 = errno;
1141 
1142    len2   = sizeof(flags2);
1143    rc2    = getsockopt(fd2, SOL_SOCKET, testflag, &flags2, &len2);
1144    errno2 = errno;
1145 
1146    if (rc1 != rc2 || errno1 != errno2 || flags1 != flags2) {
1147       if (sockscf.option.debug >= DEBUG_VERBOSE)
1148          slog(LOG_DEBUG, "%s: failed due to flags/errno/len-compare on line %d",
1149               function, __LINE__);
1150 
1151       return 0;
1152    }
1153 
1154    /*
1155     * Test is to set a flag on fd1, and see if the same flag then gets set on
1156     * fd2.  Note that this flag must be a flag we can set on a socket that
1157     * failed during connect(2), or where the peer has closed it's side
1158     * of the session, and which will be shared between descriptors that are
1159     * dup(2)'s of each other.
1160     *
1161     * File status flags are shared, but descriptor flags (e.g., FD_CLOEXEC),
1162     * are of course not.  Also note that not all platforms let all F_SETFL
1163     * commands change the same flags, and not all platforms let us set
1164     * the flag on a "failed" socket (a socket where the connect(2) failed).
1165     * We however assume that if the socket failed, and we are getting the
1166     * same errno from the socket we are checking against, it is either the
1167     * socket, or any failed socket is as good as any other failed socket.
1168     *
1169     * XXX this does not work on OpenBSD if one of the descriptors were passed
1170     * us by another process (e.g., passed us by the connect child).
1171     * Need to sendbug this.
1172     *    On OpenBSD 4.5, if we have a process A, and that process sends
1173     *    a file descriptor to process B, and process B then send that
1174     *    same descriptor back to process A, the file status flags, at
1175     *    least O_NONBLOCK, is not shared.
1176     *    Thus if process A sends descriptor k to process B, and
1177     *    process B later sends that same descriptor back to process A,
1178     *    the descriptor B sends to A is a dup of k, and gets allocated
1179     *    a new index, e.g. k2.  We then expect that if we change the
1180     *    O_NONBLOCK flag on k2, it will be reflected on k, but the bug
1181     *    is that it is not.
1182     *
1183     * The reason we do not do this test first is that if there are multiple
1184     * processes/threads using the same fd, we want to minimize the chance
1185     * of us changing the descriptor under their feet while they are using it.
1186     */
1187 
1188    if (rc1 == -1 && rc2 == -1) {
1189       if (sockscf.option.debug >= DEBUG_VERBOSE)
1190          slog(LOG_DEBUG,
1191               "%s: succeeded due to getsockopt(2) failing (%s) on line %d",
1192               function, strerror(errno1), __LINE__);
1193 
1194       return 1; /* assume any failed socket is as good as any other failed. */
1195    }
1196 
1197    if (rc1 == -1 && errno1 == ENOTSOCK) {
1198       SWARNX(fd1); /* should not happen as we are only interested in sockets. */
1199 
1200       if (sockscf.option.debug >= DEBUG_VERBOSE)
1201          slog(LOG_DEBUG, "%s: failed due to errno = ENOTSOCK on line %d",
1202               function, __LINE__);
1203 
1204       return 0;
1205    }
1206 
1207    slog(LOG_DEBUG, "%s: all looks equal so far, doing final test, flags = %d",
1208         function, flags1);
1209 
1210    SASSERTX(flags1 == flags2);
1211 
1212    if (flags1)
1213       /*
1214        * remove testflag from fd1 and see if it gets removed from fd2 too.
1215        */
1216       setflag = 0;
1217    else
1218       /*
1219        * add testflag to fd1 and see if it gets added to fd2 too.
1220        */
1221       setflag = 1;
1222 
1223    if (setsockopt(fd1, SOL_SOCKET, testflag, &setflag, sizeof(setflag)) != 0) {
1224       if (setsockopt(fd2, SOL_SOCKET, testflag, &setflag, sizeof(setflag)) != 0)
1225       {
1226          slog(LOG_DEBUG, "%s: succeeded due to setsockopt() failing on line %d",
1227               function, __LINE__);
1228 
1229          return 1;
1230       }
1231       else {
1232          if (setsockopt(fd2, SOL_SOCKET, testflag, &flags2, sizeof(flags2))
1233          != 0)
1234             slog(LOG_DEBUG, "%s: could not restore original flags on fd %d: %s",
1235                  function, fd2, strerror(errno));
1236 
1237          slog(LOG_DEBUG, "%s: failed due to setsockopt() failing on line %d",
1238               function, __LINE__);
1239 
1240          return 0;
1241       }
1242    }
1243 
1244    len1   = sizeof(newflags1);
1245    rc1    = getsockopt(fd1, SOL_SOCKET, testflag, &newflags1, &len1);
1246    errno1 = errno;
1247 
1248    len2   = sizeof(newflags2);
1249    rc2    = getsockopt(fd2, SOL_SOCKET, testflag, &newflags2, &len2);
1250    errno2 = errno;
1251 
1252    if (newflags1 == newflags2) {
1253       slog(LOG_DEBUG, "%s: newflags1 = newflags2 -> %d is a dup of %d",
1254            function, fd1, fd2);
1255 
1256       isdup = 1;
1257    }
1258    else if (rc1 == -1 && rc2 == rc1
1259    &&       errno1 == errno2) {
1260       slog(LOG_DEBUG, "%s: flagcheck failed, but rc (%d) and errno (%d) is "
1261                       "the same, so assuming %d is a dup of %d, or that "
1262                       "any failed socket is as good as any other failed "
1263                       "socket.  Not many other choices",
1264                       function, rc1, errno1, fd1, fd2);
1265       isdup = 1;
1266    }
1267    else
1268       isdup = 0;
1269 
1270    /* restore flags back to original. */
1271    SASSERTX(flags1 == flags2);
1272    (void)setsockopt(fd1, SOL_SOCKET, testflag, &flags1, sizeof(flags1));
1273    (void)setsockopt(fd2, SOL_SOCKET, testflag, &flags2, sizeof(flags2));
1274 
1275    slog(LOG_DEBUG, "%s: final test indicates fd %d %s of fd %d",
1276         function, fd1, isdup ? "is a dup" : "is not a dup", fd2);
1277 
1278    return isdup;
1279 }
1280 
1281 int
makedummyfd(_safamily,_socktype)1282 makedummyfd(_safamily, _socktype)
1283    const sa_family_t _safamily;
1284    const int _socktype;
1285 {
1286    const char *function = "makedummyfd()";
1287    struct sockaddr_storage addr;
1288    sa_family_t safamily;
1289    int socktype, s;
1290 
1291    if (_safamily == 0)
1292       safamily = AF_INET;
1293    else
1294       safamily = _safamily;
1295 
1296    if (_socktype == 0)
1297       socktype = SOCK_DGRAM;
1298    else
1299       socktype = _socktype;
1300 
1301    if ((s = socket(safamily, socktype, 0)) == -1) {
1302       swarn("%s: failed to create dummysocket of type %s, socktype %s",
1303             function, safamily2string(safamily), socktype2string(socktype));
1304 
1305       return -1;
1306    }
1307 
1308    if (socktype == SOCK_DGRAM)
1309       return s;
1310 
1311    /*
1312     * Else, need to do some more complex work, creating a genuine socket
1313     * that will not be marked ad readable or writable by select(2).
1314     */
1315 
1316    /*
1317     * The below bind(2) and listen(2) is necessary for Linux not to mark
1318     * the socket as readable/writable.  Under other UNIX systems, just a
1319     * socket(2) is enough.  Judging from the Open Unix spec., Linux is the
1320     * one that is correct though.
1321     */
1322 
1323    bzero(&addr, sizeof(addr));
1324    SET_SOCKADDR(&addr, safamily);
1325 
1326    if (safamily == AF_INET)
1327       TOIN(&addr)->sin_addr.s_addr = htonl(INADDR_ANY);
1328    else {
1329       SASSERTX(safamily == AF_INET6);
1330       memcpy(&TOIN6(&addr)->sin6_addr, &in6addr_any, sizeof(in6addr_any));
1331    }
1332 
1333    SET_SOCKADDRPORT(&addr, htons(0));
1334 
1335    if (socks_bind(s, TOSS(&addr), 0) != 0) {
1336       swarn("%s: could not bind address (%s)",
1337             function, sockaddr2string(&addr, NULL, 0));
1338 
1339       return s;
1340    }
1341 
1342    if (listen(s, 1) != 0) {
1343       swarn("%s: could not listen(2) on socket", function);
1344       return s;
1345    }
1346 
1347    return s;
1348 
1349 }
1350 
1351 #if SOCKS_CLIENT
1352 
1353 int
fd_is_network_socket(fd)1354 fd_is_network_socket(fd)
1355    const int fd;
1356 {
1357    struct stat statbuf;
1358    struct sockaddr_storage addr;
1359    socklen_t addrlen = sizeof(addr);
1360 
1361    if (fstat(fd, &statbuf) != 0)
1362       return 0;
1363 
1364    if (S_ISSOCK(statbuf.st_mode) == 0)
1365       return 0;
1366 
1367 
1368 #if SOCKSLIBRARY_DYNAMIC
1369    /*
1370     * This function is used to decide whether to track a fd or not,
1371     * so be sure to not call ourselves again when figuring out
1372     * whether sys_getsockname() should track the fd or not.
1373     */
1374 
1375    if (sys_getsockname_notracking(fd, TOSA(&addr), &addrlen) != 0)
1376       return 0;
1377 
1378 #else /* !SOCKSLIBRARY_DYNAMIC */
1379 
1380    if (getsockname(fd, TOSA(&addr), &addrlen) != 0)
1381       return 0;
1382 
1383 #endif /* !SOCKSLIBRARY_DYNAMIC */
1384 
1385    switch (addr.ss_family) {
1386       case AF_INET:
1387       case AF_INET6:
1388          return 1;
1389 
1390       default:
1391          return 0;
1392    }
1393 }
1394 
1395 #endif /* SOCKS_CLIENT */
1396