varnish-cache/bin/varnishd/mgt/mgt_acceptor.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * Acceptor socket management
31
 */
32
33
#include "config.h"
34
35
#include <sys/types.h>
36
#include <sys/socket.h>
37
#include <sys/un.h>
38
#include <sys/stat.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
#include <pwd.h>
44
#include <grp.h>
45
46
#include "mgt/mgt.h"
47
#include "common/heritage.h"
48
49
#include "vav.h"
50
#include "vcli_serve.h"
51
#include "vsa.h"
52
#include "vss.h"
53
#include "vtcp.h"
54
#include "vus.h"
55
56
struct listen_arg {
57
        unsigned                        magic;
58
#define LISTEN_ARG_MAGIC                0xbb2fc333
59
        VTAILQ_ENTRY(listen_arg)        list;
60
        const char                      *endpoint;
61
        const char                      *name;
62
        VTAILQ_HEAD(,listen_sock)       socks;
63
        const struct transport          *transport;
64
        const struct uds_perms          *perms;
65
};
66
67
struct uds_perms {
68
        unsigned        magic;
69
#define UDS_PERMS_MAGIC 0x84fb5635
70
        mode_t          mode;
71
        uid_t           uid;
72
        gid_t           gid;
73
};
74
75
static VTAILQ_HEAD(,listen_arg) listen_args =
76
    VTAILQ_HEAD_INITIALIZER(listen_args);
77
78
static int
79 1425
mac_vus_bind(void *priv, const struct sockaddr_un *uds)
80
{
81 1425
        return (VUS_bind(uds, priv));
82
}
83
84
static int
85 47075
mac_opensocket(struct listen_sock *ls)
86
{
87
        int fail;
88
        const char *err;
89
90 47075
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
91 47075
        if (ls->sock > 0) {
92 23100
                MCH_Fd_Inherit(ls->sock, NULL);
93 23100
                closefd(&ls->sock);
94 23100
        }
95 47075
        if (!ls->uds)
96 45650
                ls->sock = VTCP_bind(ls->addr, NULL);
97
        else
98 1425
                ls->sock = VUS_resolver(ls->endpoint, mac_vus_bind, NULL, &err);
99 47075
        fail = errno;
100 47075
        if (ls->sock < 0) {
101 25
                AN(fail);
102 25
                return (fail);
103
        }
104 47050
        if (ls->perms != NULL) {
105 100
                CHECK_OBJ(ls->perms, UDS_PERMS_MAGIC);
106 100
                assert(ls->uds);
107 100
                errno = 0;
108 100
                if (ls->perms->mode != 0 &&
109 100
                    chmod(ls->endpoint, ls->perms->mode) != 0)
110 0
                        return (errno);
111 100
                if (chown(ls->endpoint, ls->perms->uid, ls->perms->gid) != 0)
112 0
                        return (errno);
113 100
        }
114 47050
        MCH_Fd_Inherit(ls->sock, "sock");
115 47050
        return (0);
116 47075
}
117
118
/*=====================================================================
119
 * Reopen the accept sockets to get rid of listen status.
120
 * returns the highest errno encountered, 0 for success
121
 */
122
123
int
124 22775
MAC_reopen_sockets(void)
125
{
126
        struct listen_sock *ls;
127 22775
        int err, fail = 0;
128
129 45875
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
130 23100
                VJ_master(JAIL_MASTER_PRIVPORT);
131 23100
                err = mac_opensocket(ls);
132 23100
                VJ_master(JAIL_MASTER_LOW);
133 23100
                if (err == 0)
134 23100
                        continue;
135 0
                fail = vmax(fail, err);
136 0
                MGT_Complain(C_ERR,
137
                    "Could not reopen listen socket %s: %s",
138 0
                    ls->endpoint, VAS_errtxt(err));
139 0
        }
140 22775
        return (fail);
141
}
142
143
/*--------------------------------------------------------------------*/
144
145
static struct listen_sock *
146 23975
mk_listen_sock(const struct listen_arg *la, const struct suckaddr *sa)
147
{
148
        struct listen_sock *ls;
149
        int fail;
150
151 23975
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
152 23975
        AN(ls);
153 23975
        ls->sock = -1;
154 23975
        ls->addr = VSA_Clone(sa);
155 23975
        AN(ls->addr);
156 23975
        REPLACE(ls->endpoint, la->endpoint);
157 23975
        ls->name = la->name;
158 23975
        ls->transport = la->transport;
159 23975
        ls->perms = la->perms;
160 23975
        ls->uds = VUS_is(la->endpoint);
161 23975
        VJ_master(JAIL_MASTER_PRIVPORT);
162 23975
        fail = mac_opensocket(ls);
163 23975
        VJ_master(JAIL_MASTER_LOW);
164 23975
        if (fail) {
165 25
                VSA_free(&ls->addr);
166 25
                free(ls->endpoint);
167 25
                FREE_OBJ(ls);
168 25
                if (fail != EAFNOSUPPORT)
169 25
                        ARGV_ERR("Could not get socket %s: %s\n",
170
                            la->endpoint, VAS_errtxt(fail));
171 0
                return (NULL);
172
        }
173 23950
        return (ls);
174 23950
}
175
176
static int v_matchproto_(vss_resolved_f)
177 23250
mac_tcp(void *priv, const struct suckaddr *sa)
178
{
179
        struct listen_arg *la;
180
        struct listen_sock *ls;
181
        char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
182
        char nbuf[VTCP_ADDRBUFSIZE+VTCP_PORTBUFSIZE+2];
183
184 23250
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
185
186 23850
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
187 625
                if (!ls->uds && !VSA_Compare(sa, ls->addr))
188 25
                        ARGV_ERR("-a arguments %s and %s have same address\n",
189
                            ls->endpoint, la->endpoint);
190 600
        }
191 23225
        ls = mk_listen_sock(la, sa);
192 23225
        if (ls == NULL)
193 0
                return (0);
194 23225
        AZ(ls->uds);
195 23225
        if (VSA_Port(ls->addr) == 0) {
196
                /*
197
                 * If the argv port number is zero, we adopt whatever
198
                 * port number this VTCP_bind() found us, as if
199
                 * it was specified by the argv.
200
                 */
201 23200
                VSA_free(&ls->addr);
202 23200
                ls->addr = VTCP_my_suckaddr(ls->sock);
203 46400
                VTCP_myname(ls->sock, abuf, sizeof abuf,
204 23200
                    pbuf, sizeof pbuf);
205 23200
                if (VSA_Get_Proto(sa) == AF_INET6)
206 575
                        bprintf(nbuf, "[%s]:%s", abuf, pbuf);
207
                else
208 22625
                        bprintf(nbuf, "%s:%s", abuf, pbuf);
209 23200
                REPLACE(ls->endpoint, nbuf);
210 23200
        }
211 23225
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
212 23225
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
213 23225
        return (0);
214 23225
}
215
216
static int v_matchproto_(vus_resolved_f)
217 750
mac_uds(void *priv, const struct sockaddr_un *uds)
218
{
219
        struct listen_arg *la;
220
        struct listen_sock *ls;
221
222 750
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
223 750
        (void) uds;
224
225 875
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
226 150
                if (ls->uds && strcmp(ls->endpoint, la->endpoint) == 0)
227 25
                        ARGV_ERR("-a arguments %s and %s have same address\n",
228
                            ls->endpoint, la->endpoint);
229 125
        }
230 725
        ls = mk_listen_sock(la, bogo_ip);
231 725
        if (ls == NULL)
232 0
                return (0);
233 725
        AN(ls->uds);
234 725
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
235 725
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
236 725
        return (0);
237 725
}
238
239
void
240 24075
MAC_Arg(const char *spec)
241
{
242
        char **av;
243
        struct listen_arg *la;
244
        const char *err;
245
        int error;
246 24075
        const struct transport *xp = NULL;
247
        const char *name;
248
        char name_buf[8];
249
        static unsigned seq = 0;
250 24075
        struct passwd *pwd = NULL;
251 24075
        struct group *grp = NULL;
252 24075
        mode_t mode = 0;
253
        struct uds_perms *perms;
254
255 24075
        av = MGT_NamedArg(spec, &name, "-a");
256 24075
        AN(av);
257
258 24075
        ALLOC_OBJ(la, LISTEN_ARG_MAGIC);
259 24075
        AN(la);
260 24075
        VTAILQ_INIT(&la->socks);
261 24075
        VTAILQ_INSERT_TAIL(&listen_args, la, list);
262 24075
        la->endpoint = av[1];
263
264 24075
        if (name == NULL) {
265 23900
                bprintf(name_buf, "a%u", seq++);
266 23900
                name = strdup(name_buf);
267 23900
                AN(name);
268 23900
        }
269 24075
        la->name = name;
270
271 24075
        if (*la->endpoint != '/' && strchr(la->endpoint, '/') != NULL)
272 25
                ARGV_ERR("Unix domain socket addresses must be"
273
                    " absolute paths in -a (%s)\n", la->endpoint);
274
275 24050
        if (VUS_is(la->endpoint) && heritage.min_vcl_version < 41)
276 1150
                heritage.min_vcl_version = 41;
277
278 24650
        for (int i = 2; av[i] != NULL; i++) {
279
                char *eq, *val;
280
                int len;
281
282 1175
                if ((eq = strchr(av[i], '=')) == NULL) {
283 575
                        if (xp != NULL)
284 50
                                ARGV_ERR("Too many protocol sub-args"
285
                                    " in -a (%s)\n", av[i]);
286 525
                        xp = XPORT_Find(av[i]);
287 525
                        if (xp == NULL)
288 50
                                ARGV_ERR("Unknown protocol '%s'\n", av[i]);
289 475
                        continue;
290
                }
291 600
                if (la->endpoint[0] != '/')
292 100
                        ARGV_ERR("Invalid sub-arg %s"
293
                            " in -a\n", av[i]);
294
295 500
                val = eq + 1;
296 500
                len = eq - av[i];
297 500
                assert(len >= 0);
298 500
                if (len == 0)
299 25
                        ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
300
301 475
                if (strncmp(av[i], "user", len) == 0) {
302 25
                        if (pwd != NULL)
303 0
                                ARGV_ERR("Too many user sub-args in -a (%s)\n",
304
                                         av[i]);
305 25
                        pwd = getpwnam(val);
306 25
                        if (pwd == NULL)
307 0
                                ARGV_ERR("Unknown user %s in -a\n", val);
308 25
                        continue;
309
                }
310
311 450
                if (strncmp(av[i], "group", len) == 0) {
312 25
                        if (grp != NULL)
313 0
                                ARGV_ERR("Too many group sub-args in -a (%s)\n",
314
                                         av[i]);
315 25
                        grp = getgrnam(val);
316 25
                        if (grp == NULL)
317 0
                                ARGV_ERR("Unknown group %s in -a\n", val);
318 25
                        continue;
319
                }
320
321 425
                if (strncmp(av[i], "mode", len) == 0) {
322
                        long m;
323
                        char *p;
324
325 325
                        if (mode != 0)
326 25
                                ARGV_ERR("Too many mode sub-args in -a (%s)\n",
327
                                         av[i]);
328 300
                        if (*val == '\0')
329 25
                                ARGV_ERR("Empty mode sub-arg in -a\n");
330 275
                        errno = 0;
331 275
                        m = strtol(val, &p, 8);
332 275
                        if (*p != '\0')
333 75
                                ARGV_ERR("Invalid mode sub-arg %s in -a\n",
334
                                         val);
335 200
                        if (errno)
336 50
                                ARGV_ERR("Cannot parse mode sub-arg %s in -a: "
337
                                         "%s\n", val, VAS_errtxt(errno));
338 150
                        if (m <= 0 || m > 0777)
339 75
                                ARGV_ERR("Mode sub-arg %s out of range in -a\n",
340
                                         val);
341 75
                        mode = (mode_t) m;
342 75
                        continue;
343
                }
344
345 100
                ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
346 0
        }
347
348 23475
        if (xp == NULL)
349 23050
                xp = XPORT_Find("http");
350 23475
        AN(xp);
351 23475
        la->transport = xp;
352
353 23475
        if (pwd != NULL || grp != NULL || mode != 0) {
354 50
                ALLOC_OBJ(perms, UDS_PERMS_MAGIC);
355 50
                AN(perms);
356 50
                if (pwd != NULL)
357 25
                        perms->uid = pwd->pw_uid;
358
                else
359 25
                        perms->uid = (uid_t) -1;
360 50
                if (grp != NULL)
361 25
                        perms->gid = grp->gr_gid;
362
                else
363 25
                        perms->gid = (gid_t) -1;
364 50
                perms->mode = mode;
365 50
                la->perms = perms;
366 50
        }
367
        else
368 23425
                AZ(la->perms);
369
370 23475
        if (VUS_is(la->endpoint))
371 775
                error = VUS_resolver(av[1], mac_uds, la, &err);
372
        else
373 22700
                error = VSS_resolver(av[1], "80", mac_tcp, la, &err);
374
375 23475
        if (VTAILQ_EMPTY(&la->socks) || error)
376 25
                ARGV_ERR("Got no socket(s) for %s\n", av[1]);
377 23450
        VAV_Free(av);
378 23450
}