varnish-cache/bin/varnishd/acceptor/mgt_acceptor_uds.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2023 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Asad Sajjad Ahmed <asadsa@varnish-software.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 * Acceptor socket management
32
 */
33
34
#include "config.h"
35
36
#include <sys/types.h>
37
#include <sys/socket.h>
38
#include <sys/un.h>
39
#include <sys/stat.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <unistd.h>
44
#include <pwd.h>
45
#include <grp.h>
46
47
#include "mgt/mgt.h"
48
#include "common/heritage.h"
49
50
#include "acceptor/cache_acceptor.h"
51
#include "acceptor/acceptor_uds.h"
52
#include "acceptor/mgt_acceptor.h"
53
54
#include "vsa.h"
55
#include "vus.h"
56
57
int
58 39840
vca_uds_config(void)
59
{
60
61 39840
        return (0);
62
}
63
64
static int
65 2280
vca_vus_bind(void *priv, const struct sockaddr_un *uds)
66
{
67 2280
        return (VUS_bind(uds, priv));
68
}
69
70
static int
71 2280
vca_uds_opensocket(struct listen_sock *ls)
72
{
73
        int fail;
74
        const char *err;
75
76 2280
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
77
78 2280
        if (ls->sock > 0) {
79 1120
                MCH_Fd_Inherit(ls->sock, NULL);
80 1120
                closefd(&ls->sock);
81 1120
        }
82
83 2280
        ls->sock = VUS_resolver(ls->endpoint, vca_vus_bind, NULL, &err);
84 2280
        fail = errno;
85
86 2280
        if (ls->sock < 0) {
87 0
                AN(fail);
88 0
                return (fail);
89
        }
90
91 2280
        if (ls->perms != NULL) {
92 160
                CHECK_OBJ(ls->perms, UDS_PERMS_MAGIC);
93 160
                assert(ls->uds);
94 160
                errno = 0;
95 160
                if (ls->perms->mode != 0 &&
96 160
                    chmod(ls->endpoint, ls->perms->mode) != 0)
97 0
                        return (errno);
98 160
                if (chown(ls->endpoint, ls->perms->uid, ls->perms->gid) != 0)
99 0
                        return (errno);
100 160
        }
101
102 2280
        MCH_Fd_Inherit(ls->sock, "sock");
103 2280
        return (0);
104 2280
}
105
106
static int v_matchproto_(vus_resolved_f)
107 1200
vca_uds_open_cb(void *priv, const struct sockaddr_un *uds)
108
{
109
        struct listen_arg *la;
110
        struct listen_sock *ls;
111
        int fail;
112
113 1200
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
114 1200
        (void) uds;
115
116 1240
        VTAILQ_FOREACH(ls, &UDS_acceptor.socks, vcalist) {
117 80
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
118
119 80
                if (strcmp(ls->endpoint, la->endpoint) == 0)
120 40
                        ARGV_ERR("-a arguments %s and %s have same address\n",
121
                            ls->endpoint, la->endpoint);
122 40
        }
123
124 1160
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
125 1160
        AN(ls);
126
127 1160
        ls->sock = -1;
128 1160
        ls->vca = &UDS_acceptor;
129
130 1160
        ls->addr = VSA_Clone(bogo_ip);
131 1160
        AN(ls->addr);
132
133 1160
        REPLACE(ls->endpoint, la->endpoint);
134 1160
        ls->name = la->name;
135 1160
        ls->transport = la->transport;
136 1160
        ls->perms = la->perms;
137 1160
        ls->uds = 1;
138
139 1160
        VJ_master(JAIL_MASTER_PRIVPORT);
140 1160
        fail = vca_uds_opensocket(ls);
141 1160
        VJ_master(JAIL_MASTER_LOW);
142
143 1160
        if (fail) {
144 0
                VSA_free(&ls->addr);
145 0
                free(ls->endpoint);
146 0
                FREE_OBJ(ls);
147 0
                if (fail != EAFNOSUPPORT)
148 0
                        ARGV_ERR("Could not get socket %s: %s\n",
149
                            la->endpoint, VAS_errtxt(fail));
150 0
                return (0);
151
        }
152
153 1160
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
154 1160
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
155 1160
        VTAILQ_INSERT_TAIL(&UDS_acceptor.socks, ls, vcalist);
156
157 1160
        return (0);
158 1160
}
159
160
int
161 1920
vca_uds_open(char **av, struct listen_arg *la, const char **err)
162
{
163
164 1920
        const struct transport *xp = NULL;
165 1920
        struct passwd *pwd = NULL;
166 1920
        struct group *grp = NULL;
167
        struct uds_perms *perms;
168 1920
        mode_t mode = 0;
169
170 1920
        CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC);
171 1920
        AN(av);
172 1920
        AN(err);
173
174 1920
        if (*la->endpoint != '/' && strchr(la->endpoint, '/') != NULL)
175 0
                ARGV_ERR("Unix domain socket addresses must be"
176
                    " absolute paths in -a (%s)\n", la->endpoint);
177
178 1920
        heritage.min_vcl_version = vmax(heritage.min_vcl_version, 41U);
179
180 2200
        for (int i = 0; av[i] != NULL; i++) {
181
                char *eq, *val;
182
                int len;
183
184 960
                if ((eq = strchr(av[i], '=')) == NULL) {
185 120
                        if (xp != NULL)
186 0
                                ARGV_ERR("Too many protocol sub-args"
187
                                    " in -a (%s)\n", av[i]);
188 120
                        xp = XPORT_Find(av[i]);
189 120
                        if (xp == NULL)
190 40
                                ARGV_ERR("Unknown protocol '%s'\n", av[i]);
191 80
                        continue;
192
                }
193 840
                if (la->endpoint[0] != '/')
194 40
                        ARGV_ERR("Invalid sub-arg %s"
195
                            " in -a\n", av[i]);
196
197 800
                val = eq + 1;
198 800
                len = eq - av[i];
199 800
                assert(len >= 0);
200 800
                if (len == 0)
201 40
                        ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
202
203 760
                if (strncmp(av[i], "user", len) == 0) {
204 40
                        if (pwd != NULL)
205 0
                                ARGV_ERR("Too many user sub-args in -a (%s)\n",
206
                                         av[i]);
207 40
                        pwd = getpwnam(val);
208 40
                        if (pwd == NULL)
209 0
                                ARGV_ERR("Unknown user %s in -a\n", val);
210 40
                        continue;
211
                }
212
213 720
                if (strncmp(av[i], "group", len) == 0) {
214 40
                        if (grp != NULL)
215 0
                                ARGV_ERR("Too many group sub-args in -a (%s)\n",
216
                                         av[i]);
217 40
                        grp = getgrnam(val);
218 40
                        if (grp == NULL)
219 0
                                ARGV_ERR("Unknown group %s in -a\n", val);
220 40
                        continue;
221
                }
222
223 680
                if (strncmp(av[i], "mode", len) == 0) {
224
                        long m;
225
                        char *p;
226
227 520
                        if (mode != 0)
228 40
                                ARGV_ERR("Too many mode sub-args in -a (%s)\n",
229
                                         av[i]);
230 480
                        if (*val == '\0')
231 40
                                ARGV_ERR("Empty mode sub-arg in -a\n");
232 440
                        errno = 0;
233 440
                        m = strtol(val, &p, 8);
234 440
                        if (*p != '\0')
235 120
                                ARGV_ERR("Invalid mode sub-arg %s in -a\n",
236
                                         val);
237 320
                        if (errno)
238 80
                                ARGV_ERR("Cannot parse mode sub-arg %s in -a: "
239
                                         "%s\n", val, VAS_errtxt(errno));
240 240
                        if (m <= 0 || m > 0777)
241 120
                                ARGV_ERR("Mode sub-arg %s out of range in -a\n",
242
                                         val);
243 120
                        mode = (mode_t) m;
244 120
                        continue;
245
                }
246
247 160
                ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
248 0
        }
249
250 1240
        if (xp == NULL)
251 1160
                xp = XPORT_Find("http");
252
253 1240
        AN(xp);
254 1240
        la->transport = xp;
255
256 1240
        if (pwd != NULL || grp != NULL || mode != 0) {
257 80
                ALLOC_OBJ(perms, UDS_PERMS_MAGIC);
258 80
                AN(perms);
259 80
                if (pwd != NULL)
260 40
                        perms->uid = pwd->pw_uid;
261
                else
262 40
                        perms->uid = (uid_t) -1;
263 80
                if (grp != NULL)
264 40
                        perms->gid = grp->gr_gid;
265
                else
266 40
                        perms->gid = (gid_t) -1;
267 80
                perms->mode = mode;
268 80
                la->perms = perms;
269 80
        }
270
271 1240
        return (VUS_resolver(la->endpoint, vca_uds_open_cb, la, err));
272
}
273
274
int
275 37600
vca_uds_reopen(void)
276
{
277
        struct listen_sock *ls;
278 37600
        int err, fail = 0;
279
280 38720
        VTAILQ_FOREACH(ls, &UDS_acceptor.socks, vcalist) {
281 1120
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
282
283 1120
                VJ_master(JAIL_MASTER_PRIVPORT);
284 1120
                err = vca_uds_opensocket(ls);
285 1120
                VJ_master(JAIL_MASTER_LOW);
286
287 1120
                if (err == 0)
288 1120
                        continue;
289
290 0
                fail = vmax(fail, err);
291 0
                MGT_Complain(C_ERR, "Could not reopen listen socket %s: %s",
292 0
                    ls->endpoint, VAS_errtxt(err));
293 0
        }
294
295 37600
        return (fail);
296
}