1 /* upsd.c - watches ups state files and answers queries
2 
3    Copyright (C)
4 	1999		Russell Kroll <rkroll@exploits.org>
5 	2008		Arjen de Korte <adkorte-guest@alioth.debian.org>
6 	2011 - 2012	Arnaud Quette <arnaud.quette.free.fr>
7 	2019 		Eaton (author: Arnaud Quette <ArnaudQuette@eaton.com>)
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 
24 #include "upsd.h"
25 #include "upstype.h"
26 #include "conf.h"
27 
28 #include "netcmds.h"
29 #include "upsconf.h"
30 
31 #include <sys/un.h>
32 #include <sys/socket.h>
33 #include <netdb.h>
34 #include <signal.h>
35 
36 #include "user.h"
37 #include "nut_ctype.h"
38 #include "nut_stdint.h"
39 #include "stype.h"
40 #include "netssl.h"
41 #include "sstate.h"
42 #include "desc.h"
43 #include "neterr.h"
44 
45 #ifdef HAVE_WRAP
46 #include <tcpd.h>
47 int	allow_severity = LOG_INFO;
48 int	deny_severity = LOG_WARNING;
49 #endif	/* HAVE_WRAP */
50 
51 /* externally-visible settings and pointers */
52 
53 upstype_t	*firstups = NULL;
54 
55 /* default 15 seconds before data is marked stale */
56 int	maxage = 15;
57 
58 /* default to 1h before cleaning up status tracking entries */
59 int	tracking_delay = 3600;
60 
61 /*
62  * Preloaded to ALLOW_NO_DEVICE from upsd.conf or environment variable
63  * (with higher prio for envvar); defaults to disabled for legacy compat.
64  */
65 int allow_no_device = 0;
66 
67 /* preloaded to {OPEN_MAX} in main, can be overridden via upsd.conf */
68 nfds_t	maxconn = 0;
69 
70 /* preloaded to STATEPATH in main, can be overridden via upsd.conf */
71 char	*statepath = NULL;
72 
73 /* preloaded to DATADIR in main, can be overridden via upsd.conf */
74 char	*datapath = NULL;
75 
76 /* everything else */
77 static const char	*progname;
78 
79 nut_ctype_t	*firstclient = NULL;
80 /* static nut_ctype_t	*lastclient = NULL; */
81 
82 /* default is to listen on all local interfaces */
83 static stype_t	*firstaddr = NULL;
84 
85 static int 	opt_af = AF_UNSPEC;
86 
87 typedef enum {
88 	DRIVER = 1,
89 	CLIENT,
90 	SERVER
91 } handler_type_t;
92 
93 typedef struct {
94 	handler_type_t	type;
95 	void		*data;
96 } handler_t;
97 
98 
99 /* Commands and settings status tracking */
100 
101 /* general enable/disable status info for commands and settings
102  * (disabled by default)
103  * Note that only client that requested it will have it enabled
104  * (see nut_ctype.h) */
105 static int	tracking_enabled = 0;
106 
107 /* Commands and settings status tracking structure */
108 typedef struct tracking_s {
109 	char	*id;
110 	int	status;
111 	time_t	request_time; /* for cleanup */
112 	/* doubly linked list */
113 	struct tracking_s	*prev;
114 	struct tracking_s	*next;
115 } tracking_t;
116 
117 static tracking_t	*tracking_list = NULL;
118 
119 
120 	/* pollfd  */
121 static struct pollfd	*fds = NULL;
122 static handler_t	*handler = NULL;
123 
124 	/* pid file */
125 static char	pidfn[SMALLBUF];
126 
127 	/* set by signal handlers */
128 static int	reload_flag = 0, exit_flag = 0;
129 
130 /* Minimalistic support for UUID v4 */
131 /* Ref: RFC 4122 https://tools.ietf.org/html/rfc4122#section-4.1.2 */
132 #define UUID4_BYTESIZE 16
133 
134 
inet_ntopW(struct sockaddr_storage * s)135 static const char *inet_ntopW (struct sockaddr_storage *s)
136 {
137 	static char str[40];
138 
139 	switch (s->ss_family)
140 	{
141 	case AF_INET:
142 		return inet_ntop (AF_INET, &(((struct sockaddr_in *)s)->sin_addr), str, 16);
143 	case AF_INET6:
144 		return inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)s)->sin6_addr), str, 40);
145 	default:
146 		errno = EAFNOSUPPORT;
147 		return NULL;
148 	}
149 }
150 
151 /* return a pointer to the named ups if possible */
get_ups_ptr(const char * name)152 upstype_t *get_ups_ptr(const char *name)
153 {
154 	upstype_t	*tmp;
155 
156 	if (!name) {
157 		return NULL;
158 	}
159 
160 	for (tmp = firstups; tmp; tmp = tmp->next) {
161 		if (!strcasecmp(tmp->name, name)) {
162 			return tmp;
163 		}
164 	}
165 
166 	return NULL;
167 }
168 
169 /* mark the data stale if this is new, otherwise cleanup any remaining junk */
ups_data_stale(upstype_t * ups)170 static void ups_data_stale(upstype_t *ups)
171 {
172 	/* don't complain again if it's already known to be stale */
173 	if (ups->stale == 1) {
174 		return;
175 	}
176 
177 	ups->stale = 1;
178 
179 	upslogx(LOG_NOTICE, "Data for UPS [%s] is stale - check driver", ups->name);
180 }
181 
182 /* mark the data ok if this is new, otherwise do nothing */
ups_data_ok(upstype_t * ups)183 static void ups_data_ok(upstype_t *ups)
184 {
185 	if (ups->stale == 0) {
186 		return;
187 	}
188 
189 	ups->stale = 0;
190 
191 	upslogx(LOG_NOTICE, "UPS [%s] data is no longer stale", ups->name);
192 }
193 
194 /* add another listening address */
listen_add(const char * addr,const char * port)195 void listen_add(const char *addr, const char *port)
196 {
197 	stype_t	*server;
198 
199 	/* don't change listening addresses on reload */
200 	if (reload_flag) {
201 		return;
202 	}
203 
204 	/* grab some memory and add the info */
205 	server = xcalloc(1, sizeof(*server));
206 	server->addr = xstrdup(addr);
207 	server->port = xstrdup(port);
208 	server->sock_fd = -1;
209 	server->next = firstaddr;
210 
211 	firstaddr = server;
212 
213 	upsdebugx(3, "listen_add: added %s:%s", server->addr, server->port);
214 }
215 
216 /* create a listening socket for tcp connections */
setuptcp(stype_t * server)217 static void setuptcp(stype_t *server)
218 {
219 	struct addrinfo		hints, *res, *ai;
220 	int	v = 0, one = 1;
221 
222 	upsdebugx(3, "setuptcp: try to bind to %s port %s", server->addr, server->port);
223 
224 	memset(&hints, 0, sizeof(hints));
225 	hints.ai_flags		= AI_PASSIVE;
226 	hints.ai_family		= opt_af;
227 	hints.ai_socktype	= SOCK_STREAM;
228 	hints.ai_protocol	= IPPROTO_TCP;
229 
230 	if ((v = getaddrinfo(server->addr, server->port, &hints, &res)) != 0) {
231 		if (v == EAI_SYSTEM) {
232 			fatal_with_errno(EXIT_FAILURE, "getaddrinfo");
233 		}
234 
235 		fatalx(EXIT_FAILURE, "getaddrinfo: %s", gai_strerror(v));
236 	}
237 
238 	for (ai = res; ai; ai = ai->ai_next) {
239 		int sock_fd;
240 
241 		if ((sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) {
242 			upsdebug_with_errno(3, "setuptcp: socket");
243 			continue;
244 		}
245 
246 		if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0) {
247 			fatal_with_errno(EXIT_FAILURE, "setuptcp: setsockopt");
248 		}
249 
250 		if (bind(sock_fd, ai->ai_addr, ai->ai_addrlen) < 0) {
251 			upsdebug_with_errno(3, "setuptcp: bind");
252 			close(sock_fd);
253 			continue;
254 		}
255 
256 		if ((v = fcntl(sock_fd, F_GETFL, 0)) == -1) {
257 			fatal_with_errno(EXIT_FAILURE, "setuptcp: fcntl(get)");
258 		}
259 
260 		if (fcntl(sock_fd, F_SETFL, v | O_NDELAY) == -1) {
261 			fatal_with_errno(EXIT_FAILURE, "setuptcp: fcntl(set)");
262 		}
263 
264 		if (listen(sock_fd, 16) < 0) {
265 			upsdebug_with_errno(3, "setuptcp: listen");
266 			close(sock_fd);
267 			continue;
268 		}
269 
270 		server->sock_fd = sock_fd;
271 		break;
272 	}
273 
274 	freeaddrinfo(res);
275 
276 	/* leave up to the caller, server_load(), to fail silently if there is
277 	 * no other valid LISTEN interface */
278 	if (server->sock_fd < 0) {
279 		upslogx(LOG_ERR, "not listening on %s port %s", server->addr, server->port);
280 	} else {
281 		upslogx(LOG_INFO, "listening on %s port %s", server->addr, server->port);
282 	}
283 
284 	return;
285 }
286 
287 /* decrement the login counter for this ups */
declogins(const char * upsname)288 static void declogins(const char *upsname)
289 {
290 	upstype_t	*ups;
291 
292 	ups = get_ups_ptr(upsname);
293 
294 	if (!ups) {
295 		upslogx(LOG_INFO, "Tried to decrement invalid ups name (%s)", upsname);
296 		return;
297 	}
298 
299 	ups->numlogins--;
300 
301 	if (ups->numlogins < 0) {
302 		upslogx(LOG_ERR, "Programming error: UPS [%s] has numlogins=%d", ups->name, ups->numlogins);
303 	}
304 }
305 
306 /* disconnect a client connection and free all related memory */
client_disconnect(nut_ctype_t * client)307 static void client_disconnect(nut_ctype_t *client)
308 {
309 	if (!client) {
310 		return;
311 	}
312 
313 	upsdebugx(2, "Disconnect from %s", client->addr);
314 
315 	shutdown(client->sock_fd, 2);
316 	close(client->sock_fd);
317 
318 	if (client->loginups) {
319 		declogins(client->loginups);
320 	}
321 
322 	ssl_finish(client);
323 
324 	pconf_finish(&client->ctx);
325 
326 	if (client->prev) {
327 		client->prev->next = client->next;
328 	} else {
329 		/* deleting first entry */
330 		firstclient = client->next;
331 	}
332 
333 	if (client->next) {
334 		client->next->prev = client->prev;
335 	} else {
336 		/* deleting last entry */
337 		/* lastclient = client->prev; */
338 	}
339 
340 	free(client->addr);
341 	free(client->loginups);
342 	free(client->password);
343 	free(client->username);
344 	free(client);
345 
346 	return;
347 }
348 
349 /* send the buffer <sendbuf> of length <sendlen> to host <dest>
350  * returns effectively a boolean: 0 = failed, 1 = sent ok
351  */
sendback(nut_ctype_t * client,const char * fmt,...)352 int sendback(nut_ctype_t *client, const char *fmt, ...)
353 {
354 	ssize_t	res;
355 	size_t	len;
356 	char	ans[NUT_NET_ANSWER_MAX+1];
357 	va_list	ap;
358 
359 	if (!client) {
360 		return 0;
361 	}
362 
363 	va_start(ap, fmt);
364 	vsnprintf(ans, sizeof(ans), fmt, ap);
365 	va_end(ap);
366 
367 	len = strlen(ans);
368 
369 	/* System write() and our ssl_write() have a loophole that they write a
370 	 * size_t amount of bytes and upon success return that in ssize_t value
371 	 */
372 	assert(len < SSIZE_MAX);
373 
374 #ifdef WITH_SSL
375 	if (client->ssl) {
376 		res = ssl_write(client, ans, len);
377 	} else
378 #endif /* WITH_SSL */
379 	{
380 		res = write(client->sock_fd, ans, len);
381 	}
382 
383 	upsdebugx(2, "write: [destfd=%d] [len=%zu] [%s]", client->sock_fd, len, str_rtrim(ans, '\n'));
384 
385 	if (res < 0 || len != (size_t)res) {
386 		upslog_with_errno(LOG_NOTICE, "write() failed for %s", client->addr);
387 		client->last_heard = 0;
388 		return 0;	/* failed */
389 	}
390 
391 	return 1;	/* OK */
392 }
393 
394 /* just a simple wrapper for now */
send_err(nut_ctype_t * client,const char * errtype)395 int send_err(nut_ctype_t *client, const char *errtype)
396 {
397 	if (!client) {
398 		return -1;
399 	}
400 
401 	upsdebugx(4, "Sending error [%s] to client %s", errtype, client->addr);
402 
403 	return sendback(client, "ERR %s\n", errtype);
404 }
405 
406 /* disconnect anyone logged into this UPS */
kick_login_clients(const char * upsname)407 void kick_login_clients(const char *upsname)
408 {
409 	nut_ctype_t	*client, *cnext;
410 
411 	for (client = firstclient; client; client = cnext) {
412 
413 		cnext = client->next;
414 
415 		/* if it's not logged in, don't check it */
416 		if (!client->loginups) {
417 			continue;
418 		}
419 
420 		if (!strcmp(client->loginups, upsname)) {
421 			upslogx(LOG_INFO, "Kicking client %s (was on UPS [%s])\n", client->addr, upsname);
422 			client_disconnect(client);
423 		}
424 	}
425 }
426 
427 /* make sure a UPS is sane - connected, with fresh data */
ups_available(const upstype_t * ups,nut_ctype_t * client)428 int ups_available(const upstype_t *ups, nut_ctype_t *client)
429 {
430 	if (ups->sock_fd < 0) {
431 		send_err(client, NUT_ERR_DRIVER_NOT_CONNECTED);
432 		return 0;
433 	}
434 
435 	if (ups->stale) {
436 		send_err(client, NUT_ERR_DATA_STALE);
437 		return 0;
438 	}
439 
440 	/* must be OK */
441 	return 1;
442 }
443 
444 /* check flags and access for an incoming command from the network */
check_command(int cmdnum,nut_ctype_t * client,size_t numarg,const char ** arg)445 static void check_command(int cmdnum, nut_ctype_t *client, size_t numarg,
446 	const char **arg)
447 {
448 	if (netcmds[cmdnum].flags & FLAG_USER) {
449 #ifdef HAVE_WRAP
450 		struct request_info	req;
451 #endif	/* HAVE_WRAP */
452 
453 		if (!client->username) {
454 			send_err(client, NUT_ERR_USERNAME_REQUIRED);
455 			return;
456 		}
457 
458 		if (!client->password) {
459 			send_err(client, NUT_ERR_PASSWORD_REQUIRED);
460 			return;
461 		}
462 
463 #ifdef HAVE_WRAP
464 		request_init(&req, RQ_DAEMON, progname, RQ_FILE, client->sock_fd, RQ_USER, client->username, 0);
465 		fromhost(&req);
466 
467 		if (!hosts_access(&req)) {
468 			/* tcp-wrappers says access should be denied */
469 			send_err(client, NUT_ERR_ACCESS_DENIED);
470 			return;
471 		}
472 #endif	/* HAVE_WRAP */
473 	}
474 
475 	/* looks good - call the command */
476 	netcmds[cmdnum].func(client, (numarg < 2) ? 0 : (numarg - 1), (numarg > 1) ? &arg[1] : NULL);
477 }
478 
479 /* parse requests from the network */
parse_net(nut_ctype_t * client)480 static void parse_net(nut_ctype_t *client)
481 {
482 	int	i;
483 
484 	/* shouldn't happen */
485 	if (client->ctx.numargs < 1) {
486 		send_err(client, NUT_ERR_UNKNOWN_COMMAND);
487 		return;
488 	}
489 
490 	for (i = 0; netcmds[i].name; i++) {
491 		if (!strcasecmp(netcmds[i].name, client->ctx.arglist[0])) {
492 			check_command(i, client, client->ctx.numargs, (const char **) client->ctx.arglist);
493 			return;
494 		}
495 	}
496 
497 	/* fallthrough = not matched by any entry in netcmds */
498 
499 	send_err(client, NUT_ERR_UNKNOWN_COMMAND);
500 }
501 
502 /* answer incoming tcp connections */
client_connect(stype_t * server)503 static void client_connect(stype_t *server)
504 {
505 	struct	sockaddr_storage csock;
506 #if defined(__hpux) && !defined(_XOPEN_SOURCE_EXTENDED)
507 	int	clen;
508 #else
509 	socklen_t	clen;
510 #endif
511 	int		fd;
512 	nut_ctype_t		*client;
513 
514 	clen = sizeof(csock);
515 	fd = accept(server->sock_fd, (struct sockaddr *) &csock, &clen);
516 
517 	if (fd < 0) {
518 		return;
519 	}
520 
521 	client = xcalloc(1, sizeof(*client));
522 
523 	client->sock_fd = fd;
524 
525 	time(&client->last_heard);
526 
527 	client->addr = xstrdup(inet_ntopW(&csock));
528 
529 	client->tracking = 0;
530 
531 	pconf_init(&client->ctx, NULL);
532 
533 	if (firstclient) {
534 		firstclient->prev = client;
535 		client->next = firstclient;
536 	}
537 
538 	firstclient = client;
539 
540 /*
541 	if (lastclient) {
542 		client->prev = lastclient;
543 		lastclient->next = client;
544 	}
545 
546 	lastclient = client;
547  */
548 	upsdebugx(2, "Connect from %s", client->addr);
549 }
550 
551 /* read tcp messages and handle them */
client_readline(nut_ctype_t * client)552 static void client_readline(nut_ctype_t *client)
553 {
554 	char	buf[SMALLBUF];
555 	int	i;
556 	ssize_t	ret;
557 
558 #ifdef WITH_SSL
559 	if (client->ssl) {
560 		ret = ssl_read(client, buf, sizeof(buf));
561 	} else
562 #endif /* WITH_SSL */
563 	{
564 		ret = read(client->sock_fd, buf, sizeof(buf));
565 	}
566 
567 	if (ret < 0) {
568 		upsdebug_with_errno(2, "Disconnect %s (read failure)", client->addr);
569 		client_disconnect(client);
570 		return;
571 	}
572 
573 	if (ret == 0) {
574 		upsdebugx(2, "Disconnect %s (no data available)", client->addr);
575 		client_disconnect(client);
576 		return;
577 	}
578 
579 	/* fragment handling code */
580 	for (i = 0; i < ret; i++) {
581 
582 		/* add to the receive queue one by one */
583 		switch (pconf_char(&client->ctx, buf[i]))
584 		{
585 		case 1:
586 			time(&client->last_heard);	/* command received */
587 			parse_net(client);
588 			continue;
589 
590 		case 0:
591 			continue;	/* haven't gotten a line yet */
592 
593 		default:
594 			/* parse error */
595 			upslogx(LOG_NOTICE, "Parse error on sock: %s", client->ctx.errmsg);
596 			return;
597 		}
598 	}
599 
600 	return;
601 }
602 
server_load(void)603 void server_load(void)
604 {
605 	stype_t	*server;
606 
607 	/* default behaviour if no LISTEN addres has been specified */
608 	if (!firstaddr) {
609 		if (opt_af != AF_INET) {
610 			listen_add("::1", string_const(PORT));
611 		}
612 
613 		if (opt_af != AF_INET6) {
614 			listen_add("127.0.0.1", string_const(PORT));
615 		}
616 	}
617 
618 	for (server = firstaddr; server; server = server->next) {
619 		setuptcp(server);
620 	}
621 
622 	/* check if we have at least 1 valid LISTEN interface */
623 	if (firstaddr->sock_fd < 0) {
624 		fatalx(EXIT_FAILURE, "no listening interface available");
625 	}
626 }
627 
server_free(void)628 void server_free(void)
629 {
630 	stype_t	*server, *snext;
631 
632 	/* cleanup server fds */
633 	for (server = firstaddr; server; server = snext) {
634 		snext = server->next;
635 
636 		if (server->sock_fd != -1) {
637 			close(server->sock_fd);
638 		}
639 
640 		free(server->addr);
641 		free(server->port);
642 		free(server);
643 	}
644 
645 	firstaddr = NULL;
646 }
647 
client_free(void)648 static void client_free(void)
649 {
650 	nut_ctype_t		*client, *cnext;
651 
652 	/* cleanup client fds */
653 	for (client = firstclient; client; client = cnext) {
654 		cnext = client->next;
655 		client_disconnect(client);
656 	}
657 }
658 
driver_free(void)659 static void driver_free(void)
660 {
661 	upstype_t	*ups, *unext;
662 
663 	for (ups = firstups; ups; ups = unext) {
664 		unext = ups->next;
665 
666 		if (ups->sock_fd != -1) {
667 			close(ups->sock_fd);
668 		}
669 
670 		sstate_infofree(ups);
671 		sstate_cmdfree(ups);
672 
673 		pconf_finish(&ups->sock_ctx);
674 
675 		free(ups->fn);
676 		free(ups->name);
677 		free(ups->desc);
678 		free(ups);
679 	}
680 }
681 
upsd_cleanup(void)682 static void upsd_cleanup(void)
683 {
684 	if (strlen(pidfn) > 0) {
685 		unlink(pidfn);
686 	}
687 
688 	/* dump everything */
689 
690 	user_flush();
691 	desc_free();
692 
693 	server_free();
694 	client_free();
695 	driver_free();
696 	tracking_free();
697 
698 	free(statepath);
699 	free(datapath);
700 	free(certfile);
701 	free(certname);
702 	free(certpasswd);
703 
704 	free(fds);
705 	free(handler);
706 }
707 
poll_reload(void)708 static void poll_reload(void)
709 {
710 	long	ret;
711 
712 	ret = sysconf(_SC_OPEN_MAX);
713 
714 	if ((intmax_t)ret < (intmax_t)maxconn) {
715 		fatalx(EXIT_FAILURE,
716 			"Your system limits the maximum number of connections to %ld\n"
717 			"but you requested %jd. The server won't start until this\n"
718 			"problem is resolved.\n", ret, (intmax_t)maxconn);
719 	}
720 
721 	if (1 > maxconn) {
722 		fatalx(EXIT_FAILURE,
723 			"You requested %jd as maximum number of connections.\n"
724 			"The server won't start until this problem is resolved.\n", (intmax_t)maxconn);
725 	}
726 
727 	/* How many items can we stuff into the array? */
728 	size_t maxalloc = SIZE_MAX / sizeof(void *);
729 	if ((uintmax_t)maxalloc < (uintmax_t)maxconn) {
730 		fatalx(EXIT_FAILURE,
731 			"You requested %jd as maximum number of connections, but we can only allocate %zu.\n"
732 			"The server won't start until this problem is resolved.\n", (intmax_t)maxconn, maxalloc);
733 	}
734 
735 	/* The checks above effectively limit that maxconn is in size_t range */
736 	fds = xrealloc(fds, (size_t)maxconn * sizeof(*fds));
737 	handler = xrealloc(handler, (size_t)maxconn * sizeof(*handler));
738 }
739 
740 /* instant command and setvar status tracking */
741 
742 /* allocate a new status tracking entry */
tracking_add(const char * id)743 int tracking_add(const char *id)
744 {
745 	tracking_t	*item;
746 
747 	if ((!tracking_enabled) || (!id))
748 		return 0;
749 
750 	item = xcalloc(1, sizeof(*item));
751 
752 	item->id = xstrdup(id);
753 	item->status = STAT_PENDING;
754 	time(&item->request_time);
755 
756 	if (tracking_list) {
757 		tracking_list->prev = item;
758 		item->next = tracking_list;
759 	}
760 
761 	tracking_list = item;
762 
763 	return 1;
764 }
765 
766 /* set status of a specific tracking entry */
tracking_set(const char * id,const char * value)767 int tracking_set(const char *id, const char *value)
768 {
769 	tracking_t	*item, *next_item;
770 
771 	/* sanity checks */
772 	if ((!tracking_list) || (!id) || (!value))
773 		return 0;
774 
775 	for (item = tracking_list; item; item = next_item) {
776 
777 		next_item = item->next;
778 
779 		if (!strcasecmp(item->id, id)) {
780 			item->status = atoi(value);
781 			return 1;
782 		}
783 	}
784 
785 	return 0; /* id not found! */
786 }
787 
788 /* free a specific tracking entry */
tracking_del(const char * id)789 int tracking_del(const char *id)
790 {
791 	tracking_t	*item, *next_item;
792 
793 	/* sanity check */
794 	if ((!tracking_list) || (!id))
795 		return 0;
796 
797 	upsdebugx(3, "%s: deleting id %s", __func__, id);
798 
799 	for (item = tracking_list; item; item = next_item) {
800 
801 		next_item = item->next;
802 
803 		if (strcasecmp(item->id, id))
804 			continue;
805 
806 		if (item->prev)
807 			item->prev->next = item->next;
808 		else
809 			/* deleting first entry */
810 			tracking_list = item->next;
811 
812 		if (item->next)
813 			item->next->prev = item->prev;
814 
815 		free(item->id);
816 		free(item);
817 
818 		return 1;
819 
820 	}
821 
822 	return 0; /* id not found! */
823 }
824 
825 /* free all status tracking entries */
tracking_free(void)826 void tracking_free(void)
827 {
828 	tracking_t	*item, *next_item;
829 
830 	/* sanity check */
831 	if (!tracking_list)
832 		return;
833 
834 	upsdebugx(3, "%s", __func__);
835 
836 	for (item = tracking_list; item; item = next_item) {
837 		next_item = item->next;
838 		tracking_del(item->id);
839 	}
840 }
841 
842 /* cleanup status tracking entries according to their age and tracking_delay */
tracking_cleanup(void)843 void tracking_cleanup(void)
844 {
845 	tracking_t	*item, *next_item;
846 	time_t	now;
847 
848 	/* sanity check */
849 	if (!tracking_list)
850 		return;
851 
852 	time(&now);
853 
854 	upsdebugx(3, "%s", __func__);
855 
856 	for (item = tracking_list; item; item = next_item) {
857 
858 		next_item = item->next;
859 
860 		if (difftime(now, item->request_time) > tracking_delay) {
861 			tracking_del(item->id);
862 		}
863 	}
864 }
865 
866 /* get status of a specific tracking entry */
tracking_get(const char * id)867 char *tracking_get(const char *id)
868 {
869 	tracking_t	*item, *next_item;
870 
871 	/* sanity checks */
872 	if ((!tracking_list) || (!id))
873 		return "ERR UNKNOWN";
874 
875 	for (item = tracking_list; item; item = next_item) {
876 
877 		next_item = item->next;
878 
879 		if (strcasecmp(item->id, id))
880 			continue;
881 
882 		switch (item->status)
883 		{
884 		case STAT_PENDING:
885 			return "PENDING";
886 		case STAT_HANDLED:
887 			return "SUCCESS";
888 		case STAT_UNKNOWN:
889 			return "ERR UNKNOWN";
890 		case STAT_INVALID:
891 			return "ERR INVALID-ARGUMENT";
892 		case STAT_FAILED:
893 			return "ERR FAILED";
894 		}
895 	}
896 
897 	return "ERR UNKNOWN"; /* id not found! */
898 }
899 
900 /* enable general status tracking (tracking_enabled) and return its value (1). */
tracking_enable(void)901 int tracking_enable(void)
902 {
903 	tracking_enabled = 1;
904 
905 	return tracking_enabled;
906 }
907 
908 /* disable general status tracking only if no client use it anymore.
909  * return the new value for tracking_enabled */
tracking_disable(void)910 int tracking_disable(void)
911 {
912 	nut_ctype_t		*client, *cnext;
913 
914 	for (client = firstclient; client; client = cnext) {
915 		cnext = client->next;
916 		if (client->tracking == 1)
917 			return 1;
918 	}
919 	return 0;
920 }
921 
922 /* return current general status of tracking (tracking_enabled). */
tracking_is_enabled(void)923 int tracking_is_enabled(void)
924 {
925 	return tracking_enabled;
926 }
927 
928 /* UUID v4 basic implementation
929  * Note: 'dest' must be at least `UUID4_LEN` long */
nut_uuid_v4(char * uuid_str)930 int nut_uuid_v4(char *uuid_str)
931 {
932 	size_t		i;
933 	uint8_t nut_uuid[UUID4_BYTESIZE];
934 
935 	if (!uuid_str)
936 		return 0;
937 
938 	for (i = 0; i < UUID4_BYTESIZE; i++)
939 		nut_uuid[i] = (uint8_t)rand() + (uint8_t)rand();
940 
941 	/* set variant and version */
942 	nut_uuid[6] = (nut_uuid[6] & 0x0F) | 0x40;
943 	nut_uuid[8] = (nut_uuid[8] & 0x3F) | 0x80;
944 
945 	return snprintf(uuid_str, UUID4_LEN,
946 		"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
947 		nut_uuid[0], nut_uuid[1], nut_uuid[2], nut_uuid[3],
948 		nut_uuid[4], nut_uuid[5], nut_uuid[6], nut_uuid[7],
949 		nut_uuid[8], nut_uuid[9], nut_uuid[10], nut_uuid[11],
950 		nut_uuid[12], nut_uuid[13], nut_uuid[14], nut_uuid[15]);
951 }
952 
953 /* service requests and check on new data */
mainloop(void)954 static void mainloop(void)
955 {
956 	int	ret;
957 	nfds_t	i, nfds = 0;
958 
959 	upstype_t	*ups;
960 	nut_ctype_t		*client, *cnext;
961 	stype_t		*server;
962 	time_t	now;
963 
964 	time(&now);
965 
966 	if (reload_flag) {
967 		conf_reload();
968 		poll_reload();
969 		reload_flag = 0;
970 	}
971 
972 	/* cleanup instcmd/setvar status tracking entries if needed */
973 	tracking_cleanup();
974 
975 	/* scan through driver sockets */
976 	for (ups = firstups; ups && (nfds < maxconn); ups = ups->next) {
977 
978 		/* see if we need to (re)connect to the socket */
979 		if (ups->sock_fd < 0) {
980 			ups->sock_fd = sstate_connect(ups);
981 			continue;
982 		}
983 
984 		/* throw some warnings if it's not feeding us data any more */
985 		if (sstate_dead(ups, maxage)) {
986 			ups_data_stale(ups);
987 		} else {
988 			ups_data_ok(ups);
989 		}
990 
991 		fds[nfds].fd = ups->sock_fd;
992 		fds[nfds].events = POLLIN;
993 
994 		handler[nfds].type = DRIVER;
995 		handler[nfds].data = ups;
996 
997 		nfds++;
998 	}
999 
1000 	/* scan through client sockets */
1001 	for (client = firstclient; client; client = cnext) {
1002 
1003 		cnext = client->next;
1004 
1005 		if (difftime(now, client->last_heard) > 60) {
1006 			/* shed clients after 1 minute of inactivity */
1007 			/* FIXME: create an upsd.conf parameter (CLIENT_INACTIVITY_DELAY) */
1008 			client_disconnect(client);
1009 			continue;
1010 		}
1011 
1012 		if (nfds >= maxconn) {
1013 			/* ignore clients that we are unable to handle */
1014 			continue;
1015 		}
1016 
1017 		fds[nfds].fd = client->sock_fd;
1018 		fds[nfds].events = POLLIN;
1019 
1020 		handler[nfds].type = CLIENT;
1021 		handler[nfds].data = client;
1022 
1023 		nfds++;
1024 	}
1025 
1026 	/* scan through server sockets */
1027 	for (server = firstaddr; server && (nfds < maxconn); server = server->next) {
1028 
1029 		if (server->sock_fd < 0) {
1030 			continue;
1031 		}
1032 
1033 		fds[nfds].fd = server->sock_fd;
1034 		fds[nfds].events = POLLIN;
1035 
1036 		handler[nfds].type = SERVER;
1037 		handler[nfds].data = server;
1038 
1039 		nfds++;
1040 	}
1041 
1042 	upsdebugx(2, "%s: polling %jd filedescriptors", __func__, (intmax_t)nfds);
1043 
1044 	ret = poll(fds, nfds, 2000);
1045 
1046 	if (ret == 0) {
1047 		upsdebugx(2, "%s: no data available", __func__);
1048 		return;
1049 	}
1050 
1051 	if (ret < 0) {
1052 		upslog_with_errno(LOG_ERR, "%s", __func__);
1053 		return;
1054 	}
1055 
1056 	for (i = 0; i < nfds; i++) {
1057 
1058 		if (fds[i].revents & (POLLHUP|POLLERR|POLLNVAL)) {
1059 
1060 			switch(handler[i].type)
1061 			{
1062 			case DRIVER:
1063 				sstate_disconnect((upstype_t *)handler[i].data);
1064 				break;
1065 			case CLIENT:
1066 				client_disconnect((nut_ctype_t *)handler[i].data);
1067 				break;
1068 			case SERVER:
1069 				upsdebugx(2, "%s: server disconnected", __func__);
1070 				break;
1071 
1072 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
1073 # pragma GCC diagnostic push
1074 # pragma GCC diagnostic ignored "-Wcovered-switch-default"
1075 #endif
1076 			/* All enum cases defined as of the time of coding
1077 			 * have been covered above. Handle later definitions,
1078 			 * memory corruptions and buggy inputs below...
1079 			 */
1080 			default:
1081 				upsdebugx(2, "%s: <unknown> disconnected", __func__);
1082 				break;
1083 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
1084 # pragma GCC diagnostic pop
1085 #endif
1086 
1087 			}
1088 
1089 			continue;
1090 		}
1091 
1092 		if (fds[i].revents & POLLIN) {
1093 
1094 			switch(handler[i].type)
1095 			{
1096 			case DRIVER:
1097 				sstate_readline((upstype_t *)handler[i].data);
1098 				break;
1099 			case CLIENT:
1100 				client_readline((nut_ctype_t *)handler[i].data);
1101 				break;
1102 			case SERVER:
1103 				client_connect((stype_t *)handler[i].data);
1104 				break;
1105 
1106 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
1107 # pragma GCC diagnostic push
1108 # pragma GCC diagnostic ignored "-Wcovered-switch-default"
1109 #endif
1110 			/* All enum cases defined as of the time of coding
1111 			 * have been covered above. Handle later definitions,
1112 			 * memory corruptions and buggy inputs below...
1113 			 */
1114 			default:
1115 				upsdebugx(2, "%s: <unknown> has data available", __func__);
1116 				break;
1117 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_COVERED_SWITCH_DEFAULT)
1118 # pragma GCC diagnostic pop
1119 #endif
1120 			}
1121 
1122 			continue;
1123 		}
1124 	}
1125 }
1126 
1127 static void help(const char *arg_progname)
1128 	__attribute__((noreturn));
1129 
help(const char * arg_progname)1130 static void help(const char *arg_progname)
1131 {
1132 	printf("Network server for UPS data.\n\n");
1133 	printf("usage: %s [OPTIONS]\n", arg_progname);
1134 
1135 	printf("\n");
1136 	printf("  -c <command>	send <command> via signal to background process\n");
1137 	printf("		commands:\n");
1138 	printf("		 - reload: reread configuration files\n");
1139 	printf("		 - stop: stop process and exit\n");
1140 	printf("  -D		raise debugging level\n");
1141 	printf("  -h		display this help\n");
1142 	printf("  -r <dir>	chroots to <dir>\n");
1143 	printf("  -q		raise log level threshold\n");
1144 	printf("  -u <user>	switch to <user> (if started as root)\n");
1145 	printf("  -V		display the version of this software\n");
1146 	printf("  -4		IPv4 only\n");
1147 	printf("  -6		IPv6 only\n");
1148 
1149 	exit(EXIT_SUCCESS);
1150 }
1151 
set_reload_flag(int sig)1152 static void set_reload_flag(int sig)
1153 {
1154 	NUT_UNUSED_VARIABLE(sig);
1155 	reload_flag = 1;
1156 }
1157 
set_exit_flag(int sig)1158 static void set_exit_flag(int sig)
1159 {
1160 	exit_flag = sig;
1161 }
1162 
setup_signals(void)1163 static void setup_signals(void)
1164 {
1165 	struct sigaction	sa;
1166 
1167 	sigemptyset(&sa.sa_mask);
1168 	sigaddset(&sa.sa_mask, SIGHUP);
1169 	sa.sa_flags = 0;
1170 
1171 	/* basic signal setup to ignore SIGPIPE */
1172 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
1173 # pragma GCC diagnostic push
1174 # pragma GCC diagnostic ignored "-Wstrict-prototypes"
1175 #endif
1176 	sa.sa_handler = SIG_IGN;
1177 #if (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_PUSH_POP) && (defined HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_STRICT_PROTOTYPES)
1178 # pragma GCC diagnostic pop
1179 #endif
1180 	sigaction(SIGPIPE, &sa, NULL);
1181 
1182 	/* handle shutdown signals */
1183 	sa.sa_handler = set_exit_flag;
1184 	sigaction(SIGINT, &sa, NULL);
1185 	sigaction(SIGQUIT, &sa, NULL);
1186 	sigaction(SIGTERM, &sa, NULL);
1187 
1188 	/* handle reloading */
1189 	sa.sa_handler = set_reload_flag;
1190 	sigaction(SIGHUP, &sa, NULL);
1191 }
1192 
check_perms(const char * fn)1193 void check_perms(const char *fn)
1194 {
1195 	int	ret;
1196 	struct stat	st;
1197 
1198 	ret = stat(fn, &st);
1199 
1200 	if (ret != 0) {
1201 		fatal_with_errno(EXIT_FAILURE, "stat %s", fn);
1202 	}
1203 
1204 	/* include the x bit here in case we check a directory */
1205 	if (st.st_mode & (S_IROTH | S_IXOTH)) {
1206 		upslogx(LOG_WARNING, "%s is world readable", fn);
1207 	}
1208 }
1209 
main(int argc,char ** argv)1210 int main(int argc, char **argv)
1211 {
1212 	int	i, cmd = 0, cmdret = 0;
1213 	char	*chroot_path = NULL;
1214 	const char	*user = RUN_AS_USER;
1215 	struct passwd	*new_uid = NULL;
1216 
1217 	progname = xbasename(argv[0]);
1218 
1219 	/* yes, xstrdup - the conf handlers call free on this later */
1220 	statepath = xstrdup(dflt_statepath());
1221 	datapath = xstrdup(DATADIR);
1222 
1223 	/* set up some things for later */
1224 	snprintf(pidfn, sizeof(pidfn), "%s/%s.pid", altpidpath(), progname);
1225 
1226 	printf("Network UPS Tools %s %s\n", progname, UPS_VERSION);
1227 
1228 	while ((i = getopt(argc, argv, "+h46p:qr:i:fu:Vc:D")) != -1) {
1229 		switch (i) {
1230 			case 'p':
1231 			case 'i':
1232 				fatalx(EXIT_FAILURE, "Specifying a listening addresses with '-i <address>' and '-p <port>'\n"
1233 					"is deprecated. Use 'LISTEN <address> [<port>]' in 'upsd.conf' instead.\n"
1234 					"See 'man 8 upsd.conf' for more information.");
1235 #ifndef HAVE___ATTRIBUTE__NORETURN
1236 					exit(EXIT_FAILURE);	/* Should not get here in practice, but compiler is afraid we can fall through */
1237 #endif
1238 
1239 			case 'q':
1240 				nut_log_level++;
1241 				break;
1242 
1243 			case 'r':
1244 				chroot_path = optarg;
1245 				break;
1246 
1247 			case 'u':
1248 				user = optarg;
1249 				break;
1250 
1251 			case 'V':
1252 				/* do nothing - we already printed the banner */
1253 				exit(EXIT_SUCCESS);
1254 
1255 			case 'c':
1256 				if (!strncmp(optarg, "reload", strlen(optarg)))
1257 					cmd = SIGCMD_RELOAD;
1258 				if (!strncmp(optarg, "stop", strlen(optarg)))
1259 					cmd = SIGCMD_STOP;
1260 
1261 				/* bad command given */
1262 				if (cmd == 0)
1263 					help(progname);
1264 				break;
1265 
1266 			case 'D':
1267 				nut_debug_level++;
1268 				break;
1269 
1270 			case '4':
1271 				opt_af = AF_INET;
1272 				break;
1273 
1274 			case '6':
1275 				opt_af = AF_INET6;
1276 				break;
1277 
1278 			case 'h':
1279 			default:
1280 				help(progname);
1281 		}
1282 	}
1283 
1284 	if (cmd) {
1285 		cmdret = sendsignalfn(pidfn, cmd);
1286 		exit((cmdret == 0)?EXIT_SUCCESS:EXIT_FAILURE);
1287 	}
1288 
1289 	/* otherwise, we are being asked to start.
1290 	 * so check if a previous instance is running by sending signal '0'
1291 	 * (Ie 'kill <pid> 0') */
1292 	if (sendsignalfn(pidfn, 0) == 0) {
1293 		printf("Fatal error: A previous upsd instance is already running!\n");
1294 		printf("Either stop the previous instance first, or use the 'reload' command.\n");
1295 		exit(EXIT_FAILURE);
1296 	}
1297 
1298 	argc -= optind;
1299 	argv += optind;
1300 
1301 	if (argc != 0) {
1302 		help(progname);
1303 	}
1304 
1305 	atexit(upsd_cleanup);
1306 
1307 	setup_signals();
1308 
1309 	open_syslog(progname);
1310 
1311 	/* send logging to the syslog pre-background for later use */
1312 	syslogbit_set();
1313 
1314 	/* do this here, since getpwnam() might not work in the chroot */
1315 	new_uid = get_user_pwent(user);
1316 
1317 	if (chroot_path) {
1318 		chroot_start(chroot_path);
1319 	}
1320 
1321 	/* default to system limit (may be overridden in upsd.conf) */
1322 	/* FIXME: Check for overflows (and int size of nfds_t vs. long) - see get_max_pid_t() for example */
1323 	maxconn = (nfds_t)sysconf(_SC_OPEN_MAX);
1324 
1325 	/* handle upsd.conf */
1326 	load_upsdconf(0);	/* 0 = initial */
1327 
1328 	{ // scope
1329 	/* As documented above, the ALLOW_NO_DEVICE can be provided via
1330 	 * envvars and then has higher priority than an upsd.conf setting
1331 	 */
1332 	const char *envvar = getenv("ALLOW_NO_DEVICE");
1333 	if ( envvar != NULL) {
1334 		if ( (!strncasecmp("TRUE", envvar, 4)) || (!strncasecmp("YES", envvar, 3)) || (!strncasecmp("ON", envvar, 2)) || (!strncasecmp("1", envvar, 1)) ) {
1335 			/* Admins of this server expressed a desire to serve
1336 			 * anything on the NUT protocol, even if nothing is
1337 			 * configured yet - tell the clients so, properly.
1338 			 */
1339 			allow_no_device = 1;
1340 		} else if ( (!strncasecmp("FALSE", envvar, 5)) || (!strncasecmp("NO", envvar, 2)) || (!strncasecmp("OFF", envvar, 3)) || (!strncasecmp("0", envvar, 1)) ) {
1341 			/* Admins of this server expressed a desire to serve
1342 			 * anything on the NUT protocol, even if nothing is
1343 			 * configured yet - tell the clients so, properly.
1344 			 */
1345 			allow_no_device = 0;
1346 		}
1347 	}
1348 	} // scope
1349 
1350 	/* start server */
1351 	server_load();
1352 
1353 	become_user(new_uid);
1354 
1355 	if (chdir(statepath)) {
1356 		fatal_with_errno(EXIT_FAILURE, "Can't chdir to %s", statepath);
1357 	}
1358 
1359 	/* check statepath perms */
1360 	check_perms(statepath);
1361 
1362 	/* handle ups.conf */
1363 	read_upsconf();
1364 	upsconf_add(0);		/* 0 = initial */
1365 	poll_reload();
1366 
1367 	if (num_ups == 0) {
1368 		if (allow_no_device) {
1369 			upslogx(LOG_WARNING, "Normally at least one UPS must be defined in ups.conf, currently there are none (please configure the file and reload the service)");
1370 		} else {
1371 			fatalx(EXIT_FAILURE, "Fatal error: at least one UPS must be defined in ups.conf");
1372 		}
1373 	}
1374 
1375 	/* try to bring in the var/cmd descriptions */
1376 	desc_load();
1377 
1378 	/* handle upsd.users */
1379 	user_load();
1380 
1381 	if (!nut_debug_level) {
1382 		background();
1383 		writepid(pidfn);
1384 	} else {
1385 		memset(pidfn, 0, sizeof(pidfn));
1386 	}
1387 
1388 	/* initialize SSL (keyfile must be readable by nut user) */
1389 	ssl_init();
1390 
1391 	while (!exit_flag) {
1392 		mainloop();
1393 	}
1394 
1395 	ssl_cleanup();
1396 
1397 	upslogx(LOG_INFO, "Signal %d: exiting", exit_flag);
1398 	return EXIT_SUCCESS;
1399 }
1400 
1401