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 "db.h"
22 #include "log.h"
23 #include "proxy.h"
24 
25 #include "proxydata.h"
26 #include "../../libs/zbxcrypto/tls_tcp_active.h"
27 #include "zbxtasks.h"
28 #include "mutexs.h"
29 #include "daemon.h"
30 #include "zbxcompress.h"
31 
32 extern unsigned char	program_type;
33 static zbx_mutex_t	proxy_lock = ZBX_MUTEX_NULL;
34 
35 #define	LOCK_PROXY_HISTORY	if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) zbx_mutex_lock(proxy_lock)
36 #define	UNLOCK_PROXY_HISTORY	if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) zbx_mutex_unlock(proxy_lock)
37 
zbx_send_proxy_data_response(const DC_PROXY * proxy,zbx_socket_t * sock,const char * info,int upload_status)38 int	zbx_send_proxy_data_response(const DC_PROXY *proxy, zbx_socket_t *sock, const char *info, int upload_status)
39 {
40 	struct zbx_json		json;
41 	zbx_vector_ptr_t	tasks;
42 	int			ret, flags = ZBX_TCP_PROTOCOL, status;
43 
44 	zbx_vector_ptr_create(&tasks);
45 
46 	zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
47 
48 	switch (upload_status)
49 	{
50 		case ZBX_PROXY_UPLOAD_DISABLED:
51 			zbx_json_addstring(&json, ZBX_PROTO_TAG_PROXY_UPLOAD, ZBX_PROTO_VALUE_PROXY_UPLOAD_DISABLED,
52 					ZBX_JSON_TYPE_STRING);
53 			status = FAIL;
54 			break;
55 		case ZBX_PROXY_UPLOAD_ENABLED:
56 			zbx_json_addstring(&json, ZBX_PROTO_TAG_PROXY_UPLOAD, ZBX_PROTO_VALUE_PROXY_UPLOAD_ENABLED,
57 					ZBX_JSON_TYPE_STRING);
58 			ZBX_FALLTHROUGH;
59 		default:
60 			status = SUCCEED;
61 	}
62 
63 	if (SUCCEED == status)
64 	{
65 		zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
66 		zbx_tm_get_remote_tasks(&tasks, proxy->hostid);
67 	}
68 	else
69 		zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
70 
71 	if (NULL != info && '\0' != *info)
72 		zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, info, ZBX_JSON_TYPE_STRING);
73 
74 	if (0 != tasks.values_num)
75 		zbx_tm_json_serialize_tasks(&json, &tasks);
76 
77 	if (0 != proxy->auto_compress)
78 		flags |= ZBX_TCP_COMPRESS;
79 
80 	if (SUCCEED == (ret = zbx_tcp_send_ext(sock, json.buffer, strlen(json.buffer), 0, flags, 0)))
81 	{
82 		if (0 != tasks.values_num)
83 			zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_INPROGRESS);
84 	}
85 
86 	zbx_json_free(&json);
87 
88 	zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
89 	zbx_vector_ptr_destroy(&tasks);
90 
91 	return ret;
92 }
93 
94 /******************************************************************************
95  *                                                                            *
96  * Function: zbx_recv_proxy_data                                              *
97  *                                                                            *
98  * Purpose: receive 'proxy data' request from proxy                           *
99  *                                                                            *
100  * Parameters: sock - [IN] the connection socket                              *
101  *             jp   - [IN] the received JSON data                             *
102  *             ts   - [IN] the connection timestamp                           *
103  *                                                                            *
104  ******************************************************************************/
zbx_recv_proxy_data(zbx_socket_t * sock,struct zbx_json_parse * jp,zbx_timespec_t * ts)105 void	zbx_recv_proxy_data(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts)
106 {
107 	int			ret = FAIL, upload_status = 0, status, version, responded = 0;
108 	char			*error = NULL;
109 	DC_PROXY		proxy;
110 
111 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
112 
113 	if (SUCCEED != (status = get_active_proxy_from_request(jp, &proxy, &error)))
114 	{
115 		zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy data from active proxy at \"%s\": %s",
116 				sock->peer, error);
117 		goto out;
118 	}
119 
120 	if (SUCCEED != (status = zbx_proxy_check_permissions(&proxy, sock, &error)))
121 	{
122 		zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:"
123 				" \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error);
124 		goto out;
125 	}
126 
127 	version = zbx_get_proxy_protocol_version(jp);
128 
129 	if (SUCCEED != zbx_check_protocol_version(&proxy, version))
130 	{
131 		goto out;
132 	}
133 
134 	if (FAIL == (ret = zbx_hc_check_proxy(proxy.hostid)))
135 	{
136 		upload_status = ZBX_PROXY_UPLOAD_DISABLED;
137 	}
138 	else
139 	{
140 		upload_status = ZBX_PROXY_UPLOAD_ENABLED;
141 
142 		if (SUCCEED != (ret = process_proxy_data(&proxy, jp, ts, HOST_STATUS_PROXY_ACTIVE, NULL, &error)))
143 		{
144 			zabbix_log(LOG_LEVEL_WARNING, "received invalid proxy data from proxy \"%s\" at \"%s\": %s",
145 					proxy.host, sock->peer, error);
146 			goto out;
147 		}
148 	}
149 
150 	if (!ZBX_IS_RUNNING())
151 	{
152 		error = zbx_strdup(error, "Zabbix server shutdown in progress");
153 		zabbix_log(LOG_LEVEL_WARNING, "cannot process proxy data from active proxy at \"%s\": %s",
154 				sock->peer, error);
155 		ret = FAIL;
156 		goto out;
157 	}
158 
159 	zbx_send_proxy_data_response(&proxy, sock, error, upload_status);
160 	responded = 1;
161 
162 out:
163 	if (SUCCEED == status)	/* moved the unpredictable long operation to the end */
164 				/* we are trying to save info about lastaccess to detect communication problem */
165 	{
166 		zbx_update_proxy_data(&proxy, version, ts->sec,
167 				(0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0), 0);
168 	}
169 
170 	if (0 == responded)
171 	{
172 		int	flags = ZBX_TCP_PROTOCOL;
173 
174 		if (0 != (sock->protocol & ZBX_TCP_COMPRESS))
175 			flags |= ZBX_TCP_COMPRESS;
176 
177 		zbx_send_response_ext(sock, ret, error, NULL, flags, CONFIG_TIMEOUT);
178 	}
179 
180 	zbx_free(error);
181 
182 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
183 }
184 
185 /******************************************************************************
186  *                                                                            *
187  * Function: send_data_to_server                                              *
188  *                                                                            *
189  * Purpose: sends data from proxy to server                                   *
190  *                                                                            *
191  * Parameters: sock  - [IN] the connection socket                             *
192  *             data  - [IN] the data to send                                  *
193  *             error - [OUT] the error message                                *
194  *                                                                            *
195  ******************************************************************************/
send_data_to_server(zbx_socket_t * sock,char ** buffer,size_t buffer_size,size_t reserved,char ** error)196 static int	send_data_to_server(zbx_socket_t *sock, char **buffer, size_t buffer_size, size_t reserved,
197 		char **error)
198 {
199 	if (SUCCEED != zbx_tcp_send_ext(sock, *buffer, buffer_size, reserved, ZBX_TCP_PROTOCOL | ZBX_TCP_COMPRESS,
200 			CONFIG_TIMEOUT))
201 	{
202 		*error = zbx_strdup(*error, zbx_socket_strerror());
203 		return FAIL;
204 	}
205 
206 	zbx_free(*buffer);
207 
208 	if (SUCCEED != zbx_recv_response(sock, CONFIG_TIMEOUT, error))
209 		return FAIL;
210 
211 	return SUCCEED;
212 }
213 
214 /******************************************************************************
215  *                                                                            *
216  * Function: zbx_send_proxy_data                                              *
217  *                                                                            *
218  * Purpose: sends 'proxy data' request to server                              *
219  *                                                                            *
220  * Parameters: sock - [IN] the connection socket                              *
221  *             ts   - [IN] the connection timestamp                           *
222  *                                                                            *
223  ******************************************************************************/
zbx_send_proxy_data(zbx_socket_t * sock,zbx_timespec_t * ts)224 void	zbx_send_proxy_data(zbx_socket_t *sock, zbx_timespec_t *ts)
225 {
226 	struct zbx_json		j;
227 	zbx_uint64_t		areg_lastid = 0, history_lastid = 0, discovery_lastid = 0;
228 	char			*error = NULL, *buffer = NULL;
229 	int			availability_ts, more_history, more_discovery, more_areg, proxy_delay;
230 	zbx_vector_ptr_t	tasks;
231 	struct zbx_json_parse	jp, jp_tasks;
232 	size_t			buffer_size, reserved;
233 
234 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
235 
236 	if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request"))
237 	{
238 		/* do not send any reply to server in this case as the server expects proxy data */
239 		goto out;
240 	}
241 
242 	LOCK_PROXY_HISTORY;
243 	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
244 
245 	zbx_json_addstring(&j, ZBX_PROTO_TAG_SESSION, zbx_dc_get_session_token(), ZBX_JSON_TYPE_STRING);
246 	get_host_availability_data(&j, &availability_ts);
247 	proxy_get_hist_data(&j, &history_lastid, &more_history);
248 	proxy_get_dhis_data(&j, &discovery_lastid, &more_discovery);
249 	proxy_get_areg_data(&j, &areg_lastid, &more_areg);
250 
251 	zbx_vector_ptr_create(&tasks);
252 	zbx_tm_get_remote_tasks(&tasks, 0);
253 
254 	if (0 != tasks.values_num)
255 		zbx_tm_json_serialize_tasks(&j, &tasks);
256 
257 	if (ZBX_PROXY_DATA_MORE == more_history || ZBX_PROXY_DATA_MORE == more_discovery ||
258 			ZBX_PROXY_DATA_MORE == more_areg)
259 	{
260 		zbx_json_adduint64(&j, ZBX_PROTO_TAG_MORE, ZBX_PROXY_DATA_MORE);
261 	}
262 
263 	zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING);
264 	zbx_json_adduint64(&j, ZBX_PROTO_TAG_CLOCK, ts->sec);
265 	zbx_json_adduint64(&j, ZBX_PROTO_TAG_NS, ts->ns);
266 
267 	if (0 != history_lastid && 0 != (proxy_delay = proxy_get_delay(history_lastid)))
268 		zbx_json_adduint64(&j, ZBX_PROTO_TAG_PROXY_DELAY, proxy_delay);
269 
270 	if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size))
271 	{
272 		zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror());
273 		goto clean;
274 	}
275 
276 	reserved = j.buffer_size;
277 	zbx_json_free(&j);	/* json buffer can be large, free as fast as possible */
278 
279 	if (SUCCEED == send_data_to_server(sock, &buffer, buffer_size, reserved, &error))
280 	{
281 		zbx_set_availability_diff_ts(availability_ts);
282 
283 		DBbegin();
284 
285 		if (0 != history_lastid)
286 			proxy_set_hist_lastid(history_lastid);
287 
288 		if (0 != discovery_lastid)
289 			proxy_set_dhis_lastid(discovery_lastid);
290 
291 		if (0 != areg_lastid)
292 			proxy_set_areg_lastid(areg_lastid);
293 
294 		if (0 != tasks.values_num)
295 		{
296 			zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_DONE);
297 			zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
298 		}
299 
300 		if (SUCCEED == zbx_json_open(sock->buffer, &jp))
301 		{
302 			if (SUCCEED == zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_TASKS, &jp_tasks))
303 			{
304 				zbx_tm_json_deserialize_tasks(&jp_tasks, &tasks);
305 				zbx_tm_save_tasks(&tasks);
306 			}
307 		}
308 
309 		DBcommit();
310 	}
311 	else
312 	{
313 		zabbix_log(LOG_LEVEL_WARNING, "cannot send proxy data to server at \"%s\": %s", sock->peer, error);
314 		zbx_free(error);
315 	}
316 clean:
317 	zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
318 	zbx_vector_ptr_destroy(&tasks);
319 
320 	zbx_json_free(&j);
321 	UNLOCK_PROXY_HISTORY;
322 out:
323 	zbx_free(buffer);
324 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
325 }
326 
327 
328 /******************************************************************************
329  *                                                                            *
330  * Function: zbx_send_task_data                                               *
331  *                                                                            *
332  * Purpose: sends 'proxy data' request to server                              *
333  *                                                                            *
334  * Parameters: sock - [IN] the connection socket                              *
335  *             ts   - [IN] the connection timestamp                           *
336  *                                                                            *
337  ******************************************************************************/
zbx_send_task_data(zbx_socket_t * sock,zbx_timespec_t * ts)338 void	zbx_send_task_data(zbx_socket_t *sock, zbx_timespec_t *ts)
339 {
340 	struct zbx_json		j;
341 	char			*error = NULL, *buffer = NULL;
342 	zbx_vector_ptr_t	tasks;
343 	struct zbx_json_parse	jp, jp_tasks;
344 	size_t			buffer_size, reserved;
345 
346 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
347 
348 	if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "proxy data request"))
349 	{
350 		/* do not send any reply to server in this case as the server expects proxy data */
351 		goto out;
352 	}
353 
354 	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);
355 
356 	zbx_vector_ptr_create(&tasks);
357 	zbx_tm_get_remote_tasks(&tasks, 0);
358 
359 	if (0 != tasks.values_num)
360 		zbx_tm_json_serialize_tasks(&j, &tasks);
361 
362 	zbx_json_addstring(&j, ZBX_PROTO_TAG_VERSION, ZABBIX_VERSION, ZBX_JSON_TYPE_STRING);
363 	zbx_json_adduint64(&j, ZBX_PROTO_TAG_CLOCK, ts->sec);
364 	zbx_json_adduint64(&j, ZBX_PROTO_TAG_NS, ts->ns);
365 
366 	if (SUCCEED != zbx_compress(j.buffer, j.buffer_size, &buffer, &buffer_size))
367 	{
368 		zabbix_log(LOG_LEVEL_ERR,"cannot compress data: %s", zbx_compress_strerror());
369 		goto clean;
370 	}
371 
372 	reserved = j.buffer_size;
373 	zbx_json_free(&j);	/* json buffer can be large, free as fast as possible */
374 
375 	if (SUCCEED == send_data_to_server(sock, &buffer, buffer_size, reserved, &error))
376 	{
377 		DBbegin();
378 
379 		if (0 != tasks.values_num)
380 		{
381 			zbx_tm_update_task_status(&tasks, ZBX_TM_STATUS_DONE);
382 			zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
383 		}
384 
385 		if (SUCCEED == zbx_json_open(sock->buffer, &jp))
386 		{
387 			if (SUCCEED == zbx_json_brackets_by_name(&jp, ZBX_PROTO_TAG_TASKS, &jp_tasks))
388 			{
389 				zbx_tm_json_deserialize_tasks(&jp_tasks, &tasks);
390 				zbx_tm_save_tasks(&tasks);
391 			}
392 		}
393 
394 		DBcommit();
395 	}
396 	else
397 	{
398 		zabbix_log(LOG_LEVEL_WARNING, "cannot send task data to server at \"%s\": %s", sock->peer, error);
399 		zbx_free(error);
400 	}
401 clean:
402 	zbx_vector_ptr_clear_ext(&tasks, (zbx_clean_func_t)zbx_tm_task_free);
403 	zbx_vector_ptr_destroy(&tasks);
404 
405 	zbx_json_free(&j);
406 out:
407 	zbx_free(buffer);
408 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
409 }
410 
init_proxy_history_lock(char ** error)411 int	init_proxy_history_lock(char **error)
412 {
413 	if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
414 		return zbx_mutex_create(&proxy_lock, ZBX_MUTEX_PROXY_HISTORY, error);
415 
416 	return SUCCEED;
417 }
418 
free_proxy_history_lock(void)419 void	free_proxy_history_lock(void)
420 {
421 	if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
422 		zbx_mutex_destroy(&proxy_lock);
423 }
424 
425