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