xref: /openbsd-src/usr.sbin/identd/identd.c (revision 515e489c3d599b9cfcdf9cf6842ac49f92e154d6)
1 /*	$OpenBSD: identd.c,v 1.40 2019/07/03 03:24:03 deraadt Exp $ */
2 
3 /*
4  * Copyright (c) 2013 David Gwynne <dlg@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 
19 #include <sys/types.h>
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 #include <sys/queue.h>
23 #include <sys/stat.h>
24 #include <sys/sysctl.h>
25 #include <sys/uio.h>
26 
27 #include <netinet/in.h>
28 #include <netinet/tcp.h>
29 #include <netinet/tcp_timer.h>
30 #include <netinet/tcp_var.h>
31 
32 #include <netdb.h>
33 
34 #include <err.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <event.h>
38 #include <fcntl.h>
39 #include <pwd.h>
40 #include <stdio.h>
41 #include <limits.h>
42 #include <stdlib.h>
43 #include <stdarg.h>
44 #include <string.h>
45 #include <signal.h>
46 #include <syslog.h>
47 #include <unistd.h>
48 
49 #define IDENTD_USER "_identd"
50 
51 #define DOTNOIDENT ".noident"
52 
53 #define TIMEOUT_MIN 4
54 #define TIMEOUT_MAX 240
55 #define TIMEOUT_DEFAULT 120
56 #define INPUT_MAX 256
57 
58 enum ident_client_state {
59 	S_BEGINNING = 0,
60 	S_SERVER_PORT,
61 	S_PRE_COMMA,
62 	S_POST_COMMA,
63 	S_CLIENT_PORT,
64 	S_PRE_EOL,
65 	S_EOL,
66 
67 	S_DEAD,
68 	S_QUEUED
69 };
70 
71 #define E_NONE		0
72 #define E_NOUSER	1
73 #define E_UNKNOWN	2
74 #define E_HIDDEN	3
75 
76 struct ident_client {
77 	struct {
78 		/* from the socket */
79 		struct sockaddr_storage ss;
80 		socklen_t len;
81 
82 		/* from the request */
83 		u_int port;
84 	} client, server;
85 	SIMPLEQ_ENTRY(ident_client) entry;
86 	enum ident_client_state state;
87 	struct event ev;
88 	struct event tmo;
89 	size_t rxbytes;
90 
91 	char *buf;
92 	size_t buflen;
93 	size_t bufoff;
94 	uid_t uid;
95 };
96 
97 struct ident_resolver {
98 	SIMPLEQ_ENTRY(ident_resolver) entry;
99 	char *buf;
100 	size_t buflen;
101 	u_int error;
102 };
103 
104 struct identd_listener {
105 	struct event ev, pause;
106 };
107 
108 void	parent_rd(int, short, void *);
109 void	parent_wr(int, short, void *);
110 int	parent_username(struct ident_resolver *, struct passwd *);
111 int	parent_uid(struct ident_resolver *, struct passwd *);
112 int	parent_token(struct ident_resolver *, struct passwd *);
113 void	parent_noident(struct ident_resolver *, struct passwd *);
114 
115 void	child_rd(int, short, void *);
116 void	child_wr(int, short, void *);
117 
118 void	identd_listen(const char *, const char *, int);
119 void	identd_paused(int, short, void *);
120 void	identd_accept(int, short, void *);
121 int	identd_error(struct ident_client *, const char *);
122 void	identd_close(struct ident_client *);
123 void	identd_timeout(int, short, void *);
124 void	identd_request(int, short, void *);
125 enum ident_client_state
126 	identd_parse(struct ident_client *, int);
127 void	identd_resolving(int, short, void *);
128 void	identd_response(int, short, void *);
129 int	fetchuid(struct ident_client *);
130 
131 const char *gethost(struct sockaddr_storage *);
132 const char *gentoken(void);
133 
134 struct loggers {
135 	__dead void (*err)(int, const char *, ...)
136 	    __attribute__((__format__ (printf, 2, 3)));
137 	__dead void (*errx)(int, const char *, ...)
138 	    __attribute__((__format__ (printf, 2, 3)));
139 	void (*warn)(const char *, ...)
140 	    __attribute__((__format__ (printf, 1, 2)));
141 	void (*warnx)(const char *, ...)
142 	    __attribute__((__format__ (printf, 1, 2)));
143 	void (*notice)(const char *, ...)
144 	    __attribute__((__format__ (printf, 1, 2)));
145 	void (*debug)(const char *, ...)
146 	    __attribute__((__format__ (printf, 1, 2)));
147 };
148 
149 const struct loggers conslogger = {
150 	err,
151 	errx,
152 	warn,
153 	warnx,
154 	warnx, /* notice */
155 	warnx /* debug */
156 };
157 
158 __dead void	syslog_err(int, const char *, ...)
159 		    __attribute__((__format__ (printf, 2, 3)));
160 __dead void	syslog_errx(int, const char *, ...)
161 		    __attribute__((__format__ (printf, 2, 3)));
162 void		syslog_warn(const char *, ...)
163 		    __attribute__((__format__ (printf, 1, 2)));
164 void		syslog_warnx(const char *, ...)
165 		    __attribute__((__format__ (printf, 1, 2)));
166 void		syslog_notice(const char *, ...)
167 		    __attribute__((__format__ (printf, 1, 2)));
168 void		syslog_debug(const char *, ...)
169 		    __attribute__((__format__ (printf, 1, 2)));
170 void		syslog_vstrerror(int, int, const char *, va_list)
171 		    __attribute__((__format__ (printf, 3, 0)));
172 
173 const struct loggers syslogger = {
174 	syslog_err,
175 	syslog_errx,
176 	syslog_warn,
177 	syslog_warnx,
178 	syslog_notice,
179 	syslog_debug
180 };
181 
182 const struct loggers *logger = &conslogger;
183 
184 #define lerr(_e, _f...) logger->err((_e), _f)
185 #define lerrx(_e, _f...) logger->errx((_e), _f)
186 #define lwarn(_f...) logger->warn(_f)
187 #define lwarnx(_f...) logger->warnx(_f)
188 #define lnotice(_f...) logger->notice(_f)
189 #define ldebug(_f...) logger->debug(_f)
190 
191 #define sa(_ss) ((struct sockaddr *)(_ss))
192 
193 static __dead void
usage(void)194 usage(void)
195 {
196 	extern char *__progname;
197 	fprintf(stderr, "usage: %s [-46deHhNn] [-l address] [-t timeout]\n",
198 	    __progname);
199 	exit(1);
200 }
201 
202 struct timeval timeout = { TIMEOUT_DEFAULT, 0 };
203 int debug = 0;
204 int noident = 0;
205 int unknown_err = 0;
206 int hideall = 0;
207 
208 int (*parent_uprintf)(struct ident_resolver *, struct passwd *) =
209     parent_username;
210 
211 struct event proc_rd, proc_wr;
212 union {
213 	struct {
214 		SIMPLEQ_HEAD(, ident_resolver) replies;
215 	} parent;
216 	struct {
217 		SIMPLEQ_HEAD(, ident_client) pushing, popping;
218 	} child;
219 } sc;
220 
221 int
main(int argc,char * argv[])222 main(int argc, char *argv[])
223 {
224 	extern char *__progname;
225 	const char *errstr = NULL;
226 
227 	int		 c;
228 	struct passwd	*pw;
229 
230 	char *addr = NULL;
231 	int family = AF_UNSPEC;
232 
233 	int pair[2];
234 	pid_t parent;
235 	int sibling;
236 
237 	while ((c = getopt(argc, argv, "46deHhl:Nnt:")) != -1) {
238 		switch (c) {
239 		case '4':
240 			family = AF_INET;
241 			break;
242 		case '6':
243 			family = AF_INET6;
244 			break;
245 		case 'd':
246 			debug = 1;
247 			break;
248 		case 'e':
249 			unknown_err = 1;
250 			break;
251 		case 'H':
252 			hideall = 1;
253 			/* FALLTHROUGH */
254 		case 'h':
255 			parent_uprintf = parent_token;
256 			break;
257 		case 'l':
258 			addr = optarg;
259 			break;
260 		case 'N':
261 			noident = 1;
262 			break;
263 		case 'n':
264 			parent_uprintf = parent_uid;
265 			break;
266 		case 't':
267 			timeout.tv_sec = strtonum(optarg,
268 			    TIMEOUT_MIN, TIMEOUT_MAX, &errstr);
269 			if (errstr != NULL)
270 				errx(1, "timeout %s is %s", optarg, errstr);
271 			break;
272 		default:
273 			usage();
274 			/* NOTREACHED */
275 		}
276 	}
277 
278 	argc -= optind;
279 	argv += optind;
280 
281 	if (argc != 0)
282 		usage();
283 
284 	if (geteuid() != 0)
285 		errx(1, "need root privileges");
286 
287 	if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK,
288 	    PF_UNSPEC, pair) == -1)
289 		err(1, "socketpair");
290 
291 	pw = getpwnam(IDENTD_USER);
292 	if (pw == NULL)
293 		errx(1, "no %s user", IDENTD_USER);
294 
295 	if (!debug && daemon(1, 0) == -1)
296 		err(1, "daemon");
297 
298 	parent = fork();
299 	switch (parent) {
300 	case -1:
301 		lerr(1, "fork");
302 
303 	case 0:
304 		/* child */
305 		setproctitle("listener");
306 		close(pair[1]);
307 		sibling = pair[0];
308 		break;
309 
310 	default:
311 		/* parent */
312 		setproctitle("resolver");
313 		close(pair[0]);
314 		sibling = pair[1];
315 		break;
316 	}
317 
318 	if (!debug) {
319 		openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
320 		tzset();
321 		logger = &syslogger;
322 	}
323 
324 	event_init();
325 
326 	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
327 		lerr(1, "signal(SIGPIPE)");
328 
329 	if (parent) {
330 		if (pledge("stdio getpw rpath id", NULL) == -1)
331 			err(1, "pledge");
332 
333 		SIMPLEQ_INIT(&sc.parent.replies);
334 
335 		event_set(&proc_rd, sibling, EV_READ | EV_PERSIST,
336 		    parent_rd, NULL);
337 		event_set(&proc_wr, sibling, EV_WRITE,
338 		    parent_wr, NULL);
339 	} else {
340 		SIMPLEQ_INIT(&sc.child.pushing);
341 		SIMPLEQ_INIT(&sc.child.popping);
342 
343 		identd_listen(addr, "auth", family);
344 
345 		if (chroot(pw->pw_dir) == -1)
346 			lerr(1, "chroot(%s)", pw->pw_dir);
347 
348 		if (chdir("/") == -1)
349 			lerr(1, "chdir(%s)", pw->pw_dir);
350 
351 		event_set(&proc_rd, sibling, EV_READ | EV_PERSIST,
352 		    child_rd, NULL);
353 		event_set(&proc_wr, sibling, EV_WRITE,
354 		    child_wr, NULL);
355 	}
356 
357 	if (setgroups(1, &pw->pw_gid) ||
358 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
359 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
360 		lerr(1, "unable to revoke privs");
361 
362 	if (parent) {
363 		if (noident) {
364 			if (pledge("stdio getpw rpath", NULL) == -1)
365 				err(1, "pledge");
366 		} else {
367 			if (pledge("stdio getpw", NULL) == -1)
368 				err(1, "pledge");
369 		}
370 	}
371 
372 	event_add(&proc_rd, NULL);
373 	event_dispatch();
374 	return (0);
375 }
376 
377 void
parent_rd(int fd,short events,void * arg)378 parent_rd(int fd, short events, void *arg)
379 {
380 	struct ident_resolver *r;
381 	struct passwd *pw;
382 	ssize_t n;
383 	uid_t uid;
384 
385 	n = read(fd, &uid, sizeof(uid));
386 	switch (n) {
387 	case -1:
388 		switch (errno) {
389 		case EAGAIN:
390 		case EINTR:
391 			return;
392 		default:
393 			lerr(1, "parent read");
394 		}
395 		break;
396 	case 0:
397 		lerrx(1, "child has gone");
398 	case sizeof(uid):
399 		break;
400 	default:
401 		lerrx(1, "unexpected %zd data from child", n);
402 	}
403 
404 	r = calloc(1, sizeof(*r));
405 	if (r == NULL)
406 		lerr(1, "resolver alloc");
407 
408 	pw = getpwuid(uid);
409 	if (pw == NULL && !hideall) {
410 		r->error = E_NOUSER;
411 		goto done;
412 	}
413 
414 	if (noident && !hideall) {
415 		parent_noident(r, pw);
416 		if (r->error != E_NONE)
417 			goto done;
418 	}
419 
420 	n = (*parent_uprintf)(r, pw);
421 	if (n == -1) {
422 		r->error = E_UNKNOWN;
423 		goto done;
424 	}
425 
426 	r->buflen = n + 1;
427 
428 done:
429 	SIMPLEQ_INSERT_TAIL(&sc.parent.replies, r, entry);
430 	event_add(&proc_wr, NULL);
431 }
432 
433 int
parent_username(struct ident_resolver * r,struct passwd * pw)434 parent_username(struct ident_resolver *r, struct passwd *pw)
435 {
436 	return (asprintf(&r->buf, "%s", pw->pw_name));
437 }
438 
439 int
parent_uid(struct ident_resolver * r,struct passwd * pw)440 parent_uid(struct ident_resolver *r, struct passwd *pw)
441 {
442 	return (asprintf(&r->buf, "%u", (u_int)pw->pw_uid));
443 }
444 
445 int
parent_token(struct ident_resolver * r,struct passwd * pw)446 parent_token(struct ident_resolver *r, struct passwd *pw)
447 {
448 	const char *token;
449 	int rv;
450 
451 	token = gentoken();
452 	rv = asprintf(&r->buf, "%s", token);
453 	if (rv != -1) {
454 		if (pw)
455 			lnotice("token %s == uid %u (%s)", token,
456 			    (u_int)pw->pw_uid, pw->pw_name);
457 		else
458 			lnotice("token %s == NO USER", token);
459 	}
460 
461 	return (rv);
462 }
463 
464 void
parent_noident(struct ident_resolver * r,struct passwd * pw)465 parent_noident(struct ident_resolver *r, struct passwd *pw)
466 {
467 	char path[PATH_MAX];
468 	struct stat st;
469 	int rv;
470 
471 	rv = snprintf(path, sizeof(path), "%s/%s", pw->pw_dir, DOTNOIDENT);
472 	if (rv < 0 || rv >= sizeof(path)) {
473 		r->error = E_UNKNOWN;
474 		return;
475 	}
476 
477 	if (stat(path, &st) == -1)
478 		return;
479 
480 	r->error = E_HIDDEN;
481 }
482 
483 void
parent_wr(int fd,short events,void * arg)484 parent_wr(int fd, short events, void *arg)
485 {
486 	struct ident_resolver *r = SIMPLEQ_FIRST(&sc.parent.replies);
487 	struct iovec iov[2];
488 	int iovcnt = 0;
489 	ssize_t n;
490 
491 	iov[iovcnt].iov_base = &r->error;
492 	iov[iovcnt].iov_len = sizeof(r->error);
493 	iovcnt++;
494 
495 	if (r->buflen > 0) {
496 		iov[iovcnt].iov_base = r->buf;
497 		iov[iovcnt].iov_len = r->buflen;
498 		iovcnt++;
499 	}
500 
501 	n = writev(fd, iov, iovcnt);
502 	if (n == -1) {
503 		switch (errno) {
504 		case EINTR:
505 		case EAGAIN:
506 			event_add(&proc_wr, NULL);
507 			return;
508 		default:
509 			lerr(1, "parent write");
510 		}
511 	}
512 
513 	if (n != sizeof(r->error) + r->buflen)
514 		lerrx(1, "unexpected parent write length %zd", n);
515 
516 	SIMPLEQ_REMOVE_HEAD(&sc.parent.replies, entry);
517 
518 	if (r->buflen > 0)
519 		free(r->buf);
520 
521 	free(r);
522 
523 	if (!SIMPLEQ_EMPTY(&sc.parent.replies))
524 		event_add(&proc_wr, NULL);
525 }
526 
527 void
child_rd(int fd,short events,void * arg)528 child_rd(int fd, short events, void *arg)
529 {
530 	struct ident_client *c;
531 	struct {
532 		u_int error;
533 		char buf[512];
534 	} reply;
535 	ssize_t n;
536 
537 	n = read(fd, &reply, sizeof(reply));
538 	switch (n) {
539 	case -1:
540 		switch (errno) {
541 		case EAGAIN:
542 		case EINTR:
543 			return;
544 		default:
545 			lerr(1, "child read");
546 		}
547 		break;
548 	case 0:
549 		lerrx(1, "parent has gone");
550 	default:
551 		break;
552 	}
553 
554 	c = SIMPLEQ_FIRST(&sc.child.popping);
555 	if (c == NULL)
556 		lerrx(1, "unsolicited data from parent");
557 
558 	SIMPLEQ_REMOVE_HEAD(&sc.child.popping, entry);
559 
560 	if (n < sizeof(reply.error))
561 		lerrx(1, "short data from parent");
562 
563 	/* check if something went wrong while the parent was working */
564 	if (c->state == S_DEAD) {
565 		free(c);
566 		return;
567 	}
568 	c->state = S_DEAD;
569 
570 	switch (reply.error) {
571 	case E_NONE:
572 		n = asprintf(&c->buf, "%u , %u : USERID : UNIX : %s\r\n",
573 		    c->server.port, c->client.port, reply.buf);
574 		break;
575 	case E_NOUSER:
576 		n = asprintf(&c->buf, "%u , %u : ERROR : %s\r\n",
577 		    c->server.port, c->client.port,
578 		    unknown_err ? "UNKNOWN-ERROR" : "NO-USER");
579 		break;
580 	case E_UNKNOWN:
581 		n = asprintf(&c->buf, "%u , %u : ERROR : UNKNOWN-ERROR\r\n",
582 		    c->server.port, c->client.port);
583 		break;
584 	case E_HIDDEN:
585 		n = asprintf(&c->buf, "%u , %u : ERROR : HIDDEN-USER\r\n",
586 		    c->server.port, c->client.port);
587 		break;
588 	default:
589 		lerrx(1, "unexpected error from parent %u", reply.error);
590 	}
591 	if (n == -1)
592 		goto fail;
593 
594 	c->buflen = n;
595 
596 	fd = EVENT_FD(&c->ev);
597 	event_del(&c->ev);
598 	event_set(&c->ev, fd, EV_READ | EV_WRITE | EV_PERSIST,
599 	    identd_response, c);
600 	event_add(&c->ev, NULL);
601 	return;
602 
603 fail:
604 	identd_close(c);
605 }
606 
607 void
child_wr(int fd,short events,void * arg)608 child_wr(int fd, short events, void *arg)
609 {
610 	struct ident_client *c = SIMPLEQ_FIRST(&sc.child.pushing);
611 	const char *errstr = NULL;
612 	ssize_t n;
613 
614 	n = write(fd, &c->uid, sizeof(c->uid));
615 	switch (n) {
616 	case -1:
617 		switch (errno) {
618 		case EINTR:
619 		case EAGAIN:
620 			event_add(&proc_wr, NULL);
621 			return;
622 		case ENOBUFS: /* parent has a backlog of requests */
623 			errstr = "UNKNOWN-ERROR";
624 			break;
625 		default:
626 			lerr(1, "child write");
627 		}
628 		break;
629 	case sizeof(c->uid):
630 		break;
631 	default:
632 		lerrx(1, "unexpected child write length %zd", n);
633 	}
634 
635 	SIMPLEQ_REMOVE_HEAD(&sc.child.pushing, entry);
636 	if (errstr == NULL)
637 		SIMPLEQ_INSERT_TAIL(&sc.child.popping, c, entry);
638 	else if (identd_error(c, errstr) == -1)
639 		identd_close(c);
640 
641 	if (!SIMPLEQ_EMPTY(&sc.child.pushing))
642 		event_add(&proc_wr, NULL);
643 }
644 
645 void
identd_listen(const char * addr,const char * port,int family)646 identd_listen(const char *addr, const char *port, int family)
647 {
648 	struct identd_listener *l = NULL;
649 
650 	struct addrinfo hints, *res, *res0;
651 	int error, s;
652 	const char *cause = NULL;
653 	int on = 1;
654 
655 	memset(&hints, 0, sizeof(hints));
656 	hints.ai_family = family;
657 	hints.ai_socktype = SOCK_STREAM;
658 	hints.ai_flags = AI_PASSIVE;
659 
660 	error = getaddrinfo(addr, port, &hints, &res0);
661 	if (error)
662 		lerrx(1, "%s/%s: %s", addr, port, gai_strerror(error));
663 
664 	for (res = res0; res != NULL; res = res->ai_next) {
665 		s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK,
666 		    res->ai_protocol);
667 		if (s == -1) {
668 			cause = "socket";
669 			continue;
670 		}
671 
672 		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
673 		    &on, sizeof(on)) == -1)
674 			err(1, "listener setsockopt(SO_REUSEADDR)");
675 
676 		if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
677 			int serrno = errno;
678 
679 			cause = "bind";
680 			close(s);
681 			errno = serrno;
682 			continue;
683 		}
684 
685 		if (listen(s, 5) == -1)
686 			err(1, "listen");
687 
688 		l = calloc(1, sizeof(*l));
689 		if (l == NULL)
690 			err(1, "listener ev alloc");
691 
692 		event_set(&l->ev, s, EV_READ | EV_PERSIST, identd_accept, l);
693 		event_add(&l->ev, NULL);
694 		evtimer_set(&l->pause, identd_paused, l);
695 	}
696 	if (l == NULL)
697 		err(1, "%s", cause);
698 
699 	freeaddrinfo(res0);
700 }
701 
702 void
identd_paused(int fd,short events,void * arg)703 identd_paused(int fd, short events, void *arg)
704 {
705 	struct identd_listener *l = arg;
706 	event_add(&l->ev, NULL);
707 }
708 
709 void
identd_accept(int fd,short events,void * arg)710 identd_accept(int fd, short events, void *arg)
711 {
712 	struct identd_listener *l = arg;
713 	struct sockaddr_storage ss;
714 	struct timeval pause = { 1, 0 };
715 	struct ident_client *c = NULL;
716 	socklen_t len;
717 	int s;
718 
719 	len = sizeof(ss);
720 	s = accept4(fd, sa(&ss), &len, SOCK_NONBLOCK);
721 	if (s == -1) {
722 		switch (errno) {
723 		case EINTR:
724 		case EWOULDBLOCK:
725 		case ECONNABORTED:
726 			return;
727 		case EMFILE:
728 		case ENFILE:
729 			event_del(&l->ev);
730 			evtimer_add(&l->pause, &pause);
731 			return;
732 		default:
733 			lerr(1, "accept");
734 		}
735 	}
736 
737 	c = calloc(1, sizeof(*c));
738 	if (c == NULL) {
739 		lwarn("client alloc");
740 		close(fd);
741 		return;
742 	}
743 
744 	memcpy(&c->client.ss, &ss, len);
745 	c->client.len = len;
746 	ldebug("client: %s", gethost(&ss));
747 
748 	/* lookup the local ip it connected to */
749 	c->server.len = sizeof(c->server.ss);
750 	if (getsockname(s, sa(&c->server.ss), &c->server.len) == -1)
751 		lerr(1, "getsockname");
752 
753 	event_set(&c->ev, s, EV_READ | EV_PERSIST, identd_request, c);
754 	event_add(&c->ev, NULL);
755 
756 	evtimer_set(&c->tmo, identd_timeout, c);
757 	evtimer_add(&c->tmo, &timeout);
758 }
759 
760 void
identd_timeout(int fd,short events,void * arg)761 identd_timeout(int fd, short events, void *arg)
762 {
763 	struct ident_client *c = arg;
764 
765 	event_del(&c->ev);
766 	close(fd);
767 	free(c->buf);
768 
769 	if (c->state == S_QUEUED) /* it is queued for resolving */
770 		c->state = S_DEAD;
771 	else
772 		free(c);
773 }
774 
775 void
identd_request(int fd,short events,void * arg)776 identd_request(int fd, short events, void *arg)
777 {
778 	struct ident_client *c = arg;
779 	unsigned char buf[64];
780 	ssize_t n, i;
781 	char *errstr = unknown_err ? "UNKNOWN-ERROR" : "INVALID-PORT";
782 
783 	n = read(fd, buf, sizeof(buf));
784 	switch (n) {
785 	case -1:
786 		switch (errno) {
787 		case EINTR:
788 		case EAGAIN:
789 			return;
790 		default:
791 			lwarn("%s read", gethost(&c->client.ss));
792 			goto fail;
793 		}
794 		break;
795 
796 	case 0:
797 		ldebug("%s closed connection", gethost(&c->client.ss));
798 		goto fail;
799 	default:
800 		break;
801 	}
802 
803 	c->rxbytes += n;
804 	if (c->rxbytes >= INPUT_MAX)
805 		goto fail;
806 
807 	for (i = 0; c->state < S_EOL && i < n; i++)
808 		c->state = identd_parse(c, buf[i]);
809 
810 	if (c->state == S_DEAD)
811 		goto error;
812 	if (c->state != S_EOL)
813 		return;
814 
815 	if (c->server.port < 1 || c->client.port < 1)
816 		goto error;
817 
818 	if (fetchuid(c) == -1) {
819 		errstr = unknown_err ? "UNKNOWN-ERROR" : "NO-USER";
820 		goto error;
821 	}
822 
823 	SIMPLEQ_INSERT_TAIL(&sc.child.pushing, c, entry);
824 	c->state = S_QUEUED;
825 
826 	event_del(&c->ev);
827 	event_set(&c->ev, fd, EV_READ | EV_PERSIST, identd_resolving, c);
828 	event_add(&c->ev, NULL);
829 
830 	event_add(&proc_wr, NULL);
831 	return;
832 
833 error:
834 	if (identd_error(c, errstr) == -1)
835 		goto fail;
836 
837 	return;
838 
839 fail:
840 	identd_close(c);
841 }
842 
843 int
identd_error(struct ident_client * c,const char * errstr)844 identd_error(struct ident_client *c, const char *errstr)
845 {
846 	int fd = EVENT_FD(&c->ev);
847 	ssize_t n;
848 
849 	n = asprintf(&c->buf, "%u , %u : ERROR : %s\r\n",
850 	    c->server.port, c->client.port, errstr);
851 	if (n == -1)
852 		return (-1);
853 
854 	c->buflen = n;
855 
856 	event_del(&c->ev);
857 	event_set(&c->ev, fd, EV_READ | EV_WRITE | EV_PERSIST,
858 	    identd_response, c);
859 	event_add(&c->ev, NULL);
860 
861 	return (0);
862 }
863 
864 void
identd_close(struct ident_client * c)865 identd_close(struct ident_client *c)
866 {
867 	int fd = EVENT_FD(&c->ev);
868 
869 	evtimer_del(&c->tmo);
870 	event_del(&c->ev);
871 	close(fd);
872 	free(c->buf);
873 	free(c);
874 }
875 
876 void
identd_resolving(int fd,short events,void * arg)877 identd_resolving(int fd, short events, void *arg)
878 {
879 	struct ident_client *c = arg;
880 	char buf[64];
881 	ssize_t n;
882 
883 	/*
884 	 * something happened while we're waiting for the parent to lookup
885 	 * the user.
886 	 */
887 
888 	n = read(fd, buf, sizeof(buf));
889 	switch (n) {
890 	case -1:
891 		switch (errno) {
892 		case EINTR:
893 		case EAGAIN:
894 			return;
895 		default:
896 			lwarn("resolving read");
897 			break;
898 		}
899 		break;
900 	case 0:
901 		ldebug("%s closed connection during resolving",
902 		    gethost(&c->client.ss));
903 		break;
904 	default:
905 		c->rxbytes += n;
906 		if (c->rxbytes >= INPUT_MAX)
907 			break;
908 
909 		/* ignore extra input */
910 		return;
911 	}
912 
913 	evtimer_del(&c->tmo);
914 	event_del(&c->ev);
915 	close(fd);
916 	c->state = S_DEAD; /* on the resolving queue */
917 }
918 
919 enum ident_client_state
identd_parse(struct ident_client * c,int ch)920 identd_parse(struct ident_client *c, int ch)
921 {
922 	enum ident_client_state s = c->state;
923 
924 	switch (s) {
925 	case S_BEGINNING:
926 		/* ignore leading space */
927 		if (ch == '\t' || ch == ' ')
928 			return (s);
929 
930 		if (ch == '0' || !isdigit(ch))
931 			return (S_DEAD);
932 
933 		c->server.port = ch - '0';
934 		return (S_SERVER_PORT);
935 
936 	case S_SERVER_PORT:
937 		if (ch == '\t' || ch == ' ')
938 			return (S_PRE_COMMA);
939 		if (ch == ',')
940 			return (S_POST_COMMA);
941 
942 		if (!isdigit(ch))
943 			return (S_DEAD);
944 
945 		c->server.port *= 10;
946 		c->server.port += ch - '0';
947 		if (c->server.port > 65535)
948 			return (S_DEAD);
949 
950 		return (s);
951 
952 	case S_PRE_COMMA:
953 		if (ch == '\t' || ch == ' ')
954 			return (s);
955 		if (ch == ',')
956 			return (S_POST_COMMA);
957 
958 		return (S_DEAD);
959 
960 	case S_POST_COMMA:
961 		if (ch == '\t' || ch == ' ')
962 			return (s);
963 
964 		if (ch == '0' || !isdigit(ch))
965 			return (S_DEAD);
966 
967 		c->client.port = ch - '0';
968 		return (S_CLIENT_PORT);
969 
970 	case S_CLIENT_PORT:
971 		if (ch == '\t' || ch == ' ')
972 			return (S_PRE_EOL);
973 		if (ch == '\r' || ch == '\n')
974 			return (S_EOL);
975 
976 		if (!isdigit(ch))
977 			return (S_DEAD);
978 
979 		c->client.port *= 10;
980 		c->client.port += ch - '0';
981 		if (c->client.port > 65535)
982 			return (S_DEAD);
983 
984 		return (s);
985 
986 	case S_PRE_EOL:
987 		if (ch == '\t' || ch == ' ')
988 			return (s);
989 		if (ch == '\r' || ch == '\n')
990 			return (S_EOL);
991 
992 		return (S_DEAD);
993 
994 	case S_EOL:
995 		/* ignore trailing garbage */
996 		return (s);
997 
998 	default:
999 		return (S_DEAD);
1000 	}
1001 }
1002 
1003 void
identd_response(int fd,short events,void * arg)1004 identd_response(int fd, short events, void *arg)
1005 {
1006 	struct ident_client *c = arg;
1007 	char buf[64];
1008 	ssize_t n;
1009 
1010 	if (events & EV_READ) {
1011 		n = read(fd, buf, sizeof(buf));
1012 		switch (n) {
1013 		case -1:
1014 			switch (errno) {
1015 			case EINTR:
1016 			case EAGAIN:
1017 				/* meh, try a write */
1018 				break;
1019 			default:
1020 				lwarn("response read");
1021 				goto done;
1022 			}
1023 			break;
1024 		case 0:
1025 			ldebug("%s closed connection during response",
1026 			    gethost(&c->client.ss));
1027 			goto done;
1028 		default:
1029 			c->rxbytes += n;
1030 			if (c->rxbytes >= INPUT_MAX)
1031 				goto done;
1032 
1033 			/* ignore extra input */
1034 			break;
1035 		}
1036 	}
1037 
1038 	if (!(events & EV_WRITE))
1039 		return; /* try again later */
1040 
1041 	n = write(fd, c->buf + c->bufoff, c->buflen - c->bufoff);
1042 	if (n == -1) {
1043 		switch (errno) {
1044 		case EINTR:
1045 		case EAGAIN:
1046 			return; /* try again later */
1047 		case EPIPE:
1048 			goto done;
1049 		default:
1050 			lwarn("response write");
1051 			goto done;
1052 		}
1053 	}
1054 
1055 	c->bufoff += n;
1056 	if (c->bufoff != c->buflen)
1057 		return; /* try again later */
1058 
1059 done:
1060 	identd_close(c);
1061 }
1062 
1063 void
syslog_vstrerror(int e,int priority,const char * fmt,va_list ap)1064 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap)
1065 {
1066 	char *s;
1067 
1068 	if (vasprintf(&s, fmt, ap) == -1) {
1069 		syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror");
1070 		exit(1);
1071 	}
1072 	syslog(priority, "%s: %s", s, strerror(e));
1073 	free(s);
1074 }
1075 
1076 void
syslog_err(int ecode,const char * fmt,...)1077 syslog_err(int ecode, const char *fmt, ...)
1078 {
1079 	va_list ap;
1080 
1081 	va_start(ap, fmt);
1082 	syslog_vstrerror(errno, LOG_CRIT, fmt, ap);
1083 	va_end(ap);
1084 	exit(ecode);
1085 }
1086 
1087 void
syslog_errx(int ecode,const char * fmt,...)1088 syslog_errx(int ecode, const char *fmt, ...)
1089 {
1090 	va_list ap;
1091 
1092 	va_start(ap, fmt);
1093 	vsyslog(LOG_CRIT, fmt, ap);
1094 	va_end(ap);
1095 	exit(ecode);
1096 }
1097 
1098 void
syslog_warn(const char * fmt,...)1099 syslog_warn(const char *fmt, ...)
1100 {
1101 	va_list ap;
1102 
1103 	va_start(ap, fmt);
1104 	syslog_vstrerror(errno, LOG_ERR, fmt, ap);
1105 	va_end(ap);
1106 }
1107 
1108 void
syslog_warnx(const char * fmt,...)1109 syslog_warnx(const char *fmt, ...)
1110 {
1111 	va_list ap;
1112 
1113 	va_start(ap, fmt);
1114 	vsyslog(LOG_ERR, fmt, ap);
1115 	va_end(ap);
1116 }
1117 
1118 void
syslog_notice(const char * fmt,...)1119 syslog_notice(const char *fmt, ...)
1120 {
1121 	va_list ap;
1122 
1123 	va_start(ap, fmt);
1124 	vsyslog(LOG_NOTICE, fmt, ap);
1125 	va_end(ap);
1126 }
1127 
1128 void
syslog_debug(const char * fmt,...)1129 syslog_debug(const char *fmt, ...)
1130 {
1131 	va_list ap;
1132 
1133 	if (!debug)
1134 		return;
1135 
1136 	va_start(ap, fmt);
1137 	vsyslog(LOG_DEBUG, fmt, ap);
1138 	va_end(ap);
1139 }
1140 
1141 const char *
gethost(struct sockaddr_storage * ss)1142 gethost(struct sockaddr_storage *ss)
1143 {
1144 	struct sockaddr *sa = (struct sockaddr *)ss;
1145 	static char buf[NI_MAXHOST];
1146 
1147 	if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf),
1148 	    NULL, 0, NI_NUMERICHOST) != 0)
1149 		return ("(unknown)");
1150 
1151 	return (buf);
1152 }
1153 
1154 const char *
gentoken(void)1155 gentoken(void)
1156 {
1157 	static char buf[21];
1158 	u_int32_t r;
1159 	int i;
1160 
1161 	buf[0] = 'a' + arc4random_uniform(26);
1162 	for (i = 1; i < sizeof(buf) - 1; i++) {
1163 		r = arc4random_uniform(36);
1164 		buf[i] = (r < 26 ? 'a' : '0' - 26) + r;
1165 	}
1166 	buf[i] = '\0';
1167 
1168 	return (buf);
1169 }
1170 
1171 int
fetchuid(struct ident_client * c)1172 fetchuid(struct ident_client *c)
1173 {
1174 	struct tcp_ident_mapping tir;
1175 	int mib[] = { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT };
1176 	struct sockaddr_in *s4;
1177 	struct sockaddr_in6 *s6;
1178 	int err = 0;
1179 	size_t len;
1180 
1181 	memset(&tir, 0, sizeof(tir));
1182 	memcpy(&tir.faddr, &c->client.ss, sizeof(tir.faddr));
1183 	memcpy(&tir.laddr, &c->server.ss, sizeof(tir.laddr));
1184 
1185 	switch (c->server.ss.ss_family) {
1186 	case AF_INET:
1187 		s4 = (struct sockaddr_in *)&tir.faddr;
1188 		s4->sin_port = htons(c->client.port);
1189 
1190 		s4 = (struct sockaddr_in *)&tir.laddr;
1191 		s4->sin_port = htons(c->server.port);
1192 		break;
1193 	case AF_INET6:
1194 		s6 = (struct sockaddr_in6 *)&tir.faddr;
1195 		s6->sin6_port = htons(c->client.port);
1196 
1197 		s6 = (struct sockaddr_in6 *)&tir.laddr;
1198 		s6->sin6_port = htons(c->server.port);
1199 		break;
1200 	default:
1201 		lerrx(1, "unexpected family %d", c->server.ss.ss_family);
1202 	}
1203 
1204 	len = sizeof(tir);
1205 	err = sysctl(mib, sizeof(mib) / sizeof(mib[0]), &tir, &len, NULL, 0);
1206 	if (err == -1)
1207 		lerr(1, "sysctl");
1208 
1209 	if (tir.ruid == -1)
1210 		return (-1);
1211 
1212 	c->uid = tir.ruid;
1213 	return (0);
1214 }
1215