1 /*
2 * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2008,
3 * 2009, 2010, 2011, 2012, 2013, 2014, 2016, 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 #include "monitor.h"
47 #include "config_parse.h"
48
49 static const char rcsid[] =
50 "$Id: sockd_negotiate.c,v 1.477.4.5.2.2.4.2 2020/11/11 16:12:02 karls Exp $";
51
52 static sockd_negotiate_t negv[SOCKD_NEGOTIATEMAX];
53 static const size_t negc = ELEMENTS(negv);
54
55 static void siginfo(int sig, siginfo_t *si, void *sc);
56
57 static void
58 logdisconnect(const int s, sockd_negotiate_t *neg, const operation_t op,
59 const iologaddr_t *src, const iologaddr_t *dst,
60 const char *buf, const size_t buflen);
61 /*
62 * Logs the disconnect of the client connected to "s", using "neg".
63 * - "op" indicates the reason for the disconnect.
64 * - "src" and "dst" give information about the source and destination of
65 * the client.
66 * - "buf" and "buflen" an optional string giving more info about
67 * the disconnect.
68 */
69
70 static int
71 send_negotiate(sockd_negotiate_t *neg);
72 /*
73 * Sends "neg" to "mother".
74 * Returns:
75 * On success: 0
76 * On error: -1. If error was in relation to sending to mother,
77 * errno will be set.
78 */
79
80 static int
81 recv_negotiate(void);
82 /*
83 * Tries to receive a client from mother.
84 * Returns: the number of new clients received on success, or -1 on error.
85 *
86 * Note that a return of 0 does not indicate an error, but does mean
87 * no new clients were added, most likely because none of the clients
88 * received passed the ACL-checks.
89 */
90
91 static void
92 delete_negotiate(sockd_negotiate_t *neg, const int forwardedtomother);
93 /*
94 * Frees any state occupied by "neg", including closing any descriptors.
95 * If "forwardedtomother" is set, we are deleting the negotiate after
96 * forwarding the client object to mother (and thus need not ack mother).
97 */
98
99 static int
100 neg_fillset(fd_set *set, const int skipcompleted, const int skipinprogress);
101 /*
102 * Sets all client descriptors in our list in the set "set".
103 *
104 * If "skipcompleted" is set, skip those descriptors that belong to
105 * clients that have completed negotiation.
106 *
107 * If "skipinprogress" is set, skip those descriptors that belong to
108 * clients that have not yet completed negotiation.
109 *
110 * Returns the highest descriptor in our list, or -1 if we don't
111 * have any descriptors open currently.
112 */
113
114 static void
115 neg_clearset(sockd_negotiate_t *neg, fd_set *set);
116 /*
117 * Clears all file descriptors in "neg" from "set".
118 */
119
120 static sockd_negotiate_t *
121 neg_getset(fd_set *set);
122 /*
123 * Goes through our list until it finds a negotiate object where at least
124 * one of the descriptors is set, or where the negotiation has completed,
125 * which always implies the descriptor is "set".
126 *
127 * Returns:
128 * On success: pointer to the found object.
129 * On failure: NULL.
130 */
131
132 static size_t
133 neg_completed(const size_t howmany);
134 /*
135 * Returns the number of objects completed and ready to be sent currently.
136 * The function stops counting when a count of "howmany" is reached.
137 */
138
139 static size_t
140 neg_allocated(void);
141 /*
142 * Returns the number of objects currently allocated for use.
143 */
144
145 static void
146 proctitleupdate(void);
147 /*
148 * Updates the title of this process.
149 */
150
151 static struct timeval *
152 neg_gettimeout(struct timeval *timeout);
153 /*
154 * Fills in "timeout" with time til the first clients connection
155 * expires.
156 * Returns:
157 * If there is a timeout: pointer to filled in "timeout".
158 * If there is no timeout: NULL.
159 */
160
161 #if HAVE_NEGOTIATE_PHASE
162 static sockd_negotiate_t *
163 neg_gettimedout(const struct timeval *tnow);
164 /*
165 * Scans all clients for one that has timed out according to sockscf settings.
166 * "tnow" is the current time.
167 *
168 * Returns:
169 * If a timed out client found: pointer to it.
170 * Else: NULL.
171 */
172 #endif /* HAVE_NEGOTIATE_PHASE */
173
174 static void
175 neg_clearset(sockd_negotiate_t *neg, fd_set *set);
176 /*
177 * Clears all file descriptors in "neg" from "set".
178 */
179
180 static sockd_negotiate_t *
181 neg_getset(fd_set *set);
182 /*
183 * Goes through our list until it finds a negotiate object where at least
184 * one of the descriptors is set, or where the negotiation has completed,
185 * which always implies the descriptor is "set".
186 *
187 * Returns:
188 * On success: pointer to the found object.
189 * On failure: NULL.
190 */
191
192 static size_t
193 neg_completed(const size_t howmany);
194 /*
195 * Returns the number of objects completed and ready to be sent currently.
196 * The function stops counting when a count of "howmany" is reached.
197 */
198
199 static size_t
200 neg_allocated(void);
201 /*
202 * Returns the number of objects currently allocated for use.
203 */
204
205 static void
206 proctitleupdate(void);
207 /*
208 * Updates the title of this process.
209 */
210
211 static struct timeval *
212 neg_gettimeout(struct timeval *timeout);
213 /*
214 * Fills in "timeout" with time til the first clients connection expires.
215 * Returns:
216 * If there is a timeout: pointer to filled in "timeout".
217 * If there is no timeout: NULL.
218 */
219
220
221 void
run_negotiate()222 run_negotiate()
223 {
224 const char *function = "run_negotiate()";
225 struct sigaction sigact;
226 fd_set *rset, *rsetbuf, *tmpset, *wsetmem;
227 int sendfailed;
228
229 bzero(&sigact, sizeof(sigact));
230 sigact.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_SIGINFO;
231 sigact.sa_sigaction = siginfo;
232
233 #if HAVE_SIGNAL_SIGINFO
234 if (sigaction(SIGINFO, &sigact, NULL) != 0)
235 serr("%s: sigaction(SIGINFO)", function);
236 #endif /* HAVE_SIGNAL_SIGINFO */
237
238 /* same handler, for systems without SIGINFO. */
239 if (sigaction(SIGUSR1, &sigact, NULL) != 0)
240 serr("%s: sigaction(SIGINFO)", function);
241
242 rset = allocate_maxsize_fdset();
243 rsetbuf = allocate_maxsize_fdset();
244 tmpset = allocate_maxsize_fdset();
245 wsetmem = allocate_maxsize_fdset();
246
247 proctitleupdate();
248
249 sockd_print_child_ready_message((size_t)freedescriptors(NULL, NULL));
250
251 sendfailed = 0;
252 while (1 /* CONSTCOND */) {
253 negotiate_result_t negstatus;
254 struct timeval *timeout, timeoutmem;
255 sockd_negotiate_t *neg;
256 struct timeval tnow;
257 fd_set *wset;
258 int fdbits;
259
260 errno = 0; /* reset for each iteration. */
261
262
263 #if HAVE_NEGOTIATE_PHASE
264 gettimeofday_monotonic(&tnow);
265 while ((neg = neg_gettimedout(&tnow)) != NULL) {
266 const time_t duration
267 = socks_difftime(tnow.tv_sec, neg->state.time.accepted.tv_sec);
268
269 iologaddr_t src;
270 size_t buflen;
271 char buf[512];
272
273 init_iologaddr(&src,
274 object_sockshost,
275 &neg->negstate.dst,
276 object_sockshost,
277 &neg->negstate.src,
278 &neg->cauth,
279 GET_HOSTIDV(&neg->state),
280 GET_HOSTIDC(&neg->state));
281
282 if (neg->negstate.complete) {
283 struct sockaddr_storage p;
284
285 log_clientdropped(sockshost2sockaddr(&neg->negstate.src, &p));
286 }
287 /*
288 * else; nothing special. Negotiation simply did not complete in time.
289 */
290
291 buflen = snprintf(buf, sizeof(buf),
292 "%s after %ld second%s%s",
293 timeouttype2string(TIMEOUT_NEGOTIATE),
294 (long)duration,
295 duration == 1 ? "" : "s",
296 neg->negstate.complete ?
297 " while waiting for mother to become available" : "");
298
299
300 logdisconnect(neg->s, neg, OPERATION_ERROR, &src, NULL, buf, buflen);
301 delete_negotiate(neg, 0);
302 }
303
304 fdbits = neg_fillset(rset,
305 sendfailed, /*
306 * If we've previously failed sending
307 * the completed clients back to mother,
308 * don't bother select(2)ing on them
309 * for readability now; can't send them
310 * until we know mother is writable.
311 */
312 0); /*
313 * clients where negotiation is not
314 * yet completed we want to continue
315 * negotiating with.
316 */
317 #else /* !HAVE_NEGOTIATE_PHASE */
318
319 /*
320 * don't bother checking here. All, if any, should be completed.
321 * Meaning, neg_completed(1) will be true and no timeout will be set
322 * on select(2), unless sending to mother failed.
323 */
324 fdbits = -1;
325 FD_ZERO(rset);
326
327 #endif /* HAVE_NEGOTIATE_PHASE */
328
329 FD_COPY(rsetbuf, rset);
330
331 if (neg_completed(1) && !sendfailed) {
332 timeout = &timeoutmem;
333 timerclear(timeout);
334 }
335 else
336 timeout = neg_gettimeout(&timeoutmem);
337
338 FD_SET(sockscf.state.mother.s, rset);
339 fdbits = MAX(fdbits, sockscf.state.mother.s);
340
341 if (sendfailed) {
342 /*
343 * Previously failed sending a request to mother.
344 * Pull in select this time to check; normally we don't
345 * bother and just assume mother will be able to accept it.
346 */
347 FD_ZERO(wsetmem);
348 FD_SET(sockscf.state.mother.s, wsetmem);
349 wset = wsetmem;
350
351 fdbits = MAX(fdbits, sockscf.state.mother.s);
352 sendfailed = 0;
353 }
354 else
355 wset = NULL;
356
357 /* also check ack-pipe so we know if mother goes away. */
358 FD_SET(sockscf.state.mother.ack, rset);
359 fdbits = MAX(fdbits, sockscf.state.mother.ack);
360
361 SASSERTX(fdbits >= 0);
362
363 ++fdbits;
364 switch (selectn(fdbits, rset, rsetbuf, NULL, wset, NULL, timeout)) {
365 case -1:
366 SASSERT(ERRNOISTMP(errno));
367 continue;
368
369 case 0:
370 if (neg_completed(1)) /* XXX why? */
371 break;
372 else
373 continue;
374 }
375
376 #if !HAVE_NEGOTIATE_PHASE
377 /*
378 * since we have no negotiate phase, any fd's should be "readable", or
379 * in practice, "completed", so just add them to what is reported
380 * as readable by selectn() (could only be mother).
381 */
382 fdbits = MAX(fdbits, neg_fillset(tmpset, 0, 1));
383
384 fdsetop(fdbits, '|', rset, tmpset, rset);
385 #else /* HAVE_NEGOTIATE_PHASE */
386
387 fdsetop(fdbits, '|', rset, rsetbuf, rset);
388
389 /*
390 * Those descriptors that have completed negotiation we want to
391 * consider readable/ready, so we know to call recv_clientrequest()
392 * on them.
393 */
394 fdbits = MAX(fdbits, neg_fillset(tmpset, 0, 1));
395 fdsetop(fdbits, '|', rset, tmpset, rset);
396 #endif /* HAVE_NEGOTIATE_PHASE */
397
398 if (FD_ISSET(sockscf.state.mother.ack, rset)) {
399 sockd_readmotherscontrolsocket(function, sockscf.state.mother.ack);
400
401 #if HAVE_VALGRIND_VALGRIND_H
402 if (RUNNING_ON_VALGRIND) {
403 /* for some reason Valgrind complains the rset pointer is lost. */
404 free(rset);
405 }
406 #endif /* HAVE_VALGRIND_VALGRIND_H */
407
408 sockdexit(EXIT_SUCCESS);
409 }
410
411 if (FD_ISSET(sockscf.state.mother.s, rset)) {
412 if (recv_negotiate() == -1)
413 continue; /* loop around and check control-connection. */
414 else
415 proctitleupdate();
416
417 FD_CLR(sockscf.state.mother.s, rset);
418 }
419
420 while ((neg = neg_getset(rset)) != NULL) {
421 int io_errno;
422
423 neg_clearset(neg, rset);
424
425 errno = 0; /* reset before each client. */
426 negstatus = recv_clientrequest(neg->s, &neg->req, &neg->negstate);
427 io_errno = errno;
428
429 slog(LOG_DEBUG,
430 "%s: recv_clientrequest() from client %s returned %d, "
431 "errno is %d (%s)",
432 function,
433 sockshost2string(&neg->negstate.src, NULL, 0),
434 negstatus,
435 errno,
436 errno == 0 ?
437 "no error" : ERRNOISTMP(errno) ?
438 "temp error" : "fatal error");
439
440 switch (negstatus) {
441 case NEGOTIATE_CONTINUE:
442 break;
443
444 case NEGOTIATE_FINISHED: {
445 if (!timerisset(&neg->state.time.negotiateend))
446 gettimeofday_monotonic(&neg->state.time.negotiateend);
447
448 neg->state.command = neg->req.command;
449 neg->state.protocol = neg->req.protocol;
450 neg->state.proxyprotocol = neg->req.version;
451
452 #if COVENANT
453 if (neg->negstate.havedonerulespermit)
454 slog(LOG_DEBUG,
455 "%s: must have failed to send client %s to mother "
456 "before trying again",
457 function,
458 sockshost2string(&neg->negstate.src, NULL, 0));
459 else {
460 /*
461 * Need to do rulespermit() of second-level acl in this
462 * process as well, as if it fails due to missing proxy
463 * authentication we need to inform the client and restart
464 * negotiation (i.e., wait for the client to repeat the
465 * request, but this time with proxy authentication).
466 */
467 struct sockaddr_storage src, dst;
468 int permit;
469
470 sockshost2sockaddr(&neg->negstate.src, &src);
471 sockshost2sockaddr(&neg->negstate.dst, &dst);
472
473 slog(LOG_DEBUG, "%s: second-level acl check on %s -> %s",
474 function,
475 sockaddr2string(&src, NULL, 0),
476 sockshost2string(&neg->req.host, NULL, 0));
477
478 permit = rulespermit(neg->s,
479 &src,
480 &dst,
481 &neg->cauth,
482 &neg->sauth,
483 &neg->srule,
484 &neg->state,
485 &neg->negstate.src,
486 &neg->req.host,
487 NULL,
488 neg->negstate.emsg,
489 sizeof(neg->negstate.emsg));
490
491 if (permit)
492 neg->negstate.havedonerulespermit = 1;
493 else {
494 iologaddr_t src;
495 response_t response;
496
497 if (neg->srule.whyblock.missingproxyauth) {
498 if (!neg->negstate.haverequestedproxyauth) {
499 slog(LOG_DEBUG,
500 "%s: telling client at %s to provide proxy "
501 "authentication before restarting negotiation",
502 function,
503 sockshost2string(&neg->negstate.src, NULL, 0));
504
505 bzero(&response, sizeof(response));
506 response.version = neg->state.proxyprotocol;
507 response.host = neg->req.host;
508 response.reply.http
509 = response.version == PROXY_HTTP_10 ?
510 HTTP_NOTALLOWED : HTTP_PROXYAUTHREQUIRED;
511
512 send_response(neg->s, &response);
513
514 neg->negstate.complete = 0;
515 neg->negstate.haverequestedproxyauth = 1;
516 bzero(neg->negstate.mem, sizeof(neg->negstate.mem));
517
518 continue;
519 }
520
521 slog(LOG_DEBUG,
522 "%s: already told client at %s to provide "
523 "proxy authentication, but again it sent "
524 "us a request without authentication",
525 function,
526 sockshost2string(&neg->negstate.src, NULL, 0));
527 }
528
529 /*
530 * only log on deny. Pass will be logged as usual later.
531 */
532
533 init_iologaddr(&src,
534 object_sockshost,
535 &neg->negstate.dst,
536 object_sockshost,
537 &neg->negstate.src,
538 &neg->cauth,
539 GET_HOSTIDV(&neg->state),
540 GET_HOSTIDC(&neg->state));
541
542 if (neg->srule.log.tcpinfo) {
543 int fdv[] = { neg->s };
544
545 neg->state.tcpinfo
546 = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
547 }
548
549 iolog(&neg->srule,
550 &neg->state,
551 OPERATION_CONNECT,
552 &src,
553 NULL,
554 NULL,
555 NULL,
556 neg->negstate.emsg,
557 strlen(neg->negstate.emsg));
558
559 iolog(&neg->crule,
560 &neg->state,
561 OPERATION_CONNECT,
562 &src,
563 NULL,
564 NULL,
565 NULL,
566 neg->negstate.emsg,
567 strlen(neg->negstate.emsg));
568
569 neg->state.tcpinfo = NULL;
570
571 bzero(&response, sizeof(response));
572 response.version = neg->state.proxyprotocol;
573 response.host = neg->req.host;
574 response.reply.http = HTTP_FORBIDDEN;
575
576 send_response(neg->s, &response);
577 delete_negotiate(neg, 0);
578
579 continue;
580 }
581 }
582 #endif /* COVENANT */
583
584 if (wset != NULL && !FD_ISSET(sockscf.state.mother.s, wset)) {
585 sendfailed = 1;
586 continue; /* don't bother trying to send to mother now. */
587 }
588
589 errno = 0;
590 if (send_negotiate(neg) == 0) {
591 delete_negotiate(neg, 1);
592 sendfailed = 0;
593 }
594 else if (ERRNOISTMP(errno))
595 sendfailed = 1; /* we will retry sending this object later. */
596 else {
597 struct sockaddr_storage p;
598
599 log_clientdropped(sockshost2sockaddr(&neg->negstate.src, &p));
600
601 delete_negotiate(neg, 0);
602
603 /*
604 * assume what failed was not related to the send to mother,
605 * but some (network) error related to the connection between
606 * us and the client. If the error is between us and mother,
607 * it will be picked up on the control-pipe.
608 */
609 sendfailed = 0;
610 }
611
612 break;
613 }
614
615 case NEGOTIATE_ERROR:
616 case NEGOTIATE_EOF: {
617 const char *error;
618 const time_t duration = socks_difftime(time_monotonic(NULL),
619 neg->state.time.accepted.tv_sec);
620 iologaddr_t src;
621 char reason[256];
622 int takingtoolong = 0, erroriseof = 0;
623
624 if (negstatus == NEGOTIATE_EOF) {
625 error = "eof from local client";
626 erroriseof = 1;
627 }
628 else {
629 if (*neg->negstate.emsg == NUL) {
630 if (io_errno == 0)
631 error = "local client protocol error";
632 else
633 error = strerror(io_errno);
634 }
635 else
636 error = neg->negstate.emsg;
637 }
638
639 if (CRULE_OR_HRULE(neg)->mstats_shmid != 0
640 && (CRULE_OR_HRULE(neg)->alarmsconfigured & ALARM_DISCONNECT)) {
641 clientinfo_t cinfo;
642 int weclosed;
643
644 if (negstatus == NEGOTIATE_EOF || ERRNOISNETWORK(errno))
645 weclosed = 0;
646 else
647 weclosed = 1;
648
649 sockshost2sockaddr(&neg->negstate.src, &cinfo.from);
650 HOSTIDCOPY(&neg->state, &cinfo);
651
652 alarm_add_disconnect(weclosed,
653 CRULE_OR_HRULE(neg),
654 ALARM_INTERNAL,
655 &cinfo,
656 error,
657 sockscf.shmemfd);
658 }
659
660 if (!erroriseof && neg->negstate.complete) {
661 struct timeval tdiff;
662
663 gettimeofday_monotonic(&tnow);
664 timersub(&tnow, &neg->state.time.negotiateend, &tdiff);
665
666 if (tdiff.tv_sec >= CRULE_OR_HRULE(neg)->timeout.negotiate)
667 takingtoolong = 1;
668 }
669
670 snprintf(reason, sizeof(reason),
671 "error after reading %lu byte%s%s in %ld second%s: %s",
672 (unsigned long)neg->negstate.reqread,
673 (unsigned long)neg->negstate.reqread == 1 ? "" : "s",
674 takingtoolong ?
675 ", possibly due to us taking too "
676 "long to send the clientobject to mother" : "",
677 (long)duration,
678 duration == 1 ? "" : "s",
679 error);
680
681 init_iologaddr(&src,
682 object_sockshost,
683 &neg->negstate.dst,
684 object_sockshost,
685 &neg->negstate.src,
686 &neg->cauth,
687 GET_HOSTIDV(&neg->state),
688 GET_HOSTIDC(&neg->state));
689
690 if (neg->crule.log.tcpinfo) {
691 int fdv[] = { neg->s };
692
693 neg->state.tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
694 }
695
696 logdisconnect(neg->s,
697 neg,
698 OPERATION_ERROR,
699 &src,
700 NULL,
701 reason,
702 strlen(reason));
703
704 delete_negotiate(neg, 0);
705 break;
706 }
707
708 default:
709 SERRX(negstatus);
710 }
711 }
712 }
713 }
714
715 void
negotiate_preconfigload(void)716 negotiate_preconfigload(void)
717 {
718 const char *function = "negotiate_preconfigload()";
719
720 slog(LOG_DEBUG, "%s", function);
721 }
722
723 void
negotiate_postconfigload(void)724 negotiate_postconfigload(void)
725 {
726 const char *function = "negotiate_postconfigload()";
727 size_t i;
728
729 slog(LOG_DEBUG, "%s", function);
730
731 /*
732 * update monitor shmids in rules used by current clients.
733 */
734 for (i = 0; i < negc; ++i) {
735 const monitor_t *p;
736 monitor_t oldmonitor, newmonitor;
737 clientinfo_t cinfo;
738
739 if (!negv[i].allocated)
740 continue;
741
742 SASSERTX(CRULE_OR_HRULE(&negv[i])->mstats == NULL);
743
744 bzero(&oldmonitor, sizeof(oldmonitor));
745 if (CRULE_OR_HRULE(&negv[i])->mstats_shmid != 0)
746 COPY_MONITORFIELDS(CRULE_OR_HRULE(&negv[i]), &oldmonitor);
747
748 p = monitormatch(&negv[i].negstate.src,
749 &negv[i].negstate.dst,
750 &negv[i].cauth,
751 &negv[i].state);
752
753 if (p == NULL)
754 bzero(&newmonitor, sizeof(newmonitor));
755 else {
756 SASSERTX(p->mstats == NULL);
757 newmonitor = *p;
758 }
759
760 if (oldmonitor.mstats_shmid == 0 && newmonitor.mstats_shmid == 0)
761 continue; /* no monitors for this client before, and no now. */
762
763 sockshost2sockaddr(&negv[i].negstate.src, &cinfo.from);
764 HOSTIDCOPY(&negv[i].state, &cinfo);
765
766 monitor_move(&oldmonitor,
767 &newmonitor,
768 0, /* negotiate process does not stay attached. */
769 ALARM_INTERNAL,
770 &cinfo,
771 sockscf.shmemfd);
772
773 COPY_MONITORFIELDS(&newmonitor, CRULE_OR_HRULE(&negv[i]));
774
775 #if COVENANT
776 #warning "missing monitor code"
777 #endif /* COVENANT */
778 }
779 }
780
781
782 static int
send_negotiate(neg)783 send_negotiate(neg)
784 sockd_negotiate_t *neg;
785 {
786 const char *function = "send_negotiate()";
787 #if HAVE_GSSAPI
788 gss_buffer_desc gssapistate = { 0, NULL };
789 char gssapistatemem[MAX_GSS_STATE];
790 #endif /* HAVE_GSSAPI */
791 struct iovec iov[2];
792 sockd_request_t req;
793 clientinfo_t cinfo;
794 struct msghdr msg;
795 ssize_t w;
796 size_t length, ioc, fdsendt;
797 CMSG_AALLOC(cmsg, sizeof(int));
798 int unuse = 0;
799
800 sockshost2sockaddr(&neg->negstate.src, &cinfo.from);
801 HOSTIDCOPY(&neg->state, &cinfo);
802
803 if (CRULE_OR_HRULE(neg)->bw_shmid != 0
804 && !CRULE_OR_HRULE(neg)->bw_isinheritable)
805 unuse |= SHMEM_BW;
806
807 if (CRULE_OR_HRULE(neg)->ss_shmid != 0
808 && !CRULE_OR_HRULE(neg)->ss_isinheritable)
809 unuse |= SHMEM_SS;
810
811 if (unuse != 0)
812 slog(LOG_DEBUG,
813 "%s: unusing and clearing shmem %d; not marked as inheritable",
814 function, unuse);
815 else
816 slog(LOG_DEBUG, "%s: no shmem to unuse/clear", function);
817
818 SHMEM_UNUSE(CRULE_OR_HRULE(neg), &cinfo, sockscf.shmemfd, unuse);
819 SHMEM_CLEAR(CRULE_OR_HRULE(neg), unuse, 1);
820 SHMEM_CLEAR(CRULE_OR_HRULE(neg), SHMEM_ALL, 0);
821
822 /*
823 * copy needed fields from negotiate.
824 */
825 bzero(&req, sizeof(req)); /* silence valgrind warning */
826 sockshost2sockaddr(&neg->negstate.src, &req.from);
827 sockshost2sockaddr(&neg->negstate.dst, &req.to);
828
829 req.req = neg->req;
830 req.reqinfo.command = (neg->state.protocol == SOCKS_TCP ?
831 SOCKD_FREESLOT_TCP : SOCKD_FREESLOT_UDP);
832
833 #if HAVE_NEGOTIATE_PHASE
834 /*
835 * save initial requestdata from client, if any.
836 */
837
838 #if COVENANT
839 if (neg->req.flags.httpconnect)
840 length = 0;
841 else {
842 /* XXX should probably strip out any authorization headers if present. */
843 length = neg->negstate.reqread;
844 memcpy(req.clientdata, neg->negstate.mem, length);
845 }
846
847 #else /* SOCKS_SERVER */
848 if ((length = socks_bytesinbuffer(neg->s, READ_BUF, 0)) != 0) {
849 slog(length > sizeof(req.clientdata) ? LOG_INFO : LOG_DEBUG,
850 "%s: local socks client at %s sent us %lu bytes of payload before "
851 "we told it that it can do that. Not permitted by the SOCKS "
852 "standard. %s",
853 function,
854 socket2string(neg->s, NULL, 0),
855 (unsigned long)length,
856 length > sizeof(req.clientdata) ?
857 "Too much unexpected data for us to handle"
858 : "Trying to handle it however");
859
860 if (length > sizeof(req.clientdata))
861 return -1;
862
863 socks_getfrombuffer(neg->s, 0, READ_BUF, 0, req.clientdata, length);
864 }
865 #endif /* SOCKS_SERVER */
866
867 req.clientdatalen = length;
868
869 if (req.clientdatalen > 0)
870 slog(LOG_DEBUG,
871 "%s: saving local client data of length %lu for later forwarding",
872 function, (unsigned long)req.clientdatalen);
873 #endif /* HAVE_NEGOTIATE_PHASE */
874
875 req.crule = neg->crule;
876
877 #if HAVE_SOCKS_HOSTID
878 req.hrule = neg->hrule;
879 req.hrule_isset = neg->hrule_isset;
880 #endif /* HAVE_SOCKS_HOSTID */
881
882 #if COVENANT
883 req.srule = neg->srule;
884 #endif /* COVENANT */
885
886 req.cauth = neg->cauth;
887 req.sauth = neg->sauth;
888
889 req.state = neg->state;
890
891 SASSERTX(proxyprotocolisknown(req.state.proxyprotocol));
892
893 slog(LOG_DEBUG,
894 "%s: client %s finished negotiate phase for command %s using "
895 "proxyprotocol %s",
896 function,
897 sockaddr2string(&req.from, NULL, 0),
898 command2string(req.state.command),
899 proxyprotocol2string(req.state.proxyprotocol));
900
901 bzero(iov, sizeof(iov));
902 ioc = 0;
903 length = 0;
904 iov[ioc].iov_base = &req;
905 iov[ioc].iov_len = sizeof(req);
906 length += iov[ioc].iov_len;
907 ++ioc;
908
909 #if HAVE_GSSAPI
910 if (req.sauth.method == AUTHMETHOD_GSSAPI) {
911 gssapistate.value = gssapistatemem;
912 gssapistate.length = sizeof(gssapistatemem);
913
914 if (gssapi_export_state(&req.sauth.mdata.gssapi.state.id, &gssapistate)
915 != 0)
916 return -1;
917
918 iov[ioc].iov_base = gssapistate.value;
919 iov[ioc].iov_len = gssapistate.length;
920 length += iov[ioc].iov_len;
921 ++ioc;
922
923 if (sockscf.option.debug >= DEBUG_VERBOSE)
924 slog(LOG_DEBUG, "%s: gssapistate has length %lu",
925 function, (long unsigned)gssapistate.length);
926 }
927 #endif /* HAVE_GSSAPI */
928
929 fdsendt = 0;
930
931 #if BAREFOOTD
932 if (req.state.command != SOCKS_UDPASSOCIATE)
933 /* udp has no control/client socket until set up in request-child. */
934 CMSG_ADDOBJECT(neg->s, cmsg, sizeof(neg->s) * fdsendt++);
935
936 #else /* !BAREFOOTD */
937
938 CMSG_ADDOBJECT(neg->s, cmsg, sizeof(neg->s) * fdsendt++);
939
940 #endif /* !BAREFOOTD */
941
942 bzero(&msg, sizeof(msg));
943 msg.msg_iov = iov;
944 msg.msg_iovlen = ioc;
945 msg.msg_name = NULL;
946 msg.msg_namelen = 0;
947
948 /* LINTED pointer casts may be troublesome */
949 CMSG_SETHDR_SEND(msg, cmsg, sizeof(int) * fdsendt);
950
951 if (sockscf.option.debug >= DEBUG_VERBOSE && neg->s != -1)
952 slog(LOG_DEBUG, "%s: sending fd %d (%s) ...",
953 function, neg->s, socket2string(neg->s, NULL, 0));
954
955 if ((w = sendmsgn(sockscf.state.mother.s, &msg, 0, 100)) != (ssize_t)length){
956 slog(LOG_DEBUG, "%s: sending client to mother failed: %s",
957 function, strerror(errno));
958
959 #if HAVE_GSSAPI
960 /*
961 * re-import the gssapi state so we can delete if needed.
962 */
963 if (gssapistate.value != NULL) {
964 if (gssapi_import_state(&req.sauth.mdata.gssapi.state.id, &gssapistate)
965 != 0)
966 swarnx("%s: could not re-import gssapi state", function);
967 }
968 #endif /* HAVE_GSSAPI */
969 }
970 else {
971 if (sockscf.option.debug >= DEBUG_VERBOSE)
972 slog(LOG_DEBUG,
973 "%s: sent %ld descriptors for command %d. cauth %s, sauth %s, "
974 "neg->s %d",
975 function,
976 (unsigned long)fdsendt,
977 req.state.command,
978 method2string(req.cauth.method),
979 method2string(req.sauth.method),
980 neg->s);
981 }
982
983 return (size_t)w == length ? 0 : -1;
984 }
985
986 static int
recv_negotiate(void)987 recv_negotiate(void)
988 {
989 const char *function = "recv_negotiate()";
990 sockd_client_t client;
991 sockd_negotiate_t *neg;
992 struct iovec iov[1];
993 struct msghdr msg;
994 ssize_t r;
995 size_t i, freec, newc, failedc;
996 CMSG_AALLOC(cmsg, sizeof(int));
997 char ruleinfo[256];
998 int permit, fdreceived;
999
1000 bzero(iov, sizeof(iov));
1001 iov[0].iov_base = &client;
1002 iov[0].iov_len = sizeof(client);
1003
1004 bzero(&msg, sizeof(msg));
1005 msg.msg_iov = iov;
1006 msg.msg_iovlen = ELEMENTS(iov);
1007 msg.msg_name = NULL;
1008 msg.msg_namelen = 0;
1009
1010 /* LINTED pointer casts may be troublesome */
1011 CMSG_SETHDR_RECV(msg, cmsg, CMSG_MEMSIZE(cmsg));
1012
1013 newc = failedc = errno = 0;
1014 freec = SOCKD_NEGOTIATEMAX - neg_allocated();
1015
1016 while (newc < freec) {
1017 const size_t fdexpect = 1;
1018 iologaddr_t src, dst;
1019 clientinfo_t cinfo;
1020
1021 #if DIAGNOSTIC /* for internal debugging/testing. */
1022 shmemcheck();
1023 #endif /* DIAGNOSTIC */
1024
1025 if ((r = recvmsgn(sockscf.state.mother.s, &msg, 0)) != sizeof(client)) {
1026 switch (r) {
1027 case -1:
1028 case 0:
1029 slog(LOG_DEBUG,
1030 "%s: recvmsg() from mother returned %ld after having "
1031 "received %lu new clients (%lu failed/blocked clients). "
1032 "errno = %d (%s)",
1033 function, (long)r,
1034 (unsigned long)newc, (unsigned long)failedc,
1035 errno, strerror(errno));
1036 break;
1037
1038 default:
1039 swarnx("%s: recvmsg(): unexpected short read from mother after "
1040 "having received %lu new clients. Got %ld/%lu bytes",
1041 function,
1042 (unsigned long)newc,
1043 (long)r,
1044 (unsigned long)sizeof(client));
1045 }
1046
1047 break;
1048 }
1049
1050 if (socks_msghaserrors(function, &msg)) {
1051 ++failedc;
1052 continue;
1053 }
1054
1055 /*
1056 * Got packet of expected size, now find a free slot for it.
1057 */
1058 for (i = 0, neg = NULL; i < negc; ++i)
1059 if (!negv[i].allocated) {
1060 /*
1061 * don't allocate it yet, so siginfo() doesn't print before ready.
1062 */
1063 neg = &negv[i];
1064 break;
1065 }
1066
1067 if (neg == NULL)
1068 SERRX(neg_allocated());
1069
1070 if (!CMSG_RCPTLEN_ISOK(msg, sizeof(int) * fdexpect)) {
1071 swarnx("%s: received control message has the invalid len of %d",
1072 function, (int)CMSG_TOTLEN(msg));
1073
1074 ++failedc;
1075 continue;
1076 }
1077
1078 SASSERTX(cmsg->cmsg_level == SOL_SOCKET);
1079 SASSERTX(cmsg->cmsg_type == SCM_RIGHTS);
1080
1081 fdreceived = 0;
1082 CMSG_GETOBJECT(neg->s, cmsg, sizeof(neg->s) * fdreceived++);
1083
1084 if (sockscf.option.debug >= DEBUG_VERBOSE)
1085 slog(LOG_DEBUG, "%s: received fd %d (%s) ...",
1086 function, neg->s, socket2string(neg->s, NULL, 0));
1087
1088 neg->state.time.accepted = client.accepted;
1089 gettimeofday_monotonic(&neg->state.time.negotiatestart);
1090
1091 sockd_check_ipclatency("client object received from mother",
1092 &neg->state.time.accepted,
1093 &neg->state.time.negotiatestart,
1094 &neg->state.time.negotiatestart);
1095
1096 /*
1097 * init state correctly for checking a connection to us.
1098 */
1099
1100 sockaddr2sockshost(&client.from, &neg->negstate.src);
1101 sockaddr2sockshost(&client.to, &neg->negstate.dst);
1102
1103 neg->state.command = SOCKS_ACCEPT;
1104 neg->state.protocol = SOCKS_TCP;
1105
1106 neg->req.auth = &neg->sauth; /* pointer fixup */
1107 neg->cauth.method = AUTHMETHOD_NOTSET; /* nothing so far */
1108
1109 #if PRERELEASE
1110 #warning "XXX add call to sockd_handledsignals() here. This loop could be long"
1111 #endif /* PRERELEASE */
1112
1113 permit = rulespermit(neg->s,
1114 &client.from,
1115 &client.to,
1116 NULL,
1117 &neg->cauth,
1118 &neg->crule,
1119 &neg->state,
1120 &neg->negstate.src,
1121 &neg->negstate.dst,
1122 NULL,
1123 ruleinfo,
1124 sizeof(ruleinfo));
1125
1126 cinfo.from = client.from;
1127 HOSTIDCOPY(&neg->state, &cinfo);
1128
1129 setconfsockoptions(neg->s,
1130 neg->s,
1131 SOCKS_TCP,
1132 1,
1133 neg->crule.socketoptionc,
1134 neg->crule.socketoptionv,
1135 SOCKETOPT_ANYTIME | SOCKETOPT_POST,
1136 SOCKETOPT_ANYTIME | SOCKETOPT_POST);
1137
1138 /*
1139 * Might need to use some values from cauth when negotiating,
1140 * i.e. gssapi or pam-values. Also, in some cases (gssapi), the
1141 * authmethod to be used for socks negotiation needs to be
1142 * set at the client acl pass, so start by copying the current
1143 * cauth into what will become the sauth proper.
1144 */
1145 neg->sauth = neg->cauth;
1146
1147 /* but don't actually set the authmethod. rulespermit() will do that. */
1148 neg->sauth.method = AUTHMETHOD_NOTSET;
1149
1150 if (permit) {
1151 if (shmem_userule(&neg->crule, &cinfo, ruleinfo, sizeof(ruleinfo))
1152 != 0) {
1153 permit = 0;
1154 neg->crule.verdict = VERDICT_BLOCK;
1155
1156 SASSERTX(!SHMID_ISATTACHED(&neg->crule));
1157 SHMEM_CLEAR(&neg->crule, SHMEM_ALL, 1); /* could not use it. */
1158 }
1159 }
1160
1161 init_iologaddr(&src,
1162 object_sockaddr,
1163 &client.to,
1164 object_sockshost,
1165 &neg->negstate.src,
1166 &neg->cauth,
1167 GET_HOSTIDV(&neg->state),
1168 GET_HOSTIDC(&neg->state));
1169
1170 init_iologaddr(&dst,
1171 object_none,
1172 NULL,
1173 object_sockshost,
1174 #if BAREFOOTD
1175 &neg->crule.extra.bounceto,
1176 #else /* !BAREFOOTD */
1177 NULL,
1178 #endif /* !BAREFOOTD */
1179 NULL,
1180 NULL,
1181 0);
1182
1183
1184 #if !HAVE_SOCKS_RULES
1185 /*
1186 * If it's a block, this is the only logging that will be done, so
1187 * do it now.
1188 */
1189
1190 if (!permit) /* really SOCKS_ACCEPT, but user does not know about that. */
1191 neg->state.command = SOCKS_CONNECT;
1192
1193 if (!permit || sockscf.option.debug) {
1194 #endif /* !HAVE_SOCKS_RULES */
1195
1196 logdisconnect(neg->s,
1197 neg,
1198 permit ? OPERATION_ACCEPT : OPERATION_BLOCK,
1199 &src,
1200 #if BAREFOOTD
1201 &dst,
1202 #else /* !HAVE_SOCKS_RULES */
1203 NULL,
1204 #endif /* !HAVE_SOCKS_RULES */
1205
1206 ruleinfo,
1207 strlen(ruleinfo));
1208
1209 #if !HAVE_SOCKS_RULES
1210 }
1211 #endif /* !HAVE_SOCKS_RULES */
1212
1213 if (!permit) {
1214 ++failedc;
1215 delete_negotiate(neg, 0);
1216
1217 continue;
1218 }
1219
1220 #if HAVE_NEGOTIATE_PHASE
1221 socks_allocbuffer(neg->s, SOCK_STREAM);
1222
1223 /*
1224 * We don't want this buffer to be bigger than MAXREQLEN, as that is
1225 * the amount of memory we have allocated to hold possible client data.
1226 *
1227 * Normally there is no client data in Dante's case, but some clients
1228 * may piggy-back the payload together with the socks request, without
1229 * waiting for our response. That is not legal to do, but some clients
1230 * do it anyway, so we better support it.
1231 * We therefor need to make sure we never read more of the payload than
1232 * we can send on to the i/o process, which will eventually need to
1233 * forward it to the destination.
1234 */
1235 socks_setbufferfd(neg->s, _IONBF, MAXREQLEN);
1236 #endif /* HAVE_NEGOTIATE_PHASE */
1237
1238 #if HAVE_PAM
1239 /* copy over pam-values from matched rule. */
1240 STRCPY_ASSERTSIZE(neg->sauth.mdata.pam.servicename,
1241 CRULE_OR_HRULE(neg)->state.pamservicename);
1242 #endif /* HAVE_PAM */
1243
1244 #if HAVE_BSDAUTH
1245 /* copy over bsdauth-values from matched rule. */
1246 STRCPY_ASSERTSIZE(neg->sauth.mdata.bsd.style,
1247 CRULE_OR_HRULE(neg)->state.bsdauthstylename);
1248 #endif /* HAVE_BSDAUTH */
1249
1250 #if HAVE_GSSAPI
1251 /* copy over gssapi-values from matched rule. */
1252 STRCPY_ASSERTSIZE(neg->sauth.mdata.gssapi.servicename,
1253 CRULE_OR_HRULE(neg)->state.gssapiservicename);
1254
1255 STRCPY_ASSERTSIZE(neg->sauth.mdata.gssapi.keytab,
1256 CRULE_OR_HRULE(neg)->state.gssapikeytab);
1257
1258 neg->sauth.mdata.gssapi.encryption
1259 = CRULE_OR_HRULE(neg)->state.gssapiencryption;
1260 #endif /* HAVE_GSSAPI */
1261
1262 #if HAVE_SOCKS_HOSTID
1263 if (sockscf.hrule != NULL) {
1264 /*
1265 * Unlike the client- and socks-rules, we assume that if no
1266 * hostid-rules are configured, we should simply skip/pass
1267 * that step. The reason for this is that hostid may not be
1268 * available or in use on the network, or the user may not want
1269 * to care about it. So unless the user explicitly enables
1270 * hostid-usage by providing at least one hostid-rule, the most
1271 * sensible default is to not require hostid-rules permitting the
1272 * client.
1273 */
1274 size_t p;
1275
1276 slog(LOG_DEBUG, "%s: checking access through hostid rules", function);
1277
1278 neg->state.command = SOCKS_HOSTID;
1279 permit = rulespermit(neg->s,
1280 &client.from,
1281 &client.to,
1282 &neg->cauth,
1283 &neg->cauth,
1284 &neg->hrule,
1285 &neg->state,
1286 &neg->negstate.src,
1287 &neg->negstate.dst,
1288 NULL,
1289 ruleinfo,
1290 sizeof(ruleinfo));
1291
1292 /*
1293 * if no hostids, no rules will have been checked.
1294 */
1295 if (!permit || (permit && neg->state.hostidc > 0)) {
1296 neg->hrule_isset = 1;
1297
1298 setconfsockoptions(neg->s,
1299 -1,
1300 SOCKS_TCP,
1301 1,
1302 neg->hrule.socketoptionc,
1303 neg->hrule.socketoptionv,
1304 SOCKETOPT_PRE | SOCKETOPT_ANYTIME,
1305 0 /* should already be set. */);
1306
1307 HOSTIDCOPY(&src, &neg->state);
1308
1309 if (permit) {
1310 /*
1311 * Let the hostid-rule inherit settings from the client-rule,
1312 * or use it's own.
1313 */
1314 if (rule_inheritoruse(&neg->crule,
1315 &cinfo,
1316 &neg->hrule,
1317 &cinfo,
1318 ALARM_INTERNAL,
1319 ruleinfo,
1320 sizeof(ruleinfo)) != 0) {
1321 SHMEM_CLEAR(&neg->hrule, SHMEM_ALL, 1);
1322 permit = 0;
1323 }
1324 }
1325
1326 if (neg->hrule.log.tcpinfo) {
1327 int fdv[] = { neg->s };
1328
1329 neg->state.tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
1330 }
1331
1332 iolog(&neg->hrule,
1333 &neg->state,
1334 permit ? OPERATION_HOSTID : OPERATION_BLOCK,
1335 &src,
1336
1337 #if BAREFOOTD
1338 &dst,
1339 #else /* !HAVE_SOCKS_RULES */
1340 NULL,
1341 #endif /* !HAVE_SOCKS_RULES */
1342
1343 NULL,
1344 NULL,
1345 ruleinfo,
1346 strlen(ruleinfo));
1347
1348 if (!permit) {
1349 /*
1350 * log the client-rule close too.
1351 */
1352 p = snprintf(ruleinfo, sizeof(ruleinfo),
1353 "blocked by higher-level %s #%lu",
1354 objecttype2string(neg->hrule.type),
1355 (unsigned long)neg->hrule.number);
1356
1357 if (neg->crule.log.tcpinfo && neg->state.tcpinfo == NULL) {
1358 int fdv[] = { neg->s };
1359
1360 neg->state.tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
1361 }
1362
1363 neg->state.command = HAVE_SOCKS_RULES ?
1364 SOCKS_ACCEPT : SOCKS_CONNECT;
1365
1366 iolog(&neg->crule,
1367 &neg->state,
1368 OPERATION_BLOCK,
1369 &src,
1370
1371 #if BAREFOOTD
1372 &dst,
1373 #else /* !HAVE_SOCKS_RULES */
1374 NULL,
1375 #endif /* !HAVE_SOCKS_RULES */
1376
1377 NULL,
1378 NULL,
1379 ruleinfo,
1380 p);
1381
1382 #if !HAVE_SOCKS_RULES
1383 if (sockscf.option.debug) {
1384 neg->state.command = SOCKS_ACCEPT;
1385 /*
1386 * normally not logging tcp/accept, but if debug is enabled,
1387 * we do.
1388 */
1389 iolog(&neg->crule,
1390 &neg->state,
1391 OPERATION_BLOCK,
1392 &src,
1393 &dst,
1394 NULL,
1395 NULL,
1396 ruleinfo,
1397 p);
1398 }
1399 #endif /* !HAVE_SOCKS_RULES */
1400
1401 neg->state.tcpinfo = NULL;
1402
1403 ++failedc;
1404 delete_negotiate(neg, 0);
1405
1406 continue;
1407 }
1408
1409 neg->state.tcpinfo = NULL;
1410 }
1411 }
1412 #endif /* HAVE_SOCKS_HOSTID */
1413
1414 #if BAREFOOTD
1415
1416 neg->req.version = PROXY_SOCKS_V5;
1417 neg->req.command = SOCKS_CONNECT;
1418 neg->req.flag = 0;
1419 neg->req.protocol = SOCKS_TCP;
1420
1421 ruleaddr2sockshost(&neg->crule.extra.bounceto,
1422 &neg->req.host,
1423 neg->req.protocol);
1424
1425 neg->negstate.complete = 1; /* nothing to do in barefoot's case. */
1426
1427 #elif COVENANT /* !BAREFOOTD */
1428
1429 if (client.clientdatalen > 0) {
1430 slog(LOG_DEBUG,
1431 "%s: received client already has %lu bytes read from it. "
1432 "Must be a client that is changing it's http server target "
1433 "to %s, so request should already be parsed",
1434 function,
1435 (unsigned long)client.clientdatalen,
1436 sockshost2string(&client.request.host, NULL, 0));
1437
1438 SASSERTX(client.clientdatalen <= sizeof(neg->negstate.mem));
1439 memcpy(neg->negstate.mem, client.clientdata, client.clientdatalen);
1440 neg->negstate.reqread = client.clientdatalen;
1441 neg->negstate.complete = 1;
1442 neg->req = client.request;
1443 *neg->req.auth = client.auth; /* pointer fixup. */
1444 }
1445 #endif /* COVENANT */
1446
1447 /*
1448 * wait with this until the end, when we know that the client was
1449 * accepted and by what rule (crule or hrule).
1450 */
1451 if (CRULE_OR_HRULE(neg)->mstats_shmid != 0
1452 && CRULE_OR_HRULE(neg)->alarmsconfigured & ALARM_DISCONNECT)
1453 alarm_add_connect(CRULE_OR_HRULE(neg),
1454 ALARM_INTERNAL,
1455 &cinfo,
1456 sockscf.shmemfd);
1457
1458 neg->negstate.crule = &neg->crule;
1459
1460 neg->allocated = 1;
1461 ++newc;
1462 }
1463
1464 if (newc == 0 && failedc == 0) {
1465 slog(LOG_DEBUG,
1466 "%s: strange ... we were called to receive a new client (%lu/%lu), "
1467 "but no new client was there to receive: %s",
1468 function,
1469 (unsigned long)(freec + 1),
1470 (unsigned long)SOCKD_NEGOTIATEMAX,
1471 strerror(errno));
1472
1473 return -1;
1474 }
1475
1476 if (ERRNOISTMP(errno))
1477 errno = 0;
1478
1479 return newc;
1480 }
1481
1482 static void
delete_negotiate(neg,forwardedtomother)1483 delete_negotiate(neg, forwardedtomother)
1484 sockd_negotiate_t *neg;
1485 const int forwardedtomother;
1486 {
1487 const char *function = "delete_negotiate()";
1488
1489 slog(LOG_DEBUG, "%s: forwardedtomother: %d", function, forwardedtomother);
1490
1491 if (!forwardedtomother) {
1492 const unsigned char cmd = (neg->state.protocol == SOCKS_TCP ?
1493 SOCKD_FREESLOT_TCP : SOCKD_FREESLOT_UDP);
1494 clientinfo_t cinfo;
1495
1496 #if HAVE_GSSAPI
1497 if (neg->sauth.method == AUTHMETHOD_GSSAPI
1498 && neg->sauth.mdata.gssapi.state.id != GSS_C_NO_CONTEXT) {
1499 OM_uint32 major_status, minor_status;
1500
1501 if ((major_status
1502 = gss_delete_sec_context(&minor_status,
1503 &neg->sauth.mdata.gssapi.state.id,
1504 GSS_C_NO_BUFFER)) != GSS_S_COMPLETE){
1505 char buf[512];
1506
1507 if (!gss_err_isset(major_status,
1508 minor_status,
1509 buf,
1510 sizeof(buf))) {
1511 *buf = NUL;
1512
1513 swarn("%s: gss_delete_sec_context() failed%s%s",
1514 function,
1515 *buf == NUL ? "" : ": ",
1516 *buf == NUL ? "" : buf);
1517 }
1518 }
1519 }
1520 #endif /* HAVE_GSSAPI */
1521
1522 sockshost2sockaddr(&neg->negstate.src, &cinfo.from);
1523 HOSTIDCOPY(&neg->state, &cinfo);
1524
1525 if (socks_sendton(sockscf.state.mother.ack,
1526 &cmd,
1527 sizeof(cmd),
1528 sizeof(cmd),
1529 0,
1530 NULL,
1531 0,
1532 NULL,
1533 NULL) != sizeof(cmd))
1534 slog(sockd_motherexists() ? LOG_WARNING : LOG_DEBUG,
1535 "%s: sending ack to mother failed: %s",
1536 function, strerror(errno));
1537
1538 SHMEM_UNUSE(CRULE_OR_HRULE(neg),
1539 &cinfo,
1540 sockscf.shmemfd,
1541 SHMEM_ALL);
1542 }
1543
1544 #if HAVE_NEGOTIATE_PHASE
1545 socks_freebuffer(neg->s);
1546 #endif /* HAVE_NEGOTIATE_PHASE */
1547
1548 close(neg->s);
1549 bzero(neg, sizeof(*neg));
1550 proctitleupdate();
1551 }
1552
1553 static int
neg_fillset(set,skipcompleted,skipinprogress)1554 neg_fillset(set, skipcompleted, skipinprogress)
1555 fd_set *set;
1556 const int skipcompleted;
1557 const int skipinprogress;
1558 {
1559 size_t i;
1560 int max;
1561
1562 FD_ZERO(set);
1563 for (i = 0, max = -1; i < negc; ++i) {
1564 if (!negv[i].allocated)
1565 continue;
1566
1567 #if !HAVE_NEGOTIATE_PHASE
1568 SASSERTX(negv[i].negstate.complete);
1569 #endif /* HAVE_NEGOTIATE_PHASE */
1570
1571 if (skipcompleted && negv[i].negstate.complete)
1572 continue;
1573
1574 if (skipinprogress && !negv[i].negstate.complete)
1575 continue;
1576
1577 FD_SET(negv[i].s, set);
1578 max = MAX(max, negv[i].s);
1579 }
1580
1581 return max;
1582 }
1583
1584 static void
neg_clearset(neg,set)1585 neg_clearset(neg, set)
1586 sockd_negotiate_t *neg;
1587 fd_set *set;
1588 {
1589
1590 FD_CLR(neg->s, set);
1591 }
1592
1593 static sockd_negotiate_t *
neg_getset(set)1594 neg_getset(set)
1595 fd_set *set;
1596 {
1597 size_t i;
1598
1599 for (i = 0; i < negc; ++i) {
1600 if (!negv[i].allocated)
1601 continue;
1602
1603 if (FD_ISSET(negv[i].s, set))
1604 return &negv[i];
1605 }
1606
1607 return NULL;
1608 }
1609
1610 static size_t
neg_allocated(void)1611 neg_allocated(void)
1612 {
1613 size_t i, alloc;
1614
1615 for (i = 0, alloc = 0; i < negc; ++i)
1616 if (negv[i].allocated)
1617 ++alloc;
1618
1619 return alloc;
1620 }
1621
1622 static size_t
neg_completed(count)1623 neg_completed(count)
1624 const size_t count;
1625 {
1626 size_t i, completec;
1627
1628 for (i = 0, completec = 0; i < negc; ++i)
1629 if (negv[i].allocated && negv[i].negstate.complete)
1630 if (++completec >= count)
1631 return completec;
1632
1633 return completec;
1634 }
1635
1636 static void
proctitleupdate(void)1637 proctitleupdate(void)
1638 {
1639
1640 setproctitle("%s: %lu/%lu",
1641 childtype2string(sockscf.state.type),
1642 (unsigned long)neg_allocated(),
1643 (unsigned long)SOCKD_NEGOTIATEMAX);
1644 }
1645
1646 static void
logdisconnect(s,neg,op,src,dst,buf,buflen)1647 logdisconnect(s, neg, op, src, dst, buf, buflen)
1648 const int s;
1649 sockd_negotiate_t *neg;
1650 const operation_t op;
1651 const iologaddr_t *src;
1652 const iologaddr_t *dst;
1653 const char *buf;
1654 const size_t buflen;
1655 {
1656
1657 if (neg->crule.log.tcpinfo) {
1658 int fdv[] = { neg->s };
1659
1660 neg->state.tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
1661 }
1662
1663 iolog(&neg->crule,
1664 &neg->state,
1665 op,
1666 src,
1667 dst,
1668 NULL,
1669 NULL,
1670 buf,
1671 buflen);
1672
1673 #if HAVE_SOCKS_HOSTID
1674 if (neg->hrule_isset) {
1675 if (neg->state.tcpinfo == NULL && neg->hrule.log.tcpinfo) {
1676 int fdv[] = { neg->s };
1677
1678 neg->state.tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
1679 }
1680
1681 iolog(&neg->hrule,
1682 &neg->state,
1683 op,
1684 src,
1685 dst,
1686 NULL,
1687 NULL,
1688 buf,
1689 buflen);
1690 }
1691 #endif /* HAVE_SOCKS_HOSTID */
1692
1693 neg->state.tcpinfo = NULL;
1694 }
1695
1696
1697 static struct timeval *
neg_gettimeout(timeout)1698 neg_gettimeout(timeout)
1699 struct timeval *timeout;
1700 {
1701 #if HAVE_NEGOTIATE_PHASE
1702 const char *function = "neg_gettimeout()";
1703 time_t timenow;
1704 size_t i;
1705 int havetimeout;
1706
1707 havetimeout = 0;
1708 time_monotonic(&timenow);
1709
1710 for (i = 0; i < negc; ++i) {
1711 if (!negv[i].allocated)
1712 continue;
1713
1714 if (CRULE_OR_HRULE(&negv[i])->timeout.negotiate == 0)
1715 continue;
1716
1717 if (havetimeout)
1718 timeout->tv_sec
1719 = MAX(0,
1720 MIN(timeout->tv_sec,
1721 socks_difftime(CRULE_OR_HRULE(&negv[i])->timeout.negotiate,
1722 socks_difftime(timenow,
1723 negv[i].state.time.negotiatestart.tv_sec))));
1724 else {
1725 timeout->tv_sec
1726 = MAX(0,
1727 socks_difftime(CRULE_OR_HRULE(&negv[i])->timeout.negotiate,
1728 socks_difftime(timenow,
1729 negv[i].state.time.negotiatestart.tv_sec)));
1730 havetimeout = 1;
1731 }
1732 }
1733
1734 if (!havetimeout)
1735 timeout = NULL;
1736 else {
1737 /*
1738 * never mind sub-second accuracy, but be sure we don't end up with
1739 * {0, 0}.
1740 */
1741 timeout->tv_usec = 999999;
1742 }
1743
1744 #else /* !HAVE_NEGOTIATE_PHASE */
1745 timeout = NULL;
1746 #endif /* !HAVE_NEGOTIATE_PHASE */
1747
1748 return timeout;
1749 }
1750
1751 /* ARGSUSED */
1752 static void
siginfo(sig,si,sc)1753 siginfo(sig, si, sc)
1754 int sig;
1755 siginfo_t *si;
1756 void *sc;
1757 {
1758 const char *function = "siginfo()";
1759 const int errno_s = errno;
1760 time_t tnow;
1761 unsigned long days, hours, minutes, seconds;
1762 size_t i;
1763
1764 SIGNAL_PROLOGUE(sig, si, errno_s);
1765
1766 seconds = (unsigned long)socks_difftime(time_monotonic(&tnow),
1767 sockscf.stat.boot);
1768
1769 seconds2days(&seconds, &days, &hours, &minutes);
1770
1771 slog(LOG_INFO, "negotiate-child up %lu day%s, %lu:%.2lu:%.2lu",
1772 days, days == 1 ? "" : "s", hours, minutes, seconds);
1773
1774 for (i = 0; i < negc; ++i) {
1775 char srcstring[MAX_IOLOGADDR], *tcpinfo;
1776
1777 if (!negv[i].allocated)
1778 continue;
1779
1780 build_addrstr_src(GET_HOSTIDV(&negv[i].state),
1781 GET_HOSTIDC(&negv[i].state),
1782 &negv[i].negstate.src,
1783 NULL,
1784 NULL,
1785 &negv[i].negstate.dst,
1786 &negv[i].cauth,
1787 NULL,
1788 srcstring,
1789 sizeof(srcstring));
1790
1791 if (CRULE_OR_HRULE(&negv[i])->log.tcpinfo) {
1792 int fdv[] = { negv[i].s };
1793
1794 tcpinfo = get_tcpinfo(ELEMENTS(fdv), fdv, NULL, 0);
1795 }
1796 else
1797 tcpinfo = NULL;
1798
1799 slog(LOG_INFO,
1800 "%s: negotiating for %lds"
1801 "%s%s%s",
1802 srcstring,
1803 (long)socks_difftime(tnow, negv[i].state.time.negotiatestart.tv_sec),
1804 tcpinfo == NULL ? "" : "\n",
1805 tcpinfo == NULL ? "" : " TCP_INFO:\n",
1806 tcpinfo == NULL ? "" : tcpinfo);
1807 }
1808
1809 SIGNAL_EPILOGUE(sig, si, errno_s);
1810 }
1811
1812 #if HAVE_NEGOTIATE_PHASE
1813 static sockd_negotiate_t *
neg_gettimedout(const struct timeval * tnow)1814 neg_gettimedout(const struct timeval *tnow)
1815 {
1816 size_t i;
1817
1818 for (i = 0; i < negc; ++i) {
1819 if (!negv[i].allocated
1820 || CRULE_OR_HRULE(&negv[i])->timeout.negotiate == 0)
1821 continue;
1822
1823 if (socks_difftime(tnow->tv_sec, negv[i].state.time.negotiatestart.tv_sec)
1824 >= CRULE_OR_HRULE(&negv[i])->timeout.negotiate)
1825 return &negv[i];
1826 }
1827
1828 return NULL;
1829 }
1830 #endif /* HAVE_NEGOTIATE_PHASE */
1831