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