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  * 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 "vav.h"
51 #include "vcli_serve.h"
52 #include "vsa.h"
53 #include "vss.h"
54 #include "vtcp.h"
55 #include "vus.h"
56 
57 struct listen_arg {
58 	unsigned			magic;
59 #define LISTEN_ARG_MAGIC		0xbb2fc333
60 	VTAILQ_ENTRY(listen_arg)	list;
61 	const char			*endpoint;
62 	const char			*name;
63 	VTAILQ_HEAD(,listen_sock)	socks;
64 	const struct transport		*transport;
65 	const struct uds_perms		*perms;
66 };
67 
68 struct uds_perms {
69 	unsigned	magic;
70 #define UDS_PERMS_MAGIC 0x84fb5635
71 	mode_t		mode;
72 	uid_t		uid;
73 	gid_t		gid;
74 };
75 
76 static VTAILQ_HEAD(,listen_arg) listen_args =
77     VTAILQ_HEAD_INITIALIZER(listen_args);
78 
79 static int
mac_opensocket(struct listen_sock * ls)80 mac_opensocket(struct listen_sock *ls)
81 {
82 	int fail;
83 	struct sockaddr_un uds;
84 
85 	CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
86 	if (ls->sock > 0) {
87 		MCH_Fd_Inherit(ls->sock, NULL);
88 		closefd(&ls->sock);
89 	}
90 	if (!ls->uds)
91 		ls->sock = VTCP_bind(ls->addr, NULL);
92 	else {
93 		uds.sun_family = PF_UNIX;
94 		bprintf(uds.sun_path, "%s", ls->endpoint);
95 		ls->sock = VUS_bind(&uds, NULL);
96 	}
97 	fail = errno;
98 	if (ls->sock < 0) {
99 		AN(fail);
100 		return (fail);
101 	}
102 	if (ls->perms != NULL) {
103 		CHECK_OBJ(ls->perms, UDS_PERMS_MAGIC);
104 		assert(ls->uds);
105 		errno = 0;
106 		if (ls->perms->mode != 0 &&
107 		    chmod(ls->endpoint, ls->perms->mode) != 0)
108 			return (errno);
109 		if (chown(ls->endpoint, ls->perms->uid, ls->perms->gid) != 0)
110 			return (errno);
111 	}
112 	MCH_Fd_Inherit(ls->sock, "sock");
113 	return (0);
114 }
115 
116 /*=====================================================================
117  * Reopen the accept sockets to get rid of listen status.
118  * returns the highest errno encountered, 0 for success
119  */
120 
121 int
MAC_reopen_sockets(void)122 MAC_reopen_sockets(void)
123 {
124 	struct listen_sock *ls;
125 	int err, fail = 0;
126 
127 	VTAILQ_FOREACH(ls, &heritage.socks, list) {
128 		VJ_master(JAIL_MASTER_PRIVPORT);
129 		err = mac_opensocket(ls);
130 		VJ_master(JAIL_MASTER_LOW);
131 		if (err == 0)
132 			continue;
133 		if (err > fail)
134 			fail = err;
135 		MGT_Complain(C_ERR,
136 		    "Could not reopen listen socket %s: %s",
137 		    ls->endpoint, vstrerror(err));
138 	}
139 	return (fail);
140 }
141 
142 /*--------------------------------------------------------------------*/
143 
144 static struct listen_sock *
mk_listen_sock(const struct listen_arg * la,const struct suckaddr * sa)145 mk_listen_sock(const struct listen_arg *la, const struct suckaddr *sa)
146 {
147 	struct listen_sock *ls;
148 	int fail;
149 
150 	ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
151 	AN(ls);
152 	ls->sock = -1;
153 	ls->addr = VSA_Clone(sa);
154 	AN(ls->addr);
155 	ls->endpoint = strdup(la->endpoint);
156 	AN(ls->endpoint);
157 	ls->name = la->name;
158 	ls->transport = la->transport;
159 	ls->perms = la->perms;
160 	if (*la->endpoint == '/')
161 		ls->uds = 1;
162 	VJ_master(JAIL_MASTER_PRIVPORT);
163 	fail = mac_opensocket(ls);
164 	VJ_master(JAIL_MASTER_LOW);
165 	if (fail) {
166 		free(ls->addr);
167 		free(ls->endpoint);
168 		FREE_OBJ(ls);
169 		if (fail != EAFNOSUPPORT)
170 			ARGV_ERR("Could not get socket %s: %s\n",
171 			    la->endpoint, vstrerror(fail));
172 		return (NULL);
173 	}
174 	return (ls);
175 }
176 
v_matchproto_(vss_resolved_f)177 static int v_matchproto_(vss_resolved_f)
178 mac_tcp(void *priv, const struct suckaddr *sa)
179 {
180 	struct listen_arg *la;
181 	struct listen_sock *ls;
182 	char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
183 	char nbuf[VTCP_ADDRBUFSIZE+VTCP_PORTBUFSIZE+2];
184 
185 	CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
186 
187 	VTAILQ_FOREACH(ls, &heritage.socks, list) {
188 		if (!ls->uds && !VSA_Compare(sa, ls->addr))
189 			ARGV_ERR("-a arguments %s and %s have same address\n",
190 			    ls->endpoint, la->endpoint);
191 	}
192 	ls = mk_listen_sock(la, sa);
193 	if (ls == NULL)
194 		return (0);
195 	AZ(ls->uds);
196 	if (VSA_Port(ls->addr) == 0) {
197 		/*
198 		 * If the argv port number is zero, we adopt whatever
199 		 * port number this VTCP_bind() found us, as if
200 		 * it was specified by the argv.
201 		 */
202 		free(ls->addr);
203 		ls->addr = VTCP_my_suckaddr(ls->sock);
204 		VTCP_myname(ls->sock, abuf, sizeof abuf,
205 		    pbuf, sizeof pbuf);
206 		bprintf(nbuf, "%s:%s", abuf, pbuf);
207 		REPLACE(ls->endpoint, nbuf);
208 	}
209 	VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
210 	VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
211 	return (0);
212 }
213 
v_matchproto_(vus_resolved_f)214 static int v_matchproto_(vus_resolved_f)
215 mac_uds(void *priv, const struct sockaddr_un *uds)
216 {
217 	struct listen_arg *la;
218 	struct listen_sock *ls;
219 
220 	CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
221 
222 	VTAILQ_FOREACH(ls, &heritage.socks, list) {
223 		if (ls->uds && strcmp(uds->sun_path, ls->endpoint) == 0)
224 			ARGV_ERR("-a arguments %s and %s have same address\n",
225 			    ls->endpoint, la->endpoint);
226 	}
227 	ls = mk_listen_sock(la, bogo_ip);
228 	if (ls == NULL)
229 		return (0);
230 	AN(ls->uds);
231 	VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
232 	VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
233 	return (0);
234 }
235 
236 void
MAC_Arg(const char * spec)237 MAC_Arg(const char *spec)
238 {
239 	char **av;
240 	struct listen_arg *la;
241 	const char *err;
242 	int error;
243 	const struct transport *xp = NULL;
244 	const char *name;
245 	char name_buf[8];
246 	static unsigned seq = 0;
247 	struct passwd *pwd = NULL;
248 	struct group *grp = NULL;
249 	mode_t mode = 0;
250 	struct uds_perms *perms;
251 
252 	av = MGT_NamedArg(spec, &name, "-a");
253 	AN(av);
254 
255 	ALLOC_OBJ(la, LISTEN_ARG_MAGIC);
256 	AN(la);
257 	VTAILQ_INIT(&la->socks);
258 	VTAILQ_INSERT_TAIL(&listen_args, la, list);
259 	la->endpoint = av[1];
260 
261 	if (name == NULL) {
262 		bprintf(name_buf, "a%u", seq++);
263 		name = strdup(name_buf);
264 		AN(name);
265 	}
266 	la->name = name;
267 
268 	if (*la->endpoint != '/' && strchr(la->endpoint, '/') != NULL)
269 		ARGV_ERR("Unix domain socket addresses must be"
270 		    " absolute paths in -a (%s)\n", la->endpoint);
271 
272 	if (*la->endpoint == '/' && heritage.min_vcl_version < 41)
273 		heritage.min_vcl_version = 41;
274 
275 	for (int i = 2; av[i] != NULL; i++) {
276 		char *eq, *val;
277 		int len;
278 
279 		if ((eq = strchr(av[i], '=')) == NULL) {
280 			if (xp != NULL)
281 				ARGV_ERR("Too many protocol sub-args"
282 				    " in -a (%s)\n", av[i]);
283 			xp = XPORT_Find(av[i]);
284 			if (xp == NULL)
285 				ARGV_ERR("Unknown protocol '%s'\n", av[i]);
286 			continue;
287 		}
288 		if (la->endpoint[0] != '/')
289 			ARGV_ERR("Invalid sub-arg %s for IP addresses"
290 			    " in -a\n", av[i]);
291 
292 		val = eq + 1;
293 		len = eq - av[i];
294 		assert(len >= 0);
295 		if (len == 0)
296 			ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
297 
298 		if (strncmp(av[i], "user", len) == 0) {
299 			if (pwd != NULL)
300 				ARGV_ERR("Too many user sub-args in -a (%s)\n",
301 					 av[i]);
302 			pwd = getpwnam(val);
303 			if (pwd == NULL)
304 				ARGV_ERR("Unknown user %s in -a\n", val);
305 			continue;
306 		}
307 
308 		if (strncmp(av[i], "group", len) == 0) {
309 			if (grp != NULL)
310 				ARGV_ERR("Too many group sub-args in -a (%s)\n",
311 					 av[i]);
312 			grp = getgrnam(val);
313 			if (grp == NULL)
314 				ARGV_ERR("Unknown group %s in -a\n", val);
315 			continue;
316 		}
317 
318 		if (strncmp(av[i], "mode", len) == 0) {
319 			long m;
320 			char *p;
321 
322 			if (mode != 0)
323 				ARGV_ERR("Too many mode sub-args in -a (%s)\n",
324 					 av[i]);
325 			if (*val == '\0')
326 				ARGV_ERR("Empty mode sub-arg in -a\n");
327 			errno = 0;
328 			m = strtol(val, &p, 8);
329 			if (*p != '\0')
330 				ARGV_ERR("Invalid mode sub-arg %s in -a\n",
331 					 val);
332 			if (errno)
333 				ARGV_ERR("Cannot parse mode sub-arg %s in -a: "
334 					 "%s\n", val, vstrerror(errno));
335 			if (m <= 0 || m > 0777)
336 				ARGV_ERR("Mode sub-arg %s out of range in -a\n",
337 					 val);
338 			mode = (mode_t) m;
339 			continue;
340 		}
341 
342 		ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
343 	}
344 
345 	if (xp == NULL)
346 		xp = XPORT_Find("http");
347 	AN(xp);
348 	la->transport = xp;
349 
350 	if (pwd != NULL || grp != NULL || mode != 0) {
351 		ALLOC_OBJ(perms, UDS_PERMS_MAGIC);
352 		AN(perms);
353 		if (pwd != NULL)
354 			perms->uid = pwd->pw_uid;
355 		else
356 			perms->uid = (uid_t) -1;
357 		if (grp != NULL)
358 			perms->gid = grp->gr_gid;
359 		else
360 			perms->gid = (gid_t) -1;
361 		perms->mode = mode;
362 		la->perms = perms;
363 	}
364 	else
365 		AZ(la->perms);
366 
367 	if (*la->endpoint != '/')
368 		error = VSS_resolver(av[1], "80", mac_tcp, la, &err);
369 	else
370 		error = VUS_resolver(av[1], mac_uds, la, &err);
371 
372 	if (VTAILQ_EMPTY(&la->socks) || error)
373 		ARGV_ERR("Got no socket(s) for %s\n", av[1]);
374 	VAV_Free(av);
375 }
376