1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "listener.h"
22 
23 #include "comms.h"
24 #include "cfg.h"
25 #include "zbxconf.h"
26 #include "stats.h"
27 #include "sysinfo.h"
28 #include "log.h"
29 
30 extern unsigned char			program_type;
31 extern ZBX_THREAD_LOCAL unsigned char	process_type;
32 extern ZBX_THREAD_LOCAL int		server_num, process_num;
33 
34 #if defined(ZABBIX_SERVICE)
35 #	include "service.h"
36 #elif defined(ZABBIX_DAEMON)
37 #	include "daemon.h"
38 #endif
39 
40 #include "zbxcrypto.h"
41 #include "../libs/zbxcrypto/tls_tcp_active.h"
42 
process_listener(zbx_socket_t * s)43 static void	process_listener(zbx_socket_t *s)
44 {
45 	AGENT_RESULT	result;
46 	char		**value = NULL;
47 	int		ret;
48 
49 	if (SUCCEED == (ret = zbx_tcp_recv_to(s, CONFIG_TIMEOUT)))
50 	{
51 		zbx_rtrim(s->buffer, "\r\n");
52 
53 		zabbix_log(LOG_LEVEL_DEBUG, "Requested [%s]", s->buffer);
54 
55 		init_result(&result);
56 
57 		if (SUCCEED == process(s->buffer, PROCESS_WITH_ALIAS, &result))
58 		{
59 			if (NULL != (value = GET_TEXT_RESULT(&result)))
60 			{
61 				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [%s]", *value);
62 				ret = zbx_tcp_send_to(s, *value, CONFIG_TIMEOUT);
63 			}
64 		}
65 		else
66 		{
67 			value = GET_MSG_RESULT(&result);
68 
69 			if (NULL != value)
70 			{
71 				static char	*buffer = NULL;
72 				static size_t	buffer_alloc = 256;
73 				size_t		buffer_offset = 0;
74 
75 				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED ": %s]", *value);
76 
77 				if (NULL == buffer)
78 					buffer = (char *)zbx_malloc(buffer, buffer_alloc);
79 
80 				zbx_strncpy_alloc(&buffer, &buffer_alloc, &buffer_offset,
81 						ZBX_NOTSUPPORTED, ZBX_CONST_STRLEN(ZBX_NOTSUPPORTED));
82 				buffer_offset++;
83 				zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, *value);
84 
85 				ret = zbx_tcp_send_bytes_to(s, buffer, buffer_offset, CONFIG_TIMEOUT);
86 			}
87 			else
88 			{
89 				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED "]");
90 
91 				ret = zbx_tcp_send_to(s, ZBX_NOTSUPPORTED, CONFIG_TIMEOUT);
92 			}
93 		}
94 
95 		free_result(&result);
96 	}
97 
98 	if (FAIL == ret)
99 		zabbix_log(LOG_LEVEL_DEBUG, "Process listener error: %s", zbx_socket_strerror());
100 }
101 
ZBX_THREAD_ENTRY(listener_thread,args)102 ZBX_THREAD_ENTRY(listener_thread, args)
103 {
104 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
105 	char		*msg = NULL;
106 #endif
107 	int		ret;
108 	zbx_socket_t	s;
109 
110 	assert(args);
111 	assert(((zbx_thread_args_t *)args)->args);
112 
113 	process_type = ((zbx_thread_args_t *)args)->process_type;
114 	server_num = ((zbx_thread_args_t *)args)->server_num;
115 	process_num = ((zbx_thread_args_t *)args)->process_num;
116 
117 	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
118 			server_num, get_process_type_string(process_type), process_num);
119 
120 	memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t));
121 
122 	zbx_free(args);
123 
124 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
125 	zbx_tls_init_child();
126 #endif
127 	while (ZBX_IS_RUNNING())
128 	{
129 		zbx_setproctitle("listener #%d [waiting for connection]", process_num);
130 		ret = zbx_tcp_accept(&s, configured_tls_accept_modes);
131 		zbx_update_env(zbx_time());
132 
133 		if (SUCCEED == ret)
134 		{
135 			zbx_setproctitle("listener #%d [processing request]", process_num);
136 
137 			if ('\0' != *CONFIG_HOSTS_ALLOWED &&
138 					SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED)))
139 			{
140 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
141 				if (ZBX_TCP_SEC_TLS_CERT != s.connection_type ||
142 						SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg)))
143 #endif
144 				{
145 					process_listener(&s);
146 				}
147 			}
148 
149 			zbx_tcp_unaccept(&s);
150 		}
151 
152 		if (SUCCEED == ret || EINTR == zbx_socket_last_error())
153 			continue;
154 
155 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
156 		if (NULL != msg)
157 		{
158 			zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg);
159 			zbx_free(msg);
160 		}
161 		else
162 #endif
163 		{
164 			zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s",
165 					zbx_socket_strerror());
166 		}
167 
168 		if (ZBX_IS_RUNNING())
169 			zbx_sleep(1);
170 	}
171 
172 #ifdef _WINDOWS
173 	ZBX_DO_EXIT();
174 
175 	zbx_thread_exit(EXIT_SUCCESS);
176 #else
177 	zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
178 
179 	while (1)
180 		zbx_sleep(SEC_PER_MIN);
181 #endif
182 }
183