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