1 /*
2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2008, 2009, 2010, 2011, 2012,
3  *               2013, 2014, 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 #include "interposition.h"
48 
49 #include "upnp.h"
50 
51 #ifndef __USE_GNU
52 #define __USE_GNU /* XXX for RTLD_NEXT on Linux */
53 #endif /* !__USE_GNU */
54 #include <dlfcn.h>
55 
56 static const char rcsid[] =
57 "$Id: address.c,v 1.288.4.4.6.4 2020/11/11 17:02:23 karls Exp $";
58 
59 /*
60  * During init, we need to let all system calls resolve to the native
61  * version.  I.e., socks_shouldcallasnative() need to always return
62  * true as long as we are initing. Use this object for holding that
63  * knowledge.
64  */
65 #ifdef HAVE_VOLATILE_SIG_ATOMIC_T
66 sig_atomic_t doing_addrinit;
67 #else
68 volatile sig_atomic_t doing_addrinit;
69 #endif /* HAVE_VOLATILE_SIG_ATOMIC_T */
70 
71 
72 /*
73  * "fake" ip addresses for clients that want/need to use that.
74  * Note that this is process-specific, so it will not work with
75  * programs that fork of "dns-helper".  Shared memory might have worked,
76  * but even that would have depended on us being able to set up the
77  * shared memory early enough, so just say we don't support that.
78  */
79 static char **ipv;
80 static in_addr_t ipc;
81 
82 #define FDV_INITSIZE    64 /* on init allocate memory for first 64 fd indexes */
83 static socksfd_t socksfdinit;
84 static int *dv;
85 static size_t dc;
86 static socksfd_t *socksfdv;
87 static size_t socksfdc;
88 
89 #if HAVE_PTHREAD_H
90 
91 static int socks_pthread_mutex_init(pthread_mutex_t *mutex,
92                                     const pthread_mutexattr_t *attr);
93 static int socks_pthread_mutexattr_init(pthread_mutexattr_t *attr);
94 static int socks_pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
95 static int socks_pthread_mutex_lock(pthread_mutex_t *mutex);
96 static int socks_pthread_mutex_unlock(pthread_mutex_t *mutex);
97 
98 typedef int (*PT_INIT_FUNC_T)(pthread_mutex_t *mutex,
99                                      const pthread_mutexattr_t *attr);
100 static PT_INIT_FUNC_T pt_init;
101 
102 typedef int (*PT_ATTRINIT_FUNC_T)(pthread_mutexattr_t *attr);
103 static PT_ATTRINIT_FUNC_T pt_attrinit;
104 
105 typedef int (*PT_SETTYPE_FUNC_T)(pthread_mutexattr_t *attr, int type);
106 static PT_SETTYPE_FUNC_T pt_settype;
107 
108 typedef int (*PT_LOCK_FUNC_T)(pthread_mutex_t *mutex);
109 static PT_LOCK_FUNC_T pt_lock;
110 
111 typedef int (*PT_UNLOCK_FUNC_T)(pthread_mutex_t *mutex);
112 static PT_LOCK_FUNC_T pt_unlock;
113 
114 typedef pthread_t (*PT_SELF_FUNC_T)(void);
115 static PT_SELF_FUNC_T pt_self;
116 
117 static pthread_mutex_t addrmutex;
118 #endif /* HAVE_PTHREAD_H */
119 
120 int
121 socks_isaddr(const int fd, const int takelock);
122 /*
123  * If "takelock" is true, it means the function should take the
124  * socksfdv/addrlock.
125  *
126  * Returns true if there is a address registered for the socket "fd", false
127  * otherwise.
128  */
129 
130 
131 static int
132 socks_addfd(const int d);
133 /*
134  * adds the file descriptor "fd" to an internal table.
135  * If it is already in the table the  request is ignored.
136  * Returns:
137  *    On success: 0
138  *    On failure: -1
139  */
140 
141 static int
142 socks_isfd(const int fd);
143 /*
144  * returns 1 if "fd" is a file descriptor in our internal table, 0 if not.
145  */
146 
147 static void
148 socks_rmfd(const int fd);
149 /*
150  * removes the file descriptor "fd" from our internal table.
151  */
152 
153 socksfd_t *
socks_addaddr(clientfd,socksfd,takelock)154 socks_addaddr(clientfd, socksfd, takelock)
155    const int clientfd;
156    const socksfd_t *socksfd;
157    const int takelock;
158 {
159    const char *function = "socks_addaddr()";
160    addrlockopaque_t lock;
161 
162    clientinit();
163 
164    SASSERTX(clientfd >= 0);
165    SASSERTX(!(socksfd->state.protocol.tcp && socksfd->state.protocol.udp));
166 
167 #if 0 /* DEBUG */
168    if (socksfd->state.command != -1 && !socksfd->state.system)
169       slog(LOG_DEBUG, "%s: %d", function, clientfd);
170 #endif
171 
172    SASSERTX(socksfd->state.command == -1
173    ||       socksfd->state.command == SOCKS_BIND
174    ||       socksfd->state.command == SOCKS_CONNECT
175    ||       socksfd->state.command == SOCKS_UDPASSOCIATE);
176 
177    if (takelock)
178       socks_addrlock(F_WRLCK, &lock);
179 
180    if (socks_addfd(clientfd) != 0)
181       serrx("%s: error adding descriptor %d", function, clientfd);
182 
183    if (socksfdc < dc) { /* init/reallocate */
184 #if HAVE_GSSAPI
185       size_t i;
186 #endif /* HAVE_GSSAPI */
187 
188       slog(LOG_DEBUG,
189            "%s: realloc(3)-ing socksfdv array.  Increasing length from "
190            "%d to %d",
191            function, (int)socksfdc, (int)dc);
192 
193       if (socksfdinit.control == 0) { /* not initialized */
194          socksfdinit.control = -1;
195          /* other members have ok default value. */
196       }
197 
198       if ((socksfdv = realloc(socksfdv, sizeof(*socksfdv) * dc)) == NULL)
199          serr("%s: could not allocate %lu bytes",
200               function, (unsigned long)(sizeof(*socksfdv) * dc));
201 
202 #if HAVE_GSSAPI
203       /* update internal pointers in previously existing objects. */
204       for (i = 0; i < socksfdc; ++i) {
205          socksfd_t *sfd = &socksfdv[i];
206 
207          if (!socks_isaddr(i, 0))
208             continue;
209 
210          sfd->state.gssapistate.value = sfd->state.gssapistatemem;
211       }
212 #endif /* HAVE_GSSAPI */
213 
214       /* init new unallocated objects */
215       while (socksfdc < dc)
216          socksfdv[socksfdc++] = socksfdinit;
217    }
218 
219    /*
220     * On one machine gcc 4.1.2 expands the below to a memcpy() call with
221     * overlapping destinations, according to valgrind:
222     *    socksfdv[clientfd]           = *socksfd;
223     *
224     * Presumably a gcc bug, but what can we do ... :-/
225     */
226    memmove(&socksfdv[clientfd], socksfd, sizeof(*socksfd));
227 
228 #if HAVE_GSSAPI
229 
230    socksfdv[clientfd].state.gssapistate.value
231    = socksfdv[clientfd].state.gssapistatemem;
232 
233 #endif
234 
235    socksfdv[clientfd].allocated = 1;
236 
237    if (takelock)
238       socks_addrunlock(&lock);
239 
240 #ifdef THREAD_DEBUG
241    if (sockscf.log.fpv != NULL) {
242       char buf[80];
243 
244       snprintf(buf, sizeof(buf), "%s: allocating fd %d for command %d\n",
245                function, clientfd, socksfdv[clientfd].state.command);
246 
247       syssys_write(fileno(sockscf.log.fpv[0]), buf, strlen(buf) + 1);
248    }
249 #endif /* THREAD_DEBUG */
250 
251    if (socksfd->state.auth.method == AUTHMETHOD_GSSAPI)
252       sockscf.state.havegssapisockets = 1;
253 
254    return &socksfdv[clientfd];
255 }
256 
257 socksfd_t *
socks_getaddr(d,socksfd,takelock)258 socks_getaddr(d, socksfd, takelock)
259    const int d;
260    socksfd_t *socksfd;
261    const int takelock;
262 {
263 #if HAVE_GSSAPI
264    const char *function = "socks_getaddr()";
265 #endif /* HAVE_GSSAPI */
266    socksfd_t *sfd;
267    addrlockopaque_t lock;
268 
269    if (socksfd == NULL) {
270       static socksfd_t ifnullsocksfd;
271 
272       socksfd = &ifnullsocksfd;
273    }
274 
275    if (takelock)
276       socks_addrlock(F_RDLCK, &lock);
277 
278    if (socks_isaddr(d, 0)) {
279       sfd = &socksfdv[d];
280 
281 #if HAVE_GSSAPI
282       if (sfd->state.gssimportneeded) {
283          if (sockscf.state.insignal) {
284             char buf[32];
285             const char *msgv[] =
286             { function,
287               ": ",
288               "not importing gssapistate for fd ",
289               ltoa((long)d, buf, sizeof(buf)),
290               NULL
291             };
292 
293             signalslog(LOG_DEBUG, msgv);
294          }
295          else {
296             slog(LOG_DEBUG, "%s: importing gssapistate for fd %d", function, d);
297 
298             if (gssapi_import_state(&sfd->state.auth.mdata.gssapi.state.id,
299                                     &sfd->state.gssapistate) != 0) {
300                swarnx("%s: failed to import gssapi context of length %lu for  "
301                       "fd %d",
302                       function,
303                       (unsigned long)sfd->state.gssapistate.length, d);
304 
305                socks_rmaddr(d, 0);
306                sfd = NULL;
307             }
308             else {
309                sfd->state.gssimportneeded = 0;
310                slog(LOG_DEBUG,
311                     "%s: imported gssapistate for fd %d using ctxid %ld",
312                     function, d, (long)sfd->state.auth.mdata.gssapi.state.id);
313             }
314          }
315       }
316 #endif /* HAVE_GSSAPI */
317    }
318    else
319       sfd = NULL;
320 
321    if (takelock)
322       socks_addrunlock(&lock);
323 
324    if (sfd == NULL)
325       return NULL;
326 
327    *socksfd = *sfd;
328    return socksfd;
329 }
330 
331 void
socks_rmaddr(d,takelock)332 socks_rmaddr(d, takelock)
333    const int d;
334    const int takelock;
335 {
336    const char *function = "socks_rmaddr()";
337    addrlockopaque_t lock;
338 
339    if (d < 0 || (size_t)d >= socksfdc)
340       return; /* not a socket of ours. */
341 
342    if (takelock)
343       socks_addrlock(F_WRLCK, &lock);
344 
345    socks_rmfd(d);
346 
347    if (!socksfdv[d].state.issyscall) /* syscall adds/removes all the time. */
348       socks_freebuffer(d);
349 
350    switch (socksfdv[d].state.version) {
351       case PROXY_SOCKS_V4:
352       case PROXY_SOCKS_V5:
353          if (socksfdv[d].state.issyscall)
354             break;
355 
356 #if HAVE_GSSAPI
357 
358          if (socksfdv[d].state.auth.method == AUTHMETHOD_GSSAPI
359          &&  socksfdv[d].state.auth.mdata.gssapi.state.id != GSS_C_NO_CONTEXT) {
360             OM_uint32 major_status, minor_status;
361             char buf[512];
362 
363             major_status = gss_delete_sec_context(&minor_status,
364                                   &socksfdv[d].state.auth.mdata.gssapi.state.id,
365                                                   GSS_C_NO_BUFFER);
366 
367             if (major_status != GSS_S_COMPLETE) {
368                if (!gss_err_isset(major_status, minor_status, buf, sizeof(buf)))
369                   *buf = NUL;
370 
371                swarnx("%s: gss_delete_sec_context() for fd %d failed%s%s",
372                       function,
373                       d,
374                       *buf == NUL ? "" : ": ",
375                       *buf == NUL ? "" : buf);
376             }
377             else {
378                slog(LOG_DEBUG, "%s: deleted GSSAPI context for fd %d",
379                     function, d);
380 
381                SASSERTX(socksfdv[d].state.auth.mdata.gssapi.state.id
382                == GSS_C_NO_CONTEXT);
383             }
384          }
385 #endif /* HAVE_GSSAPI */
386 
387          switch (socksfdv[d].state.command) {
388             case SOCKS_BIND:
389                if (socksfdv[d].control == -1
390                ||  socksfdv[d].control == d)
391                   break;
392 
393                /*
394                 * If we are using the bind extension it's possible
395                 * that this control connection is shared with other
396                 * (accept()'ed) addresses, if so we must leave it
397                 * open for the other connections.
398                */
399                if (socks_addrcontrol(-1, d, 0) != -1)
400                   break;
401 
402                close(socksfdv[d].control);
403                break;
404 
405             case SOCKS_CONNECT:
406                break; /* no separate control connection. */
407 
408             case SOCKS_UDPASSOCIATE:
409                if (socksfdv[d].control != -1)
410                   close(socksfdv[d].control);
411                break;
412 
413             default:
414                SERRX(socksfdv[d].state.command);
415          }
416          break;
417 
418       case PROXY_UPNP:
419          if (socksfdv[d].state.issyscall)
420             break;
421 
422          upnpcleanup(d);
423          break;
424    }
425 
426 #ifdef THREAD_DEBUG
427    if (sockscf.log.fpv != NULL) {
428       char buf[80];
429 
430       snprintf(buf, sizeof(buf),
431                "%s: deallocating fd %d, was allocated for command %d\n",
432                function, d, socksfdv[d].state.command);
433 
434       syssys_write(fileno(sockscf.log.fpv[0]), buf, strlen(buf) + 1);
435    }
436 #endif /* THREAD_DEBUG */
437 
438    socksfdv[d] = socksfdinit;
439 
440 #if DIAGNOSTIC
441    SASSERTX(socks_isaddr(d, 0) == 0);
442    SASSERTX(socks_getaddr(d, NULL, 0) == NULL);
443 #endif /* DIAGNOSTIC */
444 
445    if (takelock)
446       socks_addrunlock(&lock);
447 }
448 
449 int
socks_isaddr(d,takelock)450 socks_isaddr(d, takelock)
451    const int d;
452    const int takelock;
453 {
454 
455    if (d < 0 || (size_t)d >= socksfdc)
456       return 0;
457 
458    return socksfdv[d].allocated;
459 }
460 
461 int
socks_addrisours(s,socksfdmatch,takelock)462 socks_addrisours(s, socksfdmatch, takelock)
463    const int s;
464    socksfd_t *socksfdmatch;
465    const int takelock;
466 {
467    const char *function = "socks_addrisours()";
468    const char *breakreason = NULL;
469    const int errno_s = errno;
470    addrlockopaque_t lock;
471    struct sockaddr_storage local, remote;
472    socklen_t locallen, remotelen;
473    int matched, type;
474 
475    slog(LOG_DEBUG, "%s: fd %d", function, s);
476 
477    if (takelock)
478       socks_addrlock(F_RDLCK, &lock);
479 
480    locallen = sizeof(local);
481    if (getsockname(s, TOSA(&local), &locallen) != 0) {
482       slog(LOG_DEBUG,
483            "%s: no match due to fd %d not having a local addr (errno = %d, %s)",
484            function, s, errno, strerror(errno));
485 
486       if (takelock)
487          socks_addrunlock(&lock);
488 
489       errno = errno_s;
490       return 0;
491    }
492    else
493       slog(LOG_DEBUG, "%s: local address of fd %d is %s",
494            function, s, sockaddr2string(&local, NULL, 0));
495 
496    /* only network-sockets can be proxied. */
497    if (local.ss_family != AF_INET
498 #ifdef AF_INET6
499    &&  local.ss_family != AF_INET6
500 #endif /* AF_INET6 */
501    ) {
502       slog(LOG_DEBUG,
503            "%s: no match due to fd %d not being an AF_INET/AF_INET6 socket",
504            function, s);
505 
506       if (takelock)
507          socks_addrunlock(&lock);
508 
509       errno = errno_s;
510       return 0;
511    }
512 
513    locallen = sizeof(type);
514    if (getsockopt(s, SOL_SOCKET, SO_TYPE, &type, &locallen) != 0) {
515       slog(LOG_DEBUG,
516            "%s: no match due to getsockopt(SO_TYPE) failing on fd %d "
517            "(errno = %d, %s)",
518            function, s, errno, strerror(errno));
519 
520       if (takelock)
521          socks_addrunlock(&lock);
522 
523       errno = errno_s;
524       return 0;
525    }
526 
527    if (type != SOCK_DGRAM && type != SOCK_STREAM) {
528       slog(LOG_DEBUG,
529            "%s: no match due to fd %d being neither SOCK_DGRAM nor SOCK_STREAM",
530            function, s);
531 
532       if (takelock)
533          socks_addrunlock(&lock);
534 
535       errno = errno_s;
536       return 0;
537    }
538 
539    errno   = 0;
540    matched = 0;
541 
542    do {
543       socksfd_t socksfd;
544 
545       if (socks_getaddr(s, &socksfd, 0) != NULL) {
546          if ((socksfd.state.protocol.udp && type != SOCK_DGRAM)
547          ||  (socksfd.state.protocol.tcp && type != SOCK_STREAM)) {
548             breakreason = "protocol mismatch between registered and current";
549             break;
550          }
551 
552          if (TOCIN(&socksfd.local)->sin_addr.s_addr == htonl(0)) {
553             /*
554              * if address was not bound before, it might have become
555              * later, after client did a send(2) or similar.
556              * It's also possible accept(2) was called, so check
557              * for that first.
558              */
559             socksfd_t nsocksfd, *socksfdptr;
560             int duped;
561 
562             remotelen = sizeof(remote);
563             if (getpeername(s, TOSA(&remote), &remotelen) == 0
564             && (duped = socks_addrmatch(&local, &remote, NULL, 0)) != -1) {
565                if ((socksfdptr = socks_addrdup(socks_getaddr(duped, NULL, 0),
566                                                &nsocksfd)) == NULL) {
567                   swarn("%s: socks_addrdup()", function);
568 
569                   if (errno == EBADF)
570                      socks_rmaddr(duped, 0);
571 
572                   breakreason = "known fd, but unbound; socks_addrdup() failed";
573                   break;
574                }
575 
576                socksfd = *socksfdptr;
577                socks_addaddr(s, &nsocksfd, 0);
578                matched = 1;
579 
580                if (!fdisopen(duped))
581                   socks_rmaddr(duped, 0);
582             }
583             else {
584                nsocksfd = socksfd;
585                TOIN(&nsocksfd.local)->sin_addr = TOIN(&local)->sin_addr;
586                socksfd = *socks_addaddr(s, &nsocksfd, 0);
587             }
588          }
589 
590          if (!sockaddrareeq(&local, &socksfd.local, 0)) {
591             breakreason = "local neq socksfd.local";
592             break;
593          }
594 
595          /* check remote endpoint too? */
596          matched = 1;
597       }
598       else { /* unknown descriptor.  Try to check whether it's a dup. */
599          int duped;
600 
601          if (!PORTISBOUND(&local)) {
602             breakreason = "unknown fd and no local IP-address bound for it";
603             break;
604          }
605 
606          /* XXX check remote endpoint also. */
607          if ((duped = socks_addrmatch(&local, NULL, NULL, 0)) != -1
608          && ((socksfdv[duped].state.protocol.udp && type == SOCK_DGRAM)
609           || (socksfdv[duped].state.protocol.tcp && type == SOCK_STREAM))) {
610             socksfd_t nsocksfd;
611 
612             slog(LOG_DEBUG, "%s: fd %d appears to be a dup of fd %d (%s)",
613                  function,
614                  s,
615                  duped,
616                  socket2string(duped, NULL, 0));
617 
618             if (socks_addrdup(socks_getaddr(duped, NULL, 0), &nsocksfd)
619             == NULL) {
620                swarn("%s: socks_addrdup()", function);
621 
622                if (errno == EBADF)
623                   socks_rmaddr(duped, 0);
624 
625                breakreason = "unknown fd and socks_addrdup() failed";
626                break;
627             }
628 
629             socks_addaddr(s, &nsocksfd, 0);
630 
631             if (!fdisopen(duped))
632                socks_rmaddr(duped, 0);
633 
634             matched = 1;
635          }
636 
637          breakreason = "unknown fd and no socks_addrmatch()";
638          break;
639       }
640    } while (/* CONSTCOND */ 0);
641 
642    if (matched) {
643       socksfd_t socksfd;
644 
645       socks_getaddr(s, &socksfd, 0);
646       SASSERTX(!(socksfd.state.protocol.tcp && socksfd.state.protocol.udp));
647 
648       if ((socksfd.state.protocol.udp && type != SOCK_DGRAM)
649       ||  (socksfd.state.protocol.tcp && type != SOCK_STREAM)) {
650          breakreason = "protocol mismatch between registered and current";
651          matched = 0;
652       }
653       else {
654          if (socksfdmatch != NULL)
655             *socksfdmatch = socksfd;
656       }
657    }
658 
659    if (takelock)
660       socks_addrunlock(&lock);
661 
662    if (!matched && breakreason != NULL)
663       slog(LOG_DEBUG, "%s: no match due to %s", function, breakreason);
664 
665    errno = errno_s;
666    return matched;
667 }
668 
669 int
socks_addrcontrol(controlsent,controlinuse,takelock)670 socks_addrcontrol(controlsent, controlinuse, takelock)
671    const int controlsent;
672    const int controlinuse;
673    const int takelock;
674 {
675    const char *function = "socks_addrcontrol()";
676    addrlockopaque_t lock;
677    char fdsentstr[1024], fdinusestr[sizeof(fdsentstr)];
678    int i;
679 
680    slog(LOG_DEBUG, "%s: sent fd %d (%s), in use fd %d (%s)",
681         function,
682         controlsent,
683         controlsent == -1 ?
684             "<none>" : socket2string(controlsent, fdsentstr, sizeof(fdsentstr)),
685         controlinuse,
686         socket2string(controlinuse, fdinusestr, sizeof(fdinusestr)));
687 
688    SASSERTX(controlinuse >= 0);
689 
690    if (takelock)
691       socks_addrlock(F_RDLCK, &lock);
692 
693    if (socks_isaddr(controlsent, 0)) {
694       /*
695        * First check the index corresponding to what the descriptor should
696        * be, if nothing tricky (dup(2) or similar) happened between the time
697        * we sent the descriptor to the connect-process, and now.
698        * If it doesn't match, we will have to go through all of the indexes.
699        */
700       if (fdisdup(controlsent, socksfdv[controlsent].control)) {
701          if (takelock)
702             socks_addrunlock(&lock);
703 
704          return controlsent;
705       }
706    }
707 
708    for (i = 0; i < (int)socksfdc; ++i) {
709       if (!socks_isaddr(i, 0))
710          continue;
711 
712       if (socksfdv[i].state.command == -1)
713          continue;
714 
715       if (fdisdup(controlinuse, socksfdv[i].control))
716          break;
717    }
718 
719    if (takelock)
720       socks_addrunlock(&lock);
721 
722    if (i < (int)socksfdc)
723       return i;
724 
725    return -1;
726 }
727 
728 int
socks_addrmatch(local,remote,state,takelock)729 socks_addrmatch(local, remote, state, takelock)
730    const struct sockaddr_storage *local;
731    const struct sockaddr_storage *remote;
732    const socksstate_t *state;
733    const int takelock;
734 {
735    const char *function = "socks_addrmatch()";
736    addrlockopaque_t lock;
737    char lstr[MAXSOCKADDRSTRING], rstr[MAXSOCKADDRSTRING];
738    int i;
739 
740    slog(LOG_DEBUG, "%s: local = %s, remote = %s",
741         function,
742         local  == NULL ?
743            "NULL" : sockaddr2string(local, lstr, sizeof(lstr)),
744         remote == NULL ?
745            "NULL" : sockaddr2string(remote, rstr, sizeof(rstr)));
746 
747    if (takelock)
748       socks_addrlock(F_RDLCK, &lock);
749 
750    for (i = 0; i < (int)socksfdc; ++i) {
751       if (!socks_isaddr(i, 0))
752          continue;
753 
754       /*
755        * only compare fields that have a valid value in request to compare
756        * against.
757        */
758 
759       if (local != NULL) {
760          if (sockaddrareeq(local, &socksfdv[i].local, 0))
761             slog(LOG_DEBUG, "%s: local address %s matches %s for socksfdv[%d]",
762                  function,
763                  sockaddr2string(local, lstr, sizeof(lstr)),
764                  sockaddr2string(&socksfdv[i].local, NULL, 0),
765                  i);
766          else
767             continue;
768       }
769 
770       if (remote != NULL) {
771          if (sockaddrareeq(remote, &socksfdv[i].remote, 0))
772             slog(LOG_DEBUG, "%s: remote address %s matches %s for socksfdv[%d]",
773                  function,
774                  sockaddr2string(remote, rstr, sizeof(rstr)),
775                  sockaddr2string(&socksfdv[i].remote, NULL, 0),
776                  i);
777          else
778             continue;
779       }
780 
781       if (state != NULL) {
782          if (state->version != -1)
783             if (state->version != socksfdv[i].state.version)
784                continue;
785 
786          if (state->command != -1)
787             if (state->command != socksfdv[i].state.command)
788                continue;
789 
790          if (state->inprogress != -1)
791             if (state->inprogress != socksfdv[i].state.inprogress)
792                continue;
793 
794          if (state->acceptpending != -1)
795             if (state->acceptpending != socksfdv[i].state.acceptpending)
796                continue;
797       }
798 
799       break;
800    }
801 
802    if (takelock)
803       socks_addrunlock(&lock);
804 
805    if (i < (int)socksfdc)
806       return i;
807 
808    return -1;
809 }
810 
811 socksfd_t *
socks_addrdup(old,new)812 socks_addrdup(old, new)
813    const socksfd_t *old;
814    socksfd_t *new;
815 {
816 /*   const char *function = "socks_addrdup()"; */
817 
818    *new = *old;   /* init most stuff. */
819 
820    switch (old->state.command) {
821       case SOCKS_BIND:
822       case SOCKS_UDPASSOCIATE:
823          if ((new->control = socketoptdup(old->control, -1)) == -1)
824             return NULL;
825          break;
826 
827       case SOCKS_CONNECT:
828          /* only descriptor for connect is the one client has. */
829          break;
830 
831       default:
832          break;
833    }
834 
835    return new;
836 }
837 
838 void
socks_addrlock(locktype,lock)839 socks_addrlock(locktype, lock)
840    const int locktype;
841    addrlockopaque_t *lock;
842 {
843 
844    socks_sigblock(-1, (sigset_t *)lock);
845 
846 #if HAVE_PTHREAD_H
847    /*
848     * With the OpenBSD thread implementation, if a thread is interrupted,
849     * calling pthread_mutex_lock() seems to clear the interrupt flag, so
850     * that e.g. select(2) will restart rather than returning EINTR.
851     * We don't wont that to happen since we depend on select(2)/etc.
852     * being interrupted by the process used to handle non-blocking connects.
853     * We instead take the risk of not taking the thread-lock in this case.
854     */
855    if (!sockscf.state.insignal)
856       /* XXX set based on locktype. */
857       socks_pthread_mutex_lock(&addrmutex);
858 #endif /* HAVE_PTHREAD_H */
859 }
860 
861 void
socks_addrunlock(lock)862 socks_addrunlock(lock)
863    const addrlockopaque_t *lock;
864 {
865 
866 #if HAVE_PTHREAD_H
867    if (!sockscf.state.insignal)
868       socks_pthread_mutex_unlock(&addrmutex);
869 #endif /* HAVE_PTHREAD_H */
870 
871    socks_sigunblock((const sigset_t *)lock);
872 }
873 
874 in_addr_t
socks_addfakeip(host)875 socks_addfakeip(host)
876    const char *host;
877 {
878    const char *function = "socks_addfakeip()";
879    addrlockopaque_t lock;
880    struct in_addr addr;
881    char **tmpmem;
882    int ipc_added;
883 
884    socks_addrlock(F_WRLCK, &lock);
885 
886    if (socks_getfakeip(host, &addr)) {
887       socks_addrunlock(&lock);
888       return addr.s_addr;
889    }
890 
891 #if FAKEIP_END < FAKEIP_START
892 error "\"FAKEIP_END\" cannot be smaller than \"FAKEIP_START\""
893 #endif
894 
895    if (ipc >= FAKEIP_END - FAKEIP_START) {
896       swarnx("%s: fakeip range (%d - %d) exhausted",
897       function, FAKEIP_START, FAKEIP_END);
898 
899       socks_addrunlock(&lock);
900       return INADDR_NONE;
901    }
902 
903    if ((tmpmem      = realloc(ipv, sizeof(*ipv) * (ipc + 1)))        == NULL
904    ||  (tmpmem[ipc] = malloc(sizeof(**tmpmem) * (strlen(host) + 1))) == NULL) {
905       swarn("%s: could not allocate %lu bytes",
906            function,
907            (unsigned long)((sizeof(*ipv) * (ipc + 1))
908                          + (sizeof(**tmpmem) * (strlen(host) + 1))));
909 
910       if (tmpmem != NULL)
911          free(tmpmem);
912 
913       socks_addrunlock(&lock);
914       return INADDR_NONE;
915    }
916    ipv = tmpmem;
917 
918    ipc_added = ipc;
919    strcpy(ipv[ipc++], host);
920 
921    socks_addrunlock(&lock);
922 
923    return htonl(ipc_added + FAKEIP_START);
924 }
925 
926 const char *
socks_getfakehost(addr)927 socks_getfakehost(addr)
928    in_addr_t addr;
929 {
930    const char *function = "socks_getfakehost()";
931    addrlockopaque_t lock;
932    const char *host;
933 
934    if (ntohl(addr) - FAKEIP_START < ipc) {
935       socks_addrlock(F_RDLCK, &lock);
936       host = ipv[ntohl(addr) - FAKEIP_START];
937       socks_addrunlock(&lock);
938    }
939    else {
940       if (ntohl(addr) >= FAKEIP_START &&  ntohl(addr) <= FAKEIP_END)
941          swarnx("%s: looks like ip address %s might be a \"fake\" ip address, "
942                 "but we have no knowledge of that address in this process.  "
943                 "Possibly this client is forking a \"dns-helper\"-style "
944                 "program for resolving hostnames.  We unfortunately do not "
945                 "support using fake ip addresses in that case.",
946                 function, inet_ntoa(*(struct in_addr *)&addr));
947 
948       host = NULL;
949    }
950 
951    return host;
952 }
953 
954 int
socks_getfakeip(host,addr)955 socks_getfakeip(host, addr)
956    const char *host;
957    struct in_addr *addr;
958 {
959    addrlockopaque_t lock;
960    unsigned int i;
961 
962    socks_addrlock(F_RDLCK, &lock);
963 
964    for (i = 0; i < ipc; ++i)
965       if (strcasecmp(host, ipv[i]) == 0) {
966          addr->s_addr = htonl(i + FAKEIP_START);
967          break;
968       }
969 
970    socks_addrunlock(&lock);
971 
972    if (i < ipc)
973       return 1;
974 
975    return 0;
976 }
977 
978 sockshost_t *
fakesockaddr2sockshost(_addr,host)979 fakesockaddr2sockshost(_addr, host)
980    const struct sockaddr_storage *_addr;
981    sockshost_t *host;
982 {
983    const char *function = "fakesockaddr2sockshost()";
984    struct sockaddr_storage addr;
985    char string[MAXSOCKADDRSTRING];
986 
987    clientinit(); /* may be called before normal init, log to right place. */
988 
989    sockaddrcpy(&addr, _addr, salen(_addr->ss_family));
990 
991    slog(LOG_DEBUG, "%s: %s -> %s",
992         function,
993         sockaddr2string(&addr, string, sizeof(string)),
994         socks_getfakehost(TOIN(&addr)->sin_addr.s_addr) == NULL ?
995             string : socks_getfakehost(TOIN(&addr)->sin_addr.s_addr));
996 
997    if (socks_getfakehost(TOIN(&addr)->sin_addr.s_addr) != NULL) {
998       const char *ipname = socks_getfakehost(TOIN(&addr)->sin_addr.s_addr);
999 
1000       SASSERTX(ipname != NULL);
1001 
1002       host->atype = SOCKS_ADDR_DOMAIN;
1003 
1004       STRCPY_ASSERTLEN(host->addr.domain, ipname);
1005 
1006       host->port = TOIN(&addr)->sin_port;
1007    }
1008    else
1009       sockaddr2sockshost(&addr, host);
1010 
1011    return host;
1012 }
1013 
1014 struct sockaddr_storage *
int_fakesockshost2sockaddr(host,_addr,_addrlen)1015 int_fakesockshost2sockaddr(host, _addr, _addrlen)
1016    const sockshost_t *host;
1017    struct sockaddr_storage *_addr;
1018    size_t _addrlen;
1019 {
1020    const char *function = "int_fakesockshost2sockaddr()";
1021    struct sockaddr_storage addr;
1022    char string[MAXSOCKSHOSTSTRING];
1023 
1024    clientinit(); /* may be called before normal init, log to right place. */
1025 
1026    slog(LOG_DEBUG, "%s: %s",
1027         function, sockshost2string(host, string, sizeof(string)));
1028 
1029    bzero(&addr, sizeof(addr));
1030 
1031    switch (host->atype) {
1032       case SOCKS_ADDR_DOMAIN:
1033          SET_SOCKADDR(&addr, AF_INET);
1034          if (socks_getfakeip(host->addr.domain, &(TOIN(&addr)->sin_addr)))
1035             break;
1036          /* else; */ /* FALLTHROUGH */
1037 
1038       default:
1039          sockshost2sockaddr(host, &addr);
1040    }
1041 
1042    TOIN(&addr)->sin_port = host->port;
1043 
1044    bzero(_addr, _addrlen);
1045    sockaddrcpy(_addr, &addr, MIN(salen(addr.ss_family), _addrlen));
1046 
1047    return _addr;
1048 }
1049 
1050 static int
socks_addfd(d)1051 socks_addfd(d)
1052    const int d;
1053 {
1054    const char *function = "socks_addfd()";
1055 
1056    clientinit();
1057 
1058    SASSERTX(d >= 0);
1059 
1060    if ((unsigned int)d >= dc) { /* init/reallocate */
1061       size_t newfdc;
1062       int *newfdv;
1063 
1064       newfdc = (d + 1) * 2; /* add some extra at the same time. */
1065 
1066       slog(LOG_DEBUG,
1067            "%s: realloc(3)-ing dv array for fd %d.  Increasing length "
1068            "from %d to %d",
1069            function, d, (int)dc, (int)newfdc);
1070 
1071       if ((newfdv = realloc(dv, sizeof(*dv) * newfdc)) == NULL)
1072          serr("%s: could not allocate %lu bytes",
1073               function, (unsigned long)(sizeof(*dv) * newfdc));
1074 
1075       dv = newfdv;
1076 
1077       /* init all to -1, a illegal value for a descriptor. */
1078       while (dc < newfdc)
1079          dv[dc++] = -1;
1080    }
1081 
1082    dv[d] = d;
1083 
1084    return 0;
1085 }
1086 
1087 static int
socks_isfd(d)1088 socks_isfd(d)
1089    const int d;
1090 {
1091    if (d < 0 || (unsigned int)d >= dc || dv[d] == -1)
1092       return 0;
1093    return 1;
1094 }
1095 
1096 static void
socks_rmfd(d)1097 socks_rmfd(d)
1098    const int d;
1099 {
1100    if (socks_isfd(d))
1101       dv[d] = -1;
1102 }
1103 
1104 
1105 void
socks_addrinit(void)1106 socks_addrinit(void)
1107 {
1108    const char *function = "socks_addrinit()";
1109 #if HAVE_PTHREAD_H
1110    pthread_mutexattr_t attr;
1111    void *lpt;
1112 #endif /* HAVE_PTHREAD_H */
1113 
1114 #ifdef HAVE_VOLATILE_SIG_ATOMIC_T
1115    static sig_atomic_t inited;
1116 #else
1117    static volatile sig_atomic_t inited;
1118 #endif /* HAVE_VOLATILE_SIG_ATOMIC_T */
1119 
1120    if (inited)
1121       return;
1122 
1123    if (doing_addrinit)
1124       /*
1125        * XXX should really be sched_yield() or similar if initing, unless
1126        * the thread initing is ours.  If the thread initing is ours,
1127        * we can just return, to handle recursive problems during init.
1128        */
1129       return;
1130 
1131    doing_addrinit = 1; /*
1132                         * XXX should be pthread_self() or similar, but how can
1133                         * we call that before we have finished initing? :-/
1134                         */
1135 
1136    SASSERTX(socksfdv == NULL && dv == NULL);
1137 
1138    if ((socksfdv = malloc(sizeof(*socksfdv) * FDV_INITSIZE)) == NULL)
1139       serr("%s: failed to alloc %lu bytes for socksify socksfd memory",
1140            function, (unsigned long)(sizeof(*socksfdv) * 64));
1141 
1142    if ((dv = malloc(sizeof(*dv) * FDV_INITSIZE)) == NULL)
1143       serr("%s: failed to alloc %lu bytes for socksify dv memory",
1144            function, (unsigned long)(sizeof(*dv) * 64));
1145 
1146    /* init new objects */
1147    while (socksfdc < FDV_INITSIZE)
1148       socksfdv[socksfdc++] = socksfdinit;
1149 
1150    /* init all to -1, a illegal value for a descriptor. */
1151    while (dc < FDV_INITSIZE)
1152       dv[dc++] = -1;
1153 
1154 
1155 #if HAVE_PTHREAD_H
1156    if (socks_getenv(ENV_SOCKS_DISABLE_THREADLOCK, istrue) != NULL)
1157       slog(LOG_DEBUG, "pthread locking off, manually disabled in environment");
1158    else {
1159 #if HAVE_RTLD_NEXT
1160       /*
1161        * XXX following test will always perceive the application as being
1162        * threaded if lib(d)socks depends on libpthread, which might be the
1163        * case if e.g., some gssapi libs require this library.
1164        */
1165       if (dlsym(RTLD_NEXT, SYMBOL_PT_ATTRINIT) != NULL) {
1166          /*
1167           * appears to be a threaded application, obtain function pointers.
1168           */
1169 
1170          lpt = RTLD_NEXT;
1171          slog(LOG_DEBUG,
1172               "%s: pthread locking desired: threaded program (rtld)", function);
1173       }
1174       else {
1175          slog(LOG_DEBUG,
1176               "%s: pthread locking off: non-threaded program (rtld)", function);
1177 
1178          lpt = NULL;
1179       }
1180 
1181 #else
1182       /* load libpthread */
1183       if ((lpt = dlopen(LIBRARY_PTHREAD, RTLD_LAZY)) == NULL) {
1184          swarn("%s: compile time configuration error?  Failed to open "
1185                "\"%s\": %s",
1186                function, LIBRARY_PTHREAD, dlerror());
1187       }
1188 #endif /* !HAVE_RTLD_NEXT */
1189 
1190       if (lpt != NULL) {
1191          /*
1192           * resolve pthread symbols.
1193           */
1194 
1195          if ((pt_init = (PT_INIT_FUNC_T)dlsym(lpt, SYMBOL_PT_INIT)) == NULL)
1196             swarn("%s: compile time configuration error?  "
1197                   "Failed to find \"%s\" in \"%s\": %s",
1198                   function, SYMBOL_PT_INIT, LIBRARY_PTHREAD, dlerror());
1199 
1200          if ((pt_attrinit = (PT_ATTRINIT_FUNC_T)dlsym(lpt, SYMBOL_PT_ATTRINIT))
1201          == NULL)
1202             swarn("%s: compile time configuration error?  "
1203                   "Failed to find \"%s\" in \"%s\": %s",
1204                   function, SYMBOL_PT_ATTRINIT, LIBRARY_PTHREAD, dlerror());
1205 
1206          if ((pt_settype = (PT_SETTYPE_FUNC_T)dlsym(lpt, SYMBOL_PT_SETTYPE))
1207          == NULL)
1208             swarn("%s: compile time configuration error?  "
1209                   "Failed to find \"%s\" in \"%s\": %s",
1210                   function, SYMBOL_PT_SETTYPE, LIBRARY_PTHREAD, dlerror());
1211 
1212          if ((pt_lock = (PT_LOCK_FUNC_T)dlsym(lpt, SYMBOL_PT_LOCK)) == NULL)
1213             swarn("%s: compile time configuration error?  "
1214                   "Failed to find \"%s\" in \"%s\": %s",
1215                   function, SYMBOL_PT_LOCK, LIBRARY_PTHREAD, dlerror());
1216 
1217          if ((pt_unlock = (PT_UNLOCK_FUNC_T)dlsym(lpt, SYMBOL_PT_UNLOCK))
1218          == NULL)
1219             swarn("%s: compile time configuration error?  "
1220                   "Failed to find \"%s\" in \"%s\": %s",
1221                   function, SYMBOL_PT_UNLOCK, LIBRARY_PTHREAD, dlerror());
1222 
1223          if ((pt_self = (PT_SELF_FUNC_T)dlsym(lpt, SYMBOL_PT_SELF)) == NULL)
1224             swarn("%s: compile time configuration error?  "
1225                   "Failed to find \"%s\" in \"%s\": %s",
1226                   function, SYMBOL_PT_SELF, LIBRARY_PTHREAD, dlerror());
1227       }
1228 
1229       if (pt_init == NULL || pt_attrinit == NULL || pt_settype == NULL
1230       ||  pt_lock == NULL || pt_unlock   == NULL || pt_self    == NULL) {
1231          pt_init     = NULL;
1232          pt_attrinit = NULL;
1233          pt_settype  = NULL;
1234          pt_lock     = NULL;
1235          pt_unlock   = NULL;
1236          pt_self     = NULL;
1237       }
1238 
1239       if (pt_init == NULL) {
1240          slog(LOG_INFO, "%s: pthread locking disabled", function);
1241          sockscf.state.threadlockenabled = 0;
1242       }
1243       else {
1244          slog(LOG_INFO, "%s: pthread locking enabled", function);
1245          sockscf.state.threadlockenabled = 1;
1246 
1247          if (socks_pthread_mutexattr_init(&attr) != 0)
1248             serr("%s: mutexattr_init() failed", function);
1249 
1250          if (socks_pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)
1251          != 0)
1252             swarn("%s: mutex_settype(PTHREAD_MUTEX_ERRORCHECK) failed",
1253                   function);
1254 
1255          if (socks_pthread_mutex_init(&addrmutex, &attr) != 0) {
1256             swarn("%s: mutex_init() failed", function);
1257 
1258             if (socks_pthread_mutex_init(&addrmutex, NULL) != 0)
1259                serr("%s: mutex_init() failed", function);
1260          }
1261       }
1262 #endif /* HAVE_PTHREAD_H */
1263    }
1264 
1265    inited         = 1;
1266    doing_addrinit = 0;
1267 }
1268 
1269 socks_id_t *
socks_whoami(id)1270 socks_whoami(id)
1271    socks_id_t *id;
1272 {
1273 
1274 #if HAVE_PTHREAD_H
1275    if (pt_self != NULL) {
1276       id->whichid   = thread;
1277       id->id.thread = pt_self();
1278 
1279       return id;
1280    }
1281 #endif /* HAVE_PTHREAD_H */
1282 
1283    id->whichid = pid;
1284    id->id.pid = getpid();
1285 
1286    return id;
1287 }
1288 
1289 #if HAVE_PTHREAD_H
1290 /* pthread lock wrapper functions */
1291 static int
socks_pthread_mutex_init(mutex,attr)1292 socks_pthread_mutex_init(mutex, attr)
1293    pthread_mutex_t *mutex;
1294    const pthread_mutexattr_t *attr;
1295 {
1296    if (pt_init != NULL)
1297       return pt_init(mutex, attr);
1298    else
1299       return 0;
1300 }
1301 
1302 static int
socks_pthread_mutexattr_init(attr)1303 socks_pthread_mutexattr_init(attr)
1304    pthread_mutexattr_t *attr;
1305 {
1306    if (pt_attrinit != NULL)
1307       return pt_attrinit(attr);
1308    else
1309       return 0;
1310 }
1311 
1312 static int
socks_pthread_mutexattr_settype(attr,type)1313 socks_pthread_mutexattr_settype(attr, type)
1314    pthread_mutexattr_t *attr;
1315    int type;
1316 {
1317    if (pt_settype != NULL)
1318       return pt_settype(attr, type);
1319    else
1320       return 0;
1321 }
1322 
1323 static int
socks_pthread_mutex_lock(mutex)1324 socks_pthread_mutex_lock(mutex)
1325    pthread_mutex_t *mutex;
1326 {
1327    if (pt_lock != NULL)
1328       return pt_lock(mutex);
1329    else
1330       return 0;
1331 }
1332 
1333 static int
socks_pthread_mutex_unlock(mutex)1334 socks_pthread_mutex_unlock(mutex)
1335    pthread_mutex_t *mutex;
1336 {
1337    if (pt_unlock != NULL)
1338       return pt_unlock(mutex);
1339    else
1340       return 0;
1341 }
1342 #endif /* HAVE_PTHREAD_H */
1343