1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*  Fluent Bit
4  *  ==========
5  *  Copyright (C) 2019-2021 The Fluent Bit Authors
6  *  Copyright (C) 2015-2018 Treasure Data Inc.
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <ctype.h>
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <msgpack.h>
30 
31 #include <monkey/mk_core.h>
32 #include <fluent-bit/flb_macros.h>
33 #include <fluent-bit/flb_config.h>
34 #include <fluent-bit/flb_error.h>
35 #include <fluent-bit/flb_input.h>
36 #include <fluent-bit/flb_output.h>
37 #include <fluent-bit/flb_utils.h>
38 #include <fluent-bit/flb_utf8.h>
39 
40 #ifdef FLB_HAVE_AWS_ERROR_REPORTER
41 #include <fluent-bit/aws/flb_aws_error_reporter.h>
42 
43 extern struct flb_aws_error_reporter *error_reporter;
44 #endif
45 
46 #ifdef FLB_HAVE_OPENSSL
47 #include <openssl/rand.h>
48 #endif
49 
50 /*
51  * The following block descriptor describes the private use unicode character range
52  * used for denoting invalid utf-8 fragments. Invalid fragment 0xCE would become
53  * utf-8 codepoint U+E0CE if FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR is set to
54  * E0 since U+E0CE = U+<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR><HEX_FRAGMENT>
55  */
56 #define FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR 0xE0
57 
flb_utils_error(int err)58 void flb_utils_error(int err)
59 {
60     char *msg = NULL;
61 
62     switch (err) {
63     case FLB_ERR_CFG_FILE:
64         msg = "Could not open configuration file";
65         break;
66     case FLB_ERR_CFG_FILE_FORMAT:
67         msg = "Configuration file contains format errors";
68         break;
69     case FLB_ERR_CFG_FILE_STOP:
70         msg = "Configuration file contains errors";
71         break;
72     case FLB_ERR_CFG_FLUSH:
73         msg = "Invalid flush value";
74         break;
75     case FLB_ERR_CFG_FLUSH_CREATE:
76         msg = "Could not create timer for flushing";
77         break;
78     case FLB_ERR_CFG_FLUSH_REGISTER:
79         msg = "Could not register timer for flushing";
80         break;
81     case FLB_ERR_INPUT_INVALID:
82         msg = "Invalid input type";
83         break;
84     case FLB_ERR_INPUT_UNDEF:
85         msg = "No Input(s) have been defined";
86         break;
87     case FLB_ERR_INPUT_UNSUP:
88         msg = "Unsupported Input";
89         break;
90     case FLB_ERR_OUTPUT_UNDEF:
91         msg = "You must specify an output target";
92         break;
93     case FLB_ERR_OUTPUT_INVALID:
94         msg = "Invalid output target";
95         break;
96     case FLB_ERR_OUTPUT_UNIQ:
97         msg = "Just one output type is supported";
98         break;
99     case FLB_ERR_FILTER_INVALID:
100         msg = "Invalid filter plugin";
101         break;
102     case FLB_ERR_CFG_PARSER_FILE:
103         msg = "Could not open parser configuration file";
104         break;
105     case FLB_ERR_JSON_INVAL:
106         msg = "Invalid JSON string";
107         break;
108     case FLB_ERR_JSON_PART:
109         msg = "Truncated JSON string";
110         break;
111     case FLB_ERR_CORO_STACK_SIZE:
112         msg = "Invalid coroutine stack size";
113         break;
114     }
115 
116     if (!msg) {
117         fprintf(stderr,
118                 "%sError%s: undefined. Aborting",
119                 ANSI_BOLD ANSI_RED, ANSI_RESET);
120         #ifdef FLB_HAVE_AWS_ERROR_REPORTER
121         if (is_error_reporting_enabled()) {
122             flb_aws_error_reporter_write(error_reporter, "Error: undefined. Aborting\n");
123         }
124         #endif
125 
126     }
127     else {
128         fprintf(stderr,
129                 "%sError%s: %s. Aborting\n\n",
130                 ANSI_BOLD ANSI_RED, ANSI_RESET, msg);
131 
132         #ifdef FLB_HAVE_AWS_ERROR_REPORTER
133         if (is_error_reporting_enabled()) {
134             flb_aws_error_reporter_write(error_reporter, msg);
135         }
136         #endif
137     }
138 
139     if (err <= FLB_ERR_FILTER_INVALID) {
140         exit(EXIT_FAILURE);
141     }
142 }
143 
144 /* Custom error */
flb_utils_error_c(const char * msg)145 void flb_utils_error_c(const char *msg)
146 {
147     fprintf(stderr,
148             "%sError%s: %s. Aborting\n\n",
149             ANSI_BOLD ANSI_RED, ANSI_RESET, msg);
150     exit(EXIT_FAILURE);
151 }
152 
flb_utils_warn_c(const char * msg)153 void flb_utils_warn_c(const char *msg)
154 {
155     fprintf(stderr,
156             "%sWarning%s: %s",
157             ANSI_BOLD ANSI_YELLOW, ANSI_RESET, msg);
158 }
159 
160 #ifdef FLB_HAVE_FORK
161 /* Run current process in background mode */
flb_utils_set_daemon(struct flb_config * config)162 int flb_utils_set_daemon(struct flb_config *config)
163 {
164     pid_t pid;
165 
166     if ((pid = fork()) < 0){
167 		flb_error("Failed creating to switch to daemon mode (fork failed)");
168         exit(EXIT_FAILURE);
169 	}
170 
171     if (pid > 0) { /* parent */
172         exit(EXIT_SUCCESS);
173     }
174 
175     /* set files mask */
176     umask(0);
177 
178     /* Create new session */
179     setsid();
180 
181     if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */
182         flb_error("Unable to unmount the inherited filesystem");
183         exit(EXIT_FAILURE);
184 	}
185 
186     /* Our last STDOUT messages */
187     flb_info("switching to background mode (PID=%ld)", (long) getpid());
188 
189     fclose(stderr);
190     fclose(stdout);
191 
192     return 0;
193 }
194 #endif
195 
flb_utils_print_setup(struct flb_config * config)196 void flb_utils_print_setup(struct flb_config *config)
197 {
198     struct mk_list *head;
199     struct flb_input_plugin *plugin;
200     struct flb_input_collector *collector;
201     struct flb_input_instance *in;
202     struct flb_filter_instance *f;
203     struct flb_output_instance *out;
204 
205     flb_info("Configuration:");
206 
207     /* general */
208     flb_info(" flush time     | %f seconds", config->flush);
209     flb_info(" grace          | %i seconds", config->grace);
210     flb_info(" daemon         | %i", config->daemon);
211 
212     /* Inputs */
213     flb_info("___________");
214     flb_info(" inputs:");
215     mk_list_foreach(head, &config->inputs) {
216         in = mk_list_entry(head, struct flb_input_instance, _head);
217         flb_info("     %s", in->p->name);
218     }
219 
220     /* Filters */
221     flb_info("___________");
222     flb_info(" filters:");
223     mk_list_foreach(head, &config->filters) {
224         f = mk_list_entry(head, struct flb_filter_instance, _head);
225         flb_info("     %s", f->name);
226     }
227 
228     /* Outputs */
229     flb_info("___________");
230     flb_info(" outputs:");
231     mk_list_foreach(head, &config->outputs) {
232         out = mk_list_entry(head, struct flb_output_instance, _head);
233         flb_info("     %s", out->name);
234     }
235 
236     /* Collectors */
237     flb_info("___________");
238     flb_info(" collectors:");
239     mk_list_foreach(head, &config->collectors) {
240         collector = mk_list_entry(head, struct flb_input_collector, _head);
241         plugin = collector->instance->p;
242 
243         if (collector->seconds > 0) {
244             flb_info("[%s %lus,%luns] ",
245                       plugin->name,
246                       collector->seconds,
247                       collector->nanoseconds);
248         }
249         else {
250             flb_info("     [%s] ", plugin->name);
251         }
252 
253     }
254 }
255 
flb_utils_split(const char * line,int separator,int max_split)256 struct mk_list *flb_utils_split(const char *line, int separator, int max_split)
257 {
258     int i = 0;
259     int count = 0;
260     int val_len;
261     int len;
262     int end;
263     char *val;
264     struct mk_list *list;
265     struct flb_split_entry *new;
266 
267     if (!line) {
268         return NULL;
269     }
270 
271     list = flb_malloc(sizeof(struct mk_list));
272     if (!list) {
273         flb_errno();
274         return NULL;
275     }
276     mk_list_init(list);
277 
278     len = strlen(line);
279     while (i < len) {
280         end = mk_string_char_search(line + i, separator, len - i);
281         if (end >= 0 && end + i < len) {
282             end += i;
283 
284             if (i == (unsigned int) end) {
285                 i++;
286                 continue;
287             }
288 
289             val = mk_string_copy_substr(line, i, end);
290             val_len = end - i;
291         }
292         else {
293             val = mk_string_copy_substr(line, i, len);
294             val_len = len - i;
295             end = len;
296         }
297 
298         /* Update last position */
299         i = end;
300 
301         /* Create new entry */
302         new = flb_malloc(sizeof(struct flb_split_entry));
303         if (!new) {
304             flb_errno();
305             flb_free(val);
306             flb_utils_split_free(list);
307             return NULL;
308         }
309         new->value = val;
310         new->len = val_len;
311         new->last_pos = i;
312         mk_list_add(&new->_head, list);
313         count++;
314 
315         /* Update index for next loop */
316         i++;
317 
318         /*
319          * If the counter exceeded the maximum specified and there
320          * are still remaining bytes, append those bytes in a new
321          * and last entry.
322          */
323         if (count >= max_split && max_split > 0 && i < len) {
324             new = flb_malloc(sizeof(struct flb_split_entry));
325             if (!new) {
326                 flb_errno();
327                 flb_utils_split_free(list);
328                 return NULL;
329             }
330             new->value = mk_string_copy_substr(line, i, len);
331             new->len   = len - i;
332             mk_list_add(&new->_head, list);
333             break;
334         }
335     }
336 
337     return list;
338 }
339 
flb_utils_split_free_entry(struct flb_split_entry * entry)340 void flb_utils_split_free_entry(struct flb_split_entry *entry)
341 {
342     mk_list_del(&entry->_head);
343     flb_free(entry->value);
344     flb_free(entry);
345 }
346 
flb_utils_split_free(struct mk_list * list)347 void flb_utils_split_free(struct mk_list *list)
348 {
349     struct mk_list *tmp;
350     struct mk_list *head;
351     struct flb_split_entry *entry;
352 
353     mk_list_foreach_safe(head, tmp, list) {
354         entry = mk_list_entry(head, struct flb_split_entry, _head);
355         flb_utils_split_free_entry(entry);
356     }
357 
358     flb_free(list);
359 }
360 
361 /* When a timer expires, it needs some handling */
flb_utils_timer_consume(flb_pipefd_t fd)362 int flb_utils_timer_consume(flb_pipefd_t fd)
363 {
364     int ret;
365     uint64_t val;
366 
367     ret = flb_pipe_r(fd, &val, sizeof(val));
368     if (ret == -1) {
369         flb_errno();
370         return -1;
371     }
372 
373 #ifdef __linux__
374     /* A timer on linux must return an unisgned 64 bit number */
375     if (ret == 0) {
376         return -1;
377     }
378 #endif
379 
380     return 0;
381 }
382 
flb_utils_pipe_byte_consume(flb_pipefd_t fd)383 int flb_utils_pipe_byte_consume(flb_pipefd_t fd)
384 {
385     int ret;
386     uint64_t val;
387 
388     ret = flb_pipe_r(fd, &val, sizeof(val));
389     if (ret == -1) {
390         flb_errno();
391         return -1;
392     }
393 
394     return 0;
395 }
396 
flb_utils_size_to_bytes(const char * size)397 int64_t flb_utils_size_to_bytes(const char *size)
398 {
399     int i;
400     int len;
401     int plen = 0;
402     int64_t val;
403     char c;
404     char tmp[3] = {0};
405     int64_t KB = 1000;
406     int64_t MB = 1000 * KB;
407     int64_t GB = 1000 * MB;
408 
409     if (!size) {
410         return -1;
411     }
412 
413     if (strcasecmp(size, "false") == 0) {
414         return 0;
415     }
416 
417     len = strlen(size);
418     val = atoll(size);
419 
420     if (len == 0) {
421         return -1;
422     }
423 
424     for (i = len - 1; i > 0; i--) {
425         if (isdigit(size[i])) {
426             break;
427         }
428         else {
429             plen++;
430         }
431     }
432 
433     if (plen == 0) {
434         return val;
435     }
436     else if (plen > 2) {
437         return -1;
438     }
439 
440     for (i = 0; i < plen; i++) {
441         c = size[(len - plen) + i];
442         tmp[i] = toupper(c);
443     }
444 
445     if (plen == 2) {
446         if (tmp[1] != 'B') {
447             return -1;
448         }
449     }
450 
451     if (tmp[0] == 'K') {
452         /* set upper bound (2**64/KB)/2 to avoid overflows */
453         if (val >= 9223372036854775 || val <= -9223372036854774)
454         {
455             return -1;
456         }
457         return (val * KB);
458     }
459     else if (tmp[0] == 'M') {
460         /* set upper bound (2**64/MB)/2 to avoid overflows */
461         if (val >= 9223372036854 || val <= -9223372036853) {
462             return -1;
463         }
464         return (val * MB);
465     }
466     else if (tmp[0] == 'G') {
467         /* set upper bound (2**64/GB)/2 to avoid overflows */
468         if (val >= 9223372036 || val <= -9223372035) {
469             return -1;
470         }
471         return (val * GB);
472     }
473     else {
474         return -1;
475     }
476 
477     return val;
478 }
479 
flb_utils_hex2int(char * hex,int len)480 int64_t flb_utils_hex2int(char *hex, int len)
481 {
482     int i = 0;
483     int64_t res = 0;
484     char c;
485 
486     while ((c = *hex++) && i < len) {
487         /* Ensure no overflow */
488         if (res >= (int64_t)((INT64_MAX/0x10) - 0xff)) {
489             return -1;
490         }
491 
492         res *= 0x10;
493 
494         if (c >= 'a' && c <= 'f') {
495             res += (c - 0x57);
496         }
497         else if (c >= 'A' && c <= 'F') {
498             res += (c - 0x37);
499         }
500         else if (c >= '0' && c <= '9') {
501             res += (c - 0x30);
502         }
503         else {
504             return -1;
505         }
506         i++;
507     }
508 
509     if (res < 0) {
510         return -1;
511     }
512 
513     return res;
514 }
515 
flb_utils_time_to_seconds(const char * time)516 int flb_utils_time_to_seconds(const char *time)
517 {
518     int len;
519     size_t val;
520 
521     len = strlen(time);
522     if (len == 0) {
523         return 0;
524     }
525     val = atoi(time);
526 
527     /* String time to seconds */
528     if (time[len - 1] == 'D' || time[len - 1] == 'd') {
529         val *= 86400;
530     }
531     if (time[len - 1] == 'H' || time[len - 1] == 'h') {
532         val *= 3600;
533     }
534     else if (time[len - 1] == 'M' || time[len - 1] == 'm') {
535         val *= 60;
536     }
537 
538     return val;
539 }
540 
flb_utils_bool(const char * val)541 int flb_utils_bool(const char *val)
542 {
543     if (strcasecmp(val, "true") == 0 ||
544         strcasecmp(val, "on") == 0 ||
545         strcasecmp(val, "yes") == 0) {
546         return FLB_TRUE;
547     }
548     else if (strcasecmp(val, "false") == 0 ||
549              strcasecmp(val, "off") == 0 ||
550              strcasecmp(val, "no") == 0) {
551         return FLB_FALSE;
552     }
553 
554     return -1;
555 }
556 
557 /* Convert a 'string' time seconds.nanoseconds to int and long values */
flb_utils_time_split(const char * time,int * sec,long * nsec)558 int flb_utils_time_split(const char *time, int *sec, long *nsec)
559 {
560     char *p;
561     char *end;
562     long val = 0;
563 
564     errno = 0;
565     val = strtol(time, &end, 10);
566     if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
567         || (errno != 0 && val == 0)) {
568         flb_errno();
569         return -1;
570     }
571     if (end == time) {
572         return -1;
573     }
574     *sec = (int) val;
575 
576     /* Try to find subseconds */
577     *nsec = 0;
578     p = strchr(time, '.');
579     if (p) {
580         p += 1;
581         val = strtol(p, &end, 10);
582         if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
583             || (errno != 0 && val == 0)) {
584             flb_errno();
585             return -1;
586         }
587         if (end == p) {
588             return -1;
589         }
590         *nsec = val;
591     }
592 
593     return 0;
594 }
595 
flb_utils_bytes_to_human_readable_size(size_t bytes,char * out_buf,size_t size)596 void flb_utils_bytes_to_human_readable_size(size_t bytes,
597                                             char *out_buf, size_t size)
598 {
599     unsigned long i;
600     unsigned long u = 1024;
601     static const char *__units[] = {
602         "b", "K", "M", "G",
603         "T", "P", "E", "Z", "Y", NULL
604     };
605 
606     for (i = 0; __units[i] != NULL; i++) {
607         if ((bytes / u) == 0) {
608             break;
609         }
610         u *= 1024;
611     }
612     if (!i) {
613         snprintf(out_buf, size, "%lu%s", (long unsigned int) bytes, __units[0]);
614     }
615     else {
616         float fsize = (float) ((double) bytes / (u / 1024));
617         snprintf(out_buf, size, "%.1f%s", fsize, __units[i]);
618     }
619 }
620 
621 
encoded_to_buf(char * out,const char * in,int len)622 static inline void encoded_to_buf(char *out, const char *in, int len)
623 {
624     int i;
625     char *p = out;
626 
627     for (i = 0; i < len; i++) {
628         *p++ = in[i];
629     }
630 }
631 
632 /*
633  * Write string pointed by 'str' to the destination buffer 'buf'. It's make sure
634  * to escape sepecial characters and convert utf-8 byte characters to string
635  * representation.
636  */
flb_utils_write_str(char * buf,int * off,size_t size,const char * str,size_t str_len)637 int flb_utils_write_str(char *buf, int *off, size_t size,
638                         const char *str, size_t str_len)
639 {
640     int i;
641     int b;
642     int ret;
643     int written = 0;
644     int required;
645     int len;
646     int hex_bytes;
647     int is_valid;
648     int utf_sequence_number;
649     int utf_sequence_length;
650     uint32_t codepoint;
651     uint32_t state = 0;
652     char tmp[16];
653     size_t available;
654     uint32_t c;
655     char *p;
656     uint8_t *s;
657 
658     available = (size - *off);
659     required = str_len;
660     if (available <= required) {
661         return FLB_FALSE;
662     }
663 
664     p = buf + *off;
665     for (i = 0; i < str_len; i++) {
666         if ((available - written) < 2) {
667             return FLB_FALSE;
668         }
669 
670         c = (uint32_t) str[i];
671         if (c == '\"') {
672             *p++ = '\\';
673             *p++ = '\"';
674         }
675         else if (c == '\\') {
676             *p++ = '\\';
677             *p++ = '\\';
678         }
679         else if (c == '\n') {
680             *p++ = '\\';
681             *p++ = 'n';
682         }
683         else if (c == '\r') {
684             *p++ = '\\';
685             *p++ = 'r';
686         }
687         else if (c == '\t') {
688             *p++ = '\\';
689             *p++ = 't';
690         }
691         else if (c == '\b') {
692             *p++ = '\\';
693             *p++ = 'b';
694         }
695         else if (c == '\f') {
696             *p++ = '\\';
697             *p++ = 'f';
698         }
699         else if (c < 32 || c == 0x7f) {
700             if ((available - written) < 6) {
701                 return FLB_FALSE;
702             }
703             len = snprintf(tmp, sizeof(tmp) - 1, "\\u%.4hhx", (unsigned char) c);
704             if ((available - written) < len) {
705                 return FLB_FALSE;
706             }
707             encoded_to_buf(p, tmp, len);
708             p += len;
709         }
710         else if (c >= 0x80 && c <= 0xFFFF) {
711             hex_bytes = flb_utf8_len(str + i);
712             if (available - written < 6) {
713                 return FLB_FALSE;
714             }
715 
716             if (i + hex_bytes > str_len) {
717                 break; /* skip truncated UTF-8 */
718             }
719 
720             state = FLB_UTF8_ACCEPT;
721             codepoint = 0;
722 
723             for (b = 0; b < hex_bytes; b++) {
724                 s = (unsigned char *) str + i + b;
725                 ret = flb_utf8_decode(&state, &codepoint, *s);
726                 if (ret == 0) {
727                     break;
728                 }
729             }
730 
731             if (state != FLB_UTF8_ACCEPT) {
732                 /* Invalid UTF-8 hex, just skip utf-8 bytes */
733                 flb_warn("[pack] invalid UTF-8 bytes found, skipping bytes");
734             }
735             else {
736                 len = snprintf(tmp, sizeof(tmp) - 1, "\\u%.4x", codepoint);
737                 if ((available - written) < len) {
738                     return FLB_FALSE;
739                 }
740                 encoded_to_buf(p, tmp, len);
741                 p += len;
742             }
743             i += (hex_bytes - 1);
744         }
745         else if (c > 0xFFFF) {
746             utf_sequence_length = flb_utf8_len(str + i);
747 
748             if (i + utf_sequence_length > str_len) {
749                 break; /* skip truncated UTF-8 */
750             }
751 
752             is_valid = FLB_TRUE;
753             for (utf_sequence_number = 0; utf_sequence_number < utf_sequence_length;
754                 utf_sequence_number++) {
755                 /* Leading characters must start with bits 11 */
756                 if (utf_sequence_number == 0 && ((str[i] & 0xC0) != 0xC0)) {
757                     /* Invalid unicode character. replace */
758                     flb_debug("[pack] unexpected UTF-8 leading byte, "
759                              "substituting character with replacement character");
760                     tmp[utf_sequence_number] = str[i];
761                     ++i; /* Consume invalid leading byte */
762                     utf_sequence_length = utf_sequence_number + 1;
763                     is_valid = FLB_FALSE;
764                     break;
765                 }
766                 /* Trailing characters must start with bits 10 */
767                 else if (utf_sequence_number > 0 && ((str[i] & 0xC0) != 0x80)) {
768                     /* Invalid unicode character. replace */
769                     flb_debug("[pack] unexpected UTF-8 continuation byte, "
770                              "substituting character with replacement character");
771                     /* This byte, i, is the start of the next unicode character */
772                     utf_sequence_length = utf_sequence_number;
773                     is_valid = FLB_FALSE;
774                     break;
775                 }
776 
777                 tmp[utf_sequence_number] = str[i];
778                 ++i;
779             }
780             --i;
781 
782             if (is_valid) {
783                 if (available - written < utf_sequence_length) {
784                     return FLB_FALSE;
785                 }
786 
787                 encoded_to_buf(p, tmp, utf_sequence_length);
788                 p += utf_sequence_length;
789             }
790             else {
791                 if (available - written < utf_sequence_length * 3) {
792                     return FLB_FALSE;
793                 }
794 
795                 /*
796                  * Utf-8 sequence is invalid. Map fragments to private use area
797                  * codepoints in range:
798                  * 0x<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR>00 to
799                  * 0x<FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR>FF
800                  */
801                 for (b = 0; b < utf_sequence_length; ++b) {
802                     /*
803                      * Utf-8 private block invalid hex mapping. Format unicode charpoint
804                      * in the following format:
805                      *
806                      *      +--------+--------+--------+
807                      *      |1110PPPP|10PPPPHH|10HHHHHH|
808                      *      +--------+--------+--------+
809                      *
810                      * Where:
811                      *   P is FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR bits (1 byte)
812                      *   H is Utf-8 fragment hex bits (1 byte)
813                      *   1 is bit 1
814                      *   0 is bit 0
815                      */
816 
817                     /* unicode codepoint start */
818                     *p = 0xE0;
819 
820                     /* print unicode private block header first 4 bits */
821                     *p |= FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR >> 4;
822                     ++p;
823 
824                     /* unicode codepoint middle */
825                     *p = 0x80;
826 
827                     /* print end of unicode private block header last 4 bits */
828                     *p |= ((FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR << 2) & 0x3f);
829 
830                     /* print hex fragment first 2 bits */
831                     *p |= (tmp[b] >> 6) & 0x03;
832                     ++p;
833 
834                     /* unicode codepoint middle */
835                     *p = 0x80;
836 
837                     /* print hex fragment last 6 bits */
838                     *p |= tmp[b] & 0x3f;
839                     ++p;
840                 }
841             }
842         }
843         else {
844             *p++ = c;
845         }
846         written = (p - (buf + *off));
847     }
848 
849     *off += written;
850 
851     return FLB_TRUE;
852 }
853 
854 
flb_utils_write_str_buf(const char * str,size_t str_len,char ** out,size_t * out_size)855 int flb_utils_write_str_buf(const char *str, size_t str_len, char **out, size_t *out_size)
856 {
857     int ret;
858     int off;
859     char *tmp;
860     char *buf;
861     size_t s;
862 
863     s = str_len + 1;
864     buf = flb_malloc(s);
865     if (!buf) {
866         flb_errno();
867         return -1;
868     }
869 
870     while (1) {
871         off = 0;
872         ret = flb_utils_write_str(buf, &off, s, str, str_len);
873         if (ret == FLB_FALSE) {
874             s += 256;
875             tmp = flb_realloc(buf, s);
876             if (!tmp) {
877                 flb_errno();
878                 flb_free(buf);
879                 return -1;
880             }
881             buf = tmp;
882         }
883         else {
884             /* done */
885             break;
886         }
887     }
888 
889     *out = buf;
890     *out_size = off;
891     return 0;
892 }
893 
flb_copy_host(const char * string,int pos_init,int pos_end)894 static char *flb_copy_host(const char *string, int pos_init, int pos_end)
895 {
896     if (string[pos_init] == '[') {            /* IPv6 */
897         if (string[pos_end-1] != ']')
898             return NULL;
899 
900         return mk_string_copy_substr(string, pos_init + 1, pos_end - 1);
901     }
902     else
903         return mk_string_copy_substr(string, pos_init, pos_end);
904 }
905 
flb_utils_url_split(const char * in_url,char ** out_protocol,char ** out_host,char ** out_port,char ** out_uri)906 int flb_utils_url_split(const char *in_url, char **out_protocol,
907                         char **out_host, char **out_port, char **out_uri)
908 {
909     char *protocol = NULL;
910     char *host = NULL;
911     char *port = NULL;
912     char *uri = NULL;
913     char *p;
914     char *tmp;
915     char *sep;
916 
917     /* Protocol */
918     p = strstr(in_url, "://");
919     if (!p) {
920         return -1;
921     }
922     if (p == in_url) {
923         return -1;
924     }
925 
926     protocol = mk_string_copy_substr(in_url, 0, p - in_url);
927     if (!protocol) {
928         flb_errno();
929         return -1;
930     }
931 
932     /* Advance position after protocol */
933     p += 3;
934 
935     /* Check for first '/' */
936     sep = strchr(p, '/');
937     tmp = strchr(p, ':');
938 
939     /* Validate port separator is found before the first slash */
940     if (sep && tmp) {
941         if (tmp > sep) {
942             tmp = NULL;
943         }
944     }
945 
946     if (tmp) {
947         host = flb_copy_host(p, 0, tmp - p);
948         if (!host) {
949             flb_errno();
950             goto error;
951         }
952         p = tmp + 1;
953 
954         /* Look for an optional URI */
955         tmp = strchr(p, '/');
956         if (tmp) {
957             port = mk_string_copy_substr(p, 0, tmp - p);
958             uri = flb_strdup(tmp);
959         }
960         else {
961             port = flb_strdup(p);
962             uri = flb_strdup("/");
963         }
964     }
965     else {
966         tmp = strchr(p, '/');
967         if (tmp) {
968             host = flb_copy_host(p, 0, tmp - p);
969             uri = flb_strdup(tmp);
970         }
971         else {
972             host = flb_copy_host(p, 0, strlen(p));
973             uri = flb_strdup("/");
974         }
975     }
976 
977     if (!port) {
978         if (strcmp(protocol, "http") == 0) {
979             port = flb_strdup("80");
980         }
981         else if (strcmp(protocol, "https") == 0) {
982             port = flb_strdup("443");
983         }
984     }
985 
986     *out_protocol = protocol;
987     *out_host = host;
988     *out_port = port;
989     *out_uri = uri;
990 
991     return 0;
992 
993  error:
994     if (protocol) {
995         flb_free(protocol);
996     }
997 
998     return -1;
999 }
1000 
1001 
1002 /*
1003  * flb_utils_proxy_url_split parses a proxy's information from a http_proxy URL.
1004  * The URL is in the form like `http://username:password@myproxy.com:8080`.
1005  * Note: currently only HTTP is supported.
1006  */
flb_utils_proxy_url_split(const char * in_url,char ** out_protocol,char ** out_username,char ** out_password,char ** out_host,char ** out_port)1007 int flb_utils_proxy_url_split(const char *in_url, char **out_protocol,
1008                               char **out_username, char **out_password,
1009                               char **out_host, char **out_port)
1010 {
1011     char *protocol = NULL;
1012     char *username = NULL;
1013     char *password = NULL;
1014     char *host = NULL;
1015     char *port = NULL;
1016     char *proto_sep;
1017     char *at_sep;
1018     char *tmp;
1019 
1020     /*  Parse protocol */
1021     proto_sep = strstr(in_url, "://");
1022     if (!proto_sep) {
1023         return -1;
1024     }
1025     if (proto_sep == in_url) {
1026         return -1;
1027     }
1028 
1029     protocol = mk_string_copy_substr(in_url, 0, proto_sep - in_url);
1030     if (!protocol) {
1031         flb_errno();
1032         return -1;
1033     }
1034     /* Only HTTP proxy is supported for now. */
1035     if (strcmp(protocol, "http") != 0) {
1036         flb_free(protocol);
1037         return -1;
1038     }
1039 
1040     /* Advance position after protocol */
1041     proto_sep += 3;
1042 
1043     /* Seperate `username:password` and `host:port` */
1044     at_sep = strchr(proto_sep, '@');
1045     if (at_sep) {
1046         /* Parse username:passwrod part. */
1047         tmp = strchr(proto_sep, ':');
1048         if (!tmp) {
1049             flb_free(protocol);
1050             return -1;
1051         }
1052         username = mk_string_copy_substr(proto_sep, 0, tmp - proto_sep);
1053         tmp += 1;
1054         password = mk_string_copy_substr(tmp, 0, at_sep - tmp);
1055 
1056         /* Parse host:port part. */
1057         at_sep += 1;
1058         tmp = strchr(at_sep, ':');
1059         if (tmp) {
1060             host = flb_copy_host(at_sep, 0, tmp - at_sep);
1061             tmp += 1;
1062             port = strdup(tmp);
1063         }
1064         else {
1065             host = flb_copy_host(at_sep, 0, strlen(at_sep));
1066             port = flb_strdup("80");
1067         }
1068     }
1069     else {
1070         /* Parse host:port part. */
1071         tmp = strchr(proto_sep, ':');
1072         if (tmp) {
1073             host = flb_copy_host(proto_sep, 0, tmp - proto_sep);
1074             tmp += 1;
1075             port = strdup(tmp);
1076         }
1077         else {
1078             host = flb_copy_host(proto_sep, 0, strlen(proto_sep));
1079             port = flb_strdup("80");
1080         }
1081     }
1082 
1083     *out_protocol = protocol;
1084     *out_host = host;
1085     *out_port = port;
1086     if (username) {
1087         *out_username = username;
1088     }
1089     if (password) {
1090         *out_password = password;
1091     }
1092 
1093     return 0;
1094 }
1095 
1096 
flb_utils_get_os_name()1097 char *flb_utils_get_os_name()
1098 {
1099 #ifdef _WIN64
1100     return "win64";
1101 #elif _WIN32
1102     return "win32";
1103 #elif __APPLE__ || __MACH__
1104     return "macos";
1105 #elif __linux__
1106     return "linux";
1107 #elif __FreeBSD__
1108     return "freebsd";
1109 #elif __unix || __unix__
1110     return "unix";
1111 #else
1112     return "other";
1113 #endif
1114 }
1115 
1116 #ifdef FLB_HAVE_OPENSSL
flb_utils_uuid_v4_gen(char * buf)1117 int flb_utils_uuid_v4_gen(char *buf)
1118 {
1119     int ret;
1120     union {
1121         struct {
1122             uint32_t time_low;
1123             uint16_t time_mid;
1124             uint16_t time_hi_and_version;
1125             uint8_t  clk_seq_hi_res;
1126             uint8_t  clk_seq_low;
1127             uint8_t  node[6];
1128         };
1129         uint8_t __rnd[16];
1130     } uuid;
1131 
1132     ret = RAND_bytes(uuid.__rnd, sizeof(uuid));
1133 
1134     uuid.clk_seq_hi_res = (uint8_t) ((uuid.clk_seq_hi_res & 0x3F) | 0x80);
1135     uuid.time_hi_and_version = (uint16_t) ((uuid.time_hi_and_version & 0x0FFF) | 0x4000);
1136 
1137     snprintf(buf, 38, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1138             uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
1139             uuid.clk_seq_hi_res, uuid.clk_seq_low,
1140             uuid.node[0], uuid.node[1], uuid.node[2],
1141             uuid.node[3], uuid.node[4], uuid.node[5]);
1142 
1143     if (ret == 1) {
1144         return 0;
1145     }
1146 
1147     return -1;
1148 }
1149 #else
flb_utils_uuid_v4_gen(char * buf)1150 int flb_utils_uuid_v4_gen(char *buf)
1151 {
1152     snprintf(buf, 38, "ddad00f1-3806-46ab-88d1-277a8c863cd6");
1153     return 0;
1154 }
1155 #endif
1156 
flb_utils_read_file(char * path,char ** out_buf,size_t * out_size)1157 int flb_utils_read_file(char *path, char **out_buf, size_t *out_size)
1158 {
1159     int fd;
1160     int ret;
1161     size_t bytes;
1162     struct stat st;
1163     flb_sds_t buf;
1164     FILE *fp;
1165 
1166     fp = fopen(path, "rb");
1167     if (!fp) {
1168         return -1;
1169     }
1170     fd = fileno(fp);
1171 
1172     ret = fstat(fd, &st);
1173     if (ret == -1) {
1174         flb_errno();
1175         close(fd);
1176         return -1;
1177     }
1178 
1179     buf = flb_calloc(1, st.st_size + 1);
1180     if (!buf) {
1181         flb_errno();
1182         fclose(fp);
1183         return -1;
1184     }
1185 
1186     bytes = fread(buf, st.st_size, 1, fp);
1187     if (bytes < 1) {
1188         flb_errno();
1189         flb_free(buf);
1190         fclose(fp);
1191         return -1;
1192     }
1193     fclose(fp);
1194 
1195     *out_buf = buf;
1196     *out_size = st.st_size;
1197     return 0;
1198 }
1199 
machine_id_read_and_sanitize(char * path,char ** out_buf,size_t * out_size)1200 static int machine_id_read_and_sanitize(char *path,
1201                                         char **out_buf, size_t *out_size)
1202 {
1203     int ret;
1204     size_t s;
1205     char *p;
1206     char *buf;
1207     size_t bytes;
1208 
1209     ret = flb_utils_read_file(path, &buf, &bytes);
1210     if (ret != 0) {
1211         return -1;
1212     }
1213 
1214     p = buf + bytes - 1;
1215     while (*p == ' ' || *p == '\n') {
1216         p--;
1217     }
1218 
1219     /* set new size */
1220     s = p - buf + 1;
1221 
1222     buf[s] = '\0';
1223     *out_size = s;
1224     *out_buf = buf;
1225 
1226     return 0;
1227 }
1228 
flb_utils_get_machine_id(char ** out_id,size_t * out_size)1229 int flb_utils_get_machine_id(char **out_id, size_t *out_size)
1230 {
1231     int ret;
1232     char *id;
1233     size_t bytes;
1234     char *uuid;
1235 
1236 #ifdef __linux__
1237     char *dbus_var = "/var/lib/dbus/machine-id";
1238     char *dbus_etc = "/etc/machine-id";
1239 
1240     /* dbus */
1241     ret = machine_id_read_and_sanitize(dbus_var, &id, &bytes);
1242     if (ret == 0) {
1243         *out_id = id;
1244         *out_size = bytes;
1245         return 0;
1246     }
1247 
1248     /* etc */
1249     ret = machine_id_read_and_sanitize(dbus_etc, &id, &bytes);
1250     if (ret == 0) {
1251         *out_id = id;
1252         *out_size = bytes;
1253         return 0;
1254     }
1255 #elif defined(__FreeBSD__) || defined(__NetBSD__) || \
1256       defined(__OpenBSD__) || defined(__DragonFly__)
1257 
1258     char *hostid = "/etc/hostid";
1259 
1260     /* hostid */
1261     ret = machine_id_read_and_sanitize(hostid, &id, &bytes);
1262     if (ret == 0) {
1263         *out_id = id;
1264         *out_size = bytes;
1265         return 0;
1266     }
1267 #endif
1268 
1269     /* generate a random uuid */
1270     uuid = flb_malloc(38);
1271     if (!uuid) {
1272         flb_errno();
1273         return -1;
1274     }
1275     ret = flb_utils_uuid_v4_gen(uuid);
1276     if (ret == 0) {
1277         *out_id = uuid;
1278         *out_size = strlen(uuid);
1279         return 0;
1280     }
1281 
1282     return -1;
1283 }
1284