GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/privsep.c Lines: 0 499 0.0 %
Date: 2017-11-07 Branches: 0 260 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: privsep.c,v 1.23 2017/04/19 05:36:13 natano Exp $ */
2
3
/*
4
 * Copyright (c) 2010 Yasuoka Masahiko <yasuoka@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
#include <sys/queue.h>
19
#include <sys/uio.h>
20
#include <sys/socket.h>
21
#include <sys/ioctl.h>
22
#include <arpa/inet.h>
23
#include <net/if.h>
24
#include <net/pfkeyv2.h>
25
#include <netinet/in.h>
26
27
#include <errno.h>
28
#include <fcntl.h>
29
#include <imsg.h>
30
#include <stddef.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <unistd.h>
34
35
#include "pathnames.h"
36
#include "privsep.h"
37
38
#include "npppd.h"
39
#include "ppp.h"
40
41
#ifndef nitems
42
#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
43
#endif
44
45
enum imsg_code {
46
	PRIVSEP_OK,
47
	PRIVSEP_OPEN,
48
	PRIVSEP_SOCKET,
49
	PRIVSEP_BIND,
50
	PRIVSEP_SENDTO,
51
	PRIVSEP_UNLINK,
52
	PRIVSEP_GET_USER_INFO,
53
	PRIVSEP_GET_IF_ADDR,
54
	PRIVSEP_SET_IF_ADDR,
55
	PRIVSEP_DEL_IF_ADDR,
56
	PRIVSEP_GET_IF_FLAGS,
57
	PRIVSEP_SET_IF_FLAGS
58
};
59
60
struct PRIVSEP_OPEN_ARG {
61
	char			 path[PATH_MAX];
62
	int			 flags;
63
};
64
65
struct PRIVSEP_SOCKET_ARG {
66
	int			 domain;
67
	int			 type;
68
	int			 protocol;
69
};
70
71
struct PRIVSEP_BIND_ARG {
72
	struct sockaddr_storage	 name;
73
	socklen_t		 namelen;
74
};
75
76
struct PRIVSEP_SENDTO_ARG {
77
	size_t			 len;
78
	int			 flags;
79
	struct sockaddr_storage	 to;
80
	socklen_t		 tolen;
81
	u_char			 msg[0];
82
};
83
84
struct PRIVSEP_UNLINK_ARG {
85
	char			 path[PATH_MAX];
86
};
87
88
struct PRIVSEP_GET_USER_INFO_ARG {
89
	char			 path[PATH_MAX];
90
	char			 username[MAX_USERNAME_LENGTH];
91
};
92
93
struct PRIVSEP_GET_IF_ADDR_ARG {
94
	char			 ifname[IFNAMSIZ];
95
};
96
97
struct PRIVSEP_GET_IF_ADDR_RESP {
98
	int			 retval;
99
	int			 rerrno;
100
	struct in_addr		 addr;
101
};
102
103
struct PRIVSEP_SET_IF_ADDR_ARG {
104
	char			 ifname[IFNAMSIZ];
105
	struct in_addr		 addr;
106
};
107
108
struct PRIVSEP_DEL_IF_ADDR_ARG {
109
	char			 ifname[IFNAMSIZ];
110
};
111
112
struct PRIVSEP_GET_IF_FLAGS_ARG {
113
	char			 ifname[IFNAMSIZ];
114
	int			 flags;
115
};
116
117
struct PRIVSEP_GET_IF_FLAGS_RESP {
118
	int			 retval;
119
	int			 rerrno;
120
	int			 flags;
121
};
122
123
struct PRIVSEP_SET_IF_FLAGS_ARG {
124
	char			 ifname[IFNAMSIZ];
125
	int			 flags;
126
};
127
128
struct PRIVSEP_COMMON_RESP {
129
	int			 retval;
130
	int			 rerrno;
131
};
132
133
struct PRIVSEP_GET_USER_INFO_RESP {
134
	int			 retval;
135
	int			 rerrno;
136
	char			 password[MAX_PASSWORD_LENGTH];
137
	struct in_addr		 framed_ip_address;
138
	struct in_addr		 framed_ip_netmask;
139
	char			 calling_number[NPPPD_PHONE_NUMBER_LEN + 1];
140
};
141
142
static void	 privsep_priv_main (int);
143
static void	 privsep_priv_dispatch_imsg (struct imsgbuf *);
144
int		 imsg_read_and_get(struct imsgbuf *, struct imsg *);
145
static int	 startswith(const char *, const char *);
146
static int	 privsep_recvfd (void);
147
static int	 privsep_common_resp (void);
148
149
static int	 privsep_npppd_check_open (struct PRIVSEP_OPEN_ARG *);
150
static int	 privsep_npppd_check_socket (struct PRIVSEP_SOCKET_ARG *);
151
static int	 privsep_npppd_check_bind (struct PRIVSEP_BIND_ARG *);
152
static int	 privsep_npppd_check_sendto (struct PRIVSEP_SENDTO_ARG *);
153
static int	 privsep_npppd_check_unlink (struct PRIVSEP_UNLINK_ARG *);
154
static int	 privsep_npppd_check_get_user_info (
155
		    struct PRIVSEP_GET_USER_INFO_ARG *);
156
static int	 privsep_npppd_check_get_if_addr (
157
		    struct PRIVSEP_GET_IF_ADDR_ARG *);
158
static int	 privsep_npppd_check_set_if_addr (
159
		    struct PRIVSEP_SET_IF_ADDR_ARG *);
160
static int	 privsep_npppd_check_del_if_addr (
161
		    struct PRIVSEP_DEL_IF_ADDR_ARG *);
162
static int	 privsep_npppd_check_get_if_flags (
163
		    struct PRIVSEP_GET_IF_FLAGS_ARG *);
164
static int	 privsep_npppd_check_set_if_flags (
165
		    struct PRIVSEP_SET_IF_FLAGS_ARG *);
166
167
static int		 privsep_sock = -1;
168
static struct imsgbuf	 privsep_ibuf;
169
static pid_t		 privsep_pid;
170
171
int
172
privsep_init(void)
173
{
174
	pid_t	 pid;
175
	int	 pairsock[2];
176
177
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pairsock) == -1)
178
		return (-1);
179
180
	if ((pid = fork()) < 0)
181
		goto fail;
182
	else if (pid == 0) {
183
		setsid();
184
		/* privileged process */
185
		setproctitle("[priv]");
186
		close(pairsock[1]);
187
		privsep_priv_main(pairsock[0]);
188
		_exit(0);
189
		/* NOTREACHED */
190
	}
191
	close(pairsock[0]);
192
	privsep_sock = pairsock[1];
193
	privsep_pid = pid;
194
	imsg_init(&privsep_ibuf, privsep_sock);
195
196
	return (0);
197
	/* NOTREACHED */
198
fail:
199
	if (pairsock[0] >= 0) {
200
		close(pairsock[0]);
201
		close(pairsock[1]);
202
	}
203
204
	return (-1);
205
}
206
207
void
208
privsep_fini(void)
209
{
210
	imsg_clear(&privsep_ibuf);
211
	if (privsep_sock >= 0) {
212
		close(privsep_sock);
213
		privsep_sock = -1;
214
	}
215
}
216
217
pid_t
218
privsep_priv_pid(void)
219
{
220
	return (privsep_pid);
221
}
222
223
/***********************************************************************
224
 * Functions for from jail
225
 ***********************************************************************/
226
int
227
priv_bind(int sock, const struct sockaddr *name, socklen_t namelen)
228
{
229
	struct PRIVSEP_BIND_ARG	 a;
230
231
	if (namelen > sizeof(a.name)) {
232
		errno = EINVAL;
233
		return (-1);
234
	}
235
	if ((sock = dup(sock)) == -1)
236
		return (-1);
237
238
	memcpy(&a.name, name, namelen);
239
	a.namelen = namelen;
240
241
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_BIND, 0, 0, sock,
242
	    &a, sizeof(a));
243
	imsg_flush(&privsep_ibuf);
244
245
	return (privsep_common_resp());
246
}
247
248
int
249
priv_socket(int domain, int type, int protocol)
250
{
251
	struct PRIVSEP_SOCKET_ARG a;
252
253
	a.domain = domain;
254
	a.type = type;
255
	a.protocol = protocol;
256
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SOCKET, 0, 0, -1,
257
	    &a, sizeof(a));
258
	imsg_flush(&privsep_ibuf);
259
260
	return (privsep_recvfd());
261
}
262
263
int
264
priv_open(const char *path, int flags)
265
{
266
	struct PRIVSEP_OPEN_ARG a;
267
268
	strlcpy(a.path, path, sizeof(a.path));
269
	a.flags = flags;
270
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_OPEN, 0, 0, -1,
271
	    &a, sizeof(a));
272
	imsg_flush(&privsep_ibuf);
273
274
	return (privsep_recvfd());
275
}
276
277
FILE *
278
priv_fopen(const char *path)
279
{
280
	int f;
281
	FILE *fp;
282
283
	if ((f = priv_open(path, O_RDONLY)) < 0)
284
		return (NULL);
285
286
	if ((fp = fdopen(f, "r")) == NULL) {
287
		close(f);
288
		return (NULL);
289
	} else
290
		return (fp);
291
}
292
293
int
294
priv_sendto(int s, const void *msg, int len, int flags,
295
    const struct sockaddr *to, socklen_t tolen)
296
{
297
	struct PRIVSEP_SENDTO_ARG	 a;
298
	struct iovec			 iov[2];
299
300
	if (tolen > sizeof(a.to)) {
301
		errno = EINVAL;
302
		return (-1);
303
	}
304
	if ((s = dup(s)) == -1)
305
		return (-1);
306
307
	a.len = len;
308
	a.flags = flags;
309
	a.tolen = tolen;
310
	if (tolen > 0)
311
		memcpy(&a.to, to, tolen);
312
	iov[0].iov_base = &a;
313
	iov[0].iov_len = offsetof(struct PRIVSEP_SENDTO_ARG, msg);
314
	iov[1].iov_base = (void *)msg;
315
	iov[1].iov_len = len;
316
317
	(void)imsg_composev(&privsep_ibuf, PRIVSEP_SENDTO, 0, 0, s,
318
	    iov, nitems(iov));
319
	imsg_flush(&privsep_ibuf);
320
321
	return (privsep_common_resp());
322
}
323
324
int
325
priv_send(int s, const void *msg, int len, int flags)
326
{
327
	return (priv_sendto(s, msg, len, flags, NULL, 0));
328
}
329
330
int
331
priv_unlink(const char *path)
332
{
333
	struct PRIVSEP_UNLINK_ARG a;
334
335
	strlcpy(a.path, path, sizeof(a.path));
336
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_UNLINK, 0, 0, -1,
337
	    &a, sizeof(a));
338
	imsg_flush(&privsep_ibuf);
339
340
	return (privsep_common_resp());
341
}
342
343
int
344
priv_get_user_info(const char *path, const char *username,
345
    npppd_auth_user **puser)
346
{
347
	struct imsg				 imsg;
348
	ssize_t					 n;
349
	struct PRIVSEP_GET_USER_INFO_RESP	*r;
350
	struct PRIVSEP_GET_USER_INFO_ARG	 a;
351
	npppd_auth_user				*u;
352
	char					*cp;
353
	int					 sz;
354
355
	strlcpy(a.path, path, sizeof(a.path));
356
	strlcpy(a.username, username, sizeof(a.username));
357
358
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_USER_INFO, 0, 0, -1,
359
	    &a, sizeof(a));
360
	imsg_flush(&privsep_ibuf);
361
362
	if ((n = imsg_read_and_get(&privsep_ibuf, &imsg)) == -1)
363
		return (-1);
364
	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r)) {
365
		errno = EACCES;
366
		goto on_error;
367
	}
368
	r = imsg.data;
369
	if (r->retval != 0) {
370
		errno = r->rerrno;
371
		goto on_error;
372
	}
373
374
	sz = strlen(username) + strlen(r->password) +
375
	    strlen(r->calling_number) + 3;
376
377
	if ((u = malloc(offsetof(npppd_auth_user, space[sz]))) == NULL)
378
		goto on_error;
379
380
	cp = u->space;
381
382
	u->username = cp;
383
	n = strlcpy(cp, username, sz);
384
	cp += ++n; sz -= n;
385
386
	u->password = cp;
387
	n = strlcpy(cp, r->password, sz);
388
	cp += ++n; sz -= n;
389
390
	u->calling_number = cp;
391
	n = strlcpy(cp, r->calling_number, sz);
392
	cp += ++n; sz -= n;
393
394
	u->framed_ip_address = r->framed_ip_address;
395
	u->framed_ip_netmask = r->framed_ip_netmask;
396
397
	*puser = u;
398
	imsg_free(&imsg);
399
400
	return (0);
401
402
on_error:
403
	imsg_free(&imsg);
404
	return (-1);
405
}
406
407
int
408
priv_get_if_addr(const char *ifname, struct in_addr *addr)
409
{
410
	struct PRIVSEP_GET_IF_ADDR_ARG   a;
411
	struct PRIVSEP_GET_IF_ADDR_RESP *r;
412
	struct imsg			 imsg;
413
	int				 retval = -1;
414
415
	strlcpy(a.ifname, ifname, sizeof(a.ifname));
416
417
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_IF_ADDR, 0, 0, -1,
418
	    &a, sizeof(a));
419
	imsg_flush(&privsep_ibuf);
420
421
	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
422
		return (-1);
423
424
	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
425
		errno = EACCES;
426
	else {
427
		r = imsg.data;
428
		if (r->retval != -1)
429
			*addr = r->addr;
430
		else
431
			errno = r->rerrno;
432
		retval = r->retval;
433
	}
434
	imsg_free(&imsg);
435
436
	return (retval);
437
}
438
439
int
440
priv_delete_if_addr(const char *ifname)
441
{
442
	struct PRIVSEP_DEL_IF_ADDR_ARG   a;
443
444
	strlcpy(a.ifname, ifname, sizeof(a.ifname));
445
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_DEL_IF_ADDR, 0, 0, -1,
446
	    &a, sizeof(a));
447
	imsg_flush(&privsep_ibuf);
448
449
	return (privsep_common_resp());
450
}
451
452
int
453
priv_set_if_addr(const char *ifname, struct in_addr *addr)
454
{
455
	struct PRIVSEP_SET_IF_ADDR_ARG   a;
456
457
	strlcpy(a.ifname, ifname, sizeof(a.ifname));
458
	a.addr = *addr;
459
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SET_IF_ADDR, 0, 0, -1,
460
	    &a, sizeof(a));
461
	imsg_flush(&privsep_ibuf);
462
463
	return (privsep_common_resp());
464
}
465
466
int
467
priv_get_if_flags(const char *ifname, int *pflags)
468
{
469
	struct PRIVSEP_GET_IF_FLAGS_ARG		 a;
470
	struct PRIVSEP_GET_IF_FLAGS_RESP	*r;
471
	struct imsg				 imsg;
472
	int					 retval = -1;
473
474
	strlcpy(a.ifname, ifname, sizeof(a.ifname));
475
	a.flags = 0;
476
477
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_GET_IF_FLAGS, 0, 0, -1,
478
	    &a, sizeof(a));
479
	imsg_flush(&privsep_ibuf);
480
481
	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
482
		return (-1);
483
	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
484
		errno = EACCES;
485
	else {
486
		r = imsg.data;
487
		*pflags = r->flags;
488
		if (r->retval != 0)
489
			errno = r->rerrno;
490
		retval = r->retval;
491
	}
492
	imsg_free(&imsg);
493
494
	return (retval);
495
}
496
497
int
498
priv_set_if_flags(const char *ifname, int flags)
499
{
500
	struct PRIVSEP_SET_IF_FLAGS_ARG   a;
501
502
	strlcpy(a.ifname, ifname, sizeof(a.ifname));
503
	a.flags = flags;
504
505
	(void)imsg_compose(&privsep_ibuf, PRIVSEP_SET_IF_FLAGS, 0, 0, -1,
506
	    &a, sizeof(a));
507
	imsg_flush(&privsep_ibuf);
508
509
	return (privsep_common_resp());
510
}
511
512
static int
513
privsep_recvfd(void)
514
{
515
	struct PRIVSEP_COMMON_RESP	*r;
516
	struct imsg			 imsg;
517
	int				 retval = -1;
518
519
	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1)
520
		return (-1);
521
	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
522
		errno = EACCES;
523
	else {
524
		r = imsg.data;
525
		retval = r->retval;
526
		if (r->retval != 0)
527
			errno = r->rerrno;
528
		else
529
			retval = imsg.fd;
530
	}
531
	imsg_free(&imsg);
532
533
	return (retval);
534
}
535
536
static int
537
privsep_common_resp(void)
538
{
539
	struct PRIVSEP_COMMON_RESP	*r;
540
	struct imsg			 imsg;
541
	int				 retval = -1;
542
543
	if (imsg_read_and_get(&privsep_ibuf, &imsg) == -1) {
544
		errno = EACCES;
545
		return (-1);
546
	}
547
	if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*r))
548
		errno = EACCES;
549
	else {
550
		r = imsg.data;
551
		if (r->retval != 0)
552
			errno = r->rerrno;
553
		retval = r->retval;
554
	}
555
	imsg_free(&imsg);
556
557
	return (retval);
558
}
559
560
/***********************************************************************
561
 * privileged process
562
 ***********************************************************************/
563
static void
564
privsep_priv_main(int sock)
565
{
566
	struct imsgbuf	 ibuf;
567
568
	imsg_init(&ibuf, sock);
569
	privsep_priv_dispatch_imsg(&ibuf);
570
	imsg_clear(&ibuf);
571
	close(sock);
572
573
	exit(EXIT_SUCCESS);
574
}
575
576
static void
577
privsep_priv_dispatch_imsg(struct imsgbuf *ibuf)
578
{
579
	struct imsg	 imsg;
580
581
	for (;;) {
582
		if (imsg_read_and_get(ibuf, &imsg) == -1)
583
			return;
584
585
		switch (imsg.hdr.type) {
586
		case PRIVSEP_OPEN: {
587
			int				 f = -1;
588
			struct PRIVSEP_OPEN_ARG		*a = imsg.data;
589
			struct PRIVSEP_COMMON_RESP	 r = { -1, 0 };
590
591
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
592
				r.rerrno = EINVAL;
593
			else if (privsep_npppd_check_open(a))
594
				r.rerrno = EACCES;
595
			else {
596
				if ((f = open(a->path, a->flags & ~O_CREAT))
597
				    == -1)
598
					r.rerrno = errno;
599
				else
600
					r.retval = 0;
601
			}
602
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, f,
603
			    &r, sizeof(r));
604
			imsg_flush(ibuf);
605
		    }
606
			break;
607
		case PRIVSEP_SOCKET: {
608
			int				 s = -1;
609
			struct PRIVSEP_SOCKET_ARG	*a = imsg.data;
610
			struct PRIVSEP_COMMON_RESP	 r = { -1, 0 };
611
612
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
613
				r.rerrno = EINVAL;
614
			else if (privsep_npppd_check_socket(a))
615
				r.rerrno = EACCES;
616
			else {
617
				if ((s = socket(a->domain, a->type,
618
				    a->protocol)) == -1)
619
					r.rerrno = errno;
620
				else
621
					r.retval = 0;
622
			}
623
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, s,
624
			    &r, sizeof(r));
625
			imsg_flush(ibuf);
626
		    }
627
			break;
628
		case PRIVSEP_UNLINK: {
629
			struct PRIVSEP_UNLINK_ARG *a = imsg.data;
630
			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
631
632
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
633
				r.rerrno = EINVAL;
634
			else if (privsep_npppd_check_unlink(a))
635
				r.rerrno = EACCES;
636
			else {
637
				if ((r.retval = unlink(a->path)) != 0)
638
					r.rerrno = errno;
639
			}
640
641
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
642
			    &r, sizeof(r));
643
			imsg_flush(ibuf);
644
		    }
645
			break;
646
		case PRIVSEP_BIND: {
647
			struct PRIVSEP_BIND_ARG	*a = imsg.data;
648
			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
649
650
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a) ||
651
			    imsg.fd < 0)
652
				r.rerrno = EINVAL;
653
			else if (privsep_npppd_check_bind(a))
654
				r.rerrno = EACCES;
655
			else {
656
				if ((r.retval = bind(imsg.fd,
657
				    (struct sockaddr *)&a->name, a->namelen))
658
				    != 0)
659
					r.rerrno = errno;
660
				close(imsg.fd);
661
			}
662
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
663
			    &r, sizeof(r));
664
			imsg_flush(ibuf);
665
		    }
666
			break;
667
		case PRIVSEP_GET_USER_INFO: {
668
			struct PRIVSEP_GET_USER_INFO_ARG *a = imsg.data;
669
			struct PRIVSEP_GET_USER_INFO_RESP r;
670
			int   retval;
671
			char *str, *buf, *db[2] = { NULL, NULL };
672
673
			memset(&r, 0, sizeof(r));
674
			r.retval = -1;
675
			r.framed_ip_address.s_addr = INADDR_NAS_SELECT;
676
			r.framed_ip_netmask.s_addr = INADDR_NONE;
677
			str = buf = NULL;
678
679
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a)) {
680
				r.rerrno = EINVAL;
681
				(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
682
				    &r, sizeof(r));
683
				return;
684
			}
685
			db[0] = a->path;
686
			if (privsep_npppd_check_get_user_info(a))
687
				r.rerrno = EACCES;
688
			else if ((retval = cgetent(&buf, db, a->username))
689
			    == 0) {
690
				if ((retval = cgetstr(buf, "password", &str))
691
				    >= 0) {
692
					if (strlcpy(r.password, str,
693
					    sizeof(r.password)) >=
694
					    sizeof(r.password))
695
						goto on_broken_entry;
696
					free(str);
697
					str = NULL;
698
				}
699
				if ((retval = cgetstr(buf, "calling-number",
700
				    &str)) >= 0) {
701
					if (strlcpy(r.calling_number, str,
702
					    sizeof(r.calling_number)) >=
703
					    sizeof(r.calling_number))
704
						goto on_broken_entry;
705
					free(str);
706
					str = NULL;
707
				}
708
				if ((retval = cgetstr(buf, "framed-ip-address",
709
				    &str)) >= 0) {
710
					if (inet_aton(str,
711
					    &r.framed_ip_address) != 1)
712
						goto on_broken_entry;
713
					free(str);
714
					str = NULL;
715
				}
716
717
				if ((retval = cgetstr(buf, "framed-ip-netmask",
718
				    &str)) >= 0) {
719
					if (inet_aton(str,
720
					    &r.framed_ip_netmask) != 1)
721
						goto on_broken_entry;
722
					free(str);
723
					str = NULL;
724
				}
725
				cgetclose();
726
				free(buf);
727
				r.retval = 0;
728
			} else if (retval == -1) {
729
				buf = NULL;
730
on_broken_entry:
731
				free(buf);
732
				free(str);
733
				r.retval = -1;
734
				r.rerrno = ENOENT;
735
			} else {
736
				r.retval = retval;
737
				r.rerrno = errno;
738
			}
739
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
740
			    &r, sizeof(r));
741
			imsg_flush(ibuf);
742
		    }
743
			break;
744
		case PRIVSEP_SENDTO: {
745
			struct PRIVSEP_SENDTO_ARG *a = imsg.data;
746
			struct PRIVSEP_COMMON_RESP r = { -1, 0 };
747
748
			if (imsg.hdr.len < IMSG_HEADER_SIZE + sizeof(*a) ||
749
			    imsg.hdr.len < IMSG_HEADER_SIZE +
750
				offsetof(struct PRIVSEP_SENDTO_ARG,
751
					msg[a->len]))
752
				r.rerrno = EMSGSIZE;
753
			else if (imsg.fd < 0)
754
				r.rerrno = EINVAL;
755
			else if (privsep_npppd_check_sendto(a))
756
				r.rerrno = EACCES;
757
			else {
758
				if (a->tolen > 0)
759
					r.retval = sendto(imsg.fd, a->msg,
760
					    a->len, a->flags,
761
					    (struct sockaddr *)&a->to,
762
					    a->tolen);
763
				else
764
					r.retval = send(imsg.fd, a->msg, a->len,
765
					    a->flags);
766
				if (r.retval < 0)
767
					r.rerrno = errno;
768
				close(imsg.fd);
769
			}
770
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
771
			    &r, sizeof(r));
772
			imsg_flush(ibuf);
773
		    }
774
			break;
775
		case PRIVSEP_GET_IF_ADDR: {
776
			int                              s;
777
			struct ifreq                     ifr;
778
			struct PRIVSEP_GET_IF_ADDR_ARG  *a = imsg.data;
779
			struct PRIVSEP_GET_IF_ADDR_RESP  r;
780
781
			memset(&r, 0, sizeof(r));
782
			r.retval = -1;
783
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
784
				r.rerrno = EINVAL;
785
			else if (privsep_npppd_check_get_if_addr(a))
786
				r.rerrno = EACCES;
787
			else {
788
				memset(&ifr, 0, sizeof(ifr));
789
				strlcpy(ifr.ifr_name, a->ifname,
790
				    sizeof(ifr.ifr_name));
791
				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
792
				    ioctl(s, SIOCGIFADDR, &ifr) != 0) {
793
					r.retval = -1;
794
					r.rerrno = errno;
795
				} else {
796
					r.retval = 0;
797
					r.addr = ((struct sockaddr_in *)
798
					    &ifr.ifr_addr)->sin_addr;
799
				}
800
				if (s >= 0)
801
					close(s);
802
			}
803
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
804
			    &r, sizeof(r));
805
			imsg_flush(ibuf);
806
		    }
807
			break;
808
		case PRIVSEP_SET_IF_ADDR: {
809
			int                              s;
810
			struct ifaliasreq                ifra;
811
			struct PRIVSEP_SET_IF_ADDR_ARG  *a = imsg.data;
812
			struct PRIVSEP_COMMON_RESP       r = { -1, 0 };
813
			struct sockaddr_in              *sin4;
814
815
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
816
				r.rerrno = EINVAL;
817
			else if (privsep_npppd_check_set_if_addr(a))
818
				r.rerrno = EACCES;
819
			else {
820
				memset(&ifra, 0, sizeof(ifra));
821
				strlcpy(ifra.ifra_name, a->ifname,
822
				    sizeof(ifra.ifra_name));
823
824
				sin4 = (struct sockaddr_in *)&ifra.ifra_addr;
825
				sin4->sin_family = AF_INET;
826
				sin4->sin_len = sizeof(struct sockaddr_in);
827
				sin4->sin_addr = a->addr;
828
829
				sin4 = (struct sockaddr_in *)&ifra.ifra_mask;
830
				sin4->sin_family = AF_INET;
831
				sin4->sin_len = sizeof(struct sockaddr_in);
832
				sin4->sin_addr.s_addr = 0xffffffffUL;
833
834
				sin4 =
835
				    (struct sockaddr_in *)&ifra.ifra_broadaddr;
836
				sin4->sin_family = AF_INET;
837
				sin4->sin_len = sizeof(struct sockaddr_in);
838
				sin4->sin_addr.s_addr = 0;
839
840
				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
841
				    ioctl(s, SIOCAIFADDR, &ifra) != 0) {
842
					r.retval = -1;
843
					r.rerrno = errno;
844
				} else
845
					r.retval = 0;
846
				if (s >= 0)
847
					close(s);
848
			}
849
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
850
			    &r, sizeof(r));
851
			imsg_flush(ibuf);
852
		    }
853
			break;
854
		case PRIVSEP_DEL_IF_ADDR: {
855
			int                              s;
856
			struct ifreq                     ifr;
857
			struct PRIVSEP_DEL_IF_ADDR_ARG  *a = imsg.data;
858
			struct PRIVSEP_COMMON_RESP       r = { 0, -1 };
859
860
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
861
				r.rerrno = EINVAL;
862
			else if (privsep_npppd_check_del_if_addr(a))
863
				r.rerrno = EACCES;
864
			else {
865
				memset(&ifr, 0, sizeof(ifr));
866
				strlcpy(ifr.ifr_name, a->ifname,
867
				    sizeof(ifr.ifr_name));
868
				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
869
				    ioctl(s, SIOCDIFADDR, &ifr) != 0) {
870
					r.retval = -1;
871
					r.rerrno = errno;
872
				} else
873
					r.retval = 0;
874
				if (s >= 0)
875
					close(s);
876
			}
877
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
878
			    &r, sizeof(r));
879
			imsg_flush(ibuf);
880
		    }
881
			break;
882
		case PRIVSEP_GET_IF_FLAGS: {
883
			int                               s;
884
			struct ifreq                      ifr;
885
			struct PRIVSEP_GET_IF_FLAGS_ARG  *a = imsg.data;
886
			struct PRIVSEP_GET_IF_FLAGS_RESP  r;
887
888
			memset(&r, 0, sizeof(r));
889
			r.retval = -1;
890
891
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
892
				r.rerrno = EINVAL;
893
			else if (privsep_npppd_check_get_if_flags(a)) {
894
				r.rerrno = EACCES;
895
			} else {
896
				memset(&ifr, 0, sizeof(ifr));
897
				strlcpy(ifr.ifr_name, a->ifname,
898
				    sizeof(ifr.ifr_name));
899
				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
900
				    ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
901
					r.retval = -1;
902
					r.rerrno = errno;
903
				} else {
904
					r.retval = 0;
905
					r.flags = ifr.ifr_flags;
906
				}
907
				if (s >= 0)
908
					close(s);
909
			}
910
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
911
			    &r, sizeof(r));
912
			imsg_flush(ibuf);
913
		    }
914
			break;
915
		case PRIVSEP_SET_IF_FLAGS: {
916
			int                               s;
917
			struct ifreq                      ifr;
918
			struct PRIVSEP_SET_IF_FLAGS_ARG  *a = imsg.data;
919
			struct PRIVSEP_COMMON_RESP        r = { -1, 0 };
920
921
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(*a))
922
				r.rerrno = EINVAL;
923
			else if (privsep_npppd_check_set_if_flags(a))
924
				r.rerrno = EACCES;
925
			else {
926
				memset(&ifr, 0, sizeof(ifr));
927
				strlcpy(ifr.ifr_name, a->ifname,
928
				    sizeof(ifr.ifr_name));
929
				ifr.ifr_flags = a->flags;
930
				if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
931
				    ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {
932
					r.retval = -1;
933
					r.rerrno = errno;
934
				} else
935
					r.retval = 0;
936
				if (s >= 0)
937
					close(s);
938
			}
939
			(void)imsg_compose(ibuf, PRIVSEP_OK, 0, 0, -1,
940
			    &r, sizeof(r));
941
			imsg_flush(ibuf);
942
		    }
943
			break;
944
		}
945
		imsg_free(&imsg);
946
	}
947
}
948
949
int
950
imsg_read_and_get(struct imsgbuf *ibuf, struct imsg *imsg)
951
{
952
	ssize_t	 n;
953
954
	for (;;) {
955
		if ((n = imsg_read(ibuf)) <= 0) {
956
			if (n == -1 && (errno == EAGAIN || errno == EINTR))
957
				continue;
958
			return (-1);
959
		}
960
		if ((n = imsg_get(ibuf, imsg)) < 0)
961
			return (-1);
962
		if (n == 0)
963
			continue;
964
		break;
965
	}
966
967
	return (0);
968
}
969
970
static int
971
startswith(const char *str, const char *prefix)
972
{
973
	return (strncmp(str, prefix, strlen(prefix)) == 0)? 1 : 0;
974
}
975
976
static int
977
privsep_npppd_check_open(struct PRIVSEP_OPEN_ARG *arg)
978
{
979
	int i;
980
	struct _allow_paths {
981
		const char *path;
982
		int path_is_prefix;
983
		int readonly;
984
	} const allow_paths[] = {
985
		{ NPPPD_DIR "/",	1,	1 },
986
		{ "/dev/bpf",		0,	0 },
987
		{ "/etc/resolv.conf",	0,	1 },
988
		{ "/dev/tun",		1,	0 },
989
		{ "/dev/pppx",		1,	0 }
990
	};
991
992
	/* O_NONBLOCK is the only 'extra' flag permitted */
993
	if (arg->flags & ~(O_ACCMODE | O_NONBLOCK))
994
		return (1);
995
	for (i = 0; i < (int)nitems(allow_paths); i++) {
996
		if (allow_paths[i].path_is_prefix) {
997
			if (!startswith(arg->path, allow_paths[i].path))
998
				continue;
999
		} else if (strcmp(arg->path, allow_paths[i].path) != 0)
1000
			continue;
1001
		if (allow_paths[i].readonly) {
1002
			if ((arg->flags & O_ACCMODE) != O_RDONLY)
1003
				continue;
1004
		}
1005
		return (0);
1006
	}
1007
	return (1);
1008
}
1009
1010
static int
1011
privsep_npppd_check_socket(struct PRIVSEP_SOCKET_ARG *arg)
1012
{
1013
	/* npppd uses routing socket */
1014
	if (arg->domain == PF_ROUTE && arg->type == SOCK_RAW &&
1015
	    arg->protocol  == AF_UNSPEC)
1016
		return (0);
1017
1018
	/* npppd uses raw ip socket for GRE */
1019
	if (arg->domain == AF_INET && arg->type == SOCK_RAW &&
1020
	    arg->protocol == IPPROTO_GRE)
1021
		return (0);
1022
1023
	/* L2TP uses PF_KEY socket to delete IPsec-SA */
1024
	if (arg->domain == PF_KEY && arg->type == SOCK_RAW &&
1025
	    arg->protocol == PF_KEY_V2)
1026
		return (0);
1027
1028
	return (1);
1029
}
1030
1031
static int
1032
privsep_npppd_check_bind(struct PRIVSEP_BIND_ARG *arg)
1033
{
1034
	return (1);
1035
}
1036
1037
static int
1038
privsep_npppd_check_sendto(struct PRIVSEP_SENDTO_ARG *arg)
1039
{
1040
	/* for reply npppdctl's request */
1041
	if (arg->flags == 0 && arg->tolen > 0 &&
1042
	    arg->to.ss_family == AF_UNIX)
1043
		return (0);
1044
1045
	/* for sending a routing socket message. */
1046
	if (arg->flags == 0 && arg->tolen == 0)
1047
		return (0);
1048
1049
	return (1);
1050
}
1051
1052
static int
1053
privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG *arg)
1054
{
1055
1056
	return (1);
1057
}
1058
1059
static int
1060
privsep_npppd_check_get_user_info(struct PRIVSEP_GET_USER_INFO_ARG *arg)
1061
{
1062
	int l;
1063
1064
	l = strlen(NPPPD_DIR "/");
1065
	if (strncmp(arg->path, NPPPD_DIR "/", l) == 0)
1066
		return (0);
1067
1068
	return (1);
1069
}
1070
1071
static int
1072
privsep_npppd_check_get_if_addr(struct PRIVSEP_GET_IF_ADDR_ARG *arg)
1073
{
1074
	if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx"))
1075
		return (0);
1076
1077
	return (1);
1078
}
1079
1080
static int
1081
privsep_npppd_check_set_if_addr(struct PRIVSEP_SET_IF_ADDR_ARG *arg)
1082
{
1083
	if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx"))
1084
		return (0);
1085
1086
	return (1);
1087
}
1088
1089
static int
1090
privsep_npppd_check_del_if_addr(struct PRIVSEP_DEL_IF_ADDR_ARG *arg)
1091
{
1092
	if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx"))
1093
		return (0);
1094
1095
	return (1);
1096
}
1097
1098
static int
1099
privsep_npppd_check_get_if_flags(struct PRIVSEP_GET_IF_FLAGS_ARG *arg)
1100
{
1101
	if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx"))
1102
		return (0);
1103
1104
	return (1);
1105
}
1106
1107
static int
1108
privsep_npppd_check_set_if_flags(struct PRIVSEP_SET_IF_FLAGS_ARG *arg)
1109
{
1110
	if (startswith(arg->ifname, "tun") || startswith(arg->ifname, "pppx"))
1111
		return (0);
1112
1113
	return (1);
1114
}