Bug Summary

File:src/usr.sbin/npppd/npppd/privsep.c
Warning:line 392, column 2
Value stored to 'cp' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name privsep.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/npppd/npppd/../common -I /usr/src/usr.sbin/npppd/npppd -I /usr/src/usr.sbin/npppd/npppd/../pptp -I /usr/src/usr.sbin/npppd/npppd/../l2tp -I /usr/src/usr.sbin/npppd/npppd/../pppoe -D USE_NPPPD_PPTP -D USE_NPPPD_L2TP -D USE_NPPPD_PPPOE -D __COPYRIGHT(x)= -D __RCSID(x)= -D NPPPD_MAX_IFACE=8 -D NPPPD_MAX_POOL=8 -D USE_NPPPD_MPPE -D USE_NPPPD_PIPEX -D USE_NPPPD_RADIUS -D USE_SA_COOKIE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/npppd/npppd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/npppd/npppd/privsep.c
1/* $OpenBSD: privsep.c,v 1.24 2020/01/23 00:17:27 dlg 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(*__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])) (sizeof((_a)) / sizeof((_a)[0]))
43#endif
44
45enum 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
60struct PRIVSEP_OPEN_ARG {
61 char path[PATH_MAX1024];
62 int flags;
63};
64
65struct PRIVSEP_SOCKET_ARG {
66 int domain;
67 int type;
68 int protocol;
69};
70
71struct PRIVSEP_BIND_ARG {
72 struct sockaddr_storage name;
73 socklen_t namelen;
74};
75
76struct 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
84struct PRIVSEP_UNLINK_ARG {
85 char path[PATH_MAX1024];
86};
87
88struct PRIVSEP_GET_USER_INFO_ARG {
89 char path[PATH_MAX1024];
90 char username[MAX_USERNAME_LENGTH256];
91};
92
93struct PRIVSEP_GET_IF_ADDR_ARG {
94 char ifname[IFNAMSIZ16];
95};
96
97struct PRIVSEP_GET_IF_ADDR_RESP {
98 int retval;
99 int rerrno;
100 struct in_addr addr;
101};
102
103struct PRIVSEP_SET_IF_ADDR_ARG {
104 char ifname[IFNAMSIZ16];
105 struct in_addr addr;
106};
107
108struct PRIVSEP_DEL_IF_ADDR_ARG {
109 char ifname[IFNAMSIZ16];
110};
111
112struct PRIVSEP_GET_IF_FLAGS_ARG {
113 char ifname[IFNAMSIZ16];
114 int flags;
115};
116
117struct PRIVSEP_GET_IF_FLAGS_RESP {
118 int retval;
119 int rerrno;
120 int flags;
121};
122
123struct PRIVSEP_SET_IF_FLAGS_ARG {
124 char ifname[IFNAMSIZ16];
125 int flags;
126};
127
128struct PRIVSEP_COMMON_RESP {
129 int retval;
130 int rerrno;
131};
132
133struct PRIVSEP_GET_USER_INFO_RESP {
134 int retval;
135 int rerrno;
136 char password[MAX_PASSWORD_LENGTH256];
137 struct in_addr framed_ip_address;
138 struct in_addr framed_ip_netmask;
139 char calling_number[NPPPD_PHONE_NUMBER_LEN32 + 1];
140};
141
142static void privsep_priv_main (int);
143static void privsep_priv_dispatch_imsg (struct imsgbuf *);
144int imsg_read_and_get(struct imsgbuf *, struct imsg *);
145static int startswith(const char *, const char *);
146static int privsep_recvfd (void);
147static int privsep_common_resp (void);
148
149static int privsep_npppd_check_open (struct PRIVSEP_OPEN_ARG *);
150static int privsep_npppd_check_socket (struct PRIVSEP_SOCKET_ARG *);
151static int privsep_npppd_check_bind (struct PRIVSEP_BIND_ARG *);
152static int privsep_npppd_check_sendto (struct PRIVSEP_SENDTO_ARG *);
153static int privsep_npppd_check_unlink (struct PRIVSEP_UNLINK_ARG *);
154static int privsep_npppd_check_get_user_info (
155 struct PRIVSEP_GET_USER_INFO_ARG *);
156static int privsep_npppd_check_get_if_addr (
157 struct PRIVSEP_GET_IF_ADDR_ARG *);
158static int privsep_npppd_check_set_if_addr (
159 struct PRIVSEP_SET_IF_ADDR_ARG *);
160static int privsep_npppd_check_del_if_addr (
161 struct PRIVSEP_DEL_IF_ADDR_ARG *);
162static int privsep_npppd_check_get_if_flags (
163 struct PRIVSEP_GET_IF_FLAGS_ARG *);
164static int privsep_npppd_check_set_if_flags (
165 struct PRIVSEP_SET_IF_FLAGS_ARG *);
166
167static int privsep_sock = -1;
168static struct imsgbuf privsep_ibuf;
169static pid_t privsep_pid;
170
171int
172privsep_init(void)
173{
174 pid_t pid;
175 int pairsock[2];
176
177 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, 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 */
198fail:
199 if (pairsock[0] >= 0) {
200 close(pairsock[0]);
201 close(pairsock[1]);
202 }
203
204 return (-1);
205}
206
207void
208privsep_fini(void)
209{
210 imsg_clear(&privsep_ibuf);
211 if (privsep_sock >= 0) {
212 close(privsep_sock);
213 privsep_sock = -1;
214 }
215}
216
217pid_t
218privsep_priv_pid(void)
219{
220 return (privsep_pid);
221}
222
223/***********************************************************************
224 * Functions for from jail
225 ***********************************************************************/
226int
227priv_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(*__errno()) = EINVAL22;
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
248int
249priv_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
263int
264priv_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
277FILE *
278priv_fopen(const char *path)
279{
280 int f;
281 FILE *fp;
282
283 if ((f = priv_open(path, O_RDONLY0x0000)) < 0)
284 return (NULL((void*)0));
285
286 if ((fp = fdopen(f, "r")) == NULL((void*)0)) {
287 close(f);
288 return (NULL((void*)0));
289 } else
290 return (fp);
291}
292
293int
294priv_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(*__errno()) = EINVAL22;
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)__builtin_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)(sizeof((iov)) / sizeof((iov)[0])));
319 imsg_flush(&privsep_ibuf);
320
321 return (privsep_common_resp());
322}
323
324int
325priv_send(int s, const void *msg, int len, int flags)
326{
327 return (priv_sendto(s, msg, len, flags, NULL((void*)0), 0));
328}
329
330int
331priv_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
343int
344priv_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_SIZEsizeof(struct imsg_hdr) + sizeof(*r)) {
365 errno(*__errno()) = EACCES13;
366 goto on_error;
367 }
368 r = imsg.data;
369 if (r->retval != 0) {
370 errno(*__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])__builtin_offsetof(npppd_auth_user, space[sz]))) == NULL((void*)0))
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;
Value stored to 'cp' is never read
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
402on_error:
403 imsg_free(&imsg);
404 return (-1);
405}
406
407int
408priv_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_SIZEsizeof(struct imsg_hdr) + sizeof(*r))
425 errno(*__errno()) = EACCES13;
426 else {
427 r = imsg.data;
428 if (r->retval != -1)
429 *addr = r->addr;
430 else
431 errno(*__errno()) = r->rerrno;
432 retval = r->retval;
433 }
434 imsg_free(&imsg);
435
436 return (retval);
437}
438
439int
440priv_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
452int
453priv_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
466int
467priv_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_SIZEsizeof(struct imsg_hdr) + sizeof(*r))
484 errno(*__errno()) = EACCES13;
485 else {
486 r = imsg.data;
487 *pflags = r->flags;
488 if (r->retval != 0)
489 errno(*__errno()) = r->rerrno;
490 retval = r->retval;
491 }
492 imsg_free(&imsg);
493
494 return (retval);
495}
496
497int
498priv_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
512static int
513privsep_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_SIZEsizeof(struct imsg_hdr) + sizeof(*r))
522 errno(*__errno()) = EACCES13;
523 else {
524 r = imsg.data;
525 retval = r->retval;
526 if (r->retval != 0)
527 errno(*__errno()) = r->rerrno;
528 else
529 retval = imsg.fd;
530 }
531 imsg_free(&imsg);
532
533 return (retval);
534}
535
536static int
537privsep_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(*__errno()) = EACCES13;
545 return (-1);
546 }
547 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(*r))
548 errno(*__errno()) = EACCES13;
549 else {
550 r = imsg.data;
551 if (r->retval != 0)
552 errno(*__errno()) = r->rerrno;
553 retval = r->retval;
554 }
555 imsg_free(&imsg);
556
557 return (retval);
558}
559
560/***********************************************************************
561 * privileged process
562 ***********************************************************************/
563static void
564privsep_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_SUCCESS0);
574}
575
576static void
577privsep_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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
592 r.rerrno = EINVAL22;
593 else if (privsep_npppd_check_open(a))
594 r.rerrno = EACCES13;
595 else {
596 if ((f = open(a->path, a->flags & ~O_CREAT0x0200))
597 == -1)
598 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
613 r.rerrno = EINVAL22;
614 else if (privsep_npppd_check_socket(a))
615 r.rerrno = EACCES13;
616 else {
617 if ((s = socket(a->domain, a->type,
618 a->protocol)) == -1)
619 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
633 r.rerrno = EINVAL22;
634 else if (privsep_npppd_check_unlink(a))
635 r.rerrno = EACCES13;
636 else {
637 if ((r.retval = unlink(a->path)) != 0)
638 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a) ||
651 imsg.fd < 0)
652 r.rerrno = EINVAL22;
653 else if (privsep_npppd_check_bind(a))
654 r.rerrno = EACCES13;
655 else {
656 if ((r.retval = bind(imsg.fd,
657 (struct sockaddr *)&a->name, a->namelen))
658 != 0)
659 r.rerrno = errno(*__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((void*)0), NULL((void*)0) };
672
673 memset(&r, 0, sizeof(r));
674 r.retval = -1;
675 r.framed_ip_address.s_addr = INADDR_NAS_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFEL) ? (__uint32_t
)(((__uint32_t)(0xFFFFFFFEL) & 0xff) << 24 | ((__uint32_t
)(0xFFFFFFFEL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFEL
) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFEL) &
0xff000000) >> 24) : __swap32md(0xFFFFFFFEL)))
;
676 r.framed_ip_netmask.s_addr = INADDR_NONE((u_int32_t)(0xffffffff));
677 str = buf = NULL((void*)0);
678
679 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(*a)) {
680 r.rerrno = EINVAL22;
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 = EACCES13;
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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0);
724 }
725 cgetclose();
726 free(buf);
727 r.retval = 0;
728 } else if (retval == -1) {
729 buf = NULL((void*)0);
730on_broken_entry:
731 free(buf);
732 free(str);
733 r.retval = -1;
734 r.rerrno = ENOENT2;
735 } else {
736 r.retval = retval;
737 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a) ||
749 imsg.hdr.len < IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
750 offsetof(struct PRIVSEP_SENDTO_ARG,__builtin_offsetof(struct PRIVSEP_SENDTO_ARG, msg[a->len])
751 msg[a->len])__builtin_offsetof(struct PRIVSEP_SENDTO_ARG, msg[a->len]))
752 r.rerrno = EMSGSIZE40;
753 else if (imsg.fd < 0)
754 r.rerrno = EINVAL22;
755 else if (privsep_npppd_check_sendto(a))
756 r.rerrno = EACCES13;
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(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
784 r.rerrno = EINVAL22;
785 else if (privsep_npppd_check_get_if_addr(a))
786 r.rerrno = EACCES13;
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_INET2, SOCK_DGRAM2, 0)) < 0 ||
792 ioctl(s, SIOCGIFADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((33)))
, &ifr) != 0) {
793 r.retval = -1;
794 r.rerrno = errno(*__errno());
795 } else {
796 r.retval = 0;
797 r.addr = ((struct sockaddr_in *)
798 &ifr.ifr_addrifr_ifru.ifru_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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
816 r.rerrno = EINVAL22;
817 else if (privsep_npppd_check_set_if_addr(a))
818 r.rerrno = EACCES13;
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_addrifra_ifrau.ifrau_addr;
825 sin4->sin_family = AF_INET2;
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_INET2;
831 sin4->sin_len = sizeof(struct sockaddr_in);
832 sin4->sin_addr.s_addr = 0xffffffffUL;
833
834 sin4 =
835 (struct sockaddr_in *)&ifra.ifra_broadaddrifra_dstaddr;
836 sin4->sin_family = AF_INET2;
837 sin4->sin_len = sizeof(struct sockaddr_in);
838 sin4->sin_addr.s_addr = 0;
839
840 if ((s = socket(AF_INET2, SOCK_DGRAM2, 0)) < 0 ||
841 ioctl(s, SIOCAIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifaliasreq) &
0x1fff) << 16) | ((('i')) << 8) | ((26)))
, &ifra) != 0) {
842 r.retval = -1;
843 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
861 r.rerrno = EINVAL22;
862 else if (privsep_npppd_check_del_if_addr(a))
863 r.rerrno = EACCES13;
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_INET2, SOCK_DGRAM2, 0)) < 0 ||
869 ioctl(s, SIOCDIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((25)))
, &ifr) != 0) {
870 r.retval = -1;
871 r.rerrno = errno(*__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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
892 r.rerrno = EINVAL22;
893 else if (privsep_npppd_check_get_if_flags(a)) {
894 r.rerrno = EACCES13;
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_INET2, SOCK_DGRAM2, 0)) < 0 ||
900 ioctl(s, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, &ifr) != 0) {
901 r.retval = -1;
902 r.rerrno = errno(*__errno());
903 } else {
904 r.retval = 0;
905 r.flags = ifr.ifr_flagsifr_ifru.ifru_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_SIZEsizeof(struct imsg_hdr) + sizeof(*a))
922 r.rerrno = EINVAL22;
923 else if (privsep_npppd_check_set_if_flags(a))
924 r.rerrno = EACCES13;
925 else {
926 memset(&ifr, 0, sizeof(ifr));
927 strlcpy(ifr.ifr_name, a->ifname,
928 sizeof(ifr.ifr_name));
929 ifr.ifr_flagsifr_ifru.ifru_flags = a->flags;
930 if ((s = socket(AF_INET2, SOCK_DGRAM2, 0)) < 0 ||
931 ioctl(s, SIOCGIFFLAGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((17)))
, &ifr) != 0) {
932 r.retval = -1;
933 r.rerrno = errno(*__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
949int
950imsg_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(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4))
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
970static int
971startswith(const char *str, const char *prefix)
972{
973 return (strncmp(str, prefix, strlen(prefix)) == 0)? 1 : 0;
974}
975
976static int
977privsep_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"/etc/npppd" "/", 1, 1 },
986 { "/dev/bpf", 0, 0 },
987 { "/etc/resolv.conf", 0, 1 },
988 { "/dev/tun", 1, 0 },
989 { "/dev/pppac", 1, 0 },
990 { "/dev/pppx", 1, 0 }
991 };
992
993 /* O_NONBLOCK is the only 'extra' flag permitted */
994 if (arg->flags & ~(O_ACCMODE0x0003 | O_NONBLOCK0x0004))
995 return (1);
996 for (i = 0; i < (int)nitems(allow_paths)(sizeof((allow_paths)) / sizeof((allow_paths)[0])); i++) {
997 if (allow_paths[i].path_is_prefix) {
998 if (!startswith(arg->path, allow_paths[i].path))
999 continue;
1000 } else if (strcmp(arg->path, allow_paths[i].path) != 0)
1001 continue;
1002 if (allow_paths[i].readonly) {
1003 if ((arg->flags & O_ACCMODE0x0003) != O_RDONLY0x0000)
1004 continue;
1005 }
1006 return (0);
1007 }
1008 return (1);
1009}
1010
1011static int
1012privsep_npppd_check_socket(struct PRIVSEP_SOCKET_ARG *arg)
1013{
1014 /* npppd uses routing socket */
1015 if (arg->domain == PF_ROUTE17 && arg->type == SOCK_RAW3 &&
1016 arg->protocol == AF_UNSPEC0)
1017 return (0);
1018
1019 /* npppd uses raw ip socket for GRE */
1020 if (arg->domain == AF_INET2 && arg->type == SOCK_RAW3 &&
1021 arg->protocol == IPPROTO_GRE47)
1022 return (0);
1023
1024 /* L2TP uses PF_KEY socket to delete IPsec-SA */
1025 if (arg->domain == PF_KEY30 && arg->type == SOCK_RAW3 &&
1026 arg->protocol == PF_KEY_V22)
1027 return (0);
1028
1029 return (1);
1030}
1031
1032static int
1033privsep_npppd_check_bind(struct PRIVSEP_BIND_ARG *arg)
1034{
1035 return (1);
1036}
1037
1038static int
1039privsep_npppd_check_sendto(struct PRIVSEP_SENDTO_ARG *arg)
1040{
1041 /* for reply npppdctl's request */
1042 if (arg->flags == 0 && arg->tolen > 0 &&
1043 arg->to.ss_family == AF_UNIX1)
1044 return (0);
1045
1046 /* for sending a routing socket message. */
1047 if (arg->flags == 0 && arg->tolen == 0)
1048 return (0);
1049
1050 return (1);
1051}
1052
1053static int
1054privsep_npppd_check_unlink(struct PRIVSEP_UNLINK_ARG *arg)
1055{
1056
1057 return (1);
1058}
1059
1060static int
1061privsep_npppd_check_get_user_info(struct PRIVSEP_GET_USER_INFO_ARG *arg)
1062{
1063 int l;
1064
1065 l = strlen(NPPPD_DIR"/etc/npppd" "/");
1066 if (strncmp(arg->path, NPPPD_DIR"/etc/npppd" "/", l) == 0)
1067 return (0);
1068
1069 return (1);
1070}
1071
1072static int
1073privsep_npppd_check_ifname(const char *ifname)
1074{
1075 if (startswith(ifname, "tun") ||
1076 startswith(ifname, "pppac") ||
1077 startswith(ifname, "pppx"))
1078 return (0);
1079
1080 return (0);
1081}
1082
1083static int
1084privsep_npppd_check_get_if_addr(struct PRIVSEP_GET_IF_ADDR_ARG *arg)
1085{
1086 return (privsep_npppd_check_ifname(arg->ifname));
1087}
1088
1089static int
1090privsep_npppd_check_set_if_addr(struct PRIVSEP_SET_IF_ADDR_ARG *arg)
1091{
1092 return (privsep_npppd_check_ifname(arg->ifname));
1093}
1094
1095static int
1096privsep_npppd_check_del_if_addr(struct PRIVSEP_DEL_IF_ADDR_ARG *arg)
1097{
1098 return (privsep_npppd_check_ifname(arg->ifname));
1099}
1100
1101static int
1102privsep_npppd_check_get_if_flags(struct PRIVSEP_GET_IF_FLAGS_ARG *arg)
1103{
1104 return (privsep_npppd_check_ifname(arg->ifname));
1105}
1106
1107static int
1108privsep_npppd_check_set_if_flags(struct PRIVSEP_SET_IF_FLAGS_ARG *arg)
1109{
1110 return (privsep_npppd_check_ifname(arg->ifname));
1111}