Bug Summary

File:src/usr.sbin/npppd/npppd/privsep.c
Warning:line 699, column 10
Although the value stored to 'retval' is used in the enclosing expression, the value is never actually read from 'retval'

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;
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",
Although the value stored to 'retval' is used in the enclosing expression, the value is never actually read from 'retval'
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}