GCC Code Coverage Report


Directory: ../replacer/
File: storage.c
Date: 2025-10-28 11:47:20
Coverage Exec Excl Total
Lines: 86.8% 99 0 114
Functions: 72.7% 8 0 11
Branches: 79.7% 63 0 79

Line Branch Exec Source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <strings.h>
5
6 #include <inttypes.h>
7 #include <stdint.h>
8 #include <pthread.h>
9 #include <pwd.h>
10 #include <time.h>
11
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/un.h>
15
16 #include <stdlib.h>
17
18 #include <sys/time.h>
19 #include <unistd.h>
20 #include <sys/ioctl.h>
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <yaml.h>
25
26 #include "global_data.h"
27 #include "queue.h"
28
29 #include "storage.h"
30 #include "stringfunc.h"
31
32 #include "unit_test_common.h"
33 #include "counters-saver.h"
34
35 static char *old_socket_connect = NULL;
36
37 static long sign_id = 0;
38 static uint64_t hdb_version = 0;
39
40 void i360_set_sign(long id) {
41 sign_id = id;
42 }
43
44 void i360_set_hdb_version(uint64_t ver) {
45 hdb_version = ver;
46 }
47
48 void i360_set_old_socket_name(char *old_sock) {
49 old_socket_connect = old_sock;
50 }
51
52 #ifndef UNIT_TESTING
53 static int i360_socket_set_non_blocking(int fd) {
54 int flags;
55
56 flags = fcntl(fd, F_GETFL, NULL);
57
58 if (flags < 0) {
59 return -1;
60 }
61
62 flags |= O_NONBLOCK;
63
64 if (fcntl(fd, F_SETFL, flags) < 0) {
65 return -1;
66 }
67 return 0;
68 }
69
70 // do a nonblocking connect
71 // return -1 on a system call error, 0 on success
72 // sa - host to connect to, filled by caller
73 // sock - the socket to connect
74 // timeout - how long to wait to connect in millisecs
75 int conn_nonb(int sock, struct sockaddr *sa, socklen_t __len, int timeout) {
76 int flags = 0, error = 0, ret = 0;
77 fd_set rset, wset;
78 socklen_t len = sizeof(error);
79 struct timeval ts;
80
81 ts.tv_sec = timeout / 1000;
82 ts.tv_usec = (timeout % 1000) * 1000;
83
84 // clear out descriptor sets for select
85 // add socket to the descriptor sets
86 FD_ZERO(&rset);
87 FD_SET(sock, &rset);
88 wset = rset; // structure assignment ok
89
90 // set socket nonblocking flag
91 if ((flags = fcntl(sock, F_GETFL, 0)) < 0)
92 return -1;
93
94 if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
95 return -1;
96
97 // initiate non-blocking connect
98 if ((ret = connect(sock, sa, __len)) < 0)
99 if (errno != EINPROGRESS)
100 return -1;
101
102 if (ret == 0) // then connect succeeded right away
103 goto done;
104
105 // we are waiting for connect to complete now
106 if ((ret = select(sock + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0)
107 return -1;
108 if (ret == 0) { // we had a timeout
109 errno = ETIMEDOUT;
110 return -1;
111 }
112
113 // we had a positivite return so a descriptor is ready
114 if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) {
115 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
116 return -1;
117 }
118 else
119 return -1;
120
121 if (error) { // check if we had a socket error
122 errno = error;
123 return -1;
124 }
125
126 done:
127 // put socket back in blocking mode
128 if (fcntl(sock, F_SETFL, flags) < 0)
129 return -1;
130
131 return 0;
132 }
133
134 int i360_connect_to_server(char *s_name, int buf_sz, int timeout) {
135 int sock;
136 struct sockaddr_un server;
137 struct sockaddr_un server_old;
138 int sendbuff = buf_sz;
139
140 sock = socket(AF_UNIX, SOCK_STREAM, 0);
141 if (sock < 0) {
142 return -1;
143 }
144 server.sun_family = AF_UNIX;
145 strcpy(server.sun_path, s_name);
146
147 if (old_socket_connect) {
148 server_old.sun_family = AF_UNIX;
149 strcpy(server_old.sun_path, old_socket_connect);
150 }
151
152 if (!timeout) {
153 if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) < 0) {
154 if (old_socket_connect) {
155 if (connect(sock, (struct sockaddr *)&server_old, sizeof(struct sockaddr_un)) < 0) {
156 close(sock);
157 return -1;
158 }
159 }
160 else {
161 close(sock);
162 return -1;
163 }
164 }
165 }
166 else {
167 if (conn_nonb(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un), timeout) < 0) {
168 if (old_socket_connect) {
169 if (conn_nonb(sock, (struct sockaddr *)&server_old, sizeof(struct sockaddr_un), timeout) < 0) {
170 close(sock);
171 return -1;
172 }
173 }
174 else {
175 close(sock);
176 return -1;
177 }
178 }
179 }
180
181 if (i360_socket_set_non_blocking(sock) < 0) {
182 close(sock);
183 return -1;
184 }
185
186 if (sendbuff > 1024)
187 setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));
188
189 return sock;
190 }
191
192 int i360_isclosed(int sock) {
193 fd_set rfd;
194 FD_ZERO(&rfd);
195 FD_SET(sock, &rfd);
196 struct timeval tv = {0, 0};
197 select(sock + 1, &rfd, 0, 0, &tv);
198 if (!FD_ISSET(sock, &rfd))
199 return 0;
200 int n = 0;
201 ioctl(sock, FIONREAD, &n);
202 return n == 0;
203 }
204
205 ssize_t i360_write_connect(int *fd, const void *buf, size_t count, char *s_name, int buf_sz,
206 __attribute__((unused)) void *mx, int timeout) {
207 ssize_t ret;
208 if (!fd) {
209 return -1;
210 }
211 if ((*fd < 0) || i360_isclosed(*fd)) {
212 *fd = i360_connect_to_server(s_name, buf_sz, timeout);
213 if (*fd < 0) {
214 return -1;
215 }
216 i360_connections_stats_new_conn();
217 }
218
219 do {
220 ret = write(*fd, buf, count);
221 } while ((ret < 0) && (errno == EINTR));
222
223 return ret;
224 }
225
226 time_t i360_get_tmstmp() {
227 return time(NULL);
228 }
229 #endif
230
231 1 uint16_t i360_get_little_e_size(int size) {
232 1 unsigned int i = 1;
233 1 char *c = (char *)&i;
234
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (*c)
235 1 return (uint16_t)size;
236 else {
237 uint16_t new_size = (uint16_t)size;
238 1 return (new_size >> 8) | (new_size << 8);
239 }
240 }
241
242 1 uint16_t i360_get_big_e_size(int size) {
243 1 unsigned int i = 1;
244 1 char *c = (char *)&i;
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (!*c)
246 return (uint16_t)size;
247 else {
248 1 uint16_t new_size = (uint16_t)size;
249 1 return (new_size >> 8) | (new_size << 8);
250 }
251 }
252
253 #define ENVBUFFER 4096
254
255 #ifndef UNIT_TESTING
256 const char *ENV_INDEX[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
257 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
258 #define MAX_PARAM_BUF 128
259 #define MAX_SIGN_BUF 256
260 #define MAX_IP_BUF 64
261 #define MAX_HDB_VER_BUF 20
262
263 char *i360_init_proto_data_mon(const i360_monitoring_data_t *mon_data, int *length) {
264 char *buf = NULL;
265 int len = 0;
266 *length = 0;
267 I360stats__MonitoringStats data = I360STATS__MONITORING_STATS__INIT;
268
269 if (mon_data == NULL)
270 return NULL;
271
272 data.module_duration = mon_data->module_duration;
273 data.total_connections = mon_data->total_connections;
274 data.total_packets_sent = mon_data->total_packets_sent;
275 data.total_requests = mon_data->total_requests;
276
277 len = i360stats__monitoring_stats__get_packed_size(&data);
278
279 send_params_buffer *buf_send = calloc(1, (len * sizeof(uint8_t)) + sizeof(uint16_t));
280 if (buf_send) {
281 i360stats__monitoring_stats__pack(&data, (uint8_t *)&buf_send->buffer);
282 *length = len + sizeof(uint16_t);
283 buf_send->size = i360_get_big_e_size(len);
284 }
285
286 buf = (char *)buf_send;
287 return buf;
288 }
289
290 int i360_init_proto_data_failure(const i360_log_data_t *ld, char *aux_env[], size_t aux_env_len, char *buf) {
291 int env_idx = 0;
292 size_t buf_left = MAX_FAILURE_BUF_LEN;
293 char tmp_buf[MAX_FAILURE_BUF_LEN] = {0};
294 char *env[MAX_FAILURE_BUF_SIZE];
295
296 I360parcel__SendInfo data = I360PARCEL__SEND_INFO__INIT;
297 I360parcel__ProactiveQueue php_info = I360PARCEL__PROACTIVE_QUEUE__INIT;
298
299 if (buf == NULL || ld == NULL)
300 return -1;
301
302 php_info.version = ld->version;
303 php_info.script = (char *)ld->script_name;
304 php_info.recognizer_id = ld->chains->recognizer_id;
305 php_info.recognizer_sub_id = ld->chains->chain_id;
306
307 switch (ld->chains->action) {
308 case BLOCK_FUNC:
309 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__BLOCK;
310 break;
311 case KILL_SCRIPT:
312 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__KILL;
313 break;
314 case DISABLED:
315 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__DISABLED;
316 break;
317 case LOG_ONLY:
318 // failthrough
319 case NO_ACTION:
320 // failthrough
321 default:
322 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__LOG;
323 break;
324 }
325 php_info.has_action = 1;
326
327 char description[MAX_FAILURE_BUF_LEN] = {0};
328 memcpy(description, ld->chains->recognizer_desr, strlen(ld->chains->recognizer_desr));
329 php_info.recognizer_name = description;
330
331 char sign_buf[MAX_FAILURE_BUF_LEN] = {0};
332 if (sign_id) {
333 i360_strnadd(sign_buf, "sign=", 5, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
334 i360_ltoa(sign_id, tmp_buf, 10);
335 i360_strnadd(sign_buf, tmp_buf, strlen(tmp_buf), MAX_FAILURE_BUF_LEN, &buf_left);
336 env[env_idx++] = sign_buf;
337 }
338
339 char dbv_buf[MAX_FAILURE_BUF_LEN] = {0};
340 if (!i360_get_database_version()) {
341 i360_strnadd(dbv_buf, "dbver=v1", 8, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
342 }
343 else {
344 i360_strnadd(dbv_buf, "dbver=v2", 8, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
345 }
346 env[env_idx++] = dbv_buf;
347
348 char hdbv_buf[MAX_HDB_VER_BUF] = {0};
349 if (hdb_version) {
350 i360_strnadd(hdbv_buf, "hdb_ver=", 8, MAX_HDB_VER_BUF, (buf_left = MAX_HDB_VER_BUF, &buf_left));
351 i360_ltoa(hdb_version, tmp_buf, 10);
352 i360_strnadd(hdbv_buf, tmp_buf, strlen(tmp_buf), MAX_HDB_VER_BUF, &buf_left);
353 env[env_idx++] = hdbv_buf;
354 }
355
356 char i360_ver_buf[MAX_FAILURE_BUF_LEN] = {0};
357 i360_strnadd(i360_ver_buf, "I_I360_V=", 9, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
358 i360_strnadd(i360_ver_buf, PHP_I360_VERSION, strlen(PHP_I360_VERSION), MAX_FAILURE_BUF_LEN, &buf_left);
359 env[env_idx++] = i360_ver_buf;
360
361 char uid_buf[MAX_FAILURE_BUF_LEN];
362 uid_t store_uid = getuid();
363 i360_strnadd(uid_buf, "PHPAP_UID=", 10, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
364 i360_itoa((int)store_uid, tmp_buf, 10);
365 i360_strnadd(uid_buf, tmp_buf, strlen(tmp_buf), MAX_FAILURE_BUF_LEN, &buf_left);
366 env[env_idx++] = uid_buf;
367
368 char gid_buf[MAX_FAILURE_BUF_LEN];
369 gid_t store_gid = getgid();
370 i360_strnadd(gid_buf, "PHPAP_GID=", 10, MAX_FAILURE_BUF_LEN, (buf_left = MAX_FAILURE_BUF_LEN, &buf_left));
371 i360_itoa((int)store_gid, tmp_buf, 10);
372 i360_strnadd(gid_buf, tmp_buf, strlen(tmp_buf), MAX_FAILURE_BUF_LEN, &buf_left);
373 env[env_idx++] = gid_buf;
374
375 char current_script_filename_buf[MAX_FAILURE_FILENAME_LEN] = "current_script=";
376 const char *current_script_filename = i360_get_cur_php_fname();
377 if (current_script_filename != NULL && strlen(current_script_filename)) {
378 strncat(current_script_filename_buf, current_script_filename, MAX_FAILURE_FILENAME_LEN - 16);
379 }
380 else {
381 strcat(current_script_filename_buf, "[no script]");
382 }
383 env[env_idx++] = current_script_filename_buf;
384
385 // Process server_env
386 char *script_uri = NULL;
387 char *server_name = NULL;
388 char *script_filename = NULL;
389 params_list *server_env = i360_get_global_server();
390 if (server_env->head) {
391 params_item *item = server_env->head;
392 while (item) {
393 // add host to env
394 if (i360_has_prefix(item->param, "PHPE_SERVER_NAME") == 1) {
395 server_name = item->param;
396 }
397 // add uri to env
398 else if (i360_has_prefix(item->param, "PHPE_SCRIPT_URI") == 1) {
399 script_uri = item->param;
400 }
401 // add script_filename to env
402 else if (i360_has_prefix(item->param, "SCRIPT_FILENAME") == 1) {
403 script_filename = item->param;
404 }
405
406 item = item->next;
407 }
408 }
409 if (server_name) {
410 env[env_idx++] = server_name;
411 }
412 if (script_uri) {
413 env[env_idx++] = script_uri;
414 }
415 if (script_filename) {
416 env[env_idx++] = script_filename;
417 }
418
419 /* Auxiliary env data */
420 size_t i;
421 for (i = 0; i < aux_env_len && env_idx < MAX_FAILURE_BUF_SIZE; i++) {
422 env[env_idx++] = aux_env[i];
423 }
424
425 php_info.n_env = env_idx;
426 php_info.env = env;
427
428 data.proactive = &php_info;
429 data.timestamp = i360_get_tmstmp();
430 data.method = I360PARCEL__SEND_INFO__METHOD__PROACTIVE;
431 I360parcel__ProactiveEnvMeta env_meta = I360PARCEL__PROACTIVE_ENV_META__INIT;
432 if (ld->application_id) {
433 env_meta.app_id = (char *)ld->application_id;
434 if (ld->application_instance_id) {
435 env_meta.instance_uid = (char *)ld->application_instance_id;
436 }
437 data.env_meta = &env_meta;
438 }
439
440 char ip_buf[MAX_IP_BUF] = {0};
441 if (ld->ip) {
442 strncpy(ip_buf, ld->ip, MAX_IP_BUF - 1);
443 char *comma = strchr(ip_buf, ',');
444 if (comma) {
445 *comma = 0;
446 }
447 }
448 else {
449 strncpy(ip_buf, "127.0.0.1", MAX_IP_BUF - 1);
450 }
451 data.ip = ip_buf;
452
453 /* Protobuf serialization */
454 size_t payload_len = i360parcel__send_info__get_packed_size(&data);
455 size_t len = payload_len + sizeof(uint16_t);
456 uint8_t packed[len];
457
458 uint16_t be_payload_len = i360_get_big_e_size(payload_len);
459 memcpy(packed, &be_payload_len, sizeof(uint16_t));
460
461 i360parcel__send_info__pack(&data, packed + sizeof(uint16_t));
462
463 memcpy(buf, packed, len);
464
465 return (int)len;
466 }
467
468 char *i360_init_proto_data(const i360_log_data_t *ld, int *length) {
469 *length = 0;
470 char env_buf[ENVBUFFER];
471 char ip_buf[MAX_IP_BUF];
472 size_t buf_left = ENVBUFFER;
473 char description[MAX_FILE_STRING] = {0};
474 char param_buf[MAX_PARAM_BUF] = {0};
475 char sign_buf[MAX_SIGN_BUF] = {0};
476 char hdbv_buf[MAX_HDB_VER_BUF] = {0};
477 if (!ld || !ld->chains || !ld->chains->recognizer_id)
478 return NULL;
479 I360parcel__SendInfo data = I360PARCEL__SEND_INFO__INIT;
480 I360parcel__ProactiveQueue php_info = I360PARCEL__PROACTIVE_QUEUE__INIT;
481 char *buf = NULL;
482 size_t len = 0;
483
484 if (!i360_is_prepared_buffer_fixed()) {
485 if (!i360_get_database_version()) {
486 i360_strnadd(env_buf, "dbver=v1", 8, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
487 }
488 else {
489 i360_strnadd(env_buf, "dbver=v2", 8, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
490 }
491 i360_add_prepared_buffer_req_data(env_buf);
492
493 if (hdb_version) {
494 i360_strnadd(env_buf, "hdb_ver=", 8, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
495 sprintf(hdbv_buf, "%" PRIu64, hdb_version);
496 i360_strnadd(env_buf, hdbv_buf, strlen(hdbv_buf), ENVBUFFER, &buf_left);
497 i360_add_prepared_buffer_req_data(env_buf);
498 }
499
500 if (sign_id) {
501 i360_strnadd(env_buf, "sign=", 5, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
502 i360_ltoa(sign_id, sign_buf, 10);
503 i360_strnadd(env_buf, sign_buf, strlen(sign_buf), ENVBUFFER, &buf_left);
504 i360_add_prepared_buffer_req_data(env_buf);
505 }
506
507 i360_strnadd(env_buf, "I_I360_V=", 9, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
508 i360_strnadd(env_buf, PHP_I360_VERSION, strlen(PHP_I360_VERSION), ENVBUFFER, &buf_left);
509 i360_add_prepared_buffer_req_data(env_buf);
510
511 uid_t store_uid = getuid();
512 gid_t store_gid = getgid();
513
514 i360_strnadd(env_buf, "PHPAP_UID=", 10, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
515 i360_itoa((int)store_uid, param_buf, 10);
516 i360_strnadd(env_buf, param_buf, strlen(param_buf), ENVBUFFER, &buf_left);
517 i360_add_prepared_buffer_req_data(env_buf);
518
519 i360_strnadd(env_buf, "PHPAP_GID=", 10, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
520 i360_itoa((int)store_gid, param_buf, 10);
521 i360_strnadd(env_buf, param_buf, strlen(param_buf), ENVBUFFER, &buf_left);
522 i360_add_prepared_buffer_req_data(env_buf);
523
524 if (ld->script_schema) {
525 i360_strnadd(env_buf, "PHPAP_SCHEMA=", 13, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
526 i360_strnadd(env_buf, ld->script_schema, strlen(ld->script_schema), ENVBUFFER, &buf_left);
527 i360_add_prepared_buffer_req_data(env_buf);
528 }
529
530 params_list *serv = (params_list *)ld->server;
531 if (serv->head) {
532 params_item *item = serv->head;
533 while (item) {
534 i360_add_prepared_buffer_req_data(item->param);
535 item = item->next;
536 }
537 }
538 }
539
540 if (!i360_is_prepared_buffer_fixed()) {
541 i360_fix_prepared_buffer();
542 }
543 else {
544 i360_restore_buffer_for_dynamic();
545 }
546
547 if (ld->include_stack && ld->include_stack[0]) {
548 i360_strnadd(env_buf, "INCLUDE_STACK=", sizeof("INCLUDE_STACK=")-1, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
549 i360_strnadd(env_buf, ld->include_stack, strlen(ld->include_stack), ENVBUFFER, &buf_left);
550 i360_add_prepared_buffer_dyn_data(env_buf);
551 }
552
553 if (ld->hash && *ld->hash) {
554 i360_strnadd(env_buf, "qhash=", 6, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
555 i360_strnadd(env_buf, ld->hash, strlen(ld->hash), ENVBUFFER, &buf_left);
556 i360_add_prepared_buffer_dyn_data(env_buf);
557 }
558
559 if (ld->last_funcname) {
560 i360_strnadd(env_buf, "PHPFP_NAM=", 10, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
561 i360_strnadd(env_buf, ld->last_funcname, strlen(ld->last_funcname), ENVBUFFER, &buf_left);
562 i360_add_prepared_buffer_dyn_data(env_buf);
563 }
564
565 if (ld->qhashfn) {
566 i360_strnadd(env_buf, ld->qhash_version ? "EF_1_NAME=" : "EF_0_NAME=", 10, ENVBUFFER,
567 (buf_left = ENVBUFFER, &buf_left));
568 i360_strnadd(env_buf, ld->qhashfn, strlen(ld->qhashfn), ENVBUFFER, &buf_left);
569 i360_add_prepared_buffer_dyn_data(env_buf);
570 }
571
572 if (ld->qhashlast) {
573 i360_strnadd(env_buf, ld->qhash_version ? "EF_1_LAST_HASH=" : "EF_0_LAST_HASH=", 15, ENVBUFFER,
574 (buf_left = ENVBUFFER, &buf_left));
575 i360_strnadd(env_buf, ld->qhashlast, strlen(ld->qhashlast), ENVBUFFER, &buf_left);
576 i360_add_prepared_buffer_dyn_data(env_buf);
577 }
578
579 if (ld->qhashlen) {
580 i360_strnadd(env_buf, ld->qhash_version ? "EF_1_LEN=" : "EF_0_LEN=", 9, ENVBUFFER,
581 (buf_left = ENVBUFFER, &buf_left));
582 i360_itoa(ld->qhashlen, param_buf, 10);
583 i360_strnadd(env_buf, param_buf, strlen(param_buf), ENVBUFFER, &buf_left);
584 i360_add_prepared_buffer_dyn_data(env_buf);
585 }
586
587 /*
588 i360_strnadd(env_buf, "PHPE_rdlt=", 10, ENVBUFFER, (buf_left = ENVBUFFER, &buf_left));
589 i360_lltoa((long long)ld->running_delta, param_buf, 10);
590 i360_strnadd(env_buf, param_buf, strlen(param_buf), ENVBUFFER, &buf_left);
591 i360_add_prepared_buffer_dyn_data(env_buf);
592 */
593
594 php_info.version = ld->version;
595
596 php_info.script = (char *)ld->script_name;
597
598 php_info.queue_string = (char *)ld->queue;
599
600 // check for any log
601 if (ld->chains->recognizer_id == 2) {
602 php_info.recognizer_id = 2;
603 php_info.has_recognizer_sub_id = 0;
604 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__LOG;
605 php_info.has_action = 1;
606 strncpy(description, "test:test", MAX_FILE_STRING);
607 php_info.recognizer_name = (char *)&description;
608 }
609 else {
610 php_info.recognizer_id = ld->chains->recognizer_id;
611 php_info.recognizer_sub_id = ld->chains->chain_id;
612 php_info.has_recognizer_sub_id = 1;
613 switch (ld->chains->action) {
614 case LOG_ONLY:
615 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__LOG;
616 break;
617 case BLOCK_FUNC:
618 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__BLOCK;
619 break;
620 case KILL_SCRIPT:
621 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__KILL;
622 break;
623 case DISABLED:
624 php_info.action = I360PARCEL__PROACTIVE_QUEUE__ACTION__DISABLED;
625 break;
626 case NO_ACTION: /* -Werror=switch */
627 default:
628 break;
629 }
630 php_info.has_action = 1;
631 memcpy(description, ld->chains->recognizer_desr, strlen(ld->chains->recognizer_desr));
632 size_t desc_buf_left = MAX_FILE_STRING - strnlen(description, MAX_FILE_STRING);
633 i360_strnadd(description, ":", 1, MAX_FILE_STRING, &desc_buf_left);
634 i360_strnadd(description, ld->chains->ruldescr, strlen(ld->chains->ruldescr), MAX_FILE_STRING, &desc_buf_left);
635 php_info.recognizer_name = (char *)&description;
636 }
637
638 if (i360_prepared_buffer_length()) {
639 php_info.n_env = i360_prepared_buffer_length() + i360_get_params_new_numb();
640 php_info.env = calloc(i360_prepared_buffer_length() + i360_get_params_new_numb(), sizeof(char *));
641 if (!php_info.env) {
642 return NULL;
643 }
644 int index = 0;
645 while (index < i360_prepared_buffer_length()) {
646 php_info.env[index] = i360_prepared_buffer_get(index);
647 index++;
648 }
649 int jndex = 0;
650 while (jndex < i360_get_params_new_numb()) {
651 php_info.env[index + jndex] = i360_get_params_new_raw(jndex);
652 jndex++;
653 }
654 }
655
656 I360parcel__ProactiveEnvMeta env_meta = I360PARCEL__PROACTIVE_ENV_META__INIT;
657 if (ld->application_id) {
658 env_meta.app_id = (char *)ld->application_id;
659 if (ld->application_instance_id) {
660 env_meta.instance_uid = (char *)ld->application_instance_id;
661 }
662 data.env_meta = &env_meta;
663 }
664 data.proactive = &php_info;
665 data.timestamp = i360_get_tmstmp();
666 if (ld->ip) {
667 memset(ip_buf, 0, MAX_IP_BUF);
668 strncpy(ip_buf, ld->ip, MAX_IP_BUF - 1);
669 char *comma = strchr(ip_buf, ',');
670 if (comma) {
671 *comma = 0;
672 }
673 }
674 else {
675 strncpy(ip_buf, "127.0.0.1", MAX_IP_BUF - 1);
676 }
677 data.ip = ip_buf;
678 data.method = I360PARCEL__SEND_INFO__METHOD__PROACTIVE;
679
680 len = i360parcel__send_info__get_packed_size(&data);
681
682 send_params_buffer *buf_send = calloc(1, (len * sizeof(uint8_t)) + sizeof(uint16_t));
683
684 if (buf_send) {
685 i360parcel__send_info__pack(&data, (uint8_t *)&buf_send->buffer);
686 *length = len + sizeof(uint16_t);
687 buf_send->size = i360_get_big_e_size(len);
688 }
689
690 buf = (char *)buf_send;
691
692 if (php_info.env)
693 free(php_info.env);
694 return buf;
695 }
696
697 char *i360_init_proto_data_stats(int *length, const char *script_name, const char *uri, const char *method, const char *app_id, const char *instance_uid) {
698 char *buf = NULL;
699 int len = 0;
700 *length = 0;
701 I360stats__ProactiveStats php_info = I360STATS__PROACTIVE_STATS__INIT;
702 php_info.uri = (char *)(uri ? uri : "no_uri");
703 php_info.script = (char *)(script_name ? script_name : "no_script");
704 if (method != NULL && !strcasecmp(method, "get")) {
705 php_info.method = I360STATS__PROACTIVE_STATS__METHOD__GET;
706 }
707 else if (method != NULL && !strcasecmp(method, "post")) {
708 php_info.method = I360STATS__PROACTIVE_STATS__METHOD__POST;
709 }
710 else {
711 php_info.method = I360STATS__PROACTIVE_STATS__METHOD__OTHER;
712 }
713 php_info.version = 1;
714
715 if (i360_counter_saver_is_active()) {
716 php_info.inpd = (uint64_t)i360_counter_saver_global_counter_in_pd_get();
717 php_info.global = (uint64_t)i360_counter_saver_global_counter_get();
718 if (i360_counter_saver_get_items()) {
719 php_info.n_rulesid = i360_counter_saver_get_items();
720 php_info.n_exectimes = i360_counter_saver_get_items();
721 php_info.rulesid = calloc(php_info.n_rulesid, sizeof(uint32_t));
722 if (!php_info.rulesid) {
723 return NULL;
724 }
725 php_info.exectimes = calloc(php_info.n_rulesid, sizeof(uint64_t));
726 if (!php_info.exectimes) {
727 free(php_info.rulesid);
728 return NULL;
729 }
730 size_t index = 0;
731 for (index = 0; index < php_info.n_rulesid; index++) {
732 i360_counter_saver_array_item *tmp_item = i360_counter_saver_index(index);
733 php_info.rulesid[index] = (uint32_t)tmp_item->key;
734 php_info.exectimes[index] = (uint64_t)tmp_item->value;
735 }
736 }
737 if (i360_dbgcounter_saver_get_items()) {
738 php_info.n_dbgrulesid = i360_dbgcounter_saver_get_items();
739 php_info.n_dbgexectimes = i360_dbgcounter_saver_get_items();
740 php_info.dbgrulesid = calloc(php_info.n_dbgrulesid, sizeof(uint32_t));
741 if (!php_info.dbgrulesid) {
742 if (php_info.rulesid)
743 free(php_info.rulesid);
744 if (php_info.exectimes)
745 free(php_info.exectimes);
746 return NULL;
747 }
748 php_info.dbgexectimes = calloc(php_info.n_dbgrulesid, sizeof(uint64_t));
749 if (!php_info.exectimes) {
750 if (php_info.rulesid)
751 free(php_info.rulesid);
752 if (php_info.exectimes)
753 free(php_info.exectimes);
754 free(php_info.dbgrulesid);
755 return NULL;
756 }
757 size_t index = 0;
758 for (index = 0; index < php_info.n_dbgrulesid; index++) {
759 i360_counter_saver_array_item *tmp_item = i360_dbgcounter_saver_index(index);
760 php_info.dbgrulesid[index] = (uint32_t)tmp_item->key;
761 php_info.dbgexectimes[index] = (uint64_t)tmp_item->value;
762 }
763 }
764 }
765 I360stats__ProactiveEnvMeta env_meta = I360STATS__PROACTIVE_ENV_META__INIT;
766 if (app_id) {
767 env_meta.app_id = (char *)app_id;
768 if (instance_uid) {
769 env_meta.instance_uid = (char *)instance_uid;
770 }
771 php_info.env_meta = &env_meta;
772 }
773
774 len = i360stats__proactive_stats__get_packed_size(&php_info);
775
776 send_params_buffer *buf_send = calloc(1, (len * sizeof(uint8_t)) + sizeof(uint16_t));
777 if (buf_send) {
778 i360stats__proactive_stats__pack(&php_info, (uint8_t *)&buf_send->buffer);
779 *length = len + sizeof(uint16_t);
780 buf_send->size = i360_get_big_e_size(len);
781 }
782
783 buf = (char *)buf_send;
784
785 if (php_info.rulesid)
786 free(php_info.rulesid);
787 if (php_info.exectimes)
788 free(php_info.exectimes);
789 if (php_info.dbgrulesid)
790 free(php_info.dbgrulesid);
791 if (php_info.dbgexectimes)
792 free(php_info.dbgexectimes);
793
794 return buf;
795 }
796 #endif
797
798 14 static int i360_parse_mode(char *value) {
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!strcmp(value, "DISABLED"))
800 return DISABLED;
801
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 else if (!strcmp(value, "LOG"))
802 8 return LOG_ONLY;
803
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 else if (!strcmp(value, "BLOCK"))
804 2 return BLOCK_FUNC;
805
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 else if (!strcmp(value, "KILL"))
806 2 return KILL_SCRIPT;
807 else
808 2 return -1;
809 }
810
811 static inline
812 15 void i360_parse_bool(const char *str, int *value) {
813
4/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
23 if (!strcasecmp(str, "on") ||
814 8 !strcasecmp(str, "true")) {
815 10 *value = 1;
816 }
817
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 else if (!!strcasecmp(str, "null")) {
818 5 *value = 0;
819 }
820 15 }
821
822 #define SECTION_NONE 0
823 #define SECTION_PROACTIVE_DEFENCE 1
824 #define SECTION_PERMISSIONS 2
825
826 static inline
827 58 int i360_yaml_section_name_to_id(char *name) {
828
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 20 times.
58 if (name) {
829
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 21 times.
38 if (!strcmp(name, "PROACTIVE_DEFENCE")) {
830 17 return SECTION_PROACTIVE_DEFENCE;
831 }
832
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 16 times.
21 else if (!strcmp(name, "PERMISSIONS")) {
833 5 return SECTION_PERMISSIONS;
834 }
835 }
836 36 return SECTION_NONE;
837 }
838
839 static inline
840 266 void i360_yaml_parse_key_value(int section_id, char *key, char *value, int *mode, i360_yaml_config_t *config) {
841
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 242 times.
266 if (section_id == SECTION_PROACTIVE_DEFENCE) {
842
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
24 if (!strcmp(key, "blamer") && config) {
843 10 i360_parse_bool(value, &config->blamer);
844 }
845
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 if (!strcmp(key, "jit_compatible_mode") && config) {
846 i360_parse_bool(value, &config->jit);
847 }
848
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
24 if (!strcmp(key, "log_whitelisted") && config) {
849 i360_parse_bool(value, &config->log_whitelisted);
850 }
851
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
24 if (!strcmp(key, "mode") && mode) {
852 14 *mode = i360_parse_mode(value);
853 }
854 }
855
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 254 times.
266 if (section_id == SECTION_PERMISSIONS) {
856
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
12 if (!strcmp(key, "user_override_proactive_defense") && config) {
857 5 i360_parse_bool(value, &config->override);
858 }
859 }
860 266 }
861
862 static inline
863 23 int i360_yaml_read(yaml_parser_t parser, i360_yaml_config_t *config) {
864 23 yaml_token_t token, key = { .type = YAML_NO_TOKEN };
865 23 int is_key = 0, is_value = 0;
866 23 int section_id = SECTION_NONE;
867 23 int mode = -1;
868
869 #define EXTRACT(token) ((char*)token.data.scalar.value)
870
871 do {
872 1312 yaml_parser_scan(&parser, &token);
873
874
7/7
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 525 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 71 times.
✓ Branch 6 taken 139 times.
1312 switch (token.type) {
875 case YAML_KEY_TOKEN:
876 259 is_key = 1; is_value = 0;
877 259 break;
878 case YAML_VALUE_TOKEN:
879 259 is_key = 0; is_value = 1;
880 259 break;
881 case YAML_BLOCK_MAPPING_START_TOKEN:
882 // Previous key is the section name, read which section it is
883 58 section_id = i360_yaml_section_name_to_id(EXTRACT(key));
884 58 yaml_token_delete(&key);
885 58 break;
886 case YAML_SCALAR_TOKEN:
887
2/2
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 266 times.
525 if (is_key) {
888 259 key = token;
889 259 continue;
890 }
891
1/2
✓ Branch 0 taken 266 times.
✗ Branch 1 not taken.
266 if (is_value) {
892 // interpret here
893 266 i360_yaml_parse_key_value(section_id, EXTRACT(key), EXTRACT(token), &mode, config);
894 // interpret here
895 266 yaml_token_delete(&key);
896 }
897 266 break;
898 case YAML_NO_TOKEN:
899 1 yaml_token_delete(&token);
900
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if (config) {
901 1 config->blamer = -1;
902 1 config->jit = -1;
903 1 config->override = -1;
904 1 config->log_whitelisted = -1;
905 }
906 1 return -1;
907 case YAML_BLOCK_END_TOKEN:
908 71 section_id = SECTION_NONE;
909 default:
910 // fall through is deliberate
911 210 break;
912 }
913
2/2
✓ Branch 0 taken 1030 times.
✓ Branch 1 taken 22 times.
1052 if (token.type != YAML_STREAM_END_TOKEN)
914 1030 yaml_token_delete(&token);
915
2/2
✓ Branch 0 taken 1289 times.
✓ Branch 1 taken 22 times.
1311 } while (token.type != YAML_STREAM_END_TOKEN);
916
917 22 yaml_token_delete(&token);
918
919 23 return mode;
920 }
921
922 /* location:
923 * global == 0 - global i360 config
924 * local == 1 - user-specified config
925 */
926 28 int i360_parse_yaml_conf(const char *filename, int location, i360_yaml_config_t *config) {
927 yaml_parser_t parser;
928 28 int mode = -1;
929
930 28 FILE *fh = fopen(filename, "r");
931 /* error with user-specified config -> use global config */
932
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 time.
28 if (fh == NULL && location == 1)
933 4 return -1;
934 /* error with global config -> mode disabled */
935
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 23 times.
24 else if (fh == NULL)
936 1 return DISABLED;
937
938
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
23 if (!yaml_parser_initialize(&parser))
939 return DISABLED;
940
941 23 yaml_parser_set_input_file(&parser, fh);
942
943 23 mode = i360_yaml_read(parser, config);
944
945 23 yaml_parser_delete(&parser);
946 23 fclose(fh);
947
948 /* proactive_defence not specified -> use global config */
949
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4 times.
23 if (mode < 0 && location == 1)
950 7 return -1;
951 /* proactive_defence not specified in global config -> disabled */
952
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 else if (mode < 0)
953 4 return DISABLED;
954
955 28 return mode;
956 }
957